~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_diff.py

  • Committer: Patch Queue Manager
  • Date: 2014-09-22 19:42:30 UTC
  • mfrom: (6597.2.1 bzr)
  • Revision ID: pqm@pqm.ubuntu.com-20140922194230-y32j0sq621bxhp7c
(richard-wilbur) Split diff format option parser into a separate function,
 update to include all format options for GNU diff v3.2,
 and test parser.  Fixes lp:1370435 (Richard Wilbur)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2014 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
35
35
from bzrlib.symbol_versioning import deprecated_in
36
36
from bzrlib.tests import features, EncodingAdapter
37
37
from bzrlib.tests.blackbox.test_diff import subst_dates
38
 
 
39
 
 
40
 
class _AttribFeature(tests.Feature):
41
 
 
42
 
    def _probe(self):
43
 
        if (sys.platform not in ('cygwin', 'win32')):
44
 
            return False
45
 
        try:
46
 
            proc = subprocess.Popen(['attrib', '.'], stdout=subprocess.PIPE)
47
 
        except OSError, e:
48
 
            return False
49
 
        return (0 == proc.wait())
50
 
 
51
 
    def feature_name(self):
52
 
        return 'attrib Windows command-line tool'
53
 
 
54
 
AttribFeature = _AttribFeature()
55
 
 
56
 
 
57
 
compiled_patiencediff_feature = tests.ModuleAvailableFeature(
58
 
                                    'bzrlib._patiencediff_c')
 
38
from bzrlib.tests import (
 
39
    features,
 
40
    )
59
41
 
60
42
 
61
43
def udiff_lines(old, new, allow_binary=False):
161
143
                          'old', ['boo\n'], 'new', ['goo\n'],
162
144
                          StringIO(), diff_opts=['-u'])
163
145
 
 
146
    def test_default_style_unified(self):
 
147
        """Check for default style '-u' only if no other style specified
 
148
        in 'diff-options'.
 
149
        """
 
150
        # Verify that style defaults to unified, id est '-u' appended
 
151
        # to option list, in the absence of an alternative style.
 
152
        self.assertEqual(['-a', '-u'], diff.default_style_unified(["-a"]))
 
153
        # Verify that for all valid style options, '-u' is not
 
154
        # appended to option list.
 
155
        for s in diff.style_option_list:
 
156
            ret_opts = diff.default_style_unified(diff_opts=["%s" % (s,)])
 
157
            self.assertEqual(["%s" % (s,)], ret_opts)
 
158
 
164
159
    def test_internal_diff_default(self):
165
160
        # Default internal diff encoding is utf8
166
161
        output = StringIO()
229
224
        self.assertIsInstance(output.getvalue(), str,
230
225
            'internal_diff should return bytestrings')
231
226
 
 
227
    def test_internal_diff_default_context(self):
 
228
        output = StringIO()
 
229
        diff.internal_diff('old', ['same_text\n','same_text\n','same_text\n',
 
230
                           'same_text\n','same_text\n','old_text\n'],
 
231
                           'new', ['same_text\n','same_text\n','same_text\n',
 
232
                           'same_text\n','same_text\n','new_text\n'], output)
 
233
        lines = output.getvalue().splitlines(True)
 
234
        self.check_patch(lines)
 
235
        self.assertEquals(['--- old\n',
 
236
                           '+++ new\n',
 
237
                           '@@ -3,4 +3,4 @@\n',
 
238
                           ' same_text\n',
 
239
                           ' same_text\n',
 
240
                           ' same_text\n',
 
241
                           '-old_text\n',
 
242
                           '+new_text\n',
 
243
                           '\n',
 
244
                          ]
 
245
                          , lines)
 
246
 
 
247
    def test_internal_diff_no_context(self):
 
248
        output = StringIO()
 
249
        diff.internal_diff('old', ['same_text\n','same_text\n','same_text\n',
 
250
                           'same_text\n','same_text\n','old_text\n'],
 
251
                           'new', ['same_text\n','same_text\n','same_text\n',
 
252
                           'same_text\n','same_text\n','new_text\n'], output,
 
253
                           context_lines=0)
 
254
        lines = output.getvalue().splitlines(True)
 
255
        self.check_patch(lines)
 
256
        self.assertEquals(['--- old\n',
 
257
                           '+++ new\n',
 
258
                           '@@ -6,1 +6,1 @@\n',
 
259
                           '-old_text\n',
 
260
                           '+new_text\n',
 
261
                           '\n',
 
262
                          ]
 
263
                          , lines)
 
264
 
 
265
    def test_internal_diff_more_context(self):
 
266
        output = StringIO()
 
267
        diff.internal_diff('old', ['same_text\n','same_text\n','same_text\n',
 
268
                           'same_text\n','same_text\n','old_text\n'],
 
269
                           'new', ['same_text\n','same_text\n','same_text\n',
 
270
                           'same_text\n','same_text\n','new_text\n'], output,
 
271
                           context_lines=4)
 
272
        lines = output.getvalue().splitlines(True)
 
273
        self.check_patch(lines)
 
274
        self.assertEquals(['--- old\n',
 
275
                           '+++ new\n',
 
276
                           '@@ -2,5 +2,5 @@\n',
 
277
                           ' same_text\n',
 
278
                           ' same_text\n',
 
279
                           ' same_text\n',
 
280
                           ' same_text\n',
 
281
                           '-old_text\n',
 
282
                           '+new_text\n',
 
283
                           '\n',
 
284
                          ]
 
285
                          , lines)
 
286
 
 
287
 
 
288
 
 
289
 
232
290
 
233
291
class TestDiffFiles(tests.TestCaseInTempDir):
234
292
 
238
296
        lines = external_udiff_lines(['\x00foobar\n'], ['foo\x00bar\n'])
239
297
 
240
298
        cmd = ['diff', '-u', '--binary', 'old', 'new']
241
 
        open('old', 'wb').write('\x00foobar\n')
242
 
        open('new', 'wb').write('foo\x00bar\n')
 
299
        with open('old', 'wb') as f: f.write('\x00foobar\n')
 
300
        with open('new', 'wb') as f: f.write('foo\x00bar\n')
243
301
        pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE,
244
302
                                     stdin=subprocess.PIPE)
245
303
        out, err = pipe.communicate()
514
572
        is a binary file in the diff.
515
573
        """
516
574
        # See https://bugs.launchpad.net/bugs/110092.
517
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
575
        self.requireFeature(features.UnicodeFilenameFeature)
518
576
 
519
577
        # This bug isn't triggered with cStringIO.
520
578
        from StringIO import StringIO
539
597
 
540
598
    def test_unicode_filename(self):
541
599
        """Test when the filename are unicode."""
542
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
600
        self.requireFeature(features.UnicodeFilenameFeature)
543
601
 
544
602
        alpha, omega = u'\u03b1', u'\u03c9'
545
603
        autf8, outf8 = alpha.encode('utf8'), omega.encode('utf8')
571
629
        """Test for bug #382699: unicode filenames on Windows should be shown
572
630
        in user encoding.
573
631
        """
574
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
632
        self.requireFeature(features.UnicodeFilenameFeature)
575
633
        # The word 'test' in Russian
576
634
        _russian_test = u'\u0422\u0435\u0441\u0442'
577
635
        directory = _russian_test + u'/'
708
766
             ' \@\@\n-old\n\+new\n\n')
709
767
 
710
768
    def test_diff_kind_change(self):
711
 
        self.requireFeature(tests.SymlinkFeature)
 
769
        self.requireFeature(features.SymlinkFeature)
712
770
        self.build_tree_contents([('old-tree/olddir/',),
713
771
                                  ('old-tree/olddir/oldfile', 'old\n')])
714
772
        self.old_tree.add('olddir')
1172
1230
 
1173
1231
class TestPatienceDiffLib_c(TestPatienceDiffLib):
1174
1232
 
1175
 
    _test_needs_features = [compiled_patiencediff_feature]
 
1233
    _test_needs_features = [features.compiled_patiencediff_feature]
1176
1234
 
1177
1235
    def setUp(self):
1178
1236
        super(TestPatienceDiffLib_c, self).setUp()
1209
1267
                 'how are you today?\n']
1210
1268
        txt_b = ['hello there\n',
1211
1269
                 'how are you today?\n']
1212
 
        open('a1', 'wb').writelines(txt_a)
1213
 
        open('b1', 'wb').writelines(txt_b)
 
1270
        with open('a1', 'wb') as f: f.writelines(txt_a)
 
1271
        with open('b1', 'wb') as f: f.writelines(txt_b)
1214
1272
 
1215
1273
        unified_diff_files = patiencediff.unified_diff_files
1216
1274
        psm = self._PatienceSequenceMatcher
1226
1284
 
1227
1285
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
1228
1286
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
1229
 
        open('a2', 'wb').writelines(txt_a)
1230
 
        open('b2', 'wb').writelines(txt_b)
 
1287
        with open('a2', 'wb') as f: f.writelines(txt_a)
 
1288
        with open('b2', 'wb') as f: f.writelines(txt_b)
1231
1289
 
1232
1290
        # This is the result with LongestCommonSubstring matching
1233
1291
        self.assertEquals(['--- a2\n',
1268
1326
 
1269
1327
class TestPatienceDiffLibFiles_c(TestPatienceDiffLibFiles):
1270
1328
 
1271
 
    _test_needs_features = [compiled_patiencediff_feature]
 
1329
    _test_needs_features = [features.compiled_patiencediff_feature]
1272
1330
 
1273
1331
    def setUp(self):
1274
1332
        super(TestPatienceDiffLibFiles_c, self).setUp()
1280
1338
class TestUsingCompiledIfAvailable(tests.TestCase):
1281
1339
 
1282
1340
    def test_PatienceSequenceMatcher(self):
1283
 
        if compiled_patiencediff_feature.available():
 
1341
        if features.compiled_patiencediff_feature.available():
1284
1342
            from bzrlib._patiencediff_c import PatienceSequenceMatcher_c
1285
1343
            self.assertIs(PatienceSequenceMatcher_c,
1286
1344
                          patiencediff.PatienceSequenceMatcher)
1290
1348
                          patiencediff.PatienceSequenceMatcher)
1291
1349
 
1292
1350
    def test_unique_lcs(self):
1293
 
        if compiled_patiencediff_feature.available():
 
1351
        if features.compiled_patiencediff_feature.available():
1294
1352
            from bzrlib._patiencediff_c import unique_lcs_c
1295
1353
            self.assertIs(unique_lcs_c,
1296
1354
                          patiencediff.unique_lcs)
1300
1358
                          patiencediff.unique_lcs)
1301
1359
 
1302
1360
    def test_recurse_matches(self):
1303
 
        if compiled_patiencediff_feature.available():
 
1361
        if features.compiled_patiencediff_feature.available():
1304
1362
            from bzrlib._patiencediff_c import recurse_matches_c
1305
1363
            self.assertIs(recurse_matches_c,
1306
1364
                          patiencediff.recurse_matches)
1346
1404
        diff_obj._execute('old', 'new')
1347
1405
        self.assertEqual(output.getvalue().rstrip(), 'old new')
1348
1406
 
1349
 
    def test_excute_missing(self):
 
1407
    def test_execute_missing(self):
1350
1408
        diff_obj = diff.DiffFromTool(['a-tool-which-is-unlikely-to-exist'],
1351
1409
                                     None, None, None)
1352
1410
        self.addCleanup(diff_obj.finish)
1356
1414
                         ' on this machine', str(e))
1357
1415
 
1358
1416
    def test_prepare_files_creates_paths_readable_by_windows_tool(self):
1359
 
        self.requireFeature(AttribFeature)
 
1417
        self.requireFeature(features.AttribFeature)
1360
1418
        output = StringIO()
1361
1419
        tree = self.make_branch_and_tree('tree')
1362
1420
        self.build_tree_contents([('tree/file', 'content')])
1470
1528
class TestGetTreesAndBranchesToDiffLocked(tests.TestCaseWithTransport):
1471
1529
 
1472
1530
    def call_gtabtd(self, path_list, revision_specs, old_url, new_url):
1473
 
        """Call get_trees_and_branches_to_diff_locked.  Overridden by
1474
 
        TestGetTreesAndBranchesToDiff.
1475
 
        """
 
1531
        """Call get_trees_and_branches_to_diff_locked."""
1476
1532
        return diff.get_trees_and_branches_to_diff_locked(
1477
1533
            path_list, revision_specs, old_url, new_url, self.addCleanup)
1478
1534
 
1515
1571
        self.assertEqual(tree.branch.base, new_branch.base)
1516
1572
        self.assertIs(None, specific_files)
1517
1573
        self.assertEqual(tree.basedir, extra_trees[0].basedir)
1518
 
 
1519
 
 
1520
 
class TestGetTreesAndBranchesToDiff(TestGetTreesAndBranchesToDiffLocked):
1521
 
    """Apply the tests for get_trees_and_branches_to_diff_locked to the
1522
 
    deprecated get_trees_and_branches_to_diff function.
1523
 
    """
1524
 
 
1525
 
    def call_gtabtd(self, path_list, revision_specs, old_url, new_url):
1526
 
        return self.applyDeprecated(
1527
 
            deprecated_in((2, 2, 0)), diff.get_trees_and_branches_to_diff,
1528
 
            path_list, revision_specs, old_url, new_url)