~bzr-pqm/bzr/bzr.dev

4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2005-2010 Canonical Ltd
1711.2.16 by John Arbash Meinel
test_diff needs a copyright statement
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
12
#
1711.2.16 by John Arbash Meinel
test_diff needs a copyright statement
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1711.2.16 by John Arbash Meinel
test_diff needs a copyright statement
16
1740.2.5 by Aaron Bentley
Merge from bzr.dev
17
import os
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
18
from cStringIO import StringIO
1920.1.1 by John Arbash Meinel
fix bug #56307, handle binary files even when LANG is not english
19
import subprocess
3287.18.6 by Matt McClure
Snapshot of unfinished work.
20
import sys
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
21
import tempfile
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
22
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
23
from bzrlib import (
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
24
    diff,
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
25
    errors,
26
    osutils,
5168.1.3 by Vincent Ladeuil
Even more import fixes.
27
    patiencediff,
28
    _patiencediff_py,
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
29
    revision as _mod_revision,
30
    revisionspec,
31
    revisiontree,
32
    tests,
33
    transform,
34
    )
5147.3.7 by Andrew Bennetts
Expect DeprecationWarnings for get_trees_and_branches_to_diff in test_diff, and add corresponding test coverage for get_trees_and_branches_to_diff_locked.
35
from bzrlib.symbol_versioning import deprecated_in
5168.1.3 by Vincent Ladeuil
Even more import fixes.
36
from bzrlib.tests import test_win32utils
4913.5.9 by Gordon Tyler
Use test_win32utils' BackslashDirSeparatorFeature instead of checking sys.platform for win32.
37
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
38
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
39
class _AttribFeature(tests.Feature):
3287.18.20 by Matt McClure
Introduces a Feature subclass to encapsulate the availability of 'attrib'.
40
41
    def _probe(self):
42
        if (sys.platform not in ('cygwin', 'win32')):
3287.18.21 by Matt McClure
Fixes capitalization of False.
43
            return False
3287.18.20 by Matt McClure
Introduces a Feature subclass to encapsulate the availability of 'attrib'.
44
        try:
45
            proc = subprocess.Popen(['attrib', '.'], stdout=subprocess.PIPE)
46
        except OSError, e:
3287.18.21 by Matt McClure
Fixes capitalization of False.
47
            return False
3287.18.20 by Matt McClure
Introduces a Feature subclass to encapsulate the availability of 'attrib'.
48
        return (0 == proc.wait())
3287.18.24 by Matt McClure
Cleans up for submission. Removes comments.
49
3287.18.20 by Matt McClure
Introduces a Feature subclass to encapsulate the availability of 'attrib'.
50
    def feature_name(self):
51
        return 'attrib Windows command-line tool'
52
53
AttribFeature = _AttribFeature()
54
55
4913.2.20 by John Arbash Meinel
Change all of the compiled_foo to compiled_foo_feature
56
compiled_patiencediff_feature = tests.ModuleAvailableFeature(
57
                                    'bzrlib._patiencediff_c')
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
58
59
1558.15.11 by Aaron Bentley
Apply merge review suggestions
60
def udiff_lines(old, new, allow_binary=False):
974.1.6 by Aaron Bentley
Added unit tests
61
    output = StringIO()
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
62
    diff.internal_diff('old', old, 'new', new, output, allow_binary)
974.1.6 by Aaron Bentley
Added unit tests
63
    output.seek(0, 0)
64
    return output.readlines()
65
1711.2.54 by John Arbash Meinel
Use mkstemp instead of NamedTemporary file for external diff.
66
1711.2.57 by John Arbash Meinel
Allow external diff to write to a file without a fileno.
67
def external_udiff_lines(old, new, use_stringio=False):
68
    if use_stringio:
69
        # StringIO has no fileno, so it tests a different codepath
70
        output = StringIO()
71
    else:
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
72
        output = tempfile.TemporaryFile()
1692.8.7 by James Henstridge
changes suggested by John Meinel
73
    try:
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
74
        diff.external_diff('old', old, 'new', new, output, diff_opts=['-u'])
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
75
    except errors.NoDiff:
76
        raise tests.TestSkipped('external "diff" not present to test')
1692.8.2 by James Henstridge
add a test for sending external diff output to a file
77
    output.seek(0, 0)
78
    lines = output.readlines()
79
    output.close()
80
    return lines
81
82
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
83
class TestDiff(tests.TestCase):
1185.81.25 by Aaron Bentley
Clean up test_diff
84
1102 by Martin Pool
- merge test refactoring from robertc
85
    def test_add_nl(self):
86
        """diff generates a valid diff for patches that add a newline"""
974.1.6 by Aaron Bentley
Added unit tests
87
        lines = udiff_lines(['boo'], ['boo\n'])
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
88
        self.check_patch(lines)
89
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
90
            ## "expected no-nl, got %r" % lines[4]
974.1.6 by Aaron Bentley
Added unit tests
91
1102 by Martin Pool
- merge test refactoring from robertc
92
    def test_add_nl_2(self):
93
        """diff generates a valid diff for patches that change last line and
94
        add a newline.
95
        """
974.1.6 by Aaron Bentley
Added unit tests
96
        lines = udiff_lines(['boo'], ['goo\n'])
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
97
        self.check_patch(lines)
98
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
99
            ## "expected no-nl, got %r" % lines[4]
974.1.6 by Aaron Bentley
Added unit tests
100
1102 by Martin Pool
- merge test refactoring from robertc
101
    def test_remove_nl(self):
102
        """diff generates a valid diff for patches that change last line and
103
        add a newline.
104
        """
974.1.6 by Aaron Bentley
Added unit tests
105
        lines = udiff_lines(['boo\n'], ['boo'])
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
106
        self.check_patch(lines)
107
        self.assertEquals(lines[5], '\\ No newline at end of file\n')
108
            ## "expected no-nl, got %r" % lines[5]
109
110
    def check_patch(self, lines):
111
        self.assert_(len(lines) > 1)
112
            ## "Not enough lines for a file header for patch:\n%s" % "".join(lines)
113
        self.assert_(lines[0].startswith ('---'))
114
            ## 'No orig line for patch:\n%s' % "".join(lines)
115
        self.assert_(lines[1].startswith ('+++'))
116
            ## 'No mod line for patch:\n%s' % "".join(lines)
117
        self.assert_(len(lines) > 2)
118
            ## "No hunks for patch:\n%s" % "".join(lines)
119
        self.assert_(lines[2].startswith('@@'))
120
            ## "No hunk header for patch:\n%s" % "".join(lines)
121
        self.assert_('@@' in lines[2][2:])
122
            ## "Unterminated hunk header for patch:\n%s" % "".join(lines)
123
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
124
    def test_binary_lines(self):
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
125
        empty = []
126
        uni_lines = [1023 * 'a' + '\x00']
127
        self.assertRaises(errors.BinaryFile, udiff_lines, uni_lines , empty)
128
        self.assertRaises(errors.BinaryFile, udiff_lines, empty, uni_lines)
129
        udiff_lines(uni_lines , empty, allow_binary=True)
130
        udiff_lines(empty, uni_lines, allow_binary=True)
1692.8.2 by James Henstridge
add a test for sending external diff output to a file
131
132
    def test_external_diff(self):
133
        lines = external_udiff_lines(['boo\n'], ['goo\n'])
134
        self.check_patch(lines)
1899.1.6 by John Arbash Meinel
internal_diff always adds a trailing \n, make sure external_diff does too
135
        self.assertEqual('\n', lines[-1])
1711.2.57 by John Arbash Meinel
Allow external diff to write to a file without a fileno.
136
137
    def test_external_diff_no_fileno(self):
138
        # Make sure that we can handle not having a fileno, even
139
        # if the diff is large
140
        lines = external_udiff_lines(['boo\n']*10000,
141
                                     ['goo\n']*10000,
142
                                     use_stringio=True)
143
        self.check_patch(lines)
1899.1.1 by John Arbash Meinel
Fix the bug in the NoDiff exception class, and add a test
144
1920.1.1 by John Arbash Meinel
fix bug #56307, handle binary files even when LANG is not english
145
    def test_external_diff_binary_lang_c(self):
2321.2.5 by Alexander Belchenko
external diff: no need for special code path for win32 (suggested by John Meinel)
146
        old_env = {}
147
        for lang in ('LANG', 'LC_ALL', 'LANGUAGE'):
148
            old_env[lang] = osutils.set_or_unset_env(lang, 'C')
1920.1.1 by John Arbash Meinel
fix bug #56307, handle binary files even when LANG is not english
149
        try:
150
            lines = external_udiff_lines(['\x00foobar\n'], ['foo\x00bar\n'])
1959.1.1 by Marien Zwart
merge.
151
            # Older versions of diffutils say "Binary files", newer
152
            # versions just say "Files".
153
            self.assertContainsRe(lines[0],
154
                                  '(Binary f|F)iles old and new differ\n')
155
            self.assertEquals(lines[1:], ['\n'])
1920.1.1 by John Arbash Meinel
fix bug #56307, handle binary files even when LANG is not english
156
        finally:
2321.2.5 by Alexander Belchenko
external diff: no need for special code path for win32 (suggested by John Meinel)
157
            for lang, old_val in old_env.iteritems():
158
                osutils.set_or_unset_env(lang, old_val)
1899.1.4 by John Arbash Meinel
Just swallow a return code of 2
159
1899.1.1 by John Arbash Meinel
Fix the bug in the NoDiff exception class, and add a test
160
    def test_no_external_diff(self):
161
        """Check that NoDiff is raised when diff is not available"""
162
        # Use os.environ['PATH'] to make sure no 'diff' command is available
163
        orig_path = os.environ['PATH']
164
        try:
165
            os.environ['PATH'] = ''
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
166
            self.assertRaises(errors.NoDiff, diff.external_diff,
1899.1.1 by John Arbash Meinel
Fix the bug in the NoDiff exception class, and add a test
167
                              'old', ['boo\n'], 'new', ['goo\n'],
168
                              StringIO(), diff_opts=['-u'])
169
        finally:
170
            os.environ['PATH'] = orig_path
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
171
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
172
    def test_internal_diff_default(self):
173
        # Default internal diff encoding is utf8
174
        output = StringIO()
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
175
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
176
                           u'new_\xe5', ['new_text\n'], output)
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
177
        lines = output.getvalue().splitlines(True)
178
        self.check_patch(lines)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
179
        self.assertEquals(['--- old_\xc2\xb5\n',
180
                           '+++ new_\xc3\xa5\n',
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
181
                           '@@ -1,1 +1,1 @@\n',
182
                           '-old_text\n',
183
                           '+new_text\n',
184
                           '\n',
185
                          ]
186
                          , lines)
187
188
    def test_internal_diff_utf8(self):
189
        output = StringIO()
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
190
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
191
                           u'new_\xe5', ['new_text\n'], output,
192
                           path_encoding='utf8')
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
193
        lines = output.getvalue().splitlines(True)
194
        self.check_patch(lines)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
195
        self.assertEquals(['--- old_\xc2\xb5\n',
196
                           '+++ new_\xc3\xa5\n',
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
197
                           '@@ -1,1 +1,1 @@\n',
198
                           '-old_text\n',
199
                           '+new_text\n',
200
                           '\n',
201
                          ]
202
                          , lines)
203
204
    def test_internal_diff_iso_8859_1(self):
205
        output = StringIO()
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
206
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
207
                           u'new_\xe5', ['new_text\n'], output,
208
                           path_encoding='iso-8859-1')
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
209
        lines = output.getvalue().splitlines(True)
210
        self.check_patch(lines)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
211
        self.assertEquals(['--- old_\xb5\n',
212
                           '+++ new_\xe5\n',
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
213
                           '@@ -1,1 +1,1 @@\n',
214
                           '-old_text\n',
215
                           '+new_text\n',
216
                           '\n',
217
                          ]
218
                          , lines)
219
3085.1.1 by John Arbash Meinel
Fix internal_diff to not fail when the texts are identical.
220
    def test_internal_diff_no_content(self):
221
        output = StringIO()
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
222
        diff.internal_diff(u'old', [], u'new', [], output)
3085.1.1 by John Arbash Meinel
Fix internal_diff to not fail when the texts are identical.
223
        self.assertEqual('', output.getvalue())
224
225
    def test_internal_diff_no_changes(self):
226
        output = StringIO()
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
227
        diff.internal_diff(u'old', ['text\n', 'contents\n'],
228
                           u'new', ['text\n', 'contents\n'],
229
                           output)
3085.1.1 by John Arbash Meinel
Fix internal_diff to not fail when the texts are identical.
230
        self.assertEqual('', output.getvalue())
231
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
232
    def test_internal_diff_returns_bytes(self):
233
        import StringIO
234
        output = StringIO.StringIO()
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
235
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
236
                            u'new_\xe5', ['new_text\n'], output)
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
237
        self.failUnless(isinstance(output.getvalue(), str),
238
            'internal_diff should return bytestrings')
239
1185.81.25 by Aaron Bentley
Clean up test_diff
240
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
241
class TestDiffFiles(tests.TestCaseInTempDir):
1920.1.1 by John Arbash Meinel
fix bug #56307, handle binary files even when LANG is not english
242
243
    def test_external_diff_binary(self):
244
        """The output when using external diff should use diff's i18n error"""
245
        # Make sure external_diff doesn't fail in the current LANG
246
        lines = external_udiff_lines(['\x00foobar\n'], ['foo\x00bar\n'])
247
2240.1.1 by Alexander Belchenko
test_external_diff_binary: run external diff with --binary flag
248
        cmd = ['diff', '-u', '--binary', 'old', 'new']
1920.1.1 by John Arbash Meinel
fix bug #56307, handle binary files even when LANG is not english
249
        open('old', 'wb').write('\x00foobar\n')
250
        open('new', 'wb').write('foo\x00bar\n')
251
        pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE,
252
                                     stdin=subprocess.PIPE)
253
        out, err = pipe.communicate()
254
        # Diff returns '2' on Binary files.
255
        self.assertEqual(2, pipe.returncode)
256
        # We should output whatever diff tells us, plus a trailing newline
257
        self.assertEqual(out.splitlines(True) + ['\n'], lines)
258
259
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
260
class TestShowDiffTreesHelper(tests.TestCaseWithTransport):
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
261
    """Has a helper for running show_diff_trees"""
262
263
    def get_diff(self, tree1, tree2, specific_files=None, working_tree=None):
264
        output = StringIO()
265
        if working_tree is not None:
266
            extra_trees = (working_tree,)
267
        else:
268
            extra_trees = ()
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
269
        diff.show_diff_trees(tree1, tree2, output,
270
                             specific_files=specific_files,
271
                             extra_trees=extra_trees, old_label='old/',
272
                             new_label='new/')
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
273
        return output.getvalue()
274
275
276
class TestDiffDates(TestShowDiffTreesHelper):
1740.2.5 by Aaron Bentley
Merge from bzr.dev
277
278
    def setUp(self):
279
        super(TestDiffDates, self).setUp()
280
        self.wt = self.make_branch_and_tree('.')
281
        self.b = self.wt.branch
282
        self.build_tree_contents([
283
            ('file1', 'file1 contents at rev 1\n'),
284
            ('file2', 'file2 contents at rev 1\n')
285
            ])
286
        self.wt.add(['file1', 'file2'])
287
        self.wt.commit(
288
            message='Revision 1',
289
            timestamp=1143849600, # 2006-04-01 00:00:00 UTC
290
            timezone=0,
291
            rev_id='rev-1')
292
        self.build_tree_contents([('file1', 'file1 contents at rev 2\n')])
293
        self.wt.commit(
294
            message='Revision 2',
295
            timestamp=1143936000, # 2006-04-02 00:00:00 UTC
296
            timezone=28800,
297
            rev_id='rev-2')
298
        self.build_tree_contents([('file2', 'file2 contents at rev 3\n')])
299
        self.wt.commit(
300
            message='Revision 3',
301
            timestamp=1144022400, # 2006-04-03 00:00:00 UTC
302
            timezone=-3600,
303
            rev_id='rev-3')
304
        self.wt.remove(['file2'])
305
        self.wt.commit(
306
            message='Revision 4',
307
            timestamp=1144108800, # 2006-04-04 00:00:00 UTC
308
            timezone=0,
309
            rev_id='rev-4')
310
        self.build_tree_contents([
311
            ('file1', 'file1 contents in working tree\n')
312
            ])
313
        # set the date stamps for files in the working tree to known values
314
        os.utime('file1', (1144195200, 1144195200)) # 2006-04-05 00:00:00 UTC
315
316
    def test_diff_rev_tree_working_tree(self):
317
        output = self.get_diff(self.wt.basis_tree(), self.wt)
318
        # note that the date for old/file1 is from rev 2 rather than from
319
        # the basis revision (rev 4)
320
        self.assertEqualDiff(output, '''\
321
=== modified file 'file1'
322
--- old/file1\t2006-04-02 00:00:00 +0000
323
+++ new/file1\t2006-04-05 00:00:00 +0000
324
@@ -1,1 +1,1 @@
325
-file1 contents at rev 2
326
+file1 contents in working tree
327
328
''')
329
330
    def test_diff_rev_tree_rev_tree(self):
331
        tree1 = self.b.repository.revision_tree('rev-2')
332
        tree2 = self.b.repository.revision_tree('rev-3')
333
        output = self.get_diff(tree1, tree2)
334
        self.assertEqualDiff(output, '''\
335
=== modified file 'file2'
336
--- old/file2\t2006-04-01 00:00:00 +0000
337
+++ new/file2\t2006-04-03 00:00:00 +0000
338
@@ -1,1 +1,1 @@
339
-file2 contents at rev 1
340
+file2 contents at rev 3
341
342
''')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
343
1740.2.5 by Aaron Bentley
Merge from bzr.dev
344
    def test_diff_add_files(self):
3668.5.1 by Jelmer Vernooij
Use NULL_REVISION rather than None for Repository.revision_tree().
345
        tree1 = self.b.repository.revision_tree(_mod_revision.NULL_REVISION)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
346
        tree2 = self.b.repository.revision_tree('rev-1')
347
        output = self.get_diff(tree1, tree2)
348
        # the files have the epoch time stamp for the tree in which
349
        # they don't exist.
350
        self.assertEqualDiff(output, '''\
351
=== added file 'file1'
352
--- old/file1\t1970-01-01 00:00:00 +0000
353
+++ new/file1\t2006-04-01 00:00:00 +0000
354
@@ -0,0 +1,1 @@
355
+file1 contents at rev 1
356
357
=== added file 'file2'
358
--- old/file2\t1970-01-01 00:00:00 +0000
359
+++ new/file2\t2006-04-01 00:00:00 +0000
360
@@ -0,0 +1,1 @@
361
+file2 contents at rev 1
362
363
''')
364
365
    def test_diff_remove_files(self):
366
        tree1 = self.b.repository.revision_tree('rev-3')
367
        tree2 = self.b.repository.revision_tree('rev-4')
368
        output = self.get_diff(tree1, tree2)
369
        # the file has the epoch time stamp for the tree in which
370
        # it doesn't exist.
371
        self.assertEqualDiff(output, '''\
372
=== removed file 'file2'
373
--- old/file2\t2006-04-03 00:00:00 +0000
374
+++ new/file2\t1970-01-01 00:00:00 +0000
375
@@ -1,1 +0,0 @@
376
-file2 contents at rev 3
377
378
''')
379
1551.7.17 by Aaron Bentley
Switch to PathsNotVersioned, accept extra_trees
380
    def test_show_diff_specified(self):
1551.7.22 by Aaron Bentley
Changes from review
381
        """A working tree filename can be used to identify a file"""
1551.7.17 by Aaron Bentley
Switch to PathsNotVersioned, accept extra_trees
382
        self.wt.rename_one('file1', 'file1b')
383
        old_tree = self.b.repository.revision_tree('rev-1')
384
        new_tree = self.b.repository.revision_tree('rev-4')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
385
        out = self.get_diff(old_tree, new_tree, specific_files=['file1b'],
1551.7.22 by Aaron Bentley
Changes from review
386
                            working_tree=self.wt)
387
        self.assertContainsRe(out, 'file1\t')
1551.7.17 by Aaron Bentley
Switch to PathsNotVersioned, accept extra_trees
388
1551.7.22 by Aaron Bentley
Changes from review
389
    def test_recursive_diff(self):
390
        """Children of directories are matched"""
391
        os.mkdir('dir1')
392
        os.mkdir('dir2')
393
        self.wt.add(['dir1', 'dir2'])
394
        self.wt.rename_one('file1', 'dir1/file1')
395
        old_tree = self.b.repository.revision_tree('rev-1')
396
        new_tree = self.b.repository.revision_tree('rev-4')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
397
        out = self.get_diff(old_tree, new_tree, specific_files=['dir1'],
1551.7.22 by Aaron Bentley
Changes from review
398
                            working_tree=self.wt)
399
        self.assertContainsRe(out, 'file1\t')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
400
        out = self.get_diff(old_tree, new_tree, specific_files=['dir2'],
1551.7.22 by Aaron Bentley
Changes from review
401
                            working_tree=self.wt)
402
        self.assertNotContainsRe(out, 'file1\t')
1740.2.5 by Aaron Bentley
Merge from bzr.dev
403
1899.1.1 by John Arbash Meinel
Fix the bug in the NoDiff exception class, and add a test
404
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
405
406
class TestShowDiffTrees(TestShowDiffTreesHelper):
407
    """Direct tests for show_diff_trees"""
408
409
    def test_modified_file(self):
410
        """Test when a file is modified."""
411
        tree = self.make_branch_and_tree('tree')
412
        self.build_tree_contents([('tree/file', 'contents\n')])
413
        tree.add(['file'], ['file-id'])
414
        tree.commit('one', rev_id='rev-1')
415
416
        self.build_tree_contents([('tree/file', 'new contents\n')])
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
417
        d = self.get_diff(tree.basis_tree(), tree)
418
        self.assertContainsRe(d, "=== modified file 'file'\n")
419
        self.assertContainsRe(d, '--- old/file\t')
420
        self.assertContainsRe(d, '\\+\\+\\+ new/file\t')
421
        self.assertContainsRe(d, '-contents\n'
422
                                 '\\+new contents\n')
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
423
2405.1.2 by John Arbash Meinel
Fix bug #103870 by passing None instead of a (sometimes wrong) path
424
    def test_modified_file_in_renamed_dir(self):
425
        """Test when a file is modified in a renamed directory."""
426
        tree = self.make_branch_and_tree('tree')
427
        self.build_tree(['tree/dir/'])
428
        self.build_tree_contents([('tree/dir/file', 'contents\n')])
429
        tree.add(['dir', 'dir/file'], ['dir-id', 'file-id'])
430
        tree.commit('one', rev_id='rev-1')
431
432
        tree.rename_one('dir', 'other')
433
        self.build_tree_contents([('tree/other/file', 'new contents\n')])
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
434
        d = self.get_diff(tree.basis_tree(), tree)
435
        self.assertContainsRe(d, "=== renamed directory 'dir' => 'other'\n")
436
        self.assertContainsRe(d, "=== modified file 'other/file'\n")
2405.1.2 by John Arbash Meinel
Fix bug #103870 by passing None instead of a (sometimes wrong) path
437
        # XXX: This is technically incorrect, because it used to be at another
438
        # location. What to do?
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
439
        self.assertContainsRe(d, '--- old/dir/file\t')
440
        self.assertContainsRe(d, '\\+\\+\\+ new/other/file\t')
441
        self.assertContainsRe(d, '-contents\n'
442
                                 '\\+new contents\n')
2405.1.2 by John Arbash Meinel
Fix bug #103870 by passing None instead of a (sometimes wrong) path
443
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
444
    def test_renamed_directory(self):
445
        """Test when only a directory is only renamed."""
446
        tree = self.make_branch_and_tree('tree')
447
        self.build_tree(['tree/dir/'])
448
        self.build_tree_contents([('tree/dir/file', 'contents\n')])
449
        tree.add(['dir', 'dir/file'], ['dir-id', 'file-id'])
450
        tree.commit('one', rev_id='rev-1')
451
452
        tree.rename_one('dir', 'newdir')
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
453
        d = self.get_diff(tree.basis_tree(), tree)
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
454
        # Renaming a directory should be a single "you renamed this dir" even
455
        # when there are files inside.
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
456
        self.assertEqual(d, "=== renamed directory 'dir' => 'newdir'\n")
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
457
458
    def test_renamed_file(self):
459
        """Test when a file is only renamed."""
460
        tree = self.make_branch_and_tree('tree')
461
        self.build_tree_contents([('tree/file', 'contents\n')])
462
        tree.add(['file'], ['file-id'])
463
        tree.commit('one', rev_id='rev-1')
464
465
        tree.rename_one('file', 'newname')
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
466
        d = self.get_diff(tree.basis_tree(), tree)
467
        self.assertContainsRe(d, "=== renamed file 'file' => 'newname'\n")
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
468
        # We shouldn't have a --- or +++ line, because there is no content
469
        # change
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
470
        self.assertNotContainsRe(d, '---')
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
471
472
    def test_renamed_and_modified_file(self):
473
        """Test when a file is only renamed."""
474
        tree = self.make_branch_and_tree('tree')
475
        self.build_tree_contents([('tree/file', 'contents\n')])
476
        tree.add(['file'], ['file-id'])
477
        tree.commit('one', rev_id='rev-1')
478
479
        tree.rename_one('file', 'newname')
480
        self.build_tree_contents([('tree/newname', 'new contents\n')])
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
481
        d = self.get_diff(tree.basis_tree(), tree)
482
        self.assertContainsRe(d, "=== renamed file 'file' => 'newname'\n")
483
        self.assertContainsRe(d, '--- old/file\t')
484
        self.assertContainsRe(d, '\\+\\+\\+ new/newname\t')
485
        self.assertContainsRe(d, '-contents\n'
486
                                 '\\+new contents\n')
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
487
3268.1.1 by C Miller
Describe the property changes in diffs. Currently, this is the executable-bit
488
489
    def test_internal_diff_exec_property(self):
490
        tree = self.make_branch_and_tree('tree')
491
492
        tt = transform.TreeTransform(tree)
493
        tt.new_file('a', tt.root, 'contents\n', 'a-id', True)
494
        tt.new_file('b', tt.root, 'contents\n', 'b-id', False)
495
        tt.new_file('c', tt.root, 'contents\n', 'c-id', True)
496
        tt.new_file('d', tt.root, 'contents\n', 'd-id', False)
497
        tt.new_file('e', tt.root, 'contents\n', 'control-e-id', True)
498
        tt.new_file('f', tt.root, 'contents\n', 'control-f-id', False)
499
        tt.apply()
500
        tree.commit('one', rev_id='rev-1')
501
502
        tt = transform.TreeTransform(tree)
503
        tt.set_executability(False, tt.trans_id_file_id('a-id'))
504
        tt.set_executability(True, tt.trans_id_file_id('b-id'))
505
        tt.set_executability(False, tt.trans_id_file_id('c-id'))
506
        tt.set_executability(True, tt.trans_id_file_id('d-id'))
507
        tt.apply()
508
        tree.rename_one('c', 'new-c')
509
        tree.rename_one('d', 'new-d')
510
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
511
        d = self.get_diff(tree.basis_tree(), tree)
3268.1.1 by C Miller
Describe the property changes in diffs. Currently, this is the executable-bit
512
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
513
        self.assertContainsRe(d, r"file 'a'.*\(properties changed:"
514
                                  ".*\+x to -x.*\)")
515
        self.assertContainsRe(d, r"file 'b'.*\(properties changed:"
516
                                  ".*-x to \+x.*\)")
517
        self.assertContainsRe(d, r"file 'c'.*\(properties changed:"
518
                                  ".*\+x to -x.*\)")
519
        self.assertContainsRe(d, r"file 'd'.*\(properties changed:"
520
                                  ".*-x to \+x.*\)")
521
        self.assertNotContainsRe(d, r"file 'e'")
522
        self.assertNotContainsRe(d, r"file 'f'")
3268.1.1 by C Miller
Describe the property changes in diffs. Currently, this is the executable-bit
523
524
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
525
    def test_binary_unicode_filenames(self):
2592.2.2 by Jonathan Lange
Apply jam's comments to test_binary_unicode_filenames. Change the
526
        """Test that contents of files are *not* encoded in UTF-8 when there
527
        is a binary file in the diff.
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
528
        """
529
        # See https://bugs.launchpad.net/bugs/110092.
3477.1.2 by John Arbash Meinel
Rename UnicodeFilename => UnicodeFilenameFeature
530
        self.requireFeature(tests.UnicodeFilenameFeature)
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
531
532
        # This bug isn't triggered with cStringIO.
533
        from StringIO import StringIO
534
        tree = self.make_branch_and_tree('tree')
2592.2.2 by Jonathan Lange
Apply jam's comments to test_binary_unicode_filenames. Change the
535
        alpha, omega = u'\u03b1', u'\u03c9'
536
        alpha_utf8, omega_utf8 = alpha.encode('utf8'), omega.encode('utf8')
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
537
        self.build_tree_contents(
2592.2.2 by Jonathan Lange
Apply jam's comments to test_binary_unicode_filenames. Change the
538
            [('tree/' + alpha, chr(0)),
539
             ('tree/' + omega,
540
              ('The %s and the %s\n' % (alpha_utf8, omega_utf8)))])
541
        tree.add([alpha], ['file-id'])
542
        tree.add([omega], ['file-id-2'])
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
543
        diff_content = StringIO()
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
544
        diff.show_diff_trees(tree.basis_tree(), tree, diff_content)
545
        d = diff_content.getvalue()
546
        self.assertContainsRe(d, r"=== added file '%s'" % alpha_utf8)
547
        self.assertContainsRe(d, "Binary files a/%s.*and b/%s.* differ\n"
548
                              % (alpha_utf8, alpha_utf8))
549
        self.assertContainsRe(d, r"=== added file '%s'" % omega_utf8)
550
        self.assertContainsRe(d, r"--- a/%s" % (omega_utf8,))
551
        self.assertContainsRe(d, r"\+\+\+ b/%s" % (omega_utf8,))
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
552
2725.2.1 by ghigo
When a unicode filename is renamed, in the diff is showed a wrong result
553
    def test_unicode_filename(self):
554
        """Test when the filename are unicode."""
3477.1.2 by John Arbash Meinel
Rename UnicodeFilename => UnicodeFilenameFeature
555
        self.requireFeature(tests.UnicodeFilenameFeature)
2725.2.1 by ghigo
When a unicode filename is renamed, in the diff is showed a wrong result
556
557
        alpha, omega = u'\u03b1', u'\u03c9'
558
        autf8, outf8 = alpha.encode('utf8'), omega.encode('utf8')
559
560
        tree = self.make_branch_and_tree('tree')
561
        self.build_tree_contents([('tree/ren_'+alpha, 'contents\n')])
562
        tree.add(['ren_'+alpha], ['file-id-2'])
563
        self.build_tree_contents([('tree/del_'+alpha, 'contents\n')])
564
        tree.add(['del_'+alpha], ['file-id-3'])
565
        self.build_tree_contents([('tree/mod_'+alpha, 'contents\n')])
566
        tree.add(['mod_'+alpha], ['file-id-4'])
567
568
        tree.commit('one', rev_id='rev-1')
569
570
        tree.rename_one('ren_'+alpha, 'ren_'+omega)
571
        tree.remove('del_'+alpha)
572
        self.build_tree_contents([('tree/add_'+alpha, 'contents\n')])
573
        tree.add(['add_'+alpha], ['file-id'])
574
        self.build_tree_contents([('tree/mod_'+alpha, 'contents_mod\n')])
575
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
576
        d = self.get_diff(tree.basis_tree(), tree)
577
        self.assertContainsRe(d,
2725.2.1 by ghigo
When a unicode filename is renamed, in the diff is showed a wrong result
578
                "=== renamed file 'ren_%s' => 'ren_%s'\n"%(autf8, outf8))
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
579
        self.assertContainsRe(d, "=== added file 'add_%s'"%autf8)
580
        self.assertContainsRe(d, "=== modified file 'mod_%s'"%autf8)
581
        self.assertContainsRe(d, "=== removed file 'del_%s'"%autf8)
582
583
584
class DiffWasIs(diff.DiffPath):
3009.2.15 by Aaron Bentley
Test differ registration
585
586
    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
587
        self.to_file.write('was: ')
588
        self.to_file.write(self.old_tree.get_file(file_id).read())
589
        self.to_file.write('is: ')
590
        self.to_file.write(self.new_tree.get_file(file_id).read())
591
        pass
592
593
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
594
class TestDiffTree(tests.TestCaseWithTransport):
3009.2.9 by Aaron Bentley
Add tests for Differ
595
596
    def setUp(self):
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
597
        super(TestDiffTree, self).setUp()
3009.2.9 by Aaron Bentley
Add tests for Differ
598
        self.old_tree = self.make_branch_and_tree('old-tree')
599
        self.old_tree.lock_write()
600
        self.addCleanup(self.old_tree.unlock)
601
        self.new_tree = self.make_branch_and_tree('new-tree')
602
        self.new_tree.lock_write()
603
        self.addCleanup(self.new_tree.unlock)
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
604
        self.differ = diff.DiffTree(self.old_tree, self.new_tree, StringIO())
3009.2.9 by Aaron Bentley
Add tests for Differ
605
606
    def test_diff_text(self):
607
        self.build_tree_contents([('old-tree/olddir/',),
608
                                  ('old-tree/olddir/oldfile', 'old\n')])
609
        self.old_tree.add('olddir')
610
        self.old_tree.add('olddir/oldfile', 'file-id')
611
        self.build_tree_contents([('new-tree/newdir/',),
612
                                  ('new-tree/newdir/newfile', 'new\n')])
613
        self.new_tree.add('newdir')
614
        self.new_tree.add('newdir/newfile', 'file-id')
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
615
        differ = diff.DiffText(self.old_tree, self.new_tree, StringIO())
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
616
        differ.diff_text('file-id', None, 'old label', 'new label')
3009.2.9 by Aaron Bentley
Add tests for Differ
617
        self.assertEqual(
618
            '--- old label\n+++ new label\n@@ -1,1 +0,0 @@\n-old\n\n',
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
619
            differ.to_file.getvalue())
620
        differ.to_file.seek(0)
621
        differ.diff_text(None, 'file-id', 'old label', 'new label')
3009.2.9 by Aaron Bentley
Add tests for Differ
622
        self.assertEqual(
623
            '--- old label\n+++ new label\n@@ -0,0 +1,1 @@\n+new\n\n',
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
624
            differ.to_file.getvalue())
625
        differ.to_file.seek(0)
626
        differ.diff_text('file-id', 'file-id', 'old label', 'new label')
3009.2.9 by Aaron Bentley
Add tests for Differ
627
        self.assertEqual(
628
            '--- old label\n+++ new label\n@@ -1,1 +1,1 @@\n-old\n+new\n\n',
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
629
            differ.to_file.getvalue())
3009.2.9 by Aaron Bentley
Add tests for Differ
630
3087.1.1 by Aaron Bentley
Diff handles missing files correctly, with no tracebacks
631
    def test_diff_deletion(self):
632
        self.build_tree_contents([('old-tree/file', 'contents'),
633
                                  ('new-tree/file', 'contents')])
634
        self.old_tree.add('file', 'file-id')
635
        self.new_tree.add('file', 'file-id')
636
        os.unlink('new-tree/file')
637
        self.differ.show_diff(None)
638
        self.assertContainsRe(self.differ.to_file.getvalue(), '-contents')
639
640
    def test_diff_creation(self):
641
        self.build_tree_contents([('old-tree/file', 'contents'),
642
                                  ('new-tree/file', 'contents')])
643
        self.old_tree.add('file', 'file-id')
644
        self.new_tree.add('file', 'file-id')
645
        os.unlink('old-tree/file')
646
        self.differ.show_diff(None)
647
        self.assertContainsRe(self.differ.to_file.getvalue(), '\+contents')
648
3009.2.9 by Aaron Bentley
Add tests for Differ
649
    def test_diff_symlink(self):
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
650
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, StringIO())
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
651
        differ.diff_symlink('old target', None)
3009.2.9 by Aaron Bentley
Add tests for Differ
652
        self.assertEqual("=== target was 'old target'\n",
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
653
                         differ.to_file.getvalue())
3009.2.9 by Aaron Bentley
Add tests for Differ
654
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
655
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, StringIO())
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
656
        differ.diff_symlink(None, 'new target')
3009.2.9 by Aaron Bentley
Add tests for Differ
657
        self.assertEqual("=== target is 'new target'\n",
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
658
                         differ.to_file.getvalue())
659
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
660
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, StringIO())
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
661
        differ.diff_symlink('old target', 'new target')
3009.2.9 by Aaron Bentley
Add tests for Differ
662
        self.assertEqual("=== target changed 'old target' => 'new target'\n",
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
663
                         differ.to_file.getvalue())
3009.2.9 by Aaron Bentley
Add tests for Differ
664
665
    def test_diff(self):
666
        self.build_tree_contents([('old-tree/olddir/',),
667
                                  ('old-tree/olddir/oldfile', 'old\n')])
668
        self.old_tree.add('olddir')
669
        self.old_tree.add('olddir/oldfile', 'file-id')
670
        self.build_tree_contents([('new-tree/newdir/',),
671
                                  ('new-tree/newdir/newfile', 'new\n')])
672
        self.new_tree.add('newdir')
673
        self.new_tree.add('newdir/newfile', 'file-id')
3009.2.12 by Aaron Bentley
Associate labels with text diffing only
674
        self.differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
3009.2.9 by Aaron Bentley
Add tests for Differ
675
        self.assertContainsRe(
676
            self.differ.to_file.getvalue(),
677
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
678
             ' \@\@\n-old\n\+new\n\n')
679
680
    def test_diff_kind_change(self):
3146.4.3 by Aaron Bentley
Add missing Symlink requirement
681
        self.requireFeature(tests.SymlinkFeature)
3009.2.9 by Aaron Bentley
Add tests for Differ
682
        self.build_tree_contents([('old-tree/olddir/',),
683
                                  ('old-tree/olddir/oldfile', 'old\n')])
684
        self.old_tree.add('olddir')
685
        self.old_tree.add('olddir/oldfile', 'file-id')
686
        self.build_tree(['new-tree/newdir/'])
687
        os.symlink('new', 'new-tree/newdir/newfile')
688
        self.new_tree.add('newdir')
689
        self.new_tree.add('newdir/newfile', 'file-id')
3009.2.12 by Aaron Bentley
Associate labels with text diffing only
690
        self.differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
3009.2.9 by Aaron Bentley
Add tests for Differ
691
        self.assertContainsRe(
692
            self.differ.to_file.getvalue(),
693
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+0,0'
694
             ' \@\@\n-old\n\n')
695
        self.assertContainsRe(self.differ.to_file.getvalue(),
4216.3.1 by Robert Collins
Fix Tree.get_symlink_target to decode from the disk encoding to get a unicode encoded string.
696
                              "=== target is u'new'\n")
3009.2.9 by Aaron Bentley
Add tests for Differ
697
3009.2.19 by Aaron Bentley
Implement directory diffing
698
    def test_diff_directory(self):
699
        self.build_tree(['new-tree/new-dir/'])
700
        self.new_tree.add('new-dir', 'new-dir-id')
701
        self.differ.diff('new-dir-id', None, 'new-dir')
702
        self.assertEqual(self.differ.to_file.getvalue(), '')
703
3009.2.16 by Aaron Bentley
Test support for extra differs
704
    def create_old_new(self):
705
        self.build_tree_contents([('old-tree/olddir/',),
706
                                  ('old-tree/olddir/oldfile', 'old\n')])
707
        self.old_tree.add('olddir')
708
        self.old_tree.add('olddir/oldfile', 'file-id')
709
        self.build_tree_contents([('new-tree/newdir/',),
710
                                  ('new-tree/newdir/newfile', 'new\n')])
711
        self.new_tree.add('newdir')
712
        self.new_tree.add('newdir/newfile', 'file-id')
713
3009.2.27 by Aaron Bentley
Use extra_factories instead of extra_diffs
714
    def test_register_diff(self):
3009.2.16 by Aaron Bentley
Test support for extra differs
715
        self.create_old_new()
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
716
        old_diff_factories = diff.DiffTree.diff_factories
717
        diff.DiffTree.diff_factories=old_diff_factories[:]
718
        diff.DiffTree.diff_factories.insert(0, DiffWasIs.from_diff_tree)
3009.2.16 by Aaron Bentley
Test support for extra differs
719
        try:
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
720
            differ = diff.DiffTree(self.old_tree, self.new_tree, StringIO())
3009.2.16 by Aaron Bentley
Test support for extra differs
721
        finally:
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
722
            diff.DiffTree.diff_factories = old_diff_factories
3009.2.16 by Aaron Bentley
Test support for extra differs
723
        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
724
        self.assertNotContainsRe(
725
            differ.to_file.getvalue(),
726
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
727
             ' \@\@\n-old\n\+new\n\n')
728
        self.assertContainsRe(differ.to_file.getvalue(),
729
                              'was: old\nis: new\n')
730
3009.2.27 by Aaron Bentley
Use extra_factories instead of extra_diffs
731
    def test_extra_factories(self):
3009.2.16 by Aaron Bentley
Test support for extra differs
732
        self.create_old_new()
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
733
        differ = diff.DiffTree(self.old_tree, self.new_tree, StringIO(),
734
                               extra_factories=[DiffWasIs.from_diff_tree])
3009.2.16 by Aaron Bentley
Test support for extra differs
735
        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
736
        self.assertNotContainsRe(
737
            differ.to_file.getvalue(),
738
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
739
             ' \@\@\n-old\n\+new\n\n')
740
        self.assertContainsRe(differ.to_file.getvalue(),
741
                              'was: old\nis: new\n')
742
3123.4.1 by Aaron Bentley
Diff sorts files in alphabetical order
743
    def test_alphabetical_order(self):
744
        self.build_tree(['new-tree/a-file'])
745
        self.new_tree.add('a-file')
746
        self.build_tree(['old-tree/b-file'])
747
        self.old_tree.add('b-file')
748
        self.differ.show_diff(None)
749
        self.assertContainsRe(self.differ.to_file.getvalue(),
750
            '.*a-file(.|\n)*b-file')
751
3009.2.9 by Aaron Bentley
Add tests for Differ
752
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
753
class TestPatienceDiffLib(tests.TestCase):
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
754
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
755
    def setUp(self):
756
        super(TestPatienceDiffLib, self).setUp()
5168.1.3 by Vincent Ladeuil
Even more import fixes.
757
        self._unique_lcs = _patiencediff_py.unique_lcs_py
758
        self._recurse_matches = _patiencediff_py.recurse_matches_py
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
759
        self._PatienceSequenceMatcher = \
5168.1.3 by Vincent Ladeuil
Even more import fixes.
760
            _patiencediff_py.PatienceSequenceMatcher_py
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
761
3628.1.3 by Lukáš Lalinský
Add a test
762
    def test_diff_unicode_string(self):
763
        a = ''.join([unichr(i) for i in range(4000, 4500, 3)])
764
        b = ''.join([unichr(i) for i in range(4300, 4800, 2)])
765
        sm = self._PatienceSequenceMatcher(None, a, b)
766
        mb = sm.get_matching_blocks()
767
        self.assertEquals(35, len(mb))
768
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
769
    def test_unique_lcs(self):
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
770
        unique_lcs = self._unique_lcs
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
771
        self.assertEquals(unique_lcs('', ''), [])
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
772
        self.assertEquals(unique_lcs('', 'a'), [])
773
        self.assertEquals(unique_lcs('a', ''), [])
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
774
        self.assertEquals(unique_lcs('a', 'a'), [(0,0)])
775
        self.assertEquals(unique_lcs('a', 'b'), [])
776
        self.assertEquals(unique_lcs('ab', 'ab'), [(0,0), (1,1)])
777
        self.assertEquals(unique_lcs('abcde', 'cdeab'), [(2,0), (3,1), (4,2)])
778
        self.assertEquals(unique_lcs('cdeab', 'abcde'), [(0,2), (1,3), (2,4)])
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
779
        self.assertEquals(unique_lcs('abXde', 'abYde'), [(0,0), (1,1),
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
780
                                                         (3,3), (4,4)])
781
        self.assertEquals(unique_lcs('acbac', 'abc'), [(2,1)])
782
783
    def test_recurse_matches(self):
784
        def test_one(a, b, matches):
785
            test_matches = []
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
786
            self._recurse_matches(
787
                a, b, 0, 0, len(a), len(b), test_matches, 10)
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
788
            self.assertEquals(test_matches, matches)
789
1711.2.17 by John Arbash Meinel
Small cleanups to patience_diff code.
790
        test_one(['a', '', 'b', '', 'c'], ['a', 'a', 'b', 'c', 'c'],
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
791
                 [(0, 0), (2, 2), (4, 4)])
792
        test_one(['a', 'c', 'b', 'a', 'c'], ['a', 'b', 'c'],
793
                 [(0, 0), (2, 1), (4, 2)])
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
794
        # Even though 'bc' is not unique globally, and is surrounded by
795
        # non-matching lines, we should still match, because they are locally
796
        # unique
797
        test_one('abcdbce', 'afbcgdbce', [(0,0), (1, 2), (2, 3), (3, 5),
798
                                          (4, 6), (5, 7), (6, 8)])
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
799
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
800
        # recurse_matches doesn't match non-unique
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
801
        # lines surrounded by bogus text.
1185.81.24 by Aaron Bentley
Reoganize patience-related code
802
        # The update has been done in patiencediff.SequenceMatcher instead
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
803
804
        # This is what it could be
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
805
        #test_one('aBccDe', 'abccde', [(0,0), (2,2), (3,3), (5,5)])
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
806
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
807
        # This is what it currently gives:
808
        test_one('aBccDe', 'abccde', [(0,0), (5,5)])
809
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
810
    def assertDiffBlocks(self, a, b, expected_blocks):
811
        """Check that the sequence matcher returns the correct blocks.
812
813
        :param a: A sequence to match
814
        :param b: Another sequence to match
815
        :param expected_blocks: The expected output, not including the final
816
            matching block (len(a), len(b), 0)
817
        """
818
        matcher = self._PatienceSequenceMatcher(None, a, b)
819
        blocks = matcher.get_matching_blocks()
820
        last = blocks.pop()
821
        self.assertEqual((len(a), len(b), 0), last)
822
        self.assertEqual(expected_blocks, blocks)
823
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
824
    def test_matching_blocks(self):
1185.81.2 by John Arbash Meinel
A couple small tests.
825
        # Some basic matching tests
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
826
        self.assertDiffBlocks('', '', [])
827
        self.assertDiffBlocks([], [], [])
828
        self.assertDiffBlocks('abc', '', [])
829
        self.assertDiffBlocks('', 'abc', [])
830
        self.assertDiffBlocks('abcd', 'abcd', [(0, 0, 4)])
831
        self.assertDiffBlocks('abcd', 'abce', [(0, 0, 3)])
832
        self.assertDiffBlocks('eabc', 'abce', [(1, 0, 3)])
833
        self.assertDiffBlocks('eabce', 'abce', [(1, 0, 4)])
834
        self.assertDiffBlocks('abcde', 'abXde', [(0, 0, 2), (3, 3, 2)])
835
        self.assertDiffBlocks('abcde', 'abXYZde', [(0, 0, 2), (3, 5, 2)])
836
        self.assertDiffBlocks('abde', 'abXYZde', [(0, 0, 2), (2, 5, 2)])
837
        # This may check too much, but it checks to see that
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
838
        # a copied block stays attached to the previous section,
839
        # not the later one.
840
        # difflib would tend to grab the trailing longest match
841
        # which would make the diff not look right
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
842
        self.assertDiffBlocks('abcdefghijklmnop', 'abcdefxydefghijklmnop',
843
                              [(0, 0, 6), (6, 11, 10)])
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
844
1185.81.2 by John Arbash Meinel
A couple small tests.
845
        # make sure it supports passing in lists
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
846
        self.assertDiffBlocks(
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
847
                   ['hello there\n',
848
                    'world\n',
849
                    'how are you today?\n'],
850
                   ['hello there\n',
851
                    'how are you today?\n'],
1185.81.2 by John Arbash Meinel
A couple small tests.
852
                [(0, 0, 1), (2, 1, 1)])
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
853
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
854
        # non unique lines surrounded by non-matching lines
855
        # won't be found
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
856
        self.assertDiffBlocks('aBccDe', 'abccde', [(0,0,1), (5,5,1)])
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
857
858
        # But they only need to be locally unique
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
859
        self.assertDiffBlocks('aBcDec', 'abcdec', [(0,0,1), (2,2,1), (4,4,2)])
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
860
861
        # non unique blocks won't be matched
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
862
        self.assertDiffBlocks('aBcdEcdFg', 'abcdecdfg', [(0,0,1), (8,8,1)])
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
863
864
        # but locally unique ones will
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
865
        self.assertDiffBlocks('aBcdEeXcdFg', 'abcdecdfg', [(0,0,1), (2,2,2),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
866
                                              (5,4,1), (7,5,2), (10,8,1)])
867
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
868
        self.assertDiffBlocks('abbabbXd', 'cabbabxd', [(7,7,1)])
869
        self.assertDiffBlocks('abbabbbb', 'cabbabbc', [])
870
        self.assertDiffBlocks('bbbbbbbb', 'cbbbbbbc', [])
1185.81.11 by John Arbash Meinel
Found some edge cases that weren't being matched.
871
3074.2.1 by John Arbash Meinel
Change the C PatienceDiff implementation to support arbitrary objects.
872
    def test_matching_blocks_tuples(self):
873
        # Some basic matching tests
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
874
        self.assertDiffBlocks([], [], [])
875
        self.assertDiffBlocks([('a',), ('b',), ('c,')], [], [])
876
        self.assertDiffBlocks([], [('a',), ('b',), ('c,')], [])
877
        self.assertDiffBlocks([('a',), ('b',), ('c,')],
878
                              [('a',), ('b',), ('c,')],
879
                              [(0, 0, 3)])
880
        self.assertDiffBlocks([('a',), ('b',), ('c,')],
881
                              [('a',), ('b',), ('d,')],
882
                              [(0, 0, 2)])
883
        self.assertDiffBlocks([('d',), ('b',), ('c,')],
884
                              [('a',), ('b',), ('c,')],
885
                              [(1, 1, 2)])
886
        self.assertDiffBlocks([('d',), ('a',), ('b',), ('c,')],
887
                              [('a',), ('b',), ('c,')],
888
                              [(1, 0, 3)])
889
        self.assertDiffBlocks([('a', 'b'), ('c', 'd'), ('e', 'f')],
890
                              [('a', 'b'), ('c', 'X'), ('e', 'f')],
891
                              [(0, 0, 1), (2, 2, 1)])
892
        self.assertDiffBlocks([('a', 'b'), ('c', 'd'), ('e', 'f')],
893
                              [('a', 'b'), ('c', 'dX'), ('e', 'f')],
894
                              [(0, 0, 1), (2, 2, 1)])
3074.2.1 by John Arbash Meinel
Change the C PatienceDiff implementation to support arbitrary objects.
895
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
896
    def test_opcodes(self):
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
897
        def chk_ops(a, b, expected_codes):
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
898
            s = self._PatienceSequenceMatcher(None, a, b)
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
899
            self.assertEquals(expected_codes, s.get_opcodes())
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
900
901
        chk_ops('', '', [])
902
        chk_ops([], [], [])
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
903
        chk_ops('abc', '', [('delete', 0,3, 0,0)])
904
        chk_ops('', 'abc', [('insert', 0,0, 0,3)])
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
905
        chk_ops('abcd', 'abcd', [('equal',    0,4, 0,4)])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
906
        chk_ops('abcd', 'abce', [('equal',   0,3, 0,3),
907
                                 ('replace', 3,4, 3,4)
908
                                ])
909
        chk_ops('eabc', 'abce', [('delete', 0,1, 0,0),
910
                                 ('equal',  1,4, 0,3),
911
                                 ('insert', 4,4, 3,4)
912
                                ])
913
        chk_ops('eabce', 'abce', [('delete', 0,1, 0,0),
914
                                  ('equal',  1,5, 0,4)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
915
                                 ])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
916
        chk_ops('abcde', 'abXde', [('equal',   0,2, 0,2),
917
                                   ('replace', 2,3, 2,3),
918
                                   ('equal',   3,5, 3,5)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
919
                                  ])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
920
        chk_ops('abcde', 'abXYZde', [('equal',   0,2, 0,2),
921
                                     ('replace', 2,3, 2,5),
922
                                     ('equal',   3,5, 5,7)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
923
                                    ])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
924
        chk_ops('abde', 'abXYZde', [('equal',  0,2, 0,2),
925
                                    ('insert', 2,2, 2,5),
926
                                    ('equal',  2,4, 5,7)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
927
                                   ])
928
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
929
                [('equal',  0,6,  0,6),
930
                 ('insert', 6,6,  6,11),
931
                 ('equal',  6,16, 11,21)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
932
                ])
933
        chk_ops(
934
                [ 'hello there\n'
935
                , 'world\n'
936
                , 'how are you today?\n'],
937
                [ 'hello there\n'
938
                , 'how are you today?\n'],
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
939
                [('equal',  0,1, 0,1),
940
                 ('delete', 1,2, 1,1),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
941
                 ('equal',  2,3, 1,2),
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
942
                ])
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
943
        chk_ops('aBccDe', 'abccde',
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
944
                [('equal',   0,1, 0,1),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
945
                 ('replace', 1,5, 1,5),
946
                 ('equal',   5,6, 5,6),
947
                ])
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
948
        chk_ops('aBcDec', 'abcdec',
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
949
                [('equal',   0,1, 0,1),
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
950
                 ('replace', 1,2, 1,2),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
951
                 ('equal',   2,3, 2,3),
952
                 ('replace', 3,4, 3,4),
953
                 ('equal',   4,6, 4,6),
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
954
                ])
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
955
        chk_ops('aBcdEcdFg', 'abcdecdfg',
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
956
                [('equal',   0,1, 0,1),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
957
                 ('replace', 1,8, 1,8),
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
958
                 ('equal',   8,9, 8,9)
1185.81.10 by John Arbash Meinel
Added some more test cases.
959
                ])
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
960
        chk_ops('aBcdEeXcdFg', 'abcdecdfg',
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
961
                [('equal',   0,1, 0,1),
962
                 ('replace', 1,2, 1,2),
963
                 ('equal',   2,4, 2,4),
964
                 ('delete', 4,5, 4,4),
965
                 ('equal',   5,6, 4,5),
966
                 ('delete', 6,7, 5,5),
967
                 ('equal',   7,9, 5,7),
968
                 ('replace', 9,10, 7,8),
969
                 ('equal',   10,11, 8,9)
970
                ])
1185.81.10 by John Arbash Meinel
Added some more test cases.
971
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
972
    def test_grouped_opcodes(self):
973
        def chk_ops(a, b, expected_codes, n=3):
974
            s = self._PatienceSequenceMatcher(None, a, b)
975
            self.assertEquals(expected_codes, list(s.get_grouped_opcodes(n)))
976
977
        chk_ops('', '', [])
978
        chk_ops([], [], [])
979
        chk_ops('abc', '', [[('delete', 0,3, 0,0)]])
980
        chk_ops('', 'abc', [[('insert', 0,0, 0,3)]])
981
        chk_ops('abcd', 'abcd', [])
982
        chk_ops('abcd', 'abce', [[('equal',   0,3, 0,3),
983
                                  ('replace', 3,4, 3,4)
984
                                 ]])
985
        chk_ops('eabc', 'abce', [[('delete', 0,1, 0,0),
986
                                 ('equal',  1,4, 0,3),
987
                                 ('insert', 4,4, 3,4)
988
                                ]])
989
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
990
                [[('equal',  3,6, 3,6),
991
                  ('insert', 6,6, 6,11),
992
                  ('equal',  6,9, 11,14)
993
                  ]])
994
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
995
                [[('equal',  2,6, 2,6),
996
                  ('insert', 6,6, 6,11),
997
                  ('equal',  6,10, 11,15)
998
                  ]], 4)
999
        chk_ops('Xabcdef', 'abcdef',
1000
                [[('delete', 0,1, 0,0),
1001
                  ('equal',  1,4, 0,3)
1002
                  ]])
1003
        chk_ops('abcdef', 'abcdefX',
1004
                [[('equal',  3,6, 3,6),
1005
                  ('insert', 6,6, 6,7)
1006
                  ]])
1007
1008
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
1009
    def test_multiple_ranges(self):
1010
        # There was an earlier bug where we used a bad set of ranges,
1011
        # this triggers that specific bug, to make sure it doesn't regress
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
1012
        self.assertDiffBlocks('abcdefghijklmnop',
1013
                              'abcXghiYZQRSTUVWXYZijklmnop',
1014
                              [(0, 0, 3), (6, 4, 3), (9, 20, 7)])
1015
1016
        self.assertDiffBlocks('ABCd efghIjk  L',
1017
                              'AxyzBCn mo pqrstuvwI1 2  L',
1018
                              [(0,0,1), (1, 4, 2), (9, 19, 1), (12, 23, 3)])
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
1019
1711.2.8 by John Arbash Meinel
rot13 the code snippet to help with clarity.
1020
        # These are rot13 code snippets.
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
1021
        self.assertDiffBlocks('''\
1711.2.8 by John Arbash Meinel
rot13 the code snippet to help with clarity.
1022
    trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
1023
    """
1024
    gnxrf_netf = ['svyr*']
1025
    gnxrf_bcgvbaf = ['ab-erphefr']
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1026
1711.2.8 by John Arbash Meinel
rot13 the code snippet to help with clarity.
1027
    qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr):
1028
        sebz omeyvo.nqq vzcbeg fzneg_nqq, nqq_ercbegre_cevag, nqq_ercbegre_ahyy
1029
        vs vf_dhvrg():
1030
            ercbegre = nqq_ercbegre_ahyy
1031
        ryfr:
1032
            ercbegre = nqq_ercbegre_cevag
1033
        fzneg_nqq(svyr_yvfg, abg ab_erphefr, ercbegre)
1034
1035
1036
pynff pzq_zxqve(Pbzznaq):
1037
'''.splitlines(True), '''\
1038
    trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
1039
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1040
    --qel-eha jvyy fubj juvpu svyrf jbhyq or nqqrq, ohg abg npghnyyl
1711.2.8 by John Arbash Meinel
rot13 the code snippet to help with clarity.
1041
    nqq gurz.
1042
    """
1043
    gnxrf_netf = ['svyr*']
1044
    gnxrf_bcgvbaf = ['ab-erphefr', 'qel-eha']
1045
1046
    qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr, qel_eha=Snyfr):
1047
        vzcbeg omeyvo.nqq
1048
1049
        vs qel_eha:
1050
            vs vf_dhvrg():
1051
                # Guvf vf cbvagyrff, ohg V'q engure abg envfr na reebe
1052
                npgvba = omeyvo.nqq.nqq_npgvba_ahyy
1053
            ryfr:
1054
  npgvba = omeyvo.nqq.nqq_npgvba_cevag
1055
        ryvs vf_dhvrg():
1056
            npgvba = omeyvo.nqq.nqq_npgvba_nqq
1057
        ryfr:
1058
       npgvba = omeyvo.nqq.nqq_npgvba_nqq_naq_cevag
1059
1060
        omeyvo.nqq.fzneg_nqq(svyr_yvfg, abg ab_erphefr, npgvba)
1061
1062
1063
pynff pzq_zxqve(Pbzznaq):
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
1064
'''.splitlines(True)
1065
, [(0,0,1), (1, 4, 2), (9, 19, 1), (12, 23, 3)])
1066
1711.2.9 by John Arbash Meinel
Rename cdv => patience
1067
    def test_patience_unified_diff(self):
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1068
        txt_a = ['hello there\n',
1069
                 'world\n',
1070
                 'how are you today?\n']
1071
        txt_b = ['hello there\n',
1072
                 'how are you today?\n']
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1073
        unified_diff = patiencediff.unified_diff
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1074
        psm = self._PatienceSequenceMatcher
3922.1.3 by John Arbash Meinel
fix some odd spacing.
1075
        self.assertEquals(['--- \n',
3922.1.2 by John Arbash Meinel
Update the test cases for the new patience diff code.
1076
                           '+++ \n',
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1077
                           '@@ -1,3 +1,2 @@\n',
1078
                           ' hello there\n',
1079
                           '-world\n',
1080
                           ' how are you today?\n'
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1081
                          ]
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
1082
                          , list(unified_diff(txt_a, txt_b,
1083
                                 sequencematcher=psm)))
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1084
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
1085
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
1086
        # This is the result with LongestCommonSubstring matching
3922.1.2 by John Arbash Meinel
Update the test cases for the new patience diff code.
1087
        self.assertEquals(['--- \n',
1088
                           '+++ \n',
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1089
                           '@@ -1,6 +1,11 @@\n',
1090
                           ' a\n',
1091
                           ' b\n',
1092
                           ' c\n',
1093
                           '+d\n',
1094
                           '+e\n',
1095
                           '+f\n',
1096
                           '+x\n',
1097
                           '+y\n',
1098
                           ' d\n',
1099
                           ' e\n',
1100
                           ' f\n']
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1101
                          , list(unified_diff(txt_a, txt_b)))
1711.2.9 by John Arbash Meinel
Rename cdv => patience
1102
        # And the patience diff
3922.1.2 by John Arbash Meinel
Update the test cases for the new patience diff code.
1103
        self.assertEquals(['--- \n',
1104
                           '+++ \n',
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1105
                           '@@ -4,6 +4,11 @@\n',
1106
                           ' d\n',
1107
                           ' e\n',
1108
                           ' f\n',
1109
                           '+x\n',
1110
                           '+y\n',
1111
                           '+d\n',
1112
                           '+e\n',
1113
                           '+f\n',
1114
                           ' g\n',
1115
                           ' h\n',
1116
                           ' i\n',
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1117
                          ]
1185.81.25 by Aaron Bentley
Clean up test_diff
1118
                          , list(unified_diff(txt_a, txt_b,
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
1119
                                 sequencematcher=psm)))
1185.81.25 by Aaron Bentley
Clean up test_diff
1120
3922.1.2 by John Arbash Meinel
Update the test cases for the new patience diff code.
1121
    def test_patience_unified_diff_with_dates(self):
1122
        txt_a = ['hello there\n',
1123
                 'world\n',
1124
                 'how are you today?\n']
1125
        txt_b = ['hello there\n',
1126
                 'how are you today?\n']
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1127
        unified_diff = patiencediff.unified_diff
3922.1.2 by John Arbash Meinel
Update the test cases for the new patience diff code.
1128
        psm = self._PatienceSequenceMatcher
3922.1.4 by John Arbash Meinel
It turns out that internal_diff worked around the trailing whitespace problem
1129
        self.assertEquals(['--- a\t2008-08-08\n',
1130
                           '+++ b\t2008-09-09\n',
3922.1.2 by John Arbash Meinel
Update the test cases for the new patience diff code.
1131
                           '@@ -1,3 +1,2 @@\n',
1132
                           ' hello there\n',
1133
                           '-world\n',
1134
                           ' how are you today?\n'
1135
                          ]
1136
                          , list(unified_diff(txt_a, txt_b,
1137
                                 fromfile='a', tofile='b',
1138
                                 fromfiledate='2008-08-08',
1139
                                 tofiledate='2008-09-09',
1140
                                 sequencematcher=psm)))
1141
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1142
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1143
class TestPatienceDiffLib_c(TestPatienceDiffLib):
1144
4913.2.20 by John Arbash Meinel
Change all of the compiled_foo to compiled_foo_feature
1145
    _test_needs_features = [compiled_patiencediff_feature]
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1146
1147
    def setUp(self):
1148
        super(TestPatienceDiffLib_c, self).setUp()
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1149
        from bzrlib import _patiencediff_c
1150
        self._unique_lcs = _patiencediff_c.unique_lcs_c
1151
        self._recurse_matches = _patiencediff_c.recurse_matches_c
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1152
        self._PatienceSequenceMatcher = \
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1153
            _patiencediff_c.PatienceSequenceMatcher_c
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1154
3074.2.3 by John Arbash Meinel
Enable some error checking, and small amount of code cleanup.
1155
    def test_unhashable(self):
1156
        """We should get a proper exception here."""
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
1157
        # We need to be able to hash items in the sequence, lists are
1158
        # unhashable, and thus cannot be diffed
3074.2.3 by John Arbash Meinel
Enable some error checking, and small amount of code cleanup.
1159
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1160
                                         None, [[]], [])
3074.2.10 by John Arbash Meinel
Cleanup the test cases (Andrew)
1161
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1162
                                         None, ['valid', []], [])
1163
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1164
                                         None, ['valid'], [[]])
1165
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1166
                                         None, ['valid'], ['valid', []])
3074.2.3 by John Arbash Meinel
Enable some error checking, and small amount of code cleanup.
1167
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1168
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
1169
class TestPatienceDiffLibFiles(tests.TestCaseInTempDir):
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1170
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1171
    def setUp(self):
1172
        super(TestPatienceDiffLibFiles, self).setUp()
1173
        self._PatienceSequenceMatcher = \
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1174
            _patiencediff_py.PatienceSequenceMatcher_py
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1175
1711.2.9 by John Arbash Meinel
Rename cdv => patience
1176
    def test_patience_unified_diff_files(self):
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1177
        txt_a = ['hello there\n',
1178
                 'world\n',
1179
                 'how are you today?\n']
1180
        txt_b = ['hello there\n',
1181
                 'how are you today?\n']
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1182
        open('a1', 'wb').writelines(txt_a)
1183
        open('b1', 'wb').writelines(txt_b)
1184
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1185
        unified_diff_files = patiencediff.unified_diff_files
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1186
        psm = self._PatienceSequenceMatcher
3922.1.2 by John Arbash Meinel
Update the test cases for the new patience diff code.
1187
        self.assertEquals(['--- a1\n',
1188
                           '+++ b1\n',
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1189
                           '@@ -1,3 +1,2 @@\n',
1190
                           ' hello there\n',
1191
                           '-world\n',
1192
                           ' how are you today?\n',
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1193
                          ]
1185.81.25 by Aaron Bentley
Clean up test_diff
1194
                          , list(unified_diff_files('a1', 'b1',
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
1195
                                 sequencematcher=psm)))
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1196
1197
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
1198
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
1199
        open('a2', 'wb').writelines(txt_a)
1200
        open('b2', 'wb').writelines(txt_b)
1201
1202
        # This is the result with LongestCommonSubstring matching
3922.1.2 by John Arbash Meinel
Update the test cases for the new patience diff code.
1203
        self.assertEquals(['--- a2\n',
1204
                           '+++ b2\n',
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1205
                           '@@ -1,6 +1,11 @@\n',
1206
                           ' a\n',
1207
                           ' b\n',
1208
                           ' c\n',
1209
                           '+d\n',
1210
                           '+e\n',
1211
                           '+f\n',
1212
                           '+x\n',
1213
                           '+y\n',
1214
                           ' d\n',
1215
                           ' e\n',
1216
                           ' f\n']
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1217
                          , list(unified_diff_files('a2', 'b2')))
1218
1711.2.9 by John Arbash Meinel
Rename cdv => patience
1219
        # And the patience diff
3922.1.2 by John Arbash Meinel
Update the test cases for the new patience diff code.
1220
        self.assertEquals(['--- a2\n',
1221
                           '+++ b2\n',
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1222
                           '@@ -4,6 +4,11 @@\n',
1223
                           ' d\n',
1224
                           ' e\n',
1225
                           ' f\n',
1226
                           '+x\n',
1227
                           '+y\n',
1228
                           '+d\n',
1229
                           '+e\n',
1230
                           '+f\n',
1231
                           ' g\n',
1232
                           ' h\n',
1233
                           ' i\n',
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1234
                          ]
1185.81.25 by Aaron Bentley
Clean up test_diff
1235
                          , list(unified_diff_files('a2', 'b2',
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
1236
                                 sequencematcher=psm)))
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1237
1238
1239
class TestPatienceDiffLibFiles_c(TestPatienceDiffLibFiles):
1240
4913.2.20 by John Arbash Meinel
Change all of the compiled_foo to compiled_foo_feature
1241
    _test_needs_features = [compiled_patiencediff_feature]
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1242
1243
    def setUp(self):
1244
        super(TestPatienceDiffLibFiles_c, self).setUp()
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1245
        from bzrlib import _patiencediff_c
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1246
        self._PatienceSequenceMatcher = \
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1247
            _patiencediff_c.PatienceSequenceMatcher_c
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1248
1249
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
1250
class TestUsingCompiledIfAvailable(tests.TestCase):
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1251
1252
    def test_PatienceSequenceMatcher(self):
4913.2.20 by John Arbash Meinel
Change all of the compiled_foo to compiled_foo_feature
1253
        if compiled_patiencediff_feature.available():
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1254
            from bzrlib._patiencediff_c import PatienceSequenceMatcher_c
1255
            self.assertIs(PatienceSequenceMatcher_c,
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1256
                          patiencediff.PatienceSequenceMatcher)
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1257
        else:
1258
            from bzrlib._patiencediff_py import PatienceSequenceMatcher_py
1259
            self.assertIs(PatienceSequenceMatcher_py,
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1260
                          patiencediff.PatienceSequenceMatcher)
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1261
1262
    def test_unique_lcs(self):
4913.2.20 by John Arbash Meinel
Change all of the compiled_foo to compiled_foo_feature
1263
        if compiled_patiencediff_feature.available():
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1264
            from bzrlib._patiencediff_c import unique_lcs_c
1265
            self.assertIs(unique_lcs_c,
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1266
                          patiencediff.unique_lcs)
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1267
        else:
1268
            from bzrlib._patiencediff_py import unique_lcs_py
1269
            self.assertIs(unique_lcs_py,
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1270
                          patiencediff.unique_lcs)
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1271
1272
    def test_recurse_matches(self):
4913.2.20 by John Arbash Meinel
Change all of the compiled_foo to compiled_foo_feature
1273
        if compiled_patiencediff_feature.available():
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1274
            from bzrlib._patiencediff_c import recurse_matches_c
1275
            self.assertIs(recurse_matches_c,
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1276
                          patiencediff.recurse_matches)
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1277
        else:
1278
            from bzrlib._patiencediff_py import recurse_matches_py
1279
            self.assertIs(recurse_matches_py,
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1280
                          patiencediff.recurse_matches)
3123.6.2 by Aaron Bentley
Implement diff --using natively
1281
1282
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
1283
class TestDiffFromTool(tests.TestCaseWithTransport):
3123.6.2 by Aaron Bentley
Implement diff --using natively
1284
1285
    def test_from_string(self):
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
1286
        diff_obj = diff.DiffFromTool.from_string('diff', None, None, None)
3123.6.2 by Aaron Bentley
Implement diff --using natively
1287
        self.addCleanup(diff_obj.finish)
4603.1.20 by Aaron Bentley
Use string.Template substitution with @ as delimiter.
1288
        self.assertEqual(['diff', '@old_path', '@new_path'],
3123.6.2 by Aaron Bentley
Implement diff --using natively
1289
            diff_obj.command_template)
3199.1.6 by Vincent Ladeuil
Fiz last leaking tmp dir.
1290
1291
    def test_from_string_u5(self):
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
1292
        diff_obj = diff.DiffFromTool.from_string('diff "-u 5"',
1293
                                                 None, None, None)
3199.1.6 by Vincent Ladeuil
Fiz last leaking tmp dir.
1294
        self.addCleanup(diff_obj.finish)
4603.1.20 by Aaron Bentley
Use string.Template substitution with @ as delimiter.
1295
        self.assertEqual(['diff', '-u 5', '@old_path', '@new_path'],
3123.6.2 by Aaron Bentley
Implement diff --using natively
1296
                         diff_obj.command_template)
1297
        self.assertEqual(['diff', '-u 5', 'old-path', 'new-path'],
1298
                         diff_obj._get_command('old-path', 'new-path'))
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
1299
4913.5.8 by Gordon Tyler
Added test_from_string_path_with_backslashes, which tests the actual scenario in bug 392428.
1300
    def test_from_string_path_with_backslashes(self):
5168.1.3 by Vincent Ladeuil
Even more import fixes.
1301
        self.requireFeature(test_win32utils.BackslashDirSeparatorFeature)
4913.5.8 by Gordon Tyler
Added test_from_string_path_with_backslashes, which tests the actual scenario in bug 392428.
1302
        tool = 'C:\\Tools\\Diff.exe'
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
1303
        diff_obj = diff.DiffFromTool.from_string(tool, None, None, None)
4913.5.8 by Gordon Tyler
Added test_from_string_path_with_backslashes, which tests the actual scenario in bug 392428.
1304
        self.addCleanup(diff_obj.finish)
1305
        self.assertEqual(['C:\\Tools\\Diff.exe', '@old_path', '@new_path'],
1306
                         diff_obj.command_template)
1307
        self.assertEqual(['C:\\Tools\\Diff.exe', 'old-path', 'new-path'],
1308
                         diff_obj._get_command('old-path', 'new-path'))
3123.6.2 by Aaron Bentley
Implement diff --using natively
1309
1310
    def test_execute(self):
1311
        output = StringIO()
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
1312
        diff_obj = diff.DiffFromTool(['python', '-c',
1313
                                      'print "@old_path @new_path"'],
1314
                                     None, None, output)
3123.6.2 by Aaron Bentley
Implement diff --using natively
1315
        self.addCleanup(diff_obj.finish)
1316
        diff_obj._execute('old', 'new')
3146.4.2 by Aaron Bentley
Avoid assuming unix newline on output
1317
        self.assertEqual(output.getvalue().rstrip(), 'old new')
3123.6.2 by Aaron Bentley
Implement diff --using natively
1318
3145.1.1 by Aaron Bentley
Handle missing tools gracefully in diff --using
1319
    def test_excute_missing(self):
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
1320
        diff_obj = diff.DiffFromTool(['a-tool-which-is-unlikely-to-exist'],
1321
                                     None, None, None)
3145.1.1 by Aaron Bentley
Handle missing tools gracefully in diff --using
1322
        self.addCleanup(diff_obj.finish)
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
1323
        e = self.assertRaises(errors.ExecutableMissing, diff_obj._execute,
1324
                              'old', 'new')
3145.1.1 by Aaron Bentley
Handle missing tools gracefully in diff --using
1325
        self.assertEqual('a-tool-which-is-unlikely-to-exist could not be found'
1326
                         ' on this machine', str(e))
1327
3287.18.22 by Matt McClure
Reverts to prior decomposition of exercise and verification, as suggested
1328
    def test_prepare_files_creates_paths_readable_by_windows_tool(self):
3287.18.20 by Matt McClure
Introduces a Feature subclass to encapsulate the availability of 'attrib'.
1329
        self.requireFeature(AttribFeature)
3287.18.10 by Matt McClure
Uses TestSkipped for test_execute_windows_tool on non-Windows platforms.
1330
        output = StringIO()
1331
        tree = self.make_branch_and_tree('tree')
1332
        self.build_tree_contents([('tree/file', 'content')])
1333
        tree.add('file', 'file-id')
3287.18.11 by Matt McClure
Removed unnecessary timestamp parameter.
1334
        tree.commit('old tree')
3287.18.10 by Matt McClure
Uses TestSkipped for test_execute_windows_tool on non-Windows platforms.
1335
        tree.lock_read()
1336
        self.addCleanup(tree.unlock)
4873.3.1 by John Arbash Meinel
Now that we return files directly from the working tree
1337
        basis_tree = tree.basis_tree()
1338
        basis_tree.lock_read()
1339
        self.addCleanup(basis_tree.unlock)
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
1340
        diff_obj = diff.DiffFromTool(['python', '-c',
1341
                                      'print "@old_path @new_path"'],
1342
                                     basis_tree, tree, output)
3287.18.22 by Matt McClure
Reverts to prior decomposition of exercise and verification, as suggested
1343
        diff_obj._prepare_files('file-id', 'file', 'file')
4873.3.1 by John Arbash Meinel
Now that we return files directly from the working tree
1344
        # The old content should be readonly
1345
        self.assertReadableByAttrib(diff_obj._root, 'old\\file',
1346
                                    r'R.*old\\file$')
1347
        # The new content should use the tree object, not a 'new' file anymore
1348
        self.assertEndsWith(tree.basedir, 'work/tree')
1349
        self.assertReadableByAttrib(tree.basedir, 'file', r'work\\tree\\file$')
3287.18.22 by Matt McClure
Reverts to prior decomposition of exercise and verification, as suggested
1350
1351
    def assertReadableByAttrib(self, cwd, relpath, regex):
1352
        proc = subprocess.Popen(['attrib', relpath],
1353
                                stdout=subprocess.PIPE,
1354
                                cwd=cwd)
4873.3.1 by John Arbash Meinel
Now that we return files directly from the working tree
1355
        (result, err) = proc.communicate()
1356
        self.assertContainsRe(result.replace('\r\n', '\n'), regex)
3287.18.9 by Matt McClure
Adds a test asserting that a Windows tool that understands forward slashes
1357
3123.6.2 by Aaron Bentley
Implement diff --using natively
1358
    def test_prepare_files(self):
1359
        output = StringIO()
1360
        tree = self.make_branch_and_tree('tree')
3123.6.5 by Aaron Bentley
Symlink to real files if possible
1361
        self.build_tree_contents([('tree/oldname', 'oldcontent')])
3287.18.23 by Matt McClure
Adds comments that document my understanding of
1362
        self.build_tree_contents([('tree/oldname2', 'oldcontent2')])
3123.6.5 by Aaron Bentley
Symlink to real files if possible
1363
        tree.add('oldname', 'file-id')
3287.18.23 by Matt McClure
Adds comments that document my understanding of
1364
        tree.add('oldname2', 'file2-id')
5151.3.1 by Martin
Fix os.utime test failures, three on FAT filesystems and one with readonly files
1365
        # Earliest allowable date on FAT32 filesystems is 1980-01-01
1366
        tree.commit('old tree', timestamp=315532800)
3123.6.5 by Aaron Bentley
Symlink to real files if possible
1367
        tree.rename_one('oldname', 'newname')
3287.18.23 by Matt McClure
Adds comments that document my understanding of
1368
        tree.rename_one('oldname2', 'newname2')
3123.6.5 by Aaron Bentley
Symlink to real files if possible
1369
        self.build_tree_contents([('tree/newname', 'newcontent')])
3287.19.1 by Matt McClure
Fixes https://bugs.launchpad.net/bzr/+bug/212289. I submitted this patch.
1370
        self.build_tree_contents([('tree/newname2', 'newcontent2')])
3123.6.2 by Aaron Bentley
Implement diff --using natively
1371
        old_tree = tree.basis_tree()
1372
        old_tree.lock_read()
1373
        self.addCleanup(old_tree.unlock)
3123.6.4 by Aaron Bentley
Set mtime (and atime) on files for --using
1374
        tree.lock_read()
1375
        self.addCleanup(tree.unlock)
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
1376
        diff_obj = diff.DiffFromTool(['python', '-c',
1377
                                      'print "@old_path @new_path"'],
1378
                                     old_tree, tree, output)
3123.6.2 by Aaron Bentley
Implement diff --using natively
1379
        self.addCleanup(diff_obj.finish)
1380
        self.assertContainsRe(diff_obj._root, 'bzr-diff-[^/]*')
1381
        old_path, new_path = diff_obj._prepare_files('file-id', 'oldname',
1382
                                                     'newname')
1383
        self.assertContainsRe(old_path, 'old/oldname$')
5151.3.1 by Martin
Fix os.utime test failures, three on FAT filesystems and one with readonly files
1384
        self.assertEqual(315532800, os.stat(old_path).st_mtime)
4845.2.1 by Gary van der Merwe
When launching an external diff app, don't write temporary files for a working tree.
1385
        self.assertContainsRe(new_path, 'tree/newname$')
3123.6.2 by Aaron Bentley
Implement diff --using natively
1386
        self.assertFileEqual('oldcontent', old_path)
1387
        self.assertFileEqual('newcontent', new_path)
3287.18.14 by Matt McClure
Extracted a host_os_dereferences_symlinks method.
1388
        if osutils.host_os_dereferences_symlinks():
3123.6.5 by Aaron Bentley
Symlink to real files if possible
1389
            self.assertTrue(os.path.samefile('tree/newname', new_path))
3123.6.2 by Aaron Bentley
Implement diff --using natively
1390
        # make sure we can create files with the same parent directories
3287.18.25 by Matt McClure
Uses the correct file_id as the argument to _prepare_files.
1391
        diff_obj._prepare_files('file2-id', 'oldname2', 'newname2')
4705.1.2 by Gary van der Merwe
Start on tests for get_trees_and_branches_to_diff.
1392
1393
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
1394
class TestGetTreesAndBranchesToDiffLocked(tests.TestCaseWithTransport):
5147.3.7 by Andrew Bennetts
Expect DeprecationWarnings for get_trees_and_branches_to_diff in test_diff, and add corresponding test coverage for get_trees_and_branches_to_diff_locked.
1395
1396
    def call_gtabtd(self, path_list, revision_specs, old_url, new_url):
1397
        """Call get_trees_and_branches_to_diff_locked.  Overridden by
1398
        TestGetTreesAndBranchesToDiff.
1399
        """
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
1400
        return diff.get_trees_and_branches_to_diff_locked(
5147.3.7 by Andrew Bennetts
Expect DeprecationWarnings for get_trees_and_branches_to_diff in test_diff, and add corresponding test coverage for get_trees_and_branches_to_diff_locked.
1401
            path_list, revision_specs, old_url, new_url, self.addCleanup)
4732.1.2 by Vincent Ladeuil
(trivial) Fix some PEP8 issues
1402
4705.1.2 by Gary van der Merwe
Start on tests for get_trees_and_branches_to_diff.
1403
    def test_basic(self):
1404
        tree = self.make_branch_and_tree('tree')
1405
        (old_tree, new_tree,
1406
         old_branch, new_branch,
5147.3.7 by Andrew Bennetts
Expect DeprecationWarnings for get_trees_and_branches_to_diff in test_diff, and add corresponding test coverage for get_trees_and_branches_to_diff_locked.
1407
         specific_files, extra_trees) = self.call_gtabtd(
1408
             ['tree'], None, None, None)
4732.1.2 by Vincent Ladeuil
(trivial) Fix some PEP8 issues
1409
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
1410
        self.assertIsInstance(old_tree, revisiontree.RevisionTree)
1411
        self.assertEqual(_mod_revision.NULL_REVISION,
1412
                         old_tree.get_revision_id())
4705.1.2 by Gary van der Merwe
Start on tests for get_trees_and_branches_to_diff.
1413
        self.assertEqual(tree.basedir, new_tree.basedir)
1414
        self.assertEqual(tree.branch.base, old_branch.base)
1415
        self.assertEqual(tree.branch.base, new_branch.base)
1416
        self.assertIs(None, specific_files)
1417
        self.assertIs(None, extra_trees)
1418
1419
    def test_with_rev_specs(self):
1420
        tree = self.make_branch_and_tree('tree')
1421
        self.build_tree_contents([('tree/file', 'oldcontent')])
1422
        tree.add('file', 'file-id')
1423
        tree.commit('old tree', timestamp=0, rev_id="old-id")
1424
        self.build_tree_contents([('tree/file', 'newcontent')])
1425
        tree.commit('new tree', timestamp=0, rev_id="new-id")
4732.1.2 by Vincent Ladeuil
(trivial) Fix some PEP8 issues
1426
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
1427
        revisions = [revisionspec.RevisionSpec.from_string('1'),
1428
                     revisionspec.RevisionSpec.from_string('2')]
4705.1.2 by Gary van der Merwe
Start on tests for get_trees_and_branches_to_diff.
1429
        (old_tree, new_tree,
1430
         old_branch, new_branch,
5147.3.7 by Andrew Bennetts
Expect DeprecationWarnings for get_trees_and_branches_to_diff in test_diff, and add corresponding test coverage for get_trees_and_branches_to_diff_locked.
1431
         specific_files, extra_trees) = self.call_gtabtd(
1432
            ['tree'], revisions, None, None)
4732.1.2 by Vincent Ladeuil
(trivial) Fix some PEP8 issues
1433
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
1434
        self.assertIsInstance(old_tree, revisiontree.RevisionTree)
4705.1.2 by Gary van der Merwe
Start on tests for get_trees_and_branches_to_diff.
1435
        self.assertEqual("old-id", old_tree.get_revision_id())
5168.1.2 by Vincent Ladeuil
Ckeanup some more imports.
1436
        self.assertIsInstance(new_tree, revisiontree.RevisionTree)
4705.1.2 by Gary van der Merwe
Start on tests for get_trees_and_branches_to_diff.
1437
        self.assertEqual("new-id", new_tree.get_revision_id())
1438
        self.assertEqual(tree.branch.base, old_branch.base)
1439
        self.assertEqual(tree.branch.base, new_branch.base)
1440
        self.assertIs(None, specific_files)
4705.1.4 by Gary van der Merwe
Add newline to end of test_diff.py
1441
        self.assertEqual(tree.basedir, extra_trees[0].basedir)
5147.3.7 by Andrew Bennetts
Expect DeprecationWarnings for get_trees_and_branches_to_diff in test_diff, and add corresponding test coverage for get_trees_and_branches_to_diff_locked.
1442
1443
1444
class TestGetTreesAndBranchesToDiff(TestGetTreesAndBranchesToDiffLocked):
1445
    """Apply the tests for get_trees_and_branches_to_diff_locked to the
1446
    deprecated get_trees_and_branches_to_diff function.
1447
    """
1448
1449
    def call_gtabtd(self, path_list, revision_specs, old_url, new_url):
1450
        return self.applyDeprecated(
5168.1.4 by Vincent Ladeuil
Final import fixes for bt.test_diff.
1451
            deprecated_in((2, 2, 0)), diff.get_trees_and_branches_to_diff,
5147.3.7 by Andrew Bennetts
Expect DeprecationWarnings for get_trees_and_branches_to_diff in test_diff, and add corresponding test coverage for get_trees_and_branches_to_diff_locked.
1452
            path_list, revision_specs, old_url, new_url)
1453