15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
from bzrlib import errors, chk_map, inventory, osutils
28
19
from bzrlib.inventory import (CHKInventory, Inventory, ROOT_ID, InventoryFile,
29
20
InventoryDirectory, InventoryEntry, TreeReference)
30
from bzrlib.tests import (
32
TestCaseWithTransport,
35
split_suite_by_condition,
37
from bzrlib.tests.per_workingtree import workingtree_formats
40
def load_tests(standard_tests, module, loader):
41
"""Parameterise some inventory tests."""
42
to_adapt, result = split_suite_by_condition(standard_tests,
43
condition_isinstance(TestDeltaApplication))
45
('Inventory', {'apply_delta':apply_inventory_Inventory}),
47
# Working tree basis delta application
48
# Repository add_inv_by_delta.
49
# Reduce form of the per_repository test logic - that logic needs to be
50
# be able to get /just/ repositories whereas these tests are fine with
51
# just creating trees.
53
for _, format in repository.format_registry.iteritems():
54
scenarios.append((str(format.__name__), {
55
'apply_delta':apply_inventory_Repository_add_inventory_by_delta,
57
for format in workingtree_formats():
59
(str(format.__class__.__name__) + ".update_basis_by_delta", {
60
'apply_delta':apply_inventory_WT_basis,
63
(str(format.__class__.__name__) + ".apply_inventory_delta", {
64
'apply_delta':apply_inventory_WT,
66
return multiply_tests(to_adapt, scenarios, result)
69
def create_texts_for_inv(repo, inv):
70
for path, ie in inv.iter_entries():
72
lines = ['a' * ie.text_size]
75
repo.texts.add_lines((ie.file_id, ie.revision), [], lines)
77
def apply_inventory_Inventory(self, basis, delta):
78
"""Apply delta to basis and return the result.
80
:param basis: An inventory to be used as the basis.
81
:param delta: The inventory delta to apply:
82
:return: An inventory resulting from the application.
84
basis.apply_delta(delta)
88
def apply_inventory_WT(self, basis, delta):
89
"""Apply delta to basis and return the result.
91
This sets the tree state to be basis, and then calls apply_inventory_delta.
93
:param basis: An inventory to be used as the basis.
94
:param delta: The inventory delta to apply:
95
:return: An inventory resulting from the application.
97
control = self.make_bzrdir('tree', format=self.format._matchingbzrdir)
98
control.create_repository()
99
control.create_branch()
100
tree = self.format.initialize(control)
103
tree._write_inventory(basis)
106
# Fresh object, reads disk again.
107
tree = tree.bzrdir.open_workingtree()
110
tree.apply_inventory_delta(delta)
113
# reload tree - ensure we get what was written.
114
tree = tree.bzrdir.open_workingtree()
116
self.addCleanup(tree.unlock)
117
# One could add 'tree._validate' here but that would cause 'early' failues
118
# as far as higher level code is concerned. Possibly adding an
119
# expect_fail parameter to this function and if that is False then do a
121
return tree.inventory
124
def apply_inventory_WT_basis(self, basis, delta):
125
"""Apply delta to basis and return the result.
127
This sets the parent and then calls update_basis_by_delta.
128
It also puts the basis in the repository under both 'basis' and 'result' to
129
allow safety checks made by the WT to succeed, and finally ensures that all
130
items in the delta with a new path are present in the WT before calling
131
update_basis_by_delta.
133
:param basis: An inventory to be used as the basis.
134
:param delta: The inventory delta to apply:
135
:return: An inventory resulting from the application.
137
control = self.make_bzrdir('tree', format=self.format._matchingbzrdir)
138
control.create_repository()
139
control.create_branch()
140
tree = self.format.initialize(control)
143
repo = tree.branch.repository
144
repo.start_write_group()
146
rev = revision.Revision('basis', timestamp=0, timezone=None,
147
message="", committer="foo@example.com")
148
basis.revision_id = 'basis'
149
create_texts_for_inv(tree.branch.repository, basis)
150
repo.add_revision('basis', rev, basis)
151
# Add a revision for the result, with the basis content -
152
# update_basis_by_delta doesn't check that the delta results in
153
# result, and we want inconsistent deltas to get called on the
154
# tree, or else the code isn't actually checked.
155
rev = revision.Revision('result', timestamp=0, timezone=None,
156
message="", committer="foo@example.com")
157
basis.revision_id = 'result'
158
repo.add_revision('result', rev, basis)
159
repo.commit_write_group()
161
repo.abort_write_group()
163
# Set the basis state as the trees current state
164
tree._write_inventory(basis)
165
# This reads basis from the repo and puts it into the tree's local
166
# cache, if it has one.
167
tree.set_parent_ids(['basis'])
170
for old, new, id, entry in delta:
171
if None in (new, entry):
173
paths[new] = (entry.file_id, entry.kind)
174
parents.add(osutils.dirname(new))
175
parents = osutils.minimum_path_selection(parents)
177
# Put place holders in the tree to permit adding the other entries.
178
for pos, parent in enumerate(parents):
179
if not tree.path2id(parent):
180
# add a synthetic directory in the tree so we can can put the
181
# tree0 entries in place for dirstate.
182
tree.add([parent], ["id%d" % pos], ["directory"])
184
# Many deltas may cause this mini-apply to fail, but we want to see what
185
# the delta application code says, not the prep that we do to deal with
186
# limitations of dirstate's update_basis code.
187
for path, (file_id, kind) in sorted(paths.items()):
189
tree.add([path], [file_id], [kind])
190
except (KeyboardInterrupt, SystemExit):
196
# Fresh lock, reads disk again.
199
tree.update_basis_by_delta('result', delta)
202
# reload tree - ensure we get what was written.
203
tree = tree.bzrdir.open_workingtree()
204
basis_tree = tree.basis_tree()
205
basis_tree.lock_read()
206
self.addCleanup(basis_tree.unlock)
207
# Note, that if the tree does not have a local cache, the trick above of
208
# setting the result as the basis, will come back to bite us. That said,
209
# all the implementations in bzr do have a local cache.
210
return basis_tree.inventory
213
def apply_inventory_Repository_add_inventory_by_delta(self, basis, delta):
214
"""Apply delta to basis and return the result.
216
This inserts basis as a whole inventory and then uses
217
add_inventory_by_delta to add delta.
219
:param basis: An inventory to be used as the basis.
220
:param delta: The inventory delta to apply:
221
:return: An inventory resulting from the application.
223
format = self.format()
224
control = self.make_bzrdir('tree', format=format._matchingbzrdir)
225
repo = format.initialize(control)
228
repo.start_write_group()
230
rev = revision.Revision('basis', timestamp=0, timezone=None,
231
message="", committer="foo@example.com")
232
basis.revision_id = 'basis'
233
create_texts_for_inv(repo, basis)
234
repo.add_revision('basis', rev, basis)
235
repo.commit_write_group()
237
repo.abort_write_group()
243
repo.start_write_group()
245
inv_sha1 = repo.add_inventory_by_delta('basis', delta,
248
repo.abort_write_group()
251
repo.commit_write_group()
254
# Fresh lock, reads disk again.
255
repo = repo.bzrdir.open_repository()
257
self.addCleanup(repo.unlock)
258
return repo.get_inventory('result')
261
class TestInventoryUpdates(TestCase):
263
def test_creation_from_root_id(self):
264
# iff a root id is passed to the constructor, a root directory is made
265
inv = inventory.Inventory(root_id='tree-root')
266
self.assertNotEqual(None, inv.root)
267
self.assertEqual('tree-root', inv.root.file_id)
269
def test_add_path_of_root(self):
270
# if no root id is given at creation time, there is no root directory
271
inv = inventory.Inventory(root_id=None)
272
self.assertIs(None, inv.root)
273
# add a root entry by adding its path
274
ie = inv.add_path("", "directory", "my-root")
275
ie.revision = 'test-rev'
276
self.assertEqual("my-root", ie.file_id)
277
self.assertIs(ie, inv.root)
279
def test_add_path(self):
280
inv = inventory.Inventory(root_id='tree_root')
281
ie = inv.add_path('hello', 'file', 'hello-id')
282
self.assertEqual('hello-id', ie.file_id)
283
self.assertEqual('file', ie.kind)
286
"""Make sure copy() works and creates a deep copy."""
287
inv = inventory.Inventory(root_id='some-tree-root')
288
ie = inv.add_path('hello', 'file', 'hello-id')
290
inv.root.file_id = 'some-new-root'
292
self.assertEqual('some-tree-root', inv2.root.file_id)
293
self.assertEqual('hello', inv2['hello-id'].name)
295
def test_copy_empty(self):
296
"""Make sure an empty inventory can be copied."""
297
inv = inventory.Inventory(root_id=None)
299
self.assertIs(None, inv2.root)
301
def test_copy_copies_root_revision(self):
302
"""Make sure the revision of the root gets copied."""
303
inv = inventory.Inventory(root_id='someroot')
304
inv.root.revision = 'therev'
306
self.assertEquals('someroot', inv2.root.file_id)
307
self.assertEquals('therev', inv2.root.revision)
309
def test_create_tree_reference(self):
310
inv = inventory.Inventory('tree-root-123')
311
inv.add(TreeReference('nested-id', 'nested', parent_id='tree-root-123',
312
revision='rev', reference_revision='rev2'))
314
def test_error_encoding(self):
315
inv = inventory.Inventory('tree-root')
316
inv.add(InventoryFile('a-id', u'\u1234', 'tree-root'))
317
e = self.assertRaises(errors.InconsistentDelta, inv.add,
318
InventoryFile('b-id', u'\u1234', 'tree-root'))
319
self.assertContainsRe(str(e), r'\\u1234')
321
def test_add_recursive(self):
322
parent = InventoryDirectory('src-id', 'src', 'tree-root')
323
child = InventoryFile('hello-id', 'hello.c', 'src-id')
324
parent.children[child.file_id] = child
325
inv = inventory.Inventory('tree-root')
327
self.assertEqual('src/hello.c', inv.id2path('hello-id'))
331
class TestDeltaApplication(TestCaseWithTransport):
333
def get_empty_inventory(self, reference_inv=None):
334
"""Get an empty inventory.
336
Note that tests should not depend on the revision of the root for
337
setting up test conditions, as it has to be flexible to accomodate non
338
rich root repositories.
340
:param reference_inv: If not None, get the revision for the root from
341
this inventory. This is useful for dealing with older repositories
342
that routinely discarded the root entry data. If None, the root's
343
revision is set to 'basis'.
345
inv = inventory.Inventory()
346
if reference_inv is not None:
347
inv.root.revision = reference_inv.root.revision
349
inv.root.revision = 'basis'
352
def test_empty_delta(self):
353
inv = self.get_empty_inventory()
355
inv = self.apply_delta(self, inv, delta)
356
inv2 = self.get_empty_inventory(inv)
357
self.assertEqual([], inv2._make_delta(inv))
359
def test_None_file_id(self):
360
inv = self.get_empty_inventory()
361
dir1 = inventory.InventoryDirectory(None, 'dir1', inv.root.file_id)
362
dir1.revision = 'result'
363
delta = [(None, u'dir1', None, dir1)]
364
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
367
def test_unicode_file_id(self):
368
inv = self.get_empty_inventory()
369
dir1 = inventory.InventoryDirectory(u'dirid', 'dir1', inv.root.file_id)
370
dir1.revision = 'result'
371
delta = [(None, u'dir1', dir1.file_id, dir1)]
372
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
375
def test_repeated_file_id(self):
376
inv = self.get_empty_inventory()
377
file1 = inventory.InventoryFile('id', 'path1', inv.root.file_id)
378
file1.revision = 'result'
381
file2 = inventory.InventoryFile('id', 'path2', inv.root.file_id)
382
file2.revision = 'result'
385
delta = [(None, u'path1', 'id', file1), (None, u'path2', 'id', file2)]
386
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
389
def test_repeated_new_path(self):
390
inv = self.get_empty_inventory()
391
file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
392
file1.revision = 'result'
395
file2 = inventory.InventoryFile('id2', 'path', inv.root.file_id)
396
file2.revision = 'result'
399
delta = [(None, u'path', 'id1', file1), (None, u'path', 'id2', file2)]
400
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
403
def test_repeated_old_path(self):
404
inv = self.get_empty_inventory()
405
file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
406
file1.revision = 'result'
409
# We can't *create* a source inventory with the same path, but
410
# a badly generated partial delta might claim the same source twice.
411
# This would be buggy in two ways: the path is repeated in the delta,
412
# And the path for one of the file ids doesn't match the source
413
# location. Alternatively, we could have a repeated fileid, but that
414
# is separately checked for.
415
file2 = inventory.InventoryFile('id2', 'path2', inv.root.file_id)
416
file2.revision = 'result'
421
delta = [(u'path', None, 'id1', None), (u'path', None, 'id2', None)]
422
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
425
def test_mismatched_id_entry_id(self):
426
inv = self.get_empty_inventory()
427
file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
428
file1.revision = 'result'
431
delta = [(None, u'path', 'id', file1)]
432
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
435
def test_mismatched_new_path_entry_None(self):
436
inv = self.get_empty_inventory()
437
delta = [(None, u'path', 'id', None)]
438
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
441
def test_mismatched_new_path_None_entry(self):
442
inv = self.get_empty_inventory()
443
file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
444
file1.revision = 'result'
447
delta = [(u"path", None, 'id1', file1)]
448
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
451
def test_parent_is_not_directory(self):
452
inv = self.get_empty_inventory()
453
file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
454
file1.revision = 'result'
457
file2 = inventory.InventoryFile('id2', 'path2', 'id1')
458
file2.revision = 'result'
462
delta = [(None, u'path/path2', 'id2', file2)]
463
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
466
def test_parent_is_missing(self):
467
inv = self.get_empty_inventory()
468
file2 = inventory.InventoryFile('id2', 'path2', 'missingparent')
469
file2.revision = 'result'
472
delta = [(None, u'path/path2', 'id2', file2)]
473
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
476
def test_new_parent_path_has_wrong_id(self):
477
inv = self.get_empty_inventory()
478
parent1 = inventory.InventoryDirectory('p-1', 'dir', inv.root.file_id)
479
parent1.revision = 'result'
480
parent2 = inventory.InventoryDirectory('p-2', 'dir2', inv.root.file_id)
481
parent2.revision = 'result'
482
file1 = inventory.InventoryFile('id', 'path', 'p-2')
483
file1.revision = 'result'
488
# This delta claims that file1 is at dir/path, but actually its at
489
# dir2/path if you follow the inventory parent structure.
490
delta = [(None, u'dir/path', 'id', file1)]
491
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
494
def test_old_parent_path_is_wrong(self):
495
inv = self.get_empty_inventory()
496
parent1 = inventory.InventoryDirectory('p-1', 'dir', inv.root.file_id)
497
parent1.revision = 'result'
498
parent2 = inventory.InventoryDirectory('p-2', 'dir2', inv.root.file_id)
499
parent2.revision = 'result'
500
file1 = inventory.InventoryFile('id', 'path', 'p-2')
501
file1.revision = 'result'
507
# This delta claims that file1 was at dir/path, but actually it was at
508
# dir2/path if you follow the inventory parent structure.
509
delta = [(u'dir/path', None, 'id', None)]
510
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
513
def test_old_parent_path_is_for_other_id(self):
514
inv = self.get_empty_inventory()
515
parent1 = inventory.InventoryDirectory('p-1', 'dir', inv.root.file_id)
516
parent1.revision = 'result'
517
parent2 = inventory.InventoryDirectory('p-2', 'dir2', inv.root.file_id)
518
parent2.revision = 'result'
519
file1 = inventory.InventoryFile('id', 'path', 'p-2')
520
file1.revision = 'result'
523
file2 = inventory.InventoryFile('id2', 'path', 'p-1')
524
file2.revision = 'result'
531
# This delta claims that file1 was at dir/path, but actually it was at
532
# dir2/path if you follow the inventory parent structure. At dir/path
533
# is another entry we should not delete.
534
delta = [(u'dir/path', None, 'id', None)]
535
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
538
def test_add_existing_id_new_path(self):
539
inv = self.get_empty_inventory()
540
parent1 = inventory.InventoryDirectory('p-1', 'dir1', inv.root.file_id)
541
parent1.revision = 'result'
542
parent2 = inventory.InventoryDirectory('p-1', 'dir2', inv.root.file_id)
543
parent2.revision = 'result'
545
delta = [(None, u'dir2', 'p-1', parent2)]
546
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
549
def test_add_new_id_existing_path(self):
550
inv = self.get_empty_inventory()
551
parent1 = inventory.InventoryDirectory('p-1', 'dir1', inv.root.file_id)
552
parent1.revision = 'result'
553
parent2 = inventory.InventoryDirectory('p-2', 'dir1', inv.root.file_id)
554
parent2.revision = 'result'
556
delta = [(None, u'dir1', 'p-2', parent2)]
557
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
560
def test_remove_dir_leaving_dangling_child(self):
561
inv = self.get_empty_inventory()
562
dir1 = inventory.InventoryDirectory('p-1', 'dir1', inv.root.file_id)
563
dir1.revision = 'result'
564
dir2 = inventory.InventoryDirectory('p-2', 'child1', 'p-1')
565
dir2.revision = 'result'
566
dir3 = inventory.InventoryDirectory('p-3', 'child2', 'p-1')
567
dir3.revision = 'result'
571
delta = [(u'dir1', None, 'p-1', None),
572
(u'dir1/child2', None, 'p-3', None)]
573
self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
577
class TestInventory(TestCase):
579
def test_is_root(self):
580
"""Ensure our root-checking code is accurate."""
581
inv = inventory.Inventory('TREE_ROOT')
582
self.assertTrue(inv.is_root('TREE_ROOT'))
583
self.assertFalse(inv.is_root('booga'))
584
inv.root.file_id = 'booga'
585
self.assertFalse(inv.is_root('TREE_ROOT'))
586
self.assertTrue(inv.is_root('booga'))
587
# works properly even if no root is set
589
self.assertFalse(inv.is_root('TREE_ROOT'))
590
self.assertFalse(inv.is_root('booga'))
592
def test_entries_for_empty_inventory(self):
593
"""Test that entries() will not fail for an empty inventory"""
594
inv = Inventory(root_id=None)
595
self.assertEqual([], inv.entries())
21
from bzrlib.tests import TestCase, TestCaseWithTransport
598
24
class TestInventoryEntry(TestCase):
1210
636
self.assertIsInstance(ie2.name, unicode)
1211
637
self.assertEqual(('tree\xce\xa9name', 'tree-root-id', 'tree-rev-id'),
1212
638
inv._bytes_to_utf8name_key(bytes))
1215
class TestCHKInventoryExpand(tests.TestCaseWithMemoryTransport):
1217
def get_chk_bytes(self):
1218
factory = groupcompress.make_pack_factory(True, True, 1)
1219
trans = self.get_transport('')
1220
return factory(trans)
1222
def make_dir(self, inv, name, parent_id):
1223
inv.add(inv.make_entry('directory', name, parent_id, name + '-id'))
1225
def make_file(self, inv, name, parent_id, content='content\n'):
1226
ie = inv.make_entry('file', name, parent_id, name + '-id')
1227
ie.text_sha1 = osutils.sha_string(content)
1228
ie.text_size = len(content)
1231
def make_simple_inventory(self):
1232
inv = Inventory('TREE_ROOT')
1233
inv.revision_id = "revid"
1234
inv.root.revision = "rootrev"
1237
# sub-file1 sub-file1-id
1238
# sub-file2 sub-file2-id
1239
# sub-dir1/ sub-dir1-id
1240
# subsub-file1 subsub-file1-id
1242
# sub2-file1 sub2-file1-id
1244
self.make_dir(inv, 'dir1', 'TREE_ROOT')
1245
self.make_dir(inv, 'dir2', 'TREE_ROOT')
1246
self.make_dir(inv, 'sub-dir1', 'dir1-id')
1247
self.make_file(inv, 'top', 'TREE_ROOT')
1248
self.make_file(inv, 'sub-file1', 'dir1-id')
1249
self.make_file(inv, 'sub-file2', 'dir1-id')
1250
self.make_file(inv, 'subsub-file1', 'sub-dir1-id')
1251
self.make_file(inv, 'sub2-file1', 'dir2-id')
1252
chk_bytes = self.get_chk_bytes()
1253
# use a small maximum_size to force internal paging structures
1254
chk_inv = CHKInventory.from_inventory(chk_bytes, inv,
1256
search_key_name='hash-255-way')
1257
bytes = ''.join(chk_inv.to_lines())
1258
return CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1260
def assert_Getitems(self, expected_fileids, inv, file_ids):
1261
self.assertEqual(sorted(expected_fileids),
1262
sorted([ie.file_id for ie in inv._getitems(file_ids)]))
1264
def assertExpand(self, all_ids, inv, file_ids):
1266
val_children) = inv._expand_fileids_to_parents_and_children(file_ids)
1267
self.assertEqual(set(all_ids), val_all_ids)
1268
entries = inv._getitems(val_all_ids)
1269
expected_children = {}
1270
for entry in entries:
1271
s = expected_children.setdefault(entry.parent_id, [])
1272
s.append(entry.file_id)
1273
val_children = dict((k, sorted(v)) for k, v
1274
in val_children.iteritems())
1275
expected_children = dict((k, sorted(v)) for k, v
1276
in expected_children.iteritems())
1277
self.assertEqual(expected_children, val_children)
1279
def test_make_simple_inventory(self):
1280
inv = self.make_simple_inventory()
1282
for path, entry in inv.iter_entries_by_dir():
1283
layout.append((path, entry.file_id))
1286
('dir1', 'dir1-id'),
1287
('dir2', 'dir2-id'),
1289
('dir1/sub-dir1', 'sub-dir1-id'),
1290
('dir1/sub-file1', 'sub-file1-id'),
1291
('dir1/sub-file2', 'sub-file2-id'),
1292
('dir1/sub-dir1/subsub-file1', 'subsub-file1-id'),
1293
('dir2/sub2-file1', 'sub2-file1-id'),
1296
def test__getitems(self):
1297
inv = self.make_simple_inventory()
1299
self.assert_Getitems(['dir1-id'], inv, ['dir1-id'])
1300
self.assertTrue('dir1-id' in inv._fileid_to_entry_cache)
1301
self.assertFalse('sub-file2-id' in inv._fileid_to_entry_cache)
1303
self.assert_Getitems(['dir1-id'], inv, ['dir1-id'])
1305
self.assert_Getitems(['dir1-id', 'sub-file2-id'], inv,
1306
['dir1-id', 'sub-file2-id'])
1307
self.assertTrue('dir1-id' in inv._fileid_to_entry_cache)
1308
self.assertTrue('sub-file2-id' in inv._fileid_to_entry_cache)
1310
def test_single_file(self):
1311
inv = self.make_simple_inventory()
1312
self.assertExpand(['TREE_ROOT', 'top-id'], inv, ['top-id'])
1314
def test_get_all_parents(self):
1315
inv = self.make_simple_inventory()
1316
self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id',
1318
], inv, ['subsub-file1-id'])
1320
def test_get_children(self):
1321
inv = self.make_simple_inventory()
1322
self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id',
1323
'sub-file1-id', 'sub-file2-id', 'subsub-file1-id',
1324
], inv, ['dir1-id'])
1326
def test_from_root(self):
1327
inv = self.make_simple_inventory()
1328
self.assertExpand(['TREE_ROOT', 'dir1-id', 'dir2-id', 'sub-dir1-id',
1329
'sub-file1-id', 'sub-file2-id', 'sub2-file1-id',
1330
'subsub-file1-id', 'top-id'], inv, ['TREE_ROOT'])
1332
def test_top_level_file(self):
1333
inv = self.make_simple_inventory()
1334
self.assertExpand(['TREE_ROOT', 'top-id'], inv, ['top-id'])
1336
def test_subsub_file(self):
1337
inv = self.make_simple_inventory()
1338
self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id',
1339
'subsub-file1-id'], inv, ['subsub-file1-id'])
1341
def test_sub_and_root(self):
1342
inv = self.make_simple_inventory()
1343
self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id', 'top-id',
1344
'subsub-file1-id'], inv, ['top-id', 'subsub-file1-id'])