~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_versionedfile.py

  • Committer: Robert Collins
  • Date: 2006-03-02 03:12:34 UTC
  • mto: (1594.2.4 integration)
  • mto: This revision was merged to the branch mainline in revision 1596.
  • Revision ID: robertc@robertcollins.net-20060302031234-cf6b75961f27c5df
InterVersionedFile implemented.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
# along with this program; if not, write to the Free Software
18
18
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
19
 
20
 
# Remaing to do is to figure out if get_graph should return a simple
21
 
# map, or a graph object of some kind.
22
 
 
23
20
 
24
21
import bzrlib
25
22
import bzrlib.errors as errors
33
30
from bzrlib.tests import TestCaseWithTransport
34
31
from bzrlib.trace import mutter
35
32
from bzrlib.transport.local import LocalTransport
 
33
from bzrlib.transport.memory import MemoryTransport
36
34
import bzrlib.versionedfile as versionedfile
37
35
from bzrlib.weave import WeaveFile
38
36
from bzrlib.weavefile import read_weave
104
102
        verify_file(f)
105
103
        verify_file(self.reopen_file())
106
104
 
 
105
    def test_create_empty(self):
 
106
        f = self.get_file()
 
107
        f.add_lines('0', [], ['a\n'])
 
108
        new_f = f.create_empty('t', MemoryTransport())
 
109
        # smoke test, specific types should check it is honoured correctly for
 
110
        # non type attributes
 
111
        self.assertEqual([], new_f.versions())
 
112
        self.assertTrue(isinstance(new_f, f.__class__))
 
113
 
 
114
    def test_get_graph(self):
 
115
        f = self.get_file()
 
116
        f.add_lines('v1', [], ['hello\n'])
 
117
        f.add_lines('v2', ['v1'], ['hello\n', 'world\n'])
 
118
        f.add_lines('v3', ['v2'], ['hello\n', 'cruel\n', 'world\n'])
 
119
        self.assertEqual({'v1': [],
 
120
                          'v2': ['v1'],
 
121
                          'v3': ['v2']},
 
122
                         f.get_graph())
 
123
 
107
124
    def test_get_parents(self):
108
125
        f = self.get_file()
109
126
        f.add_lines('r0', [], ['a\n', 'b\n'])
156
173
        self.assertEqual('hello\n', w.get_text('v1'))
157
174
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
158
175
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
159
 
        self.assertRaises(errors.WeaveInvalidChecksum, list, w.get_iter('v2'))
160
176
        self.assertRaises(errors.WeaveInvalidChecksum, w.check)
161
177
 
162
178
        w = self.get_file_corrupted_checksum()
164
180
        self.assertEqual('hello\n', w.get_text('v1'))
165
181
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
166
182
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
167
 
        self.assertRaises(errors.WeaveInvalidChecksum, list, w.get_iter('v2'))
168
183
        self.assertRaises(errors.WeaveInvalidChecksum, w.check)
169
184
 
170
185
    def get_file_corrupted_text(self):
175
190
        """Open the versioned file from disk again."""
176
191
        raise NotImplementedError(self.reopen_file)
177
192
 
178
 
    def test_join_add_parents(self):
179
 
        """Reweave inserting new parents
180
 
        
181
 
        The new version must have the right parent list and must identify
182
 
        lines originating in another parent.
183
 
        """
184
 
        w1 = self.get_file('w1')
185
 
        w2 = self.get_file('w2')
186
 
        w1.add_lines('v-1', [], ['line 1\n'])
187
 
        w2.add_lines('v-2', [], ['line 2\n'])
188
 
        w1.add_lines('v-3', ['v-1'], ['line 1\n'])
189
 
        w2.add_lines('v-3', ['v-2'], ['line 1\n'])
190
 
        w1.join(w2)
191
 
        self.assertEqual(sorted(w1.names()),
192
 
                         'v-1 v-2 v-3'.split())
193
 
        self.assertEqualDiff(w1.get_text('v-3'),
194
 
                'line 1\n')
195
 
        self.assertEqual(sorted(w1.parent_names('v-3')),
196
 
                ['v-1', 'v-2'])
197
 
        ann = list(w1.annotate('v-3'))
198
 
        self.assertEqual(len(ann), 1)
199
 
        self.assertEqual(ann[0][0], 'v-1')
200
 
        self.assertEqual(ann[0][1], 'line 1\n')
201
 
        
202
 
    def build_weave1(self):
203
 
        weave1 = self.get_file()
204
 
        self.lines1 = ['hello\n']
205
 
        self.lines3 = ['hello\n', 'cruel\n', 'world\n']
206
 
        weave1.add_lines('v1', [], self.lines1)
207
 
        weave1.add_lines('v2', ['v1'], ['hello\n', 'world\n'])
208
 
        weave1.add_lines('v3', ['v2'], self.lines3)
209
 
        return weave1
210
 
        
211
 
    def test_join_with_empty(self):
212
 
        """Reweave adding empty weave"""
213
 
        wb = self.get_file('b')
214
 
        w1 = self.build_weave1()
215
 
        w1.join(wb)
216
 
        self.assertEqual(sorted(w1.iter_names()), ['v1', 'v2', 'v3'])
217
 
        self.assertEqual(w1.get_lines('v1'), ['hello\n'])
218
 
        self.assertEqual([], w1.get_parents('v1'))
219
 
        self.assertEqual(w1.get_lines('v2'), ['hello\n', 'world\n'])
220
 
        self.assertEqual(['v1'], w1.get_parents('v2'))
221
 
        self.assertEqual(w1.get_lines('v3'), ['hello\n', 'cruel\n', 'world\n'])
222
 
        self.assertEqual(['v2'], w1.get_parents('v3'))
223
 
 
224
 
    def test_join_with_ghosts_raises_parent_mismatch(self):
225
 
        """Join combined parent lists"""
226
 
        wa = self.build_weave1()
227
 
        wb = self.get_file('b')
228
 
        wb.add_lines('x1', [], ['line from x1\n'])
229
 
        wb.add_lines('v1', [], ['hello\n'])
230
 
        wb.add_lines('v2', ['v1', 'x1'], ['hello\n', 'world\n'])
231
 
        wa.join(wb)
232
 
        self.assertEqual(['v1','x1'], wa.get_parents('v2'))
233
 
 
234
 
    def test_join_with_ghosts(self):
235
 
        """Join that inserts parents of an existing revision.
236
 
 
237
 
        This can happen when merging from another branch who
238
 
        knows about revisions the destination does not.  In 
239
 
        this test the second weave knows of an additional parent of 
240
 
        v2.  Any revisions which are in common still have to have the 
241
 
        same text.
242
 
        """
243
 
        w1 = self.build_weave1()
244
 
        wb = self.get_file('b')
245
 
        wb.add_lines('x1', [], ['line from x1\n'])
246
 
        wb.add_lines('v1', [], ['hello\n'])
247
 
        wb.add_lines('v2', ['v1', 'x1'], ['hello\n', 'world\n'])
248
 
        w1.join(wb)
249
 
        eq = self.assertEquals
250
 
        eq(sorted(w1.iter_names()), ['v1', 'v2', 'v3', 'x1',])
251
 
        eq(w1.get_text('x1'), 'line from x1\n')
252
 
        eq(w1.get_lines('v2'), ['hello\n', 'world\n'])
253
 
        eq(w1.parent_names('v2'), ['v1', 'x1'])
254
 
 
255
 
    def build_empty_weave(self, name, *pattern):
256
 
        w = self.get_file(name)
257
 
        for version, parents in pattern:
258
 
            w.add_lines(version, parents, [])
259
 
        return w
260
 
 
261
 
    def test_join_reorder(self):
262
 
        """Reweave requiring reordering of versions.
263
 
 
264
 
        Weaves must be stored such that parents come before children.  When
265
 
        reweaving, we may add new parents to some children, but it is required
266
 
        that there must be *some* valid order that can be found, otherwise the
267
 
        ancestries are contradictory.  (For the specific case of inserting
268
 
        ghost revisions there will be no disagreement, only partial knowledge
269
 
        of the history.)
270
 
 
271
 
        Note that the weaves are only partially ordered: when there are two
272
 
        versions where neither is an ancestor of the other the order in which
273
 
        they occur is unconstrained.  When we join those versions into
274
 
        another weave, they may become more constrained and it may be
275
 
        necessary to change their order.
276
 
 
277
 
        One simple case of this is 
278
 
 
279
 
        w1: (c[], a[], b[a])
280
 
        w2: (b[], c[b], a[])
281
 
        
282
 
        We need to recognize that the final weave must show the ordering
283
 
        a[], b[a], c[b].  The version that must be first in the result is 
284
 
        not first in either of the input weaves.
285
 
        """
286
 
        w1 = self.build_empty_weave('1', ('c', []), ('a', []), ('b', ['a']))
287
 
        w2 = self.build_empty_weave('2', ('b', []), ('c', ['b']), ('a', []))
288
 
        w1.join(w2)
289
 
        self.assertEqual([], w1.get_parents('a'))
290
 
        self.assertEqual(['a'], w1.get_parents('b'))
291
 
        self.assertEqual(['b'], w1.get_parents('c'))
292
193
 
293
194
class TestWeave(TestCaseWithTransport, VersionedFileTestMixIn):
294
195
 
297
198
 
298
199
    def get_file_corrupted_text(self):
299
200
        w = WeaveFile('foo', LocalTransport('.'))
300
 
        w.add('v1', [], ['hello\n'])
301
 
        w.add('v2', ['v1'], ['hello\n', 'there\n'])
 
201
        w.add_lines('v1', [], ['hello\n'])
 
202
        w.add_lines('v2', ['v1'], ['hello\n', 'there\n'])
302
203
        
303
204
        # We are going to invasively corrupt the text
304
205
        # Make sure the internals of weave are the same