diff --git a/docs/diff-tool.custom.md b/docs/diff-tool.custom.md index 073068bc..c49438b5 100644 --- a/docs/diff-tool.custom.md +++ b/docs/diff-tool.custom.md @@ -53,7 +53,7 @@ New tools are added to the top of the order, the last tool added will resolve be ```cs await DiffRunner.LaunchAsync(tempFile, targetFile); ``` -snippet source | anchor +snippet source | anchor Alternatively the instance returned from `AddTool*` can be used to explicitly launch that tool. diff --git a/readme.md b/readme.md index 91212d86..017fb99a 100644 --- a/readme.md +++ b/readme.md @@ -108,7 +108,7 @@ A tool can be launched using the following: ```cs await DiffRunner.LaunchAsync(tempFile, targetFile); ``` -snippet source | anchor +snippet source | anchor Note that this method will respect the above [difference behavior](/docs/diff-tool.md#detected-difference-behavior) in terms of Auto refresh and MDI behaviors. @@ -123,7 +123,7 @@ A tool can be closed using the following: ```cs DiffRunner.Kill(file1, file2); ``` -snippet source | anchor +snippet source | anchor Note that this method will respect the above [difference behavior](/docs/diff-tool.md#detected-difference-behavior) in terms of MDI behavior. diff --git a/src/DiffEngine.Tests/DiffRunnerTests.cs b/src/DiffEngine.Tests/DiffRunnerTests.cs index 5a0af685..0c179866 100644 --- a/src/DiffEngine.Tests/DiffRunnerTests.cs +++ b/src/DiffEngine.Tests/DiffRunnerTests.cs @@ -7,6 +7,28 @@ public class DiffRunnerTests static string SourceDirectory { get; } = Path.GetDirectoryName(GetSourceFile())!; static string GetSourceFile([CallerFilePath] string path = "") => path; + // Launching registers a real pending move of file1 over file2 with whatever owns the queue on + // this machine, usually the developer's tray. Accepting it moves file1, and discarding it + // deletes file1 and then its directory. Run against the source directory that quietly destroys + // the checked in fixtures, so the tests get copies instead. + // One directory for the whole class, because IsRunning matches the exact command string and + // WaitForRunning is also used at test start to wait out the previous test's kill, both of which + // want the same paths across tests. Fresh per run, so a FakeDiffTool left behind by a crashed + // earlier run cannot match this run's command. + static string TempDirectory { get; } = Path.Combine( + Path.GetTempPath(), + "DiffEngine.DiffRunnerTests", + Guid.NewGuid().ToString("N")); + + [After(Class)] + public static void DeleteTempDirectory() + { + if (Directory.Exists(TempDirectory)) + { + Directory.Delete(TempDirectory, true); + } + } + static ResolvedTool tool; string file2; string file1; @@ -216,11 +238,21 @@ async Task WaitForRunning(bool expected) public DiffRunnerTests() { - file1 = Path.Combine(SourceDirectory, "DiffRunner.file1.txt"); - file2 = Path.Combine(SourceDirectory, "DiffRunner.file2.txt"); + file1 = CopyFixture("DiffRunner.file1.txt"); + file2 = CopyFixture("DiffRunner.file2.txt"); command = tool.BuildCommand(file1, file2); } + // Per test rather than per class: a discard deletes the temp file and its directory, so the + // copies have to be put back for the test that follows. + static string CopyFixture(string name) + { + Directory.CreateDirectory(TempDirectory); + var target = Path.Combine(TempDirectory, name); + File.Copy(Path.Combine(SourceDirectory, name), target, true); + return target; + } + static DiffRunnerTests() => tool = DiffTools.AddTool( name: "FakeDiffTool", diff --git a/src/DiffEngine.Tests/ModuleInitializer.cs b/src/DiffEngine.Tests/ModuleInitializer.cs index b9205d43..6d65819b 100644 --- a/src/DiffEngine.Tests/ModuleInitializer.cs +++ b/src/DiffEngine.Tests/ModuleInitializer.cs @@ -1,4 +1,10 @@ -public static class ModuleInitializer +// DiffEngineTray is the obsolete public shim, but its IsRunning is still where the tray check lives. +#pragma warning disable CS0618 + +using System.Net; +using System.Net.Sockets; + +public static class ModuleInitializer { [ModuleInitializer] public static void Initialize() @@ -6,5 +12,33 @@ public static void Initialize() FileExtensions.AddTextFileConvention(_ => _.EndsWith(".txtConvention".AsSpan())); Logging.Enable(); DiffRunner.Disabled = false; + DetachFromPendingFileSurfaces(); + } + + /// + /// Launching sends a real pending move to whatever owns the queue on this machine. On a + /// developer box that is the tray, started at login, and an accept or discard from it kills the + /// diff tool process DiffRunnerTests is asserting on. Being inconclusive when a tray is running + /// would mean those tests never run locally, so cut both routes instead: no tray, and a viewer + /// port nothing is listening on. + /// + /// A failed move send is the end of the road in PendingFiles.AddMove, and only a delete + /// launches a viewer, which nothing here adds. So the moves these tests produce go nowhere and + /// no process outside the test can see them. + /// + /// + /// The cost is that the real piper send is not covered from here. That belongs with a tray + /// under test control, which is what DiffEngineTray.Tests/DiffRunnerCanKillTest does. + /// + /// + static void DetachFromPendingFileSurfaces() + { + DiffEngineTray.IsRunning = false; + + var listener = new TcpListener(IPAddress.Loopback, 0); + listener.Start(); + var port = ((IPEndPoint) listener.LocalEndpoint).Port; + listener.Stop(); + Environment.SetEnvironmentVariable(ViewerClient.PortVariable, port.ToString()); } }