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.