190
183
# XXX: Weird, using None instead of '' breaks the test -- vila 20101216
191
184
self.overrideEnv('PATH', '')
192
185
self.assertRaises(errors.NoDiff, diff.external_diff,
193
b'old', [b'boo\n'], b'new', [b'goo\n'],
186
'old', ['boo\n'], 'new', ['goo\n'],
194
187
BytesIO(), diff_opts=['-u'])
196
189
def test_internal_diff_default(self):
197
190
# Default internal diff encoding is utf8
198
191
output = BytesIO()
199
diff.internal_diff(u'old_\xb5', [b'old_text\n'],
200
u'new_\xe5', [b'new_text\n'], output)
192
diff.internal_diff(u'old_\xb5', ['old_text\n'],
193
u'new_\xe5', ['new_text\n'], output)
201
194
lines = output.getvalue().splitlines(True)
202
195
self.check_patch(lines)
203
self.assertEqual([b'--- old_\xc2\xb5\n',
204
b'+++ new_\xc3\xa5\n',
205
b'@@ -1,1 +1,1 @@\n',
196
self.assertEqual(['--- old_\xc2\xb5\n',
197
'+++ new_\xc3\xa5\n',
211
205
def test_internal_diff_utf8(self):
212
206
output = BytesIO()
213
diff.internal_diff(u'old_\xb5', [b'old_text\n'],
214
u'new_\xe5', [b'new_text\n'], output,
207
diff.internal_diff(u'old_\xb5', ['old_text\n'],
208
u'new_\xe5', ['new_text\n'], output,
215
209
path_encoding='utf8')
216
210
lines = output.getvalue().splitlines(True)
217
211
self.check_patch(lines)
218
self.assertEqual([b'--- old_\xc2\xb5\n',
219
b'+++ new_\xc3\xa5\n',
220
b'@@ -1,1 +1,1 @@\n',
212
self.assertEqual(['--- old_\xc2\xb5\n',
213
'+++ new_\xc3\xa5\n',
226
221
def test_internal_diff_iso_8859_1(self):
227
222
output = BytesIO()
228
diff.internal_diff(u'old_\xb5', [b'old_text\n'],
229
u'new_\xe5', [b'new_text\n'], output,
223
diff.internal_diff(u'old_\xb5', ['old_text\n'],
224
u'new_\xe5', ['new_text\n'], output,
230
225
path_encoding='iso-8859-1')
231
226
lines = output.getvalue().splitlines(True)
232
227
self.check_patch(lines)
233
self.assertEqual([b'--- old_\xb5\n',
235
b'@@ -1,1 +1,1 @@\n',
228
self.assertEqual(['--- old_\xb5\n',
241
237
def test_internal_diff_no_content(self):
242
238
output = BytesIO()
243
239
diff.internal_diff(u'old', [], u'new', [], output)
244
self.assertEqual(b'', output.getvalue())
240
self.assertEqual('', output.getvalue())
246
242
def test_internal_diff_no_changes(self):
247
243
output = BytesIO()
248
diff.internal_diff(u'old', [b'text\n', b'contents\n'],
249
u'new', [b'text\n', b'contents\n'],
244
diff.internal_diff(u'old', ['text\n', 'contents\n'],
245
u'new', ['text\n', 'contents\n'],
251
self.assertEqual(b'', output.getvalue())
247
self.assertEqual('', output.getvalue())
253
249
def test_internal_diff_returns_bytes(self):
255
diff.internal_diff(u'old_\xb5', [b'old_text\n'],
256
u'new_\xe5', [b'new_text\n'], output)
251
diff.internal_diff(u'old_\xb5', ['old_text\n'],
252
u'new_\xe5', ['new_text\n'], output)
257
253
output.check_types(self, bytes)
259
255
def test_internal_diff_default_context(self):
260
256
output = BytesIO()
261
diff.internal_diff('old', [b'same_text\n', b'same_text\n', b'same_text\n',
262
b'same_text\n', b'same_text\n', b'old_text\n'],
263
'new', [b'same_text\n', b'same_text\n', b'same_text\n',
264
b'same_text\n', b'same_text\n', b'new_text\n'], output)
257
diff.internal_diff('old', ['same_text\n', 'same_text\n', 'same_text\n',
258
'same_text\n', 'same_text\n', 'old_text\n'],
259
'new', ['same_text\n', 'same_text\n', 'same_text\n',
260
'same_text\n', 'same_text\n', 'new_text\n'], output)
265
261
lines = output.getvalue().splitlines(True)
266
262
self.check_patch(lines)
267
self.assertEqual([b'--- old\n',
269
b'@@ -3,4 +3,4 @@\n',
263
self.assertEqual(['--- old\n',
278
275
def test_internal_diff_no_context(self):
279
276
output = BytesIO()
280
diff.internal_diff('old', [b'same_text\n', b'same_text\n', b'same_text\n',
281
b'same_text\n', b'same_text\n', b'old_text\n'],
282
'new', [b'same_text\n', b'same_text\n', b'same_text\n',
283
b'same_text\n', b'same_text\n', b'new_text\n'], output,
277
diff.internal_diff('old', ['same_text\n', 'same_text\n', 'same_text\n',
278
'same_text\n', 'same_text\n', 'old_text\n'],
279
'new', ['same_text\n', 'same_text\n', 'same_text\n',
280
'same_text\n', 'same_text\n', 'new_text\n'], output,
285
282
lines = output.getvalue().splitlines(True)
286
283
self.check_patch(lines)
287
self.assertEqual([b'--- old\n',
289
b'@@ -6,1 +6,1 @@\n',
284
self.assertEqual(['--- old\n',
295
293
def test_internal_diff_more_context(self):
296
294
output = BytesIO()
297
diff.internal_diff('old', [b'same_text\n', b'same_text\n', b'same_text\n',
298
b'same_text\n', b'same_text\n', b'old_text\n'],
299
'new', [b'same_text\n', b'same_text\n', b'same_text\n',
300
b'same_text\n', b'same_text\n', b'new_text\n'], output,
295
diff.internal_diff('old', ['same_text\n', 'same_text\n', 'same_text\n',
296
'same_text\n', 'same_text\n', 'old_text\n'],
297
'new', ['same_text\n', 'same_text\n', 'same_text\n',
298
'same_text\n', 'same_text\n', 'new_text\n'], output,
302
300
lines = output.getvalue().splitlines(True)
303
301
self.check_patch(lines)
304
self.assertEqual([b'--- old\n',
306
b'@@ -2,5 +2,5 @@\n',
302
self.assertEqual(['--- old\n',
317
319
class TestDiffFiles(tests.TestCaseInTempDir):
862
864
self.old_tree.add('b-file')
863
865
self.differ.show_diff(None)
864
866
self.assertContainsRe(self.differ.to_file.getvalue(),
865
b'.*a-file(.|\n)*b-file')
867
'.*a-file(.|\n)*b-file')
870
class TestPatienceDiffLib(tests.TestCase):
873
super(TestPatienceDiffLib, self).setUp()
874
self._unique_lcs = _patiencediff_py.unique_lcs_py
875
self._recurse_matches = _patiencediff_py.recurse_matches_py
876
self._PatienceSequenceMatcher = \
877
_patiencediff_py.PatienceSequenceMatcher_py
879
def test_diff_unicode_string(self):
880
a = ''.join([unichr(i) for i in range(4000, 4500, 3)])
881
b = ''.join([unichr(i) for i in range(4300, 4800, 2)])
882
sm = self._PatienceSequenceMatcher(None, a, b)
883
mb = sm.get_matching_blocks()
884
self.assertEqual(35, len(mb))
886
def test_unique_lcs(self):
887
unique_lcs = self._unique_lcs
888
self.assertEqual(unique_lcs('', ''), [])
889
self.assertEqual(unique_lcs('', 'a'), [])
890
self.assertEqual(unique_lcs('a', ''), [])
891
self.assertEqual(unique_lcs('a', 'a'), [(0, 0)])
892
self.assertEqual(unique_lcs('a', 'b'), [])
893
self.assertEqual(unique_lcs('ab', 'ab'), [(0, 0), (1, 1)])
894
self.assertEqual(unique_lcs('abcde', 'cdeab'), [(2, 0), (3, 1), (4, 2)])
895
self.assertEqual(unique_lcs('cdeab', 'abcde'), [(0, 2), (1, 3), (2, 4)])
896
self.assertEqual(unique_lcs('abXde', 'abYde'), [(0, 0), (1, 1),
898
self.assertEqual(unique_lcs('acbac', 'abc'), [(2, 1)])
900
def test_recurse_matches(self):
901
def test_one(a, b, matches):
903
self._recurse_matches(
904
a, b, 0, 0, len(a), len(b), test_matches, 10)
905
self.assertEqual(test_matches, matches)
907
test_one(['a', '', 'b', '', 'c'], ['a', 'a', 'b', 'c', 'c'],
908
[(0, 0), (2, 2), (4, 4)])
909
test_one(['a', 'c', 'b', 'a', 'c'], ['a', 'b', 'c'],
910
[(0, 0), (2, 1), (4, 2)])
911
# Even though 'bc' is not unique globally, and is surrounded by
912
# non-matching lines, we should still match, because they are locally
914
test_one('abcdbce', 'afbcgdbce', [(0, 0), (1, 2), (2, 3), (3, 5),
915
(4, 6), (5, 7), (6, 8)])
917
# recurse_matches doesn't match non-unique
918
# lines surrounded by bogus text.
919
# The update has been done in patiencediff.SequenceMatcher instead
921
# This is what it could be
922
#test_one('aBccDe', 'abccde', [(0,0), (2,2), (3,3), (5,5)])
924
# This is what it currently gives:
925
test_one('aBccDe', 'abccde', [(0, 0), (5, 5)])
927
def assertDiffBlocks(self, a, b, expected_blocks):
928
"""Check that the sequence matcher returns the correct blocks.
930
:param a: A sequence to match
931
:param b: Another sequence to match
932
:param expected_blocks: The expected output, not including the final
933
matching block (len(a), len(b), 0)
935
matcher = self._PatienceSequenceMatcher(None, a, b)
936
blocks = matcher.get_matching_blocks()
938
self.assertEqual((len(a), len(b), 0), last)
939
self.assertEqual(expected_blocks, blocks)
941
def test_matching_blocks(self):
942
# Some basic matching tests
943
self.assertDiffBlocks('', '', [])
944
self.assertDiffBlocks([], [], [])
945
self.assertDiffBlocks('abc', '', [])
946
self.assertDiffBlocks('', 'abc', [])
947
self.assertDiffBlocks('abcd', 'abcd', [(0, 0, 4)])
948
self.assertDiffBlocks('abcd', 'abce', [(0, 0, 3)])
949
self.assertDiffBlocks('eabc', 'abce', [(1, 0, 3)])
950
self.assertDiffBlocks('eabce', 'abce', [(1, 0, 4)])
951
self.assertDiffBlocks('abcde', 'abXde', [(0, 0, 2), (3, 3, 2)])
952
self.assertDiffBlocks('abcde', 'abXYZde', [(0, 0, 2), (3, 5, 2)])
953
self.assertDiffBlocks('abde', 'abXYZde', [(0, 0, 2), (2, 5, 2)])
954
# This may check too much, but it checks to see that
955
# a copied block stays attached to the previous section,
957
# difflib would tend to grab the trailing longest match
958
# which would make the diff not look right
959
self.assertDiffBlocks('abcdefghijklmnop', 'abcdefxydefghijklmnop',
960
[(0, 0, 6), (6, 11, 10)])
962
# make sure it supports passing in lists
963
self.assertDiffBlocks(
966
'how are you today?\n'],
968
'how are you today?\n'],
969
[(0, 0, 1), (2, 1, 1)])
971
# non unique lines surrounded by non-matching lines
973
self.assertDiffBlocks('aBccDe', 'abccde', [(0, 0, 1), (5, 5, 1)])
975
# But they only need to be locally unique
976
self.assertDiffBlocks('aBcDec', 'abcdec', [(0, 0, 1), (2, 2, 1), (4, 4, 2)])
978
# non unique blocks won't be matched
979
self.assertDiffBlocks('aBcdEcdFg', 'abcdecdfg', [(0, 0, 1), (8, 8, 1)])
981
# but locally unique ones will
982
self.assertDiffBlocks('aBcdEeXcdFg', 'abcdecdfg', [(0, 0, 1), (2, 2, 2),
983
(5, 4, 1), (7, 5, 2), (10, 8, 1)])
985
self.assertDiffBlocks('abbabbXd', 'cabbabxd', [(7, 7, 1)])
986
self.assertDiffBlocks('abbabbbb', 'cabbabbc', [])
987
self.assertDiffBlocks('bbbbbbbb', 'cbbbbbbc', [])
989
def test_matching_blocks_tuples(self):
990
# Some basic matching tests
991
self.assertDiffBlocks([], [], [])
992
self.assertDiffBlocks([('a',), ('b',), ('c,')], [], [])
993
self.assertDiffBlocks([], [('a',), ('b',), ('c,')], [])
994
self.assertDiffBlocks([('a',), ('b',), ('c,')],
995
[('a',), ('b',), ('c,')],
997
self.assertDiffBlocks([('a',), ('b',), ('c,')],
998
[('a',), ('b',), ('d,')],
1000
self.assertDiffBlocks([('d',), ('b',), ('c,')],
1001
[('a',), ('b',), ('c,')],
1003
self.assertDiffBlocks([('d',), ('a',), ('b',), ('c,')],
1004
[('a',), ('b',), ('c,')],
1006
self.assertDiffBlocks([('a', 'b'), ('c', 'd'), ('e', 'f')],
1007
[('a', 'b'), ('c', 'X'), ('e', 'f')],
1008
[(0, 0, 1), (2, 2, 1)])
1009
self.assertDiffBlocks([('a', 'b'), ('c', 'd'), ('e', 'f')],
1010
[('a', 'b'), ('c', 'dX'), ('e', 'f')],
1011
[(0, 0, 1), (2, 2, 1)])
1013
def test_opcodes(self):
1014
def chk_ops(a, b, expected_codes):
1015
s = self._PatienceSequenceMatcher(None, a, b)
1016
self.assertEqual(expected_codes, s.get_opcodes())
1020
chk_ops('abc', '', [('delete', 0, 3, 0, 0)])
1021
chk_ops('', 'abc', [('insert', 0, 0, 0, 3)])
1022
chk_ops('abcd', 'abcd', [('equal', 0, 4, 0, 4)])
1023
chk_ops('abcd', 'abce', [('equal', 0, 3, 0, 3),
1024
('replace', 3, 4, 3, 4)
1026
chk_ops('eabc', 'abce', [('delete', 0, 1, 0, 0),
1027
('equal', 1, 4, 0, 3),
1028
('insert', 4, 4, 3, 4)
1030
chk_ops('eabce', 'abce', [('delete', 0, 1, 0, 0),
1031
('equal', 1, 5, 0, 4)
1033
chk_ops('abcde', 'abXde', [('equal', 0, 2, 0, 2),
1034
('replace', 2, 3, 2, 3),
1035
('equal', 3, 5, 3, 5)
1037
chk_ops('abcde', 'abXYZde', [('equal', 0, 2, 0, 2),
1038
('replace', 2, 3, 2, 5),
1039
('equal', 3, 5, 5, 7)
1041
chk_ops('abde', 'abXYZde', [('equal', 0, 2, 0, 2),
1042
('insert', 2, 2, 2, 5),
1043
('equal', 2, 4, 5, 7)
1045
chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
1046
[('equal', 0, 6, 0, 6),
1047
('insert', 6, 6, 6, 11),
1048
('equal', 6, 16, 11, 21)
1053
, 'how are you today?\n'],
1055
, 'how are you today?\n'],
1056
[('equal', 0, 1, 0, 1),
1057
('delete', 1, 2, 1, 1),
1058
('equal', 2, 3, 1, 2),
1060
chk_ops('aBccDe', 'abccde',
1061
[('equal', 0, 1, 0, 1),
1062
('replace', 1, 5, 1, 5),
1063
('equal', 5, 6, 5, 6),
1065
chk_ops('aBcDec', 'abcdec',
1066
[('equal', 0, 1, 0, 1),
1067
('replace', 1, 2, 1, 2),
1068
('equal', 2, 3, 2, 3),
1069
('replace', 3, 4, 3, 4),
1070
('equal', 4, 6, 4, 6),
1072
chk_ops('aBcdEcdFg', 'abcdecdfg',
1073
[('equal', 0, 1, 0, 1),
1074
('replace', 1, 8, 1, 8),
1075
('equal', 8, 9, 8, 9)
1077
chk_ops('aBcdEeXcdFg', 'abcdecdfg',
1078
[('equal', 0, 1, 0, 1),
1079
('replace', 1, 2, 1, 2),
1080
('equal', 2, 4, 2, 4),
1081
('delete', 4, 5, 4, 4),
1082
('equal', 5, 6, 4, 5),
1083
('delete', 6, 7, 5, 5),
1084
('equal', 7, 9, 5, 7),
1085
('replace', 9, 10, 7, 8),
1086
('equal', 10, 11, 8, 9)
1089
def test_grouped_opcodes(self):
1090
def chk_ops(a, b, expected_codes, n=3):
1091
s = self._PatienceSequenceMatcher(None, a, b)
1092
self.assertEqual(expected_codes, list(s.get_grouped_opcodes(n)))
1096
chk_ops('abc', '', [[('delete', 0, 3, 0, 0)]])
1097
chk_ops('', 'abc', [[('insert', 0, 0, 0, 3)]])
1098
chk_ops('abcd', 'abcd', [])
1099
chk_ops('abcd', 'abce', [[('equal', 0, 3, 0, 3),
1100
('replace', 3, 4, 3, 4)
1102
chk_ops('eabc', 'abce', [[('delete', 0, 1, 0, 0),
1103
('equal', 1, 4, 0, 3),
1104
('insert', 4, 4, 3, 4)
1106
chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
1107
[[('equal', 3, 6, 3, 6),
1108
('insert', 6, 6, 6, 11),
1109
('equal', 6, 9, 11, 14)
1111
chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
1112
[[('equal', 2, 6, 2, 6),
1113
('insert', 6, 6, 6, 11),
1114
('equal', 6, 10, 11, 15)
1116
chk_ops('Xabcdef', 'abcdef',
1117
[[('delete', 0, 1, 0, 0),
1118
('equal', 1, 4, 0, 3)
1120
chk_ops('abcdef', 'abcdefX',
1121
[[('equal', 3, 6, 3, 6),
1122
('insert', 6, 6, 6, 7)
1126
def test_multiple_ranges(self):
1127
# There was an earlier bug where we used a bad set of ranges,
1128
# this triggers that specific bug, to make sure it doesn't regress
1129
self.assertDiffBlocks('abcdefghijklmnop',
1130
'abcXghiYZQRSTUVWXYZijklmnop',
1131
[(0, 0, 3), (6, 4, 3), (9, 20, 7)])
1133
self.assertDiffBlocks('ABCd efghIjk L',
1134
'AxyzBCn mo pqrstuvwI1 2 L',
1135
[(0, 0, 1), (1, 4, 2), (9, 19, 1), (12, 23, 3)])
1137
# These are rot13 code snippets.
1138
self.assertDiffBlocks('''\
1139
trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
1141
gnxrf_netf = ['svyr*']
1142
gnxrf_bcgvbaf = ['ab-erphefr']
1144
qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr):
1145
sebz omeyvo.nqq vzcbeg fzneg_nqq, nqq_ercbegre_cevag, nqq_ercbegre_ahyy
1147
ercbegre = nqq_ercbegre_ahyy
1149
ercbegre = nqq_ercbegre_cevag
1150
fzneg_nqq(svyr_yvfg, abg ab_erphefr, ercbegre)
1153
pynff pzq_zxqve(Pbzznaq):
1154
'''.splitlines(True), '''\
1155
trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
1157
--qel-eha jvyy fubj juvpu svyrf jbhyq or nqqrq, ohg abg npghnyyl
1160
gnxrf_netf = ['svyr*']
1161
gnxrf_bcgvbaf = ['ab-erphefr', 'qel-eha']
1163
qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr, qel_eha=Snyfr):
1168
# Guvf vf cbvagyrff, ohg V'q engure abg envfr na reebe
1169
npgvba = omeyvo.nqq.nqq_npgvba_ahyy
1171
npgvba = omeyvo.nqq.nqq_npgvba_cevag
1173
npgvba = omeyvo.nqq.nqq_npgvba_nqq
1175
npgvba = omeyvo.nqq.nqq_npgvba_nqq_naq_cevag
1177
omeyvo.nqq.fzneg_nqq(svyr_yvfg, abg ab_erphefr, npgvba)
1180
pynff pzq_zxqve(Pbzznaq):
1181
'''.splitlines(True)
1182
, [(0, 0, 1), (1, 4, 2), (9, 19, 1), (12, 23, 3)])
1184
def test_patience_unified_diff(self):
1185
txt_a = ['hello there\n',
1187
'how are you today?\n']
1188
txt_b = ['hello there\n',
1189
'how are you today?\n']
1190
unified_diff = patiencediff.unified_diff
1191
psm = self._PatienceSequenceMatcher
1192
self.assertEqual(['--- \n',
1194
'@@ -1,3 +1,2 @@\n',
1197
' how are you today?\n'
1199
, list(unified_diff(txt_a, txt_b,
1200
sequencematcher=psm)))
1201
txt_a = [x+'\n' for x in 'abcdefghijklmnop']
1202
txt_b = [x+'\n' for x in 'abcdefxydefghijklmnop']
1203
# This is the result with LongestCommonSubstring matching
1204
self.assertEqual(['--- \n',
1206
'@@ -1,6 +1,11 @@\n',
1218
, list(unified_diff(txt_a, txt_b)))
1219
# And the patience diff
1220
self.assertEqual(['--- \n',
1222
'@@ -4,6 +4,11 @@\n',
1235
, list(unified_diff(txt_a, txt_b,
1236
sequencematcher=psm)))
1238
def test_patience_unified_diff_with_dates(self):
1239
txt_a = ['hello there\n',
1241
'how are you today?\n']
1242
txt_b = ['hello there\n',
1243
'how are you today?\n']
1244
unified_diff = patiencediff.unified_diff
1245
psm = self._PatienceSequenceMatcher
1246
self.assertEqual(['--- a\t2008-08-08\n',
1247
'+++ b\t2008-09-09\n',
1248
'@@ -1,3 +1,2 @@\n',
1251
' how are you today?\n'
1253
, list(unified_diff(txt_a, txt_b,
1254
fromfile='a', tofile='b',
1255
fromfiledate='2008-08-08',
1256
tofiledate='2008-09-09',
1257
sequencematcher=psm)))
1260
class TestPatienceDiffLib_c(TestPatienceDiffLib):
1262
_test_needs_features = [features.compiled_patiencediff_feature]
1265
super(TestPatienceDiffLib_c, self).setUp()
1266
from breezy import _patiencediff_c
1267
self._unique_lcs = _patiencediff_c.unique_lcs_c
1268
self._recurse_matches = _patiencediff_c.recurse_matches_c
1269
self._PatienceSequenceMatcher = \
1270
_patiencediff_c.PatienceSequenceMatcher_c
1272
def test_unhashable(self):
1273
"""We should get a proper exception here."""
1274
# We need to be able to hash items in the sequence, lists are
1275
# unhashable, and thus cannot be diffed
1276
e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1278
e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1279
None, ['valid', []], [])
1280
e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1281
None, ['valid'], [[]])
1282
e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1283
None, ['valid'], ['valid', []])
1286
class TestPatienceDiffLibFiles(tests.TestCaseInTempDir):
1289
super(TestPatienceDiffLibFiles, self).setUp()
1290
self._PatienceSequenceMatcher = \
1291
_patiencediff_py.PatienceSequenceMatcher_py
1293
def test_patience_unified_diff_files(self):
1294
txt_a = ['hello there\n',
1296
'how are you today?\n']
1297
txt_b = ['hello there\n',
1298
'how are you today?\n']
1299
with open('a1', 'wb') as f: f.writelines(txt_a)
1300
with open('b1', 'wb') as f: f.writelines(txt_b)
1302
unified_diff_files = patiencediff.unified_diff_files
1303
psm = self._PatienceSequenceMatcher
1304
self.assertEqual(['--- a1\n',
1306
'@@ -1,3 +1,2 @@\n',
1309
' how are you today?\n',
1311
, list(unified_diff_files('a1', 'b1',
1312
sequencematcher=psm)))
1314
txt_a = [x+'\n' for x in 'abcdefghijklmnop']
1315
txt_b = [x+'\n' for x in 'abcdefxydefghijklmnop']
1316
with open('a2', 'wb') as f: f.writelines(txt_a)
1317
with open('b2', 'wb') as f: f.writelines(txt_b)
1319
# This is the result with LongestCommonSubstring matching
1320
self.assertEqual(['--- a2\n',
1322
'@@ -1,6 +1,11 @@\n',
1334
, list(unified_diff_files('a2', 'b2')))
1336
# And the patience diff
1337
self.assertEqual(['--- a2\n',
1339
'@@ -4,6 +4,11 @@\n',
1351
list(unified_diff_files('a2', 'b2',
1352
sequencematcher=psm)))
1355
class TestPatienceDiffLibFiles_c(TestPatienceDiffLibFiles):
1357
_test_needs_features = [features.compiled_patiencediff_feature]
1360
super(TestPatienceDiffLibFiles_c, self).setUp()
1361
from breezy import _patiencediff_c
1362
self._PatienceSequenceMatcher = \
1363
_patiencediff_c.PatienceSequenceMatcher_c
1366
class TestUsingCompiledIfAvailable(tests.TestCase):
1368
def test_PatienceSequenceMatcher(self):
1369
if features.compiled_patiencediff_feature.available():
1370
from breezy._patiencediff_c import PatienceSequenceMatcher_c
1371
self.assertIs(PatienceSequenceMatcher_c,
1372
patiencediff.PatienceSequenceMatcher)
1374
from breezy._patiencediff_py import PatienceSequenceMatcher_py
1375
self.assertIs(PatienceSequenceMatcher_py,
1376
patiencediff.PatienceSequenceMatcher)
1378
def test_unique_lcs(self):
1379
if features.compiled_patiencediff_feature.available():
1380
from breezy._patiencediff_c import unique_lcs_c
1381
self.assertIs(unique_lcs_c,
1382
patiencediff.unique_lcs)
1384
from breezy._patiencediff_py import unique_lcs_py
1385
self.assertIs(unique_lcs_py,
1386
patiencediff.unique_lcs)
1388
def test_recurse_matches(self):
1389
if features.compiled_patiencediff_feature.available():
1390
from breezy._patiencediff_c import recurse_matches_c
1391
self.assertIs(recurse_matches_c,
1392
patiencediff.recurse_matches)
1394
from breezy._patiencediff_py import recurse_matches_py
1395
self.assertIs(recurse_matches_py,
1396
patiencediff.recurse_matches)
868
1399
class TestDiffFromTool(tests.TestCaseWithTransport):
870
1401
def test_from_string(self):
871
diff_obj = diff.DiffFromTool.from_string(
872
['diff', '{old_path}', '{new_path}'],
874
self.addCleanup(diff_obj.finish)
875
self.assertEqual(['diff', '{old_path}', '{new_path}'],
876
diff_obj.command_template)
878
def test_from_string_no_paths(self):
879
diff_obj = diff.DiffFromTool.from_string(
880
['diff', "-u5"], None, None, None)
881
self.addCleanup(diff_obj.finish)
882
self.assertEqual(['diff', '-u5'],
883
diff_obj.command_template)
884
self.assertEqual(['diff', '-u5', 'old-path', 'new-path'],
885
diff_obj._get_command('old-path', 'new-path'))
1402
diff_obj = diff.DiffFromTool.from_string('diff', None, None, None)
1403
self.addCleanup(diff_obj.finish)
1404
self.assertEqual(['diff', '@old_path', '@new_path'],
1405
diff_obj.command_template)
887
1407
def test_from_string_u5(self):
888
diff_obj = diff.DiffFromTool.from_string(
889
['diff', "-u 5", '{old_path}', '{new_path}'], None, None, None)
1408
diff_obj = diff.DiffFromTool.from_string('diff "-u 5"',
890
1410
self.addCleanup(diff_obj.finish)
891
self.assertEqual(['diff', '-u 5', '{old_path}', '{new_path}'],
1411
self.assertEqual(['diff', '-u 5', '@old_path', '@new_path'],
892
1412
diff_obj.command_template)
893
1413
self.assertEqual(['diff', '-u 5', 'old-path', 'new-path'],
894
1414
diff_obj._get_command('old-path', 'new-path'))
896
1416
def test_from_string_path_with_backslashes(self):
897
1417
self.requireFeature(features.backslashdir_feature)
898
tool = ['C:\\Tools\\Diff.exe', '{old_path}', '{new_path}']
1418
tool = 'C:\\Tools\\Diff.exe'
899
1419
diff_obj = diff.DiffFromTool.from_string(tool, None, None, None)
900
1420
self.addCleanup(diff_obj.finish)
901
self.assertEqual(['C:\\Tools\\Diff.exe', '{old_path}', '{new_path}'],
1421
self.assertEqual(['C:\\Tools\\Diff.exe', '@old_path', '@new_path'],
902
1422
diff_obj.command_template)
903
1423
self.assertEqual(['C:\\Tools\\Diff.exe', 'old-path', 'new-path'],
904
1424
diff_obj._get_command('old-path', 'new-path'))
906
1426
def test_execute(self):
907
1427
output = BytesIO()
908
diff_obj = diff.DiffFromTool([sys.executable, '-c',
909
'print("{old_path} {new_path}")'],
1428
diff_obj = diff.DiffFromTool(['python', '-c',
1429
'print "@old_path @new_path"'],
910
1430
None, None, output)
911
1431
self.addCleanup(diff_obj.finish)
912
1432
diff_obj._execute('old', 'new')
913
self.assertEqual(output.getvalue().rstrip(), b'old new')
1433
self.assertEqual(output.getvalue().rstrip(), 'old new')
915
1435
def test_execute_missing(self):
916
1436
diff_obj = diff.DiffFromTool(['a-tool-which-is-unlikely-to-exist'],