##// END OF EJS Templates
mpatch: proxy through mdiff module...
Yuya Nishihara -
r32202:0c73634d default
parent child Browse files
Show More
@@ -1,100 +1,99 b''
1 1 # Randomized torture test generation for bdiff
2 2
3 3 from __future__ import absolute_import, print_function
4 4 import random
5 5 import sys
6 6
7 7 from mercurial import (
8 8 mdiff,
9 mpatch,
10 9 )
11 10
12 11 def reducetest(a, b):
13 12 tries = 0
14 13 reductions = 0
15 14 print("reducing...")
16 15 while tries < 1000:
17 16 a2 = "\n".join(l for l in a.splitlines()
18 17 if random.randint(0, 100) > 0) + "\n"
19 18 b2 = "\n".join(l for l in b.splitlines()
20 19 if random.randint(0, 100) > 0) + "\n"
21 20 if a2 == a and b2 == b:
22 21 continue
23 22 if a2 == b2:
24 23 continue
25 24 tries += 1
26 25
27 26 try:
28 27 test1(a, b)
29 28 except Exception as inst:
30 29 reductions += 1
31 30 tries = 0
32 31 a = a2
33 32 b = b2
34 33
35 34 print("reduced:", reductions, len(a) + len(b),
36 35 repr(a), repr(b))
37 36 try:
38 37 test1(a, b)
39 38 except Exception as inst:
40 39 print("failed:", inst)
41 40
42 41 sys.exit(0)
43 42
44 43 def test1(a, b):
45 44 d = mdiff.textdiff(a, b)
46 45 if not d:
47 46 raise ValueError("empty")
48 c = mpatch.patches(a, [d])
47 c = mdiff.patches(a, [d])
49 48 if c != b:
50 49 raise ValueError("bad")
51 50
52 51 def testwrap(a, b):
53 52 try:
54 53 test1(a, b)
55 54 return
56 55 except Exception as inst:
57 56 pass
58 57 print("exception:", inst)
59 58 reducetest(a, b)
60 59
61 60 def test(a, b):
62 61 testwrap(a, b)
63 62 testwrap(b, a)
64 63
65 64 def rndtest(size, noise):
66 65 a = []
67 66 src = " aaaaaaaabbbbccd"
68 67 for x in xrange(size):
69 68 a.append(src[random.randint(0, len(src) - 1)])
70 69
71 70 while True:
72 71 b = [c for c in a if random.randint(0, 99) > noise]
73 72 b2 = []
74 73 for c in b:
75 74 b2.append(c)
76 75 while random.randint(0, 99) < noise:
77 76 b2.append(src[random.randint(0, len(src) - 1)])
78 77 if b2 != a:
79 78 break
80 79
81 80 a = "\n".join(a) + "\n"
82 81 b = "\n".join(b2) + "\n"
83 82
84 83 test(a, b)
85 84
86 85 maxvol = 10000
87 86 startsize = 2
88 87 while True:
89 88 size = startsize
90 89 count = 0
91 90 while size < maxvol:
92 91 print(size)
93 92 volume = 0
94 93 while volume < maxvol:
95 94 rndtest(size, 2)
96 95 volume += size
97 96 count += 2
98 97 size *= 2
99 98 maxvol *= 4
100 99 startsize *= 4
@@ -1,150 +1,149 b''
1 1 from __future__ import absolute_import, print_function
2 2 import collections
3 3 import struct
4 4 import unittest
5 5
6 6 from mercurial import (
7 7 mdiff,
8 mpatch,
9 8 )
10 9
11 10 class diffreplace(
12 11 collections.namedtuple('diffreplace', 'start end from_ to')):
13 12 def __repr__(self):
14 13 return 'diffreplace(%r, %r, %r, %r)' % self
15 14
16 15 class BdiffTests(unittest.TestCase):
17 16
18 17 def assert_bdiff_applies(self, a, b):
19 18 d = mdiff.textdiff(a, b)
20 19 c = a
21 20 if d:
22 c = mpatch.patches(a, [d])
21 c = mdiff.patches(a, [d])
23 22 self.assertEqual(
24 23 c, b, ("bad diff+patch result from\n %r to\n "
25 24 "%r: \nbdiff: %r\npatched: %r" % (a, b, d, c[:200])))
26 25
27 26 def assert_bdiff(self, a, b):
28 27 self.assert_bdiff_applies(a, b)
29 28 self.assert_bdiff_applies(b, a)
30 29
31 30 def test_bdiff_basic(self):
32 31 cases = [
33 32 ("a\nc\n\n\n\n", "a\nb\n\n\n"),
34 33 ("a\nb\nc\n", "a\nc\n"),
35 34 ("", ""),
36 35 ("a\nb\nc", "a\nb\nc"),
37 36 ("a\nb\nc\nd\n", "a\nd\n"),
38 37 ("a\nb\nc\nd\n", "a\nc\ne\n"),
39 38 ("a\nb\nc\n", "a\nc\n"),
40 39 ("a\n", "c\na\nb\n"),
41 40 ("a\n", ""),
42 41 ("a\n", "b\nc\n"),
43 42 ("a\n", "c\na\n"),
44 43 ("", "adjfkjdjksdhfksj"),
45 44 ("", "ab"),
46 45 ("", "abc"),
47 46 ("a", "a"),
48 47 ("ab", "ab"),
49 48 ("abc", "abc"),
50 49 ("a\n", "a\n"),
51 50 ("a\nb", "a\nb"),
52 51 ]
53 52 for a, b in cases:
54 53 self.assert_bdiff(a, b)
55 54
56 55 def showdiff(self, a, b):
57 56 bin = mdiff.textdiff(a, b)
58 57 pos = 0
59 58 q = 0
60 59 actions = []
61 60 while pos < len(bin):
62 61 p1, p2, l = struct.unpack(">lll", bin[pos:pos + 12])
63 62 pos += 12
64 63 if p1:
65 64 actions.append(a[q:p1])
66 65 actions.append(diffreplace(p1, p2, a[p1:p2], bin[pos:pos + l]))
67 66 pos += l
68 67 q = p2
69 68 if q < len(a):
70 69 actions.append(a[q:])
71 70 return actions
72 71
73 72 def test_issue1295(self):
74 73 cases = [
75 74 ("x\n\nx\n\nx\n\nx\n\nz\n", "x\n\nx\n\ny\n\nx\n\nx\n\nz\n",
76 75 ['x\n\nx\n\n', diffreplace(6, 6, '', 'y\n\n'), 'x\n\nx\n\nz\n']),
77 76 ("x\n\nx\n\nx\n\nx\n\nz\n", "x\n\nx\n\ny\n\nx\n\ny\n\nx\n\nz\n",
78 77 ['x\n\nx\n\n',
79 78 diffreplace(6, 6, '', 'y\n\n'),
80 79 'x\n\n',
81 80 diffreplace(9, 9, '', 'y\n\n'),
82 81 'x\n\nz\n']),
83 82 ]
84 83 for old, new, want in cases:
85 84 self.assertEqual(self.showdiff(old, new), want)
86 85
87 86 def test_issue1295_varies_on_pure(self):
88 87 # we should pick up abbbc. rather than bc.de as the longest match
89 88 got = self.showdiff("a\nb\nb\nb\nc\n.\nd\ne\n.\nf\n",
90 89 "a\nb\nb\na\nb\nb\nb\nc\n.\nb\nc\n.\nd\ne\nf\n")
91 90 want_c = ['a\nb\nb\n',
92 91 diffreplace(6, 6, '', 'a\nb\nb\nb\nc\n.\n'),
93 92 'b\nc\n.\nd\ne\n',
94 93 diffreplace(16, 18, '.\n', ''),
95 94 'f\n']
96 95 want_pure = [diffreplace(0, 0, '', 'a\nb\nb\n'),
97 96 'a\nb\nb\nb\nc\n.\n',
98 97 diffreplace(12, 12, '', 'b\nc\n.\n'),
99 98 'd\ne\n',
100 99 diffreplace(16, 18, '.\n', ''), 'f\n']
101 100 self.assert_(got in (want_c, want_pure),
102 101 'got: %r, wanted either %r or %r' % (
103 102 got, want_c, want_pure))
104 103
105 104 def test_fixws(self):
106 105 cases = [
107 106 (" \ta\r b\t\n", "ab\n", 1),
108 107 (" \ta\r b\t\n", " a b\n", 0),
109 108 ("", "", 1),
110 109 ("", "", 0),
111 110 ]
112 111 for a, b, allws in cases:
113 112 c = mdiff.fixws(a, allws)
114 113 self.assertEqual(
115 114 c, b, 'fixws(%r) want %r got %r (allws=%r)' % (a, b, c, allws))
116 115
117 116 def test_nice_diff_for_trivial_change(self):
118 117 self.assertEqual(self.showdiff(
119 118 ''.join('<%s\n-\n' % i for i in range(5)),
120 119 ''.join('>%s\n-\n' % i for i in range(5))),
121 120 [diffreplace(0, 3, '<0\n', '>0\n'),
122 121 '-\n',
123 122 diffreplace(5, 8, '<1\n', '>1\n'),
124 123 '-\n',
125 124 diffreplace(10, 13, '<2\n', '>2\n'),
126 125 '-\n',
127 126 diffreplace(15, 18, '<3\n', '>3\n'),
128 127 '-\n',
129 128 diffreplace(20, 23, '<4\n', '>4\n'),
130 129 '-\n'])
131 130
132 131 def test_prefer_appending(self):
133 132 # 1 line to 3 lines
134 133 self.assertEqual(self.showdiff('a\n', 'a\n' * 3),
135 134 ['a\n', diffreplace(2, 2, '', 'a\na\n')])
136 135 # 1 line to 5 lines
137 136 self.assertEqual(self.showdiff('a\n', 'a\n' * 5),
138 137 ['a\n', diffreplace(2, 2, '', 'a\na\na\na\n')])
139 138
140 139 def test_prefer_removing_trailing(self):
141 140 # 3 lines to 1 line
142 141 self.assertEqual(self.showdiff('a\n' * 3, 'a\n'),
143 142 ['a\n', diffreplace(2, 6, 'a\na\n', '')])
144 143 # 5 lines to 1 line
145 144 self.assertEqual(self.showdiff('a\n' * 5, 'a\n'),
146 145 ['a\n', diffreplace(2, 10, 'a\na\na\na\n', '')])
147 146
148 147 if __name__ == '__main__':
149 148 import silenttestrunner
150 149 silenttestrunner.main(__name__)
General Comments 0
You need to be logged in to leave comments. Login now