示例#1
0
        public void ShouldRemoveEndOfStringNode()
        {
            // Arrange
            var endOfStringNode = new EndOfStringNode();
            var childNodes      = new List <RegexNode>
            {
                new CharacterNode('a'),
                new CharacterNode('b'),
                new CharacterNode('c'),
                endOfStringNode
            };
            var rootNode = new ConcatenationNode(childNodes);
            var target   = new AnchorRemovalMutator();

            // Act
            var result = target.ApplyMutations(endOfStringNode, rootNode);

            // Assert
            var mutation = result.ShouldHaveSingleItem();

            mutation.OriginalNode.ShouldBe(endOfStringNode);
            mutation.ReplacementNode.ShouldBeNull();
            mutation.ReplacementPattern.ShouldBe("abc");
            mutation.DisplayName.ShouldBe("Regex anchor removal mutation");
            mutation.Description.ShouldBe("Anchor \"\\z\" was removed at offset 3.");
        }
示例#2
0
        public void MutationShouldNotContainOriginalNodesPrefixInDescription()
        {
            // Arrange
            var prefix          = new CommentGroupNode("This is a comment.");
            var startOfLineNode = new StartOfLineNode()
            {
                Prefix = prefix
            };
            var childNodes = new List <RegexNode>
            {
                startOfLineNode,
                new CharacterNode('a'),
                new CharacterNode('b'),
                new CharacterNode('c')
            };
            var rootNode = new ConcatenationNode(childNodes);
            var target   = new AnchorRemovalMutator();

            // Act
            var result = target.ApplyMutations(startOfLineNode, rootNode);

            // Assert
            var mutation = result.ShouldHaveSingleItem();

            mutation.OriginalNode.ShouldBe(startOfLineNode);
            mutation.ReplacementNode.ShouldBeNull();
            mutation.ReplacementPattern.ShouldBe("(?#This is a comment.)abc");
            mutation.DisplayName.ShouldBe("Regex anchor removal mutation");
            mutation.Description.ShouldBe("Anchor \"^\" was removed at offset 22.");
        }
示例#3
0
        public void ReplaceNodeShouldAddOldNodesPrefixAsFirstPrefixIfNewNodeAlreadyHasMultiplePrefixes()
        {
            // Arrange
            var oldNodePrefix = new CommentGroupNode("This is a prefix.");
            var oldNode       = new TestRegexNode()
            {
                Prefix = oldNodePrefix
            };
            var newNodeFirstPrefix  = new CommentGroupNode("This is the first prefix of the new node.");
            var newNodeSecondPrefix = new CommentGroupNode("This is the second prefix of the new node.")
            {
                Prefix = newNodeFirstPrefix
            };
            var newNode = new TestRegexNode()
            {
                Prefix = newNodeSecondPrefix
            };
            var target = new ConcatenationNode(oldNode);

            // Act
            RegexNode result = target.ReplaceNode(oldNode, newNode);

            // Assert
            var childNode = result.ChildNodes.ShouldHaveSingleItem();

            childNode.Prefix.Comment.ShouldBe(newNode.Prefix.Comment);
            childNode.Prefix.Prefix.ShouldNotBeNull();
            childNode.Prefix.Prefix.Comment.ShouldBe(newNode.Prefix.Prefix.Comment);
            childNode.Prefix.Prefix.Prefix.ShouldNotBeNull();
            childNode.Prefix.Prefix.Prefix.Comment.ShouldBe(oldNodePrefix.Comment);
        }
        public void SpanOnCommentGroupShouldStartAfter()
        {
            // Arrange
            var comment = new CommentGroupNode("This is a comment.");
            var a       = new CharacterNode('a');
            var b       = new CharacterNode('b')
            {
                Prefix = comment
            };
            var concat = new ConcatenationNode(new List <RegexNode> {
                a, b
            });

            // Act
            var(commentStart, commentLength) = comment.GetSpan();
            var(aStart, aLength)             = a.GetSpan();
            var(bStart, bLength)             = b.GetSpan();
            var(concatStart, concatLength)   = concat.GetSpan();

            // Assert
            concatStart.ShouldBe(0);
            concatLength.ShouldBe(a.ToString().Length + b.ToString().Length);
            aStart.ShouldBe(0);
            aLength.ShouldBe(1);
            commentStart.ShouldBe(1);
            commentLength.ShouldBe(comment.ToString().Length);
            bStart.ShouldBe(commentStart + commentLength);
            bLength.ShouldBe(1);
        }
        public void FlipsNegativeLookAheadToPositiveLookAhead()
        {
            // Arrange
            var foo = new List <RegexNode>
            {
                new CharacterNode('f'),
                new CharacterNode('o'),
                new CharacterNode('o')
            };
            var lookaroundGroupNode = new LookaroundGroupNode(true, false, foo);
            var rootNode            = new ConcatenationNode(lookaroundGroupNode);
            var target = new LookAroundMutator();

            // Act
            var result = target.ApplyMutations(lookaroundGroupNode, rootNode).ToList();

            // Assert
            var mutation = result.ShouldHaveSingleItem();

            mutation.OriginalNode.ShouldBe(lookaroundGroupNode);
            mutation.ReplacementNode.ToString().ShouldBe("(?=foo)");
            mutation.ReplacementPattern.ShouldBe("(?=foo)");
            mutation.DisplayName.ShouldBe("Regex greedy quantifier quantity mutation");
            mutation.Description.ShouldBe("Quantifier \"(?!foo)\" was replaced with \"(?=foo)\" at offset 0.");
        }
示例#6
0
        public void ShouldUnnegateNegatedCharacterClass()
        {
            // Arrange
            var characters = new List <RegexNode> {
                new CharacterNode('a'), new CharacterNode('b'), new CharacterNode('c')
            };
            var characterSet            = new CharacterClassCharacterSetNode(characters);
            var subtractionCharacterSet = new CharacterClassCharacterSetNode(new CharacterNode('a'));
            var subtraction             = new CharacterClassNode(subtractionCharacterSet, false);
            var characterClass          = new CharacterClassNode(characterSet, subtraction, true);
            var childNodes = new List <RegexNode> {
                new CharacterNode('x'), characterClass, new CharacterNode('y')
            };
            var root   = new ConcatenationNode(childNodes);
            var target = new CharacterClassNegationMutator();

            // Act
            var result = target.ApplyMutations(characterClass, root);

            // Assert
            var mutation = result.ShouldHaveSingleItem();

            mutation.OriginalNode.ShouldBe(characterClass);
            mutation.ReplacementNode.ToString().ShouldBe("[abc-[a]]");
            mutation.ReplacementPattern.ShouldBe("x[abc-[a]]y");
            mutation.DisplayName.ShouldBe("Regex character class negation mutation");
            mutation.Description.ShouldBe("Character class \"[^abc-[a]]\" was replaced with \"[abc-[a]]\" at offset 1.");
        }
示例#7
0
        public void ShouldApplyVariationsOnRegularInput()
        {
            // Arrange
            var characterNode  = new CharacterNode('a');
            var quantifierNode = new QuantifierNOrMoreNode(5, characterNode);
            var rootNode       = new ConcatenationNode(quantifierNode);
            var target         = new QuantifierUnlimitedQuantityMutator();

            var expectedResults = new List <string>
            {
                "a{4,}",
                "a{6,}",
            };

            // Act
            var mutations = target.ApplyMutations(quantifierNode, rootNode).ToList();

            // Assert
            var index = 0;
            var originalQuantifier = "a{5,}";

            foreach (var mutation in mutations)
            {
                mutation.OriginalNode.ShouldBe(quantifierNode);
                mutation.ReplacementNode.ToString().ShouldBe(expectedResults[index]);
                mutation.ReplacementPattern.ShouldBe(expectedResults[index]);
                mutation.DisplayName.ShouldBe("Regex greedy quantifier quantity mutation");
                mutation.Description.ShouldBe($"Quantifier \"{originalQuantifier}\" was replaced with \"{expectedResults[index]}\" at offset 1.");
                index++;
            }
            mutations.Count.ShouldBe(2);
        }
        public void ShouldSkipDecrementOnZeroEndValue()
        {
            // Arrange
            var characterNode  = new CharacterNode('a');
            var quantifierNode = new QuantifierNMNode(0, 0, characterNode);
            var rootNode       = new ConcatenationNode(quantifierNode);
            var target         = new QuantifierQuantityMutator();

            var expectedResults = new List <string>
            {
                "a{0,1}",
            };

            // Act
            var mutations = target.ApplyMutations(quantifierNode, rootNode).ToList();

            // Assert
            var index = 0;
            var originalQuantifier = "a{0,0}";

            foreach (var mutation in mutations)
            {
                mutation.OriginalNode.ShouldBe(quantifierNode);
                mutation.ReplacementNode.ToString().ShouldBe(expectedResults[index]);
                mutation.ReplacementPattern.ShouldBe(expectedResults[index]);
                mutation.DisplayName.ShouldBe("Regex greedy quantifier quantity mutation");
                mutation.Description.ShouldBe($"Quantifier \"{originalQuantifier}\" was replaced with \"{expectedResults[index]}\" at offset 1.");
                index++;
            }
            mutations.Count.ShouldBe(1);
        }
示例#9
0
        public void ShouldUnnegateNegatedShorthand()
        {
            // Arrange
            var shorthandNode = new CharacterClassShorthandNode('D');
            var childNodes    = new List <RegexNode>
            {
                shorthandNode,
                new CharacterNode('a'),
                new CharacterNode('b'),
                new CharacterNode('c')
            };
            var rootNode = new ConcatenationNode(childNodes);
            var target   = new CharacterClassShorthandNegationMutator();

            // Act
            var result = target.ApplyMutations(shorthandNode, rootNode);

            // Assert
            var mutation = result.ShouldHaveSingleItem();

            mutation.OriginalNode.ShouldBe(shorthandNode);
            mutation.ReplacementNode.ToString().ShouldBe("\\d");
            mutation.ReplacementPattern.ShouldBe("\\dabc");
            mutation.DisplayName.ShouldBe("Regex character class shorthand negation mutation");
            mutation.Description.ShouldBe("Character class shorthand \"\\D\" was replaced with \"\\d\" at offset 0.");
        }
示例#10
0
        public void RemoveNodeShouldAddOldNodesPrefixAsPrefixToNextNodesPrefixIfNextNodeAlreadyHasPrefix()
        {
            // Arrange
            var oldNodePrefix = new CommentGroupNode("This is a prefix.");
            var oldNode       = new TestRegexNode()
            {
                Prefix = oldNodePrefix
            };
            var nextNodePrefix = new CommentGroupNode("This is the prefix of the next node.");
            var nextNode       = new TestRegexNode()
            {
                Prefix = nextNodePrefix
            };
            var target = new ConcatenationNode(new List <RegexNode> {
                oldNode, nextNode
            });

            // Act
            RegexNode result = target.RemoveNode(oldNode);

            // Assert
            var remainingNode = result.ChildNodes.ShouldHaveSingleItem();

            remainingNode.Prefix.Comment.ShouldBe(nextNode.Prefix.Comment);
            remainingNode.Prefix.Prefix.ShouldNotBeNull();
            remainingNode.Prefix.Prefix.Comment.ShouldBe(oldNodePrefix.Comment);
        }
示例#11
0
        public void GetDescendantsShouldReturnAllDescendants()
        {
            // Arrange
            // a+bc*
            var charNodeA      = new CharacterNode('a');
            var charNodeB      = new CharacterNode('b');
            var charNodeC      = new CharacterNode('c');
            var quantifierPlus = new QuantifierPlusNode(charNodeA);
            var quantifierStar = new QuantifierStarNode(charNodeC);
            var grandchildren  = new List <RegexNode> {
                quantifierPlus, charNodeB, quantifierStar
            };
            var concatenationNode = new ConcatenationNode(grandchildren);
            var target            = new TestRegexNode(concatenationNode);

            // Act
            IEnumerable <RegexNode> result = target.GetDescendantNodes();

            // Assert
            result.Count().ShouldBe(6);
            result.First().ShouldBe(charNodeA);
            result.ElementAt(1).ShouldBe(quantifierPlus);
            result.ElementAt(2).ShouldBe(charNodeB);
            result.ElementAt(3).ShouldBe(charNodeC);
            result.ElementAt(4).ShouldBe(quantifierStar);
            result.Last().ShouldBe(concatenationNode);
        }
        public void ShouldRemoveQuantifierN()
        {
            // Arrange
            var quantifierNode = new QuantifierNNode(5, new CharacterNode('X'));
            var childNodes     = new List <RegexNode>
            {
                new CharacterNode('a'),
                new CharacterNode('b'),
                new CharacterNode('c'),
                quantifierNode
            };
            var rootNode = new ConcatenationNode(childNodes);
            var target   = new QuantifierRemovalMutator();

            // Act
            var result = target.ApplyMutations(quantifierNode, rootNode);

            // Assert
            var mutation = result.ShouldHaveSingleItem();

            mutation.OriginalNode.ShouldBe(quantifierNode);
            mutation.ReplacementNode.ToString().ShouldBe("X");
            mutation.ReplacementPattern.ShouldBe("abcX");
            mutation.DisplayName.ShouldBe("Regex quantifier removal mutation");
            mutation.Description.ShouldBe("Quantifier \"{5}\" was removed at offset 4.");
        }
        public void ToStringOnEmptyNodeShouldReturnEmptyString()
        {
            // Arrange
            var target = new ConcatenationNode();

            // Act
            var result = target.ToString();

            // Assert
            result.ShouldBe("");
        }
        public void SpanLengthOfEmptyConcatenationNodeShouldBeEqualToToStringLength()
        {
            // Arrange
            var target = new ConcatenationNode();

            // Act
            var(_, Length) = target.GetSpan();

            // Assert
            Length.ShouldBe(target.ToString().Length);
        }
        public void MutateShouldNotMutateNonQuantifierNode()
        {
            // Arrange
            var characterNode = new CharacterNode('a');
            var rootNode      = new ConcatenationNode(characterNode);
            var target        = new QuantifierRemovalMutator();

            // Act
            var result = target.Mutate(characterNode, rootNode);

            // Assert
            result.ShouldBeEmpty();
        }
示例#16
0
        public void MutateShouldNotMutateNonCharacterClassNode()
        {
            // Arrange
            var characterNode = new CharacterNode('a');
            var root          = new ConcatenationNode(characterNode);
            var target        = new CharacterClassNegationMutator();

            // Act
            var result = target.Mutate(characterNode, root);

            // Assert
            result.ShouldBeEmpty();
        }
        public void ToStringShouldReturnConcatenationOfChildNodesToString()
        {
            // Arrange
            var childNodes = new List <RegexNode> {
                new CharacterNode('a'), new CharacterNode('b'), new CharacterNode('c')
            };
            var target = new ConcatenationNode(childNodes);

            // Act
            var result = target.ToString();

            // Assert
            result.ShouldBe("abc");
        }
示例#18
0
        public void RemoveNodeShouldNotAddEmptyNodeWithIfOldNodeHasNoPrefix()
        {
            // Arrange
            var oldNode = new TestRegexNode();
            var target  = new ConcatenationNode(new List <RegexNode> {
                oldNode
            });

            // Act
            RegexNode result = target.RemoveNode(oldNode);

            // Assert
            result.ChildNodes.ShouldBeEmpty();
        }
        public void SpanLengthOConcatenationNodeWithChildNodesShouldBeEqualToToStringLength()
        {
            // Arrange
            var childNodes = new List <RegexNode> {
                new CharacterNode('a'), new CharacterNode('b'), new CharacterNode('c')
            };
            var target = new ConcatenationNode(childNodes);

            // Act
            var(_, Length) = target.GetSpan();

            // Assert
            Length.ShouldBe(target.ToString().Length);
        }
        public void SpanLengthOfConcatenationNodeShouldIncludeChildNodesPrefix()
        {
            // Arrange
            var childNode = new CharacterNode('a')
            {
                Prefix = new CommentGroupNode("Comment")
            };
            var target = new ConcatenationNode(childNode);

            // Act
            var(_, Length) = target.GetSpan();

            // Assert
            Length.ShouldBe(target.ToString().Length);
        }
        public void SpanLengthOfConcatenationNodeShouldNotIncludeItsOwnPrefix()
        {
            // Arrange
            var prefix = new CommentGroupNode("Comment");
            var target = new ConcatenationNode()
            {
                Prefix = prefix
            };

            // Act
            var(_, Length) = target.GetSpan();

            // Assert
            Length.ShouldBe(target.ToString().Length - prefix.ToString().Length);
        }
示例#22
0
        public void ToStringOnConditionalWithConcatenationAsAlternatesShouldReturnConditionalGroupWithConditionAndOnlyThenAlternate()
        {
            // Arrange
            var thenBranchChildNodes = new List <RegexNode> {
                new CharacterNode('t'), new CharacterNode('h'), new CharacterNode('e'), new CharacterNode('n')
            };
            var alternates = new ConcatenationNode(thenBranchChildNodes);
            var condition  = new CaptureGroupNode(new CharacterNode('c'));
            var target     = new ConditionalGroupNode(condition, alternates);

            // Act
            var result = target.ToString();

            // Assert
            result.ShouldBe("(?(c)then)", result);
        }
        public void ChildNodesGetSpanShouldReturnTupleWithStartEqualToPreviousChildsStartPlusLengthStartingAt0()
        {
            // Arrange
            var childNodes = new List <RegexNode> {
                new CharacterNode('a'), new CharacterNode('b'), new CharacterNode('c')
            };
            var target = new ConcatenationNode(childNodes);

            // Act
            var(Start, Length)   = target.ChildNodes.First().GetSpan();
            var(Start2, Length2) = target.ChildNodes.ElementAt(1).GetSpan();
            var(Start3, _)       = target.ChildNodes.ElementAt(2).GetSpan();

            // Assert
            Start.ShouldBe(0);
            Start2.ShouldBe(Start + Length);
            Start3.ShouldBe(Start2 + Length2);
        }
示例#24
0
        public void RemoveNodeShouldNotChangeOriginalNextNodeWhenMovingPrefix()
        {
            // Arrange
            var prefix  = new CommentGroupNode("This is a prefix.");
            var oldNode = new TestRegexNode()
            {
                Prefix = prefix
            };
            var nextNode = new TestRegexNode();
            var target   = new ConcatenationNode(new List <RegexNode> {
                oldNode, nextNode
            });

            // Act
            _ = target.RemoveNode(oldNode);

            // Assert
            nextNode.Prefix.ShouldBeNull();
        }
示例#25
0
        public void AddNodeShouldCopyDescendants()
        {
            // Arrange
            var grandChildConcatNode = new ConcatenationNode(new List <RegexNode> {
                new CharacterNode('d'), new CharacterNode('e')
            });
            var childConcatNode = new ConcatenationNode(new List <RegexNode> {
                grandChildConcatNode, new CharacterNode('a'), new CharacterNode('b')
            });
            var target  = new TestRegexNode(childConcatNode);
            var newNode = new CharacterNode('c');

            // Act
            RegexNode result = target.AddNode(newNode);

            // Assert
            result.ChildNodes.Count().ShouldBe(2);
            result.ChildNodes.First().ChildNodes.Count().ShouldBe(3);
            result.ChildNodes.First().ChildNodes.First().ChildNodes.Count().ShouldBe(2);
        }
示例#26
0
        public void ReplaceNodeShouldMoveOldNodesPrefixToNewNode()
        {
            // Arrange
            var prefix  = new CommentGroupNode("This is a prefix.");
            var oldNode = new TestRegexNode()
            {
                Prefix = prefix
            };
            var newNode = new TestRegexNode();
            var target  = new ConcatenationNode(oldNode);

            // Act
            RegexNode result = target.ReplaceNode(oldNode, newNode);

            // Assert
            var childNode = result.ChildNodes.ShouldHaveSingleItem();

            childNode.Prefix.ShouldNotBeNull();
            childNode.Prefix.Comment.ShouldBe(prefix.Comment);
        }
示例#27
0
        public void RemoveNodeShouldAddEmptyNodeWithOldNodesPrefixIfThereAreNoNextNodes()
        {
            // Arrange
            var prefix  = new CommentGroupNode("This is a prefix.");
            var oldNode = new TestRegexNode()
            {
                Prefix = prefix
            };
            var target = new ConcatenationNode(new List <RegexNode> {
                oldNode
            });

            // Act
            RegexNode result = target.RemoveNode(oldNode);

            // Assert
            var emptyNode = result.ChildNodes.ShouldHaveSingleItem().ShouldBeOfType <EmptyNode>();

            emptyNode.Prefix.ShouldNotBeNull();
            emptyNode.Prefix.Comment.ShouldBe(prefix.Comment);
        }
示例#28
0
        public void RemoveNodeShouldMoveOldNodesPrefixToNextNodeInTheCopy()
        {
            // Arrange
            var prefix  = new CommentGroupNode("This is a prefix.");
            var oldNode = new TestRegexNode()
            {
                Prefix = prefix
            };
            var nextNode = new TestRegexNode();
            var target   = new ConcatenationNode(new List <RegexNode> {
                oldNode, nextNode
            });

            // Act
            RegexNode result = target.RemoveNode(oldNode);

            // Assert
            var remainingNode = result.ChildNodes.ShouldHaveSingleItem();

            remainingNode.Prefix.ShouldNotBeNull();
            remainingNode.Prefix.Comment.ShouldBe(prefix.Comment);
        }