/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_merge3.py

  • Committer: Jelmer Vernooij
  • Date: 2020-04-05 19:11:34 UTC
  • mto: (7490.7.16 work)
  • mto: This revision was merged to the branch mainline in revision 7501.
  • Revision ID: jelmer@jelmer.uk-20200405191134-0aebh8ikiwygxma5
Populate the .gitignore file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 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 import (
19
 
    errors,
 
18
from .. import (
20
19
    merge3,
21
20
    tests,
22
21
    )
23
 
from bzrlib.merge3 import Merge3
24
 
from bzrlib.errors import CantReprocessAndShowBase, BinaryFile
 
22
from ..errors import BinaryFile
 
23
from ..sixish import (
 
24
    BytesIO,
 
25
    int2byte,
 
26
    )
 
27
 
25
28
 
26
29
def split_lines(t):
27
 
    from cStringIO import StringIO
28
 
    return StringIO(t).readlines()
 
30
    return BytesIO(t).readlines()
 
31
 
29
32
 
30
33
############################################################
31
34
# test case data from the gnu diffutils manual
32
35
# common base
33
 
TZU = split_lines("""     The Nameless is the origin of Heaven and Earth;
 
36
TZU = split_lines(b"""     The Nameless is the origin of Heaven and Earth;
34
37
     The named is the mother of all things.
35
38
 
36
39
     Therefore let there always be non-being,
45
48
     The door of all subtleties!
46
49
""")
47
50
 
48
 
LAO = split_lines("""     The Way that can be told of is not the eternal Way;
 
51
LAO = split_lines(b"""     The Way that can be told of is not the eternal Way;
49
52
     The name that can be named is not the eternal name.
50
53
     The Nameless is the origin of Heaven and Earth;
51
54
     The Named is the mother of all things.
59
62
""")
60
63
 
61
64
 
62
 
TAO = split_lines("""     The Way that can be told of is not the eternal Way;
 
65
TAO = split_lines(b"""     The Way that can be told of is not the eternal Way;
63
66
     The name that can be named is not the eternal name.
64
67
     The Nameless is the origin of Heaven and Earth;
65
68
     The named is the mother of all things.
76
79
 
77
80
""")
78
81
 
79
 
MERGED_RESULT = split_lines("""     The Way that can be told of is not the eternal Way;
 
82
MERGED_RESULT = split_lines(b"""     The Way that can be told of is not the eternal Way;
80
83
     The name that can be named is not the eternal name.
81
84
     The Nameless is the origin of Heaven and Earth;
82
85
     The Named is the mother of all things.
95
98
>>>>>>> TAO
96
99
""")
97
100
 
 
101
 
98
102
class TestMerge3(tests.TestCase):
99
103
 
100
104
    def test_no_changes(self):
101
105
        """No conflicts because nothing changed"""
102
 
        m3 = merge3.Merge3(['aaa', 'bbb'],
103
 
                           ['aaa', 'bbb'],
104
 
                           ['aaa', 'bbb'])
105
 
 
106
 
        self.assertEquals(m3.find_unconflicted(),
107
 
                          [(0, 2)])
108
 
 
109
 
        self.assertEquals(list(m3.find_sync_regions()),
110
 
                          [(0, 2,
111
 
                            0, 2,
112
 
                            0, 2),
113
 
                           (2,2, 2,2, 2,2)])
114
 
 
115
 
        self.assertEquals(list(m3.merge_regions()),
116
 
                          [('unchanged', 0, 2)])
117
 
 
118
 
        self.assertEquals(list(m3.merge_groups()),
119
 
                          [('unchanged', ['aaa', 'bbb'])])
 
106
        m3 = merge3.Merge3([b'aaa', b'bbb'],
 
107
                           [b'aaa', b'bbb'],
 
108
                           [b'aaa', b'bbb'])
 
109
 
 
110
        self.assertEqual(m3.find_unconflicted(),
 
111
                         [(0, 2)])
 
112
 
 
113
        self.assertEqual(list(m3.find_sync_regions()),
 
114
                         [(0, 2,
 
115
                           0, 2,
 
116
                           0, 2),
 
117
                          (2, 2, 2, 2, 2, 2)])
 
118
 
 
119
        self.assertEqual(list(m3.merge_regions()),
 
120
                         [('unchanged', 0, 2)])
 
121
 
 
122
        self.assertEqual(list(m3.merge_groups()),
 
123
                         [('unchanged', [b'aaa', b'bbb'])])
120
124
 
121
125
    def test_front_insert(self):
122
 
        m3 = merge3.Merge3(['zz'],
123
 
                           ['aaa', 'bbb', 'zz'],
124
 
                           ['zz'])
 
126
        m3 = merge3.Merge3([b'zz'],
 
127
                           [b'aaa', b'bbb', b'zz'],
 
128
                           [b'zz'])
125
129
 
126
130
        # todo: should use a sentinal at end as from get_matching_blocks
127
131
        # to match without zz
128
 
        self.assertEquals(list(m3.find_sync_regions()),
129
 
                          [(0,1, 2,3, 0,1),
130
 
                           (1,1, 3,3, 1,1),])
131
 
 
132
 
        self.assertEquals(list(m3.merge_regions()),
133
 
                          [('a', 0, 2),
134
 
                           ('unchanged', 0, 1)])
135
 
 
136
 
        self.assertEquals(list(m3.merge_groups()),
137
 
                          [('a', ['aaa', 'bbb']),
138
 
                           ('unchanged', ['zz'])])
 
132
        self.assertEqual(list(m3.find_sync_regions()),
 
133
                         [(0, 1, 2, 3, 0, 1),
 
134
                          (1, 1, 3, 3, 1, 1), ])
 
135
 
 
136
        self.assertEqual(list(m3.merge_regions()),
 
137
                         [('a', 0, 2),
 
138
                          ('unchanged', 0, 1)])
 
139
 
 
140
        self.assertEqual(list(m3.merge_groups()),
 
141
                         [('a', [b'aaa', b'bbb']),
 
142
                          ('unchanged', [b'zz'])])
139
143
 
140
144
    def test_null_insert(self):
141
145
        m3 = merge3.Merge3([],
142
 
                           ['aaa', 'bbb'],
 
146
                           [b'aaa', b'bbb'],
143
147
                           [])
144
148
        # todo: should use a sentinal at end as from get_matching_blocks
145
149
        # to match without zz
146
 
        self.assertEquals(list(m3.find_sync_regions()),
147
 
                          [(0,0, 2,2, 0,0)])
148
 
 
149
 
        self.assertEquals(list(m3.merge_regions()),
150
 
                          [('a', 0, 2)])
151
 
 
152
 
        self.assertEquals(list(m3.merge_lines()),
153
 
                          ['aaa', 'bbb'])
 
150
        self.assertEqual(list(m3.find_sync_regions()),
 
151
                         [(0, 0, 2, 2, 0, 0)])
 
152
 
 
153
        self.assertEqual(list(m3.merge_regions()),
 
154
                         [('a', 0, 2)])
 
155
 
 
156
        self.assertEqual(list(m3.merge_lines()),
 
157
                         [b'aaa', b'bbb'])
154
158
 
155
159
    def test_no_conflicts(self):
156
160
        """No conflicts because only one side changed"""
157
 
        m3 = merge3.Merge3(['aaa', 'bbb'],
158
 
                           ['aaa', '111', 'bbb'],
159
 
                           ['aaa', 'bbb'])
160
 
 
161
 
        self.assertEquals(m3.find_unconflicted(),
162
 
                          [(0, 1), (1, 2)])
163
 
 
164
 
        self.assertEquals(list(m3.find_sync_regions()),
165
 
                          [(0,1, 0,1, 0,1),
166
 
                           (1,2, 2,3, 1,2),
167
 
                           (2,2, 3,3, 2,2),])
168
 
 
169
 
        self.assertEquals(list(m3.merge_regions()),
170
 
                          [('unchanged', 0, 1),
171
 
                           ('a', 1, 2),
172
 
                           ('unchanged', 1, 2),])
 
161
        m3 = merge3.Merge3([b'aaa', b'bbb'],
 
162
                           [b'aaa', b'111', b'bbb'],
 
163
                           [b'aaa', b'bbb'])
 
164
 
 
165
        self.assertEqual(m3.find_unconflicted(),
 
166
                         [(0, 1), (1, 2)])
 
167
 
 
168
        self.assertEqual(list(m3.find_sync_regions()),
 
169
                         [(0, 1, 0, 1, 0, 1),
 
170
                          (1, 2, 2, 3, 1, 2),
 
171
                          (2, 2, 3, 3, 2, 2), ])
 
172
 
 
173
        self.assertEqual(list(m3.merge_regions()),
 
174
                         [('unchanged', 0, 1),
 
175
                          ('a', 1, 2),
 
176
                          ('unchanged', 1, 2), ])
173
177
 
174
178
    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'])
 
179
        m3 = merge3.Merge3([b'aaa\n', b'bbb\n'],
 
180
                           [b'aaa\n', b'bbb\n', b'222\n'],
 
181
                           [b'aaa\n', b'bbb\n'])
178
182
 
179
 
        self.assertEquals(''.join(m3.merge_lines()),
180
 
                          'aaa\nbbb\n222\n')
 
183
        self.assertEqual(b''.join(m3.merge_lines()),
 
184
                         b'aaa\nbbb\n222\n')
181
185
 
182
186
    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'])
 
187
        m3 = merge3.Merge3([b'aaa\n', b'bbb\n'],
 
188
                           [b'aaa\n', b'bbb\n'],
 
189
                           [b'aaa\n', b'bbb\n', b'222\n'])
186
190
 
187
 
        self.assertEquals(''.join(m3.merge_lines()),
188
 
                          'aaa\nbbb\n222\n')
 
191
        self.assertEqual(b''.join(m3.merge_lines()),
 
192
                         b'aaa\nbbb\n222\n')
189
193
 
190
194
    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'])
 
195
        m3 = merge3.Merge3([b'aaa\n', b'bbb\n'],
 
196
                           [b'aaa\n', b'bbb\n', b'222\n'],
 
197
                           [b'aaa\n', b'bbb\n', b'222\n'])
194
198
 
195
 
        self.assertEquals(''.join(m3.merge_lines()),
196
 
                          'aaa\nbbb\n222\n')
 
199
        self.assertEqual(b''.join(m3.merge_lines()),
 
200
                         b'aaa\nbbb\n222\n')
197
201
 
198
202
    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'])
 
203
        m3 = merge3.Merge3([b'aaa\n', b'bbb\n'],
 
204
                           [b'aaa\n', b'bbb\n', b'222\n'],
 
205
                           [b'aaa\n', b'bbb\n', b'333\n'])
202
206
 
203
 
        ml = m3.merge_lines(name_a='a',
204
 
                            name_b='b',
205
 
                            start_marker='<<',
206
 
                            mid_marker='--',
207
 
                            end_marker='>>')
208
 
        self.assertEquals(''.join(ml),
209
 
'''\
 
207
        ml = m3.merge_lines(name_a=b'a',
 
208
                            name_b=b'b',
 
209
                            start_marker=b'<<',
 
210
                            mid_marker=b'--',
 
211
                            end_marker=b'>>')
 
212
        self.assertEqual(b''.join(ml),
 
213
                         b'''\
210
214
aaa
211
215
bbb
212
216
<< a
217
221
''')
218
222
 
219
223
    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'])
223
 
 
224
 
        ml = m3.merge_lines(name_a='a',
225
 
                            name_b='b',
226
 
                            start_marker='<<',
227
 
                            mid_marker='--',
228
 
                            end_marker='>>')
229
 
        self.assertEquals(''.join(ml), 'aaa\n222\nbbb\n')
230
 
 
 
224
        m3 = merge3.Merge3([b'aaa\n', b'bbb\n'],
 
225
                           [b'aaa\n', b'222\n', b'bbb\n'],
 
226
                           [b'aaa\n', b'222\n', b'bbb\n'])
 
227
 
 
228
        ml = m3.merge_lines(name_a=b'a',
 
229
                            name_b=b'b',
 
230
                            start_marker=b'<<',
 
231
                            mid_marker=b'--',
 
232
                            end_marker=b'>>')
 
233
        self.assertEqual(b''.join(ml), b'aaa\n222\nbbb\n')
231
234
 
232
235
    def test_insert_clash(self):
233
236
        """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'])
237
 
 
238
 
        self.assertEquals(m3.find_unconflicted(),
239
 
                          [(0, 1), (1, 2)])
240
 
 
241
 
        self.assertEquals(list(m3.find_sync_regions()),
242
 
                          [(0,1, 0,1, 0,1),
243
 
                           (1,2, 2,3, 2,3),
244
 
                           (2,2, 3,3, 3,3),])
245
 
 
246
 
        self.assertEquals(list(m3.merge_regions()),
247
 
                          [('unchanged', 0,1),
248
 
                           ('conflict', 1,1, 1,2, 1,2),
249
 
                           ('unchanged', 1,2)])
250
 
 
251
 
        self.assertEquals(list(m3.merge_groups()),
252
 
                          [('unchanged', ['aaa\n']),
253
 
                           ('conflict', [], ['111\n'], ['222\n']),
254
 
                           ('unchanged', ['bbb\n']),
255
 
                           ])
256
 
 
257
 
        ml = m3.merge_lines(name_a='a',
258
 
                            name_b='b',
259
 
                            start_marker='<<',
260
 
                            mid_marker='--',
261
 
                            end_marker='>>')
262
 
        self.assertEquals(''.join(ml),
263
 
'''aaa
 
237
        m3 = merge3.Merge3([b'aaa\n', b'bbb\n'],
 
238
                           [b'aaa\n', b'111\n', b'bbb\n'],
 
239
                           [b'aaa\n', b'222\n', b'bbb\n'])
 
240
 
 
241
        self.assertEqual(m3.find_unconflicted(),
 
242
                         [(0, 1), (1, 2)])
 
243
 
 
244
        self.assertEqual(list(m3.find_sync_regions()),
 
245
                         [(0, 1, 0, 1, 0, 1),
 
246
                          (1, 2, 2, 3, 2, 3),
 
247
                          (2, 2, 3, 3, 3, 3), ])
 
248
 
 
249
        self.assertEqual(list(m3.merge_regions()),
 
250
                         [('unchanged', 0, 1),
 
251
                          ('conflict', 1, 1, 1, 2, 1, 2),
 
252
                          ('unchanged', 1, 2)])
 
253
 
 
254
        self.assertEqual(list(m3.merge_groups()),
 
255
                         [('unchanged', [b'aaa\n']),
 
256
                          ('conflict', [], [b'111\n'], [b'222\n']),
 
257
                          ('unchanged', [b'bbb\n']),
 
258
                          ])
 
259
 
 
260
        ml = m3.merge_lines(name_a=b'a',
 
261
                            name_b=b'b',
 
262
                            start_marker=b'<<',
 
263
                            mid_marker=b'--',
 
264
                            end_marker=b'>>')
 
265
        self.assertEqual(b''.join(ml),
 
266
                         b'''aaa
264
267
<< a
265
268
111
266
269
--
271
274
 
272
275
    def test_replace_clash(self):
273
276
        """Both try to insert lines in the same place."""
274
 
        m3 = merge3.Merge3(['aaa', '000', 'bbb'],
275
 
                           ['aaa', '111', 'bbb'],
276
 
                           ['aaa', '222', 'bbb'])
277
 
 
278
 
        self.assertEquals(m3.find_unconflicted(),
279
 
                          [(0, 1), (2, 3)])
280
 
 
281
 
        self.assertEquals(list(m3.find_sync_regions()),
282
 
                          [(0,1, 0,1, 0,1),
283
 
                           (2,3, 2,3, 2,3),
284
 
                           (3,3, 3,3, 3,3),])
 
277
        m3 = merge3.Merge3([b'aaa', b'000', b'bbb'],
 
278
                           [b'aaa', b'111', b'bbb'],
 
279
                           [b'aaa', b'222', b'bbb'])
 
280
 
 
281
        self.assertEqual(m3.find_unconflicted(),
 
282
                         [(0, 1), (2, 3)])
 
283
 
 
284
        self.assertEqual(list(m3.find_sync_regions()),
 
285
                         [(0, 1, 0, 1, 0, 1),
 
286
                          (2, 3, 2, 3, 2, 3),
 
287
                          (3, 3, 3, 3, 3, 3), ])
285
288
 
286
289
    def test_replace_multi(self):
287
290
        """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'])
291
 
 
292
 
        self.assertEquals(m3.find_unconflicted(),
293
 
                          [(0, 1), (3, 4)])
294
 
 
295
 
 
296
 
        self.assertEquals(list(m3.find_sync_regions()),
297
 
                          [(0,1, 0,1, 0,1),
298
 
                           (3,4, 4,5, 5,6),
299
 
                           (4,4, 5,5, 6,6),])
 
291
        m3 = merge3.Merge3([b'aaa', b'000', b'000', b'bbb'],
 
292
                           [b'aaa', b'111', b'111', b'111', b'bbb'],
 
293
                           [b'aaa', b'222', b'222', b'222', b'222', b'bbb'])
 
294
 
 
295
        self.assertEqual(m3.find_unconflicted(),
 
296
                         [(0, 1), (3, 4)])
 
297
 
 
298
        self.assertEqual(list(m3.find_sync_regions()),
 
299
                         [(0, 1, 0, 1, 0, 1),
 
300
                          (3, 4, 4, 5, 5, 6),
 
301
                          (4, 4, 5, 5, 6, 6), ])
300
302
 
301
303
    def test_merge_poem(self):
302
304
        """Test case from diff3 manual"""
303
305
        m3 = merge3.Merge3(TZU, LAO, TAO)
304
 
        ml = list(m3.merge_lines('LAO', 'TAO'))
 
306
        ml = list(m3.merge_lines(b'LAO', b'TAO'))
305
307
        self.log('merge result:')
306
 
        self.log(''.join(ml))
307
 
        self.assertEquals(ml, MERGED_RESULT)
 
308
        self.log(b''.join(ml))
 
309
        self.assertEqual(ml, MERGED_RESULT)
308
310
 
309
311
    def test_minimal_conflicts_common(self):
310
312
        """Reprocessing"""
311
 
        base_text = ("a\n" * 20).splitlines(True)
312
 
        this_text = ("a\n"*10+"b\n" * 10).splitlines(True)
313
 
        other_text = ("a\n"*10+"c\n"+"b\n" * 8 + "c\n").splitlines(True)
 
313
        base_text = (b"a\n" * 20).splitlines(True)
 
314
        this_text = (b"a\n" * 10 + b"b\n" * 10).splitlines(True)
 
315
        other_text = (b"a\n" * 10 + b"c\n" + b"b\n" *
 
316
                      8 + b"c\n").splitlines(True)
314
317
        m3 = merge3.Merge3(base_text, other_text, this_text)
315
 
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
316
 
        merged_text = "".join(list(m_lines))
317
 
        optimal_text = ("a\n" * 10 + "<<<<<<< OTHER\nc\n"
318
 
            + 8* "b\n" + "c\n=======\n"
319
 
            + 10*"b\n" + ">>>>>>> THIS\n")
 
318
        m_lines = m3.merge_lines(b'OTHER', b'THIS', reprocess=True)
 
319
        merged_text = b"".join(list(m_lines))
 
320
        optimal_text = (b"a\n" * 10 + b"<<<<<<< OTHER\nc\n"
 
321
                        + 8 * b"b\n" + b"c\n=======\n"
 
322
                        + 10 * b"b\n" + b">>>>>>> THIS\n")
320
323
        self.assertEqualDiff(optimal_text, merged_text)
321
324
 
322
325
    def test_minimal_conflicts_unique(self):
323
326
        def add_newline(s):
324
327
            """Add a newline to each entry in the string"""
325
 
            return [(x+'\n') for x in s]
 
328
            return [(int2byte(x) + b'\n') for x in bytearray(s)]
326
329
 
327
 
        base_text = add_newline("abcdefghijklm")
328
 
        this_text = add_newline("abcdefghijklmNOPQRSTUVWXYZ")
329
 
        other_text = add_newline("abcdefghijklm1OPQRSTUVWXY2")
 
330
        base_text = add_newline(b"abcdefghijklm")
 
331
        this_text = add_newline(b"abcdefghijklmNOPQRSTUVWXYZ")
 
332
        other_text = add_newline(b"abcdefghijklm1OPQRSTUVWXY2")
330
333
        m3 = merge3.Merge3(base_text, other_text, this_text)
331
 
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
332
 
        merged_text = "".join(list(m_lines))
333
 
        optimal_text = ''.join(add_newline("abcdefghijklm")
334
 
            + ["<<<<<<< OTHER\n1\n=======\nN\n>>>>>>> THIS\n"]
335
 
            + add_newline('OPQRSTUVWXY')
336
 
            + ["<<<<<<< OTHER\n2\n=======\nZ\n>>>>>>> THIS\n"]
337
 
            )
 
334
        m_lines = m3.merge_lines(b'OTHER', b'THIS', reprocess=True)
 
335
        merged_text = b"".join(list(m_lines))
 
336
        optimal_text = b''.join(add_newline(b"abcdefghijklm")
 
337
                                + [b"<<<<<<< OTHER\n1\n=======\nN\n>>>>>>> THIS\n"]
 
338
                                + add_newline(b'OPQRSTUVWXY')
 
339
                                + [b"<<<<<<< OTHER\n2\n=======\nZ\n>>>>>>> THIS\n"]
 
340
                                )
338
341
        self.assertEqualDiff(optimal_text, merged_text)
339
342
 
340
343
    def test_minimal_conflicts_nonunique(self):
341
344
        def add_newline(s):
342
345
            """Add a newline to each entry in the string"""
343
 
            return [(x+'\n') for x in s]
 
346
            return [(int2byte(x) + b'\n') for x in bytearray(s)]
344
347
 
345
 
        base_text = add_newline("abacddefgghij")
346
 
        this_text = add_newline("abacddefgghijkalmontfprz")
347
 
        other_text = add_newline("abacddefgghijknlmontfprd")
 
348
        base_text = add_newline(b"abacddefgghij")
 
349
        this_text = add_newline(b"abacddefgghijkalmontfprz")
 
350
        other_text = add_newline(b"abacddefgghijknlmontfprd")
348
351
        m3 = merge3.Merge3(base_text, other_text, this_text)
349
 
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
350
 
        merged_text = "".join(list(m_lines))
351
 
        optimal_text = ''.join(add_newline("abacddefgghijk")
352
 
            + ["<<<<<<< OTHER\nn\n=======\na\n>>>>>>> THIS\n"]
353
 
            + add_newline('lmontfpr')
354
 
            + ["<<<<<<< OTHER\nd\n=======\nz\n>>>>>>> THIS\n"]
355
 
            )
 
352
        m_lines = m3.merge_lines(b'OTHER', b'THIS', reprocess=True)
 
353
        merged_text = b"".join(list(m_lines))
 
354
        optimal_text = b''.join(add_newline(b"abacddefgghijk")
 
355
                                + [b"<<<<<<< OTHER\nn\n=======\na\n>>>>>>> THIS\n"]
 
356
                                + add_newline(b'lmontfpr')
 
357
                                + [b"<<<<<<< OTHER\nd\n=======\nz\n>>>>>>> THIS\n"]
 
358
                                )
356
359
        self.assertEqualDiff(optimal_text, merged_text)
357
360
 
358
361
    def test_reprocess_and_base(self):
359
362
        """Reprocessing and showing base breaks correctly"""
360
 
        base_text = ("a\n" * 20).splitlines(True)
361
 
        this_text = ("a\n"*10+"b\n" * 10).splitlines(True)
362
 
        other_text = ("a\n"*10+"c\n"+"b\n" * 8 + "c\n").splitlines(True)
 
363
        base_text = (b"a\n" * 20).splitlines(True)
 
364
        this_text = (b"a\n" * 10 + b"b\n" * 10).splitlines(True)
 
365
        other_text = (b"a\n" * 10 + b"c\n" + b"b\n" *
 
366
                      8 + b"c\n").splitlines(True)
363
367
        m3 = merge3.Merge3(base_text, other_text, this_text)
364
 
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True,
365
 
                                 base_marker='|||||||')
366
 
        self.assertRaises(CantReprocessAndShowBase, list, m_lines)
 
368
        m_lines = m3.merge_lines(b'OTHER', b'THIS', reprocess=True,
 
369
                                 base_marker=b'|||||||')
 
370
        self.assertRaises(merge3.CantReprocessAndShowBase, list, m_lines)
367
371
 
368
372
    def test_binary(self):
369
 
        self.assertRaises(BinaryFile, merge3.Merge3, ['\x00'], ['a'], ['b'])
 
373
        self.assertRaises(BinaryFile, merge3.Merge3, [b'\x00'], [b'a'], [b'b'])
370
374
 
371
375
    def test_dos_text(self):
372
 
        base_text = 'a\r\n'
373
 
        this_text = 'b\r\n'
374
 
        other_text = 'c\r\n'
 
376
        base_text = b'a\r\n'
 
377
        this_text = b'b\r\n'
 
378
        other_text = b'c\r\n'
375
379
        m3 = merge3.Merge3(base_text.splitlines(True),
376
380
                           other_text.splitlines(True),
377
381
                           this_text.splitlines(True))
378
 
        m_lines = m3.merge_lines('OTHER', 'THIS')
379
 
        self.assertEqual('<<<<<<< OTHER\r\nc\r\n=======\r\nb\r\n'
380
 
            '>>>>>>> THIS\r\n'.splitlines(True), list(m_lines))
 
382
        m_lines = m3.merge_lines(b'OTHER', b'THIS')
 
383
        self.assertEqual(b'<<<<<<< OTHER\r\nc\r\n=======\r\nb\r\n'
 
384
                         b'>>>>>>> THIS\r\n'.splitlines(True), list(m_lines))
381
385
 
382
386
    def test_mac_text(self):
383
 
        base_text = 'a\r'
384
 
        this_text = 'b\r'
385
 
        other_text = 'c\r'
 
387
        base_text = b'a\r'
 
388
        this_text = b'b\r'
 
389
        other_text = b'c\r'
386
390
        m3 = merge3.Merge3(base_text.splitlines(True),
387
391
                           other_text.splitlines(True),
388
392
                           this_text.splitlines(True))
389
 
        m_lines = m3.merge_lines('OTHER', 'THIS')
390
 
        self.assertEqual('<<<<<<< OTHER\rc\r=======\rb\r'
391
 
            '>>>>>>> THIS\r'.splitlines(True), list(m_lines))
 
393
        m_lines = m3.merge_lines(b'OTHER', b'THIS')
 
394
        self.assertEqual(b'<<<<<<< OTHER\rc\r=======\rb\r'
 
395
                         b'>>>>>>> THIS\r'.splitlines(True), list(m_lines))
392
396
 
393
397
    def test_merge3_cherrypick(self):
394
 
        base_text = "a\nb\n"
395
 
        this_text = "a\n"
396
 
        other_text = "a\nb\nc\n"
 
398
        base_text = b"a\nb\n"
 
399
        this_text = b"a\n"
 
400
        other_text = b"a\nb\nc\n"
397
401
        # When cherrypicking, lines in base are not part of the conflict
398
402
        m3 = merge3.Merge3(base_text.splitlines(True),
399
403
                           this_text.splitlines(True),
400
404
                           other_text.splitlines(True), is_cherrypick=True)
401
405
        m_lines = m3.merge_lines()
402
 
        self.assertEqualDiff('a\n<<<<<<<\n=======\nc\n>>>>>>>\n',
403
 
                             ''.join(m_lines))
 
406
        self.assertEqualDiff(b'a\n<<<<<<<\n=======\nc\n>>>>>>>\n',
 
407
                             b''.join(m_lines))
404
408
 
405
409
        # This is not symmetric
406
410
        m3 = merge3.Merge3(base_text.splitlines(True),
407
411
                           other_text.splitlines(True),
408
412
                           this_text.splitlines(True), is_cherrypick=True)
409
413
        m_lines = m3.merge_lines()
410
 
        self.assertEqualDiff('a\n<<<<<<<\nb\nc\n=======\n>>>>>>>\n',
411
 
                             ''.join(m_lines))
 
414
        self.assertEqualDiff(b'a\n<<<<<<<\nb\nc\n=======\n>>>>>>>\n',
 
415
                             b''.join(m_lines))
412
416
 
413
417
    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'
 
418
        base_text = b'a\nb\nc\nd\ne\n'
 
419
        this_text = b'a\nb\nq\n'
 
420
        other_text = b'a\nb\nc\nd\nf\ne\ng\n'
417
421
        # When cherrypicking, lines in base are not part of the conflict
418
422
        m3 = merge3.Merge3(base_text.splitlines(True),
419
423
                           this_text.splitlines(True),
420
424
                           other_text.splitlines(True), is_cherrypick=True)
421
425
        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))
 
426
        self.assertEqualDiff(b'a\n'
 
427
                             b'b\n'
 
428
                             b'<<<<<<<\n'
 
429
                             b'q\n'
 
430
                             b'=======\n'
 
431
                             b'f\n'
 
432
                             b'>>>>>>>\n'
 
433
                             b'<<<<<<<\n'
 
434
                             b'=======\n'
 
435
                             b'g\n'
 
436
                             b'>>>>>>>\n',
 
437
                             b''.join(m_lines))
434
438
 
435
439
    def test_allow_objects(self):
436
440
        """Objects other than strs may be used with Merge3 when
437
441
        allow_objects=True.
438
 
        
 
442
 
439
443
        merge_groups and merge_regions work with non-str input.  Methods that
440
444
        return lines like merge_lines fail.
441
445
        """
442
 
        base = [(x,x) for x in 'abcde']
443
 
        a = [(x,x) for x in 'abcdef']
444
 
        b = [(x,x) for x in 'Zabcde']
 
446
        base = [(x, x) for x in 'abcde']
 
447
        a = [(x, x) for x in 'abcdef']
 
448
        b = [(x, x) for x in 'Zabcde']
445
449
        m3 = merge3.Merge3(base, a, b, allow_objects=True)
446
450
        self.assertEqual(
447
451
            [('b', 0, 1),
450
454
            list(m3.merge_regions()))
451
455
        self.assertEqual(
452
456
            [('b', [('Z', 'Z')]),
453
 
             ('unchanged', [(x,x) for x in 'abcde']),
 
457
             ('unchanged', [(x, x) for x in 'abcde']),
454
458
             ('a', [('f', 'f')])],
455
459
            list(m3.merge_groups()))
456