/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1711.2.16 by John Arbash Meinel
test_diff needs a copyright statement
1
# Copyright (C) 2005, 2006 Canonical Development Ltd
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.
12
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
1692.8.5 by James Henstridge
merge from bzr.dev
20
from tempfile import TemporaryFile
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
21
1692.8.5 by James Henstridge
merge from bzr.dev
22
from bzrlib.diff import internal_diff, external_diff, show_diff_trees
1711.2.56 by John Arbash Meinel
Raise NoDiff if 'diff' not present.
23
from bzrlib.errors import BinaryFile, NoDiff
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
24
import bzrlib.patiencediff
1711.2.54 by John Arbash Meinel
Use mkstemp instead of NamedTemporary file for external diff.
25
from bzrlib.tests import (TestCase, TestCaseWithTransport,
26
                          TestCaseInTempDir, TestSkipped)
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
27
28
1558.15.11 by Aaron Bentley
Apply merge review suggestions
29
def udiff_lines(old, new, allow_binary=False):
974.1.6 by Aaron Bentley
Added unit tests
30
    output = StringIO()
1558.15.11 by Aaron Bentley
Apply merge review suggestions
31
    internal_diff('old', old, 'new', new, output, allow_binary)
974.1.6 by Aaron Bentley
Added unit tests
32
    output.seek(0, 0)
33
    return output.readlines()
34
1711.2.54 by John Arbash Meinel
Use mkstemp instead of NamedTemporary file for external diff.
35
1711.2.57 by John Arbash Meinel
Allow external diff to write to a file without a fileno.
36
def external_udiff_lines(old, new, use_stringio=False):
37
    if use_stringio:
38
        # StringIO has no fileno, so it tests a different codepath
39
        output = StringIO()
40
    else:
41
        output = TemporaryFile()
1692.8.7 by James Henstridge
changes suggested by John Meinel
42
    try:
43
        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
44
    except NoDiff:
1711.2.56 by John Arbash Meinel
Raise NoDiff if 'diff' not present.
45
        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
46
    output.seek(0, 0)
47
    lines = output.readlines()
48
    output.close()
49
    return lines
50
51
1102 by Martin Pool
- merge test refactoring from robertc
52
class TestDiff(TestCase):
1185.81.25 by Aaron Bentley
Clean up test_diff
53
1102 by Martin Pool
- merge test refactoring from robertc
54
    def test_add_nl(self):
55
        """diff generates a valid diff for patches that add a newline"""
974.1.6 by Aaron Bentley
Added unit tests
56
        lines = udiff_lines(['boo'], ['boo\n'])
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
57
        self.check_patch(lines)
58
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
59
            ## "expected no-nl, got %r" % lines[4]
974.1.6 by Aaron Bentley
Added unit tests
60
1102 by Martin Pool
- merge test refactoring from robertc
61
    def test_add_nl_2(self):
62
        """diff generates a valid diff for patches that change last line and
63
        add a newline.
64
        """
974.1.6 by Aaron Bentley
Added unit tests
65
        lines = udiff_lines(['boo'], ['goo\n'])
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
66
        self.check_patch(lines)
67
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
68
            ## "expected no-nl, got %r" % lines[4]
974.1.6 by Aaron Bentley
Added unit tests
69
1102 by Martin Pool
- merge test refactoring from robertc
70
    def test_remove_nl(self):
71
        """diff generates a valid diff for patches that change last line and
72
        add a newline.
73
        """
974.1.6 by Aaron Bentley
Added unit tests
74
        lines = udiff_lines(['boo\n'], ['boo'])
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
75
        self.check_patch(lines)
76
        self.assertEquals(lines[5], '\\ No newline at end of file\n')
77
            ## "expected no-nl, got %r" % lines[5]
78
79
    def check_patch(self, lines):
80
        self.assert_(len(lines) > 1)
81
            ## "Not enough lines for a file header for patch:\n%s" % "".join(lines)
82
        self.assert_(lines[0].startswith ('---'))
83
            ## 'No orig line for patch:\n%s' % "".join(lines)
84
        self.assert_(lines[1].startswith ('+++'))
85
            ## 'No mod line for patch:\n%s' % "".join(lines)
86
        self.assert_(len(lines) > 2)
87
            ## "No hunks for patch:\n%s" % "".join(lines)
88
        self.assert_(lines[2].startswith('@@'))
89
            ## "No hunk header for patch:\n%s" % "".join(lines)
90
        self.assert_('@@' in lines[2][2:])
91
            ## "Unterminated hunk header for patch:\n%s" % "".join(lines)
92
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
93
    def test_binary_lines(self):
94
        self.assertRaises(BinaryFile, udiff_lines, [1023 * 'a' + '\x00'], [])
95
        self.assertRaises(BinaryFile, udiff_lines, [], [1023 * 'a' + '\x00'])
1558.15.11 by Aaron Bentley
Apply merge review suggestions
96
        udiff_lines([1023 * 'a' + '\x00'], [], allow_binary=True)
97
        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
98
99
    def test_external_diff(self):
100
        lines = external_udiff_lines(['boo\n'], ['goo\n'])
101
        self.check_patch(lines)
1899.1.6 by John Arbash Meinel
internal_diff always adds a trailing \n, make sure external_diff does too
102
        self.assertEqual('\n', lines[-1])
1711.2.57 by John Arbash Meinel
Allow external diff to write to a file without a fileno.
103
104
    def test_external_diff_no_fileno(self):
105
        # Make sure that we can handle not having a fileno, even
106
        # if the diff is large
107
        lines = external_udiff_lines(['boo\n']*10000,
108
                                     ['goo\n']*10000,
109
                                     use_stringio=True)
110
        self.check_patch(lines)
1899.1.1 by John Arbash Meinel
Fix the bug in the NoDiff exception class, and add a test
111
1899.1.4 by John Arbash Meinel
Just swallow a return code of 2
112
    def test_external_diff_binary(self):
113
        lines = external_udiff_lines(['\x00foobar\n'], ['foo\x00bar\n'])
1899.1.6 by John Arbash Meinel
internal_diff always adds a trailing \n, make sure external_diff does too
114
        self.assertEqual(['Binary files old and new differ\n', '\n'], lines)
1899.1.4 by John Arbash Meinel
Just swallow a return code of 2
115
1899.1.1 by John Arbash Meinel
Fix the bug in the NoDiff exception class, and add a test
116
    def test_no_external_diff(self):
117
        """Check that NoDiff is raised when diff is not available"""
118
        # Use os.environ['PATH'] to make sure no 'diff' command is available
119
        orig_path = os.environ['PATH']
120
        try:
121
            os.environ['PATH'] = ''
122
            self.assertRaises(NoDiff, external_diff,
123
                              'old', ['boo\n'], 'new', ['goo\n'],
124
                              StringIO(), diff_opts=['-u'])
125
        finally:
126
            os.environ['PATH'] = orig_path
1692.8.2 by James Henstridge
add a test for sending external diff output to a file
127
        
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
128
    def test_internal_diff_default(self):
129
        # Default internal diff encoding is utf8
130
        output = StringIO()
131
        internal_diff(u'old_\xb5', ['old_text\n'],
132
                    u'new_\xe5', ['new_text\n'], output)
133
        lines = output.getvalue().splitlines(True)
134
        self.check_patch(lines)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
135
        self.assertEquals(['--- old_\xc2\xb5\n',
136
                           '+++ new_\xc3\xa5\n',
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
137
                           '@@ -1,1 +1,1 @@\n',
138
                           '-old_text\n',
139
                           '+new_text\n',
140
                           '\n',
141
                          ]
142
                          , lines)
143
144
    def test_internal_diff_utf8(self):
145
        output = StringIO()
146
        internal_diff(u'old_\xb5', ['old_text\n'],
147
                    u'new_\xe5', ['new_text\n'], output,
148
                    path_encoding='utf8')
149
        lines = output.getvalue().splitlines(True)
150
        self.check_patch(lines)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
151
        self.assertEquals(['--- old_\xc2\xb5\n',
152
                           '+++ new_\xc3\xa5\n',
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
153
                           '@@ -1,1 +1,1 @@\n',
154
                           '-old_text\n',
155
                           '+new_text\n',
156
                           '\n',
157
                          ]
158
                          , lines)
159
160
    def test_internal_diff_iso_8859_1(self):
161
        output = StringIO()
162
        internal_diff(u'old_\xb5', ['old_text\n'],
163
                    u'new_\xe5', ['new_text\n'], output,
164
                    path_encoding='iso-8859-1')
165
        lines = output.getvalue().splitlines(True)
166
        self.check_patch(lines)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
167
        self.assertEquals(['--- old_\xb5\n',
168
                           '+++ new_\xe5\n',
1711.2.30 by John Arbash Meinel
Fix bug in internal_diff handling of unicode paths
169
                           '@@ -1,1 +1,1 @@\n',
170
                           '-old_text\n',
171
                           '+new_text\n',
172
                           '\n',
173
                          ]
174
                          , lines)
175
176
    def test_internal_diff_returns_bytes(self):
177
        import StringIO
178
        output = StringIO.StringIO()
179
        internal_diff(u'old_\xb5', ['old_text\n'],
180
                    u'new_\xe5', ['new_text\n'], output)
181
        self.failUnless(isinstance(output.getvalue(), str),
182
            'internal_diff should return bytestrings')
183
1185.81.25 by Aaron Bentley
Clean up test_diff
184
1740.2.5 by Aaron Bentley
Merge from bzr.dev
185
class TestDiffDates(TestCaseWithTransport):
186
187
    def setUp(self):
188
        super(TestDiffDates, self).setUp()
189
        self.wt = self.make_branch_and_tree('.')
190
        self.b = self.wt.branch
191
        self.build_tree_contents([
192
            ('file1', 'file1 contents at rev 1\n'),
193
            ('file2', 'file2 contents at rev 1\n')
194
            ])
195
        self.wt.add(['file1', 'file2'])
196
        self.wt.commit(
197
            message='Revision 1',
198
            timestamp=1143849600, # 2006-04-01 00:00:00 UTC
199
            timezone=0,
200
            rev_id='rev-1')
201
        self.build_tree_contents([('file1', 'file1 contents at rev 2\n')])
202
        self.wt.commit(
203
            message='Revision 2',
204
            timestamp=1143936000, # 2006-04-02 00:00:00 UTC
205
            timezone=28800,
206
            rev_id='rev-2')
207
        self.build_tree_contents([('file2', 'file2 contents at rev 3\n')])
208
        self.wt.commit(
209
            message='Revision 3',
210
            timestamp=1144022400, # 2006-04-03 00:00:00 UTC
211
            timezone=-3600,
212
            rev_id='rev-3')
213
        self.wt.remove(['file2'])
214
        self.wt.commit(
215
            message='Revision 4',
216
            timestamp=1144108800, # 2006-04-04 00:00:00 UTC
217
            timezone=0,
218
            rev_id='rev-4')
219
        self.build_tree_contents([
220
            ('file1', 'file1 contents in working tree\n')
221
            ])
222
        # set the date stamps for files in the working tree to known values
223
        os.utime('file1', (1144195200, 1144195200)) # 2006-04-05 00:00:00 UTC
224
1551.7.22 by Aaron Bentley
Changes from review
225
    def get_diff(self, tree1, tree2, specific_files=None, working_tree=None):
1740.2.5 by Aaron Bentley
Merge from bzr.dev
226
        output = StringIO()
1551.7.22 by Aaron Bentley
Changes from review
227
        if working_tree is not None:
228
            extra_trees = (working_tree,)
229
        else:
230
            extra_trees = ()
231
        show_diff_trees(tree1, tree2, output, specific_files=specific_files,
232
                        extra_trees=extra_trees, old_label='old/', 
233
                        new_label='new/')
1740.2.5 by Aaron Bentley
Merge from bzr.dev
234
        return output.getvalue()
235
236
    def test_diff_rev_tree_working_tree(self):
237
        output = self.get_diff(self.wt.basis_tree(), self.wt)
238
        # note that the date for old/file1 is from rev 2 rather than from
239
        # the basis revision (rev 4)
240
        self.assertEqualDiff(output, '''\
241
=== modified file 'file1'
242
--- old/file1\t2006-04-02 00:00:00 +0000
243
+++ new/file1\t2006-04-05 00:00:00 +0000
244
@@ -1,1 +1,1 @@
245
-file1 contents at rev 2
246
+file1 contents in working tree
247
248
''')
249
250
    def test_diff_rev_tree_rev_tree(self):
251
        tree1 = self.b.repository.revision_tree('rev-2')
252
        tree2 = self.b.repository.revision_tree('rev-3')
253
        output = self.get_diff(tree1, tree2)
254
        self.assertEqualDiff(output, '''\
255
=== modified file 'file2'
256
--- old/file2\t2006-04-01 00:00:00 +0000
257
+++ new/file2\t2006-04-03 00:00:00 +0000
258
@@ -1,1 +1,1 @@
259
-file2 contents at rev 1
260
+file2 contents at rev 3
261
262
''')
263
        
264
    def test_diff_add_files(self):
265
        tree1 = self.b.repository.revision_tree(None)
266
        tree2 = self.b.repository.revision_tree('rev-1')
267
        output = self.get_diff(tree1, tree2)
268
        # the files have the epoch time stamp for the tree in which
269
        # they don't exist.
270
        self.assertEqualDiff(output, '''\
271
=== added file 'file1'
272
--- old/file1\t1970-01-01 00:00:00 +0000
273
+++ new/file1\t2006-04-01 00:00:00 +0000
274
@@ -0,0 +1,1 @@
275
+file1 contents at rev 1
276
277
=== added file 'file2'
278
--- old/file2\t1970-01-01 00:00:00 +0000
279
+++ new/file2\t2006-04-01 00:00:00 +0000
280
@@ -0,0 +1,1 @@
281
+file2 contents at rev 1
282
283
''')
284
285
    def test_diff_remove_files(self):
286
        tree1 = self.b.repository.revision_tree('rev-3')
287
        tree2 = self.b.repository.revision_tree('rev-4')
288
        output = self.get_diff(tree1, tree2)
289
        # the file has the epoch time stamp for the tree in which
290
        # it doesn't exist.
291
        self.assertEqualDiff(output, '''\
292
=== removed file 'file2'
293
--- old/file2\t2006-04-03 00:00:00 +0000
294
+++ new/file2\t1970-01-01 00:00:00 +0000
295
@@ -1,1 +0,0 @@
296
-file2 contents at rev 3
297
298
''')
299
1551.7.17 by Aaron Bentley
Switch to PathsNotVersioned, accept extra_trees
300
    def test_show_diff_specified(self):
1551.7.22 by Aaron Bentley
Changes from review
301
        """A working tree filename can be used to identify a file"""
1551.7.17 by Aaron Bentley
Switch to PathsNotVersioned, accept extra_trees
302
        self.wt.rename_one('file1', 'file1b')
303
        old_tree = self.b.repository.revision_tree('rev-1')
304
        new_tree = self.b.repository.revision_tree('rev-4')
1551.7.22 by Aaron Bentley
Changes from review
305
        out = self.get_diff(old_tree, new_tree, specific_files=['file1b'], 
306
                            working_tree=self.wt)
307
        self.assertContainsRe(out, 'file1\t')
1551.7.17 by Aaron Bentley
Switch to PathsNotVersioned, accept extra_trees
308
1551.7.22 by Aaron Bentley
Changes from review
309
    def test_recursive_diff(self):
310
        """Children of directories are matched"""
311
        os.mkdir('dir1')
312
        os.mkdir('dir2')
313
        self.wt.add(['dir1', 'dir2'])
314
        self.wt.rename_one('file1', 'dir1/file1')
315
        old_tree = self.b.repository.revision_tree('rev-1')
316
        new_tree = self.b.repository.revision_tree('rev-4')
317
        out = self.get_diff(old_tree, new_tree, specific_files=['dir1'], 
318
                            working_tree=self.wt)
319
        self.assertContainsRe(out, 'file1\t')
320
        out = self.get_diff(old_tree, new_tree, specific_files=['dir2'], 
321
                            working_tree=self.wt)
322
        self.assertNotContainsRe(out, 'file1\t')
1740.2.5 by Aaron Bentley
Merge from bzr.dev
323
1899.1.1 by John Arbash Meinel
Fix the bug in the NoDiff exception class, and add a test
324
1711.2.15 by John Arbash Meinel
Found a couple CDV left
325
class TestPatienceDiffLib(TestCase):
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
326
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
327
    def test_unique_lcs(self):
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
328
        unique_lcs = bzrlib.patiencediff.unique_lcs
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
329
        self.assertEquals(unique_lcs('', ''), [])
330
        self.assertEquals(unique_lcs('a', 'a'), [(0,0)])
331
        self.assertEquals(unique_lcs('a', 'b'), [])
332
        self.assertEquals(unique_lcs('ab', 'ab'), [(0,0), (1,1)])
333
        self.assertEquals(unique_lcs('abcde', 'cdeab'), [(2,0), (3,1), (4,2)])
334
        self.assertEquals(unique_lcs('cdeab', 'abcde'), [(0,2), (1,3), (2,4)])
335
        self.assertEquals(unique_lcs('abXde', 'abYde'), [(0,0), (1,1), 
336
                                                         (3,3), (4,4)])
337
        self.assertEquals(unique_lcs('acbac', 'abc'), [(2,1)])
338
339
    def test_recurse_matches(self):
340
        def test_one(a, b, matches):
341
            test_matches = []
1711.2.22 by John Arbash Meinel
Passing the alo parameter to recurse_matches shaves of 5% of the diff time.
342
            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
343
                test_matches, 10)
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
344
            self.assertEquals(test_matches, matches)
345
1711.2.17 by John Arbash Meinel
Small cleanups to patience_diff code.
346
        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,
347
                 [(0, 0), (2, 2), (4, 4)])
348
        test_one(['a', 'c', 'b', 'a', 'c'], ['a', 'b', 'c'],
349
                 [(0, 0), (2, 1), (4, 2)])
350
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
351
        # recurse_matches doesn't match non-unique 
352
        # lines surrounded by bogus text.
1185.81.24 by Aaron Bentley
Reoganize patience-related code
353
        # 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
354
355
        # This is what it could be
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
356
        #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
357
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
358
        # This is what it currently gives:
359
        test_one('aBccDe', 'abccde', [(0,0), (5,5)])
360
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
361
    def test_matching_blocks(self):
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
362
        def chk_blocks(a, b, expected_blocks):
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
363
            # difflib always adds a signature of the total
364
            # 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
365
            s = bzrlib.patiencediff.PatienceSequenceMatcher(None, a, b)
1185.81.11 by John Arbash Meinel
Found some edge cases that weren't being matched.
366
            blocks = s.get_matching_blocks()
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
367
            self.assertEquals((len(a), len(b), 0), blocks[-1])
368
            self.assertEquals(expected_blocks, blocks[:-1])
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
369
1185.81.2 by John Arbash Meinel
A couple small tests.
370
        # Some basic matching tests
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
371
        chk_blocks('', '', [])
372
        chk_blocks([], [], [])
373
        chk_blocks('abcd', 'abcd', [(0, 0, 4)])
374
        chk_blocks('abcd', 'abce', [(0, 0, 3)])
375
        chk_blocks('eabc', 'abce', [(1, 0, 3)])
376
        chk_blocks('eabce', 'abce', [(1, 0, 4)])
377
        chk_blocks('abcde', 'abXde', [(0, 0, 2), (3, 3, 2)])
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
378
        chk_blocks('abcde', 'abXYZde', [(0, 0, 2), (3, 5, 2)])
379
        chk_blocks('abde', 'abXYZde', [(0, 0, 2), (2, 5, 2)])
380
        # This may check too much, but it checks to see that 
381
        # a copied block stays attached to the previous section,
382
        # not the later one.
383
        # difflib would tend to grab the trailing longest match
384
        # 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,
385
        chk_blocks('abcdefghijklmnop', 'abcdefxydefghijklmnop',
386
                   [(0, 0, 6), (6, 11, 10)])
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
387
1185.81.2 by John Arbash Meinel
A couple small tests.
388
        # make sure it supports passing in lists
389
        chk_blocks(
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
390
                   ['hello there\n',
391
                    'world\n',
392
                    'how are you today?\n'],
393
                   ['hello there\n',
394
                    'how are you today?\n'],
1185.81.2 by John Arbash Meinel
A couple small tests.
395
                [(0, 0, 1), (2, 1, 1)])
1185.81.1 by John Arbash Meinel
Adding nofrillsprecisemerge's diff algorithm, wrapped in difflib.
396
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
397
        # non unique lines surrounded by non-matching lines
398
        # won't be found
399
        chk_blocks('aBccDe', 'abccde', [(0,0,1), (5,5,1)])
400
401
        # But they only need to be locally unique
402
        chk_blocks('aBcDec', 'abcdec', [(0,0,1), (2,2,1), (4,4,2)])
403
404
        # non unique blocks won't be matched
405
        chk_blocks('aBcdEcdFg', 'abcdecdfg', [(0,0,1), (8,8,1)])
406
407
        # but locally unique ones will
408
        chk_blocks('aBcdEeXcdFg', 'abcdecdfg', [(0,0,1), (2,2,2),
409
                                              (5,4,1), (7,5,2), (10,8,1)])
410
411
        chk_blocks('abbabbXd', 'cabbabxd', [(7,7,1)])
412
        chk_blocks('abbabbbb', 'cabbabbc', [])
413
        chk_blocks('bbbbbbbb', 'cbbbbbbc', [])
1185.81.11 by John Arbash Meinel
Found some edge cases that weren't being matched.
414
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
415
    def test_opcodes(self):
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
416
        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
417
            s = bzrlib.patiencediff.PatienceSequenceMatcher(None, a, b)
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
418
            self.assertEquals(expected_codes, s.get_opcodes())
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
419
420
        chk_ops('', '', [])
421
        chk_ops([], [], [])
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
422
        chk_ops('abcd', 'abcd', [('equal',    0,4, 0,4)])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
423
        chk_ops('abcd', 'abce', [('equal',   0,3, 0,3),
424
                                 ('replace', 3,4, 3,4)
425
                                ])
426
        chk_ops('eabc', 'abce', [('delete', 0,1, 0,0),
427
                                 ('equal',  1,4, 0,3),
428
                                 ('insert', 4,4, 3,4)
429
                                ])
430
        chk_ops('eabce', 'abce', [('delete', 0,1, 0,0),
431
                                  ('equal',  1,5, 0,4)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
432
                                 ])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
433
        chk_ops('abcde', 'abXde', [('equal',   0,2, 0,2),
434
                                   ('replace', 2,3, 2,3),
435
                                   ('equal',   3,5, 3,5)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
436
                                  ])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
437
        chk_ops('abcde', 'abXYZde', [('equal',   0,2, 0,2),
438
                                     ('replace', 2,3, 2,5),
439
                                     ('equal',   3,5, 5,7)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
440
                                    ])
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
441
        chk_ops('abde', 'abXYZde', [('equal',  0,2, 0,2),
442
                                    ('insert', 2,2, 2,5),
443
                                    ('equal',  2,4, 5,7)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
444
                                   ])
445
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
446
                [('equal',  0,6,  0,6),
447
                 ('insert', 6,6,  6,11),
448
                 ('equal',  6,16, 11,21)
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
449
                ])
450
        chk_ops(
451
                [ 'hello there\n'
452
                , 'world\n'
453
                , 'how are you today?\n'],
454
                [ 'hello there\n'
455
                , 'how are you today?\n'],
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
456
                [('equal',  0,1, 0,1),
457
                 ('delete', 1,2, 1,1),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
458
                 ('equal',  2,3, 1,2),
1185.81.9 by John Arbash Meinel
Added (failing) tests for cdv.recurse_matches with common sections,
459
                ])
460
        chk_ops('aBccDe', 'abccde', 
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
461
                [('equal',   0,1, 0,1),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
462
                 ('replace', 1,5, 1,5),
463
                 ('equal',   5,6, 5,6),
464
                ])
465
        chk_ops('aBcDec', 'abcdec', 
466
                [('equal',   0,1, 0,1),
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
467
                 ('replace', 1,2, 1,2),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
468
                 ('equal',   2,3, 2,3),
469
                 ('replace', 3,4, 3,4),
470
                 ('equal',   4,6, 4,6),
1185.81.3 by John Arbash Meinel
Adding tests for checking opcodes.
471
                ])
1185.81.10 by John Arbash Meinel
Added some more test cases.
472
        chk_ops('aBcdEcdFg', 'abcdecdfg', 
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
473
                [('equal',   0,1, 0,1),
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
474
                 ('replace', 1,8, 1,8),
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
475
                 ('equal',   8,9, 8,9)
1185.81.10 by John Arbash Meinel
Added some more test cases.
476
                ])
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
477
        chk_ops('aBcdEeXcdFg', 'abcdecdfg', 
478
                [('equal',   0,1, 0,1),
479
                 ('replace', 1,2, 1,2),
480
                 ('equal',   2,4, 2,4),
481
                 ('delete', 4,5, 4,4),
482
                 ('equal',   5,6, 4,5),
483
                 ('delete', 6,7, 5,5),
484
                 ('equal',   7,9, 5,7),
485
                 ('replace', 9,10, 7,8),
486
                 ('equal',   10,11, 8,9)
487
                ])
1185.81.10 by John Arbash Meinel
Added some more test cases.
488
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
489
    def test_multiple_ranges(self):
490
        # There was an earlier bug where we used a bad set of ranges,
491
        # 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.
492
        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.
493
            # difflib always adds a signature of the total
494
            # 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
495
            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.
496
            blocks = s.get_matching_blocks()
497
            x = blocks.pop()
498
            self.assertEquals(x, (len(a), len(b), 0))
1711.2.10 by John Arbash Meinel
Clarify the patience tests a little bit.
499
            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.
500
501
        chk_blocks('abcdefghijklmnop'
502
                 , 'abcXghiYZQRSTUVWXYZijklmnop'
503
                 , [(0, 0, 3), (6, 4, 3), (9, 20, 7)])
504
505
        chk_blocks('ABCd efghIjk  L'
506
                 , 'AxyzBCn mo pqrstuvwI1 2  L'
1711.2.21 by John Arbash Meinel
Cleanup patiencediff, remove the use of difflib.SequenceMatcher.
507
                 , [(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.
508
1711.2.8 by John Arbash Meinel
rot13 the code snippet to help with clarity.
509
        # 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.
510
        chk_blocks('''\
1711.2.8 by John Arbash Meinel
rot13 the code snippet to help with clarity.
511
    trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
512
    """
513
    gnxrf_netf = ['svyr*']
514
    gnxrf_bcgvbaf = ['ab-erphefr']
515
  
516
    qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr):
517
        sebz omeyvo.nqq vzcbeg fzneg_nqq, nqq_ercbegre_cevag, nqq_ercbegre_ahyy
518
        vs vf_dhvrg():
519
            ercbegre = nqq_ercbegre_ahyy
520
        ryfr:
521
            ercbegre = nqq_ercbegre_cevag
522
        fzneg_nqq(svyr_yvfg, abg ab_erphefr, ercbegre)
523
524
525
pynff pzq_zxqve(Pbzznaq):
526
'''.splitlines(True), '''\
527
    trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
528
529
    --qel-eha jvyy fubj juvpu svyrf jbhyq or nqqrq, ohg abg npghnyyl 
530
    nqq gurz.
531
    """
532
    gnxrf_netf = ['svyr*']
533
    gnxrf_bcgvbaf = ['ab-erphefr', 'qel-eha']
534
535
    qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr, qel_eha=Snyfr):
536
        vzcbeg omeyvo.nqq
537
538
        vs qel_eha:
539
            vs vf_dhvrg():
540
                # Guvf vf cbvagyrff, ohg V'q engure abg envfr na reebe
541
                npgvba = omeyvo.nqq.nqq_npgvba_ahyy
542
            ryfr:
543
  npgvba = omeyvo.nqq.nqq_npgvba_cevag
544
        ryvs vf_dhvrg():
545
            npgvba = omeyvo.nqq.nqq_npgvba_nqq
546
        ryfr:
547
       npgvba = omeyvo.nqq.nqq_npgvba_nqq_naq_cevag
548
549
        omeyvo.nqq.fzneg_nqq(svyr_yvfg, abg ab_erphefr, npgvba)
550
551
552
pynff pzq_zxqve(Pbzznaq):
1185.81.16 by John Arbash Meinel
Added tests, and an assert check to make sure ranges are always increasing.
553
'''.splitlines(True)
554
, [(0,0,1), (1, 4, 2), (9, 19, 1), (12, 23, 3)])
555
1711.2.9 by John Arbash Meinel
Rename cdv => patience
556
    def test_patience_unified_diff(self):
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
557
        txt_a = ['hello there\n',
558
                 'world\n',
559
                 'how are you today?\n']
560
        txt_b = ['hello there\n',
561
                 'how are you today?\n']
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
562
        unified_diff = bzrlib.patiencediff.unified_diff
563
        psm = bzrlib.patiencediff.PatienceSequenceMatcher
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
564
        self.assertEquals([ '---  \n',
565
                           '+++  \n',
566
                           '@@ -1,3 +1,2 @@\n',
567
                           ' hello there\n',
568
                           '-world\n',
569
                           ' 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
570
                          ]
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
571
                          , list(unified_diff(txt_a, txt_b,
572
                                 sequencematcher=psm)))
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
573
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
574
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
575
        # This is the result with LongestCommonSubstring matching
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
576
        self.assertEquals(['---  \n',
577
                           '+++  \n',
578
                           '@@ -1,6 +1,11 @@\n',
579
                           ' a\n',
580
                           ' b\n',
581
                           ' c\n',
582
                           '+d\n',
583
                           '+e\n',
584
                           '+f\n',
585
                           '+x\n',
586
                           '+y\n',
587
                           ' d\n',
588
                           ' e\n',
589
                           ' f\n']
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
590
                          , list(unified_diff(txt_a, txt_b)))
1711.2.9 by John Arbash Meinel
Rename cdv => patience
591
        # And the patience diff
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
592
        self.assertEquals(['---  \n',
593
                           '+++  \n',
594
                           '@@ -4,6 +4,11 @@\n',
595
                           ' d\n',
596
                           ' e\n',
597
                           ' f\n',
598
                           '+x\n',
599
                           '+y\n',
600
                           '+d\n',
601
                           '+e\n',
602
                           '+f\n',
603
                           ' g\n',
604
                           ' h\n',
605
                           ' i\n',
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
606
                          ]
1185.81.25 by Aaron Bentley
Clean up test_diff
607
                          , 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
608
                                 sequencematcher=psm)))
1185.81.25 by Aaron Bentley
Clean up test_diff
609
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
610
1711.2.15 by John Arbash Meinel
Found a couple CDV left
611
class TestPatienceDiffLibFiles(TestCaseInTempDir):
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
612
1711.2.9 by John Arbash Meinel
Rename cdv => patience
613
    def test_patience_unified_diff_files(self):
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
614
        txt_a = ['hello there\n',
615
                 'world\n',
616
                 'how are you today?\n']
617
        txt_b = ['hello there\n',
618
                 '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
619
        open('a1', 'wb').writelines(txt_a)
620
        open('b1', 'wb').writelines(txt_b)
621
1711.2.20 by John Arbash Meinel
Late bind to patiencediff objects to make it easier to plug-in
622
        unified_diff_files = bzrlib.patiencediff.unified_diff_files
623
        psm = bzrlib.patiencediff.PatienceSequenceMatcher
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
624
        self.assertEquals(['--- a1 \n',
625
                           '+++ b1 \n',
626
                           '@@ -1,3 +1,2 @@\n',
627
                           ' hello there\n',
628
                           '-world\n',
629
                           ' 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
630
                          ]
1185.81.25 by Aaron Bentley
Clean up test_diff
631
                          , 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
632
                                 sequencematcher=psm)))
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
633
634
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
635
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
636
        open('a2', 'wb').writelines(txt_a)
637
        open('b2', 'wb').writelines(txt_b)
638
639
        # This is the result with LongestCommonSubstring matching
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
640
        self.assertEquals(['--- a2 \n',
641
                           '+++ b2 \n',
642
                           '@@ -1,6 +1,11 @@\n',
643
                           ' a\n',
644
                           ' b\n',
645
                           ' c\n',
646
                           '+d\n',
647
                           '+e\n',
648
                           '+f\n',
649
                           '+x\n',
650
                           '+y\n',
651
                           ' d\n',
652
                           ' e\n',
653
                           ' f\n']
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
654
                          , list(unified_diff_files('a2', 'b2')))
655
1711.2.9 by John Arbash Meinel
Rename cdv => patience
656
        # And the patience diff
1185.81.29 by Aaron Bentley
Fix style issues and duplicated tests
657
        self.assertEquals(['--- a2 \n',
658
                           '+++ b2 \n',
659
                           '@@ -4,6 +4,11 @@\n',
660
                           ' d\n',
661
                           ' e\n',
662
                           ' f\n',
663
                           '+x\n',
664
                           '+y\n',
665
                           '+d\n',
666
                           '+e\n',
667
                           '+f\n',
668
                           ' g\n',
669
                           ' h\n',
670
                           ' i\n',
1185.81.14 by John Arbash Meinel
Added a main function for running cdvdifflib manually, included tests for unified_diff interfaces
671
                          ]
1185.81.25 by Aaron Bentley
Clean up test_diff
672
                          , 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
673
                                 sequencematcher=psm)))