~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_diff.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil
  • Date: 2017-01-30 14:42:05 UTC
  • mfrom: (6620.1.1 trunk)
  • Revision ID: tarmac-20170130144205-r8fh2xpmiuxyozpv
Merge  2.7 into trunk including fix for bug #1657238 [r=vila]

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2012, 2014, 2016, 2017 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):
87
94
        """diff generates a valid diff for patches that add a newline"""
88
95
        lines = udiff_lines(['boo'], ['boo\n'])
89
96
        self.check_patch(lines)
90
 
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
 
97
        self.assertEqual(lines[4], '\\ No newline at end of file\n')
91
98
            ## "expected no-nl, got %r" % lines[4]
92
99
 
93
100
    def test_add_nl_2(self):
96
103
        """
97
104
        lines = udiff_lines(['boo'], ['goo\n'])
98
105
        self.check_patch(lines)
99
 
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
 
106
        self.assertEqual(lines[4], '\\ No newline at end of file\n')
100
107
            ## "expected no-nl, got %r" % lines[4]
101
108
 
102
109
    def test_remove_nl(self):
105
112
        """
106
113
        lines = udiff_lines(['boo\n'], ['boo'])
107
114
        self.check_patch(lines)
108
 
        self.assertEquals(lines[5], '\\ No newline at end of file\n')
 
115
        self.assertEqual(lines[5], '\\ No newline at end of file\n')
109
116
            ## "expected no-nl, got %r" % lines[5]
110
117
 
111
118
    def check_patch(self, lines):
112
 
        self.assert_(len(lines) > 1)
 
119
        self.assertTrue(len(lines) > 1)
113
120
            ## "Not enough lines for a file header for patch:\n%s" % "".join(lines)
114
 
        self.assert_(lines[0].startswith ('---'))
 
121
        self.assertTrue(lines[0].startswith ('---'))
115
122
            ## 'No orig line for patch:\n%s' % "".join(lines)
116
 
        self.assert_(lines[1].startswith ('+++'))
 
123
        self.assertTrue(lines[1].startswith ('+++'))
117
124
            ## 'No mod line for patch:\n%s' % "".join(lines)
118
 
        self.assert_(len(lines) > 2)
 
125
        self.assertTrue(len(lines) > 2)
119
126
            ## "No hunks for patch:\n%s" % "".join(lines)
120
 
        self.assert_(lines[2].startswith('@@'))
 
127
        self.assertTrue(lines[2].startswith('@@'))
121
128
            ## "No hunk header for patch:\n%s" % "".join(lines)
122
 
        self.assert_('@@' in lines[2][2:])
 
129
        self.assertTrue('@@' in lines[2][2:])
123
130
            ## "Unterminated hunk header for patch:\n%s" % "".join(lines)
124
131
 
125
132
    def test_binary_lines(self):
150
157
        # Older versions of diffutils say "Binary files", newer
151
158
        # versions just say "Files".
152
159
        self.assertContainsRe(lines[0], '(Binary f|F)iles old and new differ\n')
153
 
        self.assertEquals(lines[1:], ['\n'])
 
160
        self.assertEqual(lines[1:], ['\n'])
154
161
 
155
162
    def test_no_external_diff(self):
156
163
        """Check that NoDiff is raised when diff is not available"""
168
175
                           u'new_\xe5', ['new_text\n'], output)
169
176
        lines = output.getvalue().splitlines(True)
170
177
        self.check_patch(lines)
171
 
        self.assertEquals(['--- old_\xc2\xb5\n',
 
178
        self.assertEqual(['--- old_\xc2\xb5\n',
172
179
                           '+++ new_\xc3\xa5\n',
173
180
                           '@@ -1,1 +1,1 @@\n',
174
181
                           '-old_text\n',
184
191
                           path_encoding='utf8')
185
192
        lines = output.getvalue().splitlines(True)
186
193
        self.check_patch(lines)
187
 
        self.assertEquals(['--- old_\xc2\xb5\n',
 
194
        self.assertEqual(['--- old_\xc2\xb5\n',
188
195
                           '+++ new_\xc3\xa5\n',
189
196
                           '@@ -1,1 +1,1 @@\n',
190
197
                           '-old_text\n',
200
207
                           path_encoding='iso-8859-1')
201
208
        lines = output.getvalue().splitlines(True)
202
209
        self.check_patch(lines)
203
 
        self.assertEquals(['--- old_\xb5\n',
 
210
        self.assertEqual(['--- old_\xb5\n',
204
211
                           '+++ new_\xe5\n',
205
212
                           '@@ -1,1 +1,1 @@\n',
206
213
                           '-old_text\n',
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.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
 
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()
246
 
        # Diff returns '2' on Binary files.
247
 
        self.assertEqual(2, pipe.returncode)
248
316
        # We should output whatever diff tells us, plus a trailing newline
249
317
        self.assertEqual(out.splitlines(True) + ['\n'], lines)
250
318
 
514
582
        is a binary file in the diff.
515
583
        """
516
584
        # See https://bugs.launchpad.net/bugs/110092.
517
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
585
        self.requireFeature(features.UnicodeFilenameFeature)
518
586
 
519
587
        # This bug isn't triggered with cStringIO.
520
588
        from StringIO import StringIO
539
607
 
540
608
    def test_unicode_filename(self):
541
609
        """Test when the filename are unicode."""
542
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
610
        self.requireFeature(features.UnicodeFilenameFeature)
543
611
 
544
612
        alpha, omega = u'\u03b1', u'\u03c9'
545
613
        autf8, outf8 = alpha.encode('utf8'), omega.encode('utf8')
571
639
        """Test for bug #382699: unicode filenames on Windows should be shown
572
640
        in user encoding.
573
641
        """
574
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
642
        self.requireFeature(features.UnicodeFilenameFeature)
575
643
        # The word 'test' in Russian
576
644
        _russian_test = u'\u0422\u0435\u0441\u0442'
577
645
        directory = _russian_test + u'/'
708
776
             ' \@\@\n-old\n\+new\n\n')
709
777
 
710
778
    def test_diff_kind_change(self):
711
 
        self.requireFeature(tests.SymlinkFeature)
 
779
        self.requireFeature(features.SymlinkFeature)
712
780
        self.build_tree_contents([('old-tree/olddir/',),
713
781
                                  ('old-tree/olddir/oldfile', 'old\n')])
714
782
        self.old_tree.add('olddir')
794
862
        b = ''.join([unichr(i) for i in range(4300, 4800, 2)])
795
863
        sm = self._PatienceSequenceMatcher(None, a, b)
796
864
        mb = sm.get_matching_blocks()
797
 
        self.assertEquals(35, len(mb))
 
865
        self.assertEqual(35, len(mb))
798
866
 
799
867
    def test_unique_lcs(self):
800
868
        unique_lcs = self._unique_lcs
801
 
        self.assertEquals(unique_lcs('', ''), [])
802
 
        self.assertEquals(unique_lcs('', 'a'), [])
803
 
        self.assertEquals(unique_lcs('a', ''), [])
804
 
        self.assertEquals(unique_lcs('a', 'a'), [(0,0)])
805
 
        self.assertEquals(unique_lcs('a', 'b'), [])
806
 
        self.assertEquals(unique_lcs('ab', 'ab'), [(0,0), (1,1)])
807
 
        self.assertEquals(unique_lcs('abcde', 'cdeab'), [(2,0), (3,1), (4,2)])
808
 
        self.assertEquals(unique_lcs('cdeab', 'abcde'), [(0,2), (1,3), (2,4)])
809
 
        self.assertEquals(unique_lcs('abXde', 'abYde'), [(0,0), (1,1),
 
869
        self.assertEqual(unique_lcs('', ''), [])
 
870
        self.assertEqual(unique_lcs('', 'a'), [])
 
871
        self.assertEqual(unique_lcs('a', ''), [])
 
872
        self.assertEqual(unique_lcs('a', 'a'), [(0,0)])
 
873
        self.assertEqual(unique_lcs('a', 'b'), [])
 
874
        self.assertEqual(unique_lcs('ab', 'ab'), [(0,0), (1,1)])
 
875
        self.assertEqual(unique_lcs('abcde', 'cdeab'), [(2,0), (3,1), (4,2)])
 
876
        self.assertEqual(unique_lcs('cdeab', 'abcde'), [(0,2), (1,3), (2,4)])
 
877
        self.assertEqual(unique_lcs('abXde', 'abYde'), [(0,0), (1,1),
810
878
                                                         (3,3), (4,4)])
811
 
        self.assertEquals(unique_lcs('acbac', 'abc'), [(2,1)])
 
879
        self.assertEqual(unique_lcs('acbac', 'abc'), [(2,1)])
812
880
 
813
881
    def test_recurse_matches(self):
814
882
        def test_one(a, b, matches):
815
883
            test_matches = []
816
884
            self._recurse_matches(
817
885
                a, b, 0, 0, len(a), len(b), test_matches, 10)
818
 
            self.assertEquals(test_matches, matches)
 
886
            self.assertEqual(test_matches, matches)
819
887
 
820
888
        test_one(['a', '', 'b', '', 'c'], ['a', 'a', 'b', 'c', 'c'],
821
889
                 [(0, 0), (2, 2), (4, 4)])
926
994
    def test_opcodes(self):
927
995
        def chk_ops(a, b, expected_codes):
928
996
            s = self._PatienceSequenceMatcher(None, a, b)
929
 
            self.assertEquals(expected_codes, s.get_opcodes())
 
997
            self.assertEqual(expected_codes, s.get_opcodes())
930
998
 
931
999
        chk_ops('', '', [])
932
1000
        chk_ops([], [], [])
1002
1070
    def test_grouped_opcodes(self):
1003
1071
        def chk_ops(a, b, expected_codes, n=3):
1004
1072
            s = self._PatienceSequenceMatcher(None, a, b)
1005
 
            self.assertEquals(expected_codes, list(s.get_grouped_opcodes(n)))
 
1073
            self.assertEqual(expected_codes, list(s.get_grouped_opcodes(n)))
1006
1074
 
1007
1075
        chk_ops('', '', [])
1008
1076
        chk_ops([], [], [])
1102
1170
                 'how are you today?\n']
1103
1171
        unified_diff = patiencediff.unified_diff
1104
1172
        psm = self._PatienceSequenceMatcher
1105
 
        self.assertEquals(['--- \n',
 
1173
        self.assertEqual(['--- \n',
1106
1174
                           '+++ \n',
1107
1175
                           '@@ -1,3 +1,2 @@\n',
1108
1176
                           ' hello there\n',
1114
1182
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
1115
1183
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
1116
1184
        # This is the result with LongestCommonSubstring matching
1117
 
        self.assertEquals(['--- \n',
 
1185
        self.assertEqual(['--- \n',
1118
1186
                           '+++ \n',
1119
1187
                           '@@ -1,6 +1,11 @@\n',
1120
1188
                           ' a\n',
1130
1198
                           ' f\n']
1131
1199
                          , list(unified_diff(txt_a, txt_b)))
1132
1200
        # And the patience diff
1133
 
        self.assertEquals(['--- \n',
 
1201
        self.assertEqual(['--- \n',
1134
1202
                           '+++ \n',
1135
1203
                           '@@ -4,6 +4,11 @@\n',
1136
1204
                           ' d\n',
1156
1224
                 'how are you today?\n']
1157
1225
        unified_diff = patiencediff.unified_diff
1158
1226
        psm = self._PatienceSequenceMatcher
1159
 
        self.assertEquals(['--- a\t2008-08-08\n',
 
1227
        self.assertEqual(['--- a\t2008-08-08\n',
1160
1228
                           '+++ b\t2008-09-09\n',
1161
1229
                           '@@ -1,3 +1,2 @@\n',
1162
1230
                           ' hello there\n',
1172
1240
 
1173
1241
class TestPatienceDiffLib_c(TestPatienceDiffLib):
1174
1242
 
1175
 
    _test_needs_features = [compiled_patiencediff_feature]
 
1243
    _test_needs_features = [features.compiled_patiencediff_feature]
1176
1244
 
1177
1245
    def setUp(self):
1178
1246
        super(TestPatienceDiffLib_c, self).setUp()
1209
1277
                 'how are you today?\n']
1210
1278
        txt_b = ['hello there\n',
1211
1279
                 'how are you today?\n']
1212
 
        open('a1', 'wb').writelines(txt_a)
1213
 
        open('b1', 'wb').writelines(txt_b)
 
1280
        with open('a1', 'wb') as f: f.writelines(txt_a)
 
1281
        with open('b1', 'wb') as f: f.writelines(txt_b)
1214
1282
 
1215
1283
        unified_diff_files = patiencediff.unified_diff_files
1216
1284
        psm = self._PatienceSequenceMatcher
1217
 
        self.assertEquals(['--- a1\n',
 
1285
        self.assertEqual(['--- a1\n',
1218
1286
                           '+++ b1\n',
1219
1287
                           '@@ -1,3 +1,2 @@\n',
1220
1288
                           ' hello there\n',
1226
1294
 
1227
1295
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
1228
1296
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
1229
 
        open('a2', 'wb').writelines(txt_a)
1230
 
        open('b2', 'wb').writelines(txt_b)
 
1297
        with open('a2', 'wb') as f: f.writelines(txt_a)
 
1298
        with open('b2', 'wb') as f: f.writelines(txt_b)
1231
1299
 
1232
1300
        # This is the result with LongestCommonSubstring matching
1233
 
        self.assertEquals(['--- a2\n',
 
1301
        self.assertEqual(['--- a2\n',
1234
1302
                           '+++ b2\n',
1235
1303
                           '@@ -1,6 +1,11 @@\n',
1236
1304
                           ' a\n',
1247
1315
                          , list(unified_diff_files('a2', 'b2')))
1248
1316
 
1249
1317
        # And the patience diff
1250
 
        self.assertEquals(['--- a2\n',
1251
 
                           '+++ b2\n',
1252
 
                           '@@ -4,6 +4,11 @@\n',
1253
 
                           ' d\n',
1254
 
                           ' e\n',
1255
 
                           ' f\n',
1256
 
                           '+x\n',
1257
 
                           '+y\n',
1258
 
                           '+d\n',
1259
 
                           '+e\n',
1260
 
                           '+f\n',
1261
 
                           ' g\n',
1262
 
                           ' h\n',
1263
 
                           ' i\n',
1264
 
                          ]
1265
 
                          , list(unified_diff_files('a2', 'b2',
1266
 
                                 sequencematcher=psm)))
 
1318
        self.assertEqual(['--- a2\n',
 
1319
                          '+++ b2\n',
 
1320
                          '@@ -4,6 +4,11 @@\n',
 
1321
                          ' d\n',
 
1322
                          ' e\n',
 
1323
                          ' f\n',
 
1324
                          '+x\n',
 
1325
                          '+y\n',
 
1326
                          '+d\n',
 
1327
                          '+e\n',
 
1328
                          '+f\n',
 
1329
                          ' g\n',
 
1330
                          ' h\n',
 
1331
                          ' i\n'],
 
1332
                         list(unified_diff_files('a2', 'b2',
 
1333
                                                 sequencematcher=psm)))
1267
1334
 
1268
1335
 
1269
1336
class TestPatienceDiffLibFiles_c(TestPatienceDiffLibFiles):
1270
1337
 
1271
 
    _test_needs_features = [compiled_patiencediff_feature]
 
1338
    _test_needs_features = [features.compiled_patiencediff_feature]
1272
1339
 
1273
1340
    def setUp(self):
1274
1341
        super(TestPatienceDiffLibFiles_c, self).setUp()
1280
1347
class TestUsingCompiledIfAvailable(tests.TestCase):
1281
1348
 
1282
1349
    def test_PatienceSequenceMatcher(self):
1283
 
        if compiled_patiencediff_feature.available():
 
1350
        if features.compiled_patiencediff_feature.available():
1284
1351
            from bzrlib._patiencediff_c import PatienceSequenceMatcher_c
1285
1352
            self.assertIs(PatienceSequenceMatcher_c,
1286
1353
                          patiencediff.PatienceSequenceMatcher)
1290
1357
                          patiencediff.PatienceSequenceMatcher)
1291
1358
 
1292
1359
    def test_unique_lcs(self):
1293
 
        if compiled_patiencediff_feature.available():
 
1360
        if features.compiled_patiencediff_feature.available():
1294
1361
            from bzrlib._patiencediff_c import unique_lcs_c
1295
1362
            self.assertIs(unique_lcs_c,
1296
1363
                          patiencediff.unique_lcs)
1300
1367
                          patiencediff.unique_lcs)
1301
1368
 
1302
1369
    def test_recurse_matches(self):
1303
 
        if compiled_patiencediff_feature.available():
 
1370
        if features.compiled_patiencediff_feature.available():
1304
1371
            from bzrlib._patiencediff_c import recurse_matches_c
1305
1372
            self.assertIs(recurse_matches_c,
1306
1373
                          patiencediff.recurse_matches)
1346
1413
        diff_obj._execute('old', 'new')
1347
1414
        self.assertEqual(output.getvalue().rstrip(), 'old new')
1348
1415
 
1349
 
    def test_excute_missing(self):
 
1416
    def test_execute_missing(self):
1350
1417
        diff_obj = diff.DiffFromTool(['a-tool-which-is-unlikely-to-exist'],
1351
1418
                                     None, None, None)
1352
1419
        self.addCleanup(diff_obj.finish)
1356
1423
                         ' on this machine', str(e))
1357
1424
 
1358
1425
    def test_prepare_files_creates_paths_readable_by_windows_tool(self):
1359
 
        self.requireFeature(AttribFeature)
 
1426
        self.requireFeature(features.AttribFeature)
1360
1427
        output = StringIO()
1361
1428
        tree = self.make_branch_and_tree('tree')
1362
1429
        self.build_tree_contents([('tree/file', 'content')])
1426
1493
    def test_encodable_filename(self):
1427
1494
        # Just checks file path for external diff tool.
1428
1495
        # We cannot change CPython's internal encoding used by os.exec*.
1429
 
        import sys
1430
1496
        diffobj = diff.DiffFromTool(['dummy', '@old_path', '@new_path'],
1431
1497
                                    None, None, None)
1432
1498
        for _, scenario in EncodingAdapter.encoding_scenarios:
1433
1499
            encoding = scenario['encoding']
1434
 
            dirname  = scenario['info']['directory']
 
1500
            dirname = scenario['info']['directory']
1435
1501
            filename = scenario['info']['filename']
1436
1502
 
1437
1503
            self.overrideAttr(diffobj, '_fenc', lambda: encoding)
1438
1504
            relpath = dirname + u'/' + filename
1439
1505
            fullpath = diffobj._safe_filename('safe', relpath)
1440
 
            self.assertEqual(
1441
 
                    fullpath,
1442
 
                    fullpath.encode(encoding).decode(encoding)
1443
 
                    )
1444
 
            self.assert_(fullpath.startswith(diffobj._root + '/safe'))
 
1506
            self.assertEqual(fullpath,
 
1507
                             fullpath.encode(encoding).decode(encoding))
 
1508
            self.assertTrue(fullpath.startswith(diffobj._root + '/safe'))
1445
1509
 
1446
1510
    def test_unencodable_filename(self):
1447
 
        import sys
1448
1511
        diffobj = diff.DiffFromTool(['dummy', '@old_path', '@new_path'],
1449
1512
                                    None, None, None)
1450
1513
        for _, scenario in EncodingAdapter.encoding_scenarios:
1451
1514
            encoding = scenario['encoding']
1452
 
            dirname  = scenario['info']['directory']
 
1515
            dirname = scenario['info']['directory']
1453
1516
            filename = scenario['info']['filename']
1454
1517
 
1455
1518
            if encoding == 'iso-8859-1':
1460
1523
            self.overrideAttr(diffobj, '_fenc', lambda: encoding)
1461
1524
            relpath = dirname + u'/' + filename
1462
1525
            fullpath = diffobj._safe_filename('safe', relpath)
1463
 
            self.assertEqual(
1464
 
                    fullpath,
1465
 
                    fullpath.encode(encoding).decode(encoding)
1466
 
                    )
1467
 
            self.assert_(fullpath.startswith(diffobj._root + '/safe'))
 
1526
            self.assertEqual(fullpath,
 
1527
                             fullpath.encode(encoding).decode(encoding))
 
1528
            self.assertTrue(fullpath.startswith(diffobj._root + '/safe'))
1468
1529
 
1469
1530
 
1470
1531
class TestGetTreesAndBranchesToDiffLocked(tests.TestCaseWithTransport):
1471
1532
 
1472
1533
    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
 
        """
 
1534
        """Call get_trees_and_branches_to_diff_locked."""
1476
1535
        return diff.get_trees_and_branches_to_diff_locked(
1477
1536
            path_list, revision_specs, old_url, new_url, self.addCleanup)
1478
1537
 
1515
1574
        self.assertEqual(tree.branch.base, new_branch.base)
1516
1575
        self.assertIs(None, specific_files)
1517
1576
        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)