~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_diff.py

(vila) Revise legal option names to be less drastic. (Vincent Ladeuil)

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
17
17
import os
18
18
from cStringIO import StringIO
19
19
import subprocess
20
 
import sys
21
20
import tempfile
22
21
 
23
22
from bzrlib import (
32
31
    tests,
33
32
    transform,
34
33
    )
35
 
from bzrlib.symbol_versioning import deprecated_in
36
 
from bzrlib.tests import features, EncodingAdapter
 
34
from bzrlib.tests import (
 
35
    features,
 
36
    EncodingAdapter,
 
37
)
37
38
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')
 
39
from bzrlib.tests.scenarios import load_tests_apply_scenarios
 
40
 
 
41
 
 
42
load_tests = load_tests_apply_scenarios
59
43
 
60
44
 
61
45
def udiff_lines(old, new, allow_binary=False):
81
65
    return lines
82
66
 
83
67
 
 
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
 
84
91
class TestDiff(tests.TestCase):
85
92
 
86
93
    def test_add_nl(self):
229
236
        self.assertIsInstance(output.getvalue(), str,
230
237
            'internal_diff should return bytestrings')
231
238
 
 
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.assertEquals(['--- 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.assertEquals(['--- 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.assertEquals(['--- 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
 
232
302
 
233
303
class TestDiffFiles(tests.TestCaseInTempDir):
234
304
 
238
308
        lines = external_udiff_lines(['\x00foobar\n'], ['foo\x00bar\n'])
239
309
 
240
310
        cmd = ['diff', '-u', '--binary', 'old', 'new']
241
 
        open('old', 'wb').write('\x00foobar\n')
242
 
        open('new', 'wb').write('foo\x00bar\n')
 
311
        with open('old', 'wb') as f: f.write('\x00foobar\n')
 
312
        with open('new', 'wb') as f: f.write('foo\x00bar\n')
243
313
        pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE,
244
314
                                     stdin=subprocess.PIPE)
245
315
        out, err = pipe.communicate()
514
584
        is a binary file in the diff.
515
585
        """
516
586
        # See https://bugs.launchpad.net/bugs/110092.
517
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
587
        self.requireFeature(features.UnicodeFilenameFeature)
518
588
 
519
589
        # This bug isn't triggered with cStringIO.
520
590
        from StringIO import StringIO
539
609
 
540
610
    def test_unicode_filename(self):
541
611
        """Test when the filename are unicode."""
542
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
612
        self.requireFeature(features.UnicodeFilenameFeature)
543
613
 
544
614
        alpha, omega = u'\u03b1', u'\u03c9'
545
615
        autf8, outf8 = alpha.encode('utf8'), omega.encode('utf8')
571
641
        """Test for bug #382699: unicode filenames on Windows should be shown
572
642
        in user encoding.
573
643
        """
574
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
644
        self.requireFeature(features.UnicodeFilenameFeature)
575
645
        # The word 'test' in Russian
576
646
        _russian_test = u'\u0422\u0435\u0441\u0442'
577
647
        directory = _russian_test + u'/'
708
778
             ' \@\@\n-old\n\+new\n\n')
709
779
 
710
780
    def test_diff_kind_change(self):
711
 
        self.requireFeature(tests.SymlinkFeature)
 
781
        self.requireFeature(features.SymlinkFeature)
712
782
        self.build_tree_contents([('old-tree/olddir/',),
713
783
                                  ('old-tree/olddir/oldfile', 'old\n')])
714
784
        self.old_tree.add('olddir')
1172
1242
 
1173
1243
class TestPatienceDiffLib_c(TestPatienceDiffLib):
1174
1244
 
1175
 
    _test_needs_features = [compiled_patiencediff_feature]
 
1245
    _test_needs_features = [features.compiled_patiencediff_feature]
1176
1246
 
1177
1247
    def setUp(self):
1178
1248
        super(TestPatienceDiffLib_c, self).setUp()
1209
1279
                 'how are you today?\n']
1210
1280
        txt_b = ['hello there\n',
1211
1281
                 'how are you today?\n']
1212
 
        open('a1', 'wb').writelines(txt_a)
1213
 
        open('b1', 'wb').writelines(txt_b)
 
1282
        with open('a1', 'wb') as f: f.writelines(txt_a)
 
1283
        with open('b1', 'wb') as f: f.writelines(txt_b)
1214
1284
 
1215
1285
        unified_diff_files = patiencediff.unified_diff_files
1216
1286
        psm = self._PatienceSequenceMatcher
1226
1296
 
1227
1297
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
1228
1298
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
1229
 
        open('a2', 'wb').writelines(txt_a)
1230
 
        open('b2', 'wb').writelines(txt_b)
 
1299
        with open('a2', 'wb') as f: f.writelines(txt_a)
 
1300
        with open('b2', 'wb') as f: f.writelines(txt_b)
1231
1301
 
1232
1302
        # This is the result with LongestCommonSubstring matching
1233
1303
        self.assertEquals(['--- a2\n',
1268
1338
 
1269
1339
class TestPatienceDiffLibFiles_c(TestPatienceDiffLibFiles):
1270
1340
 
1271
 
    _test_needs_features = [compiled_patiencediff_feature]
 
1341
    _test_needs_features = [features.compiled_patiencediff_feature]
1272
1342
 
1273
1343
    def setUp(self):
1274
1344
        super(TestPatienceDiffLibFiles_c, self).setUp()
1280
1350
class TestUsingCompiledIfAvailable(tests.TestCase):
1281
1351
 
1282
1352
    def test_PatienceSequenceMatcher(self):
1283
 
        if compiled_patiencediff_feature.available():
 
1353
        if features.compiled_patiencediff_feature.available():
1284
1354
            from bzrlib._patiencediff_c import PatienceSequenceMatcher_c
1285
1355
            self.assertIs(PatienceSequenceMatcher_c,
1286
1356
                          patiencediff.PatienceSequenceMatcher)
1290
1360
                          patiencediff.PatienceSequenceMatcher)
1291
1361
 
1292
1362
    def test_unique_lcs(self):
1293
 
        if compiled_patiencediff_feature.available():
 
1363
        if features.compiled_patiencediff_feature.available():
1294
1364
            from bzrlib._patiencediff_c import unique_lcs_c
1295
1365
            self.assertIs(unique_lcs_c,
1296
1366
                          patiencediff.unique_lcs)
1300
1370
                          patiencediff.unique_lcs)
1301
1371
 
1302
1372
    def test_recurse_matches(self):
1303
 
        if compiled_patiencediff_feature.available():
 
1373
        if features.compiled_patiencediff_feature.available():
1304
1374
            from bzrlib._patiencediff_c import recurse_matches_c
1305
1375
            self.assertIs(recurse_matches_c,
1306
1376
                          patiencediff.recurse_matches)
1346
1416
        diff_obj._execute('old', 'new')
1347
1417
        self.assertEqual(output.getvalue().rstrip(), 'old new')
1348
1418
 
1349
 
    def test_excute_missing(self):
 
1419
    def test_execute_missing(self):
1350
1420
        diff_obj = diff.DiffFromTool(['a-tool-which-is-unlikely-to-exist'],
1351
1421
                                     None, None, None)
1352
1422
        self.addCleanup(diff_obj.finish)
1356
1426
                         ' on this machine', str(e))
1357
1427
 
1358
1428
    def test_prepare_files_creates_paths_readable_by_windows_tool(self):
1359
 
        self.requireFeature(AttribFeature)
 
1429
        self.requireFeature(features.AttribFeature)
1360
1430
        output = StringIO()
1361
1431
        tree = self.make_branch_and_tree('tree')
1362
1432
        self.build_tree_contents([('tree/file', 'content')])
1426
1496
    def test_encodable_filename(self):
1427
1497
        # Just checks file path for external diff tool.
1428
1498
        # We cannot change CPython's internal encoding used by os.exec*.
1429
 
        import sys
1430
1499
        diffobj = diff.DiffFromTool(['dummy', '@old_path', '@new_path'],
1431
1500
                                    None, None, None)
1432
1501
        for _, scenario in EncodingAdapter.encoding_scenarios:
1444
1513
            self.assert_(fullpath.startswith(diffobj._root + '/safe'))
1445
1514
 
1446
1515
    def test_unencodable_filename(self):
1447
 
        import sys
1448
1516
        diffobj = diff.DiffFromTool(['dummy', '@old_path', '@new_path'],
1449
1517
                                    None, None, None)
1450
1518
        for _, scenario in EncodingAdapter.encoding_scenarios:
1470
1538
class TestGetTreesAndBranchesToDiffLocked(tests.TestCaseWithTransport):
1471
1539
 
1472
1540
    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
 
        """
 
1541
        """Call get_trees_and_branches_to_diff_locked."""
1476
1542
        return diff.get_trees_and_branches_to_diff_locked(
1477
1543
            path_list, revision_specs, old_url, new_url, self.addCleanup)
1478
1544
 
1515
1581
        self.assertEqual(tree.branch.base, new_branch.base)
1516
1582
        self.assertIs(None, specific_files)
1517
1583
        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)