private void SetBuildLog(CppBuildExecutor buildExecutor, string log) { _buildDiagnostics = string.Empty; if (buildExecutor.LastBuildStatus == Constants.BuildExecutionStatus.Failed && EnableDiagnostics) { _buildDiagnostics = log; } }
public async Task ExecuteMutants() { var mutationProcessLog = new StringBuilder(); if (!_cpp.Mutants.Any()) { PrintMutationReport(mutationProcessLog, _cpp.Mutants); return; } var mutants = _cpp.NotRunMutants; var testTasks = new List <Task>(); int totalMutants = mutants.Count; for (var index = 0; index < mutants.Count; index += NumberOfMutantsExecutingInParallel) { if (CancelMutationOperation) { break; } var directoryIndex = -1; var buildExecutor = new CppBuildExecutor( _settings, _context.TestSolution.FullName, _cpp.Target) { EnableLogging = false, Configuration = _cpp.Configuration, Platform = _cpp.Platform, IntDir = _context.IntDir, OutDir = _context.OutDir, OutputPath = _context.OutputPath, IntermediateOutputPath = _context.IntermediateOutputPath }; if (!_context.UseMultipleSolutions) { for (var mutationIndex = index; mutationIndex < Math.Min(index + NumberOfMutantsExecutingInParallel, mutants.Count); mutationIndex++) { directoryIndex++; var mutant = mutants[mutationIndex]; var testContext = _context.TestContexts[directoryIndex]; var destinationFile = testContext.SourceClass.FullName; _cpp.SourceClass.ReplaceLine( mutant.Mutation.LineNumber, mutant.Mutation.ReplacementNode, destinationFile); destinationFile.AddNameSpace(testContext.Index); } if (_context.EnableBuildOptimization) { if (!_cpp.IncludeBuildEvents) { _context.TestProject.FullName.RemoveBuildEvents(); } _context.TestProject.FullName.OptimizeTestProject(); } var buildLog = new StringBuilder(); void BuildOutputDataReceived(object sender, string args) => buildLog.Append(args.PrintWithPreTag()); buildExecutor.OutputDataReceived += BuildOutputDataReceived; await buildExecutor.ExecuteBuild(); SetBuildLog(buildExecutor, buildLog.ToString()); buildExecutor.OutputDataReceived -= BuildOutputDataReceived; } directoryIndex = -1; for (var mutationIndex = index; mutationIndex < Math.Min(index + NumberOfMutantsExecutingInParallel, mutants.Count); mutationIndex++) { if (CancelMutationOperation) { break; } if (decimal.Divide(mutants.Count(x => x.ResultStatus == MutantStatus.Survived), totalMutants) > (decimal)SurvivedThreshold || decimal.Divide(mutants.Count(x => x.ResultStatus == MutantStatus.Killed), totalMutants) > (decimal)KilledThreshold) { break; } var mutant = mutants[mutationIndex]; directoryIndex++; try { if (_context.UseMultipleSolutions) { var testContext = _context.TestContexts[directoryIndex]; var destinationFile = testContext.SourceClass.FullName; if (_context.TestContexts.Any(x => x.BackupSourceClass != null)) { _context.TestContexts[0] .BackupSourceClass .FullName .ReplaceLine( mutant.Mutation.LineNumber, mutant.Mutation.ReplacementNode, destinationFile); } else { _cpp.SourceClass.ReplaceLine( mutant.Mutation.LineNumber, mutant.Mutation.ReplacementNode, destinationFile); } } else if (buildExecutor.LastBuildStatus == Constants.BuildExecutionStatus.Failed) { mutant.ResultStatus = MutantStatus.BuildError; OnMutantExecuted(new CppMutantEventArgs { Mutant = mutant, TestLog = _testDiagnostics, BuildLog = _buildDiagnostics }); continue; } var current = directoryIndex; testTasks.Add(Task.Run(() => BuildAndExecuteTests(mutant, current))); } catch (Exception e) { mutant.ResultStatus = MutantStatus.Skipped; Trace.TraceError("Unable to Execute Mutant {0} Exception: {1}", mutant.Mutation.OriginalNode.Encode(), e); } } await Task.WhenAll(testTasks); _context.EnableBuildOptimization = false; } PrintMutationReport(mutationProcessLog, _cpp.Mutants); }
private async Task BuildAndExecuteTests(CppMutant mutant, int index) { try { if (_context.UseMultipleSolutions) { var buildExecutor = new CppBuildExecutor( _settings, string.Format(_context.TestSolution.FullName, index), _cpp.Target) { EnableLogging = false, Configuration = _cpp.Configuration, Platform = _cpp.Platform, IntDir = string.Format(_context.IntDir, index), OutDir = string.Format(_context.OutDir, index), OutputPath = string.Format(_context.OutputPath, index), IntermediateOutputPath = string.Format(_context.IntermediateOutputPath, index) }; if (_context.EnableBuildOptimization) { if (!_cpp.IncludeBuildEvents) { string.Format(_context.TestProject.FullName, index).RemoveBuildEvents(); } string.Format(_context.TestProject.FullName, index).OptimizeTestProject(); } var buildLog = new StringBuilder(); void BuildOutputDataReceived(object sender, string args) { lock (AppendLock) { buildLog.Append(args.PrintWithPreTag()); } } buildExecutor.OutputDataReceived += BuildOutputDataReceived; await buildExecutor.ExecuteBuild(); if (buildExecutor.LastBuildStatus == Constants.BuildExecutionStatus.Failed) { buildLog.Clear(); buildExecutor.Rebuild = true; await buildExecutor.ExecuteBuild(); buildExecutor.Rebuild = false; } lock (BuildAndExecuteTestLock) { SetBuildLog(buildExecutor, buildLog.ToString()); buildExecutor.OutputDataReceived -= BuildOutputDataReceived; } if (buildExecutor.LastBuildStatus == Constants.BuildExecutionStatus.Failed) { mutant.ResultStatus = MutantStatus.BuildError; OnMutantExecuted(new CppMutantEventArgs { Mutant = mutant, TestLog = _testDiagnostics, BuildLog = _buildDiagnostics }); return; } } var testExecutor = new GoogleTestExecutor { KillProcessOnTestFail = true, EnableTestTimeout = true, TestTimeout = _settings.TestTimeout }; var log = new StringBuilder(); void OutputDataReceived(object sender, string args) => log.Append(args.PrintWithPreTag()); if (EnableDiagnostics) { log.AppendLine("<fieldset style=\"margin-bottom:10\">"); var lineNumber = mutant.Mutation.LineNumber; log.Append( $"Line: {lineNumber.ToString().PrintImportant(color: Constants.Colors.Blue)} - {mutant.Mutation.DisplayName.Encode()}" .PrintWithDateTime() .PrintWithPreTag()); testExecutor.OutputDataReceived += OutputDataReceived; } var projectDirectory = Path.GetDirectoryName(_cpp.TestProject); var projectName = Path.GetFileNameWithoutExtension(_cpp.TestProject); var projectNameFromTestContext = string.Format(Path.GetFileNameWithoutExtension(_context.TestProject.Name), index); var app = $"{projectDirectory}/{string.Format(_context.OutDir, index)}{projectName}.exe"; if (!File.Exists(app)) { app = $"{projectDirectory}/{string.Format(_context.OutDir, index)}{projectNameFromTestContext}.exe"; } await testExecutor.ExecuteTests( app, _cpp.UseClassFilter ?$"{Path.GetFileNameWithoutExtension(_context.TestContexts[index].TestClass.Name)}*" : string.Empty); testExecutor.OutputDataReceived -= OutputDataReceived; if (EnableDiagnostics && testExecutor.LastTestExecutionStatus == Constants.TestExecutionStatus.Timeout) { log.AppendLine("</fieldset>"); _testDiagnostics = log.ToString(); } mutant.ResultStatus = testExecutor.LastTestExecutionStatus == Constants.TestExecutionStatus.Success ? MutantStatus.Survived : testExecutor.LastTestExecutionStatus == Constants.TestExecutionStatus.Timeout ? MutantStatus.Timeout : MutantStatus.Killed; OnMutantExecuted(new CppMutantEventArgs { Mutant = mutant, BuildLog = _buildDiagnostics, TestLog = _testDiagnostics }); } catch (Exception e) { mutant.ResultStatus = MutantStatus.BuildError; OnMutantExecuted(new CppMutantEventArgs { Mutant = mutant, BuildLog = e.ToString(), }); } }