~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_diff.py

  • Committer: Ross Lagerwall
  • Date: 2012-08-07 06:32:51 UTC
  • mto: (6437.63.5 2.5)
  • mto: This revision was merged to the branch mainline in revision 6558.
  • Revision ID: rosslagerwall@gmail.com-20120807063251-x9p03ghg2ws8oqjc
Add bzrlib/locale to .bzrignore

bzrlib/locale is generated with ./setup.py build_mo which is in turn called
by ./setup.py build

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2012, 2014, 2016 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
17
17
import os
18
18
from cStringIO import StringIO
19
19
import subprocess
 
20
import sys
20
21
import tempfile
21
22
 
22
23
from bzrlib import (
31
32
    tests,
32
33
    transform,
33
34
    )
 
35
from bzrlib.symbol_versioning import deprecated_in
 
36
from bzrlib.tests import features, EncodingAdapter
 
37
from bzrlib.tests.blackbox.test_diff import subst_dates
34
38
from bzrlib.tests import (
35
39
    features,
36
 
    EncodingAdapter,
37
 
)
38
 
from bzrlib.tests.blackbox.test_diff import subst_dates
39
 
from bzrlib.tests.scenarios import load_tests_apply_scenarios
40
 
 
41
 
 
42
 
load_tests = load_tests_apply_scenarios
 
40
    )
43
41
 
44
42
 
45
43
def udiff_lines(old, new, allow_binary=False):
65
63
    return lines
66
64
 
67
65
 
68
 
class TestDiffOptions(tests.TestCase):
69
 
 
70
 
    def test_unified_added(self):
71
 
        """Check for default style '-u' only if no other style specified
72
 
        in 'diff-options'.
73
 
        """
74
 
        # Verify that style defaults to unified, id est '-u' appended
75
 
        # to option list, in the absence of an alternative style.
76
 
        self.assertEqual(['-a', '-u'], diff.default_style_unified(['-a']))
77
 
 
78
 
 
79
 
class TestDiffOptionsScenarios(tests.TestCase):
80
 
 
81
 
    scenarios = [(s, dict(style=s)) for s in diff.style_option_list]
82
 
    style = None # Set by load_tests_apply_scenarios from scenarios
83
 
 
84
 
    def test_unified_not_added(self):
85
 
        # Verify that for all valid style options, '-u' is not
86
 
        # appended to option list.
87
 
        ret_opts = diff.default_style_unified(diff_opts=["%s" % (self.style,)])
88
 
        self.assertEqual(["%s" % (self.style,)], ret_opts)
89
 
 
90
 
 
91
66
class TestDiff(tests.TestCase):
92
67
 
93
68
    def test_add_nl(self):
94
69
        """diff generates a valid diff for patches that add a newline"""
95
70
        lines = udiff_lines(['boo'], ['boo\n'])
96
71
        self.check_patch(lines)
97
 
        self.assertEqual(lines[4], '\\ No newline at end of file\n')
 
72
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
98
73
            ## "expected no-nl, got %r" % lines[4]
99
74
 
100
75
    def test_add_nl_2(self):
103
78
        """
104
79
        lines = udiff_lines(['boo'], ['goo\n'])
105
80
        self.check_patch(lines)
106
 
        self.assertEqual(lines[4], '\\ No newline at end of file\n')
 
81
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
107
82
            ## "expected no-nl, got %r" % lines[4]
108
83
 
109
84
    def test_remove_nl(self):
112
87
        """
113
88
        lines = udiff_lines(['boo\n'], ['boo'])
114
89
        self.check_patch(lines)
115
 
        self.assertEqual(lines[5], '\\ No newline at end of file\n')
 
90
        self.assertEquals(lines[5], '\\ No newline at end of file\n')
116
91
            ## "expected no-nl, got %r" % lines[5]
117
92
 
118
93
    def check_patch(self, lines):
119
 
        self.assertTrue(len(lines) > 1)
 
94
        self.assert_(len(lines) > 1)
120
95
            ## "Not enough lines for a file header for patch:\n%s" % "".join(lines)
121
 
        self.assertTrue(lines[0].startswith ('---'))
 
96
        self.assert_(lines[0].startswith ('---'))
122
97
            ## 'No orig line for patch:\n%s' % "".join(lines)
123
 
        self.assertTrue(lines[1].startswith ('+++'))
 
98
        self.assert_(lines[1].startswith ('+++'))
124
99
            ## 'No mod line for patch:\n%s' % "".join(lines)
125
 
        self.assertTrue(len(lines) > 2)
 
100
        self.assert_(len(lines) > 2)
126
101
            ## "No hunks for patch:\n%s" % "".join(lines)
127
 
        self.assertTrue(lines[2].startswith('@@'))
 
102
        self.assert_(lines[2].startswith('@@'))
128
103
            ## "No hunk header for patch:\n%s" % "".join(lines)
129
 
        self.assertTrue('@@' in lines[2][2:])
 
104
        self.assert_('@@' in lines[2][2:])
130
105
            ## "Unterminated hunk header for patch:\n%s" % "".join(lines)
131
106
 
132
107
    def test_binary_lines(self):
157
132
        # Older versions of diffutils say "Binary files", newer
158
133
        # versions just say "Files".
159
134
        self.assertContainsRe(lines[0], '(Binary f|F)iles old and new differ\n')
160
 
        self.assertEqual(lines[1:], ['\n'])
 
135
        self.assertEquals(lines[1:], ['\n'])
161
136
 
162
137
    def test_no_external_diff(self):
163
138
        """Check that NoDiff is raised when diff is not available"""
175
150
                           u'new_\xe5', ['new_text\n'], output)
176
151
        lines = output.getvalue().splitlines(True)
177
152
        self.check_patch(lines)
178
 
        self.assertEqual(['--- old_\xc2\xb5\n',
 
153
        self.assertEquals(['--- old_\xc2\xb5\n',
179
154
                           '+++ new_\xc3\xa5\n',
180
155
                           '@@ -1,1 +1,1 @@\n',
181
156
                           '-old_text\n',
191
166
                           path_encoding='utf8')
192
167
        lines = output.getvalue().splitlines(True)
193
168
        self.check_patch(lines)
194
 
        self.assertEqual(['--- old_\xc2\xb5\n',
 
169
        self.assertEquals(['--- old_\xc2\xb5\n',
195
170
                           '+++ new_\xc3\xa5\n',
196
171
                           '@@ -1,1 +1,1 @@\n',
197
172
                           '-old_text\n',
207
182
                           path_encoding='iso-8859-1')
208
183
        lines = output.getvalue().splitlines(True)
209
184
        self.check_patch(lines)
210
 
        self.assertEqual(['--- old_\xb5\n',
 
185
        self.assertEquals(['--- old_\xb5\n',
211
186
                           '+++ new_\xe5\n',
212
187
                           '@@ -1,1 +1,1 @@\n',
213
188
                           '-old_text\n',
236
211
        self.assertIsInstance(output.getvalue(), str,
237
212
            'internal_diff should return bytestrings')
238
213
 
239
 
    def test_internal_diff_default_context(self):
240
 
        output = StringIO()
241
 
        diff.internal_diff('old', ['same_text\n','same_text\n','same_text\n',
242
 
                           'same_text\n','same_text\n','old_text\n'],
243
 
                           'new', ['same_text\n','same_text\n','same_text\n',
244
 
                           'same_text\n','same_text\n','new_text\n'], output)
245
 
        lines = output.getvalue().splitlines(True)
246
 
        self.check_patch(lines)
247
 
        self.assertEqual(['--- old\n',
248
 
                           '+++ new\n',
249
 
                           '@@ -3,4 +3,4 @@\n',
250
 
                           ' same_text\n',
251
 
                           ' same_text\n',
252
 
                           ' same_text\n',
253
 
                           '-old_text\n',
254
 
                           '+new_text\n',
255
 
                           '\n',
256
 
                          ]
257
 
                          , lines)
258
 
 
259
 
    def test_internal_diff_no_context(self):
260
 
        output = StringIO()
261
 
        diff.internal_diff('old', ['same_text\n','same_text\n','same_text\n',
262
 
                           'same_text\n','same_text\n','old_text\n'],
263
 
                           'new', ['same_text\n','same_text\n','same_text\n',
264
 
                           'same_text\n','same_text\n','new_text\n'], output,
265
 
                           context_lines=0)
266
 
        lines = output.getvalue().splitlines(True)
267
 
        self.check_patch(lines)
268
 
        self.assertEqual(['--- old\n',
269
 
                           '+++ new\n',
270
 
                           '@@ -6,1 +6,1 @@\n',
271
 
                           '-old_text\n',
272
 
                           '+new_text\n',
273
 
                           '\n',
274
 
                          ]
275
 
                          , lines)
276
 
 
277
 
    def test_internal_diff_more_context(self):
278
 
        output = StringIO()
279
 
        diff.internal_diff('old', ['same_text\n','same_text\n','same_text\n',
280
 
                           'same_text\n','same_text\n','old_text\n'],
281
 
                           'new', ['same_text\n','same_text\n','same_text\n',
282
 
                           'same_text\n','same_text\n','new_text\n'], output,
283
 
                           context_lines=4)
284
 
        lines = output.getvalue().splitlines(True)
285
 
        self.check_patch(lines)
286
 
        self.assertEqual(['--- old\n',
287
 
                           '+++ new\n',
288
 
                           '@@ -2,5 +2,5 @@\n',
289
 
                           ' same_text\n',
290
 
                           ' same_text\n',
291
 
                           ' same_text\n',
292
 
                           ' same_text\n',
293
 
                           '-old_text\n',
294
 
                           '+new_text\n',
295
 
                           '\n',
296
 
                          ]
297
 
                          , lines)
298
 
 
299
 
 
300
 
 
301
 
 
302
214
 
303
215
class TestDiffFiles(tests.TestCaseInTempDir):
304
216
 
864
776
        b = ''.join([unichr(i) for i in range(4300, 4800, 2)])
865
777
        sm = self._PatienceSequenceMatcher(None, a, b)
866
778
        mb = sm.get_matching_blocks()
867
 
        self.assertEqual(35, len(mb))
 
779
        self.assertEquals(35, len(mb))
868
780
 
869
781
    def test_unique_lcs(self):
870
782
        unique_lcs = self._unique_lcs
871
 
        self.assertEqual(unique_lcs('', ''), [])
872
 
        self.assertEqual(unique_lcs('', 'a'), [])
873
 
        self.assertEqual(unique_lcs('a', ''), [])
874
 
        self.assertEqual(unique_lcs('a', 'a'), [(0,0)])
875
 
        self.assertEqual(unique_lcs('a', 'b'), [])
876
 
        self.assertEqual(unique_lcs('ab', 'ab'), [(0,0), (1,1)])
877
 
        self.assertEqual(unique_lcs('abcde', 'cdeab'), [(2,0), (3,1), (4,2)])
878
 
        self.assertEqual(unique_lcs('cdeab', 'abcde'), [(0,2), (1,3), (2,4)])
879
 
        self.assertEqual(unique_lcs('abXde', 'abYde'), [(0,0), (1,1),
 
783
        self.assertEquals(unique_lcs('', ''), [])
 
784
        self.assertEquals(unique_lcs('', 'a'), [])
 
785
        self.assertEquals(unique_lcs('a', ''), [])
 
786
        self.assertEquals(unique_lcs('a', 'a'), [(0,0)])
 
787
        self.assertEquals(unique_lcs('a', 'b'), [])
 
788
        self.assertEquals(unique_lcs('ab', 'ab'), [(0,0), (1,1)])
 
789
        self.assertEquals(unique_lcs('abcde', 'cdeab'), [(2,0), (3,1), (4,2)])
 
790
        self.assertEquals(unique_lcs('cdeab', 'abcde'), [(0,2), (1,3), (2,4)])
 
791
        self.assertEquals(unique_lcs('abXde', 'abYde'), [(0,0), (1,1),
880
792
                                                         (3,3), (4,4)])
881
 
        self.assertEqual(unique_lcs('acbac', 'abc'), [(2,1)])
 
793
        self.assertEquals(unique_lcs('acbac', 'abc'), [(2,1)])
882
794
 
883
795
    def test_recurse_matches(self):
884
796
        def test_one(a, b, matches):
885
797
            test_matches = []
886
798
            self._recurse_matches(
887
799
                a, b, 0, 0, len(a), len(b), test_matches, 10)
888
 
            self.assertEqual(test_matches, matches)
 
800
            self.assertEquals(test_matches, matches)
889
801
 
890
802
        test_one(['a', '', 'b', '', 'c'], ['a', 'a', 'b', 'c', 'c'],
891
803
                 [(0, 0), (2, 2), (4, 4)])
996
908
    def test_opcodes(self):
997
909
        def chk_ops(a, b, expected_codes):
998
910
            s = self._PatienceSequenceMatcher(None, a, b)
999
 
            self.assertEqual(expected_codes, s.get_opcodes())
 
911
            self.assertEquals(expected_codes, s.get_opcodes())
1000
912
 
1001
913
        chk_ops('', '', [])
1002
914
        chk_ops([], [], [])
1072
984
    def test_grouped_opcodes(self):
1073
985
        def chk_ops(a, b, expected_codes, n=3):
1074
986
            s = self._PatienceSequenceMatcher(None, a, b)
1075
 
            self.assertEqual(expected_codes, list(s.get_grouped_opcodes(n)))
 
987
            self.assertEquals(expected_codes, list(s.get_grouped_opcodes(n)))
1076
988
 
1077
989
        chk_ops('', '', [])
1078
990
        chk_ops([], [], [])
1172
1084
                 'how are you today?\n']
1173
1085
        unified_diff = patiencediff.unified_diff
1174
1086
        psm = self._PatienceSequenceMatcher
1175
 
        self.assertEqual(['--- \n',
 
1087
        self.assertEquals(['--- \n',
1176
1088
                           '+++ \n',
1177
1089
                           '@@ -1,3 +1,2 @@\n',
1178
1090
                           ' hello there\n',
1184
1096
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
1185
1097
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
1186
1098
        # This is the result with LongestCommonSubstring matching
1187
 
        self.assertEqual(['--- \n',
 
1099
        self.assertEquals(['--- \n',
1188
1100
                           '+++ \n',
1189
1101
                           '@@ -1,6 +1,11 @@\n',
1190
1102
                           ' a\n',
1200
1112
                           ' f\n']
1201
1113
                          , list(unified_diff(txt_a, txt_b)))
1202
1114
        # And the patience diff
1203
 
        self.assertEqual(['--- \n',
 
1115
        self.assertEquals(['--- \n',
1204
1116
                           '+++ \n',
1205
1117
                           '@@ -4,6 +4,11 @@\n',
1206
1118
                           ' d\n',
1226
1138
                 'how are you today?\n']
1227
1139
        unified_diff = patiencediff.unified_diff
1228
1140
        psm = self._PatienceSequenceMatcher
1229
 
        self.assertEqual(['--- a\t2008-08-08\n',
 
1141
        self.assertEquals(['--- a\t2008-08-08\n',
1230
1142
                           '+++ b\t2008-09-09\n',
1231
1143
                           '@@ -1,3 +1,2 @@\n',
1232
1144
                           ' hello there\n',
1284
1196
 
1285
1197
        unified_diff_files = patiencediff.unified_diff_files
1286
1198
        psm = self._PatienceSequenceMatcher
1287
 
        self.assertEqual(['--- a1\n',
 
1199
        self.assertEquals(['--- a1\n',
1288
1200
                           '+++ b1\n',
1289
1201
                           '@@ -1,3 +1,2 @@\n',
1290
1202
                           ' hello there\n',
1300
1212
        with open('b2', 'wb') as f: f.writelines(txt_b)
1301
1213
 
1302
1214
        # This is the result with LongestCommonSubstring matching
1303
 
        self.assertEqual(['--- a2\n',
 
1215
        self.assertEquals(['--- a2\n',
1304
1216
                           '+++ b2\n',
1305
1217
                           '@@ -1,6 +1,11 @@\n',
1306
1218
                           ' a\n',
1317
1229
                          , list(unified_diff_files('a2', 'b2')))
1318
1230
 
1319
1231
        # And the patience diff
1320
 
        self.assertEqual(['--- a2\n',
1321
 
                          '+++ b2\n',
1322
 
                          '@@ -4,6 +4,11 @@\n',
1323
 
                          ' d\n',
1324
 
                          ' e\n',
1325
 
                          ' f\n',
1326
 
                          '+x\n',
1327
 
                          '+y\n',
1328
 
                          '+d\n',
1329
 
                          '+e\n',
1330
 
                          '+f\n',
1331
 
                          ' g\n',
1332
 
                          ' h\n',
1333
 
                          ' i\n'],
1334
 
                         list(unified_diff_files('a2', 'b2',
1335
 
                                                 sequencematcher=psm)))
 
1232
        self.assertEquals(['--- a2\n',
 
1233
                           '+++ b2\n',
 
1234
                           '@@ -4,6 +4,11 @@\n',
 
1235
                           ' d\n',
 
1236
                           ' e\n',
 
1237
                           ' f\n',
 
1238
                           '+x\n',
 
1239
                           '+y\n',
 
1240
                           '+d\n',
 
1241
                           '+e\n',
 
1242
                           '+f\n',
 
1243
                           ' g\n',
 
1244
                           ' h\n',
 
1245
                           ' i\n',
 
1246
                          ]
 
1247
                          , list(unified_diff_files('a2', 'b2',
 
1248
                                 sequencematcher=psm)))
1336
1249
 
1337
1250
 
1338
1251
class TestPatienceDiffLibFiles_c(TestPatienceDiffLibFiles):
1415
1328
        diff_obj._execute('old', 'new')
1416
1329
        self.assertEqual(output.getvalue().rstrip(), 'old new')
1417
1330
 
1418
 
    def test_execute_missing(self):
 
1331
    def test_excute_missing(self):
1419
1332
        diff_obj = diff.DiffFromTool(['a-tool-which-is-unlikely-to-exist'],
1420
1333
                                     None, None, None)
1421
1334
        self.addCleanup(diff_obj.finish)
1495
1408
    def test_encodable_filename(self):
1496
1409
        # Just checks file path for external diff tool.
1497
1410
        # We cannot change CPython's internal encoding used by os.exec*.
 
1411
        import sys
1498
1412
        diffobj = diff.DiffFromTool(['dummy', '@old_path', '@new_path'],
1499
1413
                                    None, None, None)
1500
1414
        for _, scenario in EncodingAdapter.encoding_scenarios:
1501
1415
            encoding = scenario['encoding']
1502
 
            dirname = scenario['info']['directory']
 
1416
            dirname  = scenario['info']['directory']
1503
1417
            filename = scenario['info']['filename']
1504
1418
 
1505
1419
            self.overrideAttr(diffobj, '_fenc', lambda: encoding)
1506
1420
            relpath = dirname + u'/' + filename
1507
1421
            fullpath = diffobj._safe_filename('safe', relpath)
1508
 
            self.assertEqual(fullpath,
1509
 
                             fullpath.encode(encoding).decode(encoding))
1510
 
            self.assertTrue(fullpath.startswith(diffobj._root + '/safe'))
 
1422
            self.assertEqual(
 
1423
                    fullpath,
 
1424
                    fullpath.encode(encoding).decode(encoding)
 
1425
                    )
 
1426
            self.assert_(fullpath.startswith(diffobj._root + '/safe'))
1511
1427
 
1512
1428
    def test_unencodable_filename(self):
 
1429
        import sys
1513
1430
        diffobj = diff.DiffFromTool(['dummy', '@old_path', '@new_path'],
1514
1431
                                    None, None, None)
1515
1432
        for _, scenario in EncodingAdapter.encoding_scenarios:
1516
1433
            encoding = scenario['encoding']
1517
 
            dirname = scenario['info']['directory']
 
1434
            dirname  = scenario['info']['directory']
1518
1435
            filename = scenario['info']['filename']
1519
1436
 
1520
1437
            if encoding == 'iso-8859-1':
1525
1442
            self.overrideAttr(diffobj, '_fenc', lambda: encoding)
1526
1443
            relpath = dirname + u'/' + filename
1527
1444
            fullpath = diffobj._safe_filename('safe', relpath)
1528
 
            self.assertEqual(fullpath,
1529
 
                             fullpath.encode(encoding).decode(encoding))
1530
 
            self.assertTrue(fullpath.startswith(diffobj._root + '/safe'))
 
1445
            self.assertEqual(
 
1446
                    fullpath,
 
1447
                    fullpath.encode(encoding).decode(encoding)
 
1448
                    )
 
1449
            self.assert_(fullpath.startswith(diffobj._root + '/safe'))
1531
1450
 
1532
1451
 
1533
1452
class TestGetTreesAndBranchesToDiffLocked(tests.TestCaseWithTransport):