/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
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
3009.2.9 by Aaron Bentley
Add tests for Differ
23
from bzrlib.diff import (
24
    internal_diff,
25
    external_diff,
3009.2.22 by Aaron Bentley
Update names & docstring
26
    DiffPath,
3009.2.9 by Aaron Bentley
Add tests for Differ
27
    show_diff_trees,
3009.2.22 by Aaron Bentley
Update names & docstring
28
    DiffSymlink,
29
    DiffTree,
30
    DiffText,
3009.2.9 by Aaron Bentley
Add tests for Differ
31
    )
1711.2.56 by John Arbash Meinel
Raise NoDiff if 'diff' not present.
32
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)
33
import bzrlib.osutils as osutils
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
34
import bzrlib.patiencediff
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
35
import bzrlib._patiencediff_py
2592.2.4 by Jonathan Lange
Skip the unicode filename test if the platform doesn't support unicode
36
from bzrlib.tests import (Feature, TestCase, TestCaseWithTransport,
1711.2.54 by John Arbash Meinel
Use mkstemp instead of NamedTemporary file for external diff.
37
                          TestCaseInTempDir, TestSkipped)
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
38
39
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
40
class _CompiledPatienceDiffFeature(Feature):
41
42
    def _probe(self):
43
        try:
44
            import bzrlib._patiencediff_c
45
        except ImportError:
46
            return False
47
        return True
48
49
    def feature_name(self):
50
        return 'bzrlib._patiencediff_c'
51
52
CompiledPatienceDiffFeature = _CompiledPatienceDiffFeature()
53
54
2592.2.4 by Jonathan Lange
Skip the unicode filename test if the platform doesn't support unicode
55
class _UnicodeFilename(Feature):
56
    """Does the filesystem support Unicode filenames?"""
57
58
    def _probe(self):
59
        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
60
            os.stat(u'\u03b1')
2592.2.4 by Jonathan Lange
Skip the unicode filename test if the platform doesn't support unicode
61
        except UnicodeEncodeError:
62
            return False
2592.2.5 by Jonathan Lange
Make UnicodeFilename feature less insane. Add a simple test for it too.
63
        except (IOError, OSError):
64
            # 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
65
            # exist.
2592.2.5 by Jonathan Lange
Make UnicodeFilename feature less insane. Add a simple test for it too.
66
            return True
67
        else:
68
            # The filesystem allows the Unicode filename and the file exists,
69
            # for some reason.
70
            return True
2592.2.4 by Jonathan Lange
Skip the unicode filename test if the platform doesn't support unicode
71
72
UnicodeFilename = _UnicodeFilename()
73
74
2592.2.5 by Jonathan Lange
Make UnicodeFilename feature less insane. Add a simple test for it too.
75
class TestUnicodeFilename(TestCase):
76
77
    def test_probe_passes(self):
78
        """UnicodeFilename._probe passes."""
79
        # We can't test much more than that because the behaviour depends
80
        # on the platform.
81
        UnicodeFilename._probe()
82
        
83
1558.15.11 by Aaron Bentley
Apply merge review suggestions
84
def udiff_lines(old, new, allow_binary=False):
974.1.6 by Aaron Bentley
Added unit tests
85
    output = StringIO()
1558.15.11 by Aaron Bentley
Apply merge review suggestions
86
    internal_diff('old', old, 'new', new, output, allow_binary)
974.1.6 by Aaron Bentley
Added unit tests
87
    output.seek(0, 0)
88
    return output.readlines()
89
1711.2.54 by John Arbash Meinel
Use mkstemp instead of NamedTemporary file for external diff.
90
1711.2.57 by John Arbash Meinel
Allow external diff to write to a file without a fileno.
91
def external_udiff_lines(old, new, use_stringio=False):
92
    if use_stringio:
93
        # StringIO has no fileno, so it tests a different codepath
94
        output = StringIO()
95
    else:
96
        output = TemporaryFile()
1692.8.7 by James Henstridge
changes suggested by John Meinel
97
    try:
98
        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
99
    except NoDiff:
1711.2.56 by John Arbash Meinel
Raise NoDiff if 'diff' not present.
100
        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
101
    output.seek(0, 0)
102
    lines = output.readlines()
103
    output.close()
104
    return lines
105
106
1102 by Martin Pool
- merge test refactoring from robertc
107
class TestDiff(TestCase):
1185.81.25 by Aaron Bentley
Clean up test_diff
108
1102 by Martin Pool
- merge test refactoring from robertc
109
    def test_add_nl(self):
110
        """diff generates a valid diff for patches that add a newline"""
974.1.6 by Aaron Bentley
Added unit tests
111
        lines = udiff_lines(['boo'], ['boo\n'])
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
112
        self.check_patch(lines)
113
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
114
            ## "expected no-nl, got %r" % lines[4]
974.1.6 by Aaron Bentley
Added unit tests
115
1102 by Martin Pool
- merge test refactoring from robertc
116
    def test_add_nl_2(self):
117
        """diff generates a valid diff for patches that change last line and
118
        add a newline.
119
        """
974.1.6 by Aaron Bentley
Added unit tests
120
        lines = udiff_lines(['boo'], ['goo\n'])
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
121
        self.check_patch(lines)
122
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
123
            ## "expected no-nl, got %r" % lines[4]
974.1.6 by Aaron Bentley
Added unit tests
124
1102 by Martin Pool
- merge test refactoring from robertc
125
    def test_remove_nl(self):
126
        """diff generates a valid diff for patches that change last line and
127
        add a newline.
128
        """
974.1.6 by Aaron Bentley
Added unit tests
129
        lines = udiff_lines(['boo\n'], ['boo'])
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
130
        self.check_patch(lines)
131
        self.assertEquals(lines[5], '\\ No newline at end of file\n')
132
            ## "expected no-nl, got %r" % lines[5]
133
134
    def check_patch(self, lines):
135
        self.assert_(len(lines) > 1)
136
            ## "Not enough lines for a file header for patch:\n%s" % "".join(lines)
137
        self.assert_(lines[0].startswith ('---'))
138
            ## 'No orig line for patch:\n%s' % "".join(lines)
139
        self.assert_(lines[1].startswith ('+++'))
140
            ## 'No mod line for patch:\n%s' % "".join(lines)
141
        self.assert_(len(lines) > 2)
142
            ## "No hunks for patch:\n%s" % "".join(lines)
143
        self.assert_(lines[2].startswith('@@'))
144
            ## "No hunk header for patch:\n%s" % "".join(lines)
145
        self.assert_('@@' in lines[2][2:])
146
            ## "Unterminated hunk header for patch:\n%s" % "".join(lines)
147
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
148
    def test_binary_lines(self):
149
        self.assertRaises(BinaryFile, udiff_lines, [1023 * 'a' + '\x00'], [])
150
        self.assertRaises(BinaryFile, udiff_lines, [], [1023 * 'a' + '\x00'])
1558.15.11 by Aaron Bentley
Apply merge review suggestions
151
        udiff_lines([1023 * 'a' + '\x00'], [], allow_binary=True)
152
        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
153
154
    def test_external_diff(self):
155
        lines = external_udiff_lines(['boo\n'], ['goo\n'])
156
        self.check_patch(lines)
1899.1.6 by John Arbash Meinel
internal_diff always adds a trailing \n, make sure external_diff does too
157
        self.assertEqual('\n', lines[-1])
1711.2.57 by John Arbash Meinel
Allow external diff to write to a file without a fileno.
158
159
    def test_external_diff_no_fileno(self):
160
        # Make sure that we can handle not having a fileno, even
161
        # if the diff is large
162
        lines = external_udiff_lines(['boo\n']*10000,
163
                                     ['goo\n']*10000,
164
                                     use_stringio=True)
165
        self.check_patch(lines)
1899.1.1 by John Arbash Meinel
Fix the bug in the NoDiff exception class, and add a test
166
1920.1.1 by John Arbash Meinel
fix bug #56307, handle binary files even when LANG is not english
167
    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)
168
        old_env = {}
169
        for lang in ('LANG', 'LC_ALL', 'LANGUAGE'):
170
            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
171
        try:
172
            lines = external_udiff_lines(['\x00foobar\n'], ['foo\x00bar\n'])
1959.1.1 by Marien Zwart
merge.
173
            # Older versions of diffutils say "Binary files", newer
174
            # versions just say "Files".
175
            self.assertContainsRe(lines[0],
176
                                  '(Binary f|F)iles old and new differ\n')
177
            self.assertEquals(lines[1:], ['\n'])
1920.1.1 by John Arbash Meinel
fix bug #56307, handle binary files even when LANG is not english
178
        finally:
2321.2.5 by Alexander Belchenko
external diff: no need for special code path for win32 (suggested by John Meinel)
179
            for lang, old_val in old_env.iteritems():
180
                osutils.set_or_unset_env(lang, old_val)
1899.1.4 by John Arbash Meinel
Just swallow a return code of 2
181
1899.1.1 by John Arbash Meinel
Fix the bug in the NoDiff exception class, and add a test
182
    def test_no_external_diff(self):
183
        """Check that NoDiff is raised when diff is not available"""
184
        # Use os.environ['PATH'] to make sure no 'diff' command is available
185
        orig_path = os.environ['PATH']
186
        try:
187
            os.environ['PATH'] = ''
188
            self.assertRaises(NoDiff, external_diff,
189
                              'old', ['boo\n'], 'new', ['goo\n'],
190
                              StringIO(), diff_opts=['-u'])
191
        finally:
192
            os.environ['PATH'] = orig_path
1692.8.2 by James Henstridge
add a test for sending external diff output to a file
193
        
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
194
    def test_internal_diff_default(self):
195
        # Default internal diff encoding is utf8
196
        output = StringIO()
197
        internal_diff(u'old_\xb5', ['old_text\n'],
198
                    u'new_\xe5', ['new_text\n'], output)
199
        lines = output.getvalue().splitlines(True)
200
        self.check_patch(lines)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
201
        self.assertEquals(['--- old_\xc2\xb5\n',
202
                           '+++ new_\xc3\xa5\n',
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
203
                           '@@ -1,1 +1,1 @@\n',
204
                           '-old_text\n',
205
                           '+new_text\n',
206
                           '\n',
207
                          ]
208
                          , lines)
209
210
    def test_internal_diff_utf8(self):
211
        output = StringIO()
212
        internal_diff(u'old_\xb5', ['old_text\n'],
213
                    u'new_\xe5', ['new_text\n'], output,
214
                    path_encoding='utf8')
215
        lines = output.getvalue().splitlines(True)
216
        self.check_patch(lines)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
217
        self.assertEquals(['--- old_\xc2\xb5\n',
218
                           '+++ new_\xc3\xa5\n',
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
219
                           '@@ -1,1 +1,1 @@\n',
220
                           '-old_text\n',
221
                           '+new_text\n',
222
                           '\n',
223
                          ]
224
                          , lines)
225
226
    def test_internal_diff_iso_8859_1(self):
227
        output = StringIO()
228
        internal_diff(u'old_\xb5', ['old_text\n'],
229
                    u'new_\xe5', ['new_text\n'], output,
230
                    path_encoding='iso-8859-1')
231
        lines = output.getvalue().splitlines(True)
232
        self.check_patch(lines)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
233
        self.assertEquals(['--- old_\xb5\n',
234
                           '+++ new_\xe5\n',
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
235
                           '@@ -1,1 +1,1 @@\n',
236
                           '-old_text\n',
237
                           '+new_text\n',
238
                           '\n',
239
                          ]
240
                          , lines)
241
242
    def test_internal_diff_returns_bytes(self):
243
        import StringIO
244
        output = StringIO.StringIO()
245
        internal_diff(u'old_\xb5', ['old_text\n'],
246
                    u'new_\xe5', ['new_text\n'], output)
247
        self.failUnless(isinstance(output.getvalue(), str),
248
            'internal_diff should return bytestrings')
249
1185.81.25 by Aaron Bentley
Clean up test_diff
250
1920.1.1 by John Arbash Meinel
fix bug #56307, handle binary files even when LANG is not english
251
class TestDiffFiles(TestCaseInTempDir):
252
253
    def test_external_diff_binary(self):
254
        """The output when using external diff should use diff's i18n error"""
255
        # Make sure external_diff doesn't fail in the current LANG
256
        lines = external_udiff_lines(['\x00foobar\n'], ['foo\x00bar\n'])
257
2240.1.1 by Alexander Belchenko
test_external_diff_binary: run external diff with --binary flag
258
        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
259
        open('old', 'wb').write('\x00foobar\n')
260
        open('new', 'wb').write('foo\x00bar\n')
261
        pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE,
262
                                     stdin=subprocess.PIPE)
263
        out, err = pipe.communicate()
264
        # Diff returns '2' on Binary files.
265
        self.assertEqual(2, pipe.returncode)
266
        # We should output whatever diff tells us, plus a trailing newline
267
        self.assertEqual(out.splitlines(True) + ['\n'], lines)
268
269
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
270
class TestShowDiffTreesHelper(TestCaseWithTransport):
271
    """Has a helper for running show_diff_trees"""
272
273
    def get_diff(self, tree1, tree2, specific_files=None, working_tree=None):
274
        output = StringIO()
275
        if working_tree is not None:
276
            extra_trees = (working_tree,)
277
        else:
278
            extra_trees = ()
279
        show_diff_trees(tree1, tree2, output, specific_files=specific_files,
280
                        extra_trees=extra_trees, old_label='old/',
281
                        new_label='new/')
282
        return output.getvalue()
283
284
285
class TestDiffDates(TestShowDiffTreesHelper):
1740.2.5 by Aaron Bentley
Merge from bzr.dev
286
287
    def setUp(self):
288
        super(TestDiffDates, self).setUp()
289
        self.wt = self.make_branch_and_tree('.')
290
        self.b = self.wt.branch
291
        self.build_tree_contents([
292
            ('file1', 'file1 contents at rev 1\n'),
293
            ('file2', 'file2 contents at rev 1\n')
294
            ])
295
        self.wt.add(['file1', 'file2'])
296
        self.wt.commit(
297
            message='Revision 1',
298
            timestamp=1143849600, # 2006-04-01 00:00:00 UTC
299
            timezone=0,
300
            rev_id='rev-1')
301
        self.build_tree_contents([('file1', 'file1 contents at rev 2\n')])
302
        self.wt.commit(
303
            message='Revision 2',
304
            timestamp=1143936000, # 2006-04-02 00:00:00 UTC
305
            timezone=28800,
306
            rev_id='rev-2')
307
        self.build_tree_contents([('file2', 'file2 contents at rev 3\n')])
308
        self.wt.commit(
309
            message='Revision 3',
310
            timestamp=1144022400, # 2006-04-03 00:00:00 UTC
311
            timezone=-3600,
312
            rev_id='rev-3')
313
        self.wt.remove(['file2'])
314
        self.wt.commit(
315
            message='Revision 4',
316
            timestamp=1144108800, # 2006-04-04 00:00:00 UTC
317
            timezone=0,
318
            rev_id='rev-4')
319
        self.build_tree_contents([
320
            ('file1', 'file1 contents in working tree\n')
321
            ])
322
        # set the date stamps for files in the working tree to known values
323
        os.utime('file1', (1144195200, 1144195200)) # 2006-04-05 00:00:00 UTC
324
325
    def test_diff_rev_tree_working_tree(self):
326
        output = self.get_diff(self.wt.basis_tree(), self.wt)
327
        # note that the date for old/file1 is from rev 2 rather than from
328
        # the basis revision (rev 4)
329
        self.assertEqualDiff(output, '''\
330
=== modified file 'file1'
331
--- old/file1\t2006-04-02 00:00:00 +0000
332
+++ new/file1\t2006-04-05 00:00:00 +0000
333
@@ -1,1 +1,1 @@
334
-file1 contents at rev 2
335
+file1 contents in working tree
336
337
''')
338
339
    def test_diff_rev_tree_rev_tree(self):
340
        tree1 = self.b.repository.revision_tree('rev-2')
341
        tree2 = self.b.repository.revision_tree('rev-3')
342
        output = self.get_diff(tree1, tree2)
343
        self.assertEqualDiff(output, '''\
344
=== modified file 'file2'
345
--- old/file2\t2006-04-01 00:00:00 +0000
346
+++ new/file2\t2006-04-03 00:00:00 +0000
347
@@ -1,1 +1,1 @@
348
-file2 contents at rev 1
349
+file2 contents at rev 3
350
351
''')
352
        
353
    def test_diff_add_files(self):
354
        tree1 = self.b.repository.revision_tree(None)
355
        tree2 = self.b.repository.revision_tree('rev-1')
356
        output = self.get_diff(tree1, tree2)
357
        # the files have the epoch time stamp for the tree in which
358
        # they don't exist.
359
        self.assertEqualDiff(output, '''\
360
=== added file 'file1'
361
--- old/file1\t1970-01-01 00:00:00 +0000
362
+++ new/file1\t2006-04-01 00:00:00 +0000
363
@@ -0,0 +1,1 @@
364
+file1 contents at rev 1
365
366
=== added file 'file2'
367
--- old/file2\t1970-01-01 00:00:00 +0000
368
+++ new/file2\t2006-04-01 00:00:00 +0000
369
@@ -0,0 +1,1 @@
370
+file2 contents at rev 1
371
372
''')
373
374
    def test_diff_remove_files(self):
375
        tree1 = self.b.repository.revision_tree('rev-3')
376
        tree2 = self.b.repository.revision_tree('rev-4')
377
        output = self.get_diff(tree1, tree2)
378
        # the file has the epoch time stamp for the tree in which
379
        # it doesn't exist.
380
        self.assertEqualDiff(output, '''\
381
=== removed file 'file2'
382
--- old/file2\t2006-04-03 00:00:00 +0000
383
+++ new/file2\t1970-01-01 00:00:00 +0000
384
@@ -1,1 +0,0 @@
385
-file2 contents at rev 3
386
387
''')
388
1551.7.17 by Aaron Bentley
Switch to PathsNotVersioned, accept extra_trees
389
    def test_show_diff_specified(self):
1551.7.22 by Aaron Bentley
Changes from review
390
        """A working tree filename can be used to identify a file"""
1551.7.17 by Aaron Bentley
Switch to PathsNotVersioned, accept extra_trees
391
        self.wt.rename_one('file1', 'file1b')
392
        old_tree = self.b.repository.revision_tree('rev-1')
393
        new_tree = self.b.repository.revision_tree('rev-4')
1551.7.22 by Aaron Bentley
Changes from review
394
        out = self.get_diff(old_tree, new_tree, specific_files=['file1b'], 
395
                            working_tree=self.wt)
396
        self.assertContainsRe(out, 'file1\t')
1551.7.17 by Aaron Bentley
Switch to PathsNotVersioned, accept extra_trees
397
1551.7.22 by Aaron Bentley
Changes from review
398
    def test_recursive_diff(self):
399
        """Children of directories are matched"""
400
        os.mkdir('dir1')
401
        os.mkdir('dir2')
402
        self.wt.add(['dir1', 'dir2'])
403
        self.wt.rename_one('file1', 'dir1/file1')
404
        old_tree = self.b.repository.revision_tree('rev-1')
405
        new_tree = self.b.repository.revision_tree('rev-4')
406
        out = self.get_diff(old_tree, new_tree, specific_files=['dir1'], 
407
                            working_tree=self.wt)
408
        self.assertContainsRe(out, 'file1\t')
409
        out = self.get_diff(old_tree, new_tree, specific_files=['dir2'], 
410
                            working_tree=self.wt)
411
        self.assertNotContainsRe(out, 'file1\t')
1740.2.5 by Aaron Bentley
Merge from bzr.dev
412
1899.1.1 by John Arbash Meinel
Fix the bug in the NoDiff exception class, and add a test
413
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
414
415
class TestShowDiffTrees(TestShowDiffTreesHelper):
416
    """Direct tests for show_diff_trees"""
417
418
    def test_modified_file(self):
419
        """Test when a file is modified."""
420
        tree = self.make_branch_and_tree('tree')
421
        self.build_tree_contents([('tree/file', 'contents\n')])
422
        tree.add(['file'], ['file-id'])
423
        tree.commit('one', rev_id='rev-1')
424
425
        self.build_tree_contents([('tree/file', 'new contents\n')])
426
        diff = self.get_diff(tree.basis_tree(), tree)
427
        self.assertContainsRe(diff, "=== modified file 'file'\n")
428
        self.assertContainsRe(diff, '--- old/file\t')
429
        self.assertContainsRe(diff, '\\+\\+\\+ new/file\t')
430
        self.assertContainsRe(diff, '-contents\n'
431
                                    '\\+new contents\n')
432
2405.1.2 by John Arbash Meinel
Fix bug #103870 by passing None instead of a (sometimes wrong) path
433
    def test_modified_file_in_renamed_dir(self):
434
        """Test when a file is modified in a renamed directory."""
435
        tree = self.make_branch_and_tree('tree')
436
        self.build_tree(['tree/dir/'])
437
        self.build_tree_contents([('tree/dir/file', 'contents\n')])
438
        tree.add(['dir', 'dir/file'], ['dir-id', 'file-id'])
439
        tree.commit('one', rev_id='rev-1')
440
441
        tree.rename_one('dir', 'other')
442
        self.build_tree_contents([('tree/other/file', 'new contents\n')])
443
        diff = self.get_diff(tree.basis_tree(), tree)
444
        self.assertContainsRe(diff, "=== renamed directory 'dir' => 'other'\n")
445
        self.assertContainsRe(diff, "=== modified file 'other/file'\n")
446
        # XXX: This is technically incorrect, because it used to be at another
447
        # 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.
448
        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
449
        self.assertContainsRe(diff, '\\+\\+\\+ new/other/file\t')
450
        self.assertContainsRe(diff, '-contents\n'
451
                                    '\\+new contents\n')
452
2405.1.1 by John Arbash Meinel
Add a bunch of direct tests for 'show_diff_trees'
453
    def test_renamed_directory(self):
454
        """Test when only a directory is only renamed."""
455
        tree = self.make_branch_and_tree('tree')
456
        self.build_tree(['tree/dir/'])
457
        self.build_tree_contents([('tree/dir/file', 'contents\n')])
458
        tree.add(['dir', 'dir/file'], ['dir-id', 'file-id'])
459
        tree.commit('one', rev_id='rev-1')
460
461
        tree.rename_one('dir', 'newdir')
462
        diff = self.get_diff(tree.basis_tree(), tree)
463
        # Renaming a directory should be a single "you renamed this dir" even
464
        # when there are files inside.
465
        self.assertEqual("=== renamed directory 'dir' => 'newdir'\n", diff)
466
467
    def test_renamed_file(self):
468
        """Test when a file is only renamed."""
469
        tree = self.make_branch_and_tree('tree')
470
        self.build_tree_contents([('tree/file', 'contents\n')])
471
        tree.add(['file'], ['file-id'])
472
        tree.commit('one', rev_id='rev-1')
473
474
        tree.rename_one('file', 'newname')
475
        diff = self.get_diff(tree.basis_tree(), tree)
476
        self.assertContainsRe(diff, "=== renamed file 'file' => 'newname'\n")
477
        # We shouldn't have a --- or +++ line, because there is no content
478
        # change
479
        self.assertNotContainsRe(diff, '---')
480
481
    def test_renamed_and_modified_file(self):
482
        """Test when a file is only renamed."""
483
        tree = self.make_branch_and_tree('tree')
484
        self.build_tree_contents([('tree/file', 'contents\n')])
485
        tree.add(['file'], ['file-id'])
486
        tree.commit('one', rev_id='rev-1')
487
488
        tree.rename_one('file', 'newname')
489
        self.build_tree_contents([('tree/newname', 'new contents\n')])
490
        diff = self.get_diff(tree.basis_tree(), tree)
491
        self.assertContainsRe(diff, "=== renamed file 'file' => 'newname'\n")
492
        self.assertContainsRe(diff, '--- old/file\t')
493
        self.assertContainsRe(diff, '\\+\\+\\+ new/newname\t')
494
        self.assertContainsRe(diff, '-contents\n'
495
                                    '\\+new contents\n')
496
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
497
    def test_binary_unicode_filenames(self):
2592.2.2 by Jonathan Lange
Apply jam's comments to test_binary_unicode_filenames. Change the
498
        """Test that contents of files are *not* encoded in UTF-8 when there
499
        is a binary file in the diff.
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
500
        """
501
        # 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
502
        self.requireFeature(UnicodeFilename)
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
503
504
        # This bug isn't triggered with cStringIO.
505
        from StringIO import StringIO
506
        tree = self.make_branch_and_tree('tree')
2592.2.2 by Jonathan Lange
Apply jam's comments to test_binary_unicode_filenames. Change the
507
        alpha, omega = u'\u03b1', u'\u03c9'
508
        alpha_utf8, omega_utf8 = alpha.encode('utf8'), omega.encode('utf8')
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
509
        self.build_tree_contents(
2592.2.2 by Jonathan Lange
Apply jam's comments to test_binary_unicode_filenames. Change the
510
            [('tree/' + alpha, chr(0)),
511
             ('tree/' + omega,
512
              ('The %s and the %s\n' % (alpha_utf8, omega_utf8)))])
513
        tree.add([alpha], ['file-id'])
514
        tree.add([omega], ['file-id-2'])
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
515
        diff_content = StringIO()
516
        show_diff_trees(tree.basis_tree(), tree, diff_content)
517
        diff = diff_content.getvalue()
2592.2.2 by Jonathan Lange
Apply jam's comments to test_binary_unicode_filenames. Change the
518
        self.assertContainsRe(diff, r"=== added file '%s'" % alpha_utf8)
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
519
        self.assertContainsRe(
2592.2.2 by Jonathan Lange
Apply jam's comments to test_binary_unicode_filenames. Change the
520
            diff, "Binary files a/%s.*and b/%s.* differ\n" % (alpha_utf8, alpha_utf8))
521
        self.assertContainsRe(diff, r"=== added file '%s'" % omega_utf8)
522
        self.assertContainsRe(diff, r"--- a/%s" % (omega_utf8,))
523
        self.assertContainsRe(diff, r"\+\+\+ b/%s" % (omega_utf8,))
2592.2.1 by Jonathan Lange
Reproduce and fix bug 110092.
524
2725.2.1 by ghigo
When a unicode filename is renamed, in the diff is showed a wrong result
525
    def test_unicode_filename(self):
526
        """Test when the filename are unicode."""
527
        self.requireFeature(UnicodeFilename)
528
529
        alpha, omega = u'\u03b1', u'\u03c9'
530
        autf8, outf8 = alpha.encode('utf8'), omega.encode('utf8')
531
532
        tree = self.make_branch_and_tree('tree')
533
        self.build_tree_contents([('tree/ren_'+alpha, 'contents\n')])
534
        tree.add(['ren_'+alpha], ['file-id-2'])
535
        self.build_tree_contents([('tree/del_'+alpha, 'contents\n')])
536
        tree.add(['del_'+alpha], ['file-id-3'])
537
        self.build_tree_contents([('tree/mod_'+alpha, 'contents\n')])
538
        tree.add(['mod_'+alpha], ['file-id-4'])
539
540
        tree.commit('one', rev_id='rev-1')
541
542
        tree.rename_one('ren_'+alpha, 'ren_'+omega)
543
        tree.remove('del_'+alpha)
544
        self.build_tree_contents([('tree/add_'+alpha, 'contents\n')])
545
        tree.add(['add_'+alpha], ['file-id'])
546
        self.build_tree_contents([('tree/mod_'+alpha, 'contents_mod\n')])
547
548
        diff = self.get_diff(tree.basis_tree(), tree)
549
        self.assertContainsRe(diff,
550
                "=== renamed file 'ren_%s' => 'ren_%s'\n"%(autf8, outf8))
551
        self.assertContainsRe(diff, "=== added file 'add_%s'"%autf8)
552
        self.assertContainsRe(diff, "=== modified file 'mod_%s'"%autf8)
553
        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'
554
3009.2.9 by Aaron Bentley
Add tests for Differ
555
3009.2.22 by Aaron Bentley
Update names & docstring
556
class DiffWasIs(DiffPath):
3009.2.15 by Aaron Bentley
Test differ registration
557
558
    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
559
        self.to_file.write('was: ')
560
        self.to_file.write(self.old_tree.get_file(file_id).read())
561
        self.to_file.write('is: ')
562
        self.to_file.write(self.new_tree.get_file(file_id).read())
563
        pass
564
565
3009.2.22 by Aaron Bentley
Update names & docstring
566
class TestDiffTree(TestCaseWithTransport):
3009.2.9 by Aaron Bentley
Add tests for Differ
567
568
    def setUp(self):
569
        TestCaseWithTransport.setUp(self)
570
        self.old_tree = self.make_branch_and_tree('old-tree')
571
        self.old_tree.lock_write()
572
        self.addCleanup(self.old_tree.unlock)
573
        self.new_tree = self.make_branch_and_tree('new-tree')
574
        self.new_tree.lock_write()
575
        self.addCleanup(self.new_tree.unlock)
3009.2.22 by Aaron Bentley
Update names & docstring
576
        self.differ = DiffTree(self.old_tree, self.new_tree, StringIO())
3009.2.9 by Aaron Bentley
Add tests for Differ
577
578
    def test_diff_text(self):
579
        self.build_tree_contents([('old-tree/olddir/',),
580
                                  ('old-tree/olddir/oldfile', 'old\n')])
581
        self.old_tree.add('olddir')
582
        self.old_tree.add('olddir/oldfile', 'file-id')
583
        self.build_tree_contents([('new-tree/newdir/',),
584
                                  ('new-tree/newdir/newfile', 'new\n')])
585
        self.new_tree.add('newdir')
586
        self.new_tree.add('newdir/newfile', 'file-id')
3009.2.22 by Aaron Bentley
Update names & docstring
587
        differ = DiffText(self.old_tree, self.new_tree, StringIO())
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
588
        differ.diff_text('file-id', None, 'old label', 'new label')
3009.2.9 by Aaron Bentley
Add tests for Differ
589
        self.assertEqual(
590
            '--- 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
591
            differ.to_file.getvalue())
592
        differ.to_file.seek(0)
593
        differ.diff_text(None, 'file-id', 'old label', 'new label')
3009.2.9 by Aaron Bentley
Add tests for Differ
594
        self.assertEqual(
595
            '--- 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
596
            differ.to_file.getvalue())
597
        differ.to_file.seek(0)
598
        differ.diff_text('file-id', 'file-id', 'old label', 'new label')
3009.2.9 by Aaron Bentley
Add tests for Differ
599
        self.assertEqual(
600
            '--- 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
601
            differ.to_file.getvalue())
3009.2.9 by Aaron Bentley
Add tests for Differ
602
603
    def test_diff_symlink(self):
3009.2.22 by Aaron Bentley
Update names & docstring
604
        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
605
        differ.diff_symlink('old target', None)
3009.2.9 by Aaron Bentley
Add tests for Differ
606
        self.assertEqual("=== target was 'old target'\n",
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
607
                         differ.to_file.getvalue())
3009.2.9 by Aaron Bentley
Add tests for Differ
608
3009.2.22 by Aaron Bentley
Update names & docstring
609
        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
610
        differ.diff_symlink(None, 'new target')
3009.2.9 by Aaron Bentley
Add tests for Differ
611
        self.assertEqual("=== target is 'new target'\n",
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
612
                         differ.to_file.getvalue())
613
3009.2.22 by Aaron Bentley
Update names & docstring
614
        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
615
        differ.diff_symlink('old target', 'new target')
3009.2.9 by Aaron Bentley
Add tests for Differ
616
        self.assertEqual("=== target changed 'old target' => 'new target'\n",
3009.2.11 by Aaron Bentley
Refactor diff to be more pluggable
617
                         differ.to_file.getvalue())
3009.2.9 by Aaron Bentley
Add tests for Differ
618
619
    def test_diff(self):
620
        self.build_tree_contents([('old-tree/olddir/',),
621
                                  ('old-tree/olddir/oldfile', 'old\n')])
622
        self.old_tree.add('olddir')
623
        self.old_tree.add('olddir/oldfile', 'file-id')
624
        self.build_tree_contents([('new-tree/newdir/',),
625
                                  ('new-tree/newdir/newfile', 'new\n')])
626
        self.new_tree.add('newdir')
627
        self.new_tree.add('newdir/newfile', 'file-id')
3009.2.12 by Aaron Bentley
Associate labels with text diffing only
628
        self.differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
3009.2.9 by Aaron Bentley
Add tests for Differ
629
        self.assertContainsRe(
630
            self.differ.to_file.getvalue(),
631
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
632
             ' \@\@\n-old\n\+new\n\n')
633
634
    def test_diff_kind_change(self):
635
        self.build_tree_contents([('old-tree/olddir/',),
636
                                  ('old-tree/olddir/oldfile', 'old\n')])
637
        self.old_tree.add('olddir')
638
        self.old_tree.add('olddir/oldfile', 'file-id')
639
        self.build_tree(['new-tree/newdir/'])
640
        os.symlink('new', 'new-tree/newdir/newfile')
641
        self.new_tree.add('newdir')
642
        self.new_tree.add('newdir/newfile', 'file-id')
3009.2.12 by Aaron Bentley
Associate labels with text diffing only
643
        self.differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
3009.2.9 by Aaron Bentley
Add tests for Differ
644
        self.assertContainsRe(
645
            self.differ.to_file.getvalue(),
646
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+0,0'
647
             ' \@\@\n-old\n\n')
648
        self.assertContainsRe(self.differ.to_file.getvalue(),
649
                              "=== target is 'new'\n")
650
3009.2.19 by Aaron Bentley
Implement directory diffing
651
    def test_diff_directory(self):
652
        self.build_tree(['new-tree/new-dir/'])
653
        self.new_tree.add('new-dir', 'new-dir-id')
654
        self.differ.diff('new-dir-id', None, 'new-dir')
655
        self.assertEqual(self.differ.to_file.getvalue(), '')
656
3009.2.16 by Aaron Bentley
Test support for extra differs
657
    def create_old_new(self):
658
        self.build_tree_contents([('old-tree/olddir/',),
659
                                  ('old-tree/olddir/oldfile', 'old\n')])
660
        self.old_tree.add('olddir')
661
        self.old_tree.add('olddir/oldfile', 'file-id')
662
        self.build_tree_contents([('new-tree/newdir/',),
663
                                  ('new-tree/newdir/newfile', 'new\n')])
664
        self.new_tree.add('newdir')
665
        self.new_tree.add('newdir/newfile', 'file-id')
666
3009.2.27 by Aaron Bentley
Use extra_factories instead of extra_diffs
667
    def test_register_diff(self):
3009.2.16 by Aaron Bentley
Test support for extra differs
668
        self.create_old_new()
3009.2.27 by Aaron Bentley
Use extra_factories instead of extra_diffs
669
        old_diff_factories = DiffTree.diff_factories
670
        DiffTree.diff_factories=old_diff_factories[:]
3009.2.28 by Aaron Bentley
Add from_diff_tree factories
671
        DiffTree.diff_factories.insert(0, DiffWasIs.from_diff_tree)
3009.2.16 by Aaron Bentley
Test support for extra differs
672
        try:
3009.2.22 by Aaron Bentley
Update names & docstring
673
            differ = DiffTree(self.old_tree, self.new_tree, StringIO())
3009.2.16 by Aaron Bentley
Test support for extra differs
674
        finally:
3009.2.27 by Aaron Bentley
Use extra_factories instead of extra_diffs
675
            DiffTree.diff_factories = old_diff_factories
3009.2.16 by Aaron Bentley
Test support for extra differs
676
        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
677
        self.assertNotContainsRe(
678
            differ.to_file.getvalue(),
679
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
680
             ' \@\@\n-old\n\+new\n\n')
681
        self.assertContainsRe(differ.to_file.getvalue(),
682
                              'was: old\nis: new\n')
683
3009.2.27 by Aaron Bentley
Use extra_factories instead of extra_diffs
684
    def test_extra_factories(self):
3009.2.16 by Aaron Bentley
Test support for extra differs
685
        self.create_old_new()
3009.2.27 by Aaron Bentley
Use extra_factories instead of extra_diffs
686
        differ = DiffTree(self.old_tree, self.new_tree, StringIO(),
3009.2.28 by Aaron Bentley
Add from_diff_tree factories
687
                            extra_factories=[DiffWasIs.from_diff_tree])
3009.2.16 by Aaron Bentley
Test support for extra differs
688
        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
689
        self.assertNotContainsRe(
690
            differ.to_file.getvalue(),
691
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
692
             ' \@\@\n-old\n\+new\n\n')
693
        self.assertContainsRe(differ.to_file.getvalue(),
694
                              'was: old\nis: new\n')
695
3009.2.9 by Aaron Bentley
Add tests for Differ
696
1711.2.15 by John Arbash Meinel
Found a couple CDV left
697
class TestPatienceDiffLib(TestCase):
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
698
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
699
    def setUp(self):
700
        super(TestPatienceDiffLib, self).setUp()
701
        self._unique_lcs = bzrlib._patiencediff_py.unique_lcs_py
702
        self._recurse_matches = bzrlib._patiencediff_py.recurse_matches_py
703
        self._PatienceSequenceMatcher = \
704
            bzrlib._patiencediff_py.PatienceSequenceMatcher_py
705
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
706
    def test_unique_lcs(self):
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
707
        unique_lcs = self._unique_lcs
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
708
        self.assertEquals(unique_lcs('', ''), [])
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
709
        self.assertEquals(unique_lcs('', 'a'), [])
710
        self.assertEquals(unique_lcs('a', ''), [])
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
711
        self.assertEquals(unique_lcs('a', 'a'), [(0,0)])
712
        self.assertEquals(unique_lcs('a', 'b'), [])
713
        self.assertEquals(unique_lcs('ab', 'ab'), [(0,0), (1,1)])
714
        self.assertEquals(unique_lcs('abcde', 'cdeab'), [(2,0), (3,1), (4,2)])
715
        self.assertEquals(unique_lcs('cdeab', 'abcde'), [(0,2), (1,3), (2,4)])
716
        self.assertEquals(unique_lcs('abXde', 'abYde'), [(0,0), (1,1), 
717
                                                         (3,3), (4,4)])
718
        self.assertEquals(unique_lcs('acbac', 'abc'), [(2,1)])
719
720
    def test_recurse_matches(self):
721
        def test_one(a, b, matches):
722
            test_matches = []
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
723
            self._recurse_matches(
724
                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,
725
            self.assertEquals(test_matches, matches)
726
1711.2.17 by John Arbash Meinel
Small cleanups to patience_diff code.
727
        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,
728
                 [(0, 0), (2, 2), (4, 4)])
729
        test_one(['a', 'c', 'b', 'a', 'c'], ['a', 'b', 'c'],
730
                 [(0, 0), (2, 1), (4, 2)])
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
731
        # Even though 'bc' is not unique globally, and is surrounded by
732
        # non-matching lines, we should still match, because they are locally
733
        # unique
734
        test_one('abcdbce', 'afbcgdbce', [(0,0), (1, 2), (2, 3), (3, 5),
735
                                          (4, 6), (5, 7), (6, 8)])
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
736
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
737
        # recurse_matches doesn't match non-unique 
738
        # lines surrounded by bogus text.
1185.81.24 by Aaron Bentley
Reoganize patience-related code
739
        # 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
740
741
        # This is what it could be
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
742
        #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
743
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
744
        # This is what it currently gives:
745
        test_one('aBccDe', 'abccde', [(0,0), (5,5)])
746
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
747
    def test_matching_blocks(self):
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
748
        def chk_blocks(a, b, expected_blocks):
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
749
            # difflib always adds a signature of the total
750
            # length, with no matching entries at the end
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
751
            s = self._PatienceSequenceMatcher(None, a, b)
1185.81.11 by John Arbash Meinel
Found some edge cases that weren't being matched.
752
            blocks = s.get_matching_blocks()
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
753
            self.assertEquals((len(a), len(b), 0), blocks[-1])
754
            self.assertEquals(expected_blocks, blocks[:-1])
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
755
1185.81.2 by John Arbash Meinel
A couple small tests.
756
        # Some basic matching tests
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
757
        chk_blocks('', '', [])
758
        chk_blocks([], [], [])
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
759
        chk_blocks('abc', '', [])
760
        chk_blocks('', 'abc', [])
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
761
        chk_blocks('abcd', 'abcd', [(0, 0, 4)])
762
        chk_blocks('abcd', 'abce', [(0, 0, 3)])
763
        chk_blocks('eabc', 'abce', [(1, 0, 3)])
764
        chk_blocks('eabce', 'abce', [(1, 0, 4)])
765
        chk_blocks('abcde', 'abXde', [(0, 0, 2), (3, 3, 2)])
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
766
        chk_blocks('abcde', 'abXYZde', [(0, 0, 2), (3, 5, 2)])
767
        chk_blocks('abde', 'abXYZde', [(0, 0, 2), (2, 5, 2)])
768
        # This may check too much, but it checks to see that 
769
        # a copied block stays attached to the previous section,
770
        # not the later one.
771
        # difflib would tend to grab the trailing longest match
772
        # 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,
773
        chk_blocks('abcdefghijklmnop', 'abcdefxydefghijklmnop',
774
                   [(0, 0, 6), (6, 11, 10)])
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
775
1185.81.2 by John Arbash Meinel
A couple small tests.
776
        # make sure it supports passing in lists
777
        chk_blocks(
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
778
                   ['hello there\n',
779
                    'world\n',
780
                    'how are you today?\n'],
781
                   ['hello there\n',
782
                    'how are you today?\n'],
1185.81.2 by John Arbash Meinel
A couple small tests.
783
                [(0, 0, 1), (2, 1, 1)])
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
784
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
785
        # non unique lines surrounded by non-matching lines
786
        # won't be found
787
        chk_blocks('aBccDe', 'abccde', [(0,0,1), (5,5,1)])
788
789
        # But they only need to be locally unique
790
        chk_blocks('aBcDec', 'abcdec', [(0,0,1), (2,2,1), (4,4,2)])
791
792
        # non unique blocks won't be matched
793
        chk_blocks('aBcdEcdFg', 'abcdecdfg', [(0,0,1), (8,8,1)])
794
795
        # but locally unique ones will
796
        chk_blocks('aBcdEeXcdFg', 'abcdecdfg', [(0,0,1), (2,2,2),
797
                                              (5,4,1), (7,5,2), (10,8,1)])
798
799
        chk_blocks('abbabbXd', 'cabbabxd', [(7,7,1)])
800
        chk_blocks('abbabbbb', 'cabbabbc', [])
801
        chk_blocks('bbbbbbbb', 'cbbbbbbc', [])
1185.81.11 by John Arbash Meinel
Found some edge cases that weren't being matched.
802
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
803
    def test_opcodes(self):
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
804
        def chk_ops(a, b, expected_codes):
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
805
            s = self._PatienceSequenceMatcher(None, a, b)
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
806
            self.assertEquals(expected_codes, s.get_opcodes())
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
807
808
        chk_ops('', '', [])
809
        chk_ops([], [], [])
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
810
        chk_ops('abc', '', [('delete', 0,3, 0,0)])
811
        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,
812
        chk_ops('abcd', 'abcd', [('equal',    0,4, 0,4)])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
813
        chk_ops('abcd', 'abce', [('equal',   0,3, 0,3),
814
                                 ('replace', 3,4, 3,4)
815
                                ])
816
        chk_ops('eabc', 'abce', [('delete', 0,1, 0,0),
817
                                 ('equal',  1,4, 0,3),
818
                                 ('insert', 4,4, 3,4)
819
                                ])
820
        chk_ops('eabce', 'abce', [('delete', 0,1, 0,0),
821
                                  ('equal',  1,5, 0,4)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
822
                                 ])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
823
        chk_ops('abcde', 'abXde', [('equal',   0,2, 0,2),
824
                                   ('replace', 2,3, 2,3),
825
                                   ('equal',   3,5, 3,5)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
826
                                  ])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
827
        chk_ops('abcde', 'abXYZde', [('equal',   0,2, 0,2),
828
                                     ('replace', 2,3, 2,5),
829
                                     ('equal',   3,5, 5,7)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
830
                                    ])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
831
        chk_ops('abde', 'abXYZde', [('equal',  0,2, 0,2),
832
                                    ('insert', 2,2, 2,5),
833
                                    ('equal',  2,4, 5,7)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
834
                                   ])
835
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
836
                [('equal',  0,6,  0,6),
837
                 ('insert', 6,6,  6,11),
838
                 ('equal',  6,16, 11,21)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
839
                ])
840
        chk_ops(
841
                [ 'hello there\n'
842
                , 'world\n'
843
                , 'how are you today?\n'],
844
                [ 'hello there\n'
845
                , 'how are you today?\n'],
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
846
                [('equal',  0,1, 0,1),
847
                 ('delete', 1,2, 1,1),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
848
                 ('equal',  2,3, 1,2),
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
849
                ])
850
        chk_ops('aBccDe', 'abccde', 
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
851
                [('equal',   0,1, 0,1),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
852
                 ('replace', 1,5, 1,5),
853
                 ('equal',   5,6, 5,6),
854
                ])
855
        chk_ops('aBcDec', 'abcdec', 
856
                [('equal',   0,1, 0,1),
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
857
                 ('replace', 1,2, 1,2),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
858
                 ('equal',   2,3, 2,3),
859
                 ('replace', 3,4, 3,4),
860
                 ('equal',   4,6, 4,6),
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
861
                ])
1185.81.10 by John Arbash Meinel
Added some more test cases.
862
        chk_ops('aBcdEcdFg', 'abcdecdfg', 
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
863
                [('equal',   0,1, 0,1),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
864
                 ('replace', 1,8, 1,8),
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
865
                 ('equal',   8,9, 8,9)
1185.81.10 by John Arbash Meinel
Added some more test cases.
866
                ])
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
867
        chk_ops('aBcdEeXcdFg', 'abcdecdfg', 
868
                [('equal',   0,1, 0,1),
869
                 ('replace', 1,2, 1,2),
870
                 ('equal',   2,4, 2,4),
871
                 ('delete', 4,5, 4,4),
872
                 ('equal',   5,6, 4,5),
873
                 ('delete', 6,7, 5,5),
874
                 ('equal',   7,9, 5,7),
875
                 ('replace', 9,10, 7,8),
876
                 ('equal',   10,11, 8,9)
877
                ])
1185.81.10 by John Arbash Meinel
Added some more test cases.
878
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
879
    def test_grouped_opcodes(self):
880
        def chk_ops(a, b, expected_codes, n=3):
881
            s = self._PatienceSequenceMatcher(None, a, b)
882
            self.assertEquals(expected_codes, list(s.get_grouped_opcodes(n)))
883
884
        chk_ops('', '', [])
885
        chk_ops([], [], [])
886
        chk_ops('abc', '', [[('delete', 0,3, 0,0)]])
887
        chk_ops('', 'abc', [[('insert', 0,0, 0,3)]])
888
        chk_ops('abcd', 'abcd', [])
889
        chk_ops('abcd', 'abce', [[('equal',   0,3, 0,3),
890
                                  ('replace', 3,4, 3,4)
891
                                 ]])
892
        chk_ops('eabc', 'abce', [[('delete', 0,1, 0,0),
893
                                 ('equal',  1,4, 0,3),
894
                                 ('insert', 4,4, 3,4)
895
                                ]])
896
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
897
                [[('equal',  3,6, 3,6),
898
                  ('insert', 6,6, 6,11),
899
                  ('equal',  6,9, 11,14)
900
                  ]])
901
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
902
                [[('equal',  2,6, 2,6),
903
                  ('insert', 6,6, 6,11),
904
                  ('equal',  6,10, 11,15)
905
                  ]], 4)
906
        chk_ops('Xabcdef', 'abcdef',
907
                [[('delete', 0,1, 0,0),
908
                  ('equal',  1,4, 0,3)
909
                  ]])
910
        chk_ops('abcdef', 'abcdefX',
911
                [[('equal',  3,6, 3,6),
912
                  ('insert', 6,6, 6,7)
913
                  ]])
914
915
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
916
    def test_multiple_ranges(self):
917
        # There was an earlier bug where we used a bad set of ranges,
918
        # 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.
919
        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.
920
            # difflib always adds a signature of the total
921
            # length, with no matching entries at the end
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
922
            s = self._PatienceSequenceMatcher(None, a, b)
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
923
            blocks = s.get_matching_blocks()
924
            x = blocks.pop()
925
            self.assertEquals(x, (len(a), len(b), 0))
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
926
            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.
927
928
        chk_blocks('abcdefghijklmnop'
929
                 , 'abcXghiYZQRSTUVWXYZijklmnop'
930
                 , [(0, 0, 3), (6, 4, 3), (9, 20, 7)])
931
932
        chk_blocks('ABCd efghIjk  L'
933
                 , 'AxyzBCn mo pqrstuvwI1 2  L'
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
934
                 , [(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.
935
1711.2.8 by John Arbash Meinel
rot13 the code snippet to help with clarity.
936
        # 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.
937
        chk_blocks('''\
1711.2.8 by John Arbash Meinel
rot13 the code snippet to help with clarity.
938
    trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
939
    """
940
    gnxrf_netf = ['svyr*']
941
    gnxrf_bcgvbaf = ['ab-erphefr']
942
  
943
    qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr):
944
        sebz omeyvo.nqq vzcbeg fzneg_nqq, nqq_ercbegre_cevag, nqq_ercbegre_ahyy
945
        vs vf_dhvrg():
946
            ercbegre = nqq_ercbegre_ahyy
947
        ryfr:
948
            ercbegre = nqq_ercbegre_cevag
949
        fzneg_nqq(svyr_yvfg, abg ab_erphefr, ercbegre)
950
951
952
pynff pzq_zxqve(Pbzznaq):
953
'''.splitlines(True), '''\
954
    trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
955
956
    --qel-eha jvyy fubj juvpu svyrf jbhyq or nqqrq, ohg abg npghnyyl 
957
    nqq gurz.
958
    """
959
    gnxrf_netf = ['svyr*']
960
    gnxrf_bcgvbaf = ['ab-erphefr', 'qel-eha']
961
962
    qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr, qel_eha=Snyfr):
963
        vzcbeg omeyvo.nqq
964
965
        vs qel_eha:
966
            vs vf_dhvrg():
967
                # Guvf vf cbvagyrff, ohg V'q engure abg envfr na reebe
968
                npgvba = omeyvo.nqq.nqq_npgvba_ahyy
969
            ryfr:
970
  npgvba = omeyvo.nqq.nqq_npgvba_cevag
971
        ryvs vf_dhvrg():
972
            npgvba = omeyvo.nqq.nqq_npgvba_nqq
973
        ryfr:
974
       npgvba = omeyvo.nqq.nqq_npgvba_nqq_naq_cevag
975
976
        omeyvo.nqq.fzneg_nqq(svyr_yvfg, abg ab_erphefr, npgvba)
977
978
979
pynff pzq_zxqve(Pbzznaq):
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
980
'''.splitlines(True)
981
, [(0,0,1), (1, 4, 2), (9, 19, 1), (12, 23, 3)])
982
1711.2.9 by John Arbash Meinel
Rename cdv => patience
983
    def test_patience_unified_diff(self):
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
984
        txt_a = ['hello there\n',
985
                 'world\n',
986
                 'how are you today?\n']
987
        txt_b = ['hello there\n',
988
                 'how are you today?\n']
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
989
        unified_diff = bzrlib.patiencediff.unified_diff
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
990
        psm = self._PatienceSequenceMatcher
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
991
        self.assertEquals([ '---  \n',
992
                           '+++  \n',
993
                           '@@ -1,3 +1,2 @@\n',
994
                           ' hello there\n',
995
                           '-world\n',
996
                           ' 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
997
                          ]
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
998
                          , list(unified_diff(txt_a, txt_b,
999
                                 sequencematcher=psm)))
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1000
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
1001
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
1002
        # This is the result with LongestCommonSubstring matching
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1003
        self.assertEquals(['---  \n',
1004
                           '+++  \n',
1005
                           '@@ -1,6 +1,11 @@\n',
1006
                           ' a\n',
1007
                           ' b\n',
1008
                           ' c\n',
1009
                           '+d\n',
1010
                           '+e\n',
1011
                           '+f\n',
1012
                           '+x\n',
1013
                           '+y\n',
1014
                           ' d\n',
1015
                           ' e\n',
1016
                           ' f\n']
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1017
                          , list(unified_diff(txt_a, txt_b)))
1711.2.9 by John Arbash Meinel
Rename cdv => patience
1018
        # And the patience diff
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1019
        self.assertEquals(['---  \n',
1020
                           '+++  \n',
1021
                           '@@ -4,6 +4,11 @@\n',
1022
                           ' d\n',
1023
                           ' e\n',
1024
                           ' f\n',
1025
                           '+x\n',
1026
                           '+y\n',
1027
                           '+d\n',
1028
                           '+e\n',
1029
                           '+f\n',
1030
                           ' g\n',
1031
                           ' h\n',
1032
                           ' i\n',
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1033
                          ]
1185.81.25 by Aaron Bentley
Clean up test_diff
1034
                          , 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
1035
                                 sequencematcher=psm)))
1185.81.25 by Aaron Bentley
Clean up test_diff
1036
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1037
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1038
class TestPatienceDiffLib_c(TestPatienceDiffLib):
1039
1040
    _test_needs_features = [CompiledPatienceDiffFeature]
1041
1042
    def setUp(self):
1043
        super(TestPatienceDiffLib_c, self).setUp()
1044
        import bzrlib._patiencediff_c
1045
        self._unique_lcs = bzrlib._patiencediff_c.unique_lcs_c
1046
        self._recurse_matches = bzrlib._patiencediff_c.recurse_matches_c
1047
        self._PatienceSequenceMatcher = \
1048
            bzrlib._patiencediff_c.PatienceSequenceMatcher_c
1049
1050
1711.2.15 by John Arbash Meinel
Found a couple CDV left
1051
class TestPatienceDiffLibFiles(TestCaseInTempDir):
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1052
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1053
    def setUp(self):
1054
        super(TestPatienceDiffLibFiles, self).setUp()
1055
        self._PatienceSequenceMatcher = \
1056
            bzrlib._patiencediff_py.PatienceSequenceMatcher_py
1057
1711.2.9 by John Arbash Meinel
Rename cdv => patience
1058
    def test_patience_unified_diff_files(self):
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1059
        txt_a = ['hello there\n',
1060
                 'world\n',
1061
                 'how are you today?\n']
1062
        txt_b = ['hello there\n',
1063
                 '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
1064
        open('a1', 'wb').writelines(txt_a)
1065
        open('b1', 'wb').writelines(txt_b)
1066
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
1067
        unified_diff_files = bzrlib.patiencediff.unified_diff_files
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1068
        psm = self._PatienceSequenceMatcher
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1069
        self.assertEquals(['--- a1 \n',
1070
                           '+++ b1 \n',
1071
                           '@@ -1,3 +1,2 @@\n',
1072
                           ' hello there\n',
1073
                           '-world\n',
1074
                           ' 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
1075
                          ]
1185.81.25 by Aaron Bentley
Clean up test_diff
1076
                          , 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
1077
                                 sequencematcher=psm)))
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1078
1079
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
1080
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
1081
        open('a2', 'wb').writelines(txt_a)
1082
        open('b2', 'wb').writelines(txt_b)
1083
1084
        # This is the result with LongestCommonSubstring matching
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1085
        self.assertEquals(['--- a2 \n',
1086
                           '+++ b2 \n',
1087
                           '@@ -1,6 +1,11 @@\n',
1088
                           ' a\n',
1089
                           ' b\n',
1090
                           ' c\n',
1091
                           '+d\n',
1092
                           '+e\n',
1093
                           '+f\n',
1094
                           '+x\n',
1095
                           '+y\n',
1096
                           ' d\n',
1097
                           ' e\n',
1098
                           ' f\n']
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1099
                          , list(unified_diff_files('a2', 'b2')))
1100
1711.2.9 by John Arbash Meinel
Rename cdv => patience
1101
        # And the patience diff
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
1102
        self.assertEquals(['--- a2 \n',
1103
                           '+++ b2 \n',
1104
                           '@@ -4,6 +4,11 @@\n',
1105
                           ' d\n',
1106
                           ' e\n',
1107
                           ' f\n',
1108
                           '+x\n',
1109
                           '+y\n',
1110
                           '+d\n',
1111
                           '+e\n',
1112
                           '+f\n',
1113
                           ' g\n',
1114
                           ' h\n',
1115
                           ' i\n',
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
1116
                          ]
1185.81.25 by Aaron Bentley
Clean up test_diff
1117
                          , 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
1118
                                 sequencematcher=psm)))
2781.1.1 by Martin Pool
merge cpatiencediff from Lukas
1119
1120
1121
class TestPatienceDiffLibFiles_c(TestPatienceDiffLibFiles):
1122
1123
    _test_needs_features = [CompiledPatienceDiffFeature]
1124
1125
    def setUp(self):
1126
        super(TestPatienceDiffLibFiles_c, self).setUp()
1127
        import bzrlib._patiencediff_c
1128
        self._PatienceSequenceMatcher = \
1129
            bzrlib._patiencediff_c.PatienceSequenceMatcher_c
1130
1131
1132
class TestUsingCompiledIfAvailable(TestCase):
1133
1134
    def test_PatienceSequenceMatcher(self):
1135
        if CompiledPatienceDiffFeature.available():
1136
            from bzrlib._patiencediff_c import PatienceSequenceMatcher_c
1137
            self.assertIs(PatienceSequenceMatcher_c,
1138
                          bzrlib.patiencediff.PatienceSequenceMatcher)
1139
        else:
1140
            from bzrlib._patiencediff_py import PatienceSequenceMatcher_py
1141
            self.assertIs(PatienceSequenceMatcher_py,
1142
                          bzrlib.patiencediff.PatienceSequenceMatcher)
1143
1144
    def test_unique_lcs(self):
1145
        if CompiledPatienceDiffFeature.available():
1146
            from bzrlib._patiencediff_c import unique_lcs_c
1147
            self.assertIs(unique_lcs_c,
1148
                          bzrlib.patiencediff.unique_lcs)
1149
        else:
1150
            from bzrlib._patiencediff_py import unique_lcs_py
1151
            self.assertIs(unique_lcs_py,
1152
                          bzrlib.patiencediff.unique_lcs)
1153
1154
    def test_recurse_matches(self):
1155
        if CompiledPatienceDiffFeature.available():
1156
            from bzrlib._patiencediff_c import recurse_matches_c
1157
            self.assertIs(recurse_matches_c,
1158
                          bzrlib.patiencediff.recurse_matches)
1159
        else:
1160
            from bzrlib._patiencediff_py import recurse_matches_py
1161
            self.assertIs(recurse_matches_py,
1162
                          bzrlib.patiencediff.recurse_matches)