diff --git a/src/Stryker.Core/Stryker.Core/InjectedHelpers/MutantControl.cs b/src/Stryker.Core/Stryker.Core/InjectedHelpers/MutantControl.cs index 38eaa1b54..1eed3837a 100644 --- a/src/Stryker.Core/Stryker.Core/InjectedHelpers/MutantControl.cs +++ b/src/Stryker.Core/Stryker.Core/InjectedHelpers/MutantControl.cs @@ -48,7 +48,9 @@ public static bool IsActive(int id) if (ActiveMutant == ActiveMutantNotInitValue) { #pragma warning disable CS8600 - string environmentVariable = System.Environment.GetEnvironmentVariable("ActiveMutation"); + // get the environment variable storign the mutation id + string environmentVariableName = System.Environment.GetEnvironmentVariable("STRYKER_CONTROL_VAR"); + string environmentVariable = System.Environment.GetEnvironmentVariable(environmentVariableName); if (string.IsNullOrEmpty(environmentVariable)) { ActiveMutant = -1; diff --git a/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestContextInformation.cs b/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestContextInformation.cs index d6494261a..cb8bfa31d 100644 --- a/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestContextInformation.cs +++ b/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestContextInformation.cs @@ -93,19 +93,22 @@ public void Dispose() } /// - /// Starts a new VsTest instance and returns a wrapper to control it. + /// Starts a new VsTest instance and returns a wrapper to control it. /// /// Name of the instance to create (used in log files) /// a controlling the created instance. - public IVsTestConsoleWrapper BuildVsTestWrapper(string runnerId) + public IVsTestConsoleWrapper BuildVsTestWrapper(string runnerId, string controlVariable) { - var vsTestConsole = _wrapperBuilder(DetermineConsoleParameters(runnerId)); + var env = DetermineConsoleParameters(runnerId); + env.EnvironmentVariables["DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX"]="2"; + // we define a per runner control variable to prevent conflict + env.EnvironmentVariables["STRYKER_CONTROL_VAR"] = controlVariable; + var vsTestConsole = _wrapperBuilder(env); try { // Set roll forward on no candidate fx so vstest console can start on incompatible dotnet core runtimes - Environment.SetEnvironmentVariable("DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX", "2"); vsTestConsole.StartSession(); - vsTestConsole.InitializeExtensions(Enumerable.Empty()); + vsTestConsole.InitializeExtensions([]); } catch (Exception e) { @@ -188,7 +191,7 @@ public bool AddTestSource(string source, string frameworkVersion = null, string private void DiscoverTestsInSources(string newSource, string frameworkVersion = null, string platform = null) { - var wrapper = BuildVsTestWrapper("TestDiscoverer"); + var wrapper = BuildVsTestWrapper("TestDiscoverer", "NOT_NEEDED"); var messages = new List(); var handler = new DiscoveryEventHandler(messages); var settings = GenerateRunSettingsForDiscovery(frameworkVersion, platform); @@ -223,6 +226,13 @@ private void DiscoverTestsInSources(string newSource, string frameworkVersion = Tests.RegisterTests(VsTests.Values.Select(t => t.Description)); } + internal void RegisterDiscoveredTest(VsTestDescription vsTestDescription) + { + VsTests[vsTestDescription.Id] = vsTestDescription; + Tests.RegisterTest(vsTestDescription.Description); + TestsPerSource[vsTestDescription.Case.Source].Add(vsTestDescription.Id); + } + private void DetectTestFrameworks(ICollection tests) { if (tests == null) @@ -262,7 +272,7 @@ private string GenerateCoreSettings(int maxCpu, string frameworkVersion, string return $@" {Math.Max(0, maxCpu)} -{frameworkConfig}{platformConfig}{testCaseFilter} true +{frameworkConfig}{platformConfig}{testCaseFilter} true"; } @@ -309,4 +319,5 @@ public string GenerateRunSettings(int? timeout, bool forCoverage, Dictionary _initialResults = new List(); + private readonly ICollection _initialResults = []; private int _subCases; public VsTestDescription(TestCase testCase) diff --git a/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestRunner.cs b/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestRunner.cs index 0c5d275aa..410f3650d 100644 --- a/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestRunner.cs +++ b/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestRunner.cs @@ -35,6 +35,7 @@ public sealed class VsTestRunner : IDisposable private const int MaxAttempts = 3; private string RunnerId => $"Runner {_id}"; + private string ControlVariableName => $"ACTIVE_MUTATION_{_id}"; public VsTestRunner(VsTestContextInformation context, int id, @@ -43,7 +44,7 @@ public VsTestRunner(VsTestContextInformation context, _context = context; _id = id; _logger = logger ?? ApplicationLogging.LoggerFactory.CreateLogger(); - _vsTestConsole = _context.BuildVsTestWrapper(RunnerId); + _vsTestConsole = _context.BuildVsTestWrapper(RunnerId, ControlVariableName); } public TestRunResult InitialTest(IProjectAndTests project) @@ -60,8 +61,7 @@ public TestRunResult InitialTest(IProjectAndTests project) if (!_context.VsTests.ContainsKey(result.TestCase.Id)) { var vsTestDescription = new VsTestDescription(result.TestCase); - _context.VsTests[result.TestCase.Id] = vsTestDescription; - _context.Tests.RegisterTest(vsTestDescription.Description); + _context.RegisterDiscoveredTest(vsTestDescription); _logger.LogWarning( "{RunnerId}: Initial test run encounter an unexpected test case ({DisplayName}), mutation tests may be inaccurate. Disable coverage analysis if you have doubts.", RunnerId, result.TestCase.DisplayName); @@ -84,7 +84,7 @@ public TestRunResult TestMultipleMutants(IProjectAndTests project, ITimeoutValue if (testCases?.Count == 0) { return new TestRunResult(_context.VsTests.Values, TestGuidsList.NoTest(), TestGuidsList.NoTest(), - TestGuidsList.NoTest(), "Mutants are not covered by any test!", Enumerable.Empty(), + TestGuidsList.NoTest(), "Mutants are not covered by any test!", [], TimeSpan.Zero); } @@ -115,7 +115,7 @@ void HandleUpdate(IRunResults handler) : new WrappedGuidsEnumeration(handlerTestResults.Select(t => t.TestCase.Id)); var failedTest = new WrappedGuidsEnumeration(handlerTestResults .Where(tr => tr.Outcome == TestOutcome.Failed) - .Select(t => t.TestCase.Id)); + .Select(t => t.TestCase.Id)); var timedOutTest = new WrappedGuidsEnumeration(handler.TestsInTimeout?.Select(t => t.Id)); var remainingMutants = update?.Invoke(mutants, failedTest, tests, timedOutTest); @@ -248,8 +248,13 @@ public IRunResults RunCoverageSession(ITestGuids testsToRun, IProjectAndTests pr } var runSettings = _context.GenerateRunSettings(timeOut, forCoverage, mutantTestsMap, projectAndTests.HelperNamespace, source.TargetFramework, source.TargetPlatform()); - _logger.LogTrace("{RunnerId}: testing assembly {source}.", RunnerId, source); + var activeId = -1; + if (mutantTestsMap!=null && mutantTestsMap.Count==1) + { + activeId = mutantTestsMap.Keys.First(); + } + Environment.SetEnvironmentVariable(ControlVariableName, activeId.ToString()); RunVsTest(tests, source.GetAssemblyPath(), runSettings, options, timeOut, runEventHandler); if (_currentSessionCancelled) @@ -281,13 +286,15 @@ private void RunVsTest(ITestGuids tests, string source, string runSettings, Test { if (tests.IsEveryTest) { - _vsTestConsole.RunTestsWithCustomTestHost(new[] { source }, runSettings, options, eventHandler, + _vsTestConsole.RunTestsWithCustomTestHost([source], runSettings, options, eventHandler, strykerVsTestHostLauncher); } else { + var actualTestCases = tests.GetGuids().Select(t => _context.VsTests[t].Case).ToList(); + var testCases = actualTestCases; _vsTestConsole.RunTestsWithCustomTestHost( - tests.GetGuids().Select(t => _context.VsTests[t].Case), + testCases, runSettings, options, eventHandler, strykerVsTestHostLauncher); } }); @@ -371,7 +378,7 @@ private void PrepareVsTestConsole() } } - _vsTestConsole = _context.BuildVsTestWrapper($"{RunnerId}-{_instanceCount}"); + _vsTestConsole = _context.BuildVsTestWrapper($"{RunnerId}-{_instanceCount}", ControlVariableName); } #region IDisposable Support diff --git a/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestRunnerPool.cs b/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestRunnerPool.cs index ab307e796..4ede47d9a 100644 --- a/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestRunnerPool.cs +++ b/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestRunnerPool.cs @@ -188,8 +188,7 @@ private bool ConvertSingleResult(TestResult testResult, ISet seenTestCases // ==> we need it to use this test against every mutation _logger.LogDebug("VsTestRunner: No coverage data for {TestCase}.", testResult.TestCase.DisplayName); seenTestCases.Add(testDescription.Id); - coverageRunResult = new CoverageRunResult(testCaseId, CoverageConfidence.Dubious, Enumerable.Empty(), - Enumerable.Empty(), Enumerable.Empty()); + coverageRunResult = new CoverageRunResult(testCaseId, CoverageConfidence.Dubious, [], [], []); } else { diff --git a/src/Stryker.DataCollector/Stryker.DataCollector/CoverageCollector.cs b/src/Stryker.DataCollector/Stryker.DataCollector/CoverageCollector.cs index c840b323a..583ff1051 100644 --- a/src/Stryker.DataCollector/Stryker.DataCollector/CoverageCollector.cs +++ b/src/Stryker.DataCollector/Stryker.DataCollector/CoverageCollector.cs @@ -29,7 +29,6 @@ public class CoverageCollector : InProcDataCollection private IDataCollectionSink _dataSink; private bool _coverageOn; private int _activeMutation = -1; - private bool _reportFailure; private Action _logger; private readonly IDictionary _mutantTestedBy = new Dictionary(); @@ -94,7 +93,6 @@ public void Initialize(IDataCollectionSink dataCollectionSink) { _dataSink = dataCollectionSink; _throwingListener = new ThrowingListener(); - SetLogger(Console.WriteLine); } public void SetLogger(Action logger) => _logger = logger; @@ -276,11 +274,7 @@ private void PublishCoverageData(DataCollectionContext dataCollectionContext) { // no test covered any mutations, so the controller was never properly initialized _dataSink.SendData(dataCollectionContext, PropertyName, ";"); - if (!_reportFailure) - { - _dataSink.SendData(dataCollectionContext, CoverageLog, $"Did not find type {_controlClassName}. Mutated assembly may not be covered by any test."); - _reportFailure = true; - } + _dataSink.SendData(dataCollectionContext, CoverageLog, $"Test {dataCollectionContext.TestCase.DisplayName} endend. No mutant covered so far."); return; }