~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_diff.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-06-30 18:28:17 UTC
  • mfrom: (5967.10.2 test-cat)
  • Revision ID: pqm@pqm.ubuntu.com-20110630182817-83a5q9r9rxfkdn8r
(mbp) don't use subprocesses for testing cat (Martin Pool)

Show diffs side-by-side

added added

removed removed

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