public void MutantPlacer_ShouldPlaceWithConditionalExpression(int id)
        {
            // 1 + 8;
            var originalNode = SyntaxFactory.BinaryExpression(SyntaxKind.AddExpression,
                                                              SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1)),
                                                              SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(8)));

            // 1 - 8;
            var mutatedNode = SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression,
                                                             SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1)),
                                                             SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(8)));

            var mutants = new List <(Mutant, ExpressionSyntax)> {
                (new Mutant {
                    Id = id, Mutation = new Mutation {
                        ReplacementNode = mutatedNode
                    }
                }, mutatedNode)
            };

            var result = MutantPlacer.PlaceExpressionControlledMutations(originalNode, mutants);

            result.ToFullString()
            .ShouldBeSemantically(@$ "({CodeInjection.HelperNamespace}.MutantControl.IsActive({id})?1-8:1+8)");

            var removedResult = MutantPlacer.RemoveMutant(result);

            removedResult.ToString().ShouldBeSemantically(originalNode.ToString());
        }
        public void MutantPlacer_ShouldPlaceWithIfStatement(int id)
        {
            // 1 + 8;
            var originalNode = SyntaxFactory.ExpressionStatement(SyntaxFactory.BinaryExpression(SyntaxKind.AddExpression,
                                                                                                SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1)),
                                                                                                SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(8))));

            // 1 - 8;
            var mutatedNode = SyntaxFactory.ExpressionStatement(SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression,
                                                                                               SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1)),
                                                                                               SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(8))));

            var result = MutantPlacer.PlaceWithIfStatement(originalNode, mutatedNode, id);

            result.ToFullString().ShouldBeSemantically(@"if (System.Environment.GetEnvironmentVariable(""ActiveMutation"") == """ + id.ToString() + @""")
            {
                1 - 8;
            } else {
                1 + 8;
            }");

            var removedResult = MutantPlacer.RemoveByIfStatement(result);

            removedResult.ToString().ShouldBeSemantically(originalNode.ToString());
        }
        protected override SyntaxNode InjectMutations(AccessorDeclarationSyntax sourceNode, SyntaxNode targetNode, MutationContext context)
        {
            var result = base.InjectMutations(sourceNode, targetNode, context) as AccessorDeclarationSyntax;

            if (result?.Body == null && result?.ExpressionBody == null)
            {
                return(result);
            }

            if (!context.HasStatementLevelMutant)
            {
                return(result);
            }

            // we need to inject static marker
            if (result.Body == null)
            {
                result = MutantPlacer.ConvertExpressionToBody(result);
            }

            var converter = sourceNode.NeedsReturn()
                ? (Func <Mutation, StatementSyntax>)((toConvert) =>
                                                     SyntaxFactory.ReturnStatement(sourceNode.ExpressionBody !.Expression.InjectMutation(toConvert)))
                : (toConvert) =>
                            SyntaxFactory.ExpressionStatement(sourceNode.ExpressionBody !.Expression.InjectMutation(toConvert));

            var newBody =
                MutantPlacer.PlaceStatementControlledMutations(result.Body,
                                                               context.StatementLevelControlledMutations.Union(context.BlockLevelControlledMutations).
                                                               Select(m => (m.Id, converter(m.Mutation))));

            context.BlockLevelControlledMutations.Clear();
            context.StatementLevelControlledMutations.Clear();
            return(result.WithBody(SyntaxFactory.Block(newBody)));
        }
Example #4
0
        internal override SyntaxNode OrchestrateMutation(ConstructorDeclarationSyntax node, MutationContext context)
        {
            if (!context.MustInjectCoverageLogic)
            {
                return(context.EnterStatic().MutateNodeAndChildren(node));
            }
            var trackedConstructor = node.TrackNodes((SyntaxNode)node.Body ?? node.ExpressionBody);

            if (node.ExpressionBody != null)
            {
                var bodyBlock =
                    SyntaxFactory.Block(SyntaxFactory.ExpressionStatement(node.ExpressionBody.Expression));
                var markedBlock = MutantPlacer.PlaceStaticContextMarker((BlockSyntax)context.MutateNodeAndChildren(bodyBlock));
                trackedConstructor = trackedConstructor.Update(
                    trackedConstructor.AttributeLists,
                    trackedConstructor.Modifiers,
                    trackedConstructor.Identifier,
                    trackedConstructor.ParameterList,
                    trackedConstructor.Initializer,
                    markedBlock,
                    null,
                    SyntaxFactory.Token(SyntaxKind.None));
            }
            else if (node.Body != null)
            {
                var markedBlock = MutantPlacer.PlaceStaticContextMarker((BlockSyntax)context.MutateNodeAndChildren(node.Body));
                trackedConstructor =
                    trackedConstructor.ReplaceNode(trackedConstructor.GetCurrentNode(node.Body), markedBlock);
            }
            return(trackedConstructor);
        }
        protected override BasePropertyDeclarationSyntax InjectMutations(PropertyDeclarationSyntax sourceNode,
                                                                         BasePropertyDeclarationSyntax targetNode, MutationContext context)
        {
            var result = base.InjectMutations(sourceNode, targetNode, context);

            if (!context.HasStatementLevelMutant)
            {
                return(result);
            }
            var mutated = result as PropertyDeclarationSyntax;

            if (mutated?.ExpressionBody == null)
            {
                return(result);
            }
            mutated = MutantPlacer.ConvertPropertyExpressionToBodyAccessor(mutated);
            var getter = mutated.GetAccessor();

            result = mutated.ReplaceNode(getter.Body !, SyntaxFactory.Block(
                                             MutantPlacer.PlaceStatementControlledMutations(
                                                 getter.Body,
                                                 context.StatementLevelControlledMutations.Union(context.BlockLevelControlledMutations).Select(
                                                     m => (m.Id,
                                                           SyntaxFactory.ReturnStatement(
                                                               sourceNode.ExpressionBody !.Expression
                                                               .InjectMutation(m.Mutation)) as StatementSyntax)))))
                     .WithSemicolonToken(SyntaxFactory.MissingToken(SyntaxKind.SemicolonToken));
            return(result);
        }
        /// <inheritdoc/>
        /// Inject mutations and convert expression body to block body if required.
        protected override BaseMethodDeclarationSyntax InjectMutations(T sourceNode, BaseMethodDeclarationSyntax targetNode,
                                                                       MutationContext context)
        {
            targetNode = base.InjectMutations(sourceNode, targetNode, context);
            if (targetNode.Body != null)
            {
                // add a return in case we changed the control flow
                return(MutantPlacer.AddEndingReturn(targetNode) as T);
            }

            if (!context.HasStatementLevelMutant)
            {
                return(targetNode);
            }

            // we need to move to a body version of the method
            targetNode = MutantPlacer.ConvertExpressionToBody(targetNode);

            StatementSyntax mutatedBlock = targetNode.Body;

            var converter = targetNode.NeedsReturn()
                ? (Func <Mutation, StatementSyntax>)((toConvert) =>
                                                     SyntaxFactory.ReturnStatement(sourceNode.ExpressionBody !.Expression.InjectMutation(toConvert)))
                : (toConvert) =>
                            SyntaxFactory.ExpressionStatement(sourceNode.ExpressionBody !.Expression.InjectMutation(toConvert));

            mutatedBlock =
                MutantPlacer.PlaceStatementControlledMutations(mutatedBlock,
                                                               context.StatementLevelControlledMutations.Union(context.BlockLevelControlledMutations).
                                                               Select(m => (m.Id, converter(m.Mutation))));
            context.BlockLevelControlledMutations.Clear();
            context.StatementLevelControlledMutations.Clear();
            return(targetNode.ReplaceNode(targetNode.Body !,
                                          SyntaxFactory.Block(mutatedBlock)));
        }
        internal override SyntaxNode OrchestrateMutation(PropertyDeclarationSyntax node, MutationContext context)
        {
            if (!context.MustInjectCoverageLogic)
            {
                return(context.MutateNodeAndChildren(node));
            }

            var trackedNode = node.TrackNodes(node.AccessorList.Accessors.Select(x => (SyntaxNode)x.Body ?? x.ExpressionBody).Where(x => x != null));

            foreach (var accessor in node.AccessorList.Accessors)
            {
                if (accessor.ExpressionBody != null)
                {
                    var markedBlock = context.MutateNodeAndChildren(accessor.ExpressionBody);
                    trackedNode = trackedNode.ReplaceNode(trackedNode.GetCurrentNode(accessor.ExpressionBody), markedBlock);
                }
                else if (accessor.Body != null)
                {
                    var markedBlock = MutantPlacer.PlaceStaticContextMarker((BlockSyntax)context.MutateNodeAndChildren(accessor.Body));
                    trackedNode = trackedNode.ReplaceNode(trackedNode.GetCurrentNode(accessor.Body), markedBlock);
                }
            }

            return(trackedNode);
        }
Example #8
0
        protected override LocalFunctionStatementSyntax InjectMutations(LocalFunctionStatementSyntax sourceNode, LocalFunctionStatementSyntax targetNode,
                                                                        MutationContext context)
        {
            // find out parameters
            targetNode = base.InjectMutations(sourceNode, targetNode, context);

            var fullTargetBody          = targetNode.Body;
            var sourceNodeParameterList = sourceNode.ParameterList;

            if (fullTargetBody != null)
            {
                // the function is in the body form
                // inject initialization to default for all out parameters
                targetNode = sourceNode.WithBody(MutantPlacer.AddDefaultInitializers(fullTargetBody,
                                                                                     sourceNodeParameterList.Parameters.Where(p =>
                                                                                                                              p.Modifiers.Any(m => m.Kind() == SyntaxKind.OutKeyword))));
                // add a return in case we changed the control flow
                return(MutantPlacer.AddEndingReturn(targetNode));
            }
            // nothing to do if there is now pending statement mutations
            if (!context.HasStatementLevelMutant)
            {
                return(targetNode);
            }

            // we need to move to a body version of the function to inject pending mutations
            targetNode = MutantPlacer.ConvertExpressionToBody(targetNode);
            return(targetNode.WithBody(SyntaxFactory.Block(context.InjectBlockLevelExpressionMutation(targetNode.Body, sourceNode.ExpressionBody.Expression, sourceNode.NeedsReturn()))));
        }
        public void ShouldRollBackFailedConstructor()
        {
            var source = @"class Test {
static TestClass()=> Value-='a';}";

            var orchestrator = new CsharpMutantOrchestrator(options: new StrykerOptions
            {
                OptimizationMode = OptimizationModes.CoverageBasedTest,
                MutationLevel    = MutationLevel.Complete
            });
            var actualNode = orchestrator.Mutate(CSharpSyntaxTree.ParseText(source).GetRoot());

            var node = actualNode.DescendantNodes().First(t => t is BlockSyntax);

            // Remove marker
            var restored = MutantPlacer.RemoveMutant(node);

            actualNode = actualNode.ReplaceNode(node, restored);

            // remove mutation
            node       = actualNode.DescendantNodes().First(t => t.IsKind(SyntaxKind.IfStatement));
            restored   = MutantPlacer.RemoveMutant(node);
            actualNode = actualNode.ReplaceNode(node, restored);

            // remove expression to body conversion
            node       = actualNode.DescendantNodes().First(t => t is ConstructorDeclarationSyntax);
            restored   = MutantPlacer.RemoveMutant(node);
            actualNode = actualNode.ReplaceNode(node, restored);

            var expectedNode = CSharpSyntaxTree.ParseText(source.Replace("StrykerNamespace", CodeInjection.HelperNamespace)).GetRoot();

            expectedNode.ShouldNotContainErrors();
            actualNode.ShouldBeSemantically(expectedNode);
            actualNode.ShouldNotContainErrors();
        }
        private void CheckMutantPlacerProperlyPlaceAndRemoveHelpers <T, TU>(string sourceCode, string expectedCode,
                                                                            Func <T, T> placer, Predicate <T> condition = null) where T : SyntaxNode where TU : SyntaxNode
        {
            var actualNode = CSharpSyntaxTree.ParseText(sourceCode).GetRoot();

            var node = actualNode.DescendantNodes().First(t => t is T ct && (condition == null || condition(ct))) as T;

            // inject helper
            actualNode = actualNode.ReplaceNode(node, placer(node));
            actualNode.ToFullString().ShouldBeSemantically(expectedCode);

            TU newNode;

            if (typeof(TU) == typeof(T))
            {
                newNode = actualNode.DescendantNodes().First(t => t is TU && t.ContainsAnnotations) as TU;
            }
            else
            {
                newNode = actualNode.DescendantNodes().First(t => t is T).DescendantNodes().First(t => t is TU && t.ContainsAnnotations) as TU;
            }

            // Remove helper
            var restored = MutantPlacer.RemoveMutant(newNode);

            actualNode = actualNode.ReplaceNode(newNode, restored);
            actualNode.ToFullString().ShouldBeSemantically(sourceCode);
            // try to remove again
            Should.Throw <InvalidOperationException>(() => MutantPlacer.RemoveMutant(restored));
        }
        public void MutantPlacer_ShouldPlaceWithIfStatement(int id)
        {
            // 1 + 8;
            var originalNode = SyntaxFactory.ExpressionStatement(SyntaxFactory.BinaryExpression(SyntaxKind.AddExpression,
                                                                                                SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1)),
                                                                                                SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(8))));

            // 1 - 8;
            var mutatedNode = SyntaxFactory.ExpressionStatement(SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression,
                                                                                               SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1)),
                                                                                               SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(8))));

            var mutants = new List <(Mutant, StatementSyntax)> {
                (new Mutant {
                    Id = id, Mutation = new Mutation {
                        ReplacementNode = mutatedNode
                    }
                }, mutatedNode)
            };

            var result = MutantPlacer.PlaceStatementControlledMutations(originalNode, mutants);

            result.ToFullString().Replace(CodeInjection.HelperNamespace, "StrykerNamespace").ShouldBeSemantically("if (StrykerNamespace.MutantControl.IsActive(" + id + @"))
            {
                1 - 8;
            } else {
                1 + 8;
            }");

            var removedResult = MutantPlacer.RemoveMutant(result);

            removedResult.ToString().ShouldBeSemantically(originalNode.ToString());
        }
        protected override SyntaxNode InjectMutations(AccessorDeclarationSyntax sourceNode, SyntaxNode targetNode, MutationContext context)
        {
            var result = base.InjectMutations(sourceNode, targetNode, context) as AccessorDeclarationSyntax;

            if (result?.Body == null && result?.ExpressionBody == null)
            {
                return(result);
            }

            if (!context.HasStatementLevelMutant)
            {
                if (result.Body != null && sourceNode.NeedsReturn())
                {
                    result = MutantPlacer.AddEndingReturn(result, sourceNode.ReturnType());
                }
                return(result);
            }

            if (result.Body == null)
            {
                result = MutantPlacer.ConvertExpressionToBody(result);
            }

            var newBody = context.InjectBlockLevelExpressionMutation(result.Body, sourceNode.ExpressionBody !.Expression, sourceNode.NeedsReturn());

            result = result.WithBody(SyntaxFactory.Block(newBody));
            if (sourceNode.NeedsReturn())
            {
                result = MutantPlacer.AddEndingReturn(result, sourceNode.ReturnType());
            }
            return(result);
        }
        public void MutantPlacer_ShouldPlaceWithIfStatement(int id)
        {
            // 1 + 8;
            var originalNode = SyntaxFactory.ExpressionStatement(SyntaxFactory.BinaryExpression(SyntaxKind.AddExpression,
                                                                                                SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1)),
                                                                                                SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(8))));

            // 1 - 8;
            var mutatedNode = SyntaxFactory.ExpressionStatement(SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression,
                                                                                               SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1)),
                                                                                               SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(8))));

            var result = MutantPlacer.PlaceWithIfStatement(originalNode, mutatedNode, id);

            result.ToFullString().ShouldBeSemantically("if (" + CodeInjection.HelperNamespace + ".MutantControl.IsActive(" + id + @"))
            {
                1 - 8;
            } else {
                1 + 8;
            }");

            var removedResult = MutantPlacer.RemoveMutant(result);

            removedResult.ToString().ShouldBeSemantically(originalNode.ToString());
        }
        /// <inheritdoc/>
        /// <remarks>Inject pending mutations that are controlled with 'if' statements.</remarks>
        protected override StatementSyntax InjectMutations(T sourceNode, StatementSyntax targetNode, MutationContext context)
        {
            var mutated = MutantPlacer.PlaceStatementControlledMutations(targetNode,
                                                                         context.StatementLevelControlledMutations.Select(m => (m.Id, (sourceNode as StatementSyntax).InjectMutation(m.Mutation))));

            context.StatementLevelControlledMutations.Clear();
            return(mutated);
        }
        /// <inheritdoc/>
        /// <remarks>Inject all pending mutations controlled with conditional operator(s).</remarks>
        protected override ExpressionSyntax InjectMutations(T sourceNode, ExpressionSyntax targetNode, MutationContext context)
        {
            var result = MutantPlacer.PlaceExpressionControlledMutations(
                targetNode,
                context.ExpressionLevelMutations.Select(m => (m.Id, (ExpressionSyntax)sourceNode.InjectMutation(m.Mutation)))) as T;

            context.ExpressionLevelMutations.Clear();
            return(result);
        }
Example #16
0
        private SyntaxTree RemoveMutantIfStatements(SyntaxTree originalTree, ICollection <Diagnostic> diagnosticInfo, bool devMode)
        {
            var rollbackRoot = originalTree.GetRoot();
            // find all if statements to remove
            var brokenMutations = new Collection <SyntaxNode>();

            foreach (var diagnostic in diagnosticInfo)
            {
                var brokenMutation = rollbackRoot.FindNode(diagnostic.Location.SourceSpan);
                var(mutationIf, mutantId) = FindMutationIfAndId(brokenMutation);
                if (mutationIf == null)
                {
                    var errorLocation = diagnostic.Location.GetMappedLineSpan();
                    _logger.LogError($"Unable to rollback mutation for node {brokenMutation} with error: {diagnostic.GetMessage()} (at {errorLocation.Path}, line: {errorLocation.StartLinePosition.Line}, col: {errorLocation.StartLinePosition.Character}).");
                    if (devMode)
                    {
                        _logger.LogCritical("Stryker.Net will stop (due to dev-mode option sets to true)");
                        throw new ApplicationException("Internal error due to failed rollback of a mutantt.");
                    }
                    _logger.LogError("This should not happen, please report this as an issue on github with the previous error message.");
                    _logger.LogWarning("Safe Mode! Rolling back all mutations in method.", brokenMutation, diagnostic.GetMessage());
                    // backup, remove all mutants in the node

                    var scan     = new Dictionary <SyntaxNode, int>();
                    var initNode = FindEnclosingMember(brokenMutation) ?? brokenMutation;
                    ScanAllMutationsIfsAndIds(initNode, scan);
                    foreach (var entry in scan)
                    {
                        if (!brokenMutations.Contains(entry.Key))
                        {
                            brokenMutations.Add(entry.Key);
                            _rollbackedIds.Add(entry.Value);
                        }
                    }
                }
                else
                {
                    if (!brokenMutations.Contains(mutationIf))
                    {
                        brokenMutations.Add(mutationIf);
                        _rollbackedIds.Add(mutantId);
                    }
                }
            }
            // mark the broken mutation nodes to track
            var trackedTree = rollbackRoot.TrackNodes(brokenMutations);

            foreach (var brokenMutation in brokenMutations)
            {
                // find the mutated node in the new tree
                var nodeToRemove = trackedTree.GetCurrentNode(brokenMutation);
                // remove the mutated node using its MutantPlacer remove method and update the tree
                trackedTree = trackedTree.ReplaceNode(nodeToRemove, MutantPlacer.RemoveMutant(nodeToRemove));
            }
            return(trackedTree.SyntaxTree);
        }
Example #17
0
        protected override BaseFieldDeclarationSyntax InjectMutations(FieldDeclarationSyntax sourceNode, BaseFieldDeclarationSyntax targetNode,
                                                                      MutationContext context)
        {
            var result = base.InjectMutations(sourceNode, targetNode, context);

            result = result.ReplaceNodes(result.Declaration.Variables.Where(v => v.Initializer != null).Select(v => v.Initializer.Value),
                                         (syntax, _) => MutantPlacer.PlaceStaticContextMarker(syntax));

            return(result);
        }
        public void ShouldInjectInitializersAndRestore()
        {
            var source   = "class Test {bool Method(out int x) {x=0;}}";
            var expected = "class Test {bool Method(out int x) {{x = default(int);}x=0;}}";

            CheckMutantPlacerProperlyPlaceAndRemoveHelpers <BlockSyntax>(source, expected,
                                                                         (n) => MutantPlacer.AddDefaultInitializers(n,
                                                                                                                    new[] { SyntaxFactory.Parameter(SyntaxFactory.Identifier("x")).WithType(SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword))
                                                                                                                                                                                            ) }));
        }
Example #19
0
        internal override SyntaxNode OrchestrateMutation(MethodDeclarationSyntax node, MutationContext context)
        {
            var mutatedNode = (MethodDeclarationSyntax)context.MutateNodeAndChildren(node);

            if (mutatedNode.Body == null)
            {
                return(mutatedNode);
            }
            // If method return type is void skip the node
            if (mutatedNode.ReturnType is PredefinedTypeSyntax predefinedType &&
                predefinedType.Keyword.IsKind(SyntaxKind.VoidKeyword))
            {
                return(mutatedNode);
            }

            if (node.Body.ContainsNodeThatVerifies(x => x.IsKind(SyntaxKind.YieldReturnStatement), false))
            {
                // not need to add yield return at the end of an enumeration method
                return(mutatedNode);
            }
            if (mutatedNode.Body.Statements.Last().Kind() == SyntaxKind.ReturnStatement)
            {
                return(mutatedNode);
            }

            var returnType = mutatedNode.ReturnType;

            // the GenericNameSyntax node can be encapsulated by QualifiedNameSyntax nodes
            var genericReturn = returnType.DescendantNodesAndSelf().OfType <GenericNameSyntax>().FirstOrDefault();

            if (mutatedNode.Modifiers.Any(x => x.IsKind(SyntaxKind.AsyncKeyword)))
            {
                if (genericReturn != null)
                {
                    // if the method is async and returns a generic task, make the return default return the underlying type
                    returnType = genericReturn.TypeArgumentList.Arguments.First();
                }
                else
                {
                    // if the method is async but returns a non-generic task, don't add the return default
                    return(mutatedNode);
                }
            }

            var newBody = mutatedNode.Body.AddStatements(
                MutantPlacer.AnnotateHelper(
                    SyntaxFactory.ReturnStatement(SyntaxFactory.DefaultExpression(returnType).WithLeadingTrivia(SyntaxFactory.Space))));

            mutatedNode = mutatedNode.ReplaceNode(mutatedNode.Body, newBody);

            return(mutatedNode);
        }
        private MutantInfo ExtractMutationInfo(SyntaxNode node)
        {
            var info = MutantPlacer.FindAnnotations(node);

            if (info.Engine == null)
            {
                return(new MutantInfo());
            }

            Logger.LogDebug("Found mutant {id} of type '{type}' controlled by '{engine}'.", info.Id, info.Type, info.Engine);

            return(info);
        }
Example #21
0
        public void MutantPlacer_ShouldPlaceWithIfStatement(int id)
        {
            // 1 + 8;
            var originalNode = SyntaxFactory.ExpressionStatement(SyntaxFactory.BinaryExpression(SyntaxKind.AddExpression,
                                                                                                SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1)),
                                                                                                SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(8))));

            // 1 - 8;
            var mutatedNode = SyntaxFactory.ExpressionStatement(SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression,
                                                                                               SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1)),
                                                                                               SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(8))));

            var result = MutantPlacer.PlaceStatementControlledMutations(originalNode, new[] { (id, (StatementSyntax)mutatedNode) });
Example #22
0
        private int?ExtractMutationIfAndId(SyntaxNode node)
        {
            var(engine, id) = MutantPlacer.FindEngine(node);

            if (engine == null)
            {
                return(null);
            }

            Logger.LogDebug(id == -1 ? $"Found a helper (engine:{engine})." : $"Found mutant {id} (controlled by {engine}).");

            return(id);
        }
        /// <inheritdoc/>
        /// <remarks>Inject all pending mutations and control them with if statements.</remarks>
        protected override StatementSyntax InjectMutations(T sourceNode, StatementSyntax targetNode, MutationContext context)
        {
            // we inject all pending mutations
            var mutationsToInject = context.StatementLevelControlledMutations
                                    .Union(context.BlockLevelControlledMutations);
            // mutations are controlled by 'if's
            var blockLevelMutations = MutantPlacer.PlaceStatementControlledMutations(targetNode,
                                                                                     mutationsToInject.Select(m =>
                                                                                                              (m.Id, (sourceNode as StatementSyntax).InjectMutation(m.Mutation))));

            context.BlockLevelControlledMutations.Clear();
            context.StatementLevelControlledMutations.Clear();
            // ensure we have a block at the end
            return(blockLevelMutations);
        }
Example #24
0
        /// <inheritdoc/>
        /// <remarks>Injects a static marker used for coverage information; this implies converting
        /// expression arrow bodied method to regular ones.</remarks>
        protected override BaseMethodDeclarationSyntax InjectMutations(ConstructorDeclarationSyntax sourceNode,
                                                                       BaseMethodDeclarationSyntax targetNode, MutationContext context)
        {
            var mutated = base.InjectMutations(sourceNode, targetNode, context);

            if (!context.MustInjectCoverageLogic)
            {
                return(mutated);
            }
            if (mutated.ExpressionBody != null)
            {
                // we need a body to place the marker
                mutated = MutantPlacer.ConvertExpressionToBody(mutated);
            }

            return(mutated.ReplaceNode(mutated.Body !, MutantPlacer.PlaceStaticContextMarker(mutated.Body)));
        }
Example #25
0
        protected override BasePropertyDeclarationSyntax OrchestrateChildrenMutation(PropertyDeclarationSyntax node, MutationContext context)
        {
            if (!node.IsStatic())
            {
                return(base.OrchestrateChildrenMutation(node, context));
            }

            var children = node.ReplaceNodes(node.ChildNodes(), (original, _) =>
                                             MutateSingleNode(original, original == node.Initializer ? context.EnterStatic() : context));

            if (children.Initializer != null)
            {
                children = children.ReplaceNode(children.Initializer.Value,
                                                MutantPlacer.PlaceStaticContextMarker(children.Initializer.Value));
            }
            return(children);
        }
Example #26
0
        protected override AnonymousFunctionExpressionSyntax InjectMutations(AnonymousFunctionExpressionSyntax sourceNode,
                                                                             AnonymousFunctionExpressionSyntax targetNode, MutationContext context)
        {
            targetNode = base.InjectMutations(sourceNode, targetNode, context);

            if (targetNode.Block == null)
            {
                if (targetNode.ExpressionBody == null)
                {
                    // only a definition (eg interface)
                    return(targetNode);
                }

                // this is an expression body method
                if (!context.HasStatementLevelMutant)
                {
                    // there is no statement or block level mutant, so the method control flow is not changed by mutations
                    // there is no need to change the method in any may
                    return(targetNode);
                }

                // we need to convert it to expression body form
                targetNode = MutantPlacer.ConvertExpressionToBody(targetNode);

                // we need to inject pending block (and statement) level mutations
                targetNode = targetNode.WithBody(
                    SyntaxFactory.Block(context.InjectBlockLevelExpressionMutation(targetNode.Block,
                                                                                   sourceNode.ExpressionBody, true)));
            }
            else
            {
                // we add an ending return, just in case
                targetNode = MutantPlacer.AddEndingReturn(targetNode);
            }

            if (targetNode is SimpleLambdaExpressionSyntax lambdaExpression && lambdaExpression.Parameter.Modifiers.Any(m => m.Kind() == SyntaxKind.OutKeyword))
            {
                targetNode = targetNode.WithBody(MutantPlacer.AddDefaultInitializers(targetNode.Block, new List <ParameterSyntax> {
                    lambdaExpression.Parameter
                }));
            }
        public void MutantPlacer_ShouldPlaceWithConditionalExpression(int id)
        {
            // 1 + 8;
            var originalNode = SyntaxFactory.BinaryExpression(SyntaxKind.AddExpression,
                                                              SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1)),
                                                              SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(8)));

            // 1 - 8;
            var mutatedNode = SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression,
                                                             SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1)),
                                                             SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(8)));

            var result = MutantPlacer.PlaceWithConditionalExpression(originalNode, mutatedNode, id);

            result.ToFullString()
            .ShouldBeSemantically(@$ "({CodeInjection.HelperNamespace}.MutantControl.IsActive({id})?1-8:1+8)");

            var removedResult = MutantPlacer.RemoveMutant(result);

            removedResult.ToString().ShouldBeSemantically(originalNode.ToString());
        }
Example #28
0
        /// <inheritdoc/>
        /// Inject mutations and convert expression body to block body if required.
        protected override BaseMethodDeclarationSyntax InjectMutations(T sourceNode, BaseMethodDeclarationSyntax targetNode,
                                                                       MutationContext context)
        {
            targetNode = base.InjectMutations(sourceNode, targetNode, context);

            if (targetNode.Body == null)
            {
                if (targetNode.ExpressionBody == null)
                {
                    // only a definition (eg interface)
                    return(targetNode);
                }

                // this is an expression body method
                if (!context.HasStatementLevelMutant)
                {
                    // there is no statement or block level mutant, so the method control flow is not changed by mutations
                    // there is no need to change the method in any may
                    return(targetNode);
                }

                // we need to convert it to expression body form
                targetNode = MutantPlacer.ConvertExpressionToBody(targetNode);

                // we need to inject pending block (and statement) level mutations
                targetNode = targetNode.WithBody(
                    SyntaxFactory.Block(context.InjectBlockLevelExpressionMutation(targetNode.Body,
                                                                                   sourceNode.ExpressionBody?.Expression, sourceNode.NeedsReturn())));
            }
            else
            {
                // we add an ending return, just in case
                targetNode = MutantPlacer.AddEndingReturn(targetNode);
            }

            // inject initialization to default for all out parameters
            targetNode = targetNode.WithBody(MutantPlacer.AddDefaultInitializers(targetNode.Body, sourceNode.ParameterList.Parameters.Where(p =>
                                                                                                                                            p.Modifiers.Any(m => m.Kind() == SyntaxKind.OutKeyword))));
            return(targetNode);
        }
Example #29
0
        private SyntaxTree RemoveMutantIfStatements(SyntaxTree originalTree, ICollection <Diagnostic> diagnosticInfo)
        {
            var rollbackRoot = originalTree.GetRoot();
            // find all if statements to remove
            var brokenMutations = new Collection <SyntaxNode>();

            foreach (var diagnostic in diagnosticInfo)
            {
                var brokenMutation = rollbackRoot.FindNode(diagnostic.Location.SourceSpan);
                var(mutationIf, mutantId) = FindMutationIfAndId(brokenMutation);
                if (mutationIf == null)
                {
                    _logger.LogError("Unable to rollback mutation for node {0} with diagnostic message {1}", brokenMutation, diagnostic.GetMessage());
                }

                if (!brokenMutations.Contains(mutationIf))
                {
                    brokenMutations.Add(mutationIf);
                    _rollbackedIds.Add(mutantId);
                }
            }
            // mark the broken mutation nodes to track
            var trackedTree = rollbackRoot.TrackNodes(brokenMutations);

            foreach (var brokenMutation in brokenMutations)
            {
                // find the mutated node in the new tree
                var nodeToRemove = trackedTree.GetCurrentNode(brokenMutation);
                // remove the mutated node using its MutantPlacer remove method and update the tree
                if (nodeToRemove is IfStatementSyntax)
                {
                    trackedTree = trackedTree.ReplaceNode(nodeToRemove, MutantPlacer.RemoveByIfStatement(nodeToRemove));
                }
                else if (nodeToRemove is ConditionalExpressionSyntax)
                {
                    trackedTree = trackedTree.ReplaceNode(nodeToRemove, MutantPlacer.RemoveByConditionalExpression(nodeToRemove));
                }
            }
            return(trackedTree.SyntaxTree);
        }
        /// <inheritdoc/>
        /// Inject mutations and convert expression body to block body if required.
        protected override BaseMethodDeclarationSyntax InjectMutations(T sourceNode, BaseMethodDeclarationSyntax targetNode,
                                                                       MutationContext context)
        {
            // find out parameters
            targetNode = base.InjectMutations(sourceNode, targetNode, context);
            if (targetNode.Body != null)
            {
                // inject initialization to default for all out parameters
                targetNode = sourceNode.ParameterList.Parameters.Where(p => p.Modifiers.Any(m => m.Kind() == SyntaxKind.OutKeyword))
                             .Aggregate(targetNode, (current, parameter) => MutantPlacer.AddDefaultInitialization(current, parameter.Identifier, parameter.Type));
                // add a return in case we changed the control flow
                return(MutantPlacer.AddEndingReturn(targetNode) as T);
            }

            if (!context.HasStatementLevelMutant)
            {
                return(targetNode);
            }

            // we need to move to a body version of the method
            targetNode = MutantPlacer.ConvertExpressionToBody(targetNode);

            StatementSyntax mutatedBlock = targetNode.Body;

            var converter = targetNode.NeedsReturn()
                ? (Func <Mutation, StatementSyntax>)((toConvert) =>
                                                     SyntaxFactory.ReturnStatement(sourceNode.ExpressionBody !.Expression.InjectMutation(toConvert)))
                : (toConvert) =>
                            SyntaxFactory.ExpressionStatement(sourceNode.ExpressionBody !.Expression.InjectMutation(toConvert));

            mutatedBlock =
                MutantPlacer.PlaceStatementControlledMutations(mutatedBlock,
                                                               context.StatementLevelControlledMutations.Union(context.BlockLevelControlledMutations).
                                                               Select(m => (m.Id, converter(m.Mutation))));
            context.BlockLevelControlledMutations.Clear();
            context.StatementLevelControlledMutations.Clear();
            return(targetNode.ReplaceNode(targetNode.Body !,
                                          SyntaxFactory.Block(mutatedBlock)));
        }