From dd6648c0074b41203cd86725f33875f72d95cf74 Mon Sep 17 00:00:00 2001 From: Shivam Bagadia Date: Mon, 28 Oct 2024 22:27:01 +0530 Subject: [PATCH 1/2] added since on line level changes --- .../Stryker.Core/DiffProviders/DiffResult.cs | 11 +- .../DiffProviders/GitDiffProvider.cs | 137 +++++++---- .../MutantFilters/SinceMutantFilter.cs | 228 ++++++++++-------- 3 files changed, 226 insertions(+), 150 deletions(-) diff --git a/src/Stryker.Core/Stryker.Core/DiffProviders/DiffResult.cs b/src/Stryker.Core/Stryker.Core/DiffProviders/DiffResult.cs index 6dc91a7619..ad95e55a41 100644 --- a/src/Stryker.Core/Stryker.Core/DiffProviders/DiffResult.cs +++ b/src/Stryker.Core/Stryker.Core/DiffProviders/DiffResult.cs @@ -1,9 +1,10 @@ using System.Collections.Generic; -namespace Stryker.Core.DiffProviders; - -public class DiffResult +namespace Stryker.Core.DiffProviders { - public ICollection ChangedTestFiles { get; set; } - public ICollection ChangedSourceFiles { get; set; } + public class DiffResult + { + public IDictionary> ChangedTestFiles { get; set; } + public IDictionary> ChangedSourceFiles { get; set; } + } } diff --git a/src/Stryker.Core/Stryker.Core/DiffProviders/GitDiffProvider.cs b/src/Stryker.Core/Stryker.Core/DiffProviders/GitDiffProvider.cs index 1b3e0b8549..9eff466246 100644 --- a/src/Stryker.Core/Stryker.Core/DiffProviders/GitDiffProvider.cs +++ b/src/Stryker.Core/Stryker.Core/DiffProviders/GitDiffProvider.cs @@ -1,81 +1,116 @@ +using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using LibGit2Sharp; +using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Extensions; +using Spectre.Console; using Stryker.Abstractions.Exceptions; using Stryker.Abstractions.Options; using Stryker.Core.Baseline.Providers; using Stryker.Core.Mutants; using Stryker.Utilities; -namespace Stryker.Core.DiffProviders; - -public class GitDiffProvider : IDiffProvider +namespace Stryker.Core.DiffProviders { - public TestSet Tests { get; } - private readonly IStrykerOptions _options; - private readonly IGitInfoProvider _gitInfoProvider; - - public GitDiffProvider(IStrykerOptions options, TestSet tests, IGitInfoProvider gitInfoProvider = null) + public class GitDiffProvider : IDiffProvider { - Tests = tests; - _options = options; - _gitInfoProvider = gitInfoProvider ?? new GitInfoProvider(options); - } - - public DiffResult ScanDiff() - { - var diffResult = new DiffResult() - { - ChangedSourceFiles = new Collection(), - ChangedTestFiles = new Collection() - }; - - // A git repository has been detected, calculate the diff to filter - var repository = _gitInfoProvider.Repository; - var commit = _gitInfoProvider.DetermineCommit(); + public TestSet Tests { get; } + private readonly IStrykerOptions _options; + private readonly IGitInfoProvider _gitInfoProvider; - if (commit == null) + public GitDiffProvider(IStrykerOptions options, TestSet tests, IGitInfoProvider gitInfoProvider = null) { - throw new InputException("Could not find a commit to diff. Please check you have provided the correct committish for 'since'."); + Tests = tests; + _options = options; + _gitInfoProvider = gitInfoProvider ?? new GitInfoProvider(options); } - var testProjects = _options.TestProjects.ToList(); - if (!testProjects.Any()) + public DiffResult ScanDiff() { - testProjects.Add(_options.ProjectPath); - } + var diffResult = new DiffResult() + { + ChangedSourceFiles = new Dictionary>(), + ChangedTestFiles = new Dictionary>(), + }; - var testPaths = testProjects - .Select(testProject => testProject.EndsWith(Path.DirectorySeparatorChar) - ? testProject - : testProject + Path.DirectorySeparatorChar) - .ToArray(); + // A git repository has been detected, calculate the diff to filter + var repository = _gitInfoProvider.Repository; + var commit = _gitInfoProvider.DetermineCommit(); - foreach (var patchChanges in repository.Diff.Compare(commit.Tree, DiffTargets.WorkingDirectory)) - { - var diffPath = FilePathUtils.NormalizePathSeparators(Path.Combine(_gitInfoProvider.RepositoryPath, patchChanges.Path)); + if (commit == null) + { + throw new InputException("Could not find a commit to diff. Please check you have provided the correct committish for 'since'."); + } - if (testPaths.Any(testPath => diffPath.StartsWith(testPath))) + var testProjects = _options.TestProjects.ToList(); + if (!testProjects.Any()) { - diffResult.ChangedTestFiles.Add(diffPath); + testProjects.Add(_options.ProjectPath); } - else + + var testPaths = testProjects + .Select(testProject => testProject.EndsWith(Path.DirectorySeparatorChar) + ? testProject + : testProject + Path.DirectorySeparatorChar) + .ToArray(); + + foreach (var patchChanges in repository.Diff.Compare(commit.Tree, DiffTargets.WorkingDirectory)) { - diffResult.ChangedSourceFiles.Add(diffPath); + var diffPath = FilePathUtils.NormalizePathSeparators(Path.Combine(_gitInfoProvider.RepositoryPath, patchChanges.Path)); + + if (testPaths.Any(testPath => diffPath.StartsWith(testPath))) + { + for (var i = 0; i < patchChanges.AddedLines.Count; i++) + { + if (!diffResult.ChangedTestFiles.ContainsKey(diffPath)) + { + diffResult.ChangedTestFiles.Add(diffPath, [patchChanges.AddedLines[i].LineNumber]); + + } + else + + { + var entry = diffResult.ChangedTestFiles[diffPath]; + entry.Add(patchChanges.AddedLines[i].LineNumber); + } + } + } + else + { + if (patchChanges.AddedLines.Count > 0) + { + for (var i = 0; i < patchChanges.AddedLines.Count; i++) + { + if (!diffResult.ChangedSourceFiles.ContainsKey(diffPath)) + { + diffResult.ChangedSourceFiles.Add(diffPath, [patchChanges.AddedLines[i].LineNumber]); + + } + else + + { + var entry = diffResult.ChangedSourceFiles[diffPath]; + entry.Add(patchChanges.AddedLines[i].LineNumber); + } + } + + } + } } - } - RemoveFilteredOutFiles(diffResult); - return diffResult; - } + RemoveFilteredOutFiles(diffResult); - private void RemoveFilteredOutFiles(DiffResult diffResult) - { - foreach (var glob in _options.DiffIgnoreChanges.Select(d => d.Glob)) + return diffResult; + } + + private void RemoveFilteredOutFiles(DiffResult diffResult) { - diffResult.ChangedSourceFiles = diffResult.ChangedSourceFiles.Where(diffResultFile => !glob.IsMatch(diffResultFile)).ToList(); - diffResult.ChangedTestFiles = diffResult.ChangedTestFiles.Where(diffResultFile => !glob.IsMatch(diffResultFile)).ToList(); + foreach (var glob in _options.DiffIgnoreChanges.Select(d => d.Glob)) + { + diffResult.ChangedSourceFiles = diffResult.ChangedSourceFiles.Where(diffResultFile => !glob.IsMatch(diffResultFile.Key)).ToDictionary(); + diffResult.ChangedTestFiles = diffResult.ChangedTestFiles.Where(diffResultFile => !glob.IsMatch(diffResultFile.Key)).ToDictionary(); + } } } } diff --git a/src/Stryker.Core/Stryker.Core/MutantFilters/SinceMutantFilter.cs b/src/Stryker.Core/Stryker.Core/MutantFilters/SinceMutantFilter.cs index ca6a6e7910..0dadfa30bb 100644 --- a/src/Stryker.Core/Stryker.Core/MutantFilters/SinceMutantFilter.cs +++ b/src/Stryker.Core/Stryker.Core/MutantFilters/SinceMutantFilter.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.VisualBasic.Syntax; using Microsoft.Extensions.Logging; using Stryker.Abstractions.Logging; using Stryker.Abstractions.Mutants; @@ -10,134 +11,173 @@ using Stryker.Core.DiffProviders; using Stryker.Core.Mutants; -namespace Stryker.Core.MutantFilters; - -public class SinceMutantFilter : IMutantFilter +namespace Stryker.Core.MutantFilters { - private readonly DiffResult _diffResult; - private readonly TestSet _tests; - private readonly ILogger _logger; - - public MutantFilter Type => MutantFilter.Since; - public string DisplayName => "since filter"; - - public SinceMutantFilter(IDiffProvider diffProvider = null) + public class SinceMutantFilter : IMutantFilter { - _logger = ApplicationLogging.LoggerFactory.CreateLogger(); + private readonly DiffResult _diffResult; + private readonly TestSet _tests; + private readonly ILogger _logger; - _diffResult = diffProvider.ScanDiff(); - _tests = diffProvider.Tests; + public MutantFilter Type => MutantFilter.Since; + public string DisplayName => "since filter"; - if (_diffResult != null) + public SinceMutantFilter(IDiffProvider diffProvider = null) { - _logger.LogInformation("{ChangedFilesCount} files changed", (_diffResult.ChangedSourceFiles?.Count ?? 0) + (_diffResult.ChangedTestFiles?.Count ?? 0)); + _logger = ApplicationLogging.LoggerFactory.CreateLogger(); + + _diffResult = diffProvider.ScanDiff(); + _tests = diffProvider.Tests; - if (_diffResult.ChangedSourceFiles != null) + if (_diffResult != null) { - foreach (var changedFile in _diffResult.ChangedSourceFiles) + _logger.LogInformation("{ChangedFilesCount} files changed", (_diffResult.ChangedSourceFiles?.Count ?? 0) + (_diffResult.ChangedTestFiles?.Count ?? 0)); + + if (_diffResult.ChangedSourceFiles != null) { - _logger.LogInformation("Changed file {ChangedFile}", changedFile); + foreach (var changedFile in _diffResult.ChangedSourceFiles) + { + _logger.LogInformation("Changed file {ChangedFile}", changedFile); + } } - } - if (_diffResult.ChangedTestFiles != null) - { - foreach (var changedFile in _diffResult.ChangedTestFiles) + if (_diffResult.ChangedTestFiles != null) { - _logger.LogInformation("Changed test file {ChangedFile}", changedFile); + foreach (var changedFile in _diffResult.ChangedTestFiles) + { + _logger.LogInformation("Changed test file {ChangedFile}", changedFile); + } } } } - } - public IEnumerable FilterMutants(IEnumerable mutants, IReadOnlyFileLeaf file, IStrykerOptions options) - { - // Mutants can be enabled for testing based on multiple reasons. We store all the filtered mutants in this list and return this list. - IEnumerable filteredMutants; - - // A non-csharp file is flagged by the diff result as modified. We cannot determine which mutants will be affected by this, thus all mutants have to be tested. - if (_diffResult.ChangedTestFiles is { } && _diffResult.ChangedTestFiles.Any(x => !x.EndsWith(".cs"))) + public IEnumerable FilterMutants(IEnumerable mutants, IReadOnlyFileLeaf file, IStrykerOptions options) { - _logger.LogDebug("Returning all mutants in {RelativePath} because a non-source file is modified", file.RelativePath); - return SetMutantStatusForNonCSharpFileChanged(mutants); - } + // Mutants can be enabled for testing based on multiple reasons. We store all the filtered mutants in this list and return this list. + IEnumerable filteredMutants; - // If the diff result flags this file as modified, we want to run all mutants again - if (_diffResult.ChangedSourceFiles != null && _diffResult.ChangedSourceFiles.Contains(file.FullPath)) - { - _logger.LogDebug("Returning all mutants in {RelativePath} because the file is modified", file.RelativePath); - return SetMutantStatusForFileChanged(mutants); - } - else - { - filteredMutants = SetNotRunMutantsToIgnored(mutants); - } + // A non-csharp file is flagged by the diff result as modified. We cannot determine which mutants will be affected by this, thus all mutants have to be tested. + if (_diffResult.ChangedTestFiles is { } && _diffResult.ChangedTestFiles.Keys.Any(x => !x.EndsWith(".cs"))) + { + _logger.LogDebug("Returning all mutants in {RelativePath} because a non-source file is modified", file.RelativePath); + return SetMutantStatusForNonCSharpFileChanged(mutants); + } - // If any of the tests have been changed, we want to return all mutants covered by these testfiles. - // Only check for changed c# files. Other files have already been handled. - if (_diffResult.ChangedTestFiles != null && _diffResult.ChangedTestFiles.Any(file => file.EndsWith(".cs"))) - { - filteredMutants = ResetMutantStatusForChangedTests(mutants); - } + // If the diff result flags this file as modified, we want to run all mutants again + if (_diffResult.ChangedSourceFiles != null && _diffResult.ChangedSourceFiles.Keys.Contains(file.FullPath)) + { + foreach (var mutant in mutants) + { + foreach (var line in _diffResult.ChangedSourceFiles[file.FullPath]) + { + + var actualLineSpan = mutant.Mutation.OriginalNode.GetLocation().GetMappedLineSpan(); + + _logger.LogDebug("Original line span is found to be {actualLineSpan}", actualLineSpan); + var start = actualLineSpan.Span.Start.Line; + var end = actualLineSpan.Span.Start.Line; + if (start <= line && line <= end) + { + if (mutant.ResultStatus != MutantStatus.NoCoverage) + { + mutant.ResultStatus = MutantStatus.Pending; + mutant.ResultStatusReason = "Mutant changed compared to target commit"; + } + } + } + } + _logger.LogDebug("Returning all mutants in {RelativePath} because the file is modified", file.RelativePath); + return mutants; + } + else + { + filteredMutants = SetNotRunMutantsToIgnored(mutants); + } - return filteredMutants; - } + // If any of the tests have been changed, we want to return all mutants covered by these testfiles. + // Only check for changed c# files. Other files have already been handled. + if (_diffResult.ChangedTestFiles != null && _diffResult.ChangedTestFiles.Keys.Any(file => file.EndsWith(".cs"))) + { + foreach (var mutant in mutants) + { + foreach (var line in _diffResult.ChangedTestFiles[file.FullPath]) + { + var actualLineSpan = mutant.Mutation.OriginalNode.GetLocation().GetMappedLineSpan(); + + _logger.LogDebug("Original line span is found to be {actualLineSpan}", actualLineSpan); + var start = actualLineSpan.Span.Start.Line; + var end = actualLineSpan.Span.Start.Line; + if (start <= line && line <= end) + { + if (mutant.ResultStatus != MutantStatus.NoCoverage) + { + mutant.ResultStatus = MutantStatus.Pending; + mutant.ResultStatusReason = "Mutant changed compared to target commit"; + } + } + } + } + } - private static IEnumerable SetNotRunMutantsToIgnored(IEnumerable mutants) - { - foreach (var mutant in mutants.Where(m => m.ResultStatus == MutantStatus.Pending || m.ResultStatus == MutantStatus.NoCoverage)) - { - mutant.ResultStatus = MutantStatus.Ignored; - mutant.ResultStatusReason = "Mutant not changed compared to target commit"; + return mutants; } - return new List(); - } - - private static IEnumerable SetMutantStatusForFileChanged(IEnumerable mutants) - { - foreach (var mutant in mutants.Where(m => m.ResultStatus != MutantStatus.NoCoverage)) + private static IEnumerable SetNotRunMutantsToIgnored(IEnumerable mutants) { - mutant.ResultStatus = MutantStatus.Pending; - mutant.ResultStatusReason = "Mutant changed compared to target commit"; - } - - return mutants; - } + foreach (var mutant in mutants.Where(m => m.ResultStatus == MutantStatus.Pending || m.ResultStatus == MutantStatus.NoCoverage)) + { + mutant.ResultStatus = MutantStatus.Ignored; + mutant.ResultStatusReason = "Mutant not changed compared to target commit"; + } - private static IEnumerable SetMutantStatusForNonCSharpFileChanged(IEnumerable mutants) - { - foreach (var mutant in mutants.Where(m => m.ResultStatus != MutantStatus.NoCoverage)) - { - mutant.ResultStatus = MutantStatus.Pending; - mutant.ResultStatusReason = "Non-CSharp files in test project were changed"; + return new List(); } - return mutants; - } + private static IEnumerable SetMutantStatusForFileChanged(IEnumerable mutants) + { + foreach (var mutant in mutants.Where(m => m.ResultStatus != MutantStatus.NoCoverage)) + { + mutant.ResultStatus = MutantStatus.Pending; + mutant.ResultStatusReason = "Mutant changed compared to target commit"; + } - private IEnumerable ResetMutantStatusForChangedTests(IEnumerable mutants) - { - var filteredMutants = new List(); + return mutants; + } - foreach (var mutant in mutants) + private static IEnumerable SetMutantStatusForNonCSharpFileChanged(IEnumerable mutants) { - if (mutant.CoveringTests.IsEmpty || mutant.CoveringTests.Count == 0) + foreach (var mutant in mutants.Where(m => m.ResultStatus != MutantStatus.NoCoverage)) { - continue; + mutant.ResultStatus = MutantStatus.Pending; + mutant.ResultStatusReason = "Non-CSharp files in test project were changed"; } - var coveringTests = _tests.Extract(mutant.CoveringTests.GetGuids()); - if (coveringTests != null - && coveringTests.Any(coveringTest => _diffResult.ChangedTestFiles.Any(changedTestFile => coveringTest.TestFilePath == changedTestFile - || string.IsNullOrEmpty(coveringTest.TestFilePath)))) + return mutants; + } + + private IEnumerable ResetMutantStatusForChangedTests(IEnumerable mutants) + { + var filteredMutants = new List(); + + foreach (var mutant in mutants) { - mutant.ResultStatus = MutantStatus.Pending; - mutant.ResultStatusReason = "One or more covering tests changed"; + if (mutant.CoveringTests.IsEmpty || mutant.CoveringTests.Count == 0) + { + continue; + } + var coveringTests = _tests.Extract(mutant.CoveringTests.GetGuids()); + + if (coveringTests != null + && coveringTests.Any(coveringTest => _diffResult.ChangedTestFiles.Keys.Any(changedTestFile => coveringTest.TestFilePath == changedTestFile + || string.IsNullOrEmpty(coveringTest.TestFilePath)))) + { + mutant.ResultStatus = MutantStatus.Pending; + mutant.ResultStatusReason = "One or more covering tests changed"; - filteredMutants.Add(mutant); + filteredMutants.Add(mutant); + } } - } - return filteredMutants; + return filteredMutants; + } } } From 8c522c6bd23f14187fbfa6d88bd0120c432922df Mon Sep 17 00:00:00 2001 From: Shivam Bagadia Date: Tue, 29 Oct 2024 11:00:14 +0530 Subject: [PATCH 2/2] restore namespace --- .../Stryker.Core/DiffProviders/DiffResult.cs | 11 +- .../DiffProviders/GitDiffProvider.cs | 135 +++++----- .../MutantFilters/SinceMutantFilter.cs | 236 +++++++++--------- 3 files changed, 188 insertions(+), 194 deletions(-) diff --git a/src/Stryker.Core/Stryker.Core/DiffProviders/DiffResult.cs b/src/Stryker.Core/Stryker.Core/DiffProviders/DiffResult.cs index ad95e55a41..9277b754d4 100644 --- a/src/Stryker.Core/Stryker.Core/DiffProviders/DiffResult.cs +++ b/src/Stryker.Core/Stryker.Core/DiffProviders/DiffResult.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; -namespace Stryker.Core.DiffProviders +namespace Stryker.Core.DiffProviders; + +public class DiffResult { - public class DiffResult - { - public IDictionary> ChangedTestFiles { get; set; } - public IDictionary> ChangedSourceFiles { get; set; } - } + public IDictionary> ChangedTestFiles { get; set; } + public IDictionary> ChangedSourceFiles { get; set; } } diff --git a/src/Stryker.Core/Stryker.Core/DiffProviders/GitDiffProvider.cs b/src/Stryker.Core/Stryker.Core/DiffProviders/GitDiffProvider.cs index 9eff466246..4c2bb07c45 100644 --- a/src/Stryker.Core/Stryker.Core/DiffProviders/GitDiffProvider.cs +++ b/src/Stryker.Core/Stryker.Core/DiffProviders/GitDiffProvider.cs @@ -3,114 +3,111 @@ using System.IO; using System.Linq; using LibGit2Sharp; -using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Extensions; -using Spectre.Console; using Stryker.Abstractions.Exceptions; using Stryker.Abstractions.Options; using Stryker.Core.Baseline.Providers; using Stryker.Core.Mutants; using Stryker.Utilities; -namespace Stryker.Core.DiffProviders +namespace Stryker.Core.DiffProviders; + +public class GitDiffProvider : IDiffProvider { - public class GitDiffProvider : IDiffProvider + public TestSet Tests { get; } + private readonly IStrykerOptions _options; + private readonly IGitInfoProvider _gitInfoProvider; + + public GitDiffProvider(IStrykerOptions options, TestSet tests, IGitInfoProvider gitInfoProvider = null) { - public TestSet Tests { get; } - private readonly IStrykerOptions _options; - private readonly IGitInfoProvider _gitInfoProvider; + Tests = tests; + _options = options; + _gitInfoProvider = gitInfoProvider ?? new GitInfoProvider(options); + } - public GitDiffProvider(IStrykerOptions options, TestSet tests, IGitInfoProvider gitInfoProvider = null) + public DiffResult ScanDiff() + { + var diffResult = new DiffResult() { - Tests = tests; - _options = options; - _gitInfoProvider = gitInfoProvider ?? new GitInfoProvider(options); + ChangedSourceFiles = new Dictionary>(), + ChangedTestFiles = new Dictionary>(), + }; + + // A git repository has been detected, calculate the diff to filter + var repository = _gitInfoProvider.Repository; + var commit = _gitInfoProvider.DetermineCommit(); + + if (commit == null) + { + throw new InputException("Could not find a commit to diff. Please check you have provided the correct committish for 'since'."); } - public DiffResult ScanDiff() + var testProjects = _options.TestProjects.ToList(); + if (!testProjects.Any()) { - var diffResult = new DiffResult() - { - ChangedSourceFiles = new Dictionary>(), - ChangedTestFiles = new Dictionary>(), - }; + testProjects.Add(_options.ProjectPath); + } - // A git repository has been detected, calculate the diff to filter - var repository = _gitInfoProvider.Repository; - var commit = _gitInfoProvider.DetermineCommit(); + var testPaths = testProjects + .Select(testProject => testProject.EndsWith(Path.DirectorySeparatorChar) + ? testProject + : testProject + Path.DirectorySeparatorChar) + .ToArray(); - if (commit == null) - { - throw new InputException("Could not find a commit to diff. Please check you have provided the correct committish for 'since'."); - } + foreach (var patchChanges in repository.Diff.Compare(commit.Tree, DiffTargets.WorkingDirectory)) + { + var diffPath = FilePathUtils.NormalizePathSeparators(Path.Combine(_gitInfoProvider.RepositoryPath, patchChanges.Path)); - var testProjects = _options.TestProjects.ToList(); - if (!testProjects.Any()) + if (testPaths.Any(testPath => diffPath.StartsWith(testPath))) { - testProjects.Add(_options.ProjectPath); - } + for (var i = 0; i < patchChanges.AddedLines.Count; i++) + { + if (!diffResult.ChangedTestFiles.ContainsKey(diffPath)) + { + diffResult.ChangedTestFiles.Add(diffPath, [patchChanges.AddedLines[i].LineNumber]); - var testPaths = testProjects - .Select(testProject => testProject.EndsWith(Path.DirectorySeparatorChar) - ? testProject - : testProject + Path.DirectorySeparatorChar) - .ToArray(); + } + else - foreach (var patchChanges in repository.Diff.Compare(commit.Tree, DiffTargets.WorkingDirectory)) + { + var entry = diffResult.ChangedTestFiles[diffPath]; + entry.Add(patchChanges.AddedLines[i].LineNumber); + } + } + } + else { - var diffPath = FilePathUtils.NormalizePathSeparators(Path.Combine(_gitInfoProvider.RepositoryPath, patchChanges.Path)); - - if (testPaths.Any(testPath => diffPath.StartsWith(testPath))) + if (patchChanges.AddedLines.Count > 0) { for (var i = 0; i < patchChanges.AddedLines.Count; i++) { - if (!diffResult.ChangedTestFiles.ContainsKey(diffPath)) + if (!diffResult.ChangedSourceFiles.ContainsKey(diffPath)) { - diffResult.ChangedTestFiles.Add(diffPath, [patchChanges.AddedLines[i].LineNumber]); + diffResult.ChangedSourceFiles.Add(diffPath, [patchChanges.AddedLines[i].LineNumber]); } else { - var entry = diffResult.ChangedTestFiles[diffPath]; + var entry = diffResult.ChangedSourceFiles[diffPath]; entry.Add(patchChanges.AddedLines[i].LineNumber); } } - } - else - { - if (patchChanges.AddedLines.Count > 0) - { - for (var i = 0; i < patchChanges.AddedLines.Count; i++) - { - if (!diffResult.ChangedSourceFiles.ContainsKey(diffPath)) - { - diffResult.ChangedSourceFiles.Add(diffPath, [patchChanges.AddedLines[i].LineNumber]); - } - else - - { - var entry = diffResult.ChangedSourceFiles[diffPath]; - entry.Add(patchChanges.AddedLines[i].LineNumber); - } - } - - } } } + } - RemoveFilteredOutFiles(diffResult); + RemoveFilteredOutFiles(diffResult); - return diffResult; - } + return diffResult; + } - private void RemoveFilteredOutFiles(DiffResult diffResult) + private void RemoveFilteredOutFiles(DiffResult diffResult) + { + foreach (var glob in _options.DiffIgnoreChanges.Select(d => d.Glob)) { - foreach (var glob in _options.DiffIgnoreChanges.Select(d => d.Glob)) - { - diffResult.ChangedSourceFiles = diffResult.ChangedSourceFiles.Where(diffResultFile => !glob.IsMatch(diffResultFile.Key)).ToDictionary(); - diffResult.ChangedTestFiles = diffResult.ChangedTestFiles.Where(diffResultFile => !glob.IsMatch(diffResultFile.Key)).ToDictionary(); - } + diffResult.ChangedSourceFiles = diffResult.ChangedSourceFiles.Where(diffResultFile => !glob.IsMatch(diffResultFile.Key)).ToDictionary(); + diffResult.ChangedTestFiles = diffResult.ChangedTestFiles.Where(diffResultFile => !glob.IsMatch(diffResultFile.Key)).ToDictionary(); } } } diff --git a/src/Stryker.Core/Stryker.Core/MutantFilters/SinceMutantFilter.cs b/src/Stryker.Core/Stryker.Core/MutantFilters/SinceMutantFilter.cs index 0dadfa30bb..c2fb33e3d7 100644 --- a/src/Stryker.Core/Stryker.Core/MutantFilters/SinceMutantFilter.cs +++ b/src/Stryker.Core/Stryker.Core/MutantFilters/SinceMutantFilter.cs @@ -1,8 +1,6 @@ - using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.VisualBasic.Syntax; using Microsoft.Extensions.Logging; using Stryker.Abstractions.Logging; using Stryker.Abstractions.Mutants; @@ -11,173 +9,173 @@ using Stryker.Core.DiffProviders; using Stryker.Core.Mutants; -namespace Stryker.Core.MutantFilters +namespace Stryker.Core.MutantFilters; + +public class SinceMutantFilter : IMutantFilter { - public class SinceMutantFilter : IMutantFilter + private readonly DiffResult _diffResult; + private readonly TestSet _tests; + private readonly ILogger _logger; + + public MutantFilter Type => MutantFilter.Since; + public string DisplayName => "since filter"; + + public SinceMutantFilter(IDiffProvider diffProvider = null) { - private readonly DiffResult _diffResult; - private readonly TestSet _tests; - private readonly ILogger _logger; + _logger = ApplicationLogging.LoggerFactory.CreateLogger(); - public MutantFilter Type => MutantFilter.Since; - public string DisplayName => "since filter"; + _diffResult = diffProvider.ScanDiff(); + _tests = diffProvider.Tests; - public SinceMutantFilter(IDiffProvider diffProvider = null) + if (_diffResult != null) { - _logger = ApplicationLogging.LoggerFactory.CreateLogger(); - - _diffResult = diffProvider.ScanDiff(); - _tests = diffProvider.Tests; + _logger.LogInformation("{ChangedFilesCount} files changed", (_diffResult.ChangedSourceFiles?.Count ?? 0) + (_diffResult.ChangedTestFiles?.Count ?? 0)); - if (_diffResult != null) + if (_diffResult.ChangedSourceFiles != null) { - _logger.LogInformation("{ChangedFilesCount} files changed", (_diffResult.ChangedSourceFiles?.Count ?? 0) + (_diffResult.ChangedTestFiles?.Count ?? 0)); - - if (_diffResult.ChangedSourceFiles != null) + foreach (var changedFile in _diffResult.ChangedSourceFiles) { - foreach (var changedFile in _diffResult.ChangedSourceFiles) - { - _logger.LogInformation("Changed file {ChangedFile}", changedFile); - } + _logger.LogInformation("Changed file {ChangedFile}", changedFile); } - if (_diffResult.ChangedTestFiles != null) + } + if (_diffResult.ChangedTestFiles != null) + { + foreach (var changedFile in _diffResult.ChangedTestFiles) { - foreach (var changedFile in _diffResult.ChangedTestFiles) - { - _logger.LogInformation("Changed test file {ChangedFile}", changedFile); - } + _logger.LogInformation("Changed test file {ChangedFile}", changedFile); } } } + } - public IEnumerable FilterMutants(IEnumerable mutants, IReadOnlyFileLeaf file, IStrykerOptions options) - { - // Mutants can be enabled for testing based on multiple reasons. We store all the filtered mutants in this list and return this list. - IEnumerable filteredMutants; + public IEnumerable FilterMutants(IEnumerable mutants, IReadOnlyFileLeaf file, IStrykerOptions options) + { + // Mutants can be enabled for testing based on multiple reasons. We store all the filtered mutants in this list and return this list. + IEnumerable filteredMutants; - // A non-csharp file is flagged by the diff result as modified. We cannot determine which mutants will be affected by this, thus all mutants have to be tested. - if (_diffResult.ChangedTestFiles is { } && _diffResult.ChangedTestFiles.Keys.Any(x => !x.EndsWith(".cs"))) - { - _logger.LogDebug("Returning all mutants in {RelativePath} because a non-source file is modified", file.RelativePath); - return SetMutantStatusForNonCSharpFileChanged(mutants); - } + // A non-csharp file is flagged by the diff result as modified. We cannot determine which mutants will be affected by this, thus all mutants have to be tested. + if (_diffResult.ChangedTestFiles is { } && _diffResult.ChangedTestFiles.Keys.Any(x => !x.EndsWith(".cs"))) + { + _logger.LogDebug("Returning all mutants in {RelativePath} because a non-source file is modified", file.RelativePath); + return SetMutantStatusForNonCSharpFileChanged(mutants); + } - // If the diff result flags this file as modified, we want to run all mutants again - if (_diffResult.ChangedSourceFiles != null && _diffResult.ChangedSourceFiles.Keys.Contains(file.FullPath)) + // If the diff result flags this file as modified, we want to run all mutants again + if (_diffResult.ChangedSourceFiles != null && _diffResult.ChangedSourceFiles.Keys.Contains(file.FullPath)) + { + foreach (var mutant in mutants) { - foreach (var mutant in mutants) + foreach (var line in _diffResult.ChangedSourceFiles[file.FullPath]) { - foreach (var line in _diffResult.ChangedSourceFiles[file.FullPath]) - { - var actualLineSpan = mutant.Mutation.OriginalNode.GetLocation().GetMappedLineSpan(); + var actualLineSpan = mutant.Mutation.OriginalNode.GetLocation().GetMappedLineSpan(); - _logger.LogDebug("Original line span is found to be {actualLineSpan}", actualLineSpan); - var start = actualLineSpan.Span.Start.Line; - var end = actualLineSpan.Span.Start.Line; - if (start <= line && line <= end) + _logger.LogDebug("Original line span is found to be {actualLineSpan}", actualLineSpan); + var start = actualLineSpan.Span.Start.Line; + var end = actualLineSpan.Span.Start.Line; + if (start <= line && line <= end) + { + if (mutant.ResultStatus != MutantStatus.NoCoverage) { - if (mutant.ResultStatus != MutantStatus.NoCoverage) - { - mutant.ResultStatus = MutantStatus.Pending; - mutant.ResultStatusReason = "Mutant changed compared to target commit"; - } + mutant.ResultStatus = MutantStatus.Pending; + mutant.ResultStatusReason = "Mutant changed compared to target commit"; } } } - _logger.LogDebug("Returning all mutants in {RelativePath} because the file is modified", file.RelativePath); - return mutants; - } - else - { - filteredMutants = SetNotRunMutantsToIgnored(mutants); } + _logger.LogDebug("Returning all mutants in {RelativePath} because the file is modified", file.RelativePath); + return mutants; + } + else + { + filteredMutants = SetNotRunMutantsToIgnored(mutants); + } - // If any of the tests have been changed, we want to return all mutants covered by these testfiles. - // Only check for changed c# files. Other files have already been handled. - if (_diffResult.ChangedTestFiles != null && _diffResult.ChangedTestFiles.Keys.Any(file => file.EndsWith(".cs"))) + // If any of the tests have been changed, we want to return all mutants covered by these testfiles. + // Only check for changed c# files. Other files have already been handled. + if (_diffResult.ChangedTestFiles != null && _diffResult.ChangedTestFiles.Keys.Any(file => file.EndsWith(".cs"))) + { + foreach (var mutant in mutants) { - foreach (var mutant in mutants) + foreach (var line in _diffResult.ChangedTestFiles[file.FullPath]) { - foreach (var line in _diffResult.ChangedTestFiles[file.FullPath]) - { - var actualLineSpan = mutant.Mutation.OriginalNode.GetLocation().GetMappedLineSpan(); + var actualLineSpan = mutant.Mutation.OriginalNode.GetLocation().GetMappedLineSpan(); - _logger.LogDebug("Original line span is found to be {actualLineSpan}", actualLineSpan); - var start = actualLineSpan.Span.Start.Line; - var end = actualLineSpan.Span.Start.Line; - if (start <= line && line <= end) + _logger.LogDebug("Original line span is found to be {actualLineSpan}", actualLineSpan); + var start = actualLineSpan.Span.Start.Line; + var end = actualLineSpan.Span.Start.Line; + if (start <= line && line <= end) + { + if (mutant.ResultStatus != MutantStatus.NoCoverage) { - if (mutant.ResultStatus != MutantStatus.NoCoverage) - { - mutant.ResultStatus = MutantStatus.Pending; - mutant.ResultStatusReason = "Mutant changed compared to target commit"; - } + mutant.ResultStatus = MutantStatus.Pending; + mutant.ResultStatusReason = "Mutant changed compared to target commit"; } } } } - - return mutants; } - private static IEnumerable SetNotRunMutantsToIgnored(IEnumerable mutants) - { - foreach (var mutant in mutants.Where(m => m.ResultStatus == MutantStatus.Pending || m.ResultStatus == MutantStatus.NoCoverage)) - { - mutant.ResultStatus = MutantStatus.Ignored; - mutant.ResultStatusReason = "Mutant not changed compared to target commit"; - } + return mutants; + } - return new List(); + private static IEnumerable SetNotRunMutantsToIgnored(IEnumerable mutants) + { + foreach (var mutant in mutants.Where(m => m.ResultStatus == MutantStatus.Pending || m.ResultStatus == MutantStatus.NoCoverage)) + { + mutant.ResultStatus = MutantStatus.Ignored; + mutant.ResultStatusReason = "Mutant not changed compared to target commit"; } - private static IEnumerable SetMutantStatusForFileChanged(IEnumerable mutants) - { - foreach (var mutant in mutants.Where(m => m.ResultStatus != MutantStatus.NoCoverage)) - { - mutant.ResultStatus = MutantStatus.Pending; - mutant.ResultStatusReason = "Mutant changed compared to target commit"; - } + return new List(); + } - return mutants; + private static IEnumerable SetMutantStatusForFileChanged(IEnumerable mutants) + { + foreach (var mutant in mutants.Where(m => m.ResultStatus != MutantStatus.NoCoverage)) + { + mutant.ResultStatus = MutantStatus.Pending; + mutant.ResultStatusReason = "Mutant changed compared to target commit"; } - private static IEnumerable SetMutantStatusForNonCSharpFileChanged(IEnumerable mutants) - { - foreach (var mutant in mutants.Where(m => m.ResultStatus != MutantStatus.NoCoverage)) - { - mutant.ResultStatus = MutantStatus.Pending; - mutant.ResultStatusReason = "Non-CSharp files in test project were changed"; - } + return mutants; + } - return mutants; + private static IEnumerable SetMutantStatusForNonCSharpFileChanged(IEnumerable mutants) + { + foreach (var mutant in mutants.Where(m => m.ResultStatus != MutantStatus.NoCoverage)) + { + mutant.ResultStatus = MutantStatus.Pending; + mutant.ResultStatusReason = "Non-CSharp files in test project were changed"; } - private IEnumerable ResetMutantStatusForChangedTests(IEnumerable mutants) - { - var filteredMutants = new List(); + return mutants; + } - foreach (var mutant in mutants) + private IEnumerable ResetMutantStatusForChangedTests(IEnumerable mutants) + { + var filteredMutants = new List(); + + foreach (var mutant in mutants) + { + if (mutant.CoveringTests.IsEmpty || mutant.CoveringTests.Count == 0) { - if (mutant.CoveringTests.IsEmpty || mutant.CoveringTests.Count == 0) - { - continue; - } - var coveringTests = _tests.Extract(mutant.CoveringTests.GetGuids()); + continue; + } + var coveringTests = _tests.Extract(mutant.CoveringTests.GetGuids()); - if (coveringTests != null - && coveringTests.Any(coveringTest => _diffResult.ChangedTestFiles.Keys.Any(changedTestFile => coveringTest.TestFilePath == changedTestFile - || string.IsNullOrEmpty(coveringTest.TestFilePath)))) - { - mutant.ResultStatus = MutantStatus.Pending; - mutant.ResultStatusReason = "One or more covering tests changed"; + if (coveringTests != null + && coveringTests.Any(coveringTest => _diffResult.ChangedTestFiles.Keys.Any(changedTestFile => coveringTest.TestFilePath == changedTestFile + || string.IsNullOrEmpty(coveringTest.TestFilePath)))) + { + mutant.ResultStatus = MutantStatus.Pending; + mutant.ResultStatusReason = "One or more covering tests changed"; - filteredMutants.Add(mutant); - } + filteredMutants.Add(mutant); } - - return filteredMutants; } + + return filteredMutants; } } +