~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_merge3.py

  • Committer: Ian Clatworthy
  • Date: 2007-08-13 14:33:10 UTC
  • mto: (2733.1.1 ianc-integration)
  • mto: This revision was merged to the branch mainline in revision 2734.
  • Revision ID: ian.clatworthy@internode.on.net-20070813143310-twhj4la0qnupvze8
Added Quick Start Summary

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2004, 2005 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
 
18
 
from bzrlib import (
19
 
    errors,
20
 
    merge3,
21
 
    tests,
22
 
    )
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
 
 
18
from bzrlib.tests import TestCaseInTempDir, TestCase
23
19
from bzrlib.merge3 import Merge3
24
20
from bzrlib.errors import CantReprocessAndShowBase, BinaryFile
25
21
 
32
28
# common base
33
29
TZU = split_lines("""     The Nameless is the origin of Heaven and Earth;
34
30
     The named is the mother of all things.
35
 
 
 
31
     
36
32
     Therefore let there always be non-being,
37
33
       so we may see their subtlety,
38
34
     And let there always be being,
63
59
     The name that can be named is not the eternal name.
64
60
     The Nameless is the origin of Heaven and Earth;
65
61
     The named is the mother of all things.
66
 
 
 
62
     
67
63
     Therefore let there always be non-being,
68
64
       so we may see their subtlety,
69
65
     And let there always be being,
71
67
     The two are the same,
72
68
     But after they are produced,
73
69
       they have different names.
74
 
 
 
70
     
75
71
       -- The Way of Lao-Tzu, tr. Wing-tsit Chan
76
72
 
77
73
""")
89
85
       they have different names.
90
86
<<<<<<< LAO
91
87
=======
92
 
 
 
88
     
93
89
       -- The Way of Lao-Tzu, tr. Wing-tsit Chan
94
90
 
95
91
>>>>>>> TAO
96
92
""")
97
93
 
98
 
class TestMerge3(tests.TestCase):
 
94
class TestMerge3(TestCase):
99
95
 
100
96
    def test_no_changes(self):
101
97
        """No conflicts because nothing changed"""
102
 
        m3 = merge3.Merge3(['aaa', 'bbb'],
103
 
                           ['aaa', 'bbb'],
104
 
                           ['aaa', 'bbb'])
 
98
        m3 = Merge3(['aaa', 'bbb'],
 
99
                    ['aaa', 'bbb'],
 
100
                    ['aaa', 'bbb'])
105
101
 
106
102
        self.assertEquals(m3.find_unconflicted(),
107
103
                          [(0, 2)])
119
115
                          [('unchanged', ['aaa', 'bbb'])])
120
116
 
121
117
    def test_front_insert(self):
122
 
        m3 = merge3.Merge3(['zz'],
123
 
                           ['aaa', 'bbb', 'zz'],
124
 
                           ['zz'])
 
118
        m3 = Merge3(['zz'],
 
119
                    ['aaa', 'bbb', 'zz'],
 
120
                    ['zz'])
125
121
 
126
122
        # todo: should use a sentinal at end as from get_matching_blocks
127
123
        # to match without zz
136
132
        self.assertEquals(list(m3.merge_groups()),
137
133
                          [('a', ['aaa', 'bbb']),
138
134
                           ('unchanged', ['zz'])])
139
 
 
 
135
        
140
136
    def test_null_insert(self):
141
 
        m3 = merge3.Merge3([],
142
 
                           ['aaa', 'bbb'],
143
 
                           [])
 
137
        m3 = Merge3([],
 
138
                    ['aaa', 'bbb'],
 
139
                    [])
144
140
        # todo: should use a sentinal at end as from get_matching_blocks
145
141
        # to match without zz
146
142
        self.assertEquals(list(m3.find_sync_regions()),
154
150
 
155
151
    def test_no_conflicts(self):
156
152
        """No conflicts because only one side changed"""
157
 
        m3 = merge3.Merge3(['aaa', 'bbb'],
158
 
                           ['aaa', '111', 'bbb'],
159
 
                           ['aaa', 'bbb'])
 
153
        m3 = Merge3(['aaa', 'bbb'],
 
154
                    ['aaa', '111', 'bbb'],
 
155
                    ['aaa', 'bbb'])
160
156
 
161
157
        self.assertEquals(m3.find_unconflicted(),
162
158
                          [(0, 1), (1, 2)])
172
168
                           ('unchanged', 1, 2),])
173
169
 
174
170
    def test_append_a(self):
175
 
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
176
 
                           ['aaa\n', 'bbb\n', '222\n'],
177
 
                           ['aaa\n', 'bbb\n'])
 
171
        m3 = Merge3(['aaa\n', 'bbb\n'],
 
172
                    ['aaa\n', 'bbb\n', '222\n'],
 
173
                    ['aaa\n', 'bbb\n'])
178
174
 
179
175
        self.assertEquals(''.join(m3.merge_lines()),
180
176
                          'aaa\nbbb\n222\n')
181
177
 
182
178
    def test_append_b(self):
183
 
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
184
 
                           ['aaa\n', 'bbb\n'],
185
 
                           ['aaa\n', 'bbb\n', '222\n'])
 
179
        m3 = Merge3(['aaa\n', 'bbb\n'],
 
180
                    ['aaa\n', 'bbb\n'],
 
181
                    ['aaa\n', 'bbb\n', '222\n'])
186
182
 
187
183
        self.assertEquals(''.join(m3.merge_lines()),
188
184
                          'aaa\nbbb\n222\n')
189
185
 
190
186
    def test_append_agreement(self):
191
 
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
192
 
                           ['aaa\n', 'bbb\n', '222\n'],
193
 
                           ['aaa\n', 'bbb\n', '222\n'])
 
187
        m3 = Merge3(['aaa\n', 'bbb\n'],
 
188
                    ['aaa\n', 'bbb\n', '222\n'],
 
189
                    ['aaa\n', 'bbb\n', '222\n'])
194
190
 
195
191
        self.assertEquals(''.join(m3.merge_lines()),
196
192
                          'aaa\nbbb\n222\n')
197
193
 
198
194
    def test_append_clash(self):
199
 
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
200
 
                           ['aaa\n', 'bbb\n', '222\n'],
201
 
                           ['aaa\n', 'bbb\n', '333\n'])
 
195
        m3 = Merge3(['aaa\n', 'bbb\n'],
 
196
                    ['aaa\n', 'bbb\n', '222\n'],
 
197
                    ['aaa\n', 'bbb\n', '333\n'])
202
198
 
203
199
        ml = m3.merge_lines(name_a='a',
204
200
                            name_b='b',
217
213
''')
218
214
 
219
215
    def test_insert_agreement(self):
220
 
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
221
 
                           ['aaa\n', '222\n', 'bbb\n'],
222
 
                           ['aaa\n', '222\n', 'bbb\n'])
 
216
        m3 = Merge3(['aaa\n', 'bbb\n'],
 
217
                    ['aaa\n', '222\n', 'bbb\n'],
 
218
                    ['aaa\n', '222\n', 'bbb\n'])
223
219
 
224
220
        ml = m3.merge_lines(name_a='a',
225
221
                            name_b='b',
227
223
                            mid_marker='--',
228
224
                            end_marker='>>')
229
225
        self.assertEquals(''.join(ml), 'aaa\n222\nbbb\n')
230
 
 
 
226
        
231
227
 
232
228
    def test_insert_clash(self):
233
229
        """Both try to insert lines in the same place."""
234
 
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
235
 
                           ['aaa\n', '111\n', 'bbb\n'],
236
 
                           ['aaa\n', '222\n', 'bbb\n'])
 
230
        m3 = Merge3(['aaa\n', 'bbb\n'],
 
231
                    ['aaa\n', '111\n', 'bbb\n'],
 
232
                    ['aaa\n', '222\n', 'bbb\n'])
237
233
 
238
234
        self.assertEquals(m3.find_unconflicted(),
239
235
                          [(0, 1), (1, 2)])
271
267
 
272
268
    def test_replace_clash(self):
273
269
        """Both try to insert lines in the same place."""
274
 
        m3 = merge3.Merge3(['aaa', '000', 'bbb'],
275
 
                           ['aaa', '111', 'bbb'],
276
 
                           ['aaa', '222', 'bbb'])
 
270
        m3 = Merge3(['aaa', '000', 'bbb'],
 
271
                    ['aaa', '111', 'bbb'],
 
272
                    ['aaa', '222', 'bbb'])
277
273
 
278
274
        self.assertEquals(m3.find_unconflicted(),
279
275
                          [(0, 1), (2, 3)])
285
281
 
286
282
    def test_replace_multi(self):
287
283
        """Replacement with regions of different size."""
288
 
        m3 = merge3.Merge3(['aaa', '000', '000', 'bbb'],
289
 
                           ['aaa', '111', '111', '111', 'bbb'],
290
 
                           ['aaa', '222', '222', '222', '222', 'bbb'])
 
284
        m3 = Merge3(['aaa', '000', '000', 'bbb'],
 
285
                    ['aaa', '111', '111', '111', 'bbb'],
 
286
                    ['aaa', '222', '222', '222', '222', 'bbb'])
291
287
 
292
288
        self.assertEquals(m3.find_unconflicted(),
293
289
                          [(0, 1), (3, 4)])
300
296
 
301
297
    def test_merge_poem(self):
302
298
        """Test case from diff3 manual"""
303
 
        m3 = merge3.Merge3(TZU, LAO, TAO)
 
299
        m3 = Merge3(TZU, LAO, TAO)
304
300
        ml = list(m3.merge_lines('LAO', 'TAO'))
305
301
        self.log('merge result:')
306
302
        self.log(''.join(ml))
311
307
        base_text = ("a\n" * 20).splitlines(True)
312
308
        this_text = ("a\n"*10+"b\n" * 10).splitlines(True)
313
309
        other_text = ("a\n"*10+"c\n"+"b\n" * 8 + "c\n").splitlines(True)
314
 
        m3 = merge3.Merge3(base_text, other_text, this_text)
 
310
        m3 = Merge3(base_text, other_text, this_text)
315
311
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
316
312
        merged_text = "".join(list(m_lines))
317
313
        optimal_text = ("a\n" * 10 + "<<<<<<< OTHER\nc\n"
327
323
        base_text = add_newline("abcdefghijklm")
328
324
        this_text = add_newline("abcdefghijklmNOPQRSTUVWXYZ")
329
325
        other_text = add_newline("abcdefghijklm1OPQRSTUVWXY2")
330
 
        m3 = merge3.Merge3(base_text, other_text, this_text)
 
326
        m3 = Merge3(base_text, other_text, this_text)
331
327
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
332
328
        merged_text = "".join(list(m_lines))
333
329
        optimal_text = ''.join(add_newline("abcdefghijklm")
345
341
        base_text = add_newline("abacddefgghij")
346
342
        this_text = add_newline("abacddefgghijkalmontfprz")
347
343
        other_text = add_newline("abacddefgghijknlmontfprd")
348
 
        m3 = merge3.Merge3(base_text, other_text, this_text)
 
344
        m3 = Merge3(base_text, other_text, this_text)
349
345
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
350
346
        merged_text = "".join(list(m_lines))
351
347
        optimal_text = ''.join(add_newline("abacddefgghijk")
360
356
        base_text = ("a\n" * 20).splitlines(True)
361
357
        this_text = ("a\n"*10+"b\n" * 10).splitlines(True)
362
358
        other_text = ("a\n"*10+"c\n"+"b\n" * 8 + "c\n").splitlines(True)
363
 
        m3 = merge3.Merge3(base_text, other_text, this_text)
364
 
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True,
 
359
        m3 = Merge3(base_text, other_text, this_text)
 
360
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True, 
365
361
                                 base_marker='|||||||')
366
362
        self.assertRaises(CantReprocessAndShowBase, list, m_lines)
367
363
 
368
364
    def test_binary(self):
369
 
        self.assertRaises(BinaryFile, merge3.Merge3, ['\x00'], ['a'], ['b'])
 
365
        self.assertRaises(BinaryFile, Merge3, ['\x00'], ['a'], ['b'])
370
366
 
371
367
    def test_dos_text(self):
372
368
        base_text = 'a\r\n'
373
369
        this_text = 'b\r\n'
374
370
        other_text = 'c\r\n'
375
 
        m3 = merge3.Merge3(base_text.splitlines(True),
376
 
                           other_text.splitlines(True),
377
 
                           this_text.splitlines(True))
 
371
        m3 = Merge3(base_text.splitlines(True), other_text.splitlines(True),
 
372
                    this_text.splitlines(True))
378
373
        m_lines = m3.merge_lines('OTHER', 'THIS')
379
374
        self.assertEqual('<<<<<<< OTHER\r\nc\r\n=======\r\nb\r\n'
380
375
            '>>>>>>> THIS\r\n'.splitlines(True), list(m_lines))
383
378
        base_text = 'a\r'
384
379
        this_text = 'b\r'
385
380
        other_text = 'c\r'
386
 
        m3 = merge3.Merge3(base_text.splitlines(True),
387
 
                           other_text.splitlines(True),
388
 
                           this_text.splitlines(True))
 
381
        m3 = Merge3(base_text.splitlines(True), other_text.splitlines(True),
 
382
                    this_text.splitlines(True))
389
383
        m_lines = m3.merge_lines('OTHER', 'THIS')
390
384
        self.assertEqual('<<<<<<< OTHER\rc\r=======\rb\r'
391
385
            '>>>>>>> THIS\r'.splitlines(True), list(m_lines))
392
 
 
393
 
    def test_merge3_cherrypick(self):
394
 
        base_text = "a\nb\n"
395
 
        this_text = "a\n"
396
 
        other_text = "a\nb\nc\n"
397
 
        # When cherrypicking, lines in base are not part of the conflict
398
 
        m3 = merge3.Merge3(base_text.splitlines(True),
399
 
                           this_text.splitlines(True),
400
 
                           other_text.splitlines(True), is_cherrypick=True)
401
 
        m_lines = m3.merge_lines()
402
 
        self.assertEqualDiff('a\n<<<<<<<\n=======\nc\n>>>>>>>\n',
403
 
                             ''.join(m_lines))
404
 
 
405
 
        # This is not symmetric
406
 
        m3 = merge3.Merge3(base_text.splitlines(True),
407
 
                           other_text.splitlines(True),
408
 
                           this_text.splitlines(True), is_cherrypick=True)
409
 
        m_lines = m3.merge_lines()
410
 
        self.assertEqualDiff('a\n<<<<<<<\nb\nc\n=======\n>>>>>>>\n',
411
 
                             ''.join(m_lines))
412
 
 
413
 
    def test_merge3_cherrypick_w_mixed(self):
414
 
        base_text = 'a\nb\nc\nd\ne\n'
415
 
        this_text = 'a\nb\nq\n'
416
 
        other_text = 'a\nb\nc\nd\nf\ne\ng\n'
417
 
        # When cherrypicking, lines in base are not part of the conflict
418
 
        m3 = merge3.Merge3(base_text.splitlines(True),
419
 
                           this_text.splitlines(True),
420
 
                           other_text.splitlines(True), is_cherrypick=True)
421
 
        m_lines = m3.merge_lines()
422
 
        self.assertEqualDiff('a\n'
423
 
                             'b\n'
424
 
                             '<<<<<<<\n'
425
 
                             'q\n'
426
 
                             '=======\n'
427
 
                             'f\n'
428
 
                             '>>>>>>>\n'
429
 
                             '<<<<<<<\n'
430
 
                             '=======\n'
431
 
                             'g\n'
432
 
                             '>>>>>>>\n',
433
 
                             ''.join(m_lines))
434
 
 
435
 
    def test_allow_objects(self):
436
 
        """Objects other than strs may be used with Merge3 when
437
 
        allow_objects=True.
438
 
        
439
 
        merge_groups and merge_regions work with non-str input.  Methods that
440
 
        return lines like merge_lines fail.
441
 
        """
442
 
        base = [(x,x) for x in 'abcde']
443
 
        a = [(x,x) for x in 'abcdef']
444
 
        b = [(x,x) for x in 'Zabcde']
445
 
        m3 = merge3.Merge3(base, a, b, allow_objects=True)
446
 
        self.assertEqual(
447
 
            [('b', 0, 1),
448
 
             ('unchanged', 0, 5),
449
 
             ('a', 5, 6)],
450
 
            list(m3.merge_regions()))
451
 
        self.assertEqual(
452
 
            [('b', [('Z', 'Z')]),
453
 
             ('unchanged', [(x,x) for x in 'abcde']),
454
 
             ('a', [('f', 'f')])],
455
 
            list(m3.merge_groups()))
456