~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_multiparent.py

Turn completion assertions into separate methods.

Many common assertions used to be expressed as arguments to the complete
method.  This makes the checks more explicit, and the code easier to read.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007, 2009, 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
from unittest import TestCase
18
 
 
19
 
from bzrlib import (
20
 
    multiparent,
21
 
    patiencediff,
22
 
    tests,
23
 
    )
24
 
 
25
 
 
26
 
LINES_1 = "a\nb\nc\nd\ne\n".splitlines(True)
27
 
LINES_2 = "a\nc\nd\ne\n".splitlines(True)
28
 
LINES_3 = "a\nb\nc\nd\n".splitlines(True)
29
 
LF_SPLIT_LINES = ['\x00\n', '\x00\r\x01\n', '\x02\r\xff']
30
 
 
31
 
 
32
 
class Mock(object):
33
 
 
34
 
    def __init__(self, **kwargs):
35
 
        self.__dict__ = kwargs
36
 
 
37
 
 
38
 
class TestMulti(TestCase):
39
 
 
40
 
    def test_compare_no_parent(self):
41
 
        diff = multiparent.MultiParent.from_lines(LINES_1)
42
 
        self.assertEqual([multiparent.NewText(LINES_1)], diff.hunks)
43
 
 
44
 
    def test_compare_one_parent(self):
45
 
        diff = multiparent.MultiParent.from_lines(LINES_1, [LINES_2])
46
 
        self.assertEqual([multiparent.ParentText(0, 0, 0, 1),
47
 
                          multiparent.NewText(['b\n']),
48
 
                          multiparent.ParentText(0, 1, 2, 3)],
49
 
                         diff.hunks)
50
 
 
51
 
        diff = multiparent.MultiParent.from_lines(LINES_2, [LINES_1])
52
 
        self.assertEqual([multiparent.ParentText(0, 0, 0, 1),
53
 
                          multiparent.ParentText(0, 2, 1, 3)],
54
 
                         diff.hunks)
55
 
 
56
 
    def test_compare_two_parents(self):
57
 
        diff = multiparent.MultiParent.from_lines(LINES_1, [LINES_2, LINES_3])
58
 
        self.assertEqual([multiparent.ParentText(1, 0, 0, 4),
59
 
                          multiparent.ParentText(0, 3, 4, 1)],
60
 
                         diff.hunks)
61
 
 
62
 
    def test_compare_two_parents_blocks(self):
63
 
        matcher = patiencediff.PatienceSequenceMatcher(None, LINES_2, LINES_1)
64
 
        blocks = matcher.get_matching_blocks()
65
 
        diff = multiparent.MultiParent.from_lines(LINES_1, [LINES_2, LINES_3],
66
 
                                                  left_blocks=blocks)
67
 
        self.assertEqual([multiparent.ParentText(1, 0, 0, 4),
68
 
                          multiparent.ParentText(0, 3, 4, 1)],
69
 
                         diff.hunks)
70
 
 
71
 
    def test_get_matching_blocks(self):
72
 
        diff = multiparent.MultiParent.from_lines(LINES_1, [LINES_2])
73
 
        self.assertEqual([(0, 0, 1), (1, 2, 3), (4, 5, 0)],
74
 
                         list(diff.get_matching_blocks(0, len(LINES_2))))
75
 
 
76
 
        diff = multiparent.MultiParent.from_lines(LINES_2, [LINES_1])
77
 
        self.assertEqual([(0, 0, 1), (2, 1, 3), (5, 4, 0)],
78
 
                         list(diff.get_matching_blocks(0, len(LINES_1))))
79
 
 
80
 
    def test_range_iterator(self):
81
 
        diff = multiparent.MultiParent.from_lines(LINES_1, [LINES_2, LINES_3])
82
 
        diff.hunks.append(multiparent.NewText(['q\n']))
83
 
        self.assertEqual([(0, 4, 'parent', (1, 0, 4)),
84
 
                          (4, 5, 'parent', (0, 3, 4)),
85
 
                          (5, 6, 'new', ['q\n'])],
86
 
                         list(diff.range_iterator()))
87
 
 
88
 
    def test_eq(self):
89
 
        diff = multiparent.MultiParent.from_lines(LINES_1)
90
 
        diff2 = multiparent.MultiParent.from_lines(LINES_1)
91
 
        self.assertEqual(diff, diff2)
92
 
        diff3 = multiparent.MultiParent.from_lines(LINES_2)
93
 
        self.assertFalse(diff == diff3)
94
 
        self.assertFalse(diff == Mock(hunks=[multiparent.NewText(LINES_1)]))
95
 
        self.assertEqual(multiparent.MultiParent(
96
 
                         [multiparent.NewText(LINES_1),
97
 
                          multiparent.ParentText(0, 1, 2, 3)]),
98
 
                         multiparent.MultiParent(
99
 
                         [multiparent.NewText(LINES_1),
100
 
                          multiparent.ParentText(0, 1, 2, 3)]))
101
 
 
102
 
    def test_to_patch(self):
103
 
        self.assertEqual(['i 1\n', 'a\n', '\n', 'c 0 1 2 3\n'],
104
 
            list(multiparent.MultiParent([multiparent.NewText(['a\n']),
105
 
            multiparent.ParentText(0, 1, 2, 3)]).to_patch()))
106
 
 
107
 
    def test_from_patch(self):
108
 
        self.assertEqual(multiparent.MultiParent(
109
 
            [multiparent.NewText(['a\n']),
110
 
             multiparent.ParentText(0, 1, 2, 3)]),
111
 
             multiparent.MultiParent.from_patch('i 1\na\n\nc 0 1 2 3'))
112
 
        self.assertEqual(multiparent.MultiParent(
113
 
            [multiparent.NewText(['a']),
114
 
             multiparent.ParentText(0, 1, 2, 3)]),
115
 
             multiparent.MultiParent.from_patch('i 1\na\nc 0 1 2 3\n'))
116
 
 
117
 
    def test_binary_content(self):
118
 
        patch = list(
119
 
            multiparent.MultiParent.from_lines(LF_SPLIT_LINES).to_patch())
120
 
        multiparent.MultiParent.from_patch(''.join(patch))
121
 
 
122
 
    def test_make_patch_from_binary(self):
123
 
        patch = multiparent.MultiParent.from_texts(''.join(LF_SPLIT_LINES))
124
 
        expected = multiparent.MultiParent([
125
 
            multiparent.NewText(LF_SPLIT_LINES)])
126
 
        self.assertEqual(expected, patch)
127
 
 
128
 
    def test_num_lines(self):
129
 
        mp = multiparent.MultiParent([multiparent.NewText(['a\n'])])
130
 
        self.assertEqual(1, mp.num_lines())
131
 
        mp.hunks.append(multiparent.NewText(['b\n', 'c\n']))
132
 
        self.assertEqual(3, mp.num_lines())
133
 
        mp.hunks.append(multiparent.ParentText(0, 0, 3, 2))
134
 
        self.assertEqual(5, mp.num_lines())
135
 
        mp.hunks.append(multiparent.NewText(['f\n', 'g\n']))
136
 
        self.assertEqual(7, mp.num_lines())
137
 
 
138
 
    def test_to_lines(self):
139
 
        mpdiff = multiparent.MultiParent.from_texts('a\nb\nc\n', ('b\nc\n',))
140
 
        lines = mpdiff.to_lines(('b\ne\n',))
141
 
        self.assertEqual(['a\n', 'b\n', 'e\n'], lines)
142
 
 
143
 
 
144
 
class TestNewText(TestCase):
145
 
 
146
 
    def test_eq(self):
147
 
        self.assertEqual(multiparent.NewText([]), multiparent.NewText([]))
148
 
        self.assertFalse(multiparent.NewText(['a']) ==
149
 
                         multiparent.NewText(['b']))
150
 
        self.assertFalse(multiparent.NewText(['a']) == Mock(lines=['a']))
151
 
 
152
 
    def test_to_patch(self):
153
 
        self.assertEqual(['i 0\n', '\n'],
154
 
                         list(multiparent.NewText([]).to_patch()))
155
 
        self.assertEqual(['i 1\n', 'a', '\n'],
156
 
                         list(multiparent.NewText(['a']).to_patch()))
157
 
        self.assertEqual(['i 1\n', 'a\n', '\n'],
158
 
                         list(multiparent.NewText(['a\n']).to_patch()))
159
 
 
160
 
 
161
 
class TestParentText(TestCase):
162
 
 
163
 
    def test_eq(self):
164
 
        self.assertEqual(multiparent.ParentText(1, 2, 3, 4),
165
 
                         multiparent.ParentText(1, 2, 3, 4))
166
 
        self.assertFalse(multiparent.ParentText(1, 2, 3, 4) ==
167
 
                         multiparent.ParentText(2, 2, 3, 4))
168
 
        self.assertFalse(multiparent.ParentText(1, 2, 3, 4) ==
169
 
                         Mock(parent=1, parent_pos=2, child_pos=3,
170
 
                              num_lines=4))
171
 
 
172
 
    def test_to_patch(self):
173
 
        self.assertEqual(['c 0 1 2 3\n'],
174
 
                         list(multiparent.ParentText(0, 1, 2, 3).to_patch()))
175
 
 
176
 
 
177
 
REV_A = ['a\n', 'b\n', 'c\n', 'd\n']
178
 
REV_B = ['a\n', 'c\n', 'd\n', 'e\n']
179
 
REV_C = ['a\n', 'b\n', 'e\n', 'f\n']
180
 
 
181
 
 
182
 
class TestVersionedFile(TestCase):
183
 
 
184
 
    def add_version(self, vf, text, version_id, parent_ids):
185
 
        vf.add_version([(t+'\n') for t in text], version_id, parent_ids)
186
 
 
187
 
    def make_vf(self):
188
 
        vf = multiparent.MultiMemoryVersionedFile()
189
 
        self.add_version(vf, 'abcd', 'rev-a', [])
190
 
        self.add_version(vf, 'acde', 'rev-b', [])
191
 
        self.add_version(vf, 'abef', 'rev-c', ['rev-a', 'rev-b'])
192
 
        return vf
193
 
 
194
 
    def test_add_version(self):
195
 
        vf = self.make_vf()
196
 
        self.assertEqual(REV_A, vf._lines['rev-a'])
197
 
        vf.clear_cache()
198
 
        self.assertEqual(vf._lines, {})
199
 
 
200
 
    def test_get_line_list(self):
201
 
        vf = self.make_vf()
202
 
        vf.clear_cache()
203
 
        self.assertEqual(REV_A, vf.get_line_list(['rev-a'])[0])
204
 
        self.assertEqual([REV_B, REV_C], vf.get_line_list(['rev-b', 'rev-c']))
205
 
 
206
 
    def test_reconstruct_empty(self):
207
 
        vf = multiparent.MultiMemoryVersionedFile()
208
 
        vf.add_version([], 'a', [])
209
 
        self.assertEqual([], self.reconstruct_version(vf, 'a'))
210
 
 
211
 
    @staticmethod
212
 
    def reconstruct(vf, revision_id, start, end):
213
 
        reconstructor = multiparent._Reconstructor(vf, vf._lines,
214
 
                                                   vf._parents)
215
 
        lines = []
216
 
        reconstructor._reconstruct(lines, revision_id, start, end)
217
 
        return lines
218
 
 
219
 
    @staticmethod
220
 
    def reconstruct_version(vf, revision_id):
221
 
        reconstructor = multiparent._Reconstructor(vf, vf._lines,
222
 
                                                   vf._parents)
223
 
        lines = []
224
 
        reconstructor.reconstruct_version(lines, revision_id)
225
 
        return lines
226
 
 
227
 
    def test_reconstructor(self):
228
 
        vf = self.make_vf()
229
 
        self.assertEqual(['a\n', 'b\n'], self.reconstruct(vf, 'rev-a',  0, 2))
230
 
        self.assertEqual(['c\n', 'd\n'], self.reconstruct(vf, 'rev-a',  2, 4))
231
 
        self.assertEqual(['e\n', 'f\n'], self.reconstruct(vf, 'rev-c',  2, 4))
232
 
        self.assertEqual(['a\n', 'b\n', 'e\n', 'f\n'],
233
 
                          self.reconstruct(vf, 'rev-c',  0, 4))
234
 
        self.assertEqual(['a\n', 'b\n', 'e\n', 'f\n'],
235
 
                          self.reconstruct_version(vf, 'rev-c'))
236
 
 
237
 
    def test_reordered(self):
238
 
        """Check for a corner case that requires re-starting the cursor"""
239
 
        vf = multiparent.MultiMemoryVersionedFile()
240
 
        # rev-b must have at least two hunks, so split a and b with c.
241
 
        self.add_version(vf, 'c', 'rev-a', [])
242
 
        self.add_version(vf, 'acb', 'rev-b', ['rev-a'])
243
 
        # rev-c and rev-d must each have a line from a different rev-b hunk
244
 
        self.add_version(vf, 'b', 'rev-c', ['rev-b'])
245
 
        self.add_version(vf, 'a', 'rev-d', ['rev-b'])
246
 
        # The lines from rev-c and rev-d must appear in the opposite order
247
 
        self.add_version(vf, 'ba', 'rev-e', ['rev-c', 'rev-d'])
248
 
        vf.clear_cache()
249
 
        lines = vf.get_line_list(['rev-e'])[0]
250
 
        self.assertEqual(['b\n', 'a\n'], lines)
251
 
 
252
 
 
253
 
class TestMultiVersionedFile(tests.TestCaseInTempDir):
254
 
 
255
 
    def test_save_load(self):
256
 
        vf = multiparent.MultiVersionedFile('foop')
257
 
        vf.add_version('a\nb\nc\nd'.splitlines(True), 'a', [])
258
 
        vf.add_version('a\ne\nd\n'.splitlines(True), 'b', ['a'])
259
 
        vf.save()
260
 
        newvf = multiparent.MultiVersionedFile('foop')
261
 
        newvf.load()
262
 
        self.assertEqual('a\nb\nc\nd', ''.join(newvf.get_line_list(['a'])[0]))
263
 
        self.assertEqual('a\ne\nd\n', ''.join(newvf.get_line_list(['b'])[0]))
264
 
 
265
 
    def test_filenames(self):
266
 
        vf = multiparent.MultiVersionedFile('foop')
267
 
        vf.add_version('a\nb\nc\nd'.splitlines(True), 'a', [])
268
 
        self.assertPathExists('foop.mpknit')
269
 
        self.assertPathDoesNotExist('foop.mpidx')
270
 
        vf.save()
271
 
        self.assertPathExists('foop.mpidx')
272
 
        vf.destroy()
273
 
        self.assertPathDoesNotExist('foop.mpknit')
274
 
        self.assertPathDoesNotExist('foop.mpidx')