~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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
1740.2.5 by Aaron Bentley
Merge from bzr.dev
17
import os
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
18
from cStringIO import StringIO
1692.8.7 by James Henstridge
changes suggested by John Meinel
19
import errno
1920.1.1 by John Arbash Meinel
fix bug #56307, handle binary files even when LANG is not english
20
import subprocess
1920.1.3 by John Arbash Meinel
Remove spurious import
21
from tempfile import TemporaryFile
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
22
1692.8.5 by James Henstridge
merge from bzr.dev
23
from bzrlib.diff import internal_diff, external_diff, show_diff_trees
1711.2.56 by John Arbash Meinel
Raise NoDiff if 'diff' not present.
24
from bzrlib.errors import BinaryFile, NoDiff
2321.2.5 by Alexander Belchenko
external diff: no need for special code path for win32 (suggested by John Meinel)
25
import bzrlib.osutils as osutils
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
26
import bzrlib.patiencediff
2592.2.4 by Jonathan Lange
Skip the unicode filename test if the platform doesn't support unicode
27
from bzrlib.tests import (Feature, TestCase, TestCaseWithTransport,
1711.2.54 by John Arbash Meinel
Use mkstemp instead of NamedTemporary file for external diff.
28
                          TestCaseInTempDir, TestSkipped)
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
29
30
2592.2.4 by Jonathan Lange
Skip the unicode filename test if the platform doesn't support unicode
31
class _UnicodeFilename(Feature):
32
    """Does the filesystem support Unicode filenames?"""
33
34
    def _probe(self):
35
        try:
2653.1.1 by John Arbash Meinel
(Jonathan Lange) Fix bug #110092, when displaying a diff that includes a binary file, make sure the binary filenames are encoded
36
            os.stat(u'\u03b1')
2592.2.4 by Jonathan Lange
Skip the unicode filename test if the platform doesn't support unicode
37
        except UnicodeEncodeError:
38
            return False
2592.2.5 by Jonathan Lange
Make UnicodeFilename feature less insane. Add a simple test for it too.
39
        except (IOError, OSError):
40
            # The filesystem allows the Unicode filename but the file doesn't
2653.1.1 by John Arbash Meinel
(Jonathan Lange) Fix bug #110092, when displaying a diff that includes a binary file, make sure the binary filenames are encoded
41
            # exist.
2592.2.5 by Jonathan Lange
Make UnicodeFilename feature less insane. Add a simple test for it too.
42
            return True
43
        else:
44
            # The filesystem allows the Unicode filename and the file exists,
45
            # for some reason.
46
            return True
2592.2.4 by Jonathan Lange
Skip the unicode filename test if the platform doesn't support unicode
47
48
UnicodeFilename = _UnicodeFilename()
49
50
2592.2.5 by Jonathan Lange
Make UnicodeFilename feature less insane. Add a simple test for it too.
51
class TestUnicodeFilename(TestCase):
52
53
    def test_probe_passes(self):
54
        """UnicodeFilename._probe passes."""
55
        # We can't test much more than that because the behaviour depends
56
        # on the platform.
57
        UnicodeFilename._probe()
58
        
59
1558.15.11 by Aaron Bentley
Apply merge review suggestions
60
def udiff_lines(old, new, allow_binary=False):
974.1.6 by Aaron Bentley
Added unit tests
61
    output = StringIO()
1558.15.11 by Aaron Bentley
Apply merge review suggestions
62
    internal_diff('old', old, 'new', new, output, allow_binary)
974.1.6 by Aaron Bentley
Added unit tests
63
    output.seek(0, 0)
64
    return output.readlines()
65
1711.2.54 by John Arbash Meinel
Use mkstemp instead of NamedTemporary file for external diff.
66
1711.2.57 by John Arbash Meinel
Allow external diff to write to a file without a fileno.
67
def external_udiff_lines(old, new, use_stringio=False):
68
    if use_stringio:
69
        # StringIO has no fileno, so it tests a different codepath
70
        output = StringIO()
71
    else:
72
        output = TemporaryFile()
1692.8.7 by James Henstridge
changes suggested by John Meinel
73
    try:
74
        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
75
    except NoDiff:
1711.2.56 by John Arbash Meinel
Raise NoDiff if 'diff' not present.
76
        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
77
    output.seek(0, 0)
78
    lines = output.readlines()
79
    output.close()
80
    return lines
81
82
1102 by Martin Pool
- merge test refactoring from robertc
83
class TestDiff(TestCase):
1185.81.25 by Aaron Bentley
Clean up test_diff
84
1102 by Martin Pool
- merge test refactoring from robertc
85
    def test_add_nl(self):
86
        """diff generates a valid diff for patches that add a newline"""
974.1.6 by Aaron Bentley
Added unit tests
87
        lines = udiff_lines(['boo'], ['boo\n'])
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
88
        self.check_patch(lines)
89
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
90
            ## "expected no-nl, got %r" % lines[4]
974.1.6 by Aaron Bentley
Added unit tests
91
1102 by Martin Pool
- merge test refactoring from robertc
92
    def test_add_nl_2(self):
93
        """diff generates a valid diff for patches that change last line and
94
        add a newline.
95
        """
974.1.6 by Aaron Bentley
Added unit tests
96
        lines = udiff_lines(['boo'], ['goo\n'])
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
97
        self.check_patch(lines)
98
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
99
            ## "expected no-nl, got %r" % lines[4]
974.1.6 by Aaron Bentley
Added unit tests
100
1102 by Martin Pool
- merge test refactoring from robertc
101
    def test_remove_nl(self):
102
        """diff generates a valid diff for patches that change last line and
103
        add a newline.
104
        """
974.1.6 by Aaron Bentley
Added unit tests
105
        lines = udiff_lines(['boo\n'], ['boo'])
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
106
        self.check_patch(lines)
107
        self.assertEquals(lines[5], '\\ No newline at end of file\n')
108
            ## "expected no-nl, got %r" % lines[5]
109
110
    def check_patch(self, lines):
111
        self.assert_(len(lines) > 1)
112
            ## "Not enough lines for a file header for patch:\n%s" % "".join(lines)
113
        self.assert_(lines[0].startswith ('---'))
114
            ## 'No orig line for patch:\n%s' % "".join(lines)
115
        self.assert_(lines[1].startswith ('+++'))
116
            ## 'No mod line for patch:\n%s' % "".join(lines)
117
        self.assert_(len(lines) > 2)
118
            ## "No hunks for patch:\n%s" % "".join(lines)
119
        self.assert_(lines[2].startswith('@@'))
120
            ## "No hunk header for patch:\n%s" % "".join(lines)
121
        self.assert_('@@' in lines[2][2:])
122
            ## "Unterminated hunk header for patch:\n%s" % "".join(lines)
123
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
124
    def test_binary_lines(self):
125
        self.assertRaises(BinaryFile, udiff_lines, [1023 * 'a' + '\x00'], [])
126
        self.assertRaises(BinaryFile, udiff_lines, [], [1023 * 'a' + '\x00'])
1558.15.11 by Aaron Bentley
Apply merge review suggestions
127
        udiff_lines([1023 * 'a' + '\x00'], [], allow_binary=True)
128
        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
129
130
    def test_external_diff(self):
131
        lines = external_udiff_lines(['boo\n'], ['goo\n'])
132
        self.check_patch(lines)
1899.1.6 by John Arbash Meinel
internal_diff always adds a trailing \n, make sure external_diff does too
133
        self.assertEqual('\n', lines[-1])
1711.2.57 by John Arbash Meinel
Allow external diff to write to a file without a fileno.
134
135
    def test_external_diff_no_fileno(self):
136
        # Make sure that we can handle not having a fileno, even
137
        # if the diff is large
138
        lines = external_udiff_lines(['boo\n']*10000,
139
                                     ['goo\n']*10000,
140
                                     use_stringio=True)
141
        self.check_patch(lines)
1899.1.1 by John Arbash Meinel
Fix the bug in the NoDiff exception class, and add a test
142
1920.1.1 by John Arbash Meinel
fix bug #56307, handle binary files even when LANG is not english
143
    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)
144
        old_env = {}
145
        for lang in ('LANG', 'LC_ALL', 'LANGUAGE'):
146
            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
147
        try:
148
            lines = external_udiff_lines(['\x00foobar\n'], ['foo\x00bar\n'])
1959.1.1 by Marien Zwart
merge.
149
            # Older versions of diffutils say "Binary files", newer
150
            # versions just say "Files".
151
            self.assertContainsRe(lines[0],
152
                                  '(Binary f|F)iles old and new differ\n')
153
            self.assertEquals(lines[1:], ['\n'])
1920.1.1 by John Arbash Meinel
fix bug #56307, handle binary files even when LANG is not english
154
        finally:
2321.2.5 by Alexander Belchenko
external diff: no need for special code path for win32 (suggested by John Meinel)
155
            for lang, old_val in old_env.iteritems():
156
                osutils.set_or_unset_env(lang, old_val)
1899.1.4 by John Arbash Meinel
Just swallow a return code of 2
157
1899.1.1 by John Arbash Meinel
Fix the bug in the NoDiff exception class, and add a test
158
    def test_no_external_diff(self):
159
        """Check that NoDiff is raised when diff is not available"""
160
        # Use os.environ['PATH'] to make sure no 'diff' command is available
161
        orig_path = os.environ['PATH']
162
        try:
163
            os.environ['PATH'] = ''
164
            self.assertRaises(NoDiff, external_diff,
165
                              'old', ['boo\n'], 'new', ['goo\n'],
166
                              StringIO(), diff_opts=['-u'])
167
        finally:
168
            os.environ['PATH'] = orig_path
1692.8.2 by James Henstridge
add a test for sending external diff output to a file
169
        
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
170
    def test_internal_diff_default(self):
171
        # Default internal diff encoding is utf8
172
        output = StringIO()
173
        internal_diff(u'old_\xb5', ['old_text\n'],
174
                    u'new_\xe5', ['new_text\n'], output)
175
        lines = output.getvalue().splitlines(True)
176
        self.check_patch(lines)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
177
        self.assertEquals(['--- old_\xc2\xb5\n',
178
                           '+++ new_\xc3\xa5\n',
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
179
                           '@@ -1,1 +1,1 @@\n',
180
                           '-old_text\n',
181
                           '+new_text\n',
182
                           '\n',
183
                          ]
184
                          , lines)
185
186
    def test_internal_diff_utf8(self):
187
        output = StringIO()
188
        internal_diff(u'old_\xb5', ['old_text\n'],
189
                    u'new_\xe5', ['new_text\n'], output,
190
                    path_encoding='utf8')
191
        lines = output.getvalue().splitlines(True)
192
        self.check_patch(lines)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
193
        self.assertEquals(['--- old_\xc2\xb5\n',
194
                           '+++ new_\xc3\xa5\n',
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
195
                           '@@ -1,1 +1,1 @@\n',
196
                           '-old_text\n',
197
                           '+new_text\n',
198
                           '\n',
199
                          ]
200
                          , lines)
201
202
    def test_internal_diff_iso_8859_1(self):
203
        output = StringIO()
204
        internal_diff(u'old_\xb5', ['old_text\n'],
205
                    u'new_\xe5', ['new_text\n'], output,
206
                    path_encoding='iso-8859-1')
207
        lines = output.getvalue().splitlines(True)
208
        self.check_patch(lines)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
209
        self.assertEquals(['--- old_\xb5\n',
210
                           '+++ new_\xe5\n',
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
211
                           '@@ -1,1 +1,1 @@\n',
212
                           '-old_text\n',
213
                           '+new_text\n',
214
                           '\n',
215
                          ]
216
                          , lines)
217
218
    def test_internal_diff_returns_bytes(self):
219
        import StringIO
220
        output = StringIO.StringIO()
221
        internal_diff(u'old_\xb5', ['old_text\n'],
222
                    u'new_\xe5', ['new_text\n'], output)
223
        self.failUnless(isinstance(output.getvalue(), str),
224
            'internal_diff should return bytestrings')
225
1185.81.25 by Aaron Bentley
Clean up test_diff
226
1920.1.1 by John Arbash Meinel
fix bug #56307, handle binary files even when LANG is not english
227
class TestDiffFiles(TestCaseInTempDir):
228
229
    def test_external_diff_binary(self):
230
        """The output when using external diff should use diff's i18n error"""
231
        # Make sure external_diff doesn't fail in the current LANG
232
        lines = external_udiff_lines(['\x00foobar\n'], ['foo\x00bar\n'])
233
2240.1.1 by Alexander Belchenko
test_external_diff_binary: run external diff with --binary flag
234
        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
235
        open('old', 'wb').write('\x00foobar\n')
236
        open('new', 'wb').write('foo\x00bar\n')
237
        pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE,
238
                                     stdin=subprocess.PIPE)
239
        out, err = pipe.communicate()
240
        # Diff returns '2' on Binary files.
241
        self.assertEqual(2, pipe.returncode)
242
        # We should output whatever diff tells us, plus a trailing newline
243
        self.assertEqual(out.splitlines(True) + ['\n'], lines)
244
245
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
246
class TestShowDiffTreesHelper(TestCaseWithTransport):
247
    """Has a helper for running show_diff_trees"""
248
249
    def get_diff(self, tree1, tree2, specific_files=None, working_tree=None):
250
        output = StringIO()
251
        if working_tree is not None:
252
            extra_trees = (working_tree,)
253
        else:
254
            extra_trees = ()
255
        show_diff_trees(tree1, tree2, output, specific_files=specific_files,
256
                        extra_trees=extra_trees, old_label='old/',
257
                        new_label='new/')
258
        return output.getvalue()
259
260
261
class TestDiffDates(TestShowDiffTreesHelper):
1740.2.5 by Aaron Bentley
Merge from bzr.dev
262
263
    def setUp(self):
264
        super(TestDiffDates, self).setUp()
265
        self.wt = self.make_branch_and_tree('.')
266
        self.b = self.wt.branch
267
        self.build_tree_contents([
268
            ('file1', 'file1 contents at rev 1\n'),
269
            ('file2', 'file2 contents at rev 1\n')
270
            ])
271
        self.wt.add(['file1', 'file2'])
272
        self.wt.commit(
273
            message='Revision 1',
274
            timestamp=1143849600, # 2006-04-01 00:00:00 UTC
275
            timezone=0,
276
            rev_id='rev-1')
277
        self.build_tree_contents([('file1', 'file1 contents at rev 2\n')])
278
        self.wt.commit(
279
            message='Revision 2',
280
            timestamp=1143936000, # 2006-04-02 00:00:00 UTC
281
            timezone=28800,
282
            rev_id='rev-2')
283
        self.build_tree_contents([('file2', 'file2 contents at rev 3\n')])
284
        self.wt.commit(
285
            message='Revision 3',
286
            timestamp=1144022400, # 2006-04-03 00:00:00 UTC
287
            timezone=-3600,
288
            rev_id='rev-3')
289
        self.wt.remove(['file2'])
290
        self.wt.commit(
291
            message='Revision 4',
292
            timestamp=1144108800, # 2006-04-04 00:00:00 UTC
293
            timezone=0,
294
            rev_id='rev-4')
295
        self.build_tree_contents([
296
            ('file1', 'file1 contents in working tree\n')
297
            ])
298
        # set the date stamps for files in the working tree to known values
299
        os.utime('file1', (1144195200, 1144195200)) # 2006-04-05 00:00:00 UTC
300
301
    def test_diff_rev_tree_working_tree(self):
302
        output = self.get_diff(self.wt.basis_tree(), self.wt)
303
        # note that the date for old/file1 is from rev 2 rather than from
304
        # the basis revision (rev 4)
305
        self.assertEqualDiff(output, '''\
306
=== modified file 'file1'
307
--- old/file1\t2006-04-02 00:00:00 +0000
308
+++ new/file1\t2006-04-05 00:00:00 +0000
309
@@ -1,1 +1,1 @@
310
-file1 contents at rev 2
311
+file1 contents in working tree
312
313
''')
314
315
    def test_diff_rev_tree_rev_tree(self):
316
        tree1 = self.b.repository.revision_tree('rev-2')
317
        tree2 = self.b.repository.revision_tree('rev-3')
318
        output = self.get_diff(tree1, tree2)
319
        self.assertEqualDiff(output, '''\
320
=== modified file 'file2'
321
--- old/file2\t2006-04-01 00:00:00 +0000
322
+++ new/file2\t2006-04-03 00:00:00 +0000
323
@@ -1,1 +1,1 @@
324
-file2 contents at rev 1
325
+file2 contents at rev 3
326
327
''')
328
        
329
    def test_diff_add_files(self):
330
        tree1 = self.b.repository.revision_tree(None)
331
        tree2 = self.b.repository.revision_tree('rev-1')
332
        output = self.get_diff(tree1, tree2)
333
        # the files have the epoch time stamp for the tree in which
334
        # they don't exist.
335
        self.assertEqualDiff(output, '''\
336
=== added file 'file1'
337
--- old/file1\t1970-01-01 00:00:00 +0000
338
+++ new/file1\t2006-04-01 00:00:00 +0000
339
@@ -0,0 +1,1 @@
340
+file1 contents at rev 1
341
342
=== added file 'file2'
343
--- old/file2\t1970-01-01 00:00:00 +0000
344
+++ new/file2\t2006-04-01 00:00:00 +0000
345
@@ -0,0 +1,1 @@
346
+file2 contents at rev 1
347
348
''')
349
350
    def test_diff_remove_files(self):
351
        tree1 = self.b.repository.revision_tree('rev-3')
352
        tree2 = self.b.repository.revision_tree('rev-4')
353
        output = self.get_diff(tree1, tree2)
354
        # the file has the epoch time stamp for the tree in which
355
        # it doesn't exist.
356
        self.assertEqualDiff(output, '''\
357
=== removed file 'file2'
358
--- old/file2\t2006-04-03 00:00:00 +0000
359
+++ new/file2\t1970-01-01 00:00:00 +0000
360
@@ -1,1 +0,0 @@
361
-file2 contents at rev 3
362
363
''')
364
1551.7.17 by Aaron Bentley
Switch to PathsNotVersioned, accept extra_trees
365
    def test_show_diff_specified(self):
1551.7.22 by Aaron Bentley
Changes from review
366
        """A working tree filename can be used to identify a file"""
1551.7.17 by Aaron Bentley
Switch to PathsNotVersioned, accept extra_trees
367
        self.wt.rename_one('file1', 'file1b')
368
        old_tree = self.b.repository.revision_tree('rev-1')
369
        new_tree = self.b.repository.revision_tree('rev-4')
1551.7.22 by Aaron Bentley
Changes from review
370
        out = self.get_diff(old_tree, new_tree, specific_files=['file1b'], 
371
                            working_tree=self.wt)
372
        self.assertContainsRe(out, 'file1\t')
1551.7.17 by Aaron Bentley
Switch to PathsNotVersioned, accept extra_trees
373
1551.7.22 by Aaron Bentley
Changes from review
374
    def test_recursive_diff(self):
375
        """Children of directories are matched"""
376
        os.mkdir('dir1')
377
        os.mkdir('dir2')
378
        self.wt.add(['dir1', 'dir2'])
379
        self.wt.rename_one('file1', 'dir1/file1')
380
        old_tree = self.b.repository.revision_tree('rev-1')
381
        new_tree = self.b.repository.revision_tree('rev-4')
382
        out = self.get_diff(old_tree, new_tree, specific_files=['dir1'], 
383
                            working_tree=self.wt)
384
        self.assertContainsRe(out, 'file1\t')
385
        out = self.get_diff(old_tree, new_tree, specific_files=['dir2'], 
386
                            working_tree=self.wt)
387
        self.assertNotContainsRe(out, 'file1\t')
1740.2.5 by Aaron Bentley
Merge from bzr.dev
388
1899.1.1 by John Arbash Meinel
Fix the bug in the NoDiff exception class, and add a test
389
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
390
391
class TestShowDiffTrees(TestShowDiffTreesHelper):
392
    """Direct tests for show_diff_trees"""
393
394
    def test_modified_file(self):
395
        """Test when a file is modified."""
396
        tree = self.make_branch_and_tree('tree')
397
        self.build_tree_contents([('tree/file', 'contents\n')])
398
        tree.add(['file'], ['file-id'])
399
        tree.commit('one', rev_id='rev-1')
400
401
        self.build_tree_contents([('tree/file', 'new contents\n')])
402
        diff = self.get_diff(tree.basis_tree(), tree)
403
        self.assertContainsRe(diff, "=== modified file 'file'\n")
404
        self.assertContainsRe(diff, '--- old/file\t')
405
        self.assertContainsRe(diff, '\\+\\+\\+ new/file\t')
406
        self.assertContainsRe(diff, '-contents\n'
407
                                    '\\+new contents\n')
408
2405.1.2 by John Arbash Meinel
Fix bug #103870 by passing None instead of a (sometimes wrong) path
409
    def test_modified_file_in_renamed_dir(self):
410
        """Test when a file is modified in a renamed directory."""
411
        tree = self.make_branch_and_tree('tree')
412
        self.build_tree(['tree/dir/'])
413
        self.build_tree_contents([('tree/dir/file', 'contents\n')])
414
        tree.add(['dir', 'dir/file'], ['dir-id', 'file-id'])
415
        tree.commit('one', rev_id='rev-1')
416
417
        tree.rename_one('dir', 'other')
418
        self.build_tree_contents([('tree/other/file', 'new contents\n')])
419
        diff = self.get_diff(tree.basis_tree(), tree)
420
        self.assertContainsRe(diff, "=== renamed directory 'dir' => 'other'\n")
421
        self.assertContainsRe(diff, "=== modified file 'other/file'\n")
422
        # XXX: This is technically incorrect, because it used to be at another
423
        # 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.
424
        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
425
        self.assertContainsRe(diff, '\\+\\+\\+ new/other/file\t')
426
        self.assertContainsRe(diff, '-contents\n'
427
                                    '\\+new contents\n')
428
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
429
    def test_renamed_directory(self):
430
        """Test when only a directory is only renamed."""
431
        tree = self.make_branch_and_tree('tree')
432
        self.build_tree(['tree/dir/'])
433
        self.build_tree_contents([('tree/dir/file', 'contents\n')])
434
        tree.add(['dir', 'dir/file'], ['dir-id', 'file-id'])
435
        tree.commit('one', rev_id='rev-1')
436
437
        tree.rename_one('dir', 'newdir')
438
        diff = self.get_diff(tree.basis_tree(), tree)
439
        # Renaming a directory should be a single "you renamed this dir" even
440
        # when there are files inside.
441
        self.assertEqual("=== renamed directory 'dir' => 'newdir'\n", diff)
442
443
    def test_renamed_file(self):
444
        """Test when a file is only renamed."""
445
        tree = self.make_branch_and_tree('tree')
446
        self.build_tree_contents([('tree/file', 'contents\n')])
447
        tree.add(['file'], ['file-id'])
448
        tree.commit('one', rev_id='rev-1')
449
450
        tree.rename_one('file', 'newname')
451
        diff = self.get_diff(tree.basis_tree(), tree)
452
        self.assertContainsRe(diff, "=== renamed file 'file' => 'newname'\n")
453
        # We shouldn't have a --- or +++ line, because there is no content
454
        # change
455
        self.assertNotContainsRe(diff, '---')
456
457
    def test_renamed_and_modified_file(self):
458
        """Test when a file is only renamed."""
459
        tree = self.make_branch_and_tree('tree')
460
        self.build_tree_contents([('tree/file', 'contents\n')])
461
        tree.add(['file'], ['file-id'])
462
        tree.commit('one', rev_id='rev-1')
463
464
        tree.rename_one('file', 'newname')
465
        self.build_tree_contents([('tree/newname', 'new contents\n')])
466
        diff = self.get_diff(tree.basis_tree(), tree)
467
        self.assertContainsRe(diff, "=== renamed file 'file' => 'newname'\n")
468
        self.assertContainsRe(diff, '--- old/file\t')
469
        self.assertContainsRe(diff, '\\+\\+\\+ new/newname\t')
470
        self.assertContainsRe(diff, '-contents\n'
471
                                    '\\+new contents\n')
472
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
473
    def test_binary_unicode_filenames(self):
2592.2.2 by Jonathan Lange
Apply jam's comments to test_binary_unicode_filenames. Change the
474
        """Test that contents of files are *not* encoded in UTF-8 when there
475
        is a binary file in the diff.
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
476
        """
477
        # See https://bugs.launchpad.net/bugs/110092.
2592.2.4 by Jonathan Lange
Skip the unicode filename test if the platform doesn't support unicode
478
        self.requireFeature(UnicodeFilename)
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
479
480
        # This bug isn't triggered with cStringIO.
481
        from StringIO import StringIO
482
        tree = self.make_branch_and_tree('tree')
2592.2.2 by Jonathan Lange
Apply jam's comments to test_binary_unicode_filenames. Change the
483
        alpha, omega = u'\u03b1', u'\u03c9'
484
        alpha_utf8, omega_utf8 = alpha.encode('utf8'), omega.encode('utf8')
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
485
        self.build_tree_contents(
2592.2.2 by Jonathan Lange
Apply jam's comments to test_binary_unicode_filenames. Change the
486
            [('tree/' + alpha, chr(0)),
487
             ('tree/' + omega,
488
              ('The %s and the %s\n' % (alpha_utf8, omega_utf8)))])
489
        tree.add([alpha], ['file-id'])
490
        tree.add([omega], ['file-id-2'])
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
491
        diff_content = StringIO()
492
        show_diff_trees(tree.basis_tree(), tree, diff_content)
493
        diff = diff_content.getvalue()
2592.2.2 by Jonathan Lange
Apply jam's comments to test_binary_unicode_filenames. Change the
494
        self.assertContainsRe(diff, r"=== added file '%s'" % alpha_utf8)
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
495
        self.assertContainsRe(
2592.2.2 by Jonathan Lange
Apply jam's comments to test_binary_unicode_filenames. Change the
496
            diff, "Binary files a/%s.*and b/%s.* differ\n" % (alpha_utf8, alpha_utf8))
497
        self.assertContainsRe(diff, r"=== added file '%s'" % omega_utf8)
498
        self.assertContainsRe(diff, r"--- a/%s" % (omega_utf8,))
499
        self.assertContainsRe(diff, r"\+\+\+ b/%s" % (omega_utf8,))
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
500
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
501
1711.2.15 by John Arbash Meinel
Found a couple CDV left
502
class TestPatienceDiffLib(TestCase):
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
503
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
504
    def test_unique_lcs(self):
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
505
        unique_lcs = bzrlib.patiencediff.unique_lcs
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
506
        self.assertEquals(unique_lcs('', ''), [])
507
        self.assertEquals(unique_lcs('a', 'a'), [(0,0)])
508
        self.assertEquals(unique_lcs('a', 'b'), [])
509
        self.assertEquals(unique_lcs('ab', 'ab'), [(0,0), (1,1)])
510
        self.assertEquals(unique_lcs('abcde', 'cdeab'), [(2,0), (3,1), (4,2)])
511
        self.assertEquals(unique_lcs('cdeab', 'abcde'), [(0,2), (1,3), (2,4)])
512
        self.assertEquals(unique_lcs('abXde', 'abYde'), [(0,0), (1,1), 
513
                                                         (3,3), (4,4)])
514
        self.assertEquals(unique_lcs('acbac', 'abc'), [(2,1)])
515
516
    def test_recurse_matches(self):
517
        def test_one(a, b, matches):
518
            test_matches = []
1711.2.22 by John Arbash Meinel
Passing the alo parameter to recurse_matches shaves of 5% of the diff time.
519
            bzrlib.patiencediff.recurse_matches(a, b, 0, 0, len(a), len(b),
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
520
                test_matches, 10)
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
521
            self.assertEquals(test_matches, matches)
522
1711.2.17 by John Arbash Meinel
Small cleanups to patience_diff code.
523
        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,
524
                 [(0, 0), (2, 2), (4, 4)])
525
        test_one(['a', 'c', 'b', 'a', 'c'], ['a', 'b', 'c'],
526
                 [(0, 0), (2, 1), (4, 2)])
527
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
528
        # recurse_matches doesn't match non-unique 
529
        # lines surrounded by bogus text.
1185.81.24 by Aaron Bentley
Reoganize patience-related code
530
        # 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
531
532
        # This is what it could be
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
533
        #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
534
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
535
        # This is what it currently gives:
536
        test_one('aBccDe', 'abccde', [(0,0), (5,5)])
537
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
538
    def test_matching_blocks(self):
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
539
        def chk_blocks(a, b, expected_blocks):
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
540
            # difflib always adds a signature of the total
541
            # length, with no matching entries at the end
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
542
            s = bzrlib.patiencediff.PatienceSequenceMatcher(None, a, b)
1185.81.11 by John Arbash Meinel
Found some edge cases that weren't being matched.
543
            blocks = s.get_matching_blocks()
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
544
            self.assertEquals((len(a), len(b), 0), blocks[-1])
545
            self.assertEquals(expected_blocks, blocks[:-1])
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
546
1185.81.2 by John Arbash Meinel
A couple small tests.
547
        # Some basic matching tests
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
548
        chk_blocks('', '', [])
549
        chk_blocks([], [], [])
550
        chk_blocks('abcd', 'abcd', [(0, 0, 4)])
551
        chk_blocks('abcd', 'abce', [(0, 0, 3)])
552
        chk_blocks('eabc', 'abce', [(1, 0, 3)])
553
        chk_blocks('eabce', 'abce', [(1, 0, 4)])
554
        chk_blocks('abcde', 'abXde', [(0, 0, 2), (3, 3, 2)])
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
555
        chk_blocks('abcde', 'abXYZde', [(0, 0, 2), (3, 5, 2)])
556
        chk_blocks('abde', 'abXYZde', [(0, 0, 2), (2, 5, 2)])
557
        # This may check too much, but it checks to see that 
558
        # a copied block stays attached to the previous section,
559
        # not the later one.
560
        # difflib would tend to grab the trailing longest match
561
        # which would make the diff not look right
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
562
        chk_blocks('abcdefghijklmnop', 'abcdefxydefghijklmnop',
563
                   [(0, 0, 6), (6, 11, 10)])
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
564
1185.81.2 by John Arbash Meinel
A couple small tests.
565
        # make sure it supports passing in lists
566
        chk_blocks(
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
567
                   ['hello there\n',
568
                    'world\n',
569
                    'how are you today?\n'],
570
                   ['hello there\n',
571
                    'how are you today?\n'],
1185.81.2 by John Arbash Meinel
A couple small tests.
572
                [(0, 0, 1), (2, 1, 1)])
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
573
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
574
        # non unique lines surrounded by non-matching lines
575
        # won't be found
576
        chk_blocks('aBccDe', 'abccde', [(0,0,1), (5,5,1)])
577
578
        # But they only need to be locally unique
579
        chk_blocks('aBcDec', 'abcdec', [(0,0,1), (2,2,1), (4,4,2)])
580
581
        # non unique blocks won't be matched
582
        chk_blocks('aBcdEcdFg', 'abcdecdfg', [(0,0,1), (8,8,1)])
583
584
        # but locally unique ones will
585
        chk_blocks('aBcdEeXcdFg', 'abcdecdfg', [(0,0,1), (2,2,2),
586
                                              (5,4,1), (7,5,2), (10,8,1)])
587
588
        chk_blocks('abbabbXd', 'cabbabxd', [(7,7,1)])
589
        chk_blocks('abbabbbb', 'cabbabbc', [])
590
        chk_blocks('bbbbbbbb', 'cbbbbbbc', [])
1185.81.11 by John Arbash Meinel
Found some edge cases that weren't being matched.
591
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
592
    def test_opcodes(self):
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
593
        def chk_ops(a, b, expected_codes):
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
594
            s = bzrlib.patiencediff.PatienceSequenceMatcher(None, a, b)
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
595
            self.assertEquals(expected_codes, s.get_opcodes())
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
596
597
        chk_ops('', '', [])
598
        chk_ops([], [], [])
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
599
        chk_ops('abcd', 'abcd', [('equal',    0,4, 0,4)])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
600
        chk_ops('abcd', 'abce', [('equal',   0,3, 0,3),
601
                                 ('replace', 3,4, 3,4)
602
                                ])
603
        chk_ops('eabc', 'abce', [('delete', 0,1, 0,0),
604
                                 ('equal',  1,4, 0,3),
605
                                 ('insert', 4,4, 3,4)
606
                                ])
607
        chk_ops('eabce', 'abce', [('delete', 0,1, 0,0),
608
                                  ('equal',  1,5, 0,4)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
609
                                 ])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
610
        chk_ops('abcde', 'abXde', [('equal',   0,2, 0,2),
611
                                   ('replace', 2,3, 2,3),
612
                                   ('equal',   3,5, 3,5)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
613
                                  ])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
614
        chk_ops('abcde', 'abXYZde', [('equal',   0,2, 0,2),
615
                                     ('replace', 2,3, 2,5),
616
                                     ('equal',   3,5, 5,7)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
617
                                    ])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
618
        chk_ops('abde', 'abXYZde', [('equal',  0,2, 0,2),
619
                                    ('insert', 2,2, 2,5),
620
                                    ('equal',  2,4, 5,7)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
621
                                   ])
622
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
623
                [('equal',  0,6,  0,6),
624
                 ('insert', 6,6,  6,11),
625
                 ('equal',  6,16, 11,21)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
626
                ])
627
        chk_ops(
628
                [ 'hello there\n'
629
                , 'world\n'
630
                , 'how are you today?\n'],
631
                [ 'hello there\n'
632
                , 'how are you today?\n'],
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
633
                [('equal',  0,1, 0,1),
634
                 ('delete', 1,2, 1,1),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
635
                 ('equal',  2,3, 1,2),
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
636
                ])
637
        chk_ops('aBccDe', 'abccde', 
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
638
                [('equal',   0,1, 0,1),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
639
                 ('replace', 1,5, 1,5),
640
                 ('equal',   5,6, 5,6),
641
                ])
642
        chk_ops('aBcDec', 'abcdec', 
643
                [('equal',   0,1, 0,1),
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
644
                 ('replace', 1,2, 1,2),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
645
                 ('equal',   2,3, 2,3),
646
                 ('replace', 3,4, 3,4),
647
                 ('equal',   4,6, 4,6),
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
648
                ])
1185.81.10 by John Arbash Meinel
Added some more test cases.
649
        chk_ops('aBcdEcdFg', 'abcdecdfg', 
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
650
                [('equal',   0,1, 0,1),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
651
                 ('replace', 1,8, 1,8),
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
652
                 ('equal',   8,9, 8,9)
1185.81.10 by John Arbash Meinel
Added some more test cases.
653
                ])
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
654
        chk_ops('aBcdEeXcdFg', 'abcdecdfg', 
655
                [('equal',   0,1, 0,1),
656
                 ('replace', 1,2, 1,2),
657
                 ('equal',   2,4, 2,4),
658
                 ('delete', 4,5, 4,4),
659
                 ('equal',   5,6, 4,5),
660
                 ('delete', 6,7, 5,5),
661
                 ('equal',   7,9, 5,7),
662
                 ('replace', 9,10, 7,8),
663
                 ('equal',   10,11, 8,9)
664
                ])
1185.81.10 by John Arbash Meinel
Added some more test cases.
665
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
666
    def test_multiple_ranges(self):
667
        # There was an earlier bug where we used a bad set of ranges,
668
        # this triggers that specific bug, to make sure it doesn't regress
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
669
        def chk_blocks(a, b, expected_blocks):
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
670
            # difflib always adds a signature of the total
671
            # length, with no matching entries at the end
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
672
            s = bzrlib.patiencediff.PatienceSequenceMatcher(None, a, b)
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
673
            blocks = s.get_matching_blocks()
674
            x = blocks.pop()
675
            self.assertEquals(x, (len(a), len(b), 0))
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
676
            self.assertEquals(expected_blocks, blocks)
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
677
678
        chk_blocks('abcdefghijklmnop'
679
                 , 'abcXghiYZQRSTUVWXYZijklmnop'
680
                 , [(0, 0, 3), (6, 4, 3), (9, 20, 7)])
681
682
        chk_blocks('ABCd efghIjk  L'
683
                 , 'AxyzBCn mo pqrstuvwI1 2  L'
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
684
                 , [(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.
685
1711.2.8 by John Arbash Meinel
rot13 the code snippet to help with clarity.
686
        # These are rot13 code snippets.
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
687
        chk_blocks('''\
1711.2.8 by John Arbash Meinel
rot13 the code snippet to help with clarity.
688
    trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
689
    """
690
    gnxrf_netf = ['svyr*']
691
    gnxrf_bcgvbaf = ['ab-erphefr']
692
  
693
    qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr):
694
        sebz omeyvo.nqq vzcbeg fzneg_nqq, nqq_ercbegre_cevag, nqq_ercbegre_ahyy
695
        vs vf_dhvrg():
696
            ercbegre = nqq_ercbegre_ahyy
697
        ryfr:
698
            ercbegre = nqq_ercbegre_cevag
699
        fzneg_nqq(svyr_yvfg, abg ab_erphefr, ercbegre)
700
701
702
pynff pzq_zxqve(Pbzznaq):
703
'''.splitlines(True), '''\
704
    trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
705
706
    --qel-eha jvyy fubj juvpu svyrf jbhyq or nqqrq, ohg abg npghnyyl 
707
    nqq gurz.
708
    """
709
    gnxrf_netf = ['svyr*']
710
    gnxrf_bcgvbaf = ['ab-erphefr', 'qel-eha']
711
712
    qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr, qel_eha=Snyfr):
713
        vzcbeg omeyvo.nqq
714
715
        vs qel_eha:
716
            vs vf_dhvrg():
717
                # Guvf vf cbvagyrff, ohg V'q engure abg envfr na reebe
718
                npgvba = omeyvo.nqq.nqq_npgvba_ahyy
719
            ryfr:
720
  npgvba = omeyvo.nqq.nqq_npgvba_cevag
721
        ryvs vf_dhvrg():
722
            npgvba = omeyvo.nqq.nqq_npgvba_nqq
723
        ryfr:
724
       npgvba = omeyvo.nqq.nqq_npgvba_nqq_naq_cevag
725
726
        omeyvo.nqq.fzneg_nqq(svyr_yvfg, abg ab_erphefr, npgvba)
727
728
729
pynff pzq_zxqve(Pbzznaq):
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
730
'''.splitlines(True)
731
, [(0,0,1), (1, 4, 2), (9, 19, 1), (12, 23, 3)])
732
1711.2.9 by John Arbash Meinel
Rename cdv => patience
733
    def test_patience_unified_diff(self):
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
734
        txt_a = ['hello there\n',
735
                 'world\n',
736
                 'how are you today?\n']
737
        txt_b = ['hello there\n',
738
                 'how are you today?\n']
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
739
        unified_diff = bzrlib.patiencediff.unified_diff
740
        psm = bzrlib.patiencediff.PatienceSequenceMatcher
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
741
        self.assertEquals([ '---  \n',
742
                           '+++  \n',
743
                           '@@ -1,3 +1,2 @@\n',
744
                           ' hello there\n',
745
                           '-world\n',
746
                           ' 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
747
                          ]
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
748
                          , list(unified_diff(txt_a, txt_b,
749
                                 sequencematcher=psm)))
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
750
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
751
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
752
        # This is the result with LongestCommonSubstring matching
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
753
        self.assertEquals(['---  \n',
754
                           '+++  \n',
755
                           '@@ -1,6 +1,11 @@\n',
756
                           ' a\n',
757
                           ' b\n',
758
                           ' c\n',
759
                           '+d\n',
760
                           '+e\n',
761
                           '+f\n',
762
                           '+x\n',
763
                           '+y\n',
764
                           ' d\n',
765
                           ' e\n',
766
                           ' f\n']
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
767
                          , list(unified_diff(txt_a, txt_b)))
1711.2.9 by John Arbash Meinel
Rename cdv => patience
768
        # And the patience diff
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
769
        self.assertEquals(['---  \n',
770
                           '+++  \n',
771
                           '@@ -4,6 +4,11 @@\n',
772
                           ' d\n',
773
                           ' e\n',
774
                           ' f\n',
775
                           '+x\n',
776
                           '+y\n',
777
                           '+d\n',
778
                           '+e\n',
779
                           '+f\n',
780
                           ' g\n',
781
                           ' h\n',
782
                           ' i\n',
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
783
                          ]
1185.81.25 by Aaron Bentley
Clean up test_diff
784
                          , 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
785
                                 sequencematcher=psm)))
1185.81.25 by Aaron Bentley
Clean up test_diff
786
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
787
1711.2.15 by John Arbash Meinel
Found a couple CDV left
788
class TestPatienceDiffLibFiles(TestCaseInTempDir):
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
789
1711.2.9 by John Arbash Meinel
Rename cdv => patience
790
    def test_patience_unified_diff_files(self):
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
791
        txt_a = ['hello there\n',
792
                 'world\n',
793
                 'how are you today?\n']
794
        txt_b = ['hello there\n',
795
                 '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
796
        open('a1', 'wb').writelines(txt_a)
797
        open('b1', 'wb').writelines(txt_b)
798
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
799
        unified_diff_files = bzrlib.patiencediff.unified_diff_files
800
        psm = bzrlib.patiencediff.PatienceSequenceMatcher
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
801
        self.assertEquals(['--- a1 \n',
802
                           '+++ b1 \n',
803
                           '@@ -1,3 +1,2 @@\n',
804
                           ' hello there\n',
805
                           '-world\n',
806
                           ' 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
807
                          ]
1185.81.25 by Aaron Bentley
Clean up test_diff
808
                          , 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
809
                                 sequencematcher=psm)))
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
810
811
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
812
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
813
        open('a2', 'wb').writelines(txt_a)
814
        open('b2', 'wb').writelines(txt_b)
815
816
        # This is the result with LongestCommonSubstring matching
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
817
        self.assertEquals(['--- a2 \n',
818
                           '+++ b2 \n',
819
                           '@@ -1,6 +1,11 @@\n',
820
                           ' a\n',
821
                           ' b\n',
822
                           ' c\n',
823
                           '+d\n',
824
                           '+e\n',
825
                           '+f\n',
826
                           '+x\n',
827
                           '+y\n',
828
                           ' d\n',
829
                           ' e\n',
830
                           ' f\n']
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
831
                          , list(unified_diff_files('a2', 'b2')))
832
1711.2.9 by John Arbash Meinel
Rename cdv => patience
833
        # And the patience diff
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
834
        self.assertEquals(['--- a2 \n',
835
                           '+++ b2 \n',
836
                           '@@ -4,6 +4,11 @@\n',
837
                           ' d\n',
838
                           ' e\n',
839
                           ' f\n',
840
                           '+x\n',
841
                           '+y\n',
842
                           '+d\n',
843
                           '+e\n',
844
                           '+f\n',
845
                           ' g\n',
846
                           ' h\n',
847
                           ' i\n',
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
848
                          ]
1185.81.25 by Aaron Bentley
Clean up test_diff
849
                          , 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
850
                                 sequencematcher=psm)))