How to use diff method in Puppeteer

Best JavaScript code snippet using puppeteer

Run Puppeteer automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

diff.js

Source: diff.js Github

copy
1var moment = require("../../moment");
2
3function equal(test, a, b, message) {
4    test.ok(Math.abs(a - b) < 0.00000001, "(" + a + " === " + b + ") " + message);
5}
6
7function dstForYear(year) {
8    var start = moment([year]),
9        end = moment([year + 1]),
10        current = start.clone(),
11        last;
12
13    while (current < end) {
14        last = current.clone();
15        current.add(24, 'hour');
16        if (last.zone() !== current.zone()) {
17            end = current.clone();
18            current = last.clone();
19            break;
20        }
21    }
22
23    while (current < end) {
24        last = current.clone();
25        current.add(1, 'hour');
26        if (last.zone() !== current.zone()) {
27            return {
28                moment : last,
29                diff : (current.zone() - last.zone()) / 60
30            };
31        }
32    }
33}
34
35exports.diff = {
36    "diff" : function (test) {
37        test.expect(5);
38
39        test.equal(moment(1000).diff(0), 1000, "1 second - 0 = 1000");
40        test.equal(moment(1000).diff(500), 500, "1 second - 0.5 seconds = 500");
41        test.equal(moment(0).diff(1000), -1000, "0 - 1 second = -1000");
42        test.equal(moment(new Date(1000)).diff(1000), 0, "1 second - 1 second = 0");
43        var oneHourDate = new Date(),
44            nowDate = new Date(+oneHourDate);
45        oneHourDate.setHours(oneHourDate.getHours() + 1);
46        test.equal(moment(oneHourDate).diff(nowDate), 60 * 60 * 1000, "1 hour from now = 3600000");
47        test.done();
48    },
49
50    "diff key after" : function (test) {
51        test.expect(10);
52
53        test.equal(moment([2010]).diff([2011], 'years'), -1, "year diff");
54        test.equal(moment([2010]).diff([2010, 2], 'months'), -2, "month diff");
55        test.equal(moment([2010]).diff([2010, 0, 7], 'weeks'), 0, "week diff");
56        test.equal(moment([2010]).diff([2010, 0, 8], 'weeks'), -1, "week diff");
57        test.equal(moment([2010]).diff([2010, 0, 21], 'weeks'), -2, "week diff");
58        test.equal(moment([2010]).diff([2010, 0, 22], 'weeks'), -3, "week diff");
59        test.equal(moment([2010]).diff([2010, 0, 4], 'days'), -3, "day diff");
60        test.equal(moment([2010]).diff([2010, 0, 1, 4], 'hours'), -4, "hour diff");
61        test.equal(moment([2010]).diff([2010, 0, 1, 0, 5], 'minutes'), -5, "minute diff");
62        test.equal(moment([2010]).diff([2010, 0, 1, 0, 0, 6], 'seconds'), -6, "second diff");
63        test.done();
64    },
65
66    "diff key before" : function (test) {
67        test.expect(10);
68
69        test.equal(moment([2011]).diff([2010], 'years'), 1, "year diff");
70        test.equal(moment([2010, 2]).diff([2010], 'months'), 2, "month diff");
71        test.equal(moment([2010, 0, 4]).diff([2010], 'days'), 3, "day diff");
72        test.equal(moment([2010, 0, 7]).diff([2010], 'weeks'), 0, "week diff");
73        test.equal(moment([2010, 0, 8]).diff([2010], 'weeks'), 1, "week diff");
74        test.equal(moment([2010, 0, 21]).diff([2010], 'weeks'), 2, "week diff");
75        test.equal(moment([2010, 0, 22]).diff([2010], 'weeks'), 3, "week diff");
76        test.equal(moment([2010, 0, 1, 4]).diff([2010], 'hours'), 4, "hour diff");
77        test.equal(moment([2010, 0, 1, 0, 5]).diff([2010], 'minutes'), 5, "minute diff");
78        test.equal(moment([2010, 0, 1, 0, 0, 6]).diff([2010], 'seconds'), 6, "second diff");
79        test.done();
80    },
81
82    "diff key before singular" : function (test) {
83        test.expect(10);
84
85        test.equal(moment([2011]).diff([2010], 'year'), 1, "year diff singular");
86        test.equal(moment([2010, 2]).diff([2010], 'month'), 2, "month diff singular");
87        test.equal(moment([2010, 0, 4]).diff([2010], 'day'), 3, "day diff singular");
88        test.equal(moment([2010, 0, 7]).diff([2010], 'week'), 0, "week diff singular");
89        test.equal(moment([2010, 0, 8]).diff([2010], 'week'), 1, "week diff singular");
90        test.equal(moment([2010, 0, 21]).diff([2010], 'week'), 2, "week diff singular");
91        test.equal(moment([2010, 0, 22]).diff([2010], 'week'), 3, "week diff singular");
92        test.equal(moment([2010, 0, 1, 4]).diff([2010], 'hour'), 4, "hour diff singular");
93        test.equal(moment([2010, 0, 1, 0, 5]).diff([2010], 'minute'), 5, "minute diff singular");
94        test.equal(moment([2010, 0, 1, 0, 0, 6]).diff([2010], 'second'), 6, "second diff singular");
95        test.done();
96    },
97
98    "diff key before abbreviated" : function (test) {
99        test.expect(10);
100
101        test.equal(moment([2011]).diff([2010], 'y'), 1, "year diff abbreviated");
102        test.equal(moment([2010, 2]).diff([2010], 'M'), 2, "month diff abbreviated");
103        test.equal(moment([2010, 0, 4]).diff([2010], 'd'), 3, "day diff abbreviated");
104        test.equal(moment([2010, 0, 7]).diff([2010], 'w'), 0, "week diff abbreviated");
105        test.equal(moment([2010, 0, 8]).diff([2010], 'w'), 1, "week diff abbreviated");
106        test.equal(moment([2010, 0, 21]).diff([2010], 'w'), 2, "week diff abbreviated");
107        test.equal(moment([2010, 0, 22]).diff([2010], 'w'), 3, "week diff abbreviated");
108        test.equal(moment([2010, 0, 1, 4]).diff([2010], 'h'), 4, "hour diff abbreviated");
109        test.equal(moment([2010, 0, 1, 0, 5]).diff([2010], 'm'), 5, "minute diff abbreviated");
110        test.equal(moment([2010, 0, 1, 0, 0, 6]).diff([2010], 's'), 6, "second diff abbreviated");
111        test.done();
112    },
113
114    "diff month" : function (test) {
115        test.expect(1);
116
117        test.equal(moment([2011, 0, 31]).diff([2011, 2, 1], 'months'), -1, "month diff");
118        test.done();
119    },
120
121    "diff across DST" : function (test) {
122        var dst = dstForYear(2012), a, b, daysInMonth;
123        if (!dst) {
124            console.log("No DST?");
125            test.done();
126            return;
127        }
128
129        test.expect(16);
130
131        a = dst.moment;
132        b = a.clone().utc().add(12, 'hours').local();
133        daysInMonth = (a.daysInMonth() + b.daysInMonth()) / 2;
134        equal(test, b.diff(a, 'ms', true), 12 * 60 * 60 * 1000,                         "ms diff across DST");
135        equal(test, b.diff(a, 's', true),  12 * 60 * 60,                                "second diff across DST");
136        equal(test, b.diff(a, 'm', true),  12 * 60,                                     "minute diff across DST");
137        equal(test, b.diff(a, 'h', true),  12,                                          "hour diff across DST");
138        equal(test, b.diff(a, 'd', true),  (12 - dst.diff) / 24,                        "day diff across DST");
139        equal(test, b.diff(a, 'w', true),  (12 - dst.diff) / 24 / 7,                    "week diff across DST");
140        equal(test, b.diff(a, 'M', true),  (12 - dst.diff) / 24 / daysInMonth,          "month diff across DST");
141        equal(test, b.diff(a, 'y', true),  (12 - dst.diff) / 24 / daysInMonth / 12,     "year diff across DST");
142
143
144        a = dst.moment;
145        b = a.clone().utc().add(12 + dst.diff, 'hours').local();
146        daysInMonth = (a.daysInMonth() + b.daysInMonth()) / 2;
147
148        equal(test, b.diff(a, 'ms', true), (12 + dst.diff) * 60 * 60 * 1000,   "ms diff across DST");
149        equal(test, b.diff(a, 's', true),  (12 + dst.diff) * 60 * 60,          "second diff across DST");
150        equal(test, b.diff(a, 'm', true),  (12 + dst.diff) * 60,               "minute diff across DST");
151        equal(test, b.diff(a, 'h', true),  (12 + dst.diff),                    "hour diff across DST");
152        equal(test, b.diff(a, 'd', true),  12 / 24,                            "day diff across DST");
153        equal(test, b.diff(a, 'w', true),  12 / 24 / 7,                        "week diff across DST");
154        equal(test, b.diff(a, 'M', true),  12 / 24 / daysInMonth,              "month diff across DST");
155        equal(test, b.diff(a, 'y', true),  12 / 24 / daysInMonth / 12,         "year diff across DST");
156
157        test.done();
158    },
159
160    "diff overflow" : function (test) {
161        test.expect(4);
162
163        test.equal(moment([2011]).diff([2010], 'months'), 12, "month diff");
164        test.equal(moment([2010, 0, 2]).diff([2010], 'hours'), 24, "hour diff");
165        test.equal(moment([2010, 0, 1, 2]).diff([2010], 'minutes'), 120, "minute diff");
166        test.equal(moment([2010, 0, 1, 0, 4]).diff([2010], 'seconds'), 240, "second diff");
167        test.done();
168    },
169
170    "diff between utc and local" : function (test) {
171        test.expect(7);
172
173        test.equal(moment([2012]).utc().diff([2011], 'years'), 1, "year diff");
174        test.equal(moment([2010, 2, 2]).utc().diff([2010, 0, 2], 'months'), 2, "month diff");
175        test.equal(moment([2010, 0, 4]).utc().diff([2010], 'days'), 3, "day diff");
176        test.equal(moment([2010, 0, 22]).utc().diff([2010], 'weeks'), 3, "week diff");
177        test.equal(moment([2010, 0, 1, 4]).utc().diff([2010], 'hours'), 4, "hour diff");
178        test.equal(moment([2010, 0, 1, 0, 5]).utc().diff([2010], 'minutes'), 5, "minute diff");
179        test.equal(moment([2010, 0, 1, 0, 0, 6]).utc().diff([2010], 'seconds'), 6, "second diff");
180
181        test.done();
182    },
183
184    "diff floored" : function (test) {
185        test.expect(7);
186
187        test.equal(moment([2010, 0, 1, 23]).diff([2010], 'day'), 0, "23 hours = 0 days");
188        test.equal(moment([2010, 0, 1, 23, 59]).diff([2010], 'day'), 0, "23:59 hours = 0 days");
189        test.equal(moment([2010, 0, 1, 24]).diff([2010], 'day'), 1, "24 hours = 1 day");
190        test.equal(moment([2010, 0, 2]).diff([2011, 0, 1], 'year'), 0, "year rounded down");
191        test.equal(moment([2011, 0, 1]).diff([2010, 0, 2], 'year'), 0, "year rounded down");
192        test.equal(moment([2010, 0, 2]).diff([2011, 0, 2], 'year'), -1, "year rounded down");
193        test.equal(moment([2011, 0, 2]).diff([2010, 0, 2], 'year'), 1, "year rounded down");
194
195        test.done();
196    },
197
198    "year diffs include dates" : function (test) {
199        test.expect(1);
200
201        test.ok(moment([2012, 1, 19]).diff(moment([2002, 1, 20]), 'years', true) < 10, "year diff should include date of month");
202
203        test.done();
204    },
205
206    "month diffs" : function (test) {
207        test.expect(8);
208
209        // due to floating point math errors, these tests just need to be accurate within 0.00000001
210        equal(test, moment([2012, 0, 1]).diff([2012, 1, 1], 'months', true), -1, 'Jan 1 to Feb 1 should be 1 month');
211        equal(test, moment([2012, 0, 1]).diff([2012, 0, 1, 12], 'months', true), -0.5 / 31, 'Jan 1 to Jan 1 noon should be 0.5 / 31 months');
212        equal(test, moment([2012, 0, 15]).diff([2012, 1, 15], 'months', true), -1, 'Jan 15 to Feb 15 should be 1 month');
213        equal(test, moment([2012, 0, 28]).diff([2012, 1, 28], 'months', true), -1, 'Jan 28 to Feb 28 should be 1 month');
214        equal(test, moment([2012, 0, 31]).diff([2012, 1, 29], 'months', true), -1 + (2 / 30), 'Jan 31 to Feb 29 should be 1 - (2 / 30) months');
215        equal(test, moment([2012, 0, 31]).diff([2012, 2, 1], 'months', true), -2 + (30 / 31), 'Jan 31 to Mar 1 should be 2 - (30 / 31) months');
216        equal(test, moment([2012, 0, 31]).diff([2012, 2, 1, 12], 'months', true), -2 + (29.5 / 31), 'Jan 31 to Mar 1 should be 2 - (29.5 / 31) months');
217        equal(test, moment([2012, 0, 1]).diff([2012, 0, 31], 'months', true), -(30 / 31), 'Jan 1 to Jan 31 should be 30 / 31 months');
218
219        test.done();
220    },
221
222    "year diffs" : function (test) {
223        test.expect(10);
224
225        // due to floating point math errors, these tests just need to be accurate within 0.00000001
226        equal(test, moment([2012, 0, 1]).diff([2013, 0, 1], 'years', true), -1, 'Jan 1 2012 to Jan 1 2013 should be 1 year');
227        equal(test, moment([2012, 1, 28]).diff([2013, 1, 28], 'years', true), -1, 'Feb 28 2012 to Feb 28 2013 should be 1 year');
228        equal(test, moment([2012, 2, 1]).diff([2013, 2, 1], 'years', true), -1, 'Mar 1 2012 to Mar 1 2013 should be 1 year');
229        equal(test, moment([2012, 11, 1]).diff([2013, 11, 1], 'years', true), -1, 'Dec 1 2012 to Dec 1 2013 should be 1 year');
230        equal(test, moment([2012, 11, 31]).diff([2013, 11, 31], 'years', true), -1, 'Dec 31 2012 to Dec 31 2013 should be 1 year');
231        equal(test, moment([2012, 0, 1]).diff([2013, 6, 1], 'years', true), -1.5, 'Jan 1 2012 to Jul 1 2013 should be 1.5 years');
232        equal(test, moment([2012, 0, 31]).diff([2013, 6, 31], 'years', true), -1.5, 'Jan 31 2012 to Jul 31 2013 should be 1.5 years');
233        equal(test, moment([2012, 0, 1]).diff([2013, 0, 1, 12], 'years', true), -1 - (0.5 / 31) / 12, 'Jan 1 2012 to Jan 1 2013 noon should be 1+(0.5 / 31) / 12 years');
234        equal(test, moment([2012, 0, 1]).diff([2013, 6, 1, 12], 'years', true), -1.5 - (0.5 / 31) / 12, 'Jan 1 2012 to Jul 1 2013 noon should be 1.5+(0.5 / 31) / 12 years');
235        equal(test, moment([2012, 1, 29]).diff([2013, 1, 28], 'years', true), -1 + (1 / 28.5) / 12, 'Feb 29 2012 to Feb 28 2013 should be 1-(1 / 28.5) / 12 years');
236
237        test.done();
238    }
239};
240
Full Screen

diff_match_patch_test.py

Source: diff_match_patch_test.py Github

copy
1#!/usr/bin/python3
2
3"""Test harness for diff_match_patch.py
4
5Copyright 2006 Google Inc.
6http://code.google.com/p/google-diff-match-patch/
7
8Licensed under the Apache License, Version 2.0 (the "License");
9you may not use this file except in compliance with the License.
10You may obtain a copy of the License at
11
12  http://www.apache.org/licenses/LICENSE-2.0
13
14Unless required by applicable law or agreed to in writing, software
15distributed under the License is distributed on an "AS IS" BASIS,
16WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17See the License for the specific language governing permissions and
18limitations under the License.
19"""
20
21import imp
22import sys
23import time
24import unittest
25import diff_match_patch as dmp_module
26# Force a module reload.  Allows one to edit the DMP module and rerun the tests
27# without leaving the Python interpreter.
28imp.reload(dmp_module)
29
30class DiffMatchPatchTest(unittest.TestCase):
31
32  def setUp(self):
33    "Test harness for dmp_module."
34    self.dmp = dmp_module.diff_match_patch()
35
36  def diff_rebuildtexts(self, diffs):
37    # Construct the two texts which made up the diff originally.
38    text1 = ""
39    text2 = ""
40    for x in range(0, len(diffs)):
41      if diffs[x][0] != dmp_module.diff_match_patch.DIFF_INSERT:
42        text1 += diffs[x][1]
43      if diffs[x][0] != dmp_module.diff_match_patch.DIFF_DELETE:
44        text2 += diffs[x][1]
45    return (text1, text2)
46
47
48class DiffTest(DiffMatchPatchTest):
49  """DIFF TEST FUNCTIONS"""
50
51  def testDiffCommonPrefix(self):
52    # Detect any common prefix.
53    # Null case.
54    self.assertEqual(0, self.dmp.diff_commonPrefix("abc", "xyz"))
55
56    # Non-null case.
57    self.assertEqual(4, self.dmp.diff_commonPrefix("1234abcdef", "1234xyz"))
58
59    # Whole case.
60    self.assertEqual(4, self.dmp.diff_commonPrefix("1234", "1234xyz"))
61
62  def testDiffCommonSuffix(self):
63    # Detect any common suffix.
64    # Null case.
65    self.assertEqual(0, self.dmp.diff_commonSuffix("abc", "xyz"))
66
67    # Non-null case.
68    self.assertEqual(4, self.dmp.diff_commonSuffix("abcdef1234", "xyz1234"))
69
70    # Whole case.
71    self.assertEqual(4, self.dmp.diff_commonSuffix("1234", "xyz1234"))
72
73  def testDiffCommonOverlap(self):
74    # Null case.
75    self.assertEqual(0, self.dmp.diff_commonOverlap("", "abcd"))
76
77    # Whole case.
78    self.assertEqual(3, self.dmp.diff_commonOverlap("abc", "abcd"))
79
80    # No overlap.
81    self.assertEqual(0, self.dmp.diff_commonOverlap("123456", "abcd"))
82
83    # Overlap.
84    self.assertEqual(3, self.dmp.diff_commonOverlap("123456xxx", "xxxabcd"))
85
86    # Unicode.
87    # Some overly clever languages (C#) may treat ligatures as equal to their
88    # component letters.  E.g. U+FB01 == 'fi'
89    self.assertEqual(0, self.dmp.diff_commonOverlap("fi", "\ufb01i"))
90
91  def testDiffHalfMatch(self):
92    # Detect a halfmatch.
93    self.dmp.Diff_Timeout = 1
94    # No match.
95    self.assertEqual(None, self.dmp.diff_halfMatch("1234567890", "abcdef"))
96
97    self.assertEqual(None, self.dmp.diff_halfMatch("12345", "23"))
98
99    # Single Match.
100    self.assertEqual(("12", "90", "a", "z", "345678"), self.dmp.diff_halfMatch("1234567890", "a345678z"))
101
102    self.assertEqual(("a", "z", "12", "90", "345678"), self.dmp.diff_halfMatch("a345678z", "1234567890"))
103
104    self.assertEqual(("abc", "z", "1234", "0", "56789"), self.dmp.diff_halfMatch("abc56789z", "1234567890"))
105
106    self.assertEqual(("a", "xyz", "1", "7890", "23456"), self.dmp.diff_halfMatch("a23456xyz", "1234567890"))
107
108    # Multiple Matches.
109    self.assertEqual(("12123", "123121", "a", "z", "1234123451234"), self.dmp.diff_halfMatch("121231234123451234123121", "a1234123451234z"))
110
111    self.assertEqual(("", "-=-=-=-=-=", "x", "", "x-=-=-=-=-=-=-="), self.dmp.diff_halfMatch("x-=-=-=-=-=-=-=-=-=-=-=-=", "xx-=-=-=-=-=-=-="))
112
113    self.assertEqual(("-=-=-=-=-=", "", "", "y", "-=-=-=-=-=-=-=y"), self.dmp.diff_halfMatch("-=-=-=-=-=-=-=-=-=-=-=-=y", "-=-=-=-=-=-=-=yy"))
114
115    # Non-optimal halfmatch.
116    # Optimal diff would be -q+x=H-i+e=lloHe+Hu=llo-Hew+y not -qHillo+x=HelloHe-w+Hulloy
117    self.assertEqual(("qHillo", "w", "x", "Hulloy", "HelloHe"), self.dmp.diff_halfMatch("qHilloHelloHew", "xHelloHeHulloy"))
118
119    # Optimal no halfmatch.
120    self.dmp.Diff_Timeout = 0
121    self.assertEqual(None, self.dmp.diff_halfMatch("qHilloHelloHew", "xHelloHeHulloy"))
122
123  def testDiffLinesToChars(self):
124    # Convert lines down to characters.
125    self.assertEqual(("\x01\x02\x01", "\x02\x01\x02", ["", "alpha\n", "beta\n"]), self.dmp.diff_linesToChars("alpha\nbeta\nalpha\n", "beta\nalpha\nbeta\n"))
126
127    self.assertEqual(("", "\x01\x02\x03\x03", ["", "alpha\r\n", "beta\r\n", "\r\n"]), self.dmp.diff_linesToChars("", "alpha\r\nbeta\r\n\r\n\r\n"))
128
129    self.assertEqual(("\x01", "\x02", ["", "a", "b"]), self.dmp.diff_linesToChars("a", "b"))
130
131    # More than 256 to reveal any 8-bit limitations.
132    n = 300
133    lineList = []
134    charList = []
135    for x in range(1, n + 1):
136      lineList.append(str(x) + "\n")
137      charList.append(chr(x))
138    self.assertEqual(n, len(lineList))
139    lines = "".join(lineList)
140    chars = "".join(charList)
141    self.assertEqual(n, len(chars))
142    lineList.insert(0, "")
143    self.assertEqual((chars, "", lineList), self.dmp.diff_linesToChars(lines, ""))
144
145  def testDiffCharsToLines(self):
146    # Convert chars up to lines.
147    diffs = [(self.dmp.DIFF_EQUAL, "\x01\x02\x01"), (self.dmp.DIFF_INSERT, "\x02\x01\x02")]
148    self.dmp.diff_charsToLines(diffs, ["", "alpha\n", "beta\n"])
149    self.assertEqual([(self.dmp.DIFF_EQUAL, "alpha\nbeta\nalpha\n"), (self.dmp.DIFF_INSERT, "beta\nalpha\nbeta\n")], diffs)
150
151    # More than 256 to reveal any 8-bit limitations.
152    n = 300
153    lineList = []
154    charList = []
155    for x in range(1, n + 1):
156      lineList.append(str(x) + "\n")
157      charList.append(chr(x))
158    self.assertEqual(n, len(lineList))
159    lines = "".join(lineList)
160    chars = "".join(charList)
161    self.assertEqual(n, len(chars))
162    lineList.insert(0, "")
163    diffs = [(self.dmp.DIFF_DELETE, chars)]
164    self.dmp.diff_charsToLines(diffs, lineList)
165    self.assertEqual([(self.dmp.DIFF_DELETE, lines)], diffs)
166
167  def testDiffCleanupMerge(self):
168    # Cleanup a messy diff.
169    # Null case.
170    diffs = []
171    self.dmp.diff_cleanupMerge(diffs)
172    self.assertEqual([], diffs)
173
174    # No change case.
175    diffs = [(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "b"), (self.dmp.DIFF_INSERT, "c")]
176    self.dmp.diff_cleanupMerge(diffs)
177    self.assertEqual([(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "b"), (self.dmp.DIFF_INSERT, "c")], diffs)
178
179    # Merge equalities.
180    diffs = [(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_EQUAL, "b"), (self.dmp.DIFF_EQUAL, "c")]
181    self.dmp.diff_cleanupMerge(diffs)
182    self.assertEqual([(self.dmp.DIFF_EQUAL, "abc")], diffs)
183
184    # Merge deletions.
185    diffs = [(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_DELETE, "b"), (self.dmp.DIFF_DELETE, "c")]
186    self.dmp.diff_cleanupMerge(diffs)
187    self.assertEqual([(self.dmp.DIFF_DELETE, "abc")], diffs)
188
189    # Merge insertions.
190    diffs = [(self.dmp.DIFF_INSERT, "a"), (self.dmp.DIFF_INSERT, "b"), (self.dmp.DIFF_INSERT, "c")]
191    self.dmp.diff_cleanupMerge(diffs)
192    self.assertEqual([(self.dmp.DIFF_INSERT, "abc")], diffs)
193
194    # Merge interweave.
195    diffs = [(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_INSERT, "b"), (self.dmp.DIFF_DELETE, "c"), (self.dmp.DIFF_INSERT, "d"), (self.dmp.DIFF_EQUAL, "e"), (self.dmp.DIFF_EQUAL, "f")]
196    self.dmp.diff_cleanupMerge(diffs)
197    self.assertEqual([(self.dmp.DIFF_DELETE, "ac"), (self.dmp.DIFF_INSERT, "bd"), (self.dmp.DIFF_EQUAL, "ef")], diffs)
198
199    # Prefix and suffix detection.
200    diffs = [(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_INSERT, "abc"), (self.dmp.DIFF_DELETE, "dc")]
201    self.dmp.diff_cleanupMerge(diffs)
202    self.assertEqual([(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "d"), (self.dmp.DIFF_INSERT, "b"), (self.dmp.DIFF_EQUAL, "c")], diffs)
203
204    # Prefix and suffix detection with equalities.
205    diffs = [(self.dmp.DIFF_EQUAL, "x"), (self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_INSERT, "abc"), (self.dmp.DIFF_DELETE, "dc"), (self.dmp.DIFF_EQUAL, "y")]
206    self.dmp.diff_cleanupMerge(diffs)
207    self.assertEqual([(self.dmp.DIFF_EQUAL, "xa"), (self.dmp.DIFF_DELETE, "d"), (self.dmp.DIFF_INSERT, "b"), (self.dmp.DIFF_EQUAL, "cy")], diffs)
208
209    # Slide edit left.
210    diffs = [(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_INSERT, "ba"), (self.dmp.DIFF_EQUAL, "c")]
211    self.dmp.diff_cleanupMerge(diffs)
212    self.assertEqual([(self.dmp.DIFF_INSERT, "ab"), (self.dmp.DIFF_EQUAL, "ac")], diffs)
213
214    # Slide edit right.
215    diffs = [(self.dmp.DIFF_EQUAL, "c"), (self.dmp.DIFF_INSERT, "ab"), (self.dmp.DIFF_EQUAL, "a")]
216    self.dmp.diff_cleanupMerge(diffs)
217    self.assertEqual([(self.dmp.DIFF_EQUAL, "ca"), (self.dmp.DIFF_INSERT, "ba")], diffs)
218
219    # Slide edit left recursive.
220    diffs = [(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "b"), (self.dmp.DIFF_EQUAL, "c"), (self.dmp.DIFF_DELETE, "ac"), (self.dmp.DIFF_EQUAL, "x")]
221    self.dmp.diff_cleanupMerge(diffs)
222    self.assertEqual([(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_EQUAL, "acx")], diffs)
223
224    # Slide edit right recursive.
225    diffs = [(self.dmp.DIFF_EQUAL, "x"), (self.dmp.DIFF_DELETE, "ca"), (self.dmp.DIFF_EQUAL, "c"), (self.dmp.DIFF_DELETE, "b"), (self.dmp.DIFF_EQUAL, "a")]
226    self.dmp.diff_cleanupMerge(diffs)
227    self.assertEqual([(self.dmp.DIFF_EQUAL, "xca"), (self.dmp.DIFF_DELETE, "cba")], diffs)
228
229  def testDiffCleanupSemanticLossless(self):
230    # Slide diffs to match logical boundaries.
231    # Null case.
232    diffs = []
233    self.dmp.diff_cleanupSemanticLossless(diffs)
234    self.assertEqual([], diffs)
235
236    # Blank lines.
237    diffs = [(self.dmp.DIFF_EQUAL, "AAA\r\n\r\nBBB"), (self.dmp.DIFF_INSERT, "\r\nDDD\r\n\r\nBBB"), (self.dmp.DIFF_EQUAL, "\r\nEEE")]
238    self.dmp.diff_cleanupSemanticLossless(diffs)
239    self.assertEqual([(self.dmp.DIFF_EQUAL, "AAA\r\n\r\n"), (self.dmp.DIFF_INSERT, "BBB\r\nDDD\r\n\r\n"), (self.dmp.DIFF_EQUAL, "BBB\r\nEEE")], diffs)
240
241    # Line boundaries.
242    diffs = [(self.dmp.DIFF_EQUAL, "AAA\r\nBBB"), (self.dmp.DIFF_INSERT, " DDD\r\nBBB"), (self.dmp.DIFF_EQUAL, " EEE")]
243    self.dmp.diff_cleanupSemanticLossless(diffs)
244    self.assertEqual([(self.dmp.DIFF_EQUAL, "AAA\r\n"), (self.dmp.DIFF_INSERT, "BBB DDD\r\n"), (self.dmp.DIFF_EQUAL, "BBB EEE")], diffs)
245
246    # Word boundaries.
247    diffs = [(self.dmp.DIFF_EQUAL, "The c"), (self.dmp.DIFF_INSERT, "ow and the c"), (self.dmp.DIFF_EQUAL, "at.")]
248    self.dmp.diff_cleanupSemanticLossless(diffs)
249    self.assertEqual([(self.dmp.DIFF_EQUAL, "The "), (self.dmp.DIFF_INSERT, "cow and the "), (self.dmp.DIFF_EQUAL, "cat.")], diffs)
250
251    # Alphanumeric boundaries.
252    diffs = [(self.dmp.DIFF_EQUAL, "The-c"), (self.dmp.DIFF_INSERT, "ow-and-the-c"), (self.dmp.DIFF_EQUAL, "at.")]
253    self.dmp.diff_cleanupSemanticLossless(diffs)
254    self.assertEqual([(self.dmp.DIFF_EQUAL, "The-"), (self.dmp.DIFF_INSERT, "cow-and-the-"), (self.dmp.DIFF_EQUAL, "cat.")], diffs)
255
256    # Hitting the start.
257    diffs = [(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_EQUAL, "ax")]
258    self.dmp.diff_cleanupSemanticLossless(diffs)
259    self.assertEqual([(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_EQUAL, "aax")], diffs)
260
261    # Hitting the end.
262    diffs = [(self.dmp.DIFF_EQUAL, "xa"), (self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_EQUAL, "a")]
263    self.dmp.diff_cleanupSemanticLossless(diffs)
264    self.assertEqual([(self.dmp.DIFF_EQUAL, "xaa"), (self.dmp.DIFF_DELETE, "a")], diffs)
265
266    # Sentence boundaries.
267    diffs = [(self.dmp.DIFF_EQUAL, "The xxx. The "), (self.dmp.DIFF_INSERT, "zzz. The "), (self.dmp.DIFF_EQUAL, "yyy.")]
268    self.dmp.diff_cleanupSemanticLossless(diffs)
269    self.assertEqual([(self.dmp.DIFF_EQUAL, "The xxx."), (self.dmp.DIFF_INSERT, " The zzz."), (self.dmp.DIFF_EQUAL, " The yyy.")], diffs)
270
271  def testDiffCleanupSemantic(self):
272    # Cleanup semantically trivial equalities.
273    # Null case.
274    diffs = []
275    self.dmp.diff_cleanupSemantic(diffs)
276    self.assertEqual([], diffs)
277
278    # No elimination #1.
279    diffs = [(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "cd"), (self.dmp.DIFF_EQUAL, "12"), (self.dmp.DIFF_DELETE, "e")]
280    self.dmp.diff_cleanupSemantic(diffs)
281    self.assertEqual([(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "cd"), (self.dmp.DIFF_EQUAL, "12"), (self.dmp.DIFF_DELETE, "e")], diffs)
282
283    # No elimination #2.
284    diffs = [(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_INSERT, "ABC"), (self.dmp.DIFF_EQUAL, "1234"), (self.dmp.DIFF_DELETE, "wxyz")]
285    self.dmp.diff_cleanupSemantic(diffs)
286    self.assertEqual([(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_INSERT, "ABC"), (self.dmp.DIFF_EQUAL, "1234"), (self.dmp.DIFF_DELETE, "wxyz")], diffs)
287
288    # Simple elimination.
289    diffs = [(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_EQUAL, "b"), (self.dmp.DIFF_DELETE, "c")]
290    self.dmp.diff_cleanupSemantic(diffs)
291    self.assertEqual([(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_INSERT, "b")], diffs)
292
293    # Backpass elimination.
294    diffs = [(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_EQUAL, "cd"), (self.dmp.DIFF_DELETE, "e"), (self.dmp.DIFF_EQUAL, "f"), (self.dmp.DIFF_INSERT, "g")]
295    self.dmp.diff_cleanupSemantic(diffs)
296    self.assertEqual([(self.dmp.DIFF_DELETE, "abcdef"), (self.dmp.DIFF_INSERT, "cdfg")], diffs)
297
298    # Multiple eliminations.
299    diffs = [(self.dmp.DIFF_INSERT, "1"), (self.dmp.DIFF_EQUAL, "A"), (self.dmp.DIFF_DELETE, "B"), (self.dmp.DIFF_INSERT, "2"), (self.dmp.DIFF_EQUAL, "_"), (self.dmp.DIFF_INSERT, "1"), (self.dmp.DIFF_EQUAL, "A"), (self.dmp.DIFF_DELETE, "B"), (self.dmp.DIFF_INSERT, "2")]
300    self.dmp.diff_cleanupSemantic(diffs)
301    self.assertEqual([(self.dmp.DIFF_DELETE, "AB_AB"), (self.dmp.DIFF_INSERT, "1A2_1A2")], diffs)
302
303    # Word boundaries.
304    diffs = [(self.dmp.DIFF_EQUAL, "The c"), (self.dmp.DIFF_DELETE, "ow and the c"), (self.dmp.DIFF_EQUAL, "at.")]
305    self.dmp.diff_cleanupSemantic(diffs)
306    self.assertEqual([(self.dmp.DIFF_EQUAL, "The "), (self.dmp.DIFF_DELETE, "cow and the "), (self.dmp.DIFF_EQUAL, "cat.")], diffs)
307
308    # No overlap elimination.
309    diffs = [(self.dmp.DIFF_DELETE, "abcxx"), (self.dmp.DIFF_INSERT, "xxdef")]
310    self.dmp.diff_cleanupSemantic(diffs)
311    self.assertEqual([(self.dmp.DIFF_DELETE, "abcxx"), (self.dmp.DIFF_INSERT, "xxdef")], diffs)
312
313    # Overlap elimination.
314    diffs = [(self.dmp.DIFF_DELETE, "abcxxx"), (self.dmp.DIFF_INSERT, "xxxdef")]
315    self.dmp.diff_cleanupSemantic(diffs)
316    self.assertEqual([(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_EQUAL, "xxx"), (self.dmp.DIFF_INSERT, "def")], diffs)
317
318    # Reverse overlap elimination.
319    diffs = [(self.dmp.DIFF_DELETE, "xxxabc"), (self.dmp.DIFF_INSERT, "defxxx")]
320    self.dmp.diff_cleanupSemantic(diffs)
321    self.assertEqual([(self.dmp.DIFF_INSERT, "def"), (self.dmp.DIFF_EQUAL, "xxx"), (self.dmp.DIFF_DELETE, "abc")], diffs)
322
323    # Two overlap eliminations.
324    diffs = [(self.dmp.DIFF_DELETE, "abcd1212"), (self.dmp.DIFF_INSERT, "1212efghi"), (self.dmp.DIFF_EQUAL, "----"), (self.dmp.DIFF_DELETE, "A3"), (self.dmp.DIFF_INSERT, "3BC")]
325    self.dmp.diff_cleanupSemantic(diffs)
326    self.assertEqual([(self.dmp.DIFF_DELETE, "abcd"), (self.dmp.DIFF_EQUAL, "1212"), (self.dmp.DIFF_INSERT, "efghi"), (self.dmp.DIFF_EQUAL, "----"), (self.dmp.DIFF_DELETE, "A"), (self.dmp.DIFF_EQUAL, "3"), (self.dmp.DIFF_INSERT, "BC")], diffs)
327
328  def testDiffCleanupEfficiency(self):
329    # Cleanup operationally trivial equalities.
330    self.dmp.Diff_EditCost = 4
331    # Null case.
332    diffs = []
333    self.dmp.diff_cleanupEfficiency(diffs)
334    self.assertEqual([], diffs)
335
336    # No elimination.
337    diffs = [(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "12"), (self.dmp.DIFF_EQUAL, "wxyz"), (self.dmp.DIFF_DELETE, "cd"), (self.dmp.DIFF_INSERT, "34")]
338    self.dmp.diff_cleanupEfficiency(diffs)
339    self.assertEqual([(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "12"), (self.dmp.DIFF_EQUAL, "wxyz"), (self.dmp.DIFF_DELETE, "cd"), (self.dmp.DIFF_INSERT, "34")], diffs)
340
341    # Four-edit elimination.
342    diffs = [(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "12"), (self.dmp.DIFF_EQUAL, "xyz"), (self.dmp.DIFF_DELETE, "cd"), (self.dmp.DIFF_INSERT, "34")]
343    self.dmp.diff_cleanupEfficiency(diffs)
344    self.assertEqual([(self.dmp.DIFF_DELETE, "abxyzcd"), (self.dmp.DIFF_INSERT, "12xyz34")], diffs)
345
346    # Three-edit elimination.
347    diffs = [(self.dmp.DIFF_INSERT, "12"), (self.dmp.DIFF_EQUAL, "x"), (self.dmp.DIFF_DELETE, "cd"), (self.dmp.DIFF_INSERT, "34")]
348    self.dmp.diff_cleanupEfficiency(diffs)
349    self.assertEqual([(self.dmp.DIFF_DELETE, "xcd"), (self.dmp.DIFF_INSERT, "12x34")], diffs)
350
351    # Backpass elimination.
352    diffs = [(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "12"), (self.dmp.DIFF_EQUAL, "xy"), (self.dmp.DIFF_INSERT, "34"), (self.dmp.DIFF_EQUAL, "z"), (self.dmp.DIFF_DELETE, "cd"), (self.dmp.DIFF_INSERT, "56")]
353    self.dmp.diff_cleanupEfficiency(diffs)
354    self.assertEqual([(self.dmp.DIFF_DELETE, "abxyzcd"), (self.dmp.DIFF_INSERT, "12xy34z56")], diffs)
355
356    # High cost elimination.
357    self.dmp.Diff_EditCost = 5
358    diffs = [(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "12"), (self.dmp.DIFF_EQUAL, "wxyz"), (self.dmp.DIFF_DELETE, "cd"), (self.dmp.DIFF_INSERT, "34")]
359    self.dmp.diff_cleanupEfficiency(diffs)
360    self.assertEqual([(self.dmp.DIFF_DELETE, "abwxyzcd"), (self.dmp.DIFF_INSERT, "12wxyz34")], diffs)
361    self.dmp.Diff_EditCost = 4
362
363  def testDiffPrettyHtml(self):
364    # Pretty print.
365    diffs = [(self.dmp.DIFF_EQUAL, "a\n"), (self.dmp.DIFF_DELETE, "<B>b</B>"), (self.dmp.DIFF_INSERT, "c&d")]
366    self.assertEqual("<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>", self.dmp.diff_prettyHtml(diffs))
367
368  def testDiffText(self):
369    # Compute the source and destination texts.
370    diffs = [(self.dmp.DIFF_EQUAL, "jump"), (self.dmp.DIFF_DELETE, "s"), (self.dmp.DIFF_INSERT, "ed"), (self.dmp.DIFF_EQUAL, " over "), (self.dmp.DIFF_DELETE, "the"), (self.dmp.DIFF_INSERT, "a"), (self.dmp.DIFF_EQUAL, " lazy")]
371    self.assertEqual("jumps over the lazy", self.dmp.diff_text1(diffs))
372
373    self.assertEqual("jumped over a lazy", self.dmp.diff_text2(diffs))
374
375  def testDiffDelta(self):
376    # Convert a diff into delta string.
377    diffs = [(self.dmp.DIFF_EQUAL, "jump"), (self.dmp.DIFF_DELETE, "s"), (self.dmp.DIFF_INSERT, "ed"), (self.dmp.DIFF_EQUAL, " over "), (self.dmp.DIFF_DELETE, "the"), (self.dmp.DIFF_INSERT, "a"), (self.dmp.DIFF_EQUAL, " lazy"), (self.dmp.DIFF_INSERT, "old dog")]
378    text1 = self.dmp.diff_text1(diffs)
379    self.assertEqual("jumps over the lazy", text1)
380
381    delta = self.dmp.diff_toDelta(diffs)
382    self.assertEqual("=4\t-1\t+ed\t=6\t-3\t+a\t=5\t+old dog", delta)
383
384    # Convert delta string into a diff.
385    self.assertEqual(diffs, self.dmp.diff_fromDelta(text1, delta))
386
387    # Generates error (19 != 20).
388    try:
389      self.dmp.diff_fromDelta(text1 + "x", delta)
390      self.assertFalse(True)
391    except ValueError:
392      # Exception expected.
393      pass
394
395    # Generates error (19 != 18).
396    try:
397      self.dmp.diff_fromDelta(text1[1:], delta)
398      self.assertFalse(True)
399    except ValueError:
400      # Exception expected.
401      pass
402
403    # Generates error (%c3%xy invalid Unicode).
404    # Note: Python 3 can decode this.
405    #try:
406    #  self.dmp.diff_fromDelta("", "+%c3xy")
407    #  self.assertFalse(True)
408    #except ValueError:
409    #  # Exception expected.
410    #  pass
411
412    # Test deltas with special characters.
413    diffs = [(self.dmp.DIFF_EQUAL, "\u0680 \x00 \t %"), (self.dmp.DIFF_DELETE, "\u0681 \x01 \n ^"), (self.dmp.DIFF_INSERT, "\u0682 \x02 \\ |")]
414    text1 = self.dmp.diff_text1(diffs)
415    self.assertEqual("\u0680 \x00 \t %\u0681 \x01 \n ^", text1)
416
417    delta = self.dmp.diff_toDelta(diffs)
418    self.assertEqual("=7\t-7\t+%DA%82 %02 %5C %7C", delta)
419
420    # Convert delta string into a diff.
421    self.assertEqual(diffs, self.dmp.diff_fromDelta(text1, delta))
422
423    # Verify pool of unchanged characters.
424    diffs = [(self.dmp.DIFF_INSERT, "A-Z a-z 0-9 - _ . ! ~ * ' ( ) ; / ? : @ & = + $ , # ")]
425    text2 = self.dmp.diff_text2(diffs)
426    self.assertEqual("A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ", text2)
427
428    delta = self.dmp.diff_toDelta(diffs)
429    self.assertEqual("+A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ", delta)
430
431    # Convert delta string into a diff.
432    self.assertEqual(diffs, self.dmp.diff_fromDelta("", delta))
433
434  def testDiffXIndex(self):
435    # Translate a location in text1 to text2.
436    self.assertEqual(5, self.dmp.diff_xIndex([(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_INSERT, "1234"), (self.dmp.DIFF_EQUAL, "xyz")], 2))
437
438    # Translation on deletion.
439    self.assertEqual(1, self.dmp.diff_xIndex([(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "1234"), (self.dmp.DIFF_EQUAL, "xyz")], 3))
440
441  def testDiffLevenshtein(self):
442    # Levenshtein with trailing equality.
443    self.assertEqual(4, self.dmp.diff_levenshtein([(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_INSERT, "1234"), (self.dmp.DIFF_EQUAL, "xyz")]))
444    # Levenshtein with leading equality.
445    self.assertEqual(4, self.dmp.diff_levenshtein([(self.dmp.DIFF_EQUAL, "xyz"), (self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_INSERT, "1234")]))
446    # Levenshtein with middle equality.
447    self.assertEqual(7, self.dmp.diff_levenshtein([(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_EQUAL, "xyz"), (self.dmp.DIFF_INSERT, "1234")]))
448
449  def testDiffBisect(self):
450    # Normal.
451    a = "cat"
452    b = "map"
453    # Since the resulting diff hasn't been normalized, it would be ok if
454    # the insertion and deletion pairs are swapped.
455    # If the order changes, tweak this test as required.
456    self.assertEqual([(self.dmp.DIFF_DELETE, "c"), (self.dmp.DIFF_INSERT, "m"), (self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "t"), (self.dmp.DIFF_INSERT, "p")], self.dmp.diff_bisect(a, b, sys.maxsize))
457
458    # Timeout.
459    self.assertEqual([(self.dmp.DIFF_DELETE, "cat"), (self.dmp.DIFF_INSERT, "map")], self.dmp.diff_bisect(a, b, 0))
460
461  def testDiffMain(self):
462    # Perform a trivial diff.
463    # Null case.
464    self.assertEqual([], self.dmp.diff_main("", "", False))
465
466    # Equality.
467    self.assertEqual([(self.dmp.DIFF_EQUAL, "abc")], self.dmp.diff_main("abc", "abc", False))
468
469    # Simple insertion.
470    self.assertEqual([(self.dmp.DIFF_EQUAL, "ab"), (self.dmp.DIFF_INSERT, "123"), (self.dmp.DIFF_EQUAL, "c")], self.dmp.diff_main("abc", "ab123c", False))
471
472    # Simple deletion.
473    self.assertEqual([(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "123"), (self.dmp.DIFF_EQUAL, "bc")], self.dmp.diff_main("a123bc", "abc", False))
474
475    # Two insertions.
476    self.assertEqual([(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_INSERT, "123"), (self.dmp.DIFF_EQUAL, "b"), (self.dmp.DIFF_INSERT, "456"), (self.dmp.DIFF_EQUAL, "c")], self.dmp.diff_main("abc", "a123b456c", False))
477
478    # Two deletions.
479    self.assertEqual([(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "123"), (self.dmp.DIFF_EQUAL, "b"), (self.dmp.DIFF_DELETE, "456"), (self.dmp.DIFF_EQUAL, "c")], self.dmp.diff_main("a123b456c", "abc", False))
480
481    # Perform a real diff.
482    # Switch off the timeout.
483    self.dmp.Diff_Timeout = 0
484    # Simple cases.
485    self.assertEqual([(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_INSERT, "b")], self.dmp.diff_main("a", "b", False))
486
487    self.assertEqual([(self.dmp.DIFF_DELETE, "Apple"), (self.dmp.DIFF_INSERT, "Banana"), (self.dmp.DIFF_EQUAL, "s are a"), (self.dmp.DIFF_INSERT, "lso"), (self.dmp.DIFF_EQUAL, " fruit.")], self.dmp.diff_main("Apples are a fruit.", "Bananas are also fruit.", False))
488
489    self.assertEqual([(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_INSERT, "\u0680"), (self.dmp.DIFF_EQUAL, "x"), (self.dmp.DIFF_DELETE, "\t"), (self.dmp.DIFF_INSERT, "\x00")], self.dmp.diff_main("ax\t", "\u0680x\x00", False))
490
491    # Overlaps.
492    self.assertEqual([(self.dmp.DIFF_DELETE, "1"), (self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "y"), (self.dmp.DIFF_EQUAL, "b"), (self.dmp.DIFF_DELETE, "2"), (self.dmp.DIFF_INSERT, "xab")], self.dmp.diff_main("1ayb2", "abxab", False))
493
494    self.assertEqual([(self.dmp.DIFF_INSERT, "xaxcx"), (self.dmp.DIFF_EQUAL, "abc"), (self.dmp.DIFF_DELETE, "y")], self.dmp.diff_main("abcy", "xaxcxabc", False))
495
496    self.assertEqual([(self.dmp.DIFF_DELETE, "ABCD"), (self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "="), (self.dmp.DIFF_INSERT, "-"), (self.dmp.DIFF_EQUAL, "bcd"), (self.dmp.DIFF_DELETE, "="), (self.dmp.DIFF_INSERT, "-"), (self.dmp.DIFF_EQUAL, "efghijklmnopqrs"), (self.dmp.DIFF_DELETE, "EFGHIJKLMNOefg")], self.dmp.diff_main("ABCDa=bcd=efghijklmnopqrsEFGHIJKLMNOefg", "a-bcd-efghijklmnopqrs", False))
497
498    # Large equality.
499    self.assertEqual([(self.dmp.DIFF_INSERT, " "), (self.dmp.DIFF_EQUAL,"a"), (self.dmp.DIFF_INSERT,"nd"), (self.dmp.DIFF_EQUAL," [[Pennsylvania]]"), (self.dmp.DIFF_DELETE," and [[New")], self.dmp.diff_main("a [[Pennsylvania]] and [[New", " and [[Pennsylvania]]", False))
500
501    # Timeout.
502    self.dmp.Diff_Timeout = 0.1  # 100ms
503    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"
504    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"
505    # Increase the text lengths by 1024 times to ensure a timeout.
506    for x in range(10):
507      a = a + a
508      b = b + b
509    startTime = time.time()
510    self.dmp.diff_main(a, b)
511    endTime = time.time()
512    # Test that we took at least the timeout period.
513    self.assertTrue(self.dmp.Diff_Timeout <= endTime - startTime)
514    # Test that we didn't take forever (be forgiving).
515    # Theoretically this test could fail very occasionally if the
516    # OS task swaps or locks up for a second at the wrong moment.
517    self.assertTrue(self.dmp.Diff_Timeout * 2 > endTime - startTime)
518    self.dmp.Diff_Timeout = 0
519
520    # Test the linemode speedup.
521    # Must be long to pass the 100 char cutoff.
522    # Simple line-mode.
523    a = "1234567890\n" * 13
524    b = "abcdefghij\n" * 13
525    self.assertEqual(self.dmp.diff_main(a, b, False), self.dmp.diff_main(a, b, True))
526
527    # Single line-mode.
528    a = "1234567890" * 13
529    b = "abcdefghij" * 13
530    self.assertEqual(self.dmp.diff_main(a, b, False), self.dmp.diff_main(a, b, True))
531
532    # Overlap line-mode.
533    a = "1234567890\n" * 13
534    b = "abcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n"
535    texts_linemode = self.diff_rebuildtexts(self.dmp.diff_main(a, b, True))
536    texts_textmode = self.diff_rebuildtexts(self.dmp.diff_main(a, b, False))
537    self.assertEqual(texts_textmode, texts_linemode)
538
539    # Test null inputs.
540    try:
541      self.dmp.diff_main(None, None)
542      self.assertFalse(True)
543    except ValueError:
544      # Exception expected.
545      pass
546
547
548class MatchTest(DiffMatchPatchTest):
549  """MATCH TEST FUNCTIONS"""
550
551  def testMatchAlphabet(self):
552    # Initialise the bitmasks for Bitap.
553    self.assertEqual({"a":4, "b":2, "c":1}, self.dmp.match_alphabet("abc"))
554
555    self.assertEqual({"a":37, "b":18, "c":8}, self.dmp.match_alphabet("abcaba"))
556
557  def testMatchBitap(self):
558    self.dmp.Match_Distance = 100
559    self.dmp.Match_Threshold = 0.5
560    # Exact matches.
561    self.assertEqual(5, self.dmp.match_bitap("abcdefghijk", "fgh", 5))
562
563    self.assertEqual(5, self.dmp.match_bitap("abcdefghijk", "fgh", 0))
564
565    # Fuzzy matches.
566    self.assertEqual(4, self.dmp.match_bitap("abcdefghijk", "efxhi", 0))
567
568    self.assertEqual(2, self.dmp.match_bitap("abcdefghijk", "cdefxyhijk", 5))
569
570    self.assertEqual(-1, self.dmp.match_bitap("abcdefghijk", "bxy", 1))
571
572    # Overflow.
573    self.assertEqual(2, self.dmp.match_bitap("123456789xx0", "3456789x0", 2))
574
575    self.assertEqual(0, self.dmp.match_bitap("abcdef", "xxabc", 4))
576
577    self.assertEqual(3, self.dmp.match_bitap("abcdef", "defyy", 4))
578
579    self.assertEqual(0, self.dmp.match_bitap("abcdef", "xabcdefy", 0))
580
581    # Threshold test.
582    self.dmp.Match_Threshold = 0.4
583    self.assertEqual(4, self.dmp.match_bitap("abcdefghijk", "efxyhi", 1))
584
585    self.dmp.Match_Threshold = 0.3
586    self.assertEqual(-1, self.dmp.match_bitap("abcdefghijk", "efxyhi", 1))
587
588    self.dmp.Match_Threshold = 0.0
589    self.assertEqual(1, self.dmp.match_bitap("abcdefghijk", "bcdef", 1))
590    self.dmp.Match_Threshold = 0.5
591
592    # Multiple select.
593    self.assertEqual(0, self.dmp.match_bitap("abcdexyzabcde", "abccde", 3))
594
595    self.assertEqual(8, self.dmp.match_bitap("abcdexyzabcde", "abccde", 5))
596
597    # Distance test.
598    self.dmp.Match_Distance = 10  # Strict location.
599    self.assertEqual(-1, self.dmp.match_bitap("abcdefghijklmnopqrstuvwxyz", "abcdefg", 24))
600
601    self.assertEqual(0, self.dmp.match_bitap("abcdefghijklmnopqrstuvwxyz", "abcdxxefg", 1))
602
603    self.dmp.Match_Distance = 1000  # Loose location.
604    self.assertEqual(0, self.dmp.match_bitap("abcdefghijklmnopqrstuvwxyz", "abcdefg", 24))
605
606
607  def testMatchMain(self):
608    # Full match.
609    # Shortcut matches.
610    self.assertEqual(0, self.dmp.match_main("abcdef", "abcdef", 1000))
611
612    self.assertEqual(-1, self.dmp.match_main("", "abcdef", 1))
613
614    self.assertEqual(3, self.dmp.match_main("abcdef", "", 3))
615
616    self.assertEqual(3, self.dmp.match_main("abcdef", "de", 3))
617
618    self.assertEqual(3, self.dmp.match_main("abcdef", "defy", 4))
619
620    self.assertEqual(0, self.dmp.match_main("abcdef", "abcdefy", 0))
621
622    # Complex match.
623    self.dmp.Match_Threshold = 0.7
624    self.assertEqual(4, self.dmp.match_main("I am the very model of a modern major general.", " that berry ", 5))
625    self.dmp.Match_Threshold = 0.5
626
627    # Test null inputs.
628    try:
629      self.dmp.match_main(None, None, 0)
630      self.assertFalse(True)
631    except ValueError:
632      # Exception expected.
633      pass
634
635
636class PatchTest(DiffMatchPatchTest):
637  """PATCH TEST FUNCTIONS"""
638
639  def testPatchObj(self):
640    # Patch Object.
641    p = dmp_module.patch_obj()
642    p.start1 = 20
643    p.start2 = 21
644    p.length1 = 18
645    p.length2 = 17
646    p.diffs = [(self.dmp.DIFF_EQUAL, "jump"), (self.dmp.DIFF_DELETE, "s"), (self.dmp.DIFF_INSERT, "ed"), (self.dmp.DIFF_EQUAL, " over "), (self.dmp.DIFF_DELETE, "the"), (self.dmp.DIFF_INSERT, "a"), (self.dmp.DIFF_EQUAL, "\nlaz")]
647    strp = str(p)
648    self.assertEqual("@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n  over \n-the\n+a\n %0Alaz\n", strp)
649
650  def testPatchFromText(self):
651    self.assertEqual([], self.dmp.patch_fromText(""))
652
653    strp = "@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n  over \n-the\n+a\n %0Alaz\n"
654    self.assertEqual(strp, str(self.dmp.patch_fromText(strp)[0]))
655
656    self.assertEqual("@@ -1 +1 @@\n-a\n+b\n", str(self.dmp.patch_fromText("@@ -1 +1 @@\n-a\n+b\n")[0]))
657
658    self.assertEqual("@@ -1,3 +0,0 @@\n-abc\n", str(self.dmp.patch_fromText("@@ -1,3 +0,0 @@\n-abc\n")[0]))
659
660    self.assertEqual("@@ -0,0 +1,3 @@\n+abc\n", str(self.dmp.patch_fromText("@@ -0,0 +1,3 @@\n+abc\n")[0]))
661
662    # Generates error.
663    try:
664      self.dmp.patch_fromText("Bad\nPatch\n")
665      self.assertFalse(True)
666    except ValueError:
667      # Exception expected.
668      pass
669
670  def testPatchToText(self):
671    strp = "@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n  over \n-the\n+a\n  laz\n"
672    p = self.dmp.patch_fromText(strp)
673    self.assertEqual(strp, self.dmp.patch_toText(p))
674
675    strp = "@@ -1,9 +1,9 @@\n-f\n+F\n oo+fooba\[email protected]@ -7,9 +7,9 @@\n obar\n-,\n+.\n tes\n"
676    p = self.dmp.patch_fromText(strp)
677    self.assertEqual(strp, self.dmp.patch_toText(p))
678
679  def testPatchAddContext(self):
680    self.dmp.Patch_Margin = 4
681    p = self.dmp.patch_fromText("@@ -21,4 +21,10 @@\n-jump\n+somersault\n")[0]
682    self.dmp.patch_addContext(p, "The quick brown fox jumps over the lazy dog.")
683    self.assertEqual("@@ -17,12 +17,18 @@\n fox \n-jump\n+somersault\n s ov\n", str(p))
684
685    # Same, but not enough trailing context.
686    p = self.dmp.patch_fromText("@@ -21,4 +21,10 @@\n-jump\n+somersault\n")[0]
687    self.dmp.patch_addContext(p, "The quick brown fox jumps.")
688    self.assertEqual("@@ -17,10 +17,16 @@\n fox \n-jump\n+somersault\n s.\n", str(p))
689
690    # Same, but not enough leading context.
691    p = self.dmp.patch_fromText("@@ -3 +3,2 @@\n-e\n+at\n")[0]
692    self.dmp.patch_addContext(p, "The quick brown fox jumps.")
693    self.assertEqual("@@ -1,7 +1,8 @@\n Th\n-e\n+at\n  qui\n", str(p))
694
695    # Same, but with ambiguity.
696    p = self.dmp.patch_fromText("@@ -3 +3,2 @@\n-e\n+at\n")[0]
697    self.dmp.patch_addContext(p, "The quick brown fox jumps.  The quick brown fox crashes.")
698    self.assertEqual("@@ -1,27 +1,28 @@\n Th\n-e\n+at\n  quick brown fox jumps. \n", str(p))
699
700  def testPatchMake(self):
701    # Null case.
702    patches = self.dmp.patch_make("", "")
703    self.assertEqual("", self.dmp.patch_toText(patches))
704
705    text1 = "The quick brown fox jumps over the lazy dog."
706    text2 = "That quick brown fox jumped over a lazy dog."
707    # Text2+Text1 inputs.
708    expectedPatch = "@@ -1,8 +1,7 @@\n Th\n-at\n+e\n  qui\[email protected]@ -21,17 +21,18 @@\n jump\n-ed\n+s\n  over \n-a\n+the\n  laz\n"
709    # The second patch must be "-21,17 +21,18", not "-22,17 +21,18" due to rolling context.
710    patches = self.dmp.patch_make(text2, text1)
711    self.assertEqual(expectedPatch, self.dmp.patch_toText(patches))
712
713    # Text1+Text2 inputs.
714    expectedPatch = "@@ -1,11 +1,12 @@\n Th\n-e\n+at\n  quick b\[email protected]@ -22,18 +22,17 @@\n jump\n-s\n+ed\n  over \n-the\n+a\n  laz\n"
715    patches = self.dmp.patch_make(text1, text2)
716    self.assertEqual(expectedPatch, self.dmp.patch_toText(patches))
717
718    # Diff input.
719    diffs = self.dmp.diff_main(text1, text2, False)
720    patches = self.dmp.patch_make(diffs)
721    self.assertEqual(expectedPatch, self.dmp.patch_toText(patches))
722
723    # Text1+Diff inputs.
724    patches = self.dmp.patch_make(text1, diffs)
725    self.assertEqual(expectedPatch, self.dmp.patch_toText(patches))
726
727    # Text1+Text2+Diff inputs (deprecated).
728    patches = self.dmp.patch_make(text1, text2, diffs)
729    self.assertEqual(expectedPatch, self.dmp.patch_toText(patches))
730
731    # Character encoding.
732    patches = self.dmp.patch_make("`1234567890-=[]\\;',./", "[email protected]#$%^&*()_+{}|:\"<>?")
733    self.assertEqual("@@ -1,21 +1,21 @@\n-%601234567890-=%5B%5D%5C;',./\[email protected]#$%25%5E&*()_+%7B%7D%7C:%22%3C%3E?\n", self.dmp.patch_toText(patches))
734
735    # Character decoding.
736    diffs = [(self.dmp.DIFF_DELETE, "`1234567890-=[]\\;',./"), (self.dmp.DIFF_INSERT, "[email protected]#$%^&*()_+{}|:\"<>?")]
737    self.assertEqual(diffs, self.dmp.patch_fromText("@@ -1,21 +1,21 @@\n-%601234567890-=%5B%5D%5C;',./\[email protected]#$%25%5E&*()_+%7B%7D%7C:%22%3C%3E?\n")[0].diffs)
738
739    # Long string with repeats.
740    text1 = ""
741    for x in range(100):
742      text1 += "abcdef"
743    text2 = text1 + "123"
744    expectedPatch = "@@ -573,28 +573,31 @@\n cdefabcdefabcdefabcdefabcdef\n+123\n"
745    patches = self.dmp.patch_make(text1, text2)
746    self.assertEqual(expectedPatch, self.dmp.patch_toText(patches))
747
748    # Test null inputs.
749    try:
750      self.dmp.patch_make(None, None)
751      self.assertFalse(True)
752    except ValueError:
753      # Exception expected.
754      pass
755
756  def testPatchSplitMax(self):
757    # Assumes that Match_MaxBits is 32.
758    patches = self.dmp.patch_make("abcdefghijklmnopqrstuvwxyz01234567890", "XabXcdXefXghXijXklXmnXopXqrXstXuvXwxXyzX01X23X45X67X89X0")
759    self.dmp.patch_splitMax(patches)
760    self.assertEqual("@@ -1,32 +1,46 @@\n+X\n ab\n+X\n cd\n+X\n ef\n+X\n gh\n+X\n ij\n+X\n kl\n+X\n mn\n+X\n op\n+X\n qr\n+X\n st\n+X\n uv\n+X\n wx\n+X\n yz\n+X\n 012345\[email protected]@ -25,13 +39,18 @@\n zX01\n+X\n 23\n+X\n 45\n+X\n 67\n+X\n 89\n+X\n 0\n", self.dmp.patch_toText(patches))
761
762    patches = self.dmp.patch_make("abcdef1234567890123456789012345678901234567890123456789012345678901234567890uvwxyz", "abcdefuvwxyz")
763    oldToText = self.dmp.patch_toText(patches)
764    self.dmp.patch_splitMax(patches)
765    self.assertEqual(oldToText, self.dmp.patch_toText(patches))
766
767    patches = self.dmp.patch_make("1234567890123456789012345678901234567890123456789012345678901234567890", "abc")
768    self.dmp.patch_splitMax(patches)
769    self.assertEqual("@@ -1,32 +1,4 @@\n-1234567890123456789012345678\n 9012\[email protected]@ -29,32 +1,4 @@\n-9012345678901234567890123456\n 7890\[email protected]@ -57,14 +1,3 @@\n-78901234567890\n+abc\n", self.dmp.patch_toText(patches))
770
771    patches = self.dmp.patch_make("abcdefghij , h : 0 , t : 1 abcdefghij , h : 0 , t : 1 abcdefghij , h : 0 , t : 1", "abcdefghij , h : 1 , t : 1 abcdefghij , h : 1 , t : 1 abcdefghij , h : 0 , t : 1")
772    self.dmp.patch_splitMax(patches)
773    self.assertEqual("@@ -2,32 +2,32 @@\n bcdefghij , h : \n-0\n+1\n  , t : 1 abcdef\[email protected]@ -29,32 +29,32 @@\n bcdefghij , h : \n-0\n+1\n  , t : 1 abcdef\n", self.dmp.patch_toText(patches))
774
775  def testPatchAddPadding(self):
776    # Both edges full.
777    patches = self.dmp.patch_make("", "test")
778    self.assertEqual("@@ -0,0 +1,4 @@\n+test\n", self.dmp.patch_toText(patches))
779    self.dmp.patch_addPadding(patches)
780    self.assertEqual("@@ -1,8 +1,12 @@\n %01%02%03%04\n+test\n %01%02%03%04\n", self.dmp.patch_toText(patches))
781
782    # Both edges partial.
783    patches = self.dmp.patch_make("XY", "XtestY")
784    self.assertEqual("@@ -1,2 +1,6 @@\n X\n+test\n Y\n", self.dmp.patch_toText(patches))
785    self.dmp.patch_addPadding(patches)
786    self.assertEqual("@@ -2,8 +2,12 @@\n %02%03%04X\n+test\n Y%01%02%03\n", self.dmp.patch_toText(patches))
787
788    # Both edges none.
789    patches = self.dmp.patch_make("XXXXYYYY", "XXXXtestYYYY")
790    self.assertEqual("@@ -1,8 +1,12 @@\n XXXX\n+test\n YYYY\n", self.dmp.patch_toText(patches))
791    self.dmp.patch_addPadding(patches)
792    self.assertEqual("@@ -5,8 +5,12 @@\n XXXX\n+test\n YYYY\n", self.dmp.patch_toText(patches))
793
794  def testPatchApply(self):
795    self.dmp.Match_Distance = 1000
796    self.dmp.Match_Threshold = 0.5
797    self.dmp.Patch_DeleteThreshold = 0.5
798    # Null case.
799    patches = self.dmp.patch_make("", "")
800    results = self.dmp.patch_apply(patches, "Hello world.")
801    self.assertEqual(("Hello world.", []), results)
802
803    # Exact match.
804    patches = self.dmp.patch_make("The quick brown fox jumps over the lazy dog.", "That quick brown fox jumped over a lazy dog.")
805    results = self.dmp.patch_apply(patches, "The quick brown fox jumps over the lazy dog.")
806    self.assertEqual(("That quick brown fox jumped over a lazy dog.", [True, True]), results)
807
808    # Partial match.
809    results = self.dmp.patch_apply(patches, "The quick red rabbit jumps over the tired tiger.")
810    self.assertEqual(("That quick red rabbit jumped over a tired tiger.", [True, True]), results)
811
812    # Failed match.
813    results = self.dmp.patch_apply(patches, "I am the very model of a modern major general.")
814    self.assertEqual(("I am the very model of a modern major general.", [False, False]), results)
815
816    # Big delete, small change.
817    patches = self.dmp.patch_make("x1234567890123456789012345678901234567890123456789012345678901234567890y", "xabcy")
818    results = self.dmp.patch_apply(patches, "x123456789012345678901234567890-----++++++++++-----123456789012345678901234567890y")
819    self.assertEqual(("xabcy", [True, True]), results)
820
821    # Big delete, big change 1.
822    patches = self.dmp.patch_make("x1234567890123456789012345678901234567890123456789012345678901234567890y", "xabcy")
823    results = self.dmp.patch_apply(patches, "x12345678901234567890---------------++++++++++---------------12345678901234567890y")
824    self.assertEqual(("xabc12345678901234567890---------------++++++++++---------------12345678901234567890y", [False, True]), results)
825
826    # Big delete, big change 2.
827    self.dmp.Patch_DeleteThreshold = 0.6
828    patches = self.dmp.patch_make("x1234567890123456789012345678901234567890123456789012345678901234567890y", "xabcy")
829    results = self.dmp.patch_apply(patches, "x12345678901234567890---------------++++++++++---------------12345678901234567890y")
830    self.assertEqual(("xabcy", [True, True]), results)
831    self.dmp.Patch_DeleteThreshold = 0.5
832
833    # Compensate for failed patch.
834    self.dmp.Match_Threshold = 0.0
835    self.dmp.Match_Distance = 0
836    patches = self.dmp.patch_make("abcdefghijklmnopqrstuvwxyz--------------------1234567890", "abcXXXXXXXXXXdefghijklmnopqrstuvwxyz--------------------1234567YYYYYYYYYY890")
837    results = self.dmp.patch_apply(patches, "ABCDEFGHIJKLMNOPQRSTUVWXYZ--------------------1234567890")
838    self.assertEqual(("ABCDEFGHIJKLMNOPQRSTUVWXYZ--------------------1234567YYYYYYYYYY890", [False, True]), results)
839    self.dmp.Match_Threshold = 0.5
840    self.dmp.Match_Distance = 1000
841
842    # No side effects.
843    patches = self.dmp.patch_make("", "test")
844    patchstr = self.dmp.patch_toText(patches)
845    results = self.dmp.patch_apply(patches, "")
846    self.assertEqual(patchstr, self.dmp.patch_toText(patches))
847
848    # No side effects with major delete.
849    patches = self.dmp.patch_make("The quick brown fox jumps over the lazy dog.", "Woof")
850    patchstr = self.dmp.patch_toText(patches)
851    self.dmp.patch_apply(patches, "The quick brown fox jumps over the lazy dog.")
852    self.assertEqual(patchstr, self.dmp.patch_toText(patches))
853
854    # Edge exact match.
855    patches = self.dmp.patch_make("", "test")
856    self.dmp.patch_apply(patches, "")
857    self.assertEqual(("test", [True]), results)
858
859    # Near edge exact match.
860    patches = self.dmp.patch_make("XY", "XtestY")
861    results = self.dmp.patch_apply(patches, "XY")
862    self.assertEqual(("XtestY", [True]), results)
863
864    # Edge partial match.
865    patches = self.dmp.patch_make("y", "y123")
866    results = self.dmp.patch_apply(patches, "x")
867    self.assertEqual(("x123", [True]), results)
868
869
870if __name__ == "__main__":
871  unittest.main()
872
Full Screen

diff_parser_unittest.py

Source: diff_parser_unittest.py Github

copy
1# Copyright (C) 2009 Google Inc. All rights reserved.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions are
5# met:
6#
7#    * Redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer.
9#    * Redistributions in binary form must reproduce the above
10# copyright notice, this list of conditions and the following disclaimer
11# in the documentation and/or other materials provided with the
12# distribution.
13#    * Neither the name of Google Inc. nor the names of its
14# contributors may be used to endorse or promote products derived from
15# this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29import cStringIO as StringIO
30import diff_parser
31import re
32import unittest
33
34from webkitpy.common.checkout.diff_test_data import DIFF_TEST_DATA
35
36class DiffParserTest(unittest.TestCase):
37    maxDiff = None
38
39    def test_diff_parser(self, parser = None):
40        if not parser:
41            parser = diff_parser.DiffParser(DIFF_TEST_DATA.splitlines())
42        self.assertEqual(3, len(parser.files))
43
44        self.assertTrue('WebCore/style/StyleFlexibleBoxData.h' in parser.files)
45        diff = parser.files['WebCore/style/StyleFlexibleBoxData.h']
46        self.assertEqual(7, len(diff.lines))
47        # The first two unchaged lines.
48        self.assertEqual((47, 47), diff.lines[0][0:2])
49        self.assertEqual('', diff.lines[0][2])
50        self.assertEqual((48, 48), diff.lines[1][0:2])
51        self.assertEqual('    unsigned align : 3; // EBoxAlignment', diff.lines[1][2])
52        # The deleted line
53        self.assertEqual((50, 0), diff.lines[3][0:2])
54        self.assertEqual('    unsigned orient: 1; // EBoxOrient', diff.lines[3][2])
55
56        # The first file looks OK. Let's check the next, more complicated file.
57        self.assertTrue('WebCore/style/StyleRareInheritedData.cpp' in parser.files)
58        diff = parser.files['WebCore/style/StyleRareInheritedData.cpp']
59        # There are 3 chunks.
60        self.assertEqual(7 + 7 + 9, len(diff.lines))
61        # Around an added line.
62        self.assertEqual((60, 61), diff.lines[9][0:2])
63        self.assertEqual((0, 62), diff.lines[10][0:2])
64        self.assertEqual((61, 63), diff.lines[11][0:2])
65        # Look through the last chunk, which contains both add's and delete's.
66        self.assertEqual((81, 83), diff.lines[14][0:2])
67        self.assertEqual((82, 84), diff.lines[15][0:2])
68        self.assertEqual((83, 85), diff.lines[16][0:2])
69        self.assertEqual((84, 0), diff.lines[17][0:2])
70        self.assertEqual((0, 86), diff.lines[18][0:2])
71        self.assertEqual((0, 87), diff.lines[19][0:2])
72        self.assertEqual((85, 88), diff.lines[20][0:2])
73        self.assertEqual((86, 89), diff.lines[21][0:2])
74        self.assertEqual((87, 90), diff.lines[22][0:2])
75
76        # Check if a newly added file is correctly handled.
77        diff = parser.files['LayoutTests/platform/mac/fast/flexbox/box-orient-button-expected.checksum']
78        self.assertEqual(1, len(diff.lines))
79        self.assertEqual((0, 1), diff.lines[0][0:2])
80
81    def test_diff_converter(self):
82        comment_lines = [
83            "Hey guys,\n",
84            "\n",
85            "See my awesome patch below!\n",
86            "\n",
87            " - Cool Hacker\n",
88            "\n",
89            ]
90
91        revision_lines = [
92            "Subversion Revision 289799\n",
93            ]
94
95        svn_diff_lines = [
96            "Index: Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n",
97            "===================================================================\n",
98            "--- Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n",
99            "+++ Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n",
100            "@@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line):\n",
101            ]
102        self.assertEqual(diff_parser.get_diff_converter(svn_diff_lines), diff_parser.svn_diff_to_svn_diff)
103        self.assertEqual(diff_parser.get_diff_converter(comment_lines + svn_diff_lines), diff_parser.svn_diff_to_svn_diff)
104        self.assertEqual(diff_parser.get_diff_converter(revision_lines + svn_diff_lines), diff_parser.svn_diff_to_svn_diff)
105
106        git_diff_lines = [
107            "diff --git a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n",
108            "index 3c5b45b..0197ead 100644\n",
109            "--- a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n",
110            "+++ b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n",
111            "@@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line):\n",
112            ]
113        self.assertEqual(diff_parser.get_diff_converter(git_diff_lines), diff_parser.git_diff_to_svn_diff)
114        self.assertEqual(diff_parser.get_diff_converter(comment_lines + git_diff_lines), diff_parser.git_diff_to_svn_diff)
115        self.assertEqual(diff_parser.get_diff_converter(revision_lines + git_diff_lines), diff_parser.git_diff_to_svn_diff)
116
117    def test_git_mnemonicprefix(self):
118        p = re.compile(r' ([a|b])/')
119
120        prefixes = [
121            { 'a' : 'i', 'b' : 'w' }, # git-diff (compares the (i)ndex and the (w)ork tree)
122            { 'a' : 'c', 'b' : 'w' }, # git-diff HEAD (compares a (c)ommit and the (w)ork tree)
123            { 'a' : 'c', 'b' : 'i' }, # git diff --cached (compares a (c)ommit and the (i)ndex)
124            { 'a' : 'o', 'b' : 'w' }, # git-diff HEAD:file1 file2 (compares an (o)bject and a (w)ork tree entity)
125            { 'a' : '1', 'b' : '2' }, # git diff --no-index a b (compares two non-git things (1) and (2))
126        ]
127
128        for prefix in prefixes:
129            patch = p.sub(lambda x: " %s/" % prefix[x.group(1)], DIFF_TEST_DATA)
130            self.test_diff_parser(diff_parser.DiffParser(patch.splitlines()))
131
132    def test_git_diff_to_svn_diff(self):
133        output = """\
134Index: Tools/Scripts/webkitpy/common/checkout/diff_parser.py
135===================================================================
136--- Tools/Scripts/webkitpy/common/checkout/diff_parser.py
137+++ Tools/Scripts/webkitpy/common/checkout/diff_parser.py
138@@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line):
139 A
140 B
141 C
142+D
143 E
144 F
145"""
146
147        inputfmt = StringIO.StringIO("""\
148diff --git a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py
149index 2ed552c4555db72df16b212547f2c125ae301a04..72870482000c0dba64ce4300ed782c03ee79b74f 100644
150--- a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py
151+++ b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py
152@@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line):
153 A
154 B
155 C
156+D
157 E
158 F
159""")
160        shortfmt = StringIO.StringIO("""\
161diff --git a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py
162index b48b162..f300960 100644
163--- a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py
164+++ b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py
165@@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line):
166 A
167 B
168 C
169+D
170 E
171 F
172""")
173
174        self.assertMultiLineEqual(output, ''.join(diff_parser.git_diff_to_svn_diff(x) for x in shortfmt.readlines()))
175        self.assertMultiLineEqual(output, ''.join(diff_parser.git_diff_to_svn_diff(x) for x in inputfmt.readlines()))
176
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Puppeteer on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)