~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-05-18 13:02:52 UTC
  • mfrom: (5830.3.6 i18n-msgfmt)
  • Revision ID: pqm@pqm.ubuntu.com-20110518130252-ky96qcvzt6o0zg3f
(mbp) add build_mo command to setup.py (INADA Naoki)

Show diffs side-by-side

added added

removed removed

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