~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_inv.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-07-20 08:56:45 UTC
  • mfrom: (4526.9.23 apply-inventory-delta)
  • Revision ID: pqm@pqm.ubuntu.com-20090720085645-54mtgybxua0yx6hw
(robertc) Add checks for inventory deltas which try to ensure that
        deltas that are not an exact fit are not applied. (Robert
        Collins, bug 397705, bug 367633)

Show diffs side-by-side

added added

removed removed

Lines of Context:
54
54
            'apply_delta':apply_inventory_Repository_add_inventory_by_delta,
55
55
            'format':format}))
56
56
    for format in workingtree_formats():
57
 
        scenarios.append((str(format.__class__.__name__), {
 
57
        scenarios.append(
 
58
            (str(format.__class__.__name__) + ".update_basis_by_delta", {
58
59
            'apply_delta':apply_inventory_WT_basis,
59
60
            'format':format}))
 
61
        scenarios.append(
 
62
            (str(format.__class__.__name__) + ".apply_inventory_delta", {
 
63
            'apply_delta':apply_inventory_WT,
 
64
            'format':format}))
60
65
    return multiply_tests(to_adapt, scenarios, result)
61
66
 
62
67
 
71
76
    return basis
72
77
 
73
78
 
 
79
def apply_inventory_WT(self, basis, delta):
 
80
    """Apply delta to basis and return the result.
 
81
 
 
82
    This sets the tree state to be basis, and then calls apply_inventory_delta.
 
83
    
 
84
    :param basis: An inventory to be used as the basis.
 
85
    :param delta: The inventory delta to apply:
 
86
    :return: An inventory resulting from the application.
 
87
    """
 
88
    control = self.make_bzrdir('tree', format=self.format._matchingbzrdir)
 
89
    control.create_repository()
 
90
    control.create_branch()
 
91
    tree = self.format.initialize(control)
 
92
    tree.lock_write()
 
93
    try:
 
94
        tree._write_inventory(basis)
 
95
    finally:
 
96
        tree.unlock()
 
97
    # Fresh object, reads disk again.
 
98
    tree = tree.bzrdir.open_workingtree()
 
99
    tree.lock_write()
 
100
    try:
 
101
        tree.apply_inventory_delta(delta)
 
102
    finally:
 
103
        tree.unlock()
 
104
    # reload tree - ensure we get what was written.
 
105
    tree = tree.bzrdir.open_workingtree()
 
106
    tree.lock_read()
 
107
    self.addCleanup(tree.unlock)
 
108
    # One could add 'tree._validate' here but that would cause 'early' failues 
 
109
    # as far as higher level code is concerned. Possibly adding an
 
110
    # expect_fail parameter to this function and if that is False then do a
 
111
    # validate call.
 
112
    return tree.inventory
 
113
 
 
114
 
74
115
def apply_inventory_WT_basis(self, basis, delta):
75
116
    """Apply delta to basis and return the result.
76
117
 
118
159
        paths = {}
119
160
        parents = set()
120
161
        for old, new, id, entry in delta:
121
 
            if entry is None:
 
162
            if None in (new, entry):
122
163
                continue
123
164
            paths[new] = (entry.file_id, entry.kind)
124
165
            parents.add(osutils.dirname(new))
236
277
        inv2 = self.get_empty_inventory(inv)
237
278
        self.assertEqual([], inv2._make_delta(inv))
238
279
 
 
280
    def test_None_file_id(self):
 
281
        inv = self.get_empty_inventory()
 
282
        dir1 = inventory.InventoryDirectory(None, 'dir1', inv.root.file_id)
 
283
        dir1.revision = 'result'
 
284
        delta = [(None, u'dir1', None, dir1)]
 
285
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
286
            inv, delta)
 
287
 
 
288
    def test_unicode_file_id(self):
 
289
        inv = self.get_empty_inventory()
 
290
        dir1 = inventory.InventoryDirectory(u'dirid', 'dir1', inv.root.file_id)
 
291
        dir1.revision = 'result'
 
292
        delta = [(None, u'dir1', dir1.file_id, dir1)]
 
293
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
294
            inv, delta)
 
295
 
239
296
    def test_repeated_file_id(self):
240
297
        inv = self.get_empty_inventory()
241
298
        file1 = inventory.InventoryFile('id', 'path1', inv.root.file_id)
296
353
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
297
354
            inv, delta)
298
355
 
 
356
    def test_mismatched_new_path_entry_None(self):
 
357
        inv = self.get_empty_inventory()
 
358
        delta = [(None, u'path', 'id', None)]
 
359
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
360
            inv, delta)
 
361
 
 
362
    def test_mismatched_new_path_None_entry(self):
 
363
        inv = self.get_empty_inventory()
 
364
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
365
        file1.revision = 'result'
 
366
        file1.text_size = 0
 
367
        file1.text_sha1 = ""
 
368
        delta = [(u"path", None, 'id1', file1)]
 
369
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
370
            inv, delta)
 
371
 
299
372
    def test_parent_is_not_directory(self):
300
373
        inv = self.get_empty_inventory()
301
374
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
321
394
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
322
395
            inv, delta)
323
396
 
 
397
    def test_new_parent_path_has_wrong_id(self):
 
398
        inv = self.get_empty_inventory()
 
399
        parent1 = inventory.InventoryDirectory('p-1', 'dir', inv.root.file_id)
 
400
        parent1.revision = 'result'
 
401
        parent2 = inventory.InventoryDirectory('p-2', 'dir2', inv.root.file_id)
 
402
        parent2.revision = 'result'
 
403
        file1 = inventory.InventoryFile('id', 'path', 'p-2')
 
404
        file1.revision = 'result'
 
405
        file1.text_size = 0
 
406
        file1.text_sha1 = ""
 
407
        inv.add(parent1)
 
408
        inv.add(parent2)
 
409
        # This delta claims that file1 is at dir/path, but actually its at
 
410
        # dir2/path if you follow the inventory parent structure.
 
411
        delta = [(None, u'dir/path', 'id', file1)]
 
412
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
413
            inv, delta)
 
414
 
 
415
    def test_old_parent_path_is_wrong(self):
 
416
        inv = self.get_empty_inventory()
 
417
        parent1 = inventory.InventoryDirectory('p-1', 'dir', inv.root.file_id)
 
418
        parent1.revision = 'result'
 
419
        parent2 = inventory.InventoryDirectory('p-2', 'dir2', inv.root.file_id)
 
420
        parent2.revision = 'result'
 
421
        file1 = inventory.InventoryFile('id', 'path', 'p-2')
 
422
        file1.revision = 'result'
 
423
        file1.text_size = 0
 
424
        file1.text_sha1 = ""
 
425
        inv.add(parent1)
 
426
        inv.add(parent2)
 
427
        inv.add(file1)
 
428
        # This delta claims that file1 was at dir/path, but actually it was at
 
429
        # dir2/path if you follow the inventory parent structure.
 
430
        delta = [(u'dir/path', None, 'id', None)]
 
431
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
432
            inv, delta)
 
433
 
 
434
    def test_old_parent_path_is_for_other_id(self):
 
435
        inv = self.get_empty_inventory()
 
436
        parent1 = inventory.InventoryDirectory('p-1', 'dir', inv.root.file_id)
 
437
        parent1.revision = 'result'
 
438
        parent2 = inventory.InventoryDirectory('p-2', 'dir2', inv.root.file_id)
 
439
        parent2.revision = 'result'
 
440
        file1 = inventory.InventoryFile('id', 'path', 'p-2')
 
441
        file1.revision = 'result'
 
442
        file1.text_size = 0
 
443
        file1.text_sha1 = ""
 
444
        file2 = inventory.InventoryFile('id2', 'path', 'p-1')
 
445
        file2.revision = 'result'
 
446
        file2.text_size = 0
 
447
        file2.text_sha1 = ""
 
448
        inv.add(parent1)
 
449
        inv.add(parent2)
 
450
        inv.add(file1)
 
451
        inv.add(file2)
 
452
        # This delta claims that file1 was at dir/path, but actually it was at
 
453
        # dir2/path if you follow the inventory parent structure. At dir/path
 
454
        # is another entry we should not delete.
 
455
        delta = [(u'dir/path', None, 'id', None)]
 
456
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
457
            inv, delta)
 
458
 
 
459
    def test_add_existing_id_new_path(self):
 
460
        inv = self.get_empty_inventory()
 
461
        parent1 = inventory.InventoryDirectory('p-1', 'dir1', inv.root.file_id)
 
462
        parent1.revision = 'result'
 
463
        parent2 = inventory.InventoryDirectory('p-1', 'dir2', inv.root.file_id)
 
464
        parent2.revision = 'result'
 
465
        inv.add(parent1)
 
466
        delta = [(None, u'dir2', 'p-1', parent2)]
 
467
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
468
            inv, delta)
 
469
 
 
470
    def test_add_new_id_existing_path(self):
 
471
        inv = self.get_empty_inventory()
 
472
        parent1 = inventory.InventoryDirectory('p-1', 'dir1', inv.root.file_id)
 
473
        parent1.revision = 'result'
 
474
        parent2 = inventory.InventoryDirectory('p-2', 'dir1', inv.root.file_id)
 
475
        parent2.revision = 'result'
 
476
        inv.add(parent1)
 
477
        delta = [(None, u'dir1', 'p-2', parent2)]
 
478
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
479
            inv, delta)
 
480
 
 
481
    def test_remove_dir_leaving_dangling_child(self):
 
482
        inv = self.get_empty_inventory()
 
483
        dir1 = inventory.InventoryDirectory('p-1', 'dir1', inv.root.file_id)
 
484
        dir1.revision = 'result'
 
485
        dir2 = inventory.InventoryDirectory('p-2', 'child1', 'p-1')
 
486
        dir2.revision = 'result'
 
487
        dir3 = inventory.InventoryDirectory('p-3', 'child2', 'p-1')
 
488
        dir3.revision = 'result'
 
489
        inv.add(dir1)
 
490
        inv.add(dir2)
 
491
        inv.add(dir3)
 
492
        delta = [(u'dir1', None, 'p-1', None),
 
493
            (u'dir1/child2', None, 'p-3', None)]
 
494
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
495
            inv, delta)
 
496
 
324
497
 
325
498
class TestInventoryEntry(TestCase):
326
499
 
738
911
        inv.add_path("", "directory", "myrootid", None)
739
912
        inv.revision_id = "expectedid"
740
913
        reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
741
 
        delta = [(None, "",  "myrootid", inv.root)]
 
914
        delta = [("", None, base_inv.root.file_id, None),
 
915
            (None, "",  "myrootid", inv.root)]
742
916
        new_inv = base_inv.create_by_apply_delta(delta, "expectedid")
743
917
        self.assertEquals(reference_inv.root, new_inv.root)
744
918