~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/testmerge3.py

  • Committer: Aaron Bentley
  • Date: 2005-07-26 14:06:11 UTC
  • mto: (1092.1.41) (1185.3.4) (974.1.47)
  • mto: This revision was merged to the branch mainline in revision 982.
  • Revision ID: abentley@panoramicfeedback.com-20050726140611-403e366f3c79c1f1
Fixed python invocation

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
2
 
#
 
1
# Copyright (C) 2004, 2005 by Canonical Ltd
 
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
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
#
 
7
 
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
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
 
    merge3,
20
 
    tests,
21
 
    )
22
 
from bzrlib.errors import CantReprocessAndShowBase, BinaryFile
23
 
 
24
 
def split_lines(t):
25
 
    from cStringIO import StringIO
26
 
    return StringIO(t).readlines()
27
 
 
28
 
############################################################
29
 
# test case data from the gnu diffutils manual
30
 
# common base
31
 
TZU = split_lines("""     The Nameless is the origin of Heaven and Earth;
32
 
     The named is the mother of all things.
33
 
 
34
 
     Therefore let there always be non-being,
35
 
       so we may see their subtlety,
36
 
     And let there always be being,
37
 
       so we may see their outcome.
38
 
     The two are the same,
39
 
     But after they are produced,
40
 
       they have different names.
41
 
     They both may be called deep and profound.
42
 
     Deeper and more profound,
43
 
     The door of all subtleties!
44
 
""")
45
 
 
46
 
LAO = split_lines("""     The Way that can be told of is not the eternal Way;
47
 
     The name that can be named is not the eternal name.
48
 
     The Nameless is the origin of Heaven and Earth;
49
 
     The Named is the mother of all things.
50
 
     Therefore let there always be non-being,
51
 
       so we may see their subtlety,
52
 
     And let there always be being,
53
 
       so we may see their outcome.
54
 
     The two are the same,
55
 
     But after they are produced,
56
 
       they have different names.
57
 
""")
58
 
 
59
 
 
60
 
TAO = split_lines("""     The Way that can be told of is not the eternal Way;
61
 
     The name that can be named is not the eternal name.
62
 
     The Nameless is the origin of Heaven and Earth;
63
 
     The named is the mother of all things.
64
 
 
65
 
     Therefore let there always be non-being,
66
 
       so we may see their subtlety,
67
 
     And let there always be being,
68
 
       so we may see their result.
69
 
     The two are the same,
70
 
     But after they are produced,
71
 
       they have different names.
72
 
 
73
 
       -- The Way of Lao-Tzu, tr. Wing-tsit Chan
74
 
 
75
 
""")
76
 
 
77
 
MERGED_RESULT = split_lines("""     The Way that can be told of is not the eternal Way;
78
 
     The name that can be named is not the eternal name.
79
 
     The Nameless is the origin of Heaven and Earth;
80
 
     The Named is the mother of all things.
81
 
     Therefore let there always be non-being,
82
 
       so we may see their subtlety,
83
 
     And let there always be being,
84
 
       so we may see their result.
85
 
     The two are the same,
86
 
     But after they are produced,
87
 
       they have different names.
88
 
<<<<<<< LAO
89
 
=======
90
 
 
91
 
       -- The Way of Lao-Tzu, tr. Wing-tsit Chan
92
 
 
93
 
>>>>>>> TAO
94
 
""")
95
 
 
96
 
class TestMerge3(tests.TestCase):
97
 
 
98
 
    def test_no_changes(self):
99
 
        """No conflicts because nothing changed"""
100
 
        m3 = merge3.Merge3(['aaa', 'bbb'],
101
 
                           ['aaa', 'bbb'],
102
 
                           ['aaa', 'bbb'])
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
 
 
18
from bzrlib.selftest import InTempDir, TestBase
 
19
from bzrlib.merge3 import Merge3
 
20
 
 
21
 
 
22
 
 
23
 
 
24
 
 
25
class NoChanges(TestBase):
 
26
    """No conflicts because nothing changed"""
 
27
    def runTest(self):
 
28
        m3 = Merge3(['aaa', 'bbb'],
 
29
                    ['aaa', 'bbb'],
 
30
                    ['aaa', 'bbb'])
103
31
 
104
32
        self.assertEquals(m3.find_unconflicted(),
105
33
                          [(0, 2)])
116
44
        self.assertEquals(list(m3.merge_groups()),
117
45
                          [('unchanged', ['aaa', 'bbb'])])
118
46
 
119
 
    def test_front_insert(self):
120
 
        m3 = merge3.Merge3(['zz'],
121
 
                           ['aaa', 'bbb', 'zz'],
122
 
                           ['zz'])
 
47
 
 
48
class FrontInsert(TestBase):
 
49
    def runTest(self):
 
50
        m3 = Merge3(['zz'],
 
51
                    ['aaa', 'bbb', 'zz'],
 
52
                    ['zz'])
123
53
 
124
54
        # todo: should use a sentinal at end as from get_matching_blocks
125
55
        # to match without zz
134
64
        self.assertEquals(list(m3.merge_groups()),
135
65
                          [('a', ['aaa', 'bbb']),
136
66
                           ('unchanged', ['zz'])])
137
 
 
138
 
    def test_null_insert(self):
139
 
        m3 = merge3.Merge3([],
140
 
                           ['aaa', 'bbb'],
141
 
                           [])
 
67
        
 
68
    
 
69
 
 
70
class NullInsert(TestBase):
 
71
    def runTest(self):
 
72
        m3 = Merge3([],
 
73
                    ['aaa', 'bbb'],
 
74
                    [])
 
75
 
142
76
        # todo: should use a sentinal at end as from get_matching_blocks
143
77
        # to match without zz
144
78
        self.assertEquals(list(m3.find_sync_regions()),
149
83
 
150
84
        self.assertEquals(list(m3.merge_lines()),
151
85
                          ['aaa', 'bbb'])
 
86
        
 
87
    
152
88
 
153
 
    def test_no_conflicts(self):
154
 
        """No conflicts because only one side changed"""
155
 
        m3 = merge3.Merge3(['aaa', 'bbb'],
156
 
                           ['aaa', '111', 'bbb'],
157
 
                           ['aaa', 'bbb'])
 
89
class NoConflicts(TestBase):
 
90
    """No conflicts because only one side changed"""
 
91
    def runTest(self):
 
92
        m3 = Merge3(['aaa', 'bbb'],
 
93
                    ['aaa', '111', 'bbb'],
 
94
                    ['aaa', 'bbb'])
158
95
 
159
96
        self.assertEquals(m3.find_unconflicted(),
160
97
                          [(0, 1), (1, 2)])
169
106
                           ('a', 1, 2),
170
107
                           ('unchanged', 1, 2),])
171
108
 
172
 
    def test_append_a(self):
173
 
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
174
 
                           ['aaa\n', 'bbb\n', '222\n'],
175
 
                           ['aaa\n', 'bbb\n'])
176
 
 
177
 
        self.assertEquals(''.join(m3.merge_lines()),
178
 
                          'aaa\nbbb\n222\n')
179
 
 
180
 
    def test_append_b(self):
181
 
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
182
 
                           ['aaa\n', 'bbb\n'],
183
 
                           ['aaa\n', 'bbb\n', '222\n'])
184
 
 
185
 
        self.assertEquals(''.join(m3.merge_lines()),
186
 
                          'aaa\nbbb\n222\n')
187
 
 
188
 
    def test_append_agreement(self):
189
 
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
190
 
                           ['aaa\n', 'bbb\n', '222\n'],
191
 
                           ['aaa\n', 'bbb\n', '222\n'])
192
 
 
193
 
        self.assertEquals(''.join(m3.merge_lines()),
194
 
                          'aaa\nbbb\n222\n')
195
 
 
196
 
    def test_append_clash(self):
197
 
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
198
 
                           ['aaa\n', 'bbb\n', '222\n'],
199
 
                           ['aaa\n', 'bbb\n', '333\n'])
 
109
 
 
110
 
 
111
class AppendA(TestBase):
 
112
    def runTest(self):
 
113
        m3 = Merge3(['aaa\n', 'bbb\n'],
 
114
                    ['aaa\n', 'bbb\n', '222\n'],
 
115
                    ['aaa\n', 'bbb\n'])
 
116
 
 
117
        self.assertEquals(''.join(m3.merge_lines()),
 
118
                          'aaa\nbbb\n222\n')
 
119
 
 
120
class AppendB(TestBase):
 
121
    def runTest(self):
 
122
        m3 = Merge3(['aaa\n', 'bbb\n'],
 
123
                    ['aaa\n', 'bbb\n'],
 
124
                    ['aaa\n', 'bbb\n', '222\n'])
 
125
 
 
126
        self.assertEquals(''.join(m3.merge_lines()),
 
127
                          'aaa\nbbb\n222\n')
 
128
 
 
129
class AppendAgreement(TestBase):
 
130
    def runTest(self):
 
131
        m3 = Merge3(['aaa\n', 'bbb\n'],
 
132
                    ['aaa\n', 'bbb\n', '222\n'],
 
133
                    ['aaa\n', 'bbb\n', '222\n'])
 
134
 
 
135
        self.assertEquals(''.join(m3.merge_lines()),
 
136
                          'aaa\nbbb\n222\n')
 
137
 
 
138
class AppendClash(TestBase):
 
139
    def runTest(self):
 
140
        m3 = Merge3(['aaa\n', 'bbb\n'],
 
141
                    ['aaa\n', 'bbb\n', '222\n'],
 
142
                    ['aaa\n', 'bbb\n', '333\n'])
200
143
 
201
144
        ml = m3.merge_lines(name_a='a',
202
145
                            name_b='b',
214
157
>> b
215
158
''')
216
159
 
217
 
    def test_insert_agreement(self):
218
 
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
219
 
                           ['aaa\n', '222\n', 'bbb\n'],
220
 
                           ['aaa\n', '222\n', 'bbb\n'])
 
160
 
 
161
class InsertAgreement(TestBase):
 
162
    def runTest(self):
 
163
        m3 = Merge3(['aaa\n', 'bbb\n'],
 
164
                    ['aaa\n', '222\n', 'bbb\n'],
 
165
                    ['aaa\n', '222\n', 'bbb\n'])
221
166
 
222
167
        ml = m3.merge_lines(name_a='a',
223
168
                            name_b='b',
224
169
                            start_marker='<<',
225
170
                            mid_marker='--',
226
171
                            end_marker='>>')
227
 
        self.assertEquals(''.join(ml), 'aaa\n222\nbbb\n')
228
 
 
229
 
 
230
 
    def test_insert_clash(self):
231
 
        """Both try to insert lines in the same place."""
232
 
        m3 = merge3.Merge3(['aaa\n', 'bbb\n'],
233
 
                           ['aaa\n', '111\n', 'bbb\n'],
234
 
                           ['aaa\n', '222\n', 'bbb\n'])
 
172
        self.assertEquals(''.join(m3.merge_lines()),
 
173
                          'aaa\n222\nbbb\n')
 
174
 
 
175
 
 
176
 
 
177
 
 
178
class InsertClash(TestBase):
 
179
    """Both try to insert lines in the same place."""
 
180
    def runTest(self):
 
181
        m3 = Merge3(['aaa\n', 'bbb\n'],
 
182
                    ['aaa\n', '111\n', 'bbb\n'],
 
183
                    ['aaa\n', '222\n', 'bbb\n'])
235
184
 
236
185
        self.assertEquals(m3.find_unconflicted(),
237
186
                          [(0, 1), (1, 2)])
267
216
bbb
268
217
''')
269
218
 
270
 
    def test_replace_clash(self):
271
 
        """Both try to insert lines in the same place."""
272
 
        m3 = merge3.Merge3(['aaa', '000', 'bbb'],
273
 
                           ['aaa', '111', 'bbb'],
274
 
                           ['aaa', '222', 'bbb'])
 
219
 
 
220
 
 
221
class ReplaceClash(TestBase):
 
222
    """Both try to insert lines in the same place."""
 
223
    def runTest(self):
 
224
        m3 = Merge3(['aaa', '000', 'bbb'],
 
225
                    ['aaa', '111', 'bbb'],
 
226
                    ['aaa', '222', 'bbb'])
275
227
 
276
228
        self.assertEquals(m3.find_unconflicted(),
277
229
                          [(0, 1), (2, 3)])
281
233
                           (2,3, 2,3, 2,3),
282
234
                           (3,3, 3,3, 3,3),])
283
235
 
284
 
    def test_replace_multi(self):
285
 
        """Replacement with regions of different size."""
286
 
        m3 = merge3.Merge3(['aaa', '000', '000', 'bbb'],
287
 
                           ['aaa', '111', '111', '111', 'bbb'],
288
 
                           ['aaa', '222', '222', '222', '222', 'bbb'])
 
236
 
 
237
 
 
238
class ReplaceMulti(TestBase):
 
239
    """Replacement with regions of different size."""
 
240
    def runTest(self):
 
241
        m3 = Merge3(['aaa', '000', '000', 'bbb'],
 
242
                    ['aaa', '111', '111', '111', 'bbb'],
 
243
                    ['aaa', '222', '222', '222', '222', 'bbb'])
289
244
 
290
245
        self.assertEquals(m3.find_unconflicted(),
291
246
                          [(0, 1), (3, 4)])
296
251
                           (3,4, 4,5, 5,6),
297
252
                           (4,4, 5,5, 6,6),])
298
253
 
299
 
    def test_merge_poem(self):
300
 
        """Test case from diff3 manual"""
301
 
        m3 = merge3.Merge3(TZU, LAO, TAO)
 
254
        
 
255
        
 
256
 
 
257
 
 
258
 
 
259
 
 
260
def split_lines(t):
 
261
    from cStringIO import StringIO
 
262
    return StringIO(t).readlines()
 
263
 
 
264
 
 
265
 
 
266
############################################################
 
267
# test case from the gnu diffutils manual
 
268
 
 
269
# common base
 
270
TZU = split_lines("""     The Nameless is the origin of Heaven and Earth;
 
271
     The named is the mother of all things.
 
272
     
 
273
     Therefore let there always be non-being,
 
274
       so we may see their subtlety,
 
275
     And let there always be being,
 
276
       so we may see their outcome.
 
277
     The two are the same,
 
278
     But after they are produced,
 
279
       they have different names.
 
280
     They both may be called deep and profound.
 
281
     Deeper and more profound,
 
282
     The door of all subtleties!
 
283
""")
 
284
 
 
285
LAO = split_lines("""     The Way that can be told of is not the eternal Way;
 
286
     The name that can be named is not the eternal name.
 
287
     The Nameless is the origin of Heaven and Earth;
 
288
     The Named is the mother of all things.
 
289
     Therefore let there always be non-being,
 
290
       so we may see their subtlety,
 
291
     And let there always be being,
 
292
       so we may see their outcome.
 
293
     The two are the same,
 
294
     But after they are produced,
 
295
       they have different names.
 
296
""")
 
297
 
 
298
 
 
299
TAO = split_lines("""     The Way that can be told of is not the eternal Way;
 
300
     The name that can be named is not the eternal name.
 
301
     The Nameless is the origin of Heaven and Earth;
 
302
     The named is the mother of all things.
 
303
     
 
304
     Therefore let there always be non-being,
 
305
       so we may see their subtlety,
 
306
     And let there always be being,
 
307
       so we may see their result.
 
308
     The two are the same,
 
309
     But after they are produced,
 
310
       they have different names.
 
311
     
 
312
       -- The Way of Lao-Tzu, tr. Wing-tsit Chan
 
313
 
 
314
""")
 
315
 
 
316
MERGED_RESULT = split_lines("""     The Way that can be told of is not the eternal Way;
 
317
     The name that can be named is not the eternal name.
 
318
     The Nameless is the origin of Heaven and Earth;
 
319
     The Named is the mother of all things.
 
320
     Therefore let there always be non-being,
 
321
       so we may see their subtlety,
 
322
     And let there always be being,
 
323
       so we may see their result.
 
324
     The two are the same,
 
325
     But after they are produced,
 
326
       they have different names.
 
327
<<<<<<<< LAO
 
328
========
 
329
     
 
330
       -- The Way of Lao-Tzu, tr. Wing-tsit Chan
 
331
 
 
332
>>>>>>>> TAO
 
333
""")
 
334
 
 
335
 
 
336
 
 
337
class MergePoem(TestBase):
 
338
    """Test case from diff3 manual"""
 
339
    def runTest(self):
 
340
        m3 = Merge3(TZU, LAO, TAO)
302
341
        ml = list(m3.merge_lines('LAO', 'TAO'))
303
342
        self.log('merge result:')
304
343
        self.log(''.join(ml))
305
344
        self.assertEquals(ml, MERGED_RESULT)
306
345
 
307
 
    def test_minimal_conflicts_common(self):
308
 
        """Reprocessing"""
309
 
        base_text = ("a\n" * 20).splitlines(True)
310
 
        this_text = ("a\n"*10+"b\n" * 10).splitlines(True)
311
 
        other_text = ("a\n"*10+"c\n"+"b\n" * 8 + "c\n").splitlines(True)
312
 
        m3 = merge3.Merge3(base_text, other_text, this_text)
313
 
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
314
 
        merged_text = "".join(list(m_lines))
315
 
        optimal_text = ("a\n" * 10 + "<<<<<<< OTHER\nc\n"
316
 
            + 8* "b\n" + "c\n=======\n"
317
 
            + 10*"b\n" + ">>>>>>> THIS\n")
318
 
        self.assertEqualDiff(optimal_text, merged_text)
319
 
 
320
 
    def test_minimal_conflicts_unique(self):
321
 
        def add_newline(s):
322
 
            """Add a newline to each entry in the string"""
323
 
            return [(x+'\n') for x in s]
324
 
 
325
 
        base_text = add_newline("abcdefghijklm")
326
 
        this_text = add_newline("abcdefghijklmNOPQRSTUVWXYZ")
327
 
        other_text = add_newline("abcdefghijklm1OPQRSTUVWXY2")
328
 
        m3 = merge3.Merge3(base_text, other_text, this_text)
329
 
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
330
 
        merged_text = "".join(list(m_lines))
331
 
        optimal_text = ''.join(add_newline("abcdefghijklm")
332
 
            + ["<<<<<<< OTHER\n1\n=======\nN\n>>>>>>> THIS\n"]
333
 
            + add_newline('OPQRSTUVWXY')
334
 
            + ["<<<<<<< OTHER\n2\n=======\nZ\n>>>>>>> THIS\n"]
335
 
            )
336
 
        self.assertEqualDiff(optimal_text, merged_text)
337
 
 
338
 
    def test_minimal_conflicts_nonunique(self):
339
 
        def add_newline(s):
340
 
            """Add a newline to each entry in the string"""
341
 
            return [(x+'\n') for x in s]
342
 
 
343
 
        base_text = add_newline("abacddefgghij")
344
 
        this_text = add_newline("abacddefgghijkalmontfprz")
345
 
        other_text = add_newline("abacddefgghijknlmontfprd")
346
 
        m3 = merge3.Merge3(base_text, other_text, this_text)
347
 
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
348
 
        merged_text = "".join(list(m_lines))
349
 
        optimal_text = ''.join(add_newline("abacddefgghijk")
350
 
            + ["<<<<<<< OTHER\nn\n=======\na\n>>>>>>> THIS\n"]
351
 
            + add_newline('lmontfpr')
352
 
            + ["<<<<<<< OTHER\nd\n=======\nz\n>>>>>>> THIS\n"]
353
 
            )
354
 
        self.assertEqualDiff(optimal_text, merged_text)
355
 
 
356
 
    def test_reprocess_and_base(self):
357
 
        """Reprocessing and showing base breaks correctly"""
358
 
        base_text = ("a\n" * 20).splitlines(True)
359
 
        this_text = ("a\n"*10+"b\n" * 10).splitlines(True)
360
 
        other_text = ("a\n"*10+"c\n"+"b\n" * 8 + "c\n").splitlines(True)
361
 
        m3 = merge3.Merge3(base_text, other_text, this_text)
362
 
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True,
363
 
                                 base_marker='|||||||')
364
 
        self.assertRaises(CantReprocessAndShowBase, list, m_lines)
365
 
 
366
 
    def test_binary(self):
367
 
        self.assertRaises(BinaryFile, merge3.Merge3, ['\x00'], ['a'], ['b'])
368
 
 
369
 
    def test_dos_text(self):
370
 
        base_text = 'a\r\n'
371
 
        this_text = 'b\r\n'
372
 
        other_text = 'c\r\n'
373
 
        m3 = merge3.Merge3(base_text.splitlines(True),
374
 
                           other_text.splitlines(True),
375
 
                           this_text.splitlines(True))
376
 
        m_lines = m3.merge_lines('OTHER', 'THIS')
377
 
        self.assertEqual('<<<<<<< OTHER\r\nc\r\n=======\r\nb\r\n'
378
 
            '>>>>>>> THIS\r\n'.splitlines(True), list(m_lines))
379
 
 
380
 
    def test_mac_text(self):
381
 
        base_text = 'a\r'
382
 
        this_text = 'b\r'
383
 
        other_text = 'c\r'
384
 
        m3 = merge3.Merge3(base_text.splitlines(True),
385
 
                           other_text.splitlines(True),
386
 
                           this_text.splitlines(True))
387
 
        m_lines = m3.merge_lines('OTHER', 'THIS')
388
 
        self.assertEqual('<<<<<<< OTHER\rc\r=======\rb\r'
389
 
            '>>>>>>> THIS\r'.splitlines(True), list(m_lines))
390
 
 
391
 
    def test_merge3_cherrypick(self):
392
 
        base_text = "a\nb\n"
393
 
        this_text = "a\n"
394
 
        other_text = "a\nb\nc\n"
395
 
        # When cherrypicking, lines in base are not part of the conflict
396
 
        m3 = merge3.Merge3(base_text.splitlines(True),
397
 
                           this_text.splitlines(True),
398
 
                           other_text.splitlines(True), is_cherrypick=True)
399
 
        m_lines = m3.merge_lines()
400
 
        self.assertEqualDiff('a\n<<<<<<<\n=======\nc\n>>>>>>>\n',
401
 
                             ''.join(m_lines))
402
 
 
403
 
        # This is not symmetric
404
 
        m3 = merge3.Merge3(base_text.splitlines(True),
405
 
                           other_text.splitlines(True),
406
 
                           this_text.splitlines(True), is_cherrypick=True)
407
 
        m_lines = m3.merge_lines()
408
 
        self.assertEqualDiff('a\n<<<<<<<\nb\nc\n=======\n>>>>>>>\n',
409
 
                             ''.join(m_lines))
410
 
 
411
 
    def test_merge3_cherrypick_w_mixed(self):
412
 
        base_text = 'a\nb\nc\nd\ne\n'
413
 
        this_text = 'a\nb\nq\n'
414
 
        other_text = 'a\nb\nc\nd\nf\ne\ng\n'
415
 
        # When cherrypicking, lines in base are not part of the conflict
416
 
        m3 = merge3.Merge3(base_text.splitlines(True),
417
 
                           this_text.splitlines(True),
418
 
                           other_text.splitlines(True), is_cherrypick=True)
419
 
        m_lines = m3.merge_lines()
420
 
        self.assertEqualDiff('a\n'
421
 
                             'b\n'
422
 
                             '<<<<<<<\n'
423
 
                             'q\n'
424
 
                             '=======\n'
425
 
                             'f\n'
426
 
                             '>>>>>>>\n'
427
 
                             '<<<<<<<\n'
428
 
                             '=======\n'
429
 
                             'g\n'
430
 
                             '>>>>>>>\n',
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
 
 
 
346
 
 
347
 
 
348
TEST_CLASSES = [
 
349
    NoChanges,
 
350
    FrontInsert,
 
351
    NullInsert,
 
352
    NoConflicts,
 
353
    AppendA,
 
354
    AppendB,
 
355
    AppendAgreement,
 
356
    AppendClash,
 
357
    InsertAgreement,
 
358
    InsertClash,
 
359
    ReplaceClash,
 
360
    ReplaceMulti,
 
361
    MergePoem,
 
362
    ]