diff --git a/Samples/PassingBashTestWithEnvironmentVariables/test.json b/Samples/PassingBashTestWithEnvironmentVariables/test.json new file mode 100644 index 0000000..ff8cf5b --- /dev/null +++ b/Samples/PassingBashTestWithEnvironmentVariables/test.json @@ -0,0 +1,12 @@ +{ + "name": "PassingBashTestWithEnvironmentVariables", + "enabled": true, + "requiresSdk": true, + "version": "1.0", + "versionSpecific": false, + "type": "bash", + "cleanup": true, + "ignoredRIDs":[ + ] +} + diff --git a/Samples/PassingBashTestWithEnvironmentVariables/test.sh b/Samples/PassingBashTestWithEnvironmentVariables/test.sh new file mode 100755 index 0000000..2863e0d --- /dev/null +++ b/Samples/PassingBashTestWithEnvironmentVariables/test.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +env + +if [[ -n "${OPENSSL_CONF}" ]]; then + echo "error: OPENSSL_CONF should never be set" + exit 1 +fi diff --git a/Samples/PassingXUnitTestWithEnvironmentVariables/PassingXUnitTestWithEnvironmentVariables.cs b/Samples/PassingXUnitTestWithEnvironmentVariables/PassingXUnitTestWithEnvironmentVariables.cs new file mode 100644 index 0000000..01b914e --- /dev/null +++ b/Samples/PassingXUnitTestWithEnvironmentVariables/PassingXUnitTestWithEnvironmentVariables.cs @@ -0,0 +1,14 @@ +using System; +using Xunit; + +namespace Samples +{ + public class PassingXUnitTestWithEnvironmentVariables + { + [Fact] + public void Test1() + { + Assert.Null(Environment.GetEnvironmentVariable("OPENSSL_CONF")); + } + } +} diff --git a/Samples/PassingXUnitTestWithEnvironmentVariables/PassingXUnitTestWithEnvironmentVariables.csproj b/Samples/PassingXUnitTestWithEnvironmentVariables/PassingXUnitTestWithEnvironmentVariables.csproj new file mode 100644 index 0000000..17766b5 --- /dev/null +++ b/Samples/PassingXUnitTestWithEnvironmentVariables/PassingXUnitTestWithEnvironmentVariables.csproj @@ -0,0 +1,17 @@ + + + + true + netcoreapp3.1 + + false + + + + + + + + + + diff --git a/Samples/PassingXUnitTestWithEnvironmentVariables/test.json b/Samples/PassingXUnitTestWithEnvironmentVariables/test.json new file mode 100644 index 0000000..e61478d --- /dev/null +++ b/Samples/PassingXUnitTestWithEnvironmentVariables/test.json @@ -0,0 +1,12 @@ +{ + "name": "PassingXUnitTestWithEnvironmentVariables", + "enabled": true, + "requiresSdk": true, + "version": "1.0", + "versionSpecific": false, + "type": "xunit", + "cleanup": true, + "ignoredRIDs":[ + ] +} + diff --git a/Turkey.Tests/EnvironmentVariableSanitizerTest.cs b/Turkey.Tests/EnvironmentVariableSanitizerTest.cs new file mode 100644 index 0000000..219b81f --- /dev/null +++ b/Turkey.Tests/EnvironmentVariableSanitizerTest.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using Xunit; + +namespace Turkey.Tests +{ + public class EnvironmentVariableSanitizerTest + { + [Theory] + // TODO enable these too + // [InlineData("ASPNETCORE_URLS")] + // [InlineData("COREHOST_TRACE")] + // [InlineData("DOTNET_FOO_BAR")] + // [InlineData("DOTNET_ROLL_FORWARD")] + // [InlineData("DOTNET_RUNTIME_ID")] + // [InlineData("DOTNET_STARTUP_HOOKS")] + // [InlineData("NUGET_PACKAGES")] + [InlineData("OPENSSL_CONF")] + public void EnvironmentVariablesAreRemoved(string name) + { + var environment = new Dictionary() + { + { name, "foobar" }, + }; + + var sanitizer = new EnvironmentVariableSanitizer(); + var result = sanitizer.SanitizeEnvironmentVariables(environment); + + Assert.DoesNotContain(name, result.Keys); + } + + [InlineData("DOTNET_ROOT")] + [InlineData("DOTNET_CLI_TELEMETRY_OPTOUT")] + [InlineData("PATH")] + [InlineData("USER")] + [InlineData("HOME")] + public void EnvironmentVariablesAreKept(string name) + { + var environment = new Dictionary() + { + { name, "foobar" }, + }; + + var sanitizer = new EnvironmentVariableSanitizer(); + var result = sanitizer.SanitizeEnvironmentVariables(environment); + + Assert.Contains(name, result.Keys); + + } + } +} diff --git a/Turkey.Tests/TestParserTest.cs b/Turkey.Tests/TestParserTest.cs index bb2af51..a99f62f 100644 --- a/Turkey.Tests/TestParserTest.cs +++ b/Turkey.Tests/TestParserTest.cs @@ -12,7 +12,7 @@ public class TestParserTests public void DisabledTestShouldBeSkipped() { TestParser parser = new TestParser(); - SystemUnderTest system = new SystemUnderTest(null, null, null); + SystemUnderTest system = new SystemUnderTest(null, null, null, null); TestDescriptor test = new TestDescriptor() { Enabled = false, @@ -41,7 +41,8 @@ public void TestShouldBeRunForSameOrHigherVersions(string version, bool expected SystemUnderTest system = new SystemUnderTest( runtimeVersion: Version.Parse(version), sdkVersion: null, - platformIds: new List()); + platformIds: new List(), + environmentVariables: null); TestDescriptor test = new TestDescriptor() { @@ -75,7 +76,8 @@ public void VersionSpecificTestShouldBeRunForSameMajorMinorVersion(string versio SystemUnderTest system = new SystemUnderTest( runtimeVersion: Version.Parse(version), sdkVersion: null, - platformIds: new List()); + platformIds: new List(), + environmentVariables: null); TestDescriptor test = new TestDescriptor() { Enabled = true, @@ -111,7 +113,8 @@ public void VersionSpecificTestWithWildcardShouldBeRunForSameMajorVersion(string SystemUnderTest system = new SystemUnderTest( runtimeVersion: Version.Parse(version), sdkVersion: null, - platformIds: new List()); + platformIds: new List(), + environmentVariables: null); TestDescriptor test = new TestDescriptor() { Enabled = true, @@ -132,7 +135,8 @@ public void MissingIgnoredRIDsIsOkay() SystemUnderTest system = new SystemUnderTest( runtimeVersion: Version.Parse("2.1"), sdkVersion: null, - platformIds: new string[] { "linux" }.ToList()); + platformIds: new string[] { "linux" }.ToList(), + environmentVariables: null); TestDescriptor test = new TestDescriptor() { Enabled = true, @@ -159,7 +163,8 @@ public void TestShouldNotRunOnIgnoredPlatforms(string[] currentPlatforms, string SystemUnderTest system = new SystemUnderTest( runtimeVersion: Version.Parse("2.1"), sdkVersion: null, - platformIds: currentPlatforms.ToList()); + platformIds: currentPlatforms.ToList(), + environmentVariables: null); TestDescriptor test = new TestDescriptor() { Enabled = true, @@ -183,7 +188,8 @@ public void SdkTestsShouldRunOnlyWithSdk(string sdkVersion, bool requiresSdk, bo SystemUnderTest system = new SystemUnderTest( runtimeVersion: Version.Parse("3.1"), sdkVersion: Version.Parse(sdkVersion), - platformIds: new List()); + platformIds: new List(), + environmentVariables: null); TestDescriptor test = new TestDescriptor() { Enabled = true, diff --git a/Turkey/BashTest.cs b/Turkey/BashTest.cs index 2b80f18..50cfda1 100644 --- a/Turkey/BashTest.cs +++ b/Turkey/BashTest.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading; @@ -36,6 +37,13 @@ protected override async Task InternalRunAsync(CancellationToken can RedirectStandardOutput = true, RedirectStandardError = true, }; + + startInfo.EnvironmentVariables.Clear(); + foreach (var (key, value) in SystemUnderTest.EnvironmentVariables) + { + startInfo.EnvironmentVariables.Add(key, value); + } + standardOutputWriter.WriteLine($"Executing {startInfo.FileName} with arguments {startInfo.Arguments} in working directory {startInfo.WorkingDirectory}"); using (Process p = Process.Start(startInfo)) { diff --git a/Turkey/DotNet.cs b/Turkey/DotNet.cs index 72d97dc..2d428db 100644 --- a/Turkey/DotNet.cs +++ b/Turkey/DotNet.cs @@ -93,7 +93,7 @@ public ProcessResult(int exitCode, string stdout, string stderr) } } - public static async Task BuildAsync(DirectoryInfo workingDirectory, CancellationToken token) + public static async Task BuildAsync(DirectoryInfo workingDirectory, IReadOnlyDictionary environment, CancellationToken token) { var arguments = new string[] { @@ -102,21 +102,21 @@ public static async Task BuildAsync(DirectoryInfo workingDirector "-p:UseSharedCompilation=false", "-m:1", }; - var result = await RunDotNetCommandAsync(workingDirectory, arguments, token); + var result = await RunDotNetCommandAsync(workingDirectory, arguments, environment, token); return result; } - public static async Task RunAsync(DirectoryInfo workingDirectory, CancellationToken token) + public static async Task RunAsync(DirectoryInfo workingDirectory, IReadOnlyDictionary environment, CancellationToken token) { - return await RunDotNetCommandAsync(workingDirectory, new string[] { "run", "--no-restore", "--no-build"} , token); + return await RunDotNetCommandAsync(workingDirectory, new string[] { "run", "--no-restore", "--no-build"} , environment, token); } - public static async Task TestAsync(DirectoryInfo workingDirectory, CancellationToken token) + public static async Task TestAsync(DirectoryInfo workingDirectory, IReadOnlyDictionary environment, CancellationToken token) { - return await RunDotNetCommandAsync(workingDirectory, new string[] { "test", "--no-restore", "--no-build"} , token); + return await RunDotNetCommandAsync(workingDirectory, new string[] { "test", "--no-restore", "--no-build"} , environment, token); } - private static async Task RunDotNetCommandAsync(DirectoryInfo workingDirectory, string[] commands, CancellationToken token) + private static async Task RunDotNetCommandAsync(DirectoryInfo workingDirectory, string[] commands, IReadOnlyDictionary environment, CancellationToken token) { var arguments = string.Join(" ", commands); ProcessStartInfo startInfo = new ProcessStartInfo() @@ -128,6 +128,12 @@ private static async Task RunDotNetCommandAsync(DirectoryInfo wor RedirectStandardError = true, }; + startInfo.EnvironmentVariables.Clear(); + foreach (var (key, value) in environment) + { + startInfo.EnvironmentVariables.Add(key, value); + } + using (var process = Process.Start(startInfo)) { StringWriter standardOutputWriter = new StringWriter(); diff --git a/Turkey/EnvironmentVariableSanitizer.cs b/Turkey/EnvironmentVariableSanitizer.cs new file mode 100644 index 0000000..7d11d87 --- /dev/null +++ b/Turkey/EnvironmentVariableSanitizer.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Turkey +{ + public class EnvironmentVariableSanitizer + { + private readonly List ToFilter = new List() + { + "OPENSSL_CONF", + }; + + public Dictionary SanitizeCurrentEnvironmentVariables() + { + return SanitizeEnvironmentVariables(Environment.GetEnvironmentVariables()); + } + + public Dictionary SanitizeEnvironmentVariables(IDictionary environmentVariables) + { + var result = new Dictionary(); + + foreach (DictionaryEntry entry in environmentVariables) + { + if (ToFilter.Contains((string)entry.Key)) + { + continue; + } + + result.Add((string)entry.Key, (string)entry.Value); + } + + return result; + } + } +} diff --git a/Turkey/Program.cs b/Turkey/Program.cs index c1f140e..7df03c7 100644 --- a/Turkey/Program.cs +++ b/Turkey/Program.cs @@ -100,15 +100,20 @@ public static async Task Run(string testRoot, List platformIds = new PlatformId().CurrentIds; Console.WriteLine($"Current platform is: {string.Join(", ", platformIds)}"); + var sanitizer = new EnvironmentVariableSanitizer(); + var envVars = sanitizer.SanitizeCurrentEnvironmentVariables(); + SystemUnderTest system = new SystemUnderTest( runtimeVersion: dotnet.LatestRuntimeVersion, sdkVersion: dotnet.LatestSdkVersion, - platformIds: platformIds + platformIds: platformIds, + environmentVariables: envVars ); Version packageVersion = dotnet.LatestRuntimeVersion; string nuGetConfig = await GenerateNuGetConfigIfNeededAsync(additionalFeed, packageVersion); + TestRunner runner = new TestRunner( cleaner: cleaner, system: system, diff --git a/Turkey/TestRunner.cs b/Turkey/TestRunner.cs index 942c514..e6c8efa 100644 --- a/Turkey/TestRunner.cs +++ b/Turkey/TestRunner.cs @@ -21,12 +21,14 @@ public class SystemUnderTest public Version RuntimeVersion { get; } public Version SdkVersion { get; } public List CurrentPlatformIds { get; } + public IReadOnlyDictionary EnvironmentVariables; - public SystemUnderTest(Version runtimeVersion, Version sdkVersion, List platformIds) + public SystemUnderTest(Version runtimeVersion, Version sdkVersion, List platformIds, IReadOnlyDictionary environmentVariables) { RuntimeVersion = runtimeVersion; SdkVersion = sdkVersion; CurrentPlatformIds = platformIds; + EnvironmentVariables = environmentVariables; } } diff --git a/Turkey/XUnitTest.cs b/Turkey/XUnitTest.cs index 3d53373..a3660c9 100644 --- a/Turkey/XUnitTest.cs +++ b/Turkey/XUnitTest.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -47,12 +48,12 @@ protected override async Task InternalRunAsync(CancellationToken can private async Task BuildProjectAsync(CancellationToken token) { - return ProcessResultToPartialResult(await DotNet.BuildAsync(Directory, token)); + return ProcessResultToPartialResult(await DotNet.BuildAsync(Directory, SystemUnderTest.EnvironmentVariables, token)); } private async Task TestProjectAsync(CancellationToken token) { - return ProcessResultToPartialResult(await DotNet.TestAsync(Directory, token)); + return ProcessResultToPartialResult(await DotNet.TestAsync(Directory, SystemUnderTest.EnvironmentVariables, token)); } private static PartialResult ProcessResultToPartialResult(DotNet.ProcessResult result)