diff --git a/readme.md b/readme.md index 3204f2c9..404cbc1f 100644 --- a/readme.md +++ b/readme.md @@ -46,6 +46,7 @@ DiffEngine manages launching and cleanup of diff tools. It is designed to be use * [Closing a tool](#closing-a-tool) * [File type detection](#file-type-detection) * [BuildServerDetector](#buildserverdetector) + * [Override in tests](#override-in-tests) * [AiCliDetector](#aiclidetector) * [Disable for a machine/process](#disable-for-a-machineprocess) * [Disable in code](#disable-in-code) @@ -162,6 +163,50 @@ var isAppVeyor = BuildServerDetector.IsAppVeyor; +### Override in tests + +`BuildServerDetector.Detected` can be set at test time. The value is stored in an `AsyncLocal`, so it is scoped to the current async context and does not leak to other threads or tests running in parallel. + + + +```cs +[Fact] +public async Task SetDetectedPersistsInAsyncContext() +{ + var original = BuildServerDetector.Detected; + try + { + BuildServerDetector.Detected = true; + Assert.True(BuildServerDetector.Detected); + + await Task.Delay(1); + + Assert.True(BuildServerDetector.Detected); + } + finally + { + BuildServerDetector.Detected = original; + } +} + +[Fact] +public async Task SetDetectedDoesNotLeakToOtherContexts() +{ + var parentValue = BuildServerDetector.Detected; + + await Task.Run(() => + { + BuildServerDetector.Detected = true; + Assert.True(BuildServerDetector.Detected); + }); + + Assert.Equal(parentValue, BuildServerDetector.Detected); +} +``` +snippet source | anchor + + + ## AiCliDetector `AiCliDetector.Detected` returns true if the current code is running in an AI-powered CLI environment. diff --git a/readme.source.md b/readme.source.md index 0f8979a6..fd77687d 100644 --- a/readme.source.md +++ b/readme.source.md @@ -84,6 +84,13 @@ There are also individual properties to check for each specific build system snippet: BuildServerDetectorProps +### Override in tests + +`BuildServerDetector.Detected` can be set at test time. The value is stored in an `AsyncLocal`, so it is scoped to the current async context and does not leak to other threads or tests running in parallel. + +snippet: BuildServerDetectorDetectedOverride + + ## AiCliDetector `AiCliDetector.Detected` returns true if the current code is running in an AI-powered CLI environment. diff --git a/src/DiffEngine.Tests/BuildServerDetectorTest.cs b/src/DiffEngine.Tests/BuildServerDetectorTest.cs index 64f83eb3..3e2f96e5 100644 --- a/src/DiffEngine.Tests/BuildServerDetectorTest.cs +++ b/src/DiffEngine.Tests/BuildServerDetectorTest.cs @@ -24,4 +24,41 @@ public void Props() // ReSharper restore UnusedVariable } + + #region BuildServerDetectorDetectedOverride + + [Fact] + public async Task SetDetectedPersistsInAsyncContext() + { + var original = BuildServerDetector.Detected; + try + { + BuildServerDetector.Detected = true; + Assert.True(BuildServerDetector.Detected); + + await Task.Delay(1); + + Assert.True(BuildServerDetector.Detected); + } + finally + { + BuildServerDetector.Detected = original; + } + } + + [Fact] + public async Task SetDetectedDoesNotLeakToOtherContexts() + { + var parentValue = BuildServerDetector.Detected; + + await Task.Run(() => + { + BuildServerDetector.Detected = true; + Assert.True(BuildServerDetector.Detected); + }); + + Assert.Equal(parentValue, BuildServerDetector.Detected); + } + + #endregion } \ No newline at end of file diff --git a/src/DiffEngine/BuildServerDetector.cs b/src/DiffEngine/BuildServerDetector.cs index 1e5bcf34..980deae1 100644 --- a/src/DiffEngine/BuildServerDetector.cs +++ b/src/DiffEngine/BuildServerDetector.cs @@ -52,7 +52,7 @@ static BuildServerDetector() // https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#access-variables-through-the-environment IsAzureDevops = ValueEquals(variables, "TF_BUILD", "True"); - Detected = IsTravis || + detected = IsTravis || IsJenkins || IsGithubAction || IsAzureDevops || @@ -65,6 +65,9 @@ static BuildServerDetector() IsAppVeyor; } + static bool detected; + static AsyncLocal overrideDetected = new(); + static bool ValueEquals(IDictionary variables, string key, string value) { var variable = variables[key]; @@ -98,5 +101,9 @@ static bool ValueEquals(IDictionary variables, string key, string value) public static bool IsJenkins { get; } - public static bool Detected { get; set; } + public static bool Detected + { + get => overrideDetected.Value ?? detected; + set => overrideDetected.Value = value; + } } \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 958f0b6d..6e729e13 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -2,7 +2,7 @@ CS1591;CS0649;NU1608;NU1109 - 18.3.0 + 18.4.0 1.0.0 Testing, Snapshot, Diff, Compare Launches diff tools based on file extensions. Designed to be consumed by snapshot testing libraries.