~bzr-pqm/bzr/bzr.dev

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