~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_inv.py

  • Committer: John Arbash Meinel
  • Date: 2009-07-29 21:35:05 UTC
  • mfrom: (4576 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4577.
  • Revision ID: john@arbash-meinel.com-20090729213505-tkqsvy1zfpocu75w
Merge bzr.dev 4576 in prep for NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
18
 
from bzrlib import errors, chk_map, inventory, osutils
 
18
from bzrlib import (
 
19
    chk_map,
 
20
    bzrdir,
 
21
    errors,
 
22
    inventory,
 
23
    osutils,
 
24
    repository,
 
25
    revision,
 
26
    )
19
27
from bzrlib.inventory import (CHKInventory, Inventory, ROOT_ID, InventoryFile,
20
28
    InventoryDirectory, InventoryEntry, TreeReference)
21
 
from bzrlib.tests import TestCase, TestCaseWithTransport
 
29
from bzrlib.tests import (
 
30
    TestCase,
 
31
    TestCaseWithTransport,
 
32
    condition_isinstance,
 
33
    multiply_tests,
 
34
    split_suite_by_condition,
 
35
    )
 
36
from bzrlib.tests.per_workingtree import workingtree_formats
 
37
 
 
38
 
 
39
def load_tests(standard_tests, module, loader):
 
40
    """Parameterise some inventory tests."""
 
41
    to_adapt, result = split_suite_by_condition(standard_tests,
 
42
        condition_isinstance(TestDeltaApplication))
 
43
    scenarios = [
 
44
        ('Inventory', {'apply_delta':apply_inventory_Inventory}),
 
45
        ]
 
46
    # Working tree basis delta application
 
47
    # Repository add_inv_by_delta.
 
48
    # Reduce form of the per_repository test logic - that logic needs to be
 
49
    # be able to get /just/ repositories whereas these tests are fine with
 
50
    # just creating trees.
 
51
    formats = set()
 
52
    for _, format in repository.format_registry.iteritems():
 
53
        scenarios.append((str(format.__name__), {
 
54
            'apply_delta':apply_inventory_Repository_add_inventory_by_delta,
 
55
            'format':format}))
 
56
    for format in workingtree_formats():
 
57
        scenarios.append(
 
58
            (str(format.__class__.__name__) + ".update_basis_by_delta", {
 
59
            'apply_delta':apply_inventory_WT_basis,
 
60
            'format':format}))
 
61
        scenarios.append(
 
62
            (str(format.__class__.__name__) + ".apply_inventory_delta", {
 
63
            'apply_delta':apply_inventory_WT,
 
64
            'format':format}))
 
65
    return multiply_tests(to_adapt, scenarios, result)
 
66
 
 
67
 
 
68
def apply_inventory_Inventory(self, basis, delta):
 
69
    """Apply delta to basis and return the result.
 
70
    
 
71
    :param basis: An inventory to be used as the basis.
 
72
    :param delta: The inventory delta to apply:
 
73
    :return: An inventory resulting from the application.
 
74
    """
 
75
    basis.apply_delta(delta)
 
76
    return basis
 
77
 
 
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
 
 
115
def apply_inventory_WT_basis(self, basis, delta):
 
116
    """Apply delta to basis and return the result.
 
117
 
 
118
    This sets the parent and then calls update_basis_by_delta.
 
119
    It also puts the basis in the repository under both 'basis' and 'result' to
 
120
    allow safety checks made by the WT to succeed, and finally ensures that all
 
121
    items in the delta with a new path are present in the WT before calling
 
122
    update_basis_by_delta.
 
123
    
 
124
    :param basis: An inventory to be used as the basis.
 
125
    :param delta: The inventory delta to apply:
 
126
    :return: An inventory resulting from the application.
 
127
    """
 
128
    control = self.make_bzrdir('tree', format=self.format._matchingbzrdir)
 
129
    control.create_repository()
 
130
    control.create_branch()
 
131
    tree = self.format.initialize(control)
 
132
    tree.lock_write()
 
133
    try:
 
134
        repo = tree.branch.repository
 
135
        repo.start_write_group()
 
136
        try:
 
137
            rev = revision.Revision('basis', timestamp=0, timezone=None,
 
138
                message="", committer="foo@example.com")
 
139
            basis.revision_id = 'basis'
 
140
            repo.add_revision('basis', rev, basis)
 
141
            # Add a revision for the result, with the basis content - 
 
142
            # update_basis_by_delta doesn't check that the delta results in
 
143
            # result, and we want inconsistent deltas to get called on the
 
144
            # tree, or else the code isn't actually checked.
 
145
            rev = revision.Revision('result', timestamp=0, timezone=None,
 
146
                message="", committer="foo@example.com")
 
147
            basis.revision_id = 'result'
 
148
            repo.add_revision('result', rev, basis)
 
149
        except:
 
150
            repo.abort_write_group()
 
151
            raise
 
152
        else:
 
153
            repo.commit_write_group()
 
154
        # Set the basis state as the trees current state
 
155
        tree._write_inventory(basis)
 
156
        # This reads basis from the repo and puts it into the tree's local
 
157
        # cache, if it has one.
 
158
        tree.set_parent_ids(['basis'])
 
159
        paths = {}
 
160
        parents = set()
 
161
        for old, new, id, entry in delta:
 
162
            if None in (new, entry):
 
163
                continue
 
164
            paths[new] = (entry.file_id, entry.kind)
 
165
            parents.add(osutils.dirname(new))
 
166
        parents = osutils.minimum_path_selection(parents)
 
167
        parents.discard('')
 
168
        # Put place holders in the tree to permit adding the other entries.
 
169
        for pos, parent in enumerate(parents):
 
170
            if not tree.path2id(parent):
 
171
                # add a synthetic directory in the tree so we can can put the
 
172
                # tree0 entries in place for dirstate.
 
173
                tree.add([parent], ["id%d" % pos], ["directory"])
 
174
        if paths:
 
175
            # Many deltas may cause this mini-apply to fail, but we want to see what
 
176
            # the delta application code says, not the prep that we do to deal with 
 
177
            # limitations of dirstate's update_basis code.
 
178
            for path, (file_id, kind) in sorted(paths.items()):
 
179
                try:
 
180
                    tree.add([path], [file_id], [kind])
 
181
                except (KeyboardInterrupt, SystemExit):
 
182
                    raise
 
183
                except:
 
184
                    pass
 
185
    finally:
 
186
        tree.unlock()
 
187
    # Fresh lock, reads disk again.
 
188
    tree.lock_write()
 
189
    try:
 
190
        tree.update_basis_by_delta('result', delta)
 
191
    finally:
 
192
        tree.unlock()
 
193
    # reload tree - ensure we get what was written.
 
194
    tree = tree.bzrdir.open_workingtree()
 
195
    basis_tree = tree.basis_tree()
 
196
    basis_tree.lock_read()
 
197
    self.addCleanup(basis_tree.unlock)
 
198
    # Note, that if the tree does not have a local cache, the trick above of
 
199
    # setting the result as the basis, will come back to bite us. That said,
 
200
    # all the implementations in bzr do have a local cache.
 
201
    return basis_tree.inventory
 
202
 
 
203
 
 
204
def apply_inventory_Repository_add_inventory_by_delta(self, basis, delta):
 
205
    """Apply delta to basis and return the result.
 
206
    
 
207
    This inserts basis as a whole inventory and then uses
 
208
    add_inventory_by_delta to add delta.
 
209
 
 
210
    :param basis: An inventory to be used as the basis.
 
211
    :param delta: The inventory delta to apply:
 
212
    :return: An inventory resulting from the application.
 
213
    """
 
214
    format = self.format()
 
215
    control = self.make_bzrdir('tree', format=format._matchingbzrdir)
 
216
    repo = format.initialize(control)
 
217
    repo.lock_write()
 
218
    try:
 
219
        repo.start_write_group()
 
220
        try:
 
221
            rev = revision.Revision('basis', timestamp=0, timezone=None,
 
222
                message="", committer="foo@example.com")
 
223
            basis.revision_id = 'basis'
 
224
            repo.add_revision('basis', rev, basis)
 
225
        except:
 
226
            repo.abort_write_group()
 
227
            raise
 
228
        else:
 
229
            repo.commit_write_group()
 
230
    finally:
 
231
        repo.unlock()
 
232
    repo.lock_write()
 
233
    try:
 
234
        repo.start_write_group()
 
235
        try:
 
236
            inv_sha1 = repo.add_inventory_by_delta('basis', delta,
 
237
                'result', ['basis'])
 
238
        except:
 
239
            repo.abort_write_group()
 
240
            raise
 
241
        else:
 
242
            repo.commit_write_group()
 
243
    finally:
 
244
        repo.unlock()
 
245
    # Fresh lock, reads disk again.
 
246
    repo = repo.bzrdir.open_repository()
 
247
    repo.lock_read()
 
248
    self.addCleanup(repo.unlock)
 
249
    return repo.get_inventory('result')
 
250
 
 
251
 
 
252
class TestDeltaApplication(TestCaseWithTransport):
 
253
 
 
254
    def get_empty_inventory(self, reference_inv=None):
 
255
        """Get an empty inventory.
 
256
 
 
257
        Note that tests should not depend on the revision of the root for
 
258
        setting up test conditions, as it has to be flexible to accomodate non
 
259
        rich root repositories.
 
260
 
 
261
        :param reference_inv: If not None, get the revision for the root from
 
262
            this inventory. This is useful for dealing with older repositories
 
263
            that routinely discarded the root entry data. If None, the root's
 
264
            revision is set to 'basis'.
 
265
        """
 
266
        inv = inventory.Inventory()
 
267
        if reference_inv is not None:
 
268
            inv.root.revision = reference_inv.root.revision
 
269
        else:
 
270
            inv.root.revision = 'basis'
 
271
        return inv
 
272
 
 
273
    def test_empty_delta(self):
 
274
        inv = self.get_empty_inventory()
 
275
        delta = []
 
276
        inv = self.apply_delta(self, inv, delta)
 
277
        inv2 = self.get_empty_inventory(inv)
 
278
        self.assertEqual([], inv2._make_delta(inv))
 
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
 
 
296
    def test_repeated_file_id(self):
 
297
        inv = self.get_empty_inventory()
 
298
        file1 = inventory.InventoryFile('id', 'path1', inv.root.file_id)
 
299
        file1.revision = 'result'
 
300
        file1.text_size = 0
 
301
        file1.text_sha1 = ""
 
302
        file2 = inventory.InventoryFile('id', 'path2', inv.root.file_id)
 
303
        file2.revision = 'result'
 
304
        file2.text_size = 0
 
305
        file2.text_sha1 = ""
 
306
        delta = [(None, u'path1', 'id', file1), (None, u'path2', 'id', file2)]
 
307
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
308
            inv, delta)
 
309
 
 
310
    def test_repeated_new_path(self):
 
311
        inv = self.get_empty_inventory()
 
312
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
313
        file1.revision = 'result'
 
314
        file1.text_size = 0
 
315
        file1.text_sha1 = ""
 
316
        file2 = inventory.InventoryFile('id2', 'path', inv.root.file_id)
 
317
        file2.revision = 'result'
 
318
        file2.text_size = 0
 
319
        file2.text_sha1 = ""
 
320
        delta = [(None, u'path', 'id1', file1), (None, u'path', 'id2', file2)]
 
321
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
322
            inv, delta)
 
323
 
 
324
    def test_repeated_old_path(self):
 
325
        inv = self.get_empty_inventory()
 
326
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
327
        file1.revision = 'result'
 
328
        file1.text_size = 0
 
329
        file1.text_sha1 = ""
 
330
        # We can't *create* a source inventory with the same path, but
 
331
        # a badly generated partial delta might claim the same source twice.
 
332
        # This would be buggy in two ways: the path is repeated in the delta,
 
333
        # And the path for one of the file ids doesn't match the source
 
334
        # location. Alternatively, we could have a repeated fileid, but that
 
335
        # is separately checked for.
 
336
        file2 = inventory.InventoryFile('id2', 'path2', inv.root.file_id)
 
337
        file2.revision = 'result'
 
338
        file2.text_size = 0
 
339
        file2.text_sha1 = ""
 
340
        inv.add(file1)
 
341
        inv.add(file2)
 
342
        delta = [(u'path', None, 'id1', None), (u'path', None, 'id2', None)]
 
343
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
344
            inv, delta)
 
345
 
 
346
    def test_mismatched_id_entry_id(self):
 
347
        inv = self.get_empty_inventory()
 
348
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
349
        file1.revision = 'result'
 
350
        file1.text_size = 0
 
351
        file1.text_sha1 = ""
 
352
        delta = [(None, u'path', 'id', file1)]
 
353
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
354
            inv, delta)
 
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
 
 
372
    def test_parent_is_not_directory(self):
 
373
        inv = self.get_empty_inventory()
 
374
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
375
        file1.revision = 'result'
 
376
        file1.text_size = 0
 
377
        file1.text_sha1 = ""
 
378
        file2 = inventory.InventoryFile('id2', 'path2', 'id1')
 
379
        file2.revision = 'result'
 
380
        file2.text_size = 0
 
381
        file2.text_sha1 = ""
 
382
        inv.add(file1)
 
383
        delta = [(None, u'path/path2', 'id2', file2)]
 
384
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
385
            inv, delta)
 
386
 
 
387
    def test_parent_is_missing(self):
 
388
        inv = self.get_empty_inventory()
 
389
        file2 = inventory.InventoryFile('id2', 'path2', 'missingparent')
 
390
        file2.revision = 'result'
 
391
        file2.text_size = 0
 
392
        file2.text_sha1 = ""
 
393
        delta = [(None, u'path/path2', 'id2', file2)]
 
394
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
395
            inv, delta)
 
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)
22
496
 
23
497
 
24
498
class TestInventoryEntry(TestCase):
297
771
        inv.root.revision = "rootrev"
298
772
        chk_bytes = self.get_chk_bytes()
299
773
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv, 120)
 
774
        chk_inv.id_to_entry._ensure_root()
300
775
        self.assertEqual(120, chk_inv.id_to_entry._root_node.maximum_size)
 
776
        self.assertEqual(1, chk_inv.id_to_entry._root_node._key_width)
 
777
        p_id_basename = chk_inv.parent_id_basename_to_file_id
 
778
        p_id_basename._ensure_root()
 
779
        self.assertEqual(120, p_id_basename._root_node.maximum_size)
 
780
        self.assertEqual(2, p_id_basename._root_node._key_width)
301
781
 
302
782
    def test___iter__(self):
303
783
        inv = Inventory()
431
911
        inv.add_path("", "directory", "myrootid", None)
432
912
        inv.revision_id = "expectedid"
433
913
        reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
434
 
        delta = [(None, "",  "myrootid", inv.root)]
 
914
        delta = [("", None, base_inv.root.file_id, None),
 
915
            (None, "",  "myrootid", inv.root)]
435
916
        new_inv = base_inv.create_by_apply_delta(delta, "expectedid")
436
917
        self.assertEquals(reference_inv.root, new_inv.root)
437
918
 
454
935
        # new_inv should be the same as reference_inv.
455
936
        self.assertEqual(reference_inv.revision_id, new_inv.revision_id)
456
937
        self.assertEqual(reference_inv.root_id, new_inv.root_id)
 
938
        reference_inv.id_to_entry._ensure_root()
 
939
        new_inv.id_to_entry._ensure_root()
457
940
        self.assertEqual(reference_inv.id_to_entry._root_node._key,
458
941
            new_inv.id_to_entry._root_node._key)
459
942
 
473
956
        reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
474
957
        delta = [(None, "A",  "A-id", a_entry)]
475
958
        new_inv = base_inv.create_by_apply_delta(delta, "expectedid")
 
959
        reference_inv.id_to_entry._ensure_root()
 
960
        reference_inv.parent_id_basename_to_file_id._ensure_root()
 
961
        new_inv.id_to_entry._ensure_root()
 
962
        new_inv.parent_id_basename_to_file_id._ensure_root()
476
963
        # new_inv should be the same as reference_inv.
477
964
        self.assertEqual(reference_inv.revision_id, new_inv.revision_id)
478
965
        self.assertEqual(reference_inv.root_id, new_inv.root_id)