using System.Text.Json; using ClawdDotNet.App.Services; using ClawdDotNet.Core.Config; using Shouldly; using ClawdDotNet.Core.Instances; namespace ClawdDotNet.App.Tests.Services; /// /// The other half of #375: existing instances carry "logDirectory": "./Logs" /// in their InstanceSettings.json — /// wrote it there. On loading it becomes "empty". /// /// Since #528 (stage 1) both spellings point to the same place anyway: /// <Instanz>/Logs. The empty value says so without pinning it down — if /// the instance moves, the log moves with it. /// /// Whoever deliberately entered a different path keeps it. /// 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 { /* Cleaning up is secondary */ } } /// Creates an instance and sets logDirectory in the file to the legacy value. 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 The_old_default_becomes_no_value(string old) { var dir = InstanceWithLogDirectory(old); _manager.LoadInstanceConfig(dir).LogDirectory.ShouldBe(""); } [Fact] public void A_deliberately_set_path_stays() { var own = Path.Combine(Path.GetTempPath(), "clawd-eigene-logs"); var dir = InstanceWithLogDirectory(own); _manager.LoadInstanceConfig(dir).LogDirectory.ShouldBe(own); } [Fact] public void The_file_is_not_written_back_on_load() { // The migration only applies in memory. A load must not touch anything — // only the next save makes the legacy value disappear. var dir = InstanceWithLogDirectory("./Logs"); var path = Path.Combine(dir, "InstanceSettings.json"); _manager.LoadInstanceConfig(dir); File.ReadAllText(path).ShouldContain("./Logs"); } [Fact] public void A_new_instance_gets_no_value_at_all() { 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"); } /// /// The actual purpose of stage 1: two freshly created instances do not log /// and back up into the same folder. /// [Fact] public void Two_fresh_instances_do_not_end_up_in_the_same_folder() { 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)); } }