Example #1
0
        private async Task <Mutant> CreateSurvivingMutantFromExpression(
            string originalExpression,
            string mutatedExpression)
        {
            var originalDocument = SourceToDocument(
                $@"namespace DummyNamespace
{{
    public static class DummyClass
    {{
        public static bool IsPositive(int a)
        {{
            return {originalExpression};
        }}
    }}
}}");
            var originalSyntaxRoot = await originalDocument.GetSyntaxRootAsync();

            var originalNode = originalSyntaxRoot.DescendantNodes().OfType <BinaryExpressionSyntax>().First();

            var mutatedNode = SyntaxFactory.ParseExpression(mutatedExpression);

            var mutatedRoot = originalSyntaxRoot.ReplaceNode(originalNode, mutatedNode);

            return(await Mutant.Create(originalDocument, originalNode, mutatedRoot));
        }
Example #2
0
        public async Task <(MutantStatus, Mutant)> Run(ITestRunner testRunner, string tempDirectory, IEventListener eventListener)
        {
            var mutatedNode = mutator.Mutate(OriginalNode);

            MutatedSyntaxRoot = originalSyntaxRoot.ReplaceNode(OriginalNode, mutatedNode);

            var mutant = await Mutant.Create(OriginalClass, OriginalNode, MutatedSyntaxRoot);

            var compilationResult = await CompileContainingProject(tempDirectory);

            if (!compilationResult.Success)
            {
                // Not all mutations are valid in all circumstances, and therefore may not compile.
                // E.g. "a + b" => "a - b" works when a and b are integers but not when they're strings.
                eventListener.MutantSkipped(mutant, "mutation resulted in invalid code");
                return(MutantStatus.Skipped, mutant);
            }

            CopyMutatedAssemblyIntoTempTestAssemblyDirectories(compilationResult.OutputFilePath, tempDirectory, config);
            var copiedTempTestAssemblyFilePaths = TempTestAssemblyFilePaths(config, tempDirectory).ToArray();

            var ranAnyTests = false;

            for (var testAssemblyIndex = 0; testAssemblyIndex < config.TestAssemblyFilePaths.Length; ++testAssemblyIndex)
            {
                var originalTestAssemblyFilePath = config.TestAssemblyFilePaths[testAssemblyIndex];
                var tempTestAssemblyFilePath     = copiedTempTestAssemblyFilePaths[testAssemblyIndex];

                string[] testsToRun = null;
                if (coverageAnalysisResult != null)
                {
                    testsToRun = coverageAnalysisResult.TestsThatCoverMember(memberName, originalTestAssemblyFilePath);
                    if (!testsToRun.Any())
                    {
                        continue;
                    }
                }

                var result = testsToRun != null?
                             testRunner.RunTests(new[] { tempTestAssemblyFilePath }, testsToRun) :
                                 testRunner.RunAllTests(new[] { tempTestAssemblyFilePath });

                ranAnyTests = true;

                if (result.Status == TestRunStatus.SomeTestsFailed)
                {
                    eventListener.MutantKilled(mutant, result.Error);
                    return(MutantStatus.Dead, mutant);
                }
            }

            if (!ranAnyTests)
            {
                eventListener.MutantSkipped(mutant, "no covering tests");
                return(MutantStatus.Skipped, mutant);
            }

            eventListener.MutantSurvived(mutant);
            return(MutantStatus.Alive, mutant);
        }