/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 bzrlib/tests/test_multiparent.py

  • Committer: Vincent Ladeuil
  • Date: 2012-01-18 14:09:19 UTC
  • mto: This revision was merged to the branch mainline in revision 6468.
  • Revision ID: v.ladeuil+lp@free.fr-20120118140919-rlvdrhpc0nq1lbwi
Change set/remove to require a lock for the branch config files.

This means that tests (or any plugin for that matter) do not requires an
explicit lock on the branch anymore to change a single option. This also
means the optimisation becomes "opt-in" and as such won't be as
spectacular as it may be and/or harder to get right (nothing fails
anymore).

This reduces the diff by ~300 lines.

Code/tests that were updating more than one config option is still taking
a lock to at least avoid some IOs and demonstrate the benefits through
the decreased number of hpss calls.

The duplication between BranchStack and BranchOnlyStack will be removed
once the same sharing is in place for local config files, at which point
the Stack class itself may be able to host the changes.

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')