~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_merge3.py

  • Committer: Vincent Ladeuil
  • Date: 2017-01-30 14:30:10 UTC
  • mfrom: (6615.3.7 merges)
  • mto: This revision was merged to the branch mainline in revision 6621.
  • Revision ID: v.ladeuil+lp@free.fr-20170130143010-p31t1ranfeqbaeki
Merge  2.7 into trunk including fix for bug #1657238

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005 Canonical Ltd
 
1
# Copyright (C) 2005-2011, 2016 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
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
18
 
from bzrlib.tests import TestCaseInTempDir, TestCase
19
 
from bzrlib.merge3 import Merge3
 
18
from bzrlib import (
 
19
    merge3,
 
20
    tests,
 
21
    )
20
22
from bzrlib.errors import CantReprocessAndShowBase, BinaryFile
21
23
 
22
24
def split_lines(t):
91
93
>>>>>>> TAO
92
94
""")
93
95
 
94
 
class TestMerge3(TestCase):
 
96
class TestMerge3(tests.TestCase):
95
97
 
96
98
    def test_no_changes(self):
97
99
        """No conflicts because nothing changed"""
98
 
        m3 = Merge3(['aaa', 'bbb'],
99
 
                    ['aaa', 'bbb'],
100
 
                    ['aaa', 'bbb'])
 
100
        m3 = merge3.Merge3(['aaa', 'bbb'],
 
101
                           ['aaa', 'bbb'],
 
102
                           ['aaa', 'bbb'])
101
103
 
102
 
        self.assertEquals(m3.find_unconflicted(),
 
104
        self.assertEqual(m3.find_unconflicted(),
103
105
                          [(0, 2)])
104
106
 
105
 
        self.assertEquals(list(m3.find_sync_regions()),
 
107
        self.assertEqual(list(m3.find_sync_regions()),
106
108
                          [(0, 2,
107
109
                            0, 2,
108
110
                            0, 2),
109
111
                           (2,2, 2,2, 2,2)])
110
112
 
111
 
        self.assertEquals(list(m3.merge_regions()),
 
113
        self.assertEqual(list(m3.merge_regions()),
112
114
                          [('unchanged', 0, 2)])
113
115
 
114
 
        self.assertEquals(list(m3.merge_groups()),
 
116
        self.assertEqual(list(m3.merge_groups()),
115
117
                          [('unchanged', ['aaa', 'bbb'])])
116
118
 
117
119
    def test_front_insert(self):
118
 
        m3 = Merge3(['zz'],
119
 
                    ['aaa', 'bbb', 'zz'],
120
 
                    ['zz'])
 
120
        m3 = merge3.Merge3(['zz'],
 
121
                           ['aaa', 'bbb', 'zz'],
 
122
                           ['zz'])
121
123
 
122
124
        # todo: should use a sentinal at end as from get_matching_blocks
123
125
        # to match without zz
124
 
        self.assertEquals(list(m3.find_sync_regions()),
 
126
        self.assertEqual(list(m3.find_sync_regions()),
125
127
                          [(0,1, 2,3, 0,1),
126
128
                           (1,1, 3,3, 1,1),])
127
129
 
128
 
        self.assertEquals(list(m3.merge_regions()),
 
130
        self.assertEqual(list(m3.merge_regions()),
129
131
                          [('a', 0, 2),
130
132
                           ('unchanged', 0, 1)])
131
133
 
132
 
        self.assertEquals(list(m3.merge_groups()),
 
134
        self.assertEqual(list(m3.merge_groups()),
133
135
                          [('a', ['aaa', 'bbb']),
134
136
                           ('unchanged', ['zz'])])
135
137
 
136
138
    def test_null_insert(self):
137
 
        m3 = Merge3([],
138
 
                    ['aaa', 'bbb'],
139
 
                    [])
 
139
        m3 = merge3.Merge3([],
 
140
                           ['aaa', 'bbb'],
 
141
                           [])
140
142
        # todo: should use a sentinal at end as from get_matching_blocks
141
143
        # to match without zz
142
 
        self.assertEquals(list(m3.find_sync_regions()),
 
144
        self.assertEqual(list(m3.find_sync_regions()),
143
145
                          [(0,0, 2,2, 0,0)])
144
146
 
145
 
        self.assertEquals(list(m3.merge_regions()),
 
147
        self.assertEqual(list(m3.merge_regions()),
146
148
                          [('a', 0, 2)])
147
149
 
148
 
        self.assertEquals(list(m3.merge_lines()),
 
150
        self.assertEqual(list(m3.merge_lines()),
149
151
                          ['aaa', 'bbb'])
150
152
 
151
153
    def test_no_conflicts(self):
152
154
        """No conflicts because only one side changed"""
153
 
        m3 = Merge3(['aaa', 'bbb'],
154
 
                    ['aaa', '111', 'bbb'],
155
 
                    ['aaa', 'bbb'])
 
155
        m3 = merge3.Merge3(['aaa', 'bbb'],
 
156
                           ['aaa', '111', 'bbb'],
 
157
                           ['aaa', 'bbb'])
156
158
 
157
 
        self.assertEquals(m3.find_unconflicted(),
 
159
        self.assertEqual(m3.find_unconflicted(),
158
160
                          [(0, 1), (1, 2)])
159
161
 
160
 
        self.assertEquals(list(m3.find_sync_regions()),
 
162
        self.assertEqual(list(m3.find_sync_regions()),
161
163
                          [(0,1, 0,1, 0,1),
162
164
                           (1,2, 2,3, 1,2),
163
165
                           (2,2, 3,3, 2,2),])
164
166
 
165
 
        self.assertEquals(list(m3.merge_regions()),
 
167
        self.assertEqual(list(m3.merge_regions()),
166
168
                          [('unchanged', 0, 1),
167
169
                           ('a', 1, 2),
168
170
                           ('unchanged', 1, 2),])
169
171
 
170
172
    def test_append_a(self):
171
 
        m3 = Merge3(['aaa\n', 'bbb\n'],
172
 
                    ['aaa\n', 'bbb\n', '222\n'],
173
 
                    ['aaa\n', 'bbb\n'])
 
173
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
 
174
                           ['aaa\n', 'bbb\n', '222\n'],
 
175
                           ['aaa\n', 'bbb\n'])
174
176
 
175
 
        self.assertEquals(''.join(m3.merge_lines()),
 
177
        self.assertEqual(''.join(m3.merge_lines()),
176
178
                          'aaa\nbbb\n222\n')
177
179
 
178
180
    def test_append_b(self):
179
 
        m3 = Merge3(['aaa\n', 'bbb\n'],
180
 
                    ['aaa\n', 'bbb\n'],
181
 
                    ['aaa\n', 'bbb\n', '222\n'])
 
181
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
 
182
                           ['aaa\n', 'bbb\n'],
 
183
                           ['aaa\n', 'bbb\n', '222\n'])
182
184
 
183
 
        self.assertEquals(''.join(m3.merge_lines()),
 
185
        self.assertEqual(''.join(m3.merge_lines()),
184
186
                          'aaa\nbbb\n222\n')
185
187
 
186
188
    def test_append_agreement(self):
187
 
        m3 = Merge3(['aaa\n', 'bbb\n'],
188
 
                    ['aaa\n', 'bbb\n', '222\n'],
189
 
                    ['aaa\n', 'bbb\n', '222\n'])
 
189
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
 
190
                           ['aaa\n', 'bbb\n', '222\n'],
 
191
                           ['aaa\n', 'bbb\n', '222\n'])
190
192
 
191
 
        self.assertEquals(''.join(m3.merge_lines()),
 
193
        self.assertEqual(''.join(m3.merge_lines()),
192
194
                          'aaa\nbbb\n222\n')
193
195
 
194
196
    def test_append_clash(self):
195
 
        m3 = Merge3(['aaa\n', 'bbb\n'],
196
 
                    ['aaa\n', 'bbb\n', '222\n'],
197
 
                    ['aaa\n', 'bbb\n', '333\n'])
 
197
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
 
198
                           ['aaa\n', 'bbb\n', '222\n'],
 
199
                           ['aaa\n', 'bbb\n', '333\n'])
198
200
 
199
201
        ml = m3.merge_lines(name_a='a',
200
202
                            name_b='b',
201
203
                            start_marker='<<',
202
204
                            mid_marker='--',
203
205
                            end_marker='>>')
204
 
        self.assertEquals(''.join(ml),
 
206
        self.assertEqual(''.join(ml),
205
207
'''\
206
208
aaa
207
209
bbb
213
215
''')
214
216
 
215
217
    def test_insert_agreement(self):
216
 
        m3 = Merge3(['aaa\n', 'bbb\n'],
217
 
                    ['aaa\n', '222\n', 'bbb\n'],
218
 
                    ['aaa\n', '222\n', 'bbb\n'])
 
218
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
 
219
                           ['aaa\n', '222\n', 'bbb\n'],
 
220
                           ['aaa\n', '222\n', 'bbb\n'])
219
221
 
220
222
        ml = m3.merge_lines(name_a='a',
221
223
                            name_b='b',
222
224
                            start_marker='<<',
223
225
                            mid_marker='--',
224
226
                            end_marker='>>')
225
 
        self.assertEquals(''.join(ml), 'aaa\n222\nbbb\n')
 
227
        self.assertEqual(''.join(ml), 'aaa\n222\nbbb\n')
226
228
 
227
229
 
228
230
    def test_insert_clash(self):
229
231
        """Both try to insert lines in the same place."""
230
 
        m3 = Merge3(['aaa\n', 'bbb\n'],
231
 
                    ['aaa\n', '111\n', 'bbb\n'],
232
 
                    ['aaa\n', '222\n', 'bbb\n'])
 
232
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
 
233
                           ['aaa\n', '111\n', 'bbb\n'],
 
234
                           ['aaa\n', '222\n', 'bbb\n'])
233
235
 
234
 
        self.assertEquals(m3.find_unconflicted(),
 
236
        self.assertEqual(m3.find_unconflicted(),
235
237
                          [(0, 1), (1, 2)])
236
238
 
237
 
        self.assertEquals(list(m3.find_sync_regions()),
 
239
        self.assertEqual(list(m3.find_sync_regions()),
238
240
                          [(0,1, 0,1, 0,1),
239
241
                           (1,2, 2,3, 2,3),
240
242
                           (2,2, 3,3, 3,3),])
241
243
 
242
 
        self.assertEquals(list(m3.merge_regions()),
 
244
        self.assertEqual(list(m3.merge_regions()),
243
245
                          [('unchanged', 0,1),
244
246
                           ('conflict', 1,1, 1,2, 1,2),
245
247
                           ('unchanged', 1,2)])
246
248
 
247
 
        self.assertEquals(list(m3.merge_groups()),
 
249
        self.assertEqual(list(m3.merge_groups()),
248
250
                          [('unchanged', ['aaa\n']),
249
251
                           ('conflict', [], ['111\n'], ['222\n']),
250
252
                           ('unchanged', ['bbb\n']),
255
257
                            start_marker='<<',
256
258
                            mid_marker='--',
257
259
                            end_marker='>>')
258
 
        self.assertEquals(''.join(ml),
 
260
        self.assertEqual(''.join(ml),
259
261
'''aaa
260
262
<< a
261
263
111
267
269
 
268
270
    def test_replace_clash(self):
269
271
        """Both try to insert lines in the same place."""
270
 
        m3 = Merge3(['aaa', '000', 'bbb'],
271
 
                    ['aaa', '111', 'bbb'],
272
 
                    ['aaa', '222', 'bbb'])
 
272
        m3 = merge3.Merge3(['aaa', '000', 'bbb'],
 
273
                           ['aaa', '111', 'bbb'],
 
274
                           ['aaa', '222', 'bbb'])
273
275
 
274
 
        self.assertEquals(m3.find_unconflicted(),
 
276
        self.assertEqual(m3.find_unconflicted(),
275
277
                          [(0, 1), (2, 3)])
276
278
 
277
 
        self.assertEquals(list(m3.find_sync_regions()),
 
279
        self.assertEqual(list(m3.find_sync_regions()),
278
280
                          [(0,1, 0,1, 0,1),
279
281
                           (2,3, 2,3, 2,3),
280
282
                           (3,3, 3,3, 3,3),])
281
283
 
282
284
    def test_replace_multi(self):
283
285
        """Replacement with regions of different size."""
284
 
        m3 = Merge3(['aaa', '000', '000', 'bbb'],
285
 
                    ['aaa', '111', '111', '111', 'bbb'],
286
 
                    ['aaa', '222', '222', '222', '222', 'bbb'])
 
286
        m3 = merge3.Merge3(['aaa', '000', '000', 'bbb'],
 
287
                           ['aaa', '111', '111', '111', 'bbb'],
 
288
                           ['aaa', '222', '222', '222', '222', 'bbb'])
287
289
 
288
 
        self.assertEquals(m3.find_unconflicted(),
 
290
        self.assertEqual(m3.find_unconflicted(),
289
291
                          [(0, 1), (3, 4)])
290
292
 
291
293
 
292
 
        self.assertEquals(list(m3.find_sync_regions()),
 
294
        self.assertEqual(list(m3.find_sync_regions()),
293
295
                          [(0,1, 0,1, 0,1),
294
296
                           (3,4, 4,5, 5,6),
295
297
                           (4,4, 5,5, 6,6),])
296
298
 
297
299
    def test_merge_poem(self):
298
300
        """Test case from diff3 manual"""
299
 
        m3 = Merge3(TZU, LAO, TAO)
 
301
        m3 = merge3.Merge3(TZU, LAO, TAO)
300
302
        ml = list(m3.merge_lines('LAO', 'TAO'))
301
303
        self.log('merge result:')
302
304
        self.log(''.join(ml))
303
 
        self.assertEquals(ml, MERGED_RESULT)
 
305
        self.assertEqual(ml, MERGED_RESULT)
304
306
 
305
307
    def test_minimal_conflicts_common(self):
306
308
        """Reprocessing"""
307
309
        base_text = ("a\n" * 20).splitlines(True)
308
310
        this_text = ("a\n"*10+"b\n" * 10).splitlines(True)
309
311
        other_text = ("a\n"*10+"c\n"+"b\n" * 8 + "c\n").splitlines(True)
310
 
        m3 = Merge3(base_text, other_text, this_text)
 
312
        m3 = merge3.Merge3(base_text, other_text, this_text)
311
313
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
312
314
        merged_text = "".join(list(m_lines))
313
315
        optimal_text = ("a\n" * 10 + "<<<<<<< OTHER\nc\n"
323
325
        base_text = add_newline("abcdefghijklm")
324
326
        this_text = add_newline("abcdefghijklmNOPQRSTUVWXYZ")
325
327
        other_text = add_newline("abcdefghijklm1OPQRSTUVWXY2")
326
 
        m3 = Merge3(base_text, other_text, this_text)
 
328
        m3 = merge3.Merge3(base_text, other_text, this_text)
327
329
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
328
330
        merged_text = "".join(list(m_lines))
329
331
        optimal_text = ''.join(add_newline("abcdefghijklm")
341
343
        base_text = add_newline("abacddefgghij")
342
344
        this_text = add_newline("abacddefgghijkalmontfprz")
343
345
        other_text = add_newline("abacddefgghijknlmontfprd")
344
 
        m3 = Merge3(base_text, other_text, this_text)
 
346
        m3 = merge3.Merge3(base_text, other_text, this_text)
345
347
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
346
348
        merged_text = "".join(list(m_lines))
347
349
        optimal_text = ''.join(add_newline("abacddefgghijk")
356
358
        base_text = ("a\n" * 20).splitlines(True)
357
359
        this_text = ("a\n"*10+"b\n" * 10).splitlines(True)
358
360
        other_text = ("a\n"*10+"c\n"+"b\n" * 8 + "c\n").splitlines(True)
359
 
        m3 = Merge3(base_text, other_text, this_text)
 
361
        m3 = merge3.Merge3(base_text, other_text, this_text)
360
362
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True,
361
363
                                 base_marker='|||||||')
362
364
        self.assertRaises(CantReprocessAndShowBase, list, m_lines)
363
365
 
364
366
    def test_binary(self):
365
 
        self.assertRaises(BinaryFile, Merge3, ['\x00'], ['a'], ['b'])
 
367
        self.assertRaises(BinaryFile, merge3.Merge3, ['\x00'], ['a'], ['b'])
366
368
 
367
369
    def test_dos_text(self):
368
370
        base_text = 'a\r\n'
369
371
        this_text = 'b\r\n'
370
372
        other_text = 'c\r\n'
371
 
        m3 = Merge3(base_text.splitlines(True), other_text.splitlines(True),
372
 
                    this_text.splitlines(True))
 
373
        m3 = merge3.Merge3(base_text.splitlines(True),
 
374
                           other_text.splitlines(True),
 
375
                           this_text.splitlines(True))
373
376
        m_lines = m3.merge_lines('OTHER', 'THIS')
374
377
        self.assertEqual('<<<<<<< OTHER\r\nc\r\n=======\r\nb\r\n'
375
378
            '>>>>>>> THIS\r\n'.splitlines(True), list(m_lines))
378
381
        base_text = 'a\r'
379
382
        this_text = 'b\r'
380
383
        other_text = 'c\r'
381
 
        m3 = Merge3(base_text.splitlines(True), other_text.splitlines(True),
382
 
                    this_text.splitlines(True))
 
384
        m3 = merge3.Merge3(base_text.splitlines(True),
 
385
                           other_text.splitlines(True),
 
386
                           this_text.splitlines(True))
383
387
        m_lines = m3.merge_lines('OTHER', 'THIS')
384
388
        self.assertEqual('<<<<<<< OTHER\rc\r=======\rb\r'
385
389
            '>>>>>>> THIS\r'.splitlines(True), list(m_lines))
389
393
        this_text = "a\n"
390
394
        other_text = "a\nb\nc\n"
391
395
        # When cherrypicking, lines in base are not part of the conflict
392
 
        m3 = Merge3(base_text.splitlines(True), this_text.splitlines(True),
393
 
                    other_text.splitlines(True), is_cherrypick=True)
 
396
        m3 = merge3.Merge3(base_text.splitlines(True),
 
397
                           this_text.splitlines(True),
 
398
                           other_text.splitlines(True), is_cherrypick=True)
394
399
        m_lines = m3.merge_lines()
395
400
        self.assertEqualDiff('a\n<<<<<<<\n=======\nc\n>>>>>>>\n',
396
401
                             ''.join(m_lines))
397
402
 
398
403
        # This is not symmetric
399
 
        m3 = Merge3(base_text.splitlines(True), other_text.splitlines(True),
400
 
                    this_text.splitlines(True), is_cherrypick=True)
 
404
        m3 = merge3.Merge3(base_text.splitlines(True),
 
405
                           other_text.splitlines(True),
 
406
                           this_text.splitlines(True), is_cherrypick=True)
401
407
        m_lines = m3.merge_lines()
402
408
        self.assertEqualDiff('a\n<<<<<<<\nb\nc\n=======\n>>>>>>>\n',
403
409
                             ''.join(m_lines))
407
413
        this_text = 'a\nb\nq\n'
408
414
        other_text = 'a\nb\nc\nd\nf\ne\ng\n'
409
415
        # When cherrypicking, lines in base are not part of the conflict
410
 
        m3 = Merge3(base_text.splitlines(True), this_text.splitlines(True),
411
 
                    other_text.splitlines(True), is_cherrypick=True)
 
416
        m3 = merge3.Merge3(base_text.splitlines(True),
 
417
                           this_text.splitlines(True),
 
418
                           other_text.splitlines(True), is_cherrypick=True)
412
419
        m_lines = m3.merge_lines()
413
420
        self.assertEqualDiff('a\n'
414
421
                             'b\n'
422
429
                             'g\n'
423
430
                             '>>>>>>>\n',
424
431
                             ''.join(m_lines))
 
432
 
 
433
    def test_allow_objects(self):
 
434
        """Objects other than strs may be used with Merge3 when
 
435
        allow_objects=True.
 
436
        
 
437
        merge_groups and merge_regions work with non-str input.  Methods that
 
438
        return lines like merge_lines fail.
 
439
        """
 
440
        base = [(x,x) for x in 'abcde']
 
441
        a = [(x,x) for x in 'abcdef']
 
442
        b = [(x,x) for x in 'Zabcde']
 
443
        m3 = merge3.Merge3(base, a, b, allow_objects=True)
 
444
        self.assertEqual(
 
445
            [('b', 0, 1),
 
446
             ('unchanged', 0, 5),
 
447
             ('a', 5, 6)],
 
448
            list(m3.merge_regions()))
 
449
        self.assertEqual(
 
450
            [('b', [('Z', 'Z')]),
 
451
             ('unchanged', [(x,x) for x in 'abcde']),
 
452
             ('a', [('f', 'f')])],
 
453
            list(m3.merge_groups()))
 
454