예제 #1
0
        public void diff_halfmatchTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();

            dmp.Diff_Timeout = 1;
            // No match.
            Assert.IsNull(dmp.HalfMatch("1234567890", "abcdef"));

            Assert.IsNull(dmp.HalfMatch("12345", "23"));

            // Single Match.
            CollectionAssert.AreEqual(new string[] { "12", "90", "a", "z", "345678" }, dmp.HalfMatch("1234567890", "a345678z"));

            CollectionAssert.AreEqual(new string[] { "a", "z", "12", "90", "345678" }, dmp.HalfMatch("a345678z", "1234567890"));

            CollectionAssert.AreEqual(new string[] { "abc", "z", "1234", "0", "56789" }, dmp.HalfMatch("abc56789z", "1234567890"));

            CollectionAssert.AreEqual(new string[] { "a", "xyz", "1", "7890", "23456" }, dmp.HalfMatch("a23456xyz", "1234567890"));

            // Multiple Matches.
            CollectionAssert.AreEqual(new string[] { "12123", "123121", "a", "z", "1234123451234" }, dmp.HalfMatch("121231234123451234123121", "a1234123451234z"));

            CollectionAssert.AreEqual(new string[] { "", "-=-=-=-=-=", "x", "", "x-=-=-=-=-=-=-=" }, dmp.HalfMatch("x-=-=-=-=-=-=-=-=-=-=-=-=", "xx-=-=-=-=-=-=-="));

            CollectionAssert.AreEqual(new string[] { "-=-=-=-=-=", "", "", "y", "-=-=-=-=-=-=-=y" }, dmp.HalfMatch("-=-=-=-=-=-=-=-=-=-=-=-=y", "-=-=-=-=-=-=-=yy"));

            // Non-optimal halfmatch.
            // Optimal diff would be -q+x=H-i+e=lloHe+Hu=llo-Hew+y not -qHillo+x=HelloHe-w+Hulloy
            CollectionAssert.AreEqual(new string[] { "qHillo", "w", "x", "Hulloy", "HelloHe" }, dmp.HalfMatch("qHilloHelloHew", "xHelloHeHulloy"));

            // Optimal no halfmatch.
            dmp.Diff_Timeout = 0;
            Assert.IsNull(dmp.HalfMatch("qHilloHelloHew", "xHelloHeHulloy"));
        }
예제 #2
0
        public void diff_levenshteinTest()
        {
            TestDiffOperations dmp   = new TestDiffOperations();
            List <Diff>        diffs = new List <Diff> {
                new Diff(Operation.DELETE, "abc"),
                new Diff(Operation.INSERT, "1234"),
                new Diff(Operation.EQUAL, "xyz")
            };

            Assert.AreEqual(4, dmp.ToLevenshteinDistance(diffs), "diff_levenshtein: Levenshtein with trailing equality.");

            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "xyz"),
                new Diff(Operation.DELETE, "abc"),
                new Diff(Operation.INSERT, "1234")
            };
            Assert.AreEqual(4, dmp.ToLevenshteinDistance(diffs), "diff_levenshtein: Levenshtein with leading equality.");

            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "abc"),
                new Diff(Operation.EQUAL, "xyz"),
                new Diff(Operation.INSERT, "1234")
            };
            Assert.AreEqual(7, dmp.ToLevenshteinDistance(diffs), "diff_levenshtein: Levenshtein with middle equality.");
        }
예제 #3
0
        public void diff_linesToCharsTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();
            // Convert lines down to characters.
            List <string> tmpVector = new List <string>();

            tmpVector.Add("");
            tmpVector.Add("alpha\n");
            tmpVector.Add("beta\n");
            Object[] result = dmp.LinesToChars("alpha\nbeta\nalpha\n", "beta\nalpha\nbeta\n");
            Assert.AreEqual("\u0001\u0002\u0001", result[0]);
            Assert.AreEqual("\u0002\u0001\u0002", result[1]);
            CollectionAssert.AreEqual(tmpVector, (List <string>)result[2]);

            tmpVector.Clear();
            tmpVector.Add("");
            tmpVector.Add("alpha\r\n");
            tmpVector.Add("beta\r\n");
            tmpVector.Add("\r\n");
            result = dmp.LinesToChars("", "alpha\r\nbeta\r\n\r\n\r\n");
            Assert.AreEqual("", result[0]);
            Assert.AreEqual("\u0001\u0002\u0003\u0003", result[1]);
            CollectionAssert.AreEqual(tmpVector, (List <string>)result[2]);

            tmpVector.Clear();
            tmpVector.Add("");
            tmpVector.Add("a");
            tmpVector.Add("b");
            result = dmp.LinesToChars("a", "b");
            Assert.AreEqual("\u0001", result[0]);
            Assert.AreEqual("\u0002", result[1]);
            CollectionAssert.AreEqual(tmpVector, (List <string>)result[2]);

            // More than 256 to reveal any 8-bit limitations.
            int n = 300;

            tmpVector.Clear();
            StringBuilder lineList = new StringBuilder();
            StringBuilder charList = new StringBuilder();

            for (int x = 1; x < n + 1; x++)
            {
                tmpVector.Add(x + "\n");
                lineList.Append(x + "\n");
                charList.Append(Convert.ToChar(x));
            }
            Assert.AreEqual(n, tmpVector.Count);
            string lines = lineList.ToString();
            string chars = charList.ToString();

            Assert.AreEqual(n, chars.Length);
            tmpVector.Insert(0, "");
            result = dmp.LinesToChars(lines, "");
            Assert.AreEqual(chars, result[0]);
            Assert.AreEqual("", result[1]);
            CollectionAssert.AreEqual(tmpVector, (List <string>)result[2]);
        }
예제 #4
0
        public void diff_prettyHtmlTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();
            // Pretty print.
            List <Diff> diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "a\n"),
                new Diff(Operation.DELETE, "<B>b</B>"),
                new Diff(Operation.INSERT, "c&d")
            };

            Assert.AreEqual("<span>a&para;<br></span><del style=\"background:#ffe6e6;\">&lt;B&gt;b&lt;/B&gt;</del><ins style=\"background:#e6ffe6;\">c&amp;d</ins>",
                            dmp.ToPrettyHtml(diffs));
        }
예제 #5
0
        public void diff_commonSuffixTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();

            // Detect any common suffix.
            // Null case.
            Assert.AreEqual(0, dmp.FindCommonSuffix("abc", "xyz"));

            // Non-null case.
            Assert.AreEqual(4, dmp.FindCommonSuffix("abcdef1234", "xyz1234"));

            // Whole case.
            Assert.AreEqual(4, dmp.FindCommonSuffix("1234", "xyz1234"));
        }
예제 #6
0
        public void diff_charsToLinesTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();
            // Convert chars up to lines.
            List <Diff> diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "\u0001\u0002\u0001"),
                new Diff(Operation.INSERT, "\u0002\u0001\u0002")
            };
            List <string> tmpVector = new List <string>();

            tmpVector.Add("");
            tmpVector.Add("alpha\n");
            tmpVector.Add("beta\n");
            dmp.CharsToLines(diffs, tmpVector);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "alpha\nbeta\nalpha\n"),
                new Diff(Operation.INSERT, "beta\nalpha\nbeta\n")
            }, diffs);

            // More than 256 to reveal any 8-bit limitations.
            int n = 300;

            tmpVector.Clear();
            StringBuilder lineList = new StringBuilder();
            StringBuilder charList = new StringBuilder();

            for (int x = 1; x < n + 1; x++)
            {
                tmpVector.Add(x + "\n");
                lineList.Append(x + "\n");
                charList.Append(Convert.ToChar(x));
            }
            Assert.AreEqual(n, tmpVector.Count);
            string lines = lineList.ToString();
            string chars = charList.ToString();

            Assert.AreEqual(n, chars.Length);
            tmpVector.Insert(0, "");
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, chars)
            };
            dmp.CharsToLines(diffs, tmpVector);
            CollectionAssert.AreEqual(new List <Diff>
            {
                new Diff(Operation.DELETE, lines)
            }, diffs);
        }
예제 #7
0
        public void diff_textTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();
            // Compute the source and destination texts.
            List <Diff> diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "jump"),
                new Diff(Operation.DELETE, "s"),
                new Diff(Operation.INSERT, "ed"),
                new Diff(Operation.EQUAL, " over "),
                new Diff(Operation.DELETE, "the"),
                new Diff(Operation.INSERT, "a"),
                new Diff(Operation.EQUAL, " lazy")
            };

            Assert.AreEqual("jumps over the lazy", dmp.GetText1(diffs));

            Assert.AreEqual("jumped over a lazy", dmp.GetText2(diffs));
        }
예제 #8
0
        public void diff_xIndexTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();
            // Translate a location in text1 to text2.
            List <Diff> diffs = new List <Diff> {
                new Diff(Operation.DELETE, "a"),
                new Diff(Operation.INSERT, "1234"),
                new Diff(Operation.EQUAL, "xyz")
            };

            Assert.AreEqual(5, dmp.FindIndex(diffs, 2), "diff_xIndex: Translation on equality.");

            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "a"),
                new Diff(Operation.DELETE, "1234"),
                new Diff(Operation.EQUAL, "xyz")
            };
            Assert.AreEqual(1, dmp.FindIndex(diffs, 3), "diff_xIndex: Translation on deletion.");
        }
예제 #9
0
        public void diff_bisectTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();
            // Normal.
            string a = "cat";
            string b = "map";
            // Since the resulting diff hasn't been normalized, it would be ok if
            // the insertion and deletion pairs are swapped.
            // If the order changes, tweak this test as required.
            List <Diff> diffs = new List <Diff> {
                new Diff(Operation.DELETE, "c"), new Diff(Operation.INSERT, "m"), new Diff(Operation.EQUAL, "a"), new Diff(Operation.DELETE, "t"), new Diff(Operation.INSERT, "p")
            };

            CollectionAssert.AreEqual(diffs, dmp.Bisect(a, b, DateTime.MaxValue));

            // Timeout.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "cat"), new Diff(Operation.INSERT, "map")
            };
            CollectionAssert.AreEqual(diffs, dmp.Bisect(a, b, DateTime.MinValue));
        }
예제 #10
0
        public void diff_commonOverlapTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();

            // Detect any suffix/prefix overlap.
            // Null case.
            Assert.AreEqual(0, dmp.CommonOverlap("", "abcd"));

            // Whole case.
            Assert.AreEqual(3, dmp.CommonOverlap("abc", "abcd"));

            // No overlap.
            Assert.AreEqual(0, dmp.CommonOverlap("123456", "abcd"));

            // Overlap.
            Assert.AreEqual(3, dmp.CommonOverlap("123456xxx", "xxxabcd"));

            // Unicode.
            // Some overly clever languages (C#) may treat ligatures as equal to their
            // component letters.  E.g. U+FB01 == 'fi'
            Assert.AreEqual(0, dmp.CommonOverlap("fi", "\ufb01i"));
        }
예제 #11
0
        public void diff_mainTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();
            // Perform a trivial diff.
            List <Diff> diffs = new List <Diff> {
            };

            CollectionAssert.AreEqual(diffs, dmp.GetDifference("", "", false), "diff_main: Null case.");

            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "abc")
            };
            CollectionAssert.AreEqual(diffs, dmp.GetDifference("abc", "abc", false), "diff_main: Equality.");

            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "ab"), new Diff(Operation.INSERT, "123"), new Diff(Operation.EQUAL, "c")
            };
            CollectionAssert.AreEqual(diffs, dmp.GetDifference("abc", "ab123c", false), "diff_main: Simple insertion.");

            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "a"), new Diff(Operation.DELETE, "123"), new Diff(Operation.EQUAL, "bc")
            };
            CollectionAssert.AreEqual(diffs, dmp.GetDifference("a123bc", "abc", false), "diff_main: Simple deletion.");

            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "a"), new Diff(Operation.INSERT, "123"), new Diff(Operation.EQUAL, "b"), new Diff(Operation.INSERT, "456"), new Diff(Operation.EQUAL, "c")
            };
            CollectionAssert.AreEqual(diffs, dmp.GetDifference("abc", "a123b456c", false), "diff_main: Two insertions.");

            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "a"), new Diff(Operation.DELETE, "123"), new Diff(Operation.EQUAL, "b"), new Diff(Operation.DELETE, "456"), new Diff(Operation.EQUAL, "c")
            };
            CollectionAssert.AreEqual(diffs, dmp.GetDifference("a123b456c", "abc", false), "diff_main: Two deletions.");

            // Perform a real diff.
            // Switch off the timeout.
            dmp.Diff_Timeout = 0;
            diffs            = new List <Diff> {
                new Diff(Operation.DELETE, "a"), new Diff(Operation.INSERT, "b")
            };
            CollectionAssert.AreEqual(diffs, dmp.GetDifference("a", "b", false), "diff_main: Simple case #1.");

            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "Apple"), new Diff(Operation.INSERT, "Banana"), new Diff(Operation.EQUAL, "s are a"), new Diff(Operation.INSERT, "lso"), new Diff(Operation.EQUAL, " fruit.")
            };
            CollectionAssert.AreEqual(diffs, dmp.GetDifference("Apples are a fruit.", "Bananas are also fruit.", false), "diff_main: Simple case #2.");

            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "a"), new Diff(Operation.INSERT, "\u0680"), new Diff(Operation.EQUAL, "x"), new Diff(Operation.DELETE, "\t"), new Diff(Operation.INSERT, new string (new char[] { (char)0 }))
            };
            CollectionAssert.AreEqual(diffs, dmp.GetDifference("ax\t", "\u0680x" + (char)0, false), "diff_main: Simple case #3.");

            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "1"), new Diff(Operation.EQUAL, "a"), new Diff(Operation.DELETE, "y"), new Diff(Operation.EQUAL, "b"), new Diff(Operation.DELETE, "2"), new Diff(Operation.INSERT, "xab")
            };
            CollectionAssert.AreEqual(diffs, dmp.GetDifference("1ayb2", "abxab", false), "diff_main: Overlap #1.");

            diffs = new List <Diff> {
                new Diff(Operation.INSERT, "xaxcx"), new Diff(Operation.EQUAL, "abc"), new Diff(Operation.DELETE, "y")
            };
            CollectionAssert.AreEqual(diffs, dmp.GetDifference("abcy", "xaxcxabc", false), "diff_main: Overlap #2.");

            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "ABCD"), new Diff(Operation.EQUAL, "a"), new Diff(Operation.DELETE, "="), new Diff(Operation.INSERT, "-"), new Diff(Operation.EQUAL, "bcd"), new Diff(Operation.DELETE, "="), new Diff(Operation.INSERT, "-"), new Diff(Operation.EQUAL, "efghijklmnopqrs"), new Diff(Operation.DELETE, "EFGHIJKLMNOefg")
            };
            CollectionAssert.AreEqual(diffs, dmp.GetDifference("ABCDa=bcd=efghijklmnopqrsEFGHIJKLMNOefg", "a-bcd-efghijklmnopqrs", false), "diff_main: Overlap #3.");

            diffs = new List <Diff> {
                new Diff(Operation.INSERT, " "), new Diff(Operation.EQUAL, "a"), new Diff(Operation.INSERT, "nd"), new Diff(Operation.EQUAL, " [[Pennsylvania]]"), new Diff(Operation.DELETE, " and [[New")
            };
            CollectionAssert.AreEqual(diffs, dmp.GetDifference("a [[Pennsylvania]] and [[New", " and [[Pennsylvania]]", false), "diff_main: Large equality.");

            dmp.Diff_Timeout = 0.1f;  // 100ms
            string a = "`Twas brillig, and the slithy toves\nDid gyre and gimble in the wabe:\nAll mimsy were the borogoves,\nAnd the mome raths outgrabe.\n";
            string b = "I am the very model of a modern major general,\nI've information vegetable, animal, and mineral,\nI know the kings of England, and I quote the fights historical,\nFrom Marathon to Waterloo, in order categorical.\n";

            // Increase the text lengths by 1024 times to ensure a timeout.
            for (int x = 0; x < 10; x++)
            {
                a = a + a;
                b = b + b;
            }
            DateTime startTime = DateTime.Now;

            dmp.GetDifference(a, b);
            DateTime endTime = DateTime.Now;

            // Test that we took at least the timeout period.
            Assert.IsTrue(new TimeSpan(((long)(dmp.Diff_Timeout * 1000)) * 10000) <= endTime - startTime);
            // Test that we didn't take forever (be forgiving).
            // Theoretically this test could fail very occasionally if the
            // OS task swaps or locks up for a second at the wrong moment.
            Assert.IsTrue(new TimeSpan(((long)(dmp.Diff_Timeout * 1000)) * 10000 * 2) > endTime - startTime);
            dmp.Diff_Timeout = 0;

            // Test the linemode speedup.
            // Must be long to pass the 100 char cutoff.
            a = "1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n";
            b = "abcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\n";
            CollectionAssert.AreEqual(dmp.GetDifference(a, b, true), dmp.GetDifference(a, b, false), "diff_main: Simple line-mode.");

            a = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
            b = "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij";
            CollectionAssert.AreEqual(dmp.GetDifference(a, b, true), dmp.GetDifference(a, b, false), "diff_main: Single line-mode.");

            a = "1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n";
            b = "abcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n";
            string[] texts_linemode = diff_rebuildtexts(dmp.GetDifference(a, b, true));
            string[] texts_textmode = diff_rebuildtexts(dmp.GetDifference(a, b, false));
            CollectionAssert.AreEqual(texts_textmode, texts_linemode, "diff_main: Overlap line-mode.");

            // Test null inputs -- not needed because nulls can't be passed in C#.
        }
예제 #12
0
        public void diff_deltaTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();
            // Convert a diff into delta string.
            List <Diff> diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "jump"),
                new Diff(Operation.DELETE, "s"),
                new Diff(Operation.INSERT, "ed"),
                new Diff(Operation.EQUAL, " over "),
                new Diff(Operation.DELETE, "the"),
                new Diff(Operation.INSERT, "a"),
                new Diff(Operation.EQUAL, " lazy"),
                new Diff(Operation.INSERT, "old dog")
            };
            string text1 = dmp.GetText1(diffs);

            Assert.AreEqual("jumps over the lazy", text1);

            string delta = dmp.ToDelta(diffs);

            Assert.AreEqual("=4\t-1\t+ed\t=6\t-3\t+a\t=5\t+old dog", delta);

            // Convert delta string into a diff.
            CollectionAssert.AreEqual(diffs, dmp.FromDelta(text1, delta));

            // Generates error (19 < 20).
            try {
                dmp.FromDelta(text1 + "x", delta);
                Assert.Fail("diff_fromDelta: Too long.");
            } catch (ArgumentException) {
                // Exception expected.
            }

            // Generates error (19 > 18).
            try {
                dmp.FromDelta(text1.Substring(1), delta);
                Assert.Fail("diff_fromDelta: Too short.");
            } catch (ArgumentException) {
                // Exception expected.
            }

            // Generates error (%c3%xy invalid Unicode).
            try {
                dmp.FromDelta("", "+%c3%xy");
                Assert.Fail("diff_fromDelta: Invalid character.");
            } catch (ArgumentException) {
                // Exception expected.
            }

            // Test deltas with special characters.
            char zero = (char)0;
            char one  = (char)1;
            char two  = (char)2;

            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "\u0680 " + zero + " \t %"),
                new Diff(Operation.DELETE, "\u0681 " + one + " \n ^"),
                new Diff(Operation.INSERT, "\u0682 " + two + " \\ |")
            };
            text1 = dmp.GetText1(diffs);
            Assert.AreEqual("\u0680 " + zero + " \t %\u0681 " + one + " \n ^", text1);

            delta = dmp.ToDelta(diffs);
            // Lowercase, due to UrlEncode uses lower.
            Assert.AreEqual("=7\t-7\t+%da%82 %02 %5c %7c", delta, "diff_toDelta: Unicode.");

            CollectionAssert.AreEqual(diffs, dmp.FromDelta(text1, delta), "diff_fromDelta: Unicode.");

            // Verify pool of unchanged characters.
            diffs = new List <Diff> {
                new Diff(Operation.INSERT, "A-Z a-z 0-9 - _ . ! ~ * ' ( ) ; / ? : @ & = + $ , # ")
            };
            string text2 = dmp.GetText2(diffs);

            Assert.AreEqual("A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ", text2, "diff_text2: Unchanged characters.");

            delta = dmp.ToDelta(diffs);
            Assert.AreEqual("+A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ", delta, "diff_toDelta: Unchanged characters.");

            // Convert delta string into a diff.
            CollectionAssert.AreEqual(diffs, dmp.FromDelta("", delta), "diff_fromDelta: Unchanged characters.");
        }
예제 #13
0
        public void diff_cleanupEfficiencyTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();

            // Cleanup operationally trivial equalities.
            dmp.Diff_EditCost = 4;
            // Null case.
            List <Diff> diffs = new List <Diff> ();

            dmp.CleanupEfficiency(diffs);
            CollectionAssert.AreEqual(new List <Diff>(), diffs);

            // No elimination.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "ab"),
                new Diff(Operation.INSERT, "12"),
                new Diff(Operation.EQUAL, "wxyz"),
                new Diff(Operation.DELETE, "cd"),
                new Diff(Operation.INSERT, "34")
            };
            dmp.CleanupEfficiency(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "ab"),
                new Diff(Operation.INSERT, "12"),
                new Diff(Operation.EQUAL, "wxyz"),
                new Diff(Operation.DELETE, "cd"),
                new Diff(Operation.INSERT, "34")
            }, diffs);

            // Four-edit elimination.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "ab"),
                new Diff(Operation.INSERT, "12"),
                new Diff(Operation.EQUAL, "xyz"),
                new Diff(Operation.DELETE, "cd"),
                new Diff(Operation.INSERT, "34")
            };
            dmp.CleanupEfficiency(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "abxyzcd"),
                new Diff(Operation.INSERT, "12xyz34")
            }, diffs);

            // Three-edit elimination.
            diffs = new List <Diff> {
                new Diff(Operation.INSERT, "12"),
                new Diff(Operation.EQUAL, "x"),
                new Diff(Operation.DELETE, "cd"),
                new Diff(Operation.INSERT, "34")
            };
            dmp.CleanupEfficiency(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "xcd"),
                new Diff(Operation.INSERT, "12x34")
            }, diffs);

            // Backpass elimination.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "ab"),
                new Diff(Operation.INSERT, "12"),
                new Diff(Operation.EQUAL, "xy"),
                new Diff(Operation.INSERT, "34"),
                new Diff(Operation.EQUAL, "z"),
                new Diff(Operation.DELETE, "cd"),
                new Diff(Operation.INSERT, "56")
            };
            dmp.CleanupEfficiency(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "abxyzcd"),
                new Diff(Operation.INSERT, "12xy34z56")
            }, diffs);

            // High cost elimination.
            dmp.Diff_EditCost = 5;
            diffs             = new List <Diff> {
                new Diff(Operation.DELETE, "ab"),
                new Diff(Operation.INSERT, "12"),
                new Diff(Operation.EQUAL, "wxyz"),
                new Diff(Operation.DELETE, "cd"),
                new Diff(Operation.INSERT, "34")
            };
            dmp.CleanupEfficiency(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "abwxyzcd"),
                new Diff(Operation.INSERT, "12wxyz34")
            }, diffs);
            dmp.Diff_EditCost = 4;
        }
예제 #14
0
        public void diff_cleanupSemanticTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();
            // Cleanup semantically trivial equalities.
            // Null case.
            List <Diff> diffs = new List <Diff>();

            dmp.CleanupSemantic(diffs);
            CollectionAssert.AreEqual(new List <Diff>(), diffs);

            // No elimination #1.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "ab"),
                new Diff(Operation.INSERT, "cd"),
                new Diff(Operation.EQUAL, "12"),
                new Diff(Operation.DELETE, "e")
            };
            dmp.CleanupSemantic(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "ab"),
                new Diff(Operation.INSERT, "cd"),
                new Diff(Operation.EQUAL, "12"),
                new Diff(Operation.DELETE, "e")
            }, diffs);

            // No elimination #2.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "abc"),
                new Diff(Operation.INSERT, "ABC"),
                new Diff(Operation.EQUAL, "1234"),
                new Diff(Operation.DELETE, "wxyz")
            };
            dmp.CleanupSemantic(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "abc"),
                new Diff(Operation.INSERT, "ABC"),
                new Diff(Operation.EQUAL, "1234"),
                new Diff(Operation.DELETE, "wxyz")
            }, diffs);

            // Simple elimination.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "a"),
                new Diff(Operation.EQUAL, "b"),
                new Diff(Operation.DELETE, "c")
            };
            dmp.CleanupSemantic(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "abc"),
                new Diff(Operation.INSERT, "b")
            }, diffs);

            // Backpass elimination.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "ab"),
                new Diff(Operation.EQUAL, "cd"),
                new Diff(Operation.DELETE, "e"),
                new Diff(Operation.EQUAL, "f"),
                new Diff(Operation.INSERT, "g")
            };
            dmp.CleanupSemantic(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "abcdef"),
                new Diff(Operation.INSERT, "cdfg")
            }, diffs);

            // Multiple eliminations.
            diffs = new List <Diff> {
                new Diff(Operation.INSERT, "1"),
                new Diff(Operation.EQUAL, "A"),
                new Diff(Operation.DELETE, "B"),
                new Diff(Operation.INSERT, "2"),
                new Diff(Operation.EQUAL, "_"),
                new Diff(Operation.INSERT, "1"),
                new Diff(Operation.EQUAL, "A"),
                new Diff(Operation.DELETE, "B"),
                new Diff(Operation.INSERT, "2")
            };
            dmp.CleanupSemantic(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "AB_AB"),
                new Diff(Operation.INSERT, "1A2_1A2")
            }, diffs);

            // Word boundaries.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "The c"),
                new Diff(Operation.DELETE, "ow and the c"),
                new Diff(Operation.EQUAL, "at.")
            };
            dmp.CleanupSemantic(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "The "),
                new Diff(Operation.DELETE, "cow and the "),
                new Diff(Operation.EQUAL, "cat.")
            }, diffs);

            // No overlap elimination.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "abcxx"),
                new Diff(Operation.INSERT, "xxdef")
            };
            dmp.CleanupSemantic(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "abcxx"),
                new Diff(Operation.INSERT, "xxdef")
            }, diffs);

            // Overlap elimination.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "abcxxx"),
                new Diff(Operation.INSERT, "xxxdef")
            };
            dmp.CleanupSemantic(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "abc"),
                new Diff(Operation.EQUAL, "xxx"),
                new Diff(Operation.INSERT, "def")
            }, diffs);

            // Reverse overlap elimination.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "xxxabc"),
                new Diff(Operation.INSERT, "defxxx")
            };
            dmp.CleanupSemantic(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.INSERT, "def"),
                new Diff(Operation.EQUAL, "xxx"),
                new Diff(Operation.DELETE, "abc")
            }, diffs);

            // Two overlap eliminations.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "abcd1212"),
                new Diff(Operation.INSERT, "1212efghi"),
                new Diff(Operation.EQUAL, "----"),
                new Diff(Operation.DELETE, "A3"),
                new Diff(Operation.INSERT, "3BC")
            };
            dmp.CleanupSemantic(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "abcd"),
                new Diff(Operation.EQUAL, "1212"),
                new Diff(Operation.INSERT, "efghi"),
                new Diff(Operation.EQUAL, "----"),
                new Diff(Operation.DELETE, "A"),
                new Diff(Operation.EQUAL, "3"),
                new Diff(Operation.INSERT, "BC")
            }, diffs);
        }
예제 #15
0
        public void diff_cleanupSemanticLosslessTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();
            // Slide diffs to match logical boundaries.
            // Null case.
            List <Diff> diffs = new List <Diff>();

            dmp.CleanupSemanticLossless(diffs);
            CollectionAssert.AreEqual(new List <Diff>(), diffs);

            // Blank lines.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "AAA\r\n\r\nBBB"),
                new Diff(Operation.INSERT, "\r\nDDD\r\n\r\nBBB"),
                new Diff(Operation.EQUAL, "\r\nEEE")
            };
            dmp.CleanupSemanticLossless(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "AAA\r\n\r\n"),
                new Diff(Operation.INSERT, "BBB\r\nDDD\r\n\r\n"),
                new Diff(Operation.EQUAL, "BBB\r\nEEE")
            }, diffs);

            // Line boundaries.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "AAA\r\nBBB"),
                new Diff(Operation.INSERT, " DDD\r\nBBB"),
                new Diff(Operation.EQUAL, " EEE")
            };
            dmp.CleanupSemanticLossless(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "AAA\r\n"),
                new Diff(Operation.INSERT, "BBB DDD\r\n"),
                new Diff(Operation.EQUAL, "BBB EEE")
            }, diffs);

            // Word boundaries.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "The c"),
                new Diff(Operation.INSERT, "ow and the c"),
                new Diff(Operation.EQUAL, "at.")
            };
            dmp.CleanupSemanticLossless(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "The "),
                new Diff(Operation.INSERT, "cow and the "),
                new Diff(Operation.EQUAL, "cat.")
            }, diffs);

            // Alphanumeric boundaries.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "The-c"),
                new Diff(Operation.INSERT, "ow-and-the-c"),
                new Diff(Operation.EQUAL, "at.")
            };
            dmp.CleanupSemanticLossless(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "The-"),
                new Diff(Operation.INSERT, "cow-and-the-"),
                new Diff(Operation.EQUAL, "cat.")
            }, diffs);

            // Hitting the start.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "a"),
                new Diff(Operation.DELETE, "a"),
                new Diff(Operation.EQUAL, "ax")
            };
            dmp.CleanupSemanticLossless(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "a"),
                new Diff(Operation.EQUAL, "aax")
            }, diffs);

            // Hitting the end.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "xa"),
                new Diff(Operation.DELETE, "a"),
                new Diff(Operation.EQUAL, "a")
            };
            dmp.CleanupSemanticLossless(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "xaa"),
                new Diff(Operation.DELETE, "a")
            }, diffs);

            // Sentence boundaries.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "The xxx. The "),
                new Diff(Operation.INSERT, "zzz. The "),
                new Diff(Operation.EQUAL, "yyy.")
            };
            dmp.CleanupSemanticLossless(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "The xxx."),
                new Diff(Operation.INSERT, " The zzz."),
                new Diff(Operation.EQUAL, " The yyy.")
            }, diffs);
        }
예제 #16
0
        public void diff_cleanupMergeTest()
        {
            TestDiffOperations dmp = new TestDiffOperations();
            // Cleanup a messy diff.
            // Null case.
            List <Diff> diffs = new List <Diff>();

            dmp.CleanupMerge(diffs);
            CollectionAssert.AreEqual(new List <Diff>(), diffs);

            // No change case.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "a"), new Diff(Operation.DELETE, "b"), new Diff(Operation.INSERT, "c")
            };
            dmp.CleanupMerge(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "a"), new Diff(Operation.DELETE, "b"), new Diff(Operation.INSERT, "c")
            }, diffs);

            // Merge equalities.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "a"), new Diff(Operation.EQUAL, "b"), new Diff(Operation.EQUAL, "c")
            };
            dmp.CleanupMerge(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "abc")
            }, diffs);

            // Merge deletions.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "a"), new Diff(Operation.DELETE, "b"), new Diff(Operation.DELETE, "c")
            };
            dmp.CleanupMerge(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "abc")
            }, diffs);

            // Merge insertions.
            diffs = new List <Diff> {
                new Diff(Operation.INSERT, "a"), new Diff(Operation.INSERT, "b"), new Diff(Operation.INSERT, "c")
            };
            dmp.CleanupMerge(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.INSERT, "abc")
            }, diffs);

            // Merge interweave.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "a"), new Diff(Operation.INSERT, "b"), new Diff(Operation.DELETE, "c"), new Diff(Operation.INSERT, "d"), new Diff(Operation.EQUAL, "e"), new Diff(Operation.EQUAL, "f")
            };
            dmp.CleanupMerge(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "ac"), new Diff(Operation.INSERT, "bd"), new Diff(Operation.EQUAL, "ef")
            }, diffs);

            // Prefix and suffix detection.
            diffs = new List <Diff> {
                new Diff(Operation.DELETE, "a"), new Diff(Operation.INSERT, "abc"), new Diff(Operation.DELETE, "dc")
            };
            dmp.CleanupMerge(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "a"), new Diff(Operation.DELETE, "d"), new Diff(Operation.INSERT, "b"), new Diff(Operation.EQUAL, "c")
            }, diffs);

            // Prefix and suffix detection with equalities.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "x"), new Diff(Operation.DELETE, "a"), new Diff(Operation.INSERT, "abc"), new Diff(Operation.DELETE, "dc"), new Diff(Operation.EQUAL, "y")
            };
            dmp.CleanupMerge(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "xa"), new Diff(Operation.DELETE, "d"), new Diff(Operation.INSERT, "b"), new Diff(Operation.EQUAL, "cy")
            }, diffs);

            // Slide edit left.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "a"), new Diff(Operation.INSERT, "ba"), new Diff(Operation.EQUAL, "c")
            };
            dmp.CleanupMerge(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.INSERT, "ab"), new Diff(Operation.EQUAL, "ac")
            }, diffs);

            // Slide edit right.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "c"), new Diff(Operation.INSERT, "ab"), new Diff(Operation.EQUAL, "a")
            };
            dmp.CleanupMerge(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "ca"), new Diff(Operation.INSERT, "ba")
            }, diffs);

            // Slide edit left recursive.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "a"), new Diff(Operation.DELETE, "b"), new Diff(Operation.EQUAL, "c"), new Diff(Operation.DELETE, "ac"), new Diff(Operation.EQUAL, "x")
            };
            dmp.CleanupMerge(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.DELETE, "abc"), new Diff(Operation.EQUAL, "acx")
            }, diffs);

            // Slide edit right recursive.
            diffs = new List <Diff> {
                new Diff(Operation.EQUAL, "x"), new Diff(Operation.DELETE, "ca"), new Diff(Operation.EQUAL, "c"), new Diff(Operation.DELETE, "b"), new Diff(Operation.EQUAL, "a")
            };
            dmp.CleanupMerge(diffs);
            CollectionAssert.AreEqual(new List <Diff> {
                new Diff(Operation.EQUAL, "xca"), new Diff(Operation.DELETE, "cba")
            }, diffs);
        }