~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_versionedfile.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-03-09 06:39:13 UTC
  • mfrom: (1596.2.6 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20060309063913-6d8ce700706d0802
Merge knit performance stage 1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
93
93
 
94
94
        self.assertRaises(RevisionNotPresent,
95
95
            f.get_ancestry, ['rM', 'rX'])
 
96
 
 
97
    def test_mutate_after_finish(self):
 
98
        f = self.get_file()
 
99
        f.transaction_finished()
 
100
        self.assertRaises(errors.OutSideTransaction, f.add_lines, '', [], [])
 
101
        self.assertRaises(errors.OutSideTransaction, f.add_lines_with_ghosts, '', [], [])
 
102
        self.assertRaises(errors.OutSideTransaction, f.fix_parents, '', [])
 
103
        self.assertRaises(errors.OutSideTransaction, f.join, '')
 
104
        self.assertRaises(errors.OutSideTransaction, f.clone_text, 'base', 'bar', ['foo'])
96
105
        
97
106
    def test_clear_cache(self):
98
107
        f = self.get_file()
224
233
        """Open the versioned file from disk again."""
225
234
        raise NotImplementedError(self.reopen_file)
226
235
 
 
236
    def test_iter_lines_added_or_present_in_versions(self):
 
237
        # test that we get at least an equalset of the lines added by
 
238
        # versions in the weave 
 
239
        # the ordering here is to make a tree so that dumb searches have
 
240
        # more changes to muck up.
 
241
        vf = self.get_file()
 
242
        # add a base to get included
 
243
        vf.add_lines('base', [], ['base\n'])
 
244
        # add a ancestor to be included on one side
 
245
        vf.add_lines('lancestor', [], ['lancestor\n'])
 
246
        # add a ancestor to be included on the other side
 
247
        vf.add_lines('rancestor', ['base'], ['rancestor\n'])
 
248
        # add a child of rancestor with no eofile-nl
 
249
        vf.add_lines('child', ['rancestor'], ['base\n', 'child\n'])
 
250
        # add a child of lancestor and base to join the two roots
 
251
        vf.add_lines('otherchild',
 
252
                     ['lancestor', 'base'],
 
253
                     ['base\n', 'lancestor\n', 'otherchild\n'])
 
254
        def iter_with_versions(versions):
 
255
            # now we need to see what lines are returned, and how often.
 
256
            lines = {'base\n':0,
 
257
                     'lancestor\n':0,
 
258
                     'rancestor\n':0,
 
259
                     'child\n':0,
 
260
                     'otherchild\n':0,
 
261
                     }
 
262
            # iterate over the lines
 
263
            for line in vf.iter_lines_added_or_present_in_versions(versions):
 
264
                lines[line] += 1
 
265
            return lines
 
266
        lines = iter_with_versions(['child', 'otherchild'])
 
267
        # we must see child and otherchild
 
268
        self.assertTrue(lines['child\n'] > 0)
 
269
        self.assertTrue(lines['otherchild\n'] > 0)
 
270
        # we dont care if we got more than that.
 
271
        
 
272
        # test all lines
 
273
        lines = iter_with_versions(None)
 
274
        # all lines must be seen at least once
 
275
        self.assertTrue(lines['base\n'] > 0)
 
276
        self.assertTrue(lines['lancestor\n'] > 0)
 
277
        self.assertTrue(lines['rancestor\n'] > 0)
 
278
        self.assertTrue(lines['child\n'] > 0)
 
279
        self.assertTrue(lines['otherchild\n'] > 0)
 
280
 
 
281
    def test_fix_parents(self):
 
282
        # some versioned files allow incorrect parents to be corrected after
 
283
        # insertion - this may not fix ancestry..
 
284
        # if they do not supported, they just do not implement it.
 
285
        # we test this as an interface test to ensure that those that *do*
 
286
        # implementent it get it right.
 
287
        vf = self.get_file()
 
288
        vf.add_lines('notbase', [], [])
 
289
        vf.add_lines('base', [], [])
 
290
        try:
 
291
            vf.fix_parents('notbase', ['base'])
 
292
        except NotImplementedError:
 
293
            return
 
294
        self.assertEqual(['base'], vf.get_parents('notbase'))
 
295
        # open again, check it stuck.
 
296
        vf = self.get_file()
 
297
        self.assertEqual(['base'], vf.get_parents('notbase'))
 
298
 
 
299
    def test_fix_parents_with_ghosts(self):
 
300
        # when fixing parents, ghosts that are listed should not be ghosts
 
301
        # anymore.
 
302
        vf = self.get_file()
 
303
 
 
304
        try:
 
305
            vf.add_lines_with_ghosts('notbase', ['base', 'stillghost'], [])
 
306
        except NotImplementedError:
 
307
            return
 
308
        vf.add_lines('base', [], [])
 
309
        vf.fix_parents('notbase', ['base', 'stillghost'])
 
310
        self.assertEqual(['base'], vf.get_parents('notbase'))
 
311
        # open again, check it stuck.
 
312
        vf = self.get_file()
 
313
        self.assertEqual(['base'], vf.get_parents('notbase'))
 
314
        # and check the ghosts
 
315
        self.assertEqual(['base', 'stillghost'],
 
316
                         vf.get_parents_with_ghosts('notbase'))
 
317
 
 
318
    def test_add_lines_with_ghosts(self):
 
319
        # some versioned file formats allow lines to be added with parent
 
320
        # information that is > than that in the format. Formats that do
 
321
        # not support this need to raise NotImplementedError on the
 
322
        # add_lines_with_ghosts api.
 
323
        vf = self.get_file()
 
324
        # add a revision with ghost parents
 
325
        try:
 
326
            vf.add_lines_with_ghosts('notbase', ['base'], [])
 
327
        except NotImplementedError:
 
328
            # check the other ghost apis are also not implemented
 
329
            self.assertRaises(NotImplementedError, vf.has_ghost, 'foo')
 
330
            self.assertRaises(NotImplementedError, vf.get_ancestry_with_ghosts, ['foo'])
 
331
            self.assertRaises(NotImplementedError, vf.get_parents_with_ghosts, 'foo')
 
332
            self.assertRaises(NotImplementedError, vf.get_graph_with_ghosts)
 
333
            return
 
334
        # test key graph related apis: getncestry, _graph, get_parents
 
335
        # has_version
 
336
        # - these are ghost unaware and must not be reflect ghosts
 
337
        self.assertEqual(['notbase'], vf.get_ancestry('notbase'))
 
338
        self.assertEqual([], vf.get_parents('notbase'))
 
339
        self.assertEqual({'notbase':[]}, vf.get_graph())
 
340
        self.assertFalse(vf.has_version('base'))
 
341
        # we have _with_ghost apis to give us ghost information.
 
342
        self.assertEqual(['base', 'notbase'], vf.get_ancestry_with_ghosts(['notbase']))
 
343
        self.assertEqual(['base'], vf.get_parents_with_ghosts('notbase'))
 
344
        self.assertEqual({'notbase':['base']}, vf.get_graph_with_ghosts())
 
345
        self.assertTrue(vf.has_ghost('base'))
 
346
        # if we add something that is a ghost of another, it should correct the
 
347
        # results of the prior apis
 
348
        vf.add_lines('base', [], [])
 
349
        self.assertEqual(['base', 'notbase'], vf.get_ancestry(['notbase']))
 
350
        self.assertEqual(['base'], vf.get_parents('notbase'))
 
351
        self.assertEqual({'base':[],
 
352
                          'notbase':['base'],
 
353
                          },
 
354
                         vf.get_graph())
 
355
        self.assertTrue(vf.has_version('base'))
 
356
        # we have _with_ghost apis to give us ghost information.
 
357
        self.assertEqual(['base', 'notbase'], vf.get_ancestry_with_ghosts(['notbase']))
 
358
        self.assertEqual(['base'], vf.get_parents_with_ghosts('notbase'))
 
359
        self.assertEqual({'base':[],
 
360
                          'notbase':['base'],
 
361
                          },
 
362
                         vf.get_graph_with_ghosts())
 
363
        self.assertFalse(vf.has_ghost('base'))
 
364
 
 
365
    def test_add_lines_with_ghosts_after_normal_revs(self):
 
366
        # some versioned file formats allow lines to be added with parent
 
367
        # information that is > than that in the format. Formats that do
 
368
        # not support this need to raise NotImplementedError on the
 
369
        # add_lines_with_ghosts api.
 
370
        vf = self.get_file()
 
371
        # probe for ghost support
 
372
        try:
 
373
            vf.has_ghost('hoo')
 
374
        except NotImplementedError:
 
375
            return
 
376
        vf.add_lines_with_ghosts('base', [], ['line\n', 'line_b\n'])
 
377
        vf.add_lines_with_ghosts('references_ghost',
 
378
                                 ['base', 'a_ghost'],
 
379
                                 ['line\n', 'line_b\n', 'line_c\n'])
 
380
        origins = vf.annotate('references_ghost')
 
381
        self.assertEquals(('base', 'line\n'), origins[0])
 
382
        self.assertEquals(('base', 'line_b\n'), origins[1])
 
383
        self.assertEquals(('references_ghost', 'line_c\n'), origins[2])
 
384
 
 
385
    def test_readonly_mode(self):
 
386
        transport = get_transport(self.get_url('.'))
 
387
        factory = self.get_factory()
 
388
        vf = factory('id', transport, 0777, create=True, access_mode='w')
 
389
        vf = factory('id', transport, access_mode='r')
 
390
        self.assertRaises(errors.ReadOnlyError, vf.add_lines, 'base', [], [])
 
391
        self.assertRaises(errors.ReadOnlyError,
 
392
                          vf.add_lines_with_ghosts,
 
393
                          'base',
 
394
                          [],
 
395
                          [])
 
396
        self.assertRaises(errors.ReadOnlyError, vf.fix_parents, 'base', [])
 
397
        self.assertRaises(errors.ReadOnlyError, vf.join, 'base')
 
398
        self.assertRaises(errors.ReadOnlyError, vf.clone_text, 'base', 'bar', ['foo'])
 
399
        
227
400
 
228
401
class TestWeave(TestCaseWithTransport, VersionedFileTestMixIn):
229
402
 
273
446
                          'foo',
274
447
                          get_transport(self.get_url('.')))
275
448
 
 
449
    def get_factory(self):
 
450
        return WeaveFile
 
451
 
276
452
 
277
453
class TestKnit(TestCaseWithTransport, VersionedFileTestMixIn):
278
454
 
280
456
        return KnitVersionedFile(name, get_transport(self.get_url('.')),
281
457
                                 delta=True, create=True)
282
458
 
 
459
    def get_factory(self):
 
460
        return KnitVersionedFile
 
461
 
283
462
    def get_file_corrupted_text(self):
284
463
        knit = self.get_file()
285
464
        knit.add_lines('v1', [], ['hello\n'])
364
543
            versionedfile.InterVersionedFile.unregister_optimiser(InterString)
365
544
        # now we should get the default InterVersionedFile object again.
366
545
        self.assertGetsDefaultInterVersionedFile(dummy_a, dummy_b)
367
 
 
368