private void CompileMutations() { using var ms = new MemoryStream(); using var msForSymbols = _options.DevMode ? new MemoryStream() : null; // compile the mutated syntax trees var compileResult = _compilingProcess.Compile(_input.ProjectInfo.ProjectContents.CompilationSyntaxTrees, ms, msForSymbols, _options.DevMode); foreach (var testProject in _input.ProjectInfo.TestProjectAnalyzerResults) { var injectionPath = testProject.TargetDirectory; if (!_fileSystem.Directory.Exists(injectionPath)) { _fileSystem.Directory.CreateDirectory(injectionPath); } // inject the mutated Assembly into the test project using var fs = _fileSystem.File.Create(Path.Combine(injectionPath, _input.ProjectInfo.ProjectUnderTestAnalyzerResult.TargetFileName)); ms.Position = 0; ms.CopyTo(fs); if (msForSymbols != null) { // inject the debug symbols into the test project using var symbolDestination = _fileSystem.File.Create(Path.Combine(injectionPath, _input.ProjectInfo.ProjectUnderTestAnalyzerResult.SymbolFileName)); msForSymbols.Position = 0; msForSymbols.CopyTo(symbolDestination); } _logger.LogDebug("Injected the mutated assembly file into {0}", injectionPath); } // if a rollback took place, mark the rolled back mutants as status:BuildError if (compileResult.RollbackResult?.RollbackedIds.Any() ?? false) { foreach (var mutant in _input.ProjectInfo.ProjectContents.Mutants .Where(x => compileResult.RollbackResult.RollbackedIds.Contains(x.Id))) { // Ignore compilation errors if the mutation is skipped anyways. if (mutant.ResultStatus == MutantStatus.Ignored) { continue; } mutant.ResultStatus = MutantStatus.CompileError; mutant.ResultStatusReason = "Mutant caused compile errors"; } } }
private void CompileMutations() { using (var ms = new MemoryStream()) { // compile the mutated syntax trees var compileResult = _compilingProcess.Compile(_input.ProjectInfo.ProjectContents.CompilationSyntaxTrees, ms, _options.DevMode); foreach (var testProject in _input.ProjectInfo.TestProjectAnalyzerResults) { var injectionPath = _input.ProjectInfo.GetInjectionPath(testProject); if (!_fileSystem.Directory.Exists(Path.GetDirectoryName(injectionPath)) && !_fileSystem.File.Exists(injectionPath)) { _fileSystem.Directory.CreateDirectory(Path.GetDirectoryName(injectionPath)); } // inject the mutated Assembly into the test project using (var fs = _fileSystem.File.Create(injectionPath)) { ms.Position = 0; ms.CopyTo(fs); } _logger.LogDebug("Injected the mutated assembly file into {0}", injectionPath); } // if a rollback took place, mark the rollbacked mutants as status:BuildError if (compileResult.RollbackResult?.RollbackedIds.Any() ?? false) { foreach (var mutant in _input.ProjectInfo.ProjectContents.Mutants .Where(x => compileResult.RollbackResult.RollbackedIds.Contains(x.Id))) { // Ignore compilation errors if the mutation is skipped anyways. if (mutant.ResultStatus == MutantStatus.Ignored) { continue; } mutant.ResultStatus = MutantStatus.CompileError; mutant.ResultStatusReason = "Could not compile"; } } } }
public void Mutate() { var preprocessorSymbols = _input.ProjectInfo.ProjectUnderTestAnalyzerResult.DefineConstants; _logger.LogDebug("Injecting helpers into assembly."); var mutatedSyntaxTrees = new List <SyntaxTree>(); var cSharpParseOptions = new CSharpParseOptions(_options.LanguageVersion, DocumentationMode.None, preprocessorSymbols: preprocessorSymbols); foreach (var(name, code) in CodeInjection.MutantHelpers) { mutatedSyntaxTrees.Add(CSharpSyntaxTree.ParseText(code, path: name, options: cSharpParseOptions)); } foreach (var file in _input.ProjectInfo.ProjectContents.GetAllFiles()) { // Get the syntax tree for the source file var syntaxTree = CSharpSyntaxTree.ParseText(file.SourceCode, path: file.FullPath, options: cSharpParseOptions); _logger.LogDebug($"Mutating {file.Name}"); // Mutate the syntax tree var mutatedSyntaxTree = _orchestrator.Mutate(syntaxTree.GetRoot()); // Add the mutated syntax tree for compilation mutatedSyntaxTrees.Add(mutatedSyntaxTree.SyntaxTree); if (_options.DevMode) { _logger.LogTrace($"Mutated {file.Name}:{Environment.NewLine}{mutatedSyntaxTree.ToFullString()}"); } // Filter the mutants var allMutants = _orchestrator.GetLatestMutantBatch(); IEnumerable <Mutant> filteredMutants = allMutants; foreach (var mutantFilter in _mutantFilters) { var current = mutantFilter.FilterMutants(filteredMutants, file, _options).ToList(); // Mark the filtered mutants as skipped foreach (var skippedMutant in filteredMutants.Except(current)) { skippedMutant.ResultStatus = MutantStatus.Skipped; skippedMutant.ResultStatusReason = $"Removed by {mutantFilter.DisplayName}"; } filteredMutants = current; } // Store the generated mutants in the file file.Mutants = allMutants; } _logger.LogDebug("{0} mutants created", _input.ProjectInfo.ProjectContents.Mutants.Count()); using (var ms = new MemoryStream()) { // compile the mutated syntax trees var compileResult = _compilingProcess.Compile(mutatedSyntaxTrees, ms, _options.DevMode); foreach (var testProject in _input.ProjectInfo.TestProjectAnalyzerResults) { var injectionPath = _input.ProjectInfo.GetInjectionPath(testProject); if (!_fileSystem.Directory.Exists(Path.GetDirectoryName(injectionPath)) && !_fileSystem.File.Exists(injectionPath)) { _fileSystem.Directory.CreateDirectory(Path.GetDirectoryName(injectionPath)); } // inject the mutated Assembly into the test project using (var fs = _fileSystem.File.Create(injectionPath)) { ms.Position = 0; ms.CopyTo(fs); } _logger.LogDebug("Injected the mutated assembly file into {0}", injectionPath); } // if a rollback took place, mark the rollbacked mutants as status:BuildError if (compileResult.RollbackResult?.RollbackedIds.Any() ?? false) { foreach (var mutant in _input.ProjectInfo.ProjectContents.Mutants .Where(x => compileResult.RollbackResult.RollbackedIds.Contains(x.Id))) { // Ignore compilation errors if the mutation is skipped anyways. if (mutant.ResultStatus == MutantStatus.Skipped) { continue; } mutant.ResultStatus = MutantStatus.CompileError; mutant.ResultStatusReason = "Could not compile"; } } } var skippedMutantGroups = _input.ProjectInfo.ProjectContents.GetAllFiles() .SelectMany(f => f.Mutants) .Where(x => x.ResultStatus != MutantStatus.NotRun).GroupBy(x => x.ResultStatusReason) .OrderBy(x => x.Key); foreach (var skippedMutantGroup in skippedMutantGroups) { _logger.LogInformation("{0} mutants got status {1}. Reason: {2}", skippedMutantGroup.Count(), skippedMutantGroup.First().ResultStatus, skippedMutantGroup.Key); } _logger.LogInformation("{0} mutants ready for test", _input.ProjectInfo.ProjectContents.TotalMutants.Count()); _reporter.OnMutantsCreated(_input.ProjectInfo.ProjectContents); }
public void Mutate(StrykerOptions options) { _logger.LogDebug("Injecting helpers into assembly."); var mutatedSyntaxTrees = new List <SyntaxTree>(); foreach (var helper in CodeInjection.MutantHelpers) { mutatedSyntaxTrees.Add(CSharpSyntaxTree.ParseText(helper.Value, path: helper.Key, options: new CSharpParseOptions(options.LanguageVersion))); } foreach (var file in _input.ProjectInfo.ProjectContents.GetAllFiles()) { // Get the syntax tree for the source file var syntaxTree = CSharpSyntaxTree.ParseText(file.SourceCode, path: file.FullPath, options: new CSharpParseOptions(options.LanguageVersion)); if (!file.IsExcluded) { // Mutate the syntax tree var mutatedSyntaxTree = _orchestrator.Mutate(syntaxTree.GetRoot()); // Add the mutated syntax tree for compilation mutatedSyntaxTrees.Add(mutatedSyntaxTree.SyntaxTree); // Store the generated mutants in the file file.Mutants = _orchestrator.GetLatestMutantBatch(); } else { // Add the original syntax tree for future compilation mutatedSyntaxTrees.Add(syntaxTree); // There aren't any mutants generated so a new list of mutants is sufficient file.Mutants = new List <Mutant>(); _logger.LogDebug("Excluded file {0}, no mutants created", file.FullPath); } } _logger.LogDebug("{0} mutants created", _input.ProjectInfo.ProjectContents.Mutants.Count()); using (var ms = new MemoryStream()) { // compile the mutated syntax trees var compileResult = _compilingProcess.Compile(mutatedSyntaxTrees, ms, options.DevMode); string injectionPath = _input.ProjectInfo.GetInjectionPath(); if (!_fileSystem.Directory.Exists(Path.GetDirectoryName(injectionPath)) && !_fileSystem.File.Exists(injectionPath)) { _fileSystem.Directory.CreateDirectory(Path.GetDirectoryName(injectionPath)); } // inject the mutated Assembly into the test project using (var fs = _fileSystem.File.Create(injectionPath)) { ms.Position = 0; ms.CopyTo(fs); } _logger.LogDebug("Injected the mutated assembly file into {0}", injectionPath); // if a rollback took place, mark the rollbacked mutants as status:BuildError if (compileResult.RollbackResult?.RollbackedIds.Any() ?? false) { foreach (var mutant in _input.ProjectInfo.ProjectContents.Mutants .Where(x => compileResult.RollbackResult.RollbackedIds.Contains(x.Id))) { mutant.ResultStatus = MutantStatus.CompileError; } } int numberOfBuildErrors = compileResult.RollbackResult?.RollbackedIds.Count() ?? 0; if (numberOfBuildErrors > 0) { _logger.LogInformation("{0} mutants could not compile and got status {1}", numberOfBuildErrors, MutantStatus.CompileError.ToString()); } if (options.ExcludedMutations.Count() != 0) { var mutantsToSkip = _input.ProjectInfo.ProjectContents.Mutants .Where(x => options.ExcludedMutations.Contains(x.Mutation.Type)).ToList(); foreach (var mutant in mutantsToSkip) { mutant.ResultStatus = MutantStatus.Skipped; } _logger.LogInformation("{0} mutants got status {1}", mutantsToSkip.Count(), MutantStatus.Skipped.ToString()); } } _logger.LogInformation("{0} mutants ready for test", _input.ProjectInfo.ProjectContents.TotalMutants.Count()); _reporter.OnMutantsCreated(_input.ProjectInfo.ProjectContents); }