~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/testmerge3.py

Introduce --debug switch to enable some debugging code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005 by Canonical 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
 
 
17
 
 
18
 
from bzrlib.selftest import TestCaseInTempDir, TestCase
19
 
from bzrlib.merge3 import Merge3
20
 
 
21
 
def split_lines(t):
22
 
    from cStringIO import StringIO
23
 
    return StringIO(t).readlines()
24
 
 
25
 
############################################################
26
 
# test case data from the gnu diffutils manual
27
 
# common base
28
 
TZU = split_lines("""     The Nameless is the origin of Heaven and Earth;
29
 
     The named is the mother of all things.
30
 
     
31
 
     Therefore let there always be non-being,
32
 
       so we may see their subtlety,
33
 
     And let there always be being,
34
 
       so we may see their outcome.
35
 
     The two are the same,
36
 
     But after they are produced,
37
 
       they have different names.
38
 
     They both may be called deep and profound.
39
 
     Deeper and more profound,
40
 
     The door of all subtleties!
41
 
""")
42
 
 
43
 
LAO = split_lines("""     The Way that can be told of is not the eternal Way;
44
 
     The name that can be named is not the eternal name.
45
 
     The Nameless is the origin of Heaven and Earth;
46
 
     The Named is the mother of all things.
47
 
     Therefore let there always be non-being,
48
 
       so we may see their subtlety,
49
 
     And let there always be being,
50
 
       so we may see their outcome.
51
 
     The two are the same,
52
 
     But after they are produced,
53
 
       they have different names.
54
 
""")
55
 
 
56
 
 
57
 
TAO = split_lines("""     The Way that can be told of is not the eternal Way;
58
 
     The name that can be named is not the eternal name.
59
 
     The Nameless is the origin of Heaven and Earth;
60
 
     The named is the mother of all things.
61
 
     
62
 
     Therefore let there always be non-being,
63
 
       so we may see their subtlety,
64
 
     And let there always be being,
65
 
       so we may see their result.
66
 
     The two are the same,
67
 
     But after they are produced,
68
 
       they have different names.
69
 
     
70
 
       -- The Way of Lao-Tzu, tr. Wing-tsit Chan
71
 
 
72
 
""")
73
 
 
74
 
MERGED_RESULT = split_lines("""     The Way that can be told of is not the eternal Way;
75
 
     The name that can be named is not the eternal name.
76
 
     The Nameless is the origin of Heaven and Earth;
77
 
     The Named is the mother of all things.
78
 
     Therefore let there always be non-being,
79
 
       so we may see their subtlety,
80
 
     And let there always be being,
81
 
       so we may see their result.
82
 
     The two are the same,
83
 
     But after they are produced,
84
 
       they have different names.
85
 
<<<<<<< LAO
86
 
=======
87
 
     
88
 
       -- The Way of Lao-Tzu, tr. Wing-tsit Chan
89
 
 
90
 
>>>>>>> TAO
91
 
""")
92
 
 
93
 
class TestMerge3(TestCase):
94
 
 
95
 
    def test_no_changes(self):
96
 
        """No conflicts because nothing changed"""
97
 
        m3 = Merge3(['aaa', 'bbb'],
98
 
                    ['aaa', 'bbb'],
99
 
                    ['aaa', 'bbb'])
100
 
 
101
 
        self.assertEquals(m3.find_unconflicted(),
102
 
                          [(0, 2)])
103
 
 
104
 
        self.assertEquals(list(m3.find_sync_regions()),
105
 
                          [(0, 2,
106
 
                            0, 2,
107
 
                            0, 2),
108
 
                           (2,2, 2,2, 2,2)])
109
 
 
110
 
        self.assertEquals(list(m3.merge_regions()),
111
 
                          [('unchanged', 0, 2)])
112
 
 
113
 
        self.assertEquals(list(m3.merge_groups()),
114
 
                          [('unchanged', ['aaa', 'bbb'])])
115
 
 
116
 
    def test_front_insert(self):
117
 
        m3 = Merge3(['zz'],
118
 
                    ['aaa', 'bbb', 'zz'],
119
 
                    ['zz'])
120
 
 
121
 
        # todo: should use a sentinal at end as from get_matching_blocks
122
 
        # to match without zz
123
 
        self.assertEquals(list(m3.find_sync_regions()),
124
 
                          [(0,1, 2,3, 0,1),
125
 
                           (1,1, 3,3, 1,1),])
126
 
 
127
 
        self.assertEquals(list(m3.merge_regions()),
128
 
                          [('a', 0, 2),
129
 
                           ('unchanged', 0, 1)])
130
 
 
131
 
        self.assertEquals(list(m3.merge_groups()),
132
 
                          [('a', ['aaa', 'bbb']),
133
 
                           ('unchanged', ['zz'])])
134
 
        
135
 
    def test_null_insert(self):
136
 
        m3 = Merge3([],
137
 
                    ['aaa', 'bbb'],
138
 
                    [])
139
 
        # todo: should use a sentinal at end as from get_matching_blocks
140
 
        # to match without zz
141
 
        self.assertEquals(list(m3.find_sync_regions()),
142
 
                          [(0,0, 2,2, 0,0)])
143
 
 
144
 
        self.assertEquals(list(m3.merge_regions()),
145
 
                          [('a', 0, 2)])
146
 
 
147
 
        self.assertEquals(list(m3.merge_lines()),
148
 
                          ['aaa', 'bbb'])
149
 
 
150
 
    def test_no_conflicts(self):
151
 
        """No conflicts because only one side changed"""
152
 
        m3 = Merge3(['aaa', 'bbb'],
153
 
                    ['aaa', '111', 'bbb'],
154
 
                    ['aaa', 'bbb'])
155
 
 
156
 
        self.assertEquals(m3.find_unconflicted(),
157
 
                          [(0, 1), (1, 2)])
158
 
 
159
 
        self.assertEquals(list(m3.find_sync_regions()),
160
 
                          [(0,1, 0,1, 0,1),
161
 
                           (1,2, 2,3, 1,2),
162
 
                           (2,2, 3,3, 2,2),])
163
 
 
164
 
        self.assertEquals(list(m3.merge_regions()),
165
 
                          [('unchanged', 0, 1),
166
 
                           ('a', 1, 2),
167
 
                           ('unchanged', 1, 2),])
168
 
 
169
 
    def test_append_a(self):
170
 
        m3 = Merge3(['aaa\n', 'bbb\n'],
171
 
                    ['aaa\n', 'bbb\n', '222\n'],
172
 
                    ['aaa\n', 'bbb\n'])
173
 
 
174
 
        self.assertEquals(''.join(m3.merge_lines()),
175
 
                          'aaa\nbbb\n222\n')
176
 
 
177
 
    def test_append_b(self):
178
 
        m3 = Merge3(['aaa\n', 'bbb\n'],
179
 
                    ['aaa\n', 'bbb\n'],
180
 
                    ['aaa\n', 'bbb\n', '222\n'])
181
 
 
182
 
        self.assertEquals(''.join(m3.merge_lines()),
183
 
                          'aaa\nbbb\n222\n')
184
 
 
185
 
    def test_append_agreement(self):
186
 
        m3 = Merge3(['aaa\n', 'bbb\n'],
187
 
                    ['aaa\n', 'bbb\n', '222\n'],
188
 
                    ['aaa\n', 'bbb\n', '222\n'])
189
 
 
190
 
        self.assertEquals(''.join(m3.merge_lines()),
191
 
                          'aaa\nbbb\n222\n')
192
 
 
193
 
    def test_append_clash(self):
194
 
        m3 = Merge3(['aaa\n', 'bbb\n'],
195
 
                    ['aaa\n', 'bbb\n', '222\n'],
196
 
                    ['aaa\n', 'bbb\n', '333\n'])
197
 
 
198
 
        ml = m3.merge_lines(name_a='a',
199
 
                            name_b='b',
200
 
                            start_marker='<<',
201
 
                            mid_marker='--',
202
 
                            end_marker='>>')
203
 
        self.assertEquals(''.join(ml),
204
 
'''\
205
 
aaa
206
 
bbb
207
 
<< a
208
 
222
209
 
--
210
 
333
211
 
>> b
212
 
''')
213
 
 
214
 
    def test_insert_agreement(self):
215
 
        m3 = Merge3(['aaa\n', 'bbb\n'],
216
 
                    ['aaa\n', '222\n', 'bbb\n'],
217
 
                    ['aaa\n', '222\n', 'bbb\n'])
218
 
 
219
 
        ml = m3.merge_lines(name_a='a',
220
 
                            name_b='b',
221
 
                            start_marker='<<',
222
 
                            mid_marker='--',
223
 
                            end_marker='>>')
224
 
        self.assertEquals(''.join(ml), 'aaa\n222\nbbb\n')
225
 
        
226
 
 
227
 
    def test_insert_clash(self):
228
 
        """Both try to insert lines in the same place."""
229
 
        m3 = Merge3(['aaa\n', 'bbb\n'],
230
 
                    ['aaa\n', '111\n', 'bbb\n'],
231
 
                    ['aaa\n', '222\n', 'bbb\n'])
232
 
 
233
 
        self.assertEquals(m3.find_unconflicted(),
234
 
                          [(0, 1), (1, 2)])
235
 
 
236
 
        self.assertEquals(list(m3.find_sync_regions()),
237
 
                          [(0,1, 0,1, 0,1),
238
 
                           (1,2, 2,3, 2,3),
239
 
                           (2,2, 3,3, 3,3),])
240
 
 
241
 
        self.assertEquals(list(m3.merge_regions()),
242
 
                          [('unchanged', 0,1),
243
 
                           ('conflict', 1,1, 1,2, 1,2),
244
 
                           ('unchanged', 1,2)])
245
 
 
246
 
        self.assertEquals(list(m3.merge_groups()),
247
 
                          [('unchanged', ['aaa\n']),
248
 
                           ('conflict', [], ['111\n'], ['222\n']),
249
 
                           ('unchanged', ['bbb\n']),
250
 
                           ])
251
 
 
252
 
        ml = m3.merge_lines(name_a='a',
253
 
                            name_b='b',
254
 
                            start_marker='<<',
255
 
                            mid_marker='--',
256
 
                            end_marker='>>')
257
 
        self.assertEquals(''.join(ml),
258
 
'''aaa
259
 
<< a
260
 
111
261
 
--
262
 
222
263
 
>> b
264
 
bbb
265
 
''')
266
 
 
267
 
    def test_replace_clash(self):
268
 
        """Both try to insert lines in the same place."""
269
 
        m3 = Merge3(['aaa', '000', 'bbb'],
270
 
                    ['aaa', '111', 'bbb'],
271
 
                    ['aaa', '222', 'bbb'])
272
 
 
273
 
        self.assertEquals(m3.find_unconflicted(),
274
 
                          [(0, 1), (2, 3)])
275
 
 
276
 
        self.assertEquals(list(m3.find_sync_regions()),
277
 
                          [(0,1, 0,1, 0,1),
278
 
                           (2,3, 2,3, 2,3),
279
 
                           (3,3, 3,3, 3,3),])
280
 
 
281
 
    def test_replace_multi(self):
282
 
        """Replacement with regions of different size."""
283
 
        m3 = Merge3(['aaa', '000', '000', 'bbb'],
284
 
                    ['aaa', '111', '111', '111', 'bbb'],
285
 
                    ['aaa', '222', '222', '222', '222', 'bbb'])
286
 
 
287
 
        self.assertEquals(m3.find_unconflicted(),
288
 
                          [(0, 1), (3, 4)])
289
 
 
290
 
 
291
 
        self.assertEquals(list(m3.find_sync_regions()),
292
 
                          [(0,1, 0,1, 0,1),
293
 
                           (3,4, 4,5, 5,6),
294
 
                           (4,4, 5,5, 6,6),])
295
 
 
296
 
    def test_merge_poem(self):
297
 
        """Test case from diff3 manual"""
298
 
        m3 = Merge3(TZU, LAO, TAO)
299
 
        ml = list(m3.merge_lines('LAO', 'TAO'))
300
 
        self.log('merge result:')
301
 
        self.log(''.join(ml))
302
 
        self.assertEquals(ml, MERGED_RESULT)