using System.Text.Json; using ClawdDotNet.App.Services; using ClawdDotNet.Core.Config; using Shouldly; using ClawdDotNet.Core.Instances; namespace ClawdDotNet.App.Tests.Services; /// /// Die andere Hälfte von #375: Bestehende Instanzen tragen "logDirectory": "./Logs" /// in ihrer InstanceSettings.json — /// hat es dort hineingeschrieben. Beim Laden wird daraus „leer". /// /// Seit #528 (Stufe 1) zeigen beide Schreibweisen ohnehin auf denselben Ort: /// <Instanz>/Logs. Der leere Wert sagt das, ohne es festzuschreiben — zieht /// die Instanz um, zieht das Protokoll mit. /// /// Wer bewusst einen anderen Pfad eingetragen hat, behält ihn. /// public sealed class InstanceLogDirectoryMigrationTests : IDisposable { private readonly string _instancesDir; private readonly InstanceDirectoryManager _manager; public InstanceLogDirectoryMigrationTests() { _instancesDir = Path.Combine( Path.GetTempPath(), "clawd-tests", Guid.NewGuid().ToString("N"), "Instances"); _manager = new InstanceDirectoryManager(_instancesDir); } public void Dispose() { try { Directory.Delete(Path.GetDirectoryName(_instancesDir)!, recursive: true); } catch { /* Aufräumen ist Nebensache */ } } /// Legt eine Instanz an und setzt logDirectory in der Datei auf den Altwert. private string InstanceWithLogDirectory(string value) { var dir = _manager.CreateInstance("Test"); var path = Path.Combine(dir, "InstanceSettings.json"); var config = JsonSerializer.Deserialize(File.ReadAllText(path))!; config.LogDirectory = value; File.WriteAllText(path, JsonSerializer.Serialize(config)); return dir; } [Theory] [InlineData("./Logs")] [InlineData(@".\Logs")] [InlineData("Logs")] public void Die_alte_Vorbelegung_wird_zu_keiner_Angabe(string alt) { var dir = InstanceWithLogDirectory(alt); _manager.LoadInstanceConfig(dir).LogDirectory.ShouldBe(""); } [Fact] public void Ein_bewusst_gesetzter_Pfad_bleibt_stehen() { var eigen = Path.Combine(Path.GetTempPath(), "clawd-eigene-logs"); var dir = InstanceWithLogDirectory(eigen); _manager.LoadInstanceConfig(dir).LogDirectory.ShouldBe(eigen); } [Fact] public void Die_Datei_wird_beim_Laden_nicht_zurueckgeschrieben() { // Die Migration greift nur im Speicher. Ein Ladevorgang darf nichts anfassen — // erst das nächste Speichern lässt den Altwert verschwinden. var dir = InstanceWithLogDirectory("./Logs"); var path = Path.Combine(dir, "InstanceSettings.json"); _manager.LoadInstanceConfig(dir); File.ReadAllText(path).ShouldContain("./Logs"); } [Fact] public void Eine_neue_Instanz_bekommt_gar_keinen_Wert() { var dir = _manager.CreateInstance("Frisch"); var config = _manager.LoadInstanceConfig(dir); config.LogDirectory.ShouldBe(""); config.BackupDirectory.ShouldBe(""); File.ReadAllText(Path.Combine(dir, "InstanceSettings.json")).ShouldNotContain("./Logs"); } /// /// Der eigentliche Zweck von Stufe 1: Zwei frisch angelegte Instanzen protokollieren /// und sichern nicht in denselben Ordner. /// [Fact] public void Zwei_frische_Instanzen_landen_nicht_im_selben_Ordner() { var a = _manager.CreateInstance("Eins"); var b = _manager.CreateInstance("Zwei"); var configA = _manager.LoadInstanceConfig(a); var configB = _manager.LoadInstanceConfig(b); AppHost.ResolveLogDirectory(configA, a) .ShouldNotBe(AppHost.ResolveLogDirectory(configB, b)); AppHost.ResolveBackupDirectory(configA, a) .ShouldNotBe(AppHost.ResolveBackupDirectory(configB, b)); } }