public void OnMutantTested(IReadOnlyMutant result) { switch (result.ResultStatus) { case MutantStatus.Killed: _chalk.Default("."); break; case MutantStatus.Survived: _chalk.Red("S"); break; case MutantStatus.Timeout: _chalk.Default("T"); break; } ; }
private static void WriteClassificationToConsole( IAnalyzableNode @class, NodesClassification classification, IChalk chalk) { foreach (var node in @class.DescendantNodesAndSelf()) { var result = classification.GetResult(node); if (result.IsArid) { chalk.Magenta($"ARID {node.Kind()}"); } else { chalk.Green($"NON-ARID {node.Kind()}"); } chalk.Default(node.GetText()); chalk.Default(Environment.NewLine + Environment.NewLine); } }
private async Task InitializeMutants(SourceClassDetail source) { _chalk.Default("\nInitialize Mutants..."); var mutantAnalyzer = new MutantInitializer(source) { ExecuteAllTests = source.TestClaz.MethodDetails.Count > _useClassFilterTestsThreshold || ExecuteAllTests, MutantFilterRegEx = RegEx, SpecificFilterRegEx = Specific, MutantsPerLine = MutantsPerLine }; if (UseExternalCodeCoverage) { mutantAnalyzer.ExecuteAllTests = true; mutantAnalyzer.MutantFilterRegEx = string.Empty; mutantAnalyzer.SpecificFilterRegEx = string.Empty; mutantAnalyzer.MutantsAtSpecificLines.AddRange(ExternalCoveredMutants); } await mutantAnalyzer.InitializeMutants(MutantOrchestrator.DefaultMutators); }
public void OnAllMutantsTested(IReadOnlyInputComponent inputComponent) { // setup display handlers inputComponent.DisplayFolder = (int depth, IReadOnlyInputComponent current) => { // show depth _chalk.Default($"{new string('-', depth)} {Path.DirectorySeparatorChar}{Path.GetFileName(current.Name)} "); DisplayComponent(current); }; inputComponent.DisplayFile = (int depth, IReadOnlyInputComponent current) => { // show depth _chalk.Default($"{new string('-', depth)} {current.Name} "); DisplayComponent(current); foreach (var mutant in current.TotalMutants) { if (mutant.ResultStatus == MutantStatus.Killed || mutant.ResultStatus == MutantStatus.Timeout) { _chalk.Green($"[{mutant.ResultStatus}] "); } else { _chalk.Red($"[{mutant.ResultStatus}] "); } _chalk.Default($"{mutant.Mutation.DisplayName} on line {mutant.Mutation.OriginalNode.GetLocation().GetLineSpan().StartLinePosition.Line + 1}: '{mutant.Mutation.OriginalNode}' ==> '{mutant.Mutation.ReplacementNode}'{Environment.NewLine}"); } }; // print empty line for readability _chalk.Default($"{Environment.NewLine}{Environment.NewLine}All mutants have been tested, and your mutation score has been calculated{Environment.NewLine}"); // start recursive invocation of handlers inputComponent.Display(1); }
private static int Main(string[] args) { try { _chalk = new Chalk(); Trace.Listeners.Add(new EventLogTraceListener("MuTest_CPP_CLI")); _muTest = new MuTestRunner(_chalk, new CppDirectoryFactory()); var app = new MuTestCli(_muTest); CancelKeyPress += CancelMutationHandler; AppDomain.CurrentDomain.ProcessExit += CancelMutationHandler; return(app.Run(args)); } catch (MuTestInputException ex) { ShowMessage(ex); CancelMutation(); return(1); } catch (CommandParsingException ex) { _chalk.Red(ex.Message); CancelMutation(); return(1); } catch (Exception ex) { CancelMutation(); var innerException = ex.InnerException; if (innerException != null && (innerException.GetType() == typeof(MuTestInputException) || innerException.GetType().BaseType == typeof(MuTestInputException))) { ShowMessage((MuTestInputException)innerException); var statusCode = MuTestExceptions[innerException.GetType()]; _chalk.Red($"\nStatus Code: {statusCode}\n"); return(statusCode); } if (ex.Message.StartsWith("Unrecognized option")) { _chalk.Default($"{ex.Message}{Environment.NewLine}"); return(1); } Trace.TraceError("{0}", ex); _chalk.Red($"\n{ex.Message} - review trace for more details\n"); return(1); } }
public void OnAllMutantsTested(IReadOnlyInputComponent reportComponent) { // setup display handlers reportComponent.DisplayFolder = (int depth, IReadOnlyInputComponent current) => { // show depth _chalk.Default($"{new string('-', depth)} {Path.DirectorySeparatorChar}{Path.GetFileName(current.Name)} "); DisplayComponent(current); }; reportComponent.DisplayFile = (int depth, IReadOnlyInputComponent current) => { // show depth _chalk.Default($"{new string('-', depth)} {current.Name} "); DisplayComponent(current); foreach (var mutant in current.TotalMutants) { if (mutant.ResultStatus == MutantStatus.Killed || mutant.ResultStatus == MutantStatus.Timeout) { _chalk.Green($"[{mutant.ResultStatus}] "); } else if (mutant.ResultStatus == MutantStatus.NoCoverage) { _chalk.Yellow($"[{mutant.ResultStatus}] "); } else { _chalk.Red($"[{mutant.ResultStatus}] "); } _chalk.Default(mutant.LongName + Environment.NewLine); } }; // print empty line for readability _chalk.Default($"{Environment.NewLine}{Environment.NewLine}All mutants have been tested, and your mutation score has been calculated{Environment.NewLine}"); // start recursive invocation of handlers reportComponent.Display(1); }
public void OnAllMutantsTested(IReadOnlyInputComponent reportComponent) { var files = new List <FileLeaf>(); FolderComposite rootFolder = null; reportComponent.DisplayFolder = (int _, IReadOnlyInputComponent current) => { rootFolder ??= (FolderComposite)current; }; reportComponent.DisplayFile = (int _, IReadOnlyInputComponent current) => { var fileLeaf = (FileLeaf)current; files.Add((FileLeaf)current); }; // print empty line for readability _chalk.Default($"{Environment.NewLine}{Environment.NewLine}All mutants have been tested, and your mutation score has been calculated{Environment.NewLine}"); // start recursive invocation of handlers reportComponent.Display(0); var filePathLength = Math.Max(9, files.Max(f => f.RelativePathToProjectFile?.Length ?? 0) + 1); _chalk.Default($"┌─{new string('─', filePathLength)}┬──────────┬──────────┬───────────┬────────────┬──────────┬─────────┐{Environment.NewLine}"); _chalk.Default($"│ File{new string(' ', filePathLength - 4)}│ % score │ # killed │ # timeout │ # survived │ # no cov │ # error │{Environment.NewLine}"); _chalk.Default($"├─{new string('─', filePathLength)}┼──────────┼──────────┼───────────┼────────────┼──────────┼─────────┤{Environment.NewLine}"); DisplayComponent(rootFolder, filePathLength); foreach (var file in files) { DisplayComponent(file, filePathLength); } _chalk.Default($"└─{new string('─', filePathLength)}┴──────────┴──────────┴───────────┴────────────┴──────────┴─────────┘{Environment.NewLine}"); }
public async Task RunMutationTest(MuTestOptions options) { if (!File.Exists(MuTestSettings.MSBuildPath)) { throw new MuTestInputException($"Unable to locate MSBuild Path at {MuTestSettings.MSBuildPath}. Please update MSBuildPath in MuTest.Console.exe.config if you are using different version"); } if (!File.Exists(MuTestSettings.VSTestConsolePath)) { throw new MuTestInputException($"Unable to locate VS Test Console Path at {MuTestSettings.VSTestConsolePath}. Please update VSTestConsolePath in MuTest.Console.exe.config if you are using different version"); } if (!File.Exists(MuTestSettings.RunSettingsPath)) { throw new MuTestInputException($"Unable to locate tests run settings path at {MuTestSettings.RunSettingsPath}. Please update RunSettingsPath in MuTest.Console.exe.config if you are using different location"); } _stopwatch = new Stopwatch(); _stopwatch.Start(); _options = options; if (!_options.SkipTestProjectBuild) { var originalProject = _options.TestProjectParameter; if (_options.OptimizeTestProject && _options.MultipleTargetClasses.Count == 1) { var targetClass = _options.MultipleTargetClasses.First(); _options.TestProjectParameter = _options .TestProjectParameter .UpdateTestProject(targetClass.TestClassPath.GetClass().ClassName()); } await ExecuteBuild(); if (!originalProject.Equals(_options.TestProjectParameter, StringComparison.InvariantCultureIgnoreCase)) { if (File.Exists(_options.TestProjectParameter)) { File.Delete(_options.TestProjectParameter); } _options.TestProjectParameter = originalProject; } } var serial = 1; _chalk.Default("\n*********************************** Matched Classes ***********************************"); foreach (var srcClass in _options.MultipleTargetClasses) { _chalk.Green($"\n{serial++}. {srcClass.ClassName} in {srcClass.ClassPath}"); } _chalk.Default("\n***************************************************************************************"); var projectSummary = new ProjectSummary { SourceProject = _options.SourceProjectParameter, TestProject = _options.TestProjectParameter }; var mutantAnalyzer = new MutantAnalyzer(_chalk, MuTestSettings) { ProcessWholeProject = _options.ProcessWholeProject, BuildInReleaseMode = _options.BuildInReleaseModeParameter, ConcurrentTestRunners = _options.ConcurrentTestRunners, EnableDiagnostics = _options.EnableDiagnostics, ExecuteAllTests = _options.ExecuteAllTests, IncludeNestedClasses = _options.IncludeNestedClasses, IncludePartialClasses = _options.IncludePartialClasses || _options.UseClassFilter || _options.ExecuteAllTests, KilledThreshold = _options.KilledThreshold, NoCoverage = _options.NoCoverage, RegEx = _options.RegEx, Specific = _options.Specific, SurvivedThreshold = _options.SurvivedThreshold, TestProject = _options.TestProjectParameter, TestProjectLibrary = _options.TestProjectLibraryParameter, UseClassFilter = _options.UseClassFilter, X64TargetPlatform = _options.X64TargetPlatform, TestExecutionTime = _options.TestExecutionThreshold, MutantsPerLine = _options.MutantsPerLine }; foreach (var targetClass in _options.MultipleTargetClasses) { mutantAnalyzer.TestClass = targetClass.TestClassPath; mutantAnalyzer.UseExternalCodeCoverage = false; mutantAnalyzer.MutantExecutor = null; var sourceClass = targetClass.ClassPath; var className = targetClass.ClassName; mutantAnalyzer.SourceProjectLibrary = _options.SourceProjectLibraryParameter; try { var sourceHash = sourceClass.GetCodeFileContent().ComputeHash(); var testHash = targetClass.TestClassPath.GetCodeFileContent().ComputeHash(); var hash = $"{sourceHash}-{testHash}".ComputeHash(); await GetFromDB(hash); if (_source != null) { var testClaz = targetClass.TestClassPath.GetClass(); var loader = new SemanticsClassDeclarationLoader(); _source.Claz = loader.Load(sourceClass, _options.SourceProjectParameter, className); _source.ClassLibrary = _options.SourceProjectLibraryParameter; _source.ClassProject = _options.SourceProjectParameter; _source.FilePath = sourceClass; _source.TestClaz = new TestClassDetail { Claz = new ClassDeclaration(testClaz), FilePath = targetClass.TestClassPath, ClassProject = _options.TestProjectParameter, FullName = testClaz.FullName(), ClassLibrary = _options.TestProjectLibraryParameter, X64TargetPlatform = _options.X64TargetPlatform }; } if (_source == null) { mutantAnalyzer.ExternalCoveredMutants.Clear(); _source = await mutantAnalyzer.Analyze(sourceClass, className, _options.SourceProjectParameter); _source.SHA256 = hash; _source.StoreToDb = true; if (_source.ExternalCoveredClassesIncluded.Any() && _options.AnalyzeExternalCoveredClasses) { _chalk.Yellow("\n\nAnalyzing External Coverage..."); mutantAnalyzer.UseExternalCodeCoverage = true; foreach (var acc in _source.ExternalCoveredClassesIncluded) { mutantAnalyzer.ExternalCoveredMutants.AddRange(acc.MutantsLines); var projectFile = new FileInfo(acc.ClassPath).FindProjectFile(); mutantAnalyzer.SourceProjectLibrary = projectFile.FindLibraryPath()?.FullName; if (!string.IsNullOrWhiteSpace(mutantAnalyzer.SourceProjectLibrary)) { var accClass = await mutantAnalyzer.Analyze( acc.ClassPath, acc.ClassName, projectFile.FullName); accClass.CalculateMutationScore(); if (accClass.MutationScore.Survived == 0) { acc.ZeroSurvivedMutants = true; } } } mutantAnalyzer.ExternalCoveredMutants.Clear(); } } } catch (Exception ex) when(!(ex is MuTestInputException)) { throw; } finally { MutantExecutor = mutantAnalyzer.MutantExecutor ?? new MutantExecutor(_source, MuTestSettings); _stopwatch.Stop(); if (_source != null) { await GenerateReports(); if (!string.IsNullOrWhiteSpace(_options.ProcessWholeProject)) { projectSummary.Classes.Add(new ClassSummary { TargetClass = new TargetClass { ClassPath = _source.FilePath, ClassName = _source.Claz.Syntax.FullName(), TestClassPath = _source.TestClaz.FilePath }, MutationScore = _source.MutationScore, Coverage = _source.Coverage ?? new Coverage() }); } } } } if (!string.IsNullOrWhiteSpace(_options.ProcessWholeProject)) { projectSummary.CalculateMutationScore(); var builder = new StringBuilder(HtmlTemplate); builder.AppendLine("<fieldset style=\"margin-bottom:10; margin-top:10\">"); builder.AppendLine("Mutation Report".PrintImportantWithLegend()); builder.Append(" ".PrintWithPreTag()); builder.Append($"{"Source Project:".PrintImportant()} {projectSummary.SourceProject}".PrintWithPreTag()); builder.Append($"{"Test Project :".PrintImportant()} {projectSummary.TestProject}".PrintWithPreTag()); builder.Append(" ".PrintWithPreTag()); builder.AppendLine("<fieldset style=\"margin-bottom:10; margin-top:10\">"); builder.AppendLine("Classes Mutation".PrintImportantWithLegend()); foreach (var claz in projectSummary.Classes) { builder.AppendLine("<fieldset style=\"margin-bottom:10; margin-top:10\">"); builder.AppendLine($"{claz.TargetClass.ClassName} [{claz.TargetClass.ClassPath}]".PrintImportantWithLegend(color: Colors.BlueViolet)); builder.Append($"{claz.MutationScore.Mutation} - {claz.MutationScore}".PrintWithPreTagWithMarginImportant()); builder.Append($"Code Coverage - {claz.Coverage}".PrintWithPreTagWithMarginImportant()); builder.AppendLine("</fieldset>"); } builder.AppendLine("</fieldset>"); builder.AppendLine("<fieldset style=\"margin-bottom:10; margin-top:10\">"); builder.AppendLine("ProjectWise Summary".PrintImportantWithLegend()); builder.Append(projectSummary.MutationScore.ToString().PrintWithPreTagWithMarginImportant(color: Colors.BlueViolet)); builder.Append($"Coverage: Mutation({projectSummary.MutationScore.Mutation}) {projectSummary.Coverage}".PrintWithPreTagWithMarginImportant(color: Colors.Blue)); builder.AppendLine("</fieldset>"); builder.AppendLine("</fieldset>"); CreateHtmlReport(builder, ProjectSummary); await CreateJsonReport(ProjectSummary, projectSummary); } }
public void OnAllMutantsTested(IReadOnlyInputComponent reportComponent) { var rootFolderProcessed = false; // setup display handlers reportComponent.DisplayFolder = (int _, IReadOnlyInputComponent current) => { // show depth var continuationLines = ParentContinuationLines(current); var stringBuilder = new StringBuilder(); foreach (var item in continuationLines.SkipLast(1)) { stringBuilder.Append(item ? ContinueLine : NoLine); } var folderLines = string.Empty; if (continuationLines.Count > 0) { folderLines = continuationLines.Last() ? BranchLine : FinalBranchLine; } var name = current.Name; if (name == null && !rootFolderProcessed) { name = "All files"; rootFolderProcessed = true; } if (!string.IsNullOrWhiteSpace(name)) { _chalk.Default($"{stringBuilder}{folderLines}{name}"); DisplayComponent(current); } }; reportComponent.DisplayFile = (int _, IReadOnlyInputComponent current) => { // show depth var continuationLines = ParentContinuationLines(current); var stringBuilder = new StringBuilder(); foreach (var item in continuationLines.SkipLast(1)) { stringBuilder.Append(item ? ContinueLine : NoLine); } _chalk.Default($"{stringBuilder}{(continuationLines.Last() ? BranchLine : FinalBranchLine)}{current.Name}"); DisplayComponent(current); stringBuilder.Append(continuationLines.Last() ? ContinueLine : NoLine); var prefix = stringBuilder.ToString(); foreach (var mutant in current.TotalMutants) { var isLastMutant = current.TotalMutants.Last() == mutant; _chalk.Default($"{prefix}{(isLastMutant ? FinalBranchLine : BranchLine)}"); switch (mutant.ResultStatus) { case MutantStatus.Killed: case MutantStatus.Timeout: _chalk.Green($"[{mutant.ResultStatus}]"); break; case MutantStatus.NoCoverage: _chalk.Yellow($"[{mutant.ResultStatus}]"); break; default: _chalk.Red($"[{mutant.ResultStatus}]"); break; } _chalk.Default($" {mutant.Mutation.DisplayName} on line {mutant.Line}{Environment.NewLine}"); _chalk.Default($"{prefix}{(isLastMutant ? NoLine : ContinueLine)}{BranchLine}[-] {mutant.Mutation.OriginalNode}{Environment.NewLine}"); _chalk.Default($"{prefix}{(isLastMutant ? NoLine : ContinueLine)}{FinalBranchLine}[+] {mutant.Mutation.ReplacementNode}{Environment.NewLine}"); } }; // print empty line for readability _chalk.Default($"{Environment.NewLine}{Environment.NewLine}All mutants have been tested, and your mutation score has been calculated{Environment.NewLine}"); // start recursive invocation of handlers reportComponent.Display(1); }
private static int Main(string[] args) { try { _chalk = new Chalk(); Trace.Listeners.Add(new EventLogTraceListener("MuTest_CPP_CLI")); var services = new ServiceCollection(); services .AddHttpClient <IFirebaseApiClient, FirebaseApiClient>() .AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetCircuitBreakerPatternPolicy()); services.AddSingleton(_chalk); var provider = services.BuildServiceProvider(); var factory = provider.GetService <IHttpClientFactory>(); _muTest = new MuTestRunner( _chalk, new CppDirectoryFactory(), new FirebaseApiClient( factory.CreateClient(), MuTestSettings.FireBaseDatabaseApiUrl, MuTestSettings.FireBaseStorageApiUrl)); var app = new MuTestCli(_muTest); CancelKeyPress += CancelMutationHandler; AppDomain.CurrentDomain.ProcessExit += CancelMutationHandler; return(app.Run(args)); } catch (MuTestInputException ex) { ShowMessage(ex); CancelMutation(); return(1); } catch (CommandParsingException ex) { _chalk.Red(ex.Message); CancelMutation(); return(1); } catch (Exception ex) { CancelMutation(); var innerException = ex.InnerException; if (innerException != null && (innerException.GetType() == typeof(MuTestInputException) || innerException.GetType().BaseType == typeof(MuTestInputException))) { ShowMessage((MuTestInputException)innerException); var statusCode = MuTestExceptions[innerException.GetType()]; _chalk.Red($"\nStatus Code: {statusCode}\n"); return(statusCode); } if (ex.Message.StartsWith("Unrecognized option")) { _chalk.Default($"{ex.Message}{Environment.NewLine}"); return(1); } Trace.TraceError("{0}", ex); _chalk.Red($"\n{ex.Message} - review trace for more details\n"); return(1); } }
public async Task RunMutationTest(MuTestOptions options) { try { if (!File.Exists(MuTestSettings.MSBuildPath)) { throw new MuTestInputException($"Unable to locate MSBuild Path at {MuTestSettings.MSBuildPath}. Please update MSBuildPath in MuTest.Console.exe.config if you are using different version"); } _stopwatch = new Stopwatch(); _stopwatch.Start(); _options = options; _chalk.Default("\nPreparing Required Files...\n"); DirectoryFactory.NumberOfMutantsExecutingInParallel = _options.ConcurrentTestRunners; _cppClass = new CppClass { Configuration = _options.Configuration, SourceClass = _options.SourceClass, Platform = _options.Platform, TestClass = _options.TestClass, TestProject = _options.TestProject, Target = _options.Target, SourceHeader = _options.SourceHeader, TestSolution = _options.TestSolution, IncludeBuildEvents = _options.IncludeBuildEvents }; Context = !_options.InIsolation ? DirectoryFactory.PrepareTestFiles(_cppClass) : DirectoryFactory.PrepareSolutionFiles(_cppClass); if (Context.TestContexts.Any()) { await ExecuteBuild(); await ExecuteTests(); if (!_options.DisableBuildOptimization) { Context.EnableBuildOptimization = true; } _chalk.Default("\nRunning Mutation Analysis...\n"); var defaultMutants = CppMutantOrchestrator.GetDefaultMutants(_options.SourceClass, _options.SpecificLines).ToList(); defaultMutants = _aridNodeMutantFilterer.FilterMutants(defaultMutants).ToList(); defaultMutants = _mutantsSelector.SelectMutants(_options.MutantsPerLine, defaultMutants).ToList(); _cppClass.Mutants.AddRange(defaultMutants); if (_cppClass.CoveredLineNumbers.Any()) { foreach (var mutant in _cppClass.Mutants) { if (_cppClass.CoveredLineNumbers.All(x => x != mutant.Mutation.LineNumber)) { mutant.ResultStatus = MutantStatus.NotCovered; } else if (mutant.Mutation.EndLineNumber > mutant.Mutation.LineNumber) { if (!_cppClass.CoveredLineNumbers.Any(x => x > mutant.Mutation.LineNumber && x <= mutant.Mutation.EndLineNumber)) { mutant.ResultStatus = MutantStatus.Skipped; } } } } _chalk.Default($"\nNumber of Mutants: {_cppClass.Mutants.Count}\n"); var sourceHash = _cppClass .SourceClass .GetCodeFileContent() .ComputeHash(); var testHash = _cppClass .TestClass .GetCodeFileContent() .ComputeHash(); _cppClass.Sha256 = (sourceHash + testHash).ComputeHash(); var data = await _client.GetFileDataFromStorage(_cppClass.Sha256); _cppClass.StoreInDb = true; if (data != null) { var cppClass = JsonConvert.DeserializeObject <CppClass>(data); cppClass.StoreInDb = false; cppClass.SourceClass = _cppClass.SourceClass; cppClass.SourceHeader = _cppClass.SourceHeader; cppClass.TestClass = _cppClass.TestClass; cppClass.TestProject = _cppClass.TestProject; cppClass.Configuration = _cppClass.Configuration; cppClass.Target = _cppClass.Target; cppClass.Platform = _cppClass.Platform; cppClass.TestSolution = _cppClass.TestSolution; cppClass.IncludeBuildEvents = _cppClass.IncludeBuildEvents; _cppClass = cppClass; } MutantsExecutor = new CppMutantExecutor(_cppClass, Context, MuTestSettings) { EnableDiagnostics = _options.EnableDiagnostics, KilledThreshold = _options.KilledThreshold, SurvivedThreshold = _options.SurvivedThreshold, NumberOfMutantsExecutingInParallel = _options.ConcurrentTestRunners }; _totalMutants = _cppClass.NotRunMutants.Count; _mutantProgress = 0; if (_cppClass.Mutants.Any() && data == null) { MutantsExecutor.MutantExecuted += MutantAnalyzerOnMutantExecuted; await MutantsExecutor.ExecuteMutants(); } await GenerateReports(); } } finally { if (Context != null) { DirectoryFactory.DeleteTestFiles(Context); } } }