/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5557.1.7 by John Arbash Meinel
Merge in the bzr.dev 5582
1
# Copyright (C) 2005-2011 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
963 by Martin Pool
- add the start of a test for inventory file-id matching
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
963 by Martin Pool
- add the start of a test for inventory file-id matching
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
963 by Martin Pool
- add the start of a test for inventory file-id matching
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
963 by Martin Pool
- add the start of a test for inventory file-id matching
16
2729.2.5 by Martin Pool
Move per-inventory tests from test_inv to tests.inventory_implementations
17
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
18
from bzrlib import (
19
    chk_map,
4634.51.1 by John Arbash Meinel
Switch away from creating a whole repository just to get a VF.
20
    groupcompress,
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
21
    errors,
22
    inventory,
23
    osutils,
24
    repository,
25
    revision,
4634.51.1 by John Arbash Meinel
Switch away from creating a whole repository just to get a VF.
26
    tests,
5662.3.1 by Jelmer Vernooij
Add WorkingTreeFormatRegistry.
27
    workingtree,
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
28
    )
5579.3.1 by Jelmer Vernooij
Remove unused imports.
29
from bzrlib.inventory import (
30
    CHKInventory,
31
    Inventory,
32
    ROOT_ID,
33
    InventoryFile,
34
    InventoryDirectory,
35
    InventoryEntry,
36
    TreeReference,
5802.1.2 by Jelmer Vernooij
Add test for mutable_inventory_from_tree.
37
    mutable_inventory_from_tree,
5579.3.1 by Jelmer Vernooij
Remove unused imports.
38
    )
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
39
from bzrlib.tests import (
40
    TestCase,
41
    TestCaseWithTransport,
42
    )
5559.2.2 by Martin Pool
Change to using standard load_tests_apply_scenarios.
43
from bzrlib.tests.scenarios import load_tests_apply_scenarios
44
45
46
load_tests = load_tests_apply_scenarios
47
48
49
def delta_application_scenarios():
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
50
    scenarios = [
51
        ('Inventory', {'apply_delta':apply_inventory_Inventory}),
52
        ]
53
    # Working tree basis delta application
54
    # Repository add_inv_by_delta.
55
    # Reduce form of the per_repository test logic - that logic needs to be
56
    # be able to get /just/ repositories whereas these tests are fine with
57
    # just creating trees.
58
    formats = set()
59
    for _, format in repository.format_registry.iteritems():
5718.3.1 by Jelmer Vernooij
Skip more tests for repository formats that don't support the full
60
        if format.supports_full_versioned_files:
61
            scenarios.append((str(format.__name__), {
62
                'apply_delta':apply_inventory_Repository_add_inventory_by_delta,
63
                'format':format}))
5662.3.1 by Jelmer Vernooij
Add WorkingTreeFormatRegistry.
64
    for format in workingtree.format_registry._get_all():
5718.3.1 by Jelmer Vernooij
Skip more tests for repository formats that don't support the full
65
        repo_fmt = format._matchingbzrdir.repository_format
66
        if not repo_fmt.supports_full_versioned_files:
67
            continue
4526.9.2 by Robert Collins
Handle deltas with new paths not matching the actual path.
68
        scenarios.append(
69
            (str(format.__class__.__name__) + ".update_basis_by_delta", {
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
70
            'apply_delta':apply_inventory_WT_basis,
71
            'format':format}))
4526.9.2 by Robert Collins
Handle deltas with new paths not matching the actual path.
72
        scenarios.append(
73
            (str(format.__class__.__name__) + ".apply_inventory_delta", {
4526.9.1 by Robert Collins
Add WorkingTree.apply_inventory_delta to the set of delta implementations interface tested.
74
            'apply_delta':apply_inventory_WT,
75
            'format':format}))
5559.2.2 by Martin Pool
Change to using standard load_tests_apply_scenarios.
76
    return scenarios
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
77
78
4634.35.19 by Andrew Bennetts
Fix test_inv.
79
def create_texts_for_inv(repo, inv):
80
    for path, ie in inv.iter_entries():
81
        if ie.text_size:
82
            lines = ['a' * ie.text_size]
83
        else:
84
            lines = []
85
        repo.texts.add_lines((ie.file_id, ie.revision), [], lines)
5559.2.2 by Martin Pool
Change to using standard load_tests_apply_scenarios.
86
5718.3.1 by Jelmer Vernooij
Skip more tests for repository formats that don't support the full
87
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
88
def apply_inventory_Inventory(self, basis, delta, invalid_delta=True):
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
89
    """Apply delta to basis and return the result.
5847.4.12 by John Arbash Meinel
(broken) Expand the test coverage for cases we care about.
90
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
91
    :param basis: An inventory to be used as the basis.
92
    :param delta: The inventory delta to apply:
93
    :return: An inventory resulting from the application.
94
    """
95
    basis.apply_delta(delta)
96
    return basis
97
98
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
99
def apply_inventory_WT(self, basis, delta, invalid_delta=True):
4526.9.1 by Robert Collins
Add WorkingTree.apply_inventory_delta to the set of delta implementations interface tested.
100
    """Apply delta to basis and return the result.
101
102
    This sets the tree state to be basis, and then calls apply_inventory_delta.
5847.4.12 by John Arbash Meinel
(broken) Expand the test coverage for cases we care about.
103
4526.9.1 by Robert Collins
Add WorkingTree.apply_inventory_delta to the set of delta implementations interface tested.
104
    :param basis: An inventory to be used as the basis.
105
    :param delta: The inventory delta to apply:
106
    :return: An inventory resulting from the application.
107
    """
108
    control = self.make_bzrdir('tree', format=self.format._matchingbzrdir)
109
    control.create_repository()
110
    control.create_branch()
111
    tree = self.format.initialize(control)
112
    tree.lock_write()
113
    try:
114
        tree._write_inventory(basis)
115
    finally:
116
        tree.unlock()
117
    # Fresh object, reads disk again.
118
    tree = tree.bzrdir.open_workingtree()
119
    tree.lock_write()
120
    try:
121
        tree.apply_inventory_delta(delta)
122
    finally:
123
        tree.unlock()
124
    # reload tree - ensure we get what was written.
125
    tree = tree.bzrdir.open_workingtree()
126
    tree.lock_read()
127
    self.addCleanup(tree.unlock)
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
128
    if not invalid_delta:
5847.4.12 by John Arbash Meinel
(broken) Expand the test coverage for cases we care about.
129
        tree._validate()
6405.2.9 by Jelmer Vernooij
More test fixes.
130
    return tree.root_inventory
4526.9.1 by Robert Collins
Add WorkingTree.apply_inventory_delta to the set of delta implementations interface tested.
131
132
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
133
def _create_repo_revisions(repo, basis, delta, invalid_delta):
5847.4.12 by John Arbash Meinel
(broken) Expand the test coverage for cases we care about.
134
    repo.start_write_group()
135
    try:
136
        rev = revision.Revision('basis', timestamp=0, timezone=None,
137
            message="", committer="foo@example.com")
138
        basis.revision_id = 'basis'
139
        create_texts_for_inv(repo, basis)
140
        repo.add_revision('basis', rev, basis)
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
141
        if invalid_delta:
5847.4.12 by John Arbash Meinel
(broken) Expand the test coverage for cases we care about.
142
            # We don't want to apply the delta to the basis, because we expect
143
            # the delta is invalid.
144
            result_inv = basis
145
            result_inv.revision_id = 'result'
146
            target_entries = None
147
        else:
148
            result_inv = basis.create_by_apply_delta(delta, 'result')
149
            create_texts_for_inv(repo, result_inv)
150
            target_entries = list(result_inv.iter_entries_by_dir())
151
        rev = revision.Revision('result', timestamp=0, timezone=None,
152
            message="", committer="foo@example.com")
153
        repo.add_revision('result', rev, result_inv)
154
        repo.commit_write_group()
155
    except:
156
        repo.abort_write_group()
157
        raise
158
    return target_entries
159
160
161
def _get_basis_entries(tree):
162
    basis_tree = tree.basis_tree()
163
    basis_tree.lock_read()
164
    basis_tree_entries = list(basis_tree.inventory.iter_entries_by_dir())
165
    basis_tree.unlock()
166
    return basis_tree_entries
167
168
5847.4.13 by John Arbash Meinel
Mostly more test cases, some small progress in getting
169
def _populate_different_tree(tree, basis, delta):
170
    """Put all entries into tree, but at a unique location."""
171
    added_ids = set()
172
    added_paths = set()
173
    tree.add(['unique-dir'], ['unique-dir-id'], ['directory'])
174
    for path, ie in basis.iter_entries_by_dir():
175
        if ie.file_id in added_ids:
176
            continue
177
        # We want a unique path for each of these, we use the file-id
178
        tree.add(['unique-dir/' + ie.file_id], [ie.file_id], [ie.kind])
179
        added_ids.add(ie.file_id)
180
    for old_path, new_path, file_id, ie in delta:
181
        if file_id in added_ids:
182
            continue
183
        tree.add(['unique-dir/' + file_id], [file_id], [ie.kind])
184
185
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
186
def apply_inventory_WT_basis(test, basis, delta, invalid_delta=True):
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
187
    """Apply delta to basis and return the result.
188
189
    This sets the parent and then calls update_basis_by_delta.
4505.5.4 by Robert Collins
Repeated path/id corruption detected.
190
    It also puts the basis in the repository under both 'basis' and 'result' to
191
    allow safety checks made by the WT to succeed, and finally ensures that all
192
    items in the delta with a new path are present in the WT before calling
193
    update_basis_by_delta.
5847.4.12 by John Arbash Meinel
(broken) Expand the test coverage for cases we care about.
194
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
195
    :param basis: An inventory to be used as the basis.
196
    :param delta: The inventory delta to apply:
197
    :return: An inventory resulting from the application.
198
    """
5847.4.12 by John Arbash Meinel
(broken) Expand the test coverage for cases we care about.
199
    control = test.make_bzrdir('tree', format=test.format._matchingbzrdir)
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
200
    control.create_repository()
201
    control.create_branch()
5847.4.12 by John Arbash Meinel
(broken) Expand the test coverage for cases we care about.
202
    tree = test.format.initialize(control)
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
203
    tree.lock_write()
204
    try:
5847.4.12 by John Arbash Meinel
(broken) Expand the test coverage for cases we care about.
205
        target_entries = _create_repo_revisions(tree.branch.repository, basis,
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
206
                                                delta, invalid_delta)
4505.5.5 by Robert Collins
Parents used in a delta must be directories.
207
        # Set the basis state as the trees current state
208
        tree._write_inventory(basis)
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
209
        # This reads basis from the repo and puts it into the tree's local
210
        # cache, if it has one.
211
        tree.set_parent_ids(['basis'])
212
    finally:
213
        tree.unlock()
214
    # Fresh lock, reads disk again.
215
    tree.lock_write()
216
    try:
217
        tree.update_basis_by_delta('result', delta)
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
218
        if not invalid_delta:
5847.4.12 by John Arbash Meinel
(broken) Expand the test coverage for cases we care about.
219
            tree._validate()
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
220
    finally:
221
        tree.unlock()
222
    # reload tree - ensure we get what was written.
223
    tree = tree.bzrdir.open_workingtree()
224
    basis_tree = tree.basis_tree()
225
    basis_tree.lock_read()
5847.4.12 by John Arbash Meinel
(broken) Expand the test coverage for cases we care about.
226
    test.addCleanup(basis_tree.unlock)
6405.2.10 by Jelmer Vernooij
Fix more tests.
227
    basis_inv = basis_tree.root_inventory
5847.4.12 by John Arbash Meinel
(broken) Expand the test coverage for cases we care about.
228
    if target_entries:
229
        basis_entries = list(basis_inv.iter_entries_by_dir())
230
        test.assertEqual(target_entries, basis_entries)
231
    return basis_inv
232
233
234
def apply_inventory_Repository_add_inventory_by_delta(self, basis, delta,
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
235
                                                      invalid_delta=True):
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
236
    """Apply delta to basis and return the result.
237
    
238
    This inserts basis as a whole inventory and then uses
239
    add_inventory_by_delta to add delta.
240
241
    :param basis: An inventory to be used as the basis.
242
    :param delta: The inventory delta to apply:
243
    :return: An inventory resulting from the application.
244
    """
245
    format = self.format()
246
    control = self.make_bzrdir('tree', format=format._matchingbzrdir)
247
    repo = format.initialize(control)
248
    repo.lock_write()
249
    try:
250
        repo.start_write_group()
251
        try:
252
            rev = revision.Revision('basis', timestamp=0, timezone=None,
253
                message="", committer="foo@example.com")
254
            basis.revision_id = 'basis'
4634.35.19 by Andrew Bennetts
Fix test_inv.
255
            create_texts_for_inv(repo, basis)
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
256
            repo.add_revision('basis', rev, basis)
4634.35.19 by Andrew Bennetts
Fix test_inv.
257
            repo.commit_write_group()
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
258
        except:
259
            repo.abort_write_group()
260
            raise
261
    finally:
262
        repo.unlock()
263
    repo.lock_write()
264
    try:
265
        repo.start_write_group()
266
        try:
267
            inv_sha1 = repo.add_inventory_by_delta('basis', delta,
268
                'result', ['basis'])
269
        except:
270
            repo.abort_write_group()
271
            raise
272
        else:
273
            repo.commit_write_group()
274
    finally:
275
        repo.unlock()
276
    # Fresh lock, reads disk again.
277
    repo = repo.bzrdir.open_repository()
278
    repo.lock_read()
279
    self.addCleanup(repo.unlock)
280
    return repo.get_inventory('result')
281
282
4634.51.7 by John Arbash Meinel
Finish adding CHKInventory as a permutation in per_inventory.
283
class TestInventoryUpdates(TestCase):
284
285
    def test_creation_from_root_id(self):
286
        # iff a root id is passed to the constructor, a root directory is made
287
        inv = inventory.Inventory(root_id='tree-root')
288
        self.assertNotEqual(None, inv.root)
289
        self.assertEqual('tree-root', inv.root.file_id)
290
291
    def test_add_path_of_root(self):
292
        # if no root id is given at creation time, there is no root directory
293
        inv = inventory.Inventory(root_id=None)
294
        self.assertIs(None, inv.root)
295
        # add a root entry by adding its path
296
        ie = inv.add_path("", "directory", "my-root")
297
        ie.revision = 'test-rev'
298
        self.assertEqual("my-root", ie.file_id)
299
        self.assertIs(ie, inv.root)
300
301
    def test_add_path(self):
302
        inv = inventory.Inventory(root_id='tree_root')
303
        ie = inv.add_path('hello', 'file', 'hello-id')
304
        self.assertEqual('hello-id', ie.file_id)
305
        self.assertEqual('file', ie.kind)
306
307
    def test_copy(self):
308
        """Make sure copy() works and creates a deep copy."""
309
        inv = inventory.Inventory(root_id='some-tree-root')
310
        ie = inv.add_path('hello', 'file', 'hello-id')
311
        inv2 = inv.copy()
312
        inv.root.file_id = 'some-new-root'
313
        ie.name = 'file2'
314
        self.assertEqual('some-tree-root', inv2.root.file_id)
315
        self.assertEqual('hello', inv2['hello-id'].name)
316
317
    def test_copy_empty(self):
318
        """Make sure an empty inventory can be copied."""
319
        inv = inventory.Inventory(root_id=None)
320
        inv2 = inv.copy()
321
        self.assertIs(None, inv2.root)
322
323
    def test_copy_copies_root_revision(self):
324
        """Make sure the revision of the root gets copied."""
325
        inv = inventory.Inventory(root_id='someroot')
326
        inv.root.revision = 'therev'
327
        inv2 = inv.copy()
328
        self.assertEquals('someroot', inv2.root.file_id)
329
        self.assertEquals('therev', inv2.root.revision)
330
331
    def test_create_tree_reference(self):
332
        inv = inventory.Inventory('tree-root-123')
333
        inv.add(TreeReference('nested-id', 'nested', parent_id='tree-root-123',
334
                              revision='rev', reference_revision='rev2'))
335
336
    def test_error_encoding(self):
337
        inv = inventory.Inventory('tree-root')
338
        inv.add(InventoryFile('a-id', u'\u1234', 'tree-root'))
339
        e = self.assertRaises(errors.InconsistentDelta, inv.add,
340
            InventoryFile('b-id', u'\u1234', 'tree-root'))
341
        self.assertContainsRe(str(e), r'\\u1234')
342
343
    def test_add_recursive(self):
344
        parent = InventoryDirectory('src-id', 'src', 'tree-root')
345
        child = InventoryFile('hello-id', 'hello.c', 'src-id')
346
        parent.children[child.file_id] = child
347
        inv = inventory.Inventory('tree-root')
348
        inv.add(parent)
349
        self.assertEqual('src/hello.c', inv.id2path('hello-id'))
350
351
352
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
353
class TestDeltaApplication(TestCaseWithTransport):
5559.2.2 by Martin Pool
Change to using standard load_tests_apply_scenarios.
354
355
    scenarios = delta_application_scenarios()
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
356
 
357
    def get_empty_inventory(self, reference_inv=None):
358
        """Get an empty inventory.
359
360
        Note that tests should not depend on the revision of the root for
361
        setting up test conditions, as it has to be flexible to accomodate non
362
        rich root repositories.
363
364
        :param reference_inv: If not None, get the revision for the root from
365
            this inventory. This is useful for dealing with older repositories
366
            that routinely discarded the root entry data. If None, the root's
367
            revision is set to 'basis'.
368
        """
369
        inv = inventory.Inventory()
370
        if reference_inv is not None:
371
            inv.root.revision = reference_inv.root.revision
372
        else:
373
            inv.root.revision = 'basis'
374
        return inv
375
5847.4.10 by John Arbash Meinel
A few more bug fixes.
376
    def make_file_ie(self, file_id='file-id', name='name', parent_id=None):
377
        ie_file = inventory.InventoryFile(file_id, name, parent_id)
378
        ie_file.revision = 'result'
379
        ie_file.text_size = 0
380
        ie_file.text_sha1 = ''
381
        return ie_file
382
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
383
    def test_empty_delta(self):
384
        inv = self.get_empty_inventory()
385
        delta = []
386
        inv = self.apply_delta(self, inv, delta)
387
        inv2 = self.get_empty_inventory(inv)
388
        self.assertEqual([], inv2._make_delta(inv))
389
4526.9.22 by Robert Collins
Check fileids in inventory deltas are not None and are strings.
390
    def test_None_file_id(self):
391
        inv = self.get_empty_inventory()
392
        dir1 = inventory.InventoryDirectory(None, 'dir1', inv.root.file_id)
393
        dir1.revision = 'result'
394
        delta = [(None, u'dir1', None, dir1)]
395
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
396
            inv, delta)
397
398
    def test_unicode_file_id(self):
399
        inv = self.get_empty_inventory()
400
        dir1 = inventory.InventoryDirectory(u'dirid', 'dir1', inv.root.file_id)
401
        dir1.revision = 'result'
402
        delta = [(None, u'dir1', dir1.file_id, dir1)]
403
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
404
            inv, delta)
405
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
406
    def test_repeated_file_id(self):
407
        inv = self.get_empty_inventory()
408
        file1 = inventory.InventoryFile('id', 'path1', inv.root.file_id)
409
        file1.revision = 'result'
410
        file1.text_size = 0
411
        file1.text_sha1 = ""
5847.4.10 by John Arbash Meinel
A few more bug fixes.
412
        file2 = file1.copy()
413
        file2.name = 'path2'
4505.5.7 by Robert Collins
Handle unicode parents correctly in dirstate parent checking.
414
        delta = [(None, u'path1', 'id', file1), (None, u'path2', 'id', file2)]
4505.5.3 by Robert Collins
Test infrastructure for testing all inventory delta applications and fix CHK inventories to reject repeated file ids in deltas.
415
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
416
            inv, delta)
963 by Martin Pool
- add the start of a test for inventory file-id matching
417
4505.5.4 by Robert Collins
Repeated path/id corruption detected.
418
    def test_repeated_new_path(self):
419
        inv = self.get_empty_inventory()
420
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
421
        file1.revision = 'result'
422
        file1.text_size = 0
423
        file1.text_sha1 = ""
5847.4.10 by John Arbash Meinel
A few more bug fixes.
424
        file2 = file1.copy()
425
        file2.file_id = 'id2'
4505.5.7 by Robert Collins
Handle unicode parents correctly in dirstate parent checking.
426
        delta = [(None, u'path', 'id1', file1), (None, u'path', 'id2', file2)]
4505.5.4 by Robert Collins
Repeated path/id corruption detected.
427
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
428
            inv, delta)
429
430
    def test_repeated_old_path(self):
431
        inv = self.get_empty_inventory()
432
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
433
        file1.revision = 'result'
434
        file1.text_size = 0
435
        file1.text_sha1 = ""
436
        # We can't *create* a source inventory with the same path, but
437
        # a badly generated partial delta might claim the same source twice.
438
        # This would be buggy in two ways: the path is repeated in the delta,
439
        # And the path for one of the file ids doesn't match the source
440
        # location. Alternatively, we could have a repeated fileid, but that
441
        # is separately checked for.
442
        file2 = inventory.InventoryFile('id2', 'path2', inv.root.file_id)
443
        file2.revision = 'result'
444
        file2.text_size = 0
445
        file2.text_sha1 = ""
446
        inv.add(file1)
447
        inv.add(file2)
4505.5.7 by Robert Collins
Handle unicode parents correctly in dirstate parent checking.
448
        delta = [(u'path', None, 'id1', None), (u'path', None, 'id2', None)]
4505.5.4 by Robert Collins
Repeated path/id corruption detected.
449
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
450
            inv, delta)
451
452
    def test_mismatched_id_entry_id(self):
453
        inv = self.get_empty_inventory()
454
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
455
        file1.revision = 'result'
456
        file1.text_size = 0
457
        file1.text_sha1 = ""
4505.5.7 by Robert Collins
Handle unicode parents correctly in dirstate parent checking.
458
        delta = [(None, u'path', 'id', file1)]
4505.5.4 by Robert Collins
Repeated path/id corruption detected.
459
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
460
            inv, delta)
461
4526.9.4 by Robert Collins
Look for trivial issues with new_path and entry being out of sync in deltas.
462
    def test_mismatched_new_path_entry_None(self):
463
        inv = self.get_empty_inventory()
464
        delta = [(None, u'path', 'id', None)]
465
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
466
            inv, delta)
467
468
    def test_mismatched_new_path_None_entry(self):
469
        inv = self.get_empty_inventory()
470
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
471
        file1.revision = 'result'
472
        file1.text_size = 0
473
        file1.text_sha1 = ""
474
        delta = [(u"path", None, 'id1', file1)]
475
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
476
            inv, delta)
477
4505.5.5 by Robert Collins
Parents used in a delta must be directories.
478
    def test_parent_is_not_directory(self):
479
        inv = self.get_empty_inventory()
480
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
481
        file1.revision = 'result'
482
        file1.text_size = 0
483
        file1.text_sha1 = ""
484
        file2 = inventory.InventoryFile('id2', 'path2', 'id1')
485
        file2.revision = 'result'
486
        file2.text_size = 0
487
        file2.text_sha1 = ""
488
        inv.add(file1)
4505.5.7 by Robert Collins
Handle unicode parents correctly in dirstate parent checking.
489
        delta = [(None, u'path/path2', 'id2', file2)]
4505.5.5 by Robert Collins
Parents used in a delta must be directories.
490
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
491
            inv, delta)
492
4505.5.6 by Robert Collins
Check for missing parents in deltas.
493
    def test_parent_is_missing(self):
494
        inv = self.get_empty_inventory()
495
        file2 = inventory.InventoryFile('id2', 'path2', 'missingparent')
496
        file2.revision = 'result'
497
        file2.text_size = 0
498
        file2.text_sha1 = ""
4505.5.7 by Robert Collins
Handle unicode parents correctly in dirstate parent checking.
499
        delta = [(None, u'path/path2', 'id2', file2)]
4505.5.6 by Robert Collins
Check for missing parents in deltas.
500
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
501
            inv, delta)
502
4526.9.2 by Robert Collins
Handle deltas with new paths not matching the actual path.
503
    def test_new_parent_path_has_wrong_id(self):
504
        inv = self.get_empty_inventory()
505
        parent1 = inventory.InventoryDirectory('p-1', 'dir', inv.root.file_id)
506
        parent1.revision = 'result'
507
        parent2 = inventory.InventoryDirectory('p-2', 'dir2', inv.root.file_id)
508
        parent2.revision = 'result'
509
        file1 = inventory.InventoryFile('id', 'path', 'p-2')
510
        file1.revision = 'result'
511
        file1.text_size = 0
512
        file1.text_sha1 = ""
513
        inv.add(parent1)
514
        inv.add(parent2)
515
        # This delta claims that file1 is at dir/path, but actually its at
516
        # dir2/path if you follow the inventory parent structure.
517
        delta = [(None, u'dir/path', 'id', file1)]
518
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
519
            inv, delta)
520
4526.9.3 by Robert Collins
Handle mismatches between inventory delta paths and actual paths found by traversing parent pointers.
521
    def test_old_parent_path_is_wrong(self):
522
        inv = self.get_empty_inventory()
523
        parent1 = inventory.InventoryDirectory('p-1', 'dir', inv.root.file_id)
524
        parent1.revision = 'result'
525
        parent2 = inventory.InventoryDirectory('p-2', 'dir2', inv.root.file_id)
526
        parent2.revision = 'result'
527
        file1 = inventory.InventoryFile('id', 'path', 'p-2')
528
        file1.revision = 'result'
529
        file1.text_size = 0
530
        file1.text_sha1 = ""
531
        inv.add(parent1)
532
        inv.add(parent2)
533
        inv.add(file1)
534
        # This delta claims that file1 was at dir/path, but actually it was at
535
        # dir2/path if you follow the inventory parent structure.
536
        delta = [(u'dir/path', None, 'id', None)]
537
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
538
            inv, delta)
539
540
    def test_old_parent_path_is_for_other_id(self):
541
        inv = self.get_empty_inventory()
542
        parent1 = inventory.InventoryDirectory('p-1', 'dir', inv.root.file_id)
543
        parent1.revision = 'result'
544
        parent2 = inventory.InventoryDirectory('p-2', 'dir2', inv.root.file_id)
545
        parent2.revision = 'result'
546
        file1 = inventory.InventoryFile('id', 'path', 'p-2')
547
        file1.revision = 'result'
548
        file1.text_size = 0
549
        file1.text_sha1 = ""
550
        file2 = inventory.InventoryFile('id2', 'path', 'p-1')
551
        file2.revision = 'result'
552
        file2.text_size = 0
553
        file2.text_sha1 = ""
554
        inv.add(parent1)
555
        inv.add(parent2)
556
        inv.add(file1)
557
        inv.add(file2)
558
        # This delta claims that file1 was at dir/path, but actually it was at
559
        # dir2/path if you follow the inventory parent structure. At dir/path
560
        # is another entry we should not delete.
561
        delta = [(u'dir/path', None, 'id', None)]
562
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
563
            inv, delta)
564
4526.9.5 by Robert Collins
Require that added ids in inventory deltas be new.
565
    def test_add_existing_id_new_path(self):
566
        inv = self.get_empty_inventory()
567
        parent1 = inventory.InventoryDirectory('p-1', 'dir1', inv.root.file_id)
568
        parent1.revision = 'result'
569
        parent2 = inventory.InventoryDirectory('p-1', 'dir2', inv.root.file_id)
570
        parent2.revision = 'result'
571
        inv.add(parent1)
572
        delta = [(None, u'dir2', 'p-1', parent2)]
573
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
574
            inv, delta)
575
4526.9.8 by Robert Collins
Check that the paths deltas put entries into are not in use already.
576
    def test_add_new_id_existing_path(self):
577
        inv = self.get_empty_inventory()
578
        parent1 = inventory.InventoryDirectory('p-1', 'dir1', inv.root.file_id)
579
        parent1.revision = 'result'
580
        parent2 = inventory.InventoryDirectory('p-2', 'dir1', inv.root.file_id)
581
        parent2.revision = 'result'
582
        inv.add(parent1)
583
        delta = [(None, u'dir1', 'p-2', parent2)]
584
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
585
            inv, delta)
586
4526.9.9 by Robert Collins
Add interface tests for dangling children in inventory deltas.
587
    def test_remove_dir_leaving_dangling_child(self):
588
        inv = self.get_empty_inventory()
589
        dir1 = inventory.InventoryDirectory('p-1', 'dir1', inv.root.file_id)
590
        dir1.revision = 'result'
591
        dir2 = inventory.InventoryDirectory('p-2', 'child1', 'p-1')
592
        dir2.revision = 'result'
593
        dir3 = inventory.InventoryDirectory('p-3', 'child2', 'p-1')
594
        dir3.revision = 'result'
595
        inv.add(dir1)
596
        inv.add(dir2)
597
        inv.add(dir3)
598
        delta = [(u'dir1', None, 'p-1', None),
599
            (u'dir1/child2', None, 'p-3', None)]
600
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
601
            inv, delta)
602
5876.1.1 by John Arbash Meinel
Fix bug #781168, and allow WT.update_basis_by_delta
603
    def test_add_file(self):
604
        inv = self.get_empty_inventory()
605
        file1 = inventory.InventoryFile('file-id', 'path', inv.root.file_id)
606
        file1.revision = 'result'
607
        file1.text_size = 0
608
        file1.text_sha1 = ''
609
        delta = [(None, u'path', 'file-id', file1)]
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
610
        res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
5876.1.1 by John Arbash Meinel
Fix bug #781168, and allow WT.update_basis_by_delta
611
        self.assertEqual('file-id', res_inv['file-id'].file_id)
612
613
    def test_remove_file(self):
614
        inv = self.get_empty_inventory()
615
        file1 = inventory.InventoryFile('file-id', 'path', inv.root.file_id)
616
        file1.revision = 'result'
617
        file1.text_size = 0
618
        file1.text_sha1 = ''
619
        inv.add(file1)
620
        delta = [(u'path', None, 'file-id', None)]
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
621
        res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
5876.1.1 by John Arbash Meinel
Fix bug #781168, and allow WT.update_basis_by_delta
622
        self.assertEqual(None, res_inv.path2id('path'))
623
        self.assertRaises(errors.NoSuchId, res_inv.id2path, 'file-id')
624
625
    def test_rename_file(self):
626
        inv = self.get_empty_inventory()
5847.4.10 by John Arbash Meinel
A few more bug fixes.
627
        file1 = self.make_file_ie(name='path', parent_id=inv.root.file_id)
5876.1.1 by John Arbash Meinel
Fix bug #781168, and allow WT.update_basis_by_delta
628
        inv.add(file1)
5847.4.10 by John Arbash Meinel
A few more bug fixes.
629
        file2 = self.make_file_ie(name='path2', parent_id=inv.root.file_id)
5876.1.1 by John Arbash Meinel
Fix bug #781168, and allow WT.update_basis_by_delta
630
        delta = [(u'path', 'path2', 'file-id', file2)]
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
631
        res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
5876.1.1 by John Arbash Meinel
Fix bug #781168, and allow WT.update_basis_by_delta
632
        self.assertEqual(None, res_inv.path2id('path'))
633
        self.assertEqual('file-id', res_inv.path2id('path2'))
4634.51.7 by John Arbash Meinel
Finish adding CHKInventory as a permutation in per_inventory.
634
5847.4.10 by John Arbash Meinel
A few more bug fixes.
635
    def test_replaced_at_new_path(self):
636
        inv = self.get_empty_inventory()
637
        file1 = self.make_file_ie(file_id='id1', parent_id=inv.root.file_id)
638
        inv.add(file1)
639
        file2 = self.make_file_ie(file_id='id2', parent_id=inv.root.file_id)
640
        delta = [(u'name', None, 'id1', None),
641
                 (None, u'name', 'id2', file2)]
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
642
        res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
5847.4.10 by John Arbash Meinel
A few more bug fixes.
643
        self.assertEqual('id2', res_inv.path2id('name'))
644
5847.4.13 by John Arbash Meinel
Mostly more test cases, some small progress in getting
645
    def test_rename_dir(self):
646
        inv = self.get_empty_inventory()
647
        dir1 = inventory.InventoryDirectory('dir-id', 'dir1', inv.root.file_id)
648
        dir1.revision = 'basis'
649
        file1 = self.make_file_ie(parent_id='dir-id')
650
        inv.add(dir1)
651
        inv.add(file1)
652
        dir2 = inventory.InventoryDirectory('dir-id', 'dir2', inv.root.file_id)
653
        dir2.revision = 'result'
654
        delta = [('dir1', 'dir2', 'dir-id', dir2)]
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
655
        res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
5847.4.13 by John Arbash Meinel
Mostly more test cases, some small progress in getting
656
        # The file should be accessible under the new path
657
        self.assertEqual('file-id', res_inv.path2id('dir2/name'))
658
659
    def test_renamed_dir_with_renamed_child(self):
660
        inv = self.get_empty_inventory()
661
        dir1 = inventory.InventoryDirectory('dir-id', 'dir1', inv.root.file_id)
662
        dir1.revision = 'basis'
663
        file1 = self.make_file_ie('file-id-1', 'name1', parent_id='dir-id')
664
        file2 = self.make_file_ie('file-id-2', 'name2', parent_id='dir-id')
665
        inv.add(dir1)
666
        inv.add(file1)
667
        inv.add(file2)
668
        dir2 = inventory.InventoryDirectory('dir-id', 'dir2', inv.root.file_id)
669
        dir2.revision = 'result'
670
        file2b = self.make_file_ie('file-id-2', 'name2', inv.root.file_id)
671
        delta = [('dir1', 'dir2', 'dir-id', dir2),
672
                 ('dir1/name2', 'name2', 'file-id-2', file2b)]
5847.4.35 by John Arbash Meinel
Rename 'expect_fail' to 'invalid_delta' as suggested by Jelmer
673
        res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
5847.4.13 by John Arbash Meinel
Mostly more test cases, some small progress in getting
674
        # The file should be accessible under the new path
675
        self.assertEqual('file-id-1', res_inv.path2id('dir2/name1'))
676
        self.assertEqual(None, res_inv.path2id('dir2/name2'))
677
        self.assertEqual('file-id-2', res_inv.path2id('name2'))
678
4634.51.7 by John Arbash Meinel
Finish adding CHKInventory as a permutation in per_inventory.
679
    def test_is_root(self):
680
        """Ensure our root-checking code is accurate."""
681
        inv = inventory.Inventory('TREE_ROOT')
682
        self.assertTrue(inv.is_root('TREE_ROOT'))
683
        self.assertFalse(inv.is_root('booga'))
684
        inv.root.file_id = 'booga'
685
        self.assertFalse(inv.is_root('TREE_ROOT'))
686
        self.assertTrue(inv.is_root('booga'))
687
        # works properly even if no root is set
688
        inv.root = None
689
        self.assertFalse(inv.is_root('TREE_ROOT'))
690
        self.assertFalse(inv.is_root('booga'))
691
5410.1.2 by Daniel Knittl-Frank
Add a test case for `entries()` on empty inventory
692
    def test_entries_for_empty_inventory(self):
693
        """Test that entries() will not fail for an empty inventory"""
5410.1.3 by Daniel Knittl-Frank
fix whitespace (only use spaces)
694
        inv = Inventory(root_id=None)
695
        self.assertEqual([], inv.entries())
5410.1.2 by Daniel Knittl-Frank
Add a test case for `entries()` on empty inventory
696
4634.51.7 by John Arbash Meinel
Finish adding CHKInventory as a permutation in per_inventory.
697
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
698
class TestInventoryEntry(TestCase):
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
699
6478.3.3 by Jelmer Vernooij
Support backslash filenames in Inventory.
700
    def test_file_invalid_entry_name(self):
701
        self.assertRaises(errors.InvalidEntryName, inventory.InventoryFile,
702
            '123', 'a/hello.c', ROOT_ID)
703
704
    def test_file_backslash(self):
705
        file = inventory.InventoryFile('123', 'h\\ello.c', ROOT_ID)
706
        self.assertEquals(file.name, 'h\\ello.c')
707
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
708
    def test_file_kind_character(self):
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
709
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
710
        self.assertEqual(file.kind_character(), '')
711
712
    def test_dir_kind_character(self):
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
713
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
714
        self.assertEqual(dir.kind_character(), '/')
715
716
    def test_link_kind_character(self):
1399.1.10 by Robert Collins
remove kind from the InventoryEntry constructor - only child classes should be created now
717
        dir = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
718
        self.assertEqual(dir.kind_character(), '')
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
719
720
    def test_dir_detect_changes(self):
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
721
        left = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
722
        right = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
723
        self.assertEqual((False, False), left.detect_changes(right))
724
        self.assertEqual((False, False), right.detect_changes(left))
725
726
    def test_file_detect_changes(self):
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
727
        left = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
728
        left.text_sha1 = 123
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
729
        right = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
730
        right.text_sha1 = 123
731
        self.assertEqual((False, False), left.detect_changes(right))
732
        self.assertEqual((False, False), right.detect_changes(left))
733
        left.executable = True
734
        self.assertEqual((False, True), left.detect_changes(right))
735
        self.assertEqual((False, True), right.detect_changes(left))
736
        right.text_sha1 = 321
737
        self.assertEqual((True, True), left.detect_changes(right))
738
        self.assertEqual((True, True), right.detect_changes(left))
739
740
    def test_symlink_detect_changes(self):
1399.1.10 by Robert Collins
remove kind from the InventoryEntry constructor - only child classes should be created now
741
        left = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
742
        left.symlink_target='foo'
1399.1.10 by Robert Collins
remove kind from the InventoryEntry constructor - only child classes should be created now
743
        right = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
744
        right.symlink_target='foo'
745
        self.assertEqual((False, False), left.detect_changes(right))
746
        self.assertEqual((False, False), right.detect_changes(left))
747
        left.symlink_target = 'different'
748
        self.assertEqual((True, False), left.detect_changes(right))
749
        self.assertEqual((True, False), right.detect_changes(left))
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
750
1399.1.5 by Robert Collins
move checking whether an entry stores text into inventory.py from fetch,py
751
    def test_file_has_text(self):
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
752
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
753
        self.assertTrue(file.has_text())
1399.1.5 by Robert Collins
move checking whether an entry stores text into inventory.py from fetch,py
754
755
    def test_directory_has_text(self):
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
756
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
757
        self.assertFalse(dir.has_text())
1399.1.5 by Robert Collins
move checking whether an entry stores text into inventory.py from fetch,py
758
759
    def test_link_has_text(self):
1399.1.10 by Robert Collins
remove kind from the InventoryEntry constructor - only child classes should be created now
760
        link = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
761
        self.assertFalse(link.has_text())
1399.1.5 by Robert Collins
move checking whether an entry stores text into inventory.py from fetch,py
762
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
763
    def test_make_entry(self):
764
        self.assertIsInstance(inventory.make_entry("file", "name", ROOT_ID),
765
            inventory.InventoryFile)
766
        self.assertIsInstance(inventory.make_entry("symlink", "name", ROOT_ID),
767
            inventory.InventoryLink)
768
        self.assertIsInstance(inventory.make_entry("directory", "name", ROOT_ID),
769
            inventory.InventoryDirectory)
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
770
1830.3.5 by John Arbash Meinel
make_entry refuses to create non-normalized entries.
771
    def test_make_entry_non_normalized(self):
772
        orig_normalized_filename = osutils.normalized_filename
773
774
        try:
775
            osutils.normalized_filename = osutils._accessible_normalized_filename
776
            entry = inventory.make_entry("file", u'a\u030a', ROOT_ID)
777
            self.assertEqual(u'\xe5', entry.name)
778
            self.assertIsInstance(entry, inventory.InventoryFile)
779
780
            osutils.normalized_filename = osutils._inaccessible_normalized_filename
781
            self.assertRaises(errors.InvalidNormalization,
782
                    inventory.make_entry, 'file', u'a\u030a', ROOT_ID)
783
        finally:
784
            osutils.normalized_filename = orig_normalized_filename
785
786
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
787
class TestDescribeChanges(TestCase):
788
789
    def test_describe_change(self):
790
        # we need to test the following change combinations:
791
        # rename
792
        # reparent
793
        # modify
794
        # gone
795
        # added
796
        # renamed/reparented and modified
797
        # change kind (perhaps can't be done yet?)
798
        # also, merged in combination with all of these?
799
        old_a = InventoryFile('a-id', 'a_file', ROOT_ID)
800
        old_a.text_sha1 = '123132'
801
        old_a.text_size = 0
802
        new_a = InventoryFile('a-id', 'a_file', ROOT_ID)
803
        new_a.text_sha1 = '123132'
804
        new_a.text_size = 0
805
806
        self.assertChangeDescription('unchanged', old_a, new_a)
807
808
        new_a.text_size = 10
809
        new_a.text_sha1 = 'abcabc'
810
        self.assertChangeDescription('modified', old_a, new_a)
811
812
        self.assertChangeDescription('added', None, new_a)
813
        self.assertChangeDescription('removed', old_a, None)
814
        # perhaps a bit questionable but seems like the most reasonable thing...
815
        self.assertChangeDescription('unchanged', None, None)
816
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
817
        # in this case it's both renamed and modified; show a rename and
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
818
        # modification:
819
        new_a.name = 'newfilename'
820
        self.assertChangeDescription('modified and renamed', old_a, new_a)
821
822
        # reparenting is 'renaming'
823
        new_a.name = old_a.name
824
        new_a.parent_id = 'somedir-id'
825
        self.assertChangeDescription('modified and renamed', old_a, new_a)
826
827
        # reset the content values so its not modified
828
        new_a.text_size = old_a.text_size
829
        new_a.text_sha1 = old_a.text_sha1
830
        new_a.name = old_a.name
831
832
        new_a.name = 'newfilename'
833
        self.assertChangeDescription('renamed', old_a, new_a)
834
835
        # reparenting is 'renaming'
836
        new_a.name = old_a.name
837
        new_a.parent_id = 'somedir-id'
838
        self.assertChangeDescription('renamed', old_a, new_a)
839
840
    def assertChangeDescription(self, expected_change, old_ie, new_ie):
841
        change = InventoryEntry.describe_change(old_ie, new_ie)
842
        self.assertEqual(expected_change, change)
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
843
844
4634.51.1 by John Arbash Meinel
Switch away from creating a whole repository just to get a VF.
845
class TestCHKInventory(tests.TestCaseWithMemoryTransport):
3735.2.99 by John Arbash Meinel
Merge bzr.dev 4034. Whitespace cleanup
846
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
847
    def get_chk_bytes(self):
4634.51.1 by John Arbash Meinel
Switch away from creating a whole repository just to get a VF.
848
        factory = groupcompress.make_pack_factory(True, True, 1)
849
        trans = self.get_transport('')
850
        return factory(trans)
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
851
852
    def read_bytes(self, chk_bytes, key):
853
        stream = chk_bytes.get_record_stream([key], 'unordered', True)
854
        return stream.next().get_bytes_as("fulltext")
855
856
    def test_deserialise_gives_CHKInventory(self):
857
        inv = Inventory()
858
        inv.revision_id = "revid"
859
        inv.root.revision = "rootrev"
860
        chk_bytes = self.get_chk_bytes()
861
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
862
        bytes = ''.join(chk_inv.to_lines())
863
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
864
        self.assertEqual("revid", new_inv.revision_id)
865
        self.assertEqual("directory", new_inv.root.kind)
866
        self.assertEqual(inv.root.file_id, new_inv.root.file_id)
867
        self.assertEqual(inv.root.parent_id, new_inv.root.parent_id)
868
        self.assertEqual(inv.root.name, new_inv.root.name)
869
        self.assertEqual("rootrev", new_inv.root.revision)
3735.16.7 by John Arbash Meinel
Start parameterizing CHKInventory and CHKSerializer so that we can
870
        self.assertEqual('plain', new_inv._search_key_name)
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
871
872
    def test_deserialise_wrong_revid(self):
873
        inv = Inventory()
874
        inv.revision_id = "revid"
875
        inv.root.revision = "rootrev"
876
        chk_bytes = self.get_chk_bytes()
877
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
878
        bytes = ''.join(chk_inv.to_lines())
879
        self.assertRaises(ValueError, CHKInventory.deserialise, chk_bytes,
880
            bytes, ("revid2",))
881
882
    def test_captures_rev_root_byid(self):
883
        inv = Inventory()
884
        inv.revision_id = "foo"
885
        inv.root.revision = "bar"
886
        chk_bytes = self.get_chk_bytes()
887
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
3735.16.7 by John Arbash Meinel
Start parameterizing CHKInventory and CHKSerializer so that we can
888
        lines = chk_inv.to_lines()
889
        self.assertEqual([
890
            'chkinventory:\n',
891
            'revision_id: foo\n',
892
            'root_id: TREE_ROOT\n',
3735.2.132 by John Arbash Meinel
Remove references to parent_id_basename_index, now that we know we want it.
893
            'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
3735.17.11 by John Arbash Meinel
Actually format the inventories using line-based separation.
894
            'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
3735.16.7 by John Arbash Meinel
Start parameterizing CHKInventory and CHKSerializer so that we can
895
            ], lines)
896
        chk_inv = CHKInventory.deserialise(chk_bytes, ''.join(lines), ('foo',))
897
        self.assertEqual('plain', chk_inv._search_key_name)
898
899
    def test_captures_parent_id_basename_index(self):
900
        inv = Inventory()
901
        inv.revision_id = "foo"
902
        inv.root.revision = "bar"
903
        chk_bytes = self.get_chk_bytes()
3735.2.132 by John Arbash Meinel
Remove references to parent_id_basename_index, now that we know we want it.
904
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
3735.16.7 by John Arbash Meinel
Start parameterizing CHKInventory and CHKSerializer so that we can
905
        lines = chk_inv.to_lines()
906
        self.assertEqual([
907
            'chkinventory:\n',
908
            'revision_id: foo\n',
909
            'root_id: TREE_ROOT\n',
3735.17.8 by John Arbash Meinel
Most direct tests are now passing.
910
            'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
3735.17.11 by John Arbash Meinel
Actually format the inventories using line-based separation.
911
            'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
3735.16.7 by John Arbash Meinel
Start parameterizing CHKInventory and CHKSerializer so that we can
912
            ], lines)
913
        chk_inv = CHKInventory.deserialise(chk_bytes, ''.join(lines), ('foo',))
914
        self.assertEqual('plain', chk_inv._search_key_name)
915
916
    def test_captures_search_key_name(self):
917
        inv = Inventory()
918
        inv.revision_id = "foo"
919
        inv.root.revision = "bar"
920
        chk_bytes = self.get_chk_bytes()
921
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv,
922
                                              search_key_name='hash-16-way')
923
        lines = chk_inv.to_lines()
924
        self.assertEqual([
925
            'chkinventory:\n',
926
            'search_key_name: hash-16-way\n',
3735.24.2 by John Arbash Meinel
Add a bit more strictness to the formatting, update the test case.
927
            'root_id: TREE_ROOT\n',
3735.17.8 by John Arbash Meinel
Most direct tests are now passing.
928
            'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
3735.24.2 by John Arbash Meinel
Add a bit more strictness to the formatting, update the test case.
929
            'revision_id: foo\n',
3735.17.11 by John Arbash Meinel
Actually format the inventories using line-based separation.
930
            'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
3735.16.7 by John Arbash Meinel
Start parameterizing CHKInventory and CHKSerializer so that we can
931
            ], lines)
932
        chk_inv = CHKInventory.deserialise(chk_bytes, ''.join(lines), ('foo',))
933
        self.assertEqual('hash-16-way', chk_inv._search_key_name)
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
934
935
    def test_directory_children_on_demand(self):
936
        inv = Inventory()
937
        inv.revision_id = "revid"
938
        inv.root.revision = "rootrev"
939
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
940
        inv["fileid"].revision = "filerev"
941
        inv["fileid"].executable = True
942
        inv["fileid"].text_sha1 = "ffff"
943
        inv["fileid"].text_size = 1
944
        chk_bytes = self.get_chk_bytes()
945
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
946
        bytes = ''.join(chk_inv.to_lines())
947
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
948
        root_entry = new_inv[inv.root.file_id]
949
        self.assertEqual(None, root_entry._children)
950
        self.assertEqual(['file'], root_entry.children.keys())
951
        file_direct = new_inv["fileid"]
952
        file_found = root_entry.children['file']
953
        self.assertEqual(file_direct.kind, file_found.kind)
954
        self.assertEqual(file_direct.file_id, file_found.file_id)
955
        self.assertEqual(file_direct.parent_id, file_found.parent_id)
956
        self.assertEqual(file_direct.name, file_found.name)
957
        self.assertEqual(file_direct.revision, file_found.revision)
958
        self.assertEqual(file_direct.text_sha1, file_found.text_sha1)
959
        self.assertEqual(file_direct.text_size, file_found.text_size)
960
        self.assertEqual(file_direct.executable, file_found.executable)
961
3735.2.27 by Robert Collins
Use 4K pages for development3 repositories.
962
    def test_from_inventory_maximum_size(self):
963
        # from_inventory supports the maximum_size parameter.
964
        inv = Inventory()
965
        inv.revision_id = "revid"
966
        inv.root.revision = "rootrev"
967
        chk_bytes = self.get_chk_bytes()
968
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv, 120)
4413.5.10 by John Arbash Meinel
Clean upt the test_inv tests that assumed _root_node was real and not just a key.
969
        chk_inv.id_to_entry._ensure_root()
3735.2.27 by Robert Collins
Use 4K pages for development3 repositories.
970
        self.assertEqual(120, chk_inv.id_to_entry._root_node.maximum_size)
4413.5.10 by John Arbash Meinel
Clean upt the test_inv tests that assumed _root_node was real and not just a key.
971
        self.assertEqual(1, chk_inv.id_to_entry._root_node._key_width)
972
        p_id_basename = chk_inv.parent_id_basename_to_file_id
973
        p_id_basename._ensure_root()
974
        self.assertEqual(120, p_id_basename._root_node.maximum_size)
975
        self.assertEqual(2, p_id_basename._root_node._key_width)
3735.2.27 by Robert Collins
Use 4K pages for development3 repositories.
976
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
977
    def test___iter__(self):
978
        inv = Inventory()
979
        inv.revision_id = "revid"
980
        inv.root.revision = "rootrev"
981
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
982
        inv["fileid"].revision = "filerev"
983
        inv["fileid"].executable = True
984
        inv["fileid"].text_sha1 = "ffff"
985
        inv["fileid"].text_size = 1
986
        chk_bytes = self.get_chk_bytes()
987
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
988
        bytes = ''.join(chk_inv.to_lines())
989
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
990
        fileids = list(new_inv.__iter__())
991
        fileids.sort()
992
        self.assertEqual([inv.root.file_id, "fileid"], fileids)
993
994
    def test__len__(self):
995
        inv = Inventory()
996
        inv.revision_id = "revid"
997
        inv.root.revision = "rootrev"
998
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
999
        inv["fileid"].revision = "filerev"
1000
        inv["fileid"].executable = True
1001
        inv["fileid"].text_sha1 = "ffff"
1002
        inv["fileid"].text_size = 1
1003
        chk_bytes = self.get_chk_bytes()
1004
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1005
        self.assertEqual(2, len(chk_inv))
1006
1007
    def test___getitem__(self):
1008
        inv = Inventory()
1009
        inv.revision_id = "revid"
1010
        inv.root.revision = "rootrev"
1011
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
1012
        inv["fileid"].revision = "filerev"
1013
        inv["fileid"].executable = True
1014
        inv["fileid"].text_sha1 = "ffff"
1015
        inv["fileid"].text_size = 1
1016
        chk_bytes = self.get_chk_bytes()
1017
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1018
        bytes = ''.join(chk_inv.to_lines())
1019
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1020
        root_entry = new_inv[inv.root.file_id]
1021
        file_entry = new_inv["fileid"]
1022
        self.assertEqual("directory", root_entry.kind)
1023
        self.assertEqual(inv.root.file_id, root_entry.file_id)
1024
        self.assertEqual(inv.root.parent_id, root_entry.parent_id)
1025
        self.assertEqual(inv.root.name, root_entry.name)
1026
        self.assertEqual("rootrev", root_entry.revision)
1027
        self.assertEqual("file", file_entry.kind)
1028
        self.assertEqual("fileid", file_entry.file_id)
1029
        self.assertEqual(inv.root.file_id, file_entry.parent_id)
1030
        self.assertEqual("file", file_entry.name)
1031
        self.assertEqual("filerev", file_entry.revision)
1032
        self.assertEqual("ffff", file_entry.text_sha1)
1033
        self.assertEqual(1, file_entry.text_size)
1034
        self.assertEqual(True, file_entry.executable)
3735.2.53 by Robert Collins
Support Inventory.__getitem__ more consistently.
1035
        self.assertRaises(errors.NoSuchId, new_inv.__getitem__, 'missing')
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
1036
1037
    def test_has_id_true(self):
1038
        inv = Inventory()
1039
        inv.revision_id = "revid"
1040
        inv.root.revision = "rootrev"
1041
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
1042
        inv["fileid"].revision = "filerev"
1043
        inv["fileid"].executable = True
1044
        inv["fileid"].text_sha1 = "ffff"
1045
        inv["fileid"].text_size = 1
1046
        chk_bytes = self.get_chk_bytes()
1047
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1048
        self.assertTrue(chk_inv.has_id('fileid'))
1049
        self.assertTrue(chk_inv.has_id(inv.root.file_id))
1050
1051
    def test_has_id_not(self):
1052
        inv = Inventory()
1053
        inv.revision_id = "revid"
1054
        inv.root.revision = "rootrev"
1055
        chk_bytes = self.get_chk_bytes()
1056
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1057
        self.assertFalse(chk_inv.has_id('fileid'))
3735.2.10 by Robert Collins
Teach CHKInventory how to make a new inventory from an inventory delta.
1058
3735.2.12 by Robert Collins
Implement commit-via-deltas for split inventory repositories.
1059
    def test_id2path(self):
1060
        inv = Inventory()
1061
        inv.revision_id = "revid"
1062
        inv.root.revision = "rootrev"
1063
        direntry = InventoryDirectory("dirid", "dir", inv.root.file_id)
1064
        fileentry = InventoryFile("fileid", "file", "dirid")
1065
        inv.add(direntry)
1066
        inv.add(fileentry)
1067
        inv["fileid"].revision = "filerev"
1068
        inv["fileid"].executable = True
1069
        inv["fileid"].text_sha1 = "ffff"
1070
        inv["fileid"].text_size = 1
1071
        inv["dirid"].revision = "filerev"
1072
        chk_bytes = self.get_chk_bytes()
1073
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1074
        bytes = ''.join(chk_inv.to_lines())
1075
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1076
        self.assertEqual('', new_inv.id2path(inv.root.file_id))
1077
        self.assertEqual('dir', new_inv.id2path('dirid'))
1078
        self.assertEqual('dir/file', new_inv.id2path('fileid'))
1079
1080
    def test_path2id(self):
1081
        inv = Inventory()
1082
        inv.revision_id = "revid"
1083
        inv.root.revision = "rootrev"
1084
        direntry = InventoryDirectory("dirid", "dir", inv.root.file_id)
1085
        fileentry = InventoryFile("fileid", "file", "dirid")
1086
        inv.add(direntry)
1087
        inv.add(fileentry)
1088
        inv["fileid"].revision = "filerev"
1089
        inv["fileid"].executable = True
1090
        inv["fileid"].text_sha1 = "ffff"
1091
        inv["fileid"].text_size = 1
1092
        inv["dirid"].revision = "filerev"
1093
        chk_bytes = self.get_chk_bytes()
1094
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1095
        bytes = ''.join(chk_inv.to_lines())
1096
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1097
        self.assertEqual(inv.root.file_id, new_inv.path2id(''))
1098
        self.assertEqual('dirid', new_inv.path2id('dir'))
1099
        self.assertEqual('fileid', new_inv.path2id('dir/file'))
1100
3735.2.57 by Jelmer Vernooij
Make sure CHKInventory._entry_cache gets initialized in create_by_apply_delta.
1101
    def test_create_by_apply_delta_sets_root(self):
1102
        inv = Inventory()
1103
        inv.revision_id = "revid"
1104
        chk_bytes = self.get_chk_bytes()
1105
        base_inv = CHKInventory.from_inventory(chk_bytes, inv)
1106
        inv.add_path("", "directory", "myrootid", None)
1107
        inv.revision_id = "expectedid"
1108
        reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
4526.9.15 by Robert Collins
Fix broken CHK inventory test that was applying an inconsistend delta.
1109
        delta = [("", None, base_inv.root.file_id, None),
1110
            (None, "",  "myrootid", inv.root)]
3735.2.57 by Jelmer Vernooij
Make sure CHKInventory._entry_cache gets initialized in create_by_apply_delta.
1111
        new_inv = base_inv.create_by_apply_delta(delta, "expectedid")
1112
        self.assertEquals(reference_inv.root, new_inv.root)
1113
3735.2.10 by Robert Collins
Teach CHKInventory how to make a new inventory from an inventory delta.
1114
    def test_create_by_apply_delta_empty_add_child(self):
1115
        inv = Inventory()
1116
        inv.revision_id = "revid"
1117
        inv.root.revision = "rootrev"
1118
        chk_bytes = self.get_chk_bytes()
1119
        base_inv = CHKInventory.from_inventory(chk_bytes, inv)
1120
        a_entry = InventoryFile("A-id", "A", inv.root.file_id)
1121
        a_entry.revision = "filerev"
1122
        a_entry.executable = True
1123
        a_entry.text_sha1 = "ffff"
1124
        a_entry.text_size = 1
1125
        inv.add(a_entry)
1126
        inv.revision_id = "expectedid"
1127
        reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
1128
        delta = [(None, "A",  "A-id", a_entry)]
1129
        new_inv = base_inv.create_by_apply_delta(delta, "expectedid")
1130
        # new_inv should be the same as reference_inv.
1131
        self.assertEqual(reference_inv.revision_id, new_inv.revision_id)
1132
        self.assertEqual(reference_inv.root_id, new_inv.root_id)
4413.5.10 by John Arbash Meinel
Clean upt the test_inv tests that assumed _root_node was real and not just a key.
1133
        reference_inv.id_to_entry._ensure_root()
1134
        new_inv.id_to_entry._ensure_root()
3735.2.10 by Robert Collins
Teach CHKInventory how to make a new inventory from an inventory delta.
1135
        self.assertEqual(reference_inv.id_to_entry._root_node._key,
1136
            new_inv.id_to_entry._root_node._key)
3735.2.33 by Robert Collins
Create a smoke-tested CHKInventory.iter_changes(CHKInventory) - incomplete in general but enough to start working with.
1137
3735.2.41 by Robert Collins
Make the parent_id_basename index be updated during CHKInventory.apply_delta.
1138
    def test_create_by_apply_delta_empty_add_child_updates_parent_id(self):
1139
        inv = Inventory()
1140
        inv.revision_id = "revid"
1141
        inv.root.revision = "rootrev"
1142
        chk_bytes = self.get_chk_bytes()
3735.2.132 by John Arbash Meinel
Remove references to parent_id_basename_index, now that we know we want it.
1143
        base_inv = CHKInventory.from_inventory(chk_bytes, inv)
3735.2.41 by Robert Collins
Make the parent_id_basename index be updated during CHKInventory.apply_delta.
1144
        a_entry = InventoryFile("A-id", "A", inv.root.file_id)
1145
        a_entry.revision = "filerev"
1146
        a_entry.executable = True
1147
        a_entry.text_sha1 = "ffff"
1148
        a_entry.text_size = 1
1149
        inv.add(a_entry)
1150
        inv.revision_id = "expectedid"
3735.2.132 by John Arbash Meinel
Remove references to parent_id_basename_index, now that we know we want it.
1151
        reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
3735.2.41 by Robert Collins
Make the parent_id_basename index be updated during CHKInventory.apply_delta.
1152
        delta = [(None, "A",  "A-id", a_entry)]
1153
        new_inv = base_inv.create_by_apply_delta(delta, "expectedid")
4413.5.10 by John Arbash Meinel
Clean upt the test_inv tests that assumed _root_node was real and not just a key.
1154
        reference_inv.id_to_entry._ensure_root()
1155
        reference_inv.parent_id_basename_to_file_id._ensure_root()
1156
        new_inv.id_to_entry._ensure_root()
1157
        new_inv.parent_id_basename_to_file_id._ensure_root()
3735.2.41 by Robert Collins
Make the parent_id_basename index be updated during CHKInventory.apply_delta.
1158
        # new_inv should be the same as reference_inv.
1159
        self.assertEqual(reference_inv.revision_id, new_inv.revision_id)
1160
        self.assertEqual(reference_inv.root_id, new_inv.root_id)
1161
        self.assertEqual(reference_inv.id_to_entry._root_node._key,
1162
            new_inv.id_to_entry._root_node._key)
1163
        self.assertEqual(reference_inv.parent_id_basename_to_file_id._root_node._key,
1164
            new_inv.parent_id_basename_to_file_id._root_node._key)
1165
3735.2.33 by Robert Collins
Create a smoke-tested CHKInventory.iter_changes(CHKInventory) - incomplete in general but enough to start working with.
1166
    def test_iter_changes(self):
1167
        # Low level bootstrapping smoke test; comprehensive generic tests via
1168
        # InterTree are coming.
1169
        inv = Inventory()
1170
        inv.revision_id = "revid"
1171
        inv.root.revision = "rootrev"
1172
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
1173
        inv["fileid"].revision = "filerev"
1174
        inv["fileid"].executable = True
1175
        inv["fileid"].text_sha1 = "ffff"
1176
        inv["fileid"].text_size = 1
1177
        inv2 = Inventory()
1178
        inv2.revision_id = "revid2"
1179
        inv2.root.revision = "rootrev"
1180
        inv2.add(InventoryFile("fileid", "file", inv.root.file_id))
1181
        inv2["fileid"].revision = "filerev2"
1182
        inv2["fileid"].executable = False
1183
        inv2["fileid"].text_sha1 = "bbbb"
1184
        inv2["fileid"].text_size = 2
1185
        # get fresh objects.
1186
        chk_bytes = self.get_chk_bytes()
1187
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1188
        bytes = ''.join(chk_inv.to_lines())
1189
        inv_1 = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1190
        chk_inv2 = CHKInventory.from_inventory(chk_bytes, inv2)
1191
        bytes = ''.join(chk_inv2.to_lines())
1192
        inv_2 = CHKInventory.deserialise(chk_bytes, bytes, ("revid2",))
1193
        self.assertEqual([('fileid', (u'file', u'file'), True, (True, True),
1194
            ('TREE_ROOT', 'TREE_ROOT'), (u'file', u'file'), ('file', 'file'),
1195
            (False, True))],
1196
            list(inv_1.iter_changes(inv_2)))
3735.2.40 by Robert Collins
Add development4 which has a parent_id to basename index on CHKInventory objects.
1197
3735.2.41 by Robert Collins
Make the parent_id_basename index be updated during CHKInventory.apply_delta.
1198
    def test_parent_id_basename_to_file_id_index_enabled(self):
3735.2.40 by Robert Collins
Add development4 which has a parent_id to basename index on CHKInventory objects.
1199
        inv = Inventory()
1200
        inv.revision_id = "revid"
1201
        inv.root.revision = "rootrev"
1202
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
1203
        inv["fileid"].revision = "filerev"
1204
        inv["fileid"].executable = True
1205
        inv["fileid"].text_sha1 = "ffff"
1206
        inv["fileid"].text_size = 1
1207
        # get fresh objects.
1208
        chk_bytes = self.get_chk_bytes()
3735.2.132 by John Arbash Meinel
Remove references to parent_id_basename_index, now that we know we want it.
1209
        tmp_inv = CHKInventory.from_inventory(chk_bytes, inv)
3735.2.40 by Robert Collins
Add development4 which has a parent_id to basename index on CHKInventory objects.
1210
        bytes = ''.join(tmp_inv.to_lines())
1211
        chk_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
3735.2.41 by Robert Collins
Make the parent_id_basename index be updated during CHKInventory.apply_delta.
1212
        self.assertIsInstance(chk_inv.parent_id_basename_to_file_id, chk_map.CHKMap)
3735.2.40 by Robert Collins
Add development4 which has a parent_id to basename index on CHKInventory objects.
1213
        self.assertEqual(
1214
            {('', ''): 'TREE_ROOT', ('TREE_ROOT', 'file'): 'fileid'},
3735.2.41 by Robert Collins
Make the parent_id_basename index be updated during CHKInventory.apply_delta.
1215
            dict(chk_inv.parent_id_basename_to_file_id.iteritems()))
3735.36.12 by John Arbash Meinel
Add some direct tests for CHKInventory._entry_to_bytes
1216
1217
    def test_file_entry_to_bytes(self):
1218
        inv = CHKInventory(None)
1219
        ie = inventory.InventoryFile('file-id', 'filename', 'parent-id')
1220
        ie.executable = True
1221
        ie.revision = 'file-rev-id'
1222
        ie.text_sha1 = 'abcdefgh'
1223
        ie.text_size = 100
1224
        bytes = inv._entry_to_bytes(ie)
1225
        self.assertEqual('file: file-id\nparent-id\nfilename\n'
1226
                         'file-rev-id\nabcdefgh\n100\nY', bytes)
1227
        ie2 = inv._bytes_to_entry(bytes)
1228
        self.assertEqual(ie, ie2)
1229
        self.assertIsInstance(ie2.name, unicode)
1230
        self.assertEqual(('filename', 'file-id', 'file-rev-id'),
1231
                         inv._bytes_to_utf8name_key(bytes))
1232
1233
    def test_file2_entry_to_bytes(self):
1234
        inv = CHKInventory(None)
1235
        # \u30a9 == 'omega'
1236
        ie = inventory.InventoryFile('file-id', u'\u03a9name', 'parent-id')
1237
        ie.executable = False
1238
        ie.revision = 'file-rev-id'
1239
        ie.text_sha1 = '123456'
1240
        ie.text_size = 25
1241
        bytes = inv._entry_to_bytes(ie)
1242
        self.assertEqual('file: file-id\nparent-id\n\xce\xa9name\n'
1243
                         'file-rev-id\n123456\n25\nN', bytes)
1244
        ie2 = inv._bytes_to_entry(bytes)
1245
        self.assertEqual(ie, ie2)
1246
        self.assertIsInstance(ie2.name, unicode)
1247
        self.assertEqual(('\xce\xa9name', 'file-id', 'file-rev-id'),
1248
                         inv._bytes_to_utf8name_key(bytes))
1249
1250
    def test_dir_entry_to_bytes(self):
1251
        inv = CHKInventory(None)
1252
        ie = inventory.InventoryDirectory('dir-id', 'dirname', 'parent-id')
1253
        ie.revision = 'dir-rev-id'
1254
        bytes = inv._entry_to_bytes(ie)
1255
        self.assertEqual('dir: dir-id\nparent-id\ndirname\ndir-rev-id', bytes)
1256
        ie2 = inv._bytes_to_entry(bytes)
1257
        self.assertEqual(ie, ie2)
1258
        self.assertIsInstance(ie2.name, unicode)
1259
        self.assertEqual(('dirname', 'dir-id', 'dir-rev-id'),
1260
                         inv._bytes_to_utf8name_key(bytes))
1261
1262
    def test_dir2_entry_to_bytes(self):
1263
        inv = CHKInventory(None)
1264
        ie = inventory.InventoryDirectory('dir-id', u'dir\u03a9name',
1265
                                          None)
1266
        ie.revision = 'dir-rev-id'
1267
        bytes = inv._entry_to_bytes(ie)
1268
        self.assertEqual('dir: dir-id\n\ndir\xce\xa9name\n'
1269
                         'dir-rev-id', bytes)
1270
        ie2 = inv._bytes_to_entry(bytes)
1271
        self.assertEqual(ie, ie2)
1272
        self.assertIsInstance(ie2.name, unicode)
1273
        self.assertIs(ie2.parent_id, None)
1274
        self.assertEqual(('dir\xce\xa9name', 'dir-id', 'dir-rev-id'),
1275
                         inv._bytes_to_utf8name_key(bytes))
1276
1277
    def test_symlink_entry_to_bytes(self):
1278
        inv = CHKInventory(None)
1279
        ie = inventory.InventoryLink('link-id', 'linkname', 'parent-id')
1280
        ie.revision = 'link-rev-id'
1281
        ie.symlink_target = u'target/path'
1282
        bytes = inv._entry_to_bytes(ie)
1283
        self.assertEqual('symlink: link-id\nparent-id\nlinkname\n'
1284
                         'link-rev-id\ntarget/path', bytes)
1285
        ie2 = inv._bytes_to_entry(bytes)
1286
        self.assertEqual(ie, ie2)
1287
        self.assertIsInstance(ie2.name, unicode)
1288
        self.assertIsInstance(ie2.symlink_target, unicode)
1289
        self.assertEqual(('linkname', 'link-id', 'link-rev-id'),
1290
                         inv._bytes_to_utf8name_key(bytes))
1291
1292
    def test_symlink2_entry_to_bytes(self):
1293
        inv = CHKInventory(None)
1294
        ie = inventory.InventoryLink('link-id', u'link\u03a9name', 'parent-id')
1295
        ie.revision = 'link-rev-id'
1296
        ie.symlink_target = u'target/\u03a9path'
1297
        bytes = inv._entry_to_bytes(ie)
1298
        self.assertEqual('symlink: link-id\nparent-id\nlink\xce\xa9name\n'
1299
                         'link-rev-id\ntarget/\xce\xa9path', bytes)
1300
        ie2 = inv._bytes_to_entry(bytes)
1301
        self.assertEqual(ie, ie2)
1302
        self.assertIsInstance(ie2.name, unicode)
1303
        self.assertIsInstance(ie2.symlink_target, unicode)
1304
        self.assertEqual(('link\xce\xa9name', 'link-id', 'link-rev-id'),
1305
                         inv._bytes_to_utf8name_key(bytes))
1306
1307
    def test_tree_reference_entry_to_bytes(self):
1308
        inv = CHKInventory(None)
1309
        ie = inventory.TreeReference('tree-root-id', u'tree\u03a9name',
1310
                                     'parent-id')
1311
        ie.revision = 'tree-rev-id'
1312
        ie.reference_revision = 'ref-rev-id'
1313
        bytes = inv._entry_to_bytes(ie)
1314
        self.assertEqual('tree: tree-root-id\nparent-id\ntree\xce\xa9name\n'
1315
                         'tree-rev-id\nref-rev-id', bytes)
1316
        ie2 = inv._bytes_to_entry(bytes)
1317
        self.assertEqual(ie, ie2)
1318
        self.assertIsInstance(ie2.name, unicode)
1319
        self.assertEqual(('tree\xce\xa9name', 'tree-root-id', 'tree-rev-id'),
1320
                         inv._bytes_to_utf8name_key(bytes))
5726.2.3 by John Arbash Meinel
Properly decode basename. In the map it is always stored as UTF-8, but
1321
5726.2.4 by John Arbash Meinel
_preload should also handle when some entries have already been expanded.
1322
    def make_basic_utf8_inventory(self):
5726.2.3 by John Arbash Meinel
Properly decode basename. In the map it is always stored as UTF-8, but
1323
        inv = Inventory()
1324
        inv.revision_id = "revid"
1325
        inv.root.revision = "rootrev"
1326
        root_id = inv.root.file_id
1327
        inv.add(InventoryFile("fileid", u'f\xefle', root_id))
1328
        inv["fileid"].revision = "filerev"
1329
        inv["fileid"].text_sha1 = "ffff"
1330
        inv["fileid"].text_size = 0
1331
        inv.add(InventoryDirectory("dirid", u'dir-\N{EURO SIGN}', root_id))
1332
        inv.add(InventoryFile("childid", u'ch\xefld', "dirid"))
1333
        inv["childid"].revision = "filerev"
1334
        inv["childid"].text_sha1 = "ffff"
1335
        inv["childid"].text_size = 0
1336
        chk_bytes = self.get_chk_bytes()
1337
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1338
        bytes = ''.join(chk_inv.to_lines())
5726.2.4 by John Arbash Meinel
_preload should also handle when some entries have already been expanded.
1339
        return CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1340
1341
    def test__preload_handles_utf8(self):
1342
        new_inv = self.make_basic_utf8_inventory()
5726.2.3 by John Arbash Meinel
Properly decode basename. In the map it is always stored as UTF-8, but
1343
        self.assertEqual({}, new_inv._fileid_to_entry_cache)
1344
        self.assertFalse(new_inv._fully_cached)
1345
        new_inv._preload_cache()
1346
        self.assertEqual(
5726.2.4 by John Arbash Meinel
_preload should also handle when some entries have already been expanded.
1347
            sorted([new_inv.root_id, "fileid", "dirid", "childid"]),
5726.2.3 by John Arbash Meinel
Properly decode basename. In the map it is always stored as UTF-8, but
1348
            sorted(new_inv._fileid_to_entry_cache.keys()))
5726.2.4 by John Arbash Meinel
_preload should also handle when some entries have already been expanded.
1349
        ie_root = new_inv._fileid_to_entry_cache[new_inv.root_id]
5726.2.3 by John Arbash Meinel
Properly decode basename. In the map it is always stored as UTF-8, but
1350
        self.assertEqual([u'dir-\N{EURO SIGN}', u'f\xefle'],
1351
                         sorted(ie_root._children.keys()))
1352
        ie_dir = new_inv._fileid_to_entry_cache['dirid']
1353
        self.assertEqual([u'ch\xefld'], sorted(ie_dir._children.keys()))
1354
5726.2.1 by John Arbash Meinel
Fix bug #737234. Preload all entries for iter_entries_by_dir().
1355
    def test__preload_populates_cache(self):
1356
        inv = Inventory()
1357
        inv.revision_id = "revid"
1358
        inv.root.revision = "rootrev"
1359
        root_id = inv.root.file_id
1360
        inv.add(InventoryFile("fileid", "file", root_id))
1361
        inv["fileid"].revision = "filerev"
1362
        inv["fileid"].executable = True
1363
        inv["fileid"].text_sha1 = "ffff"
1364
        inv["fileid"].text_size = 1
1365
        inv.add(InventoryDirectory("dirid", "dir", root_id))
1366
        inv.add(InventoryFile("childid", "child", "dirid"))
1367
        inv["childid"].revision = "filerev"
1368
        inv["childid"].executable = False
1369
        inv["childid"].text_sha1 = "dddd"
1370
        inv["childid"].text_size = 1
1371
        chk_bytes = self.get_chk_bytes()
1372
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1373
        bytes = ''.join(chk_inv.to_lines())
1374
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1375
        self.assertEqual({}, new_inv._fileid_to_entry_cache)
1376
        self.assertFalse(new_inv._fully_cached)
1377
        new_inv._preload_cache()
1378
        self.assertEqual(
1379
            sorted([root_id, "fileid", "dirid", "childid"]),
1380
            sorted(new_inv._fileid_to_entry_cache.keys()))
1381
        self.assertTrue(new_inv._fully_cached)
1382
        ie_root = new_inv._fileid_to_entry_cache[root_id]
1383
        self.assertEqual(['dir', 'file'], sorted(ie_root._children.keys()))
1384
        ie_dir = new_inv._fileid_to_entry_cache['dirid']
1385
        self.assertEqual(['child'], sorted(ie_dir._children.keys()))
5609.27.1 by John Arbash Meinel
Backport the fix for bug #737234 to the 2.3 series.
1386
5726.2.4 by John Arbash Meinel
_preload should also handle when some entries have already been expanded.
1387
    def test__preload_handles_partially_evaluated_inventory(self):
1388
        new_inv = self.make_basic_utf8_inventory()
1389
        ie = new_inv[new_inv.root_id]
1390
        self.assertIs(None, ie._children)
1391
        self.assertEqual([u'dir-\N{EURO SIGN}', u'f\xefle'],
1392
                         sorted(ie.children.keys()))
1393
        # Accessing .children loads _children
1394
        self.assertEqual([u'dir-\N{EURO SIGN}', u'f\xefle'],
1395
                         sorted(ie._children.keys()))
1396
        new_inv._preload_cache()
1397
        # No change
1398
        self.assertEqual([u'dir-\N{EURO SIGN}', u'f\xefle'],
1399
                         sorted(ie._children.keys()))
1400
        ie_dir = new_inv["dirid"]
1401
        self.assertEqual([u'ch\xefld'],
1402
                         sorted(ie_dir._children.keys()))
1403
6024.2.1 by Bastian Bowe
Test to prove error in CHKInventory.filter method
1404
    def test_filter_change_in_renamed_subfolder(self):
1405
        inv = Inventory('tree-root')
1406
        src_ie = inv.add_path('src', 'directory', 'src-id')
1407
        inv.add_path('src/sub/', 'directory', 'sub-id')
1408
        a_ie = inv.add_path('src/sub/a', 'file', 'a-id')
1409
        a_ie.text_sha1 = osutils.sha_string('content\n')
1410
        a_ie.text_size = len('content\n')
1411
        chk_bytes = self.get_chk_bytes()
1412
        inv = CHKInventory.from_inventory(chk_bytes, inv)
1413
        inv = inv.create_by_apply_delta([
1414
            ("src/sub/a", "src/sub/a", "a-id", a_ie),
1415
            ("src", "src2", "src-id", src_ie),
1416
            ], 'new-rev-2')
1417
        new_inv = inv.filter(['a-id', 'src-id'])
1418
        self.assertEqual([
1419
            ('', 'tree-root'),
1420
            ('src', 'src-id'),
1421
            ('src/sub', 'sub-id'),
1422
            ('src/sub/a', 'a-id'),
1423
            ], [(path, ie.file_id) for path, ie in new_inv.iter_entries()])
4634.51.2 by John Arbash Meinel
Start laying the groundwork for testing the expansion code
1424
1425
class TestCHKInventoryExpand(tests.TestCaseWithMemoryTransport):
1426
1427
    def get_chk_bytes(self):
1428
        factory = groupcompress.make_pack_factory(True, True, 1)
1429
        trans = self.get_transport('')
1430
        return factory(trans)
1431
1432
    def make_dir(self, inv, name, parent_id):
1433
        inv.add(inv.make_entry('directory', name, parent_id, name + '-id'))
1434
1435
    def make_file(self, inv, name, parent_id, content='content\n'):
4634.51.3 by John Arbash Meinel
We have iteration to parents working, need to find children now.
1436
        ie = inv.make_entry('file', name, parent_id, name + '-id')
4634.51.2 by John Arbash Meinel
Start laying the groundwork for testing the expansion code
1437
        ie.text_sha1 = osutils.sha_string(content)
1438
        ie.text_size = len(content)
1439
        inv.add(ie)
1440
1441
    def make_simple_inventory(self):
1442
        inv = Inventory('TREE_ROOT')
1443
        inv.revision_id = "revid"
1444
        inv.root.revision = "rootrev"
1445
        # /                 TREE_ROOT
1446
        # dir1/             dir1-id
1447
        #   sub-file1       sub-file1-id
1448
        #   sub-file2       sub-file2-id
1449
        #   sub-dir1/       sub-dir1-id
1450
        #     subsub-file1  subsub-file1-id
1451
        # dir2/             dir2-id
1452
        #   sub2-file1      sub2-file1-id
1453
        # top               top-id
1454
        self.make_dir(inv, 'dir1', 'TREE_ROOT')
1455
        self.make_dir(inv, 'dir2', 'TREE_ROOT')
1456
        self.make_dir(inv, 'sub-dir1', 'dir1-id')
1457
        self.make_file(inv, 'top', 'TREE_ROOT')
1458
        self.make_file(inv, 'sub-file1', 'dir1-id')
1459
        self.make_file(inv, 'sub-file2', 'dir1-id')
1460
        self.make_file(inv, 'subsub-file1', 'sub-dir1-id')
1461
        self.make_file(inv, 'sub2-file1', 'dir2-id')
1462
        chk_bytes = self.get_chk_bytes()
4634.51.8 by John Arbash Meinel
Catch a corner case that we were missing.
1463
        #  use a small maximum_size to force internal paging structures
1464
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv,
1465
                        maximum_size=100,
1466
                        search_key_name='hash-255-way')
4634.51.3 by John Arbash Meinel
We have iteration to parents working, need to find children now.
1467
        bytes = ''.join(chk_inv.to_lines())
1468
        return CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1469
1470
    def assert_Getitems(self, expected_fileids, inv, file_ids):
1471
        self.assertEqual(sorted(expected_fileids),
1472
                         sorted([ie.file_id for ie in inv._getitems(file_ids)]))
1473
4634.51.5 by John Arbash Meinel
Change the api a bit.
1474
    def assertExpand(self, all_ids, inv, file_ids):
1475
        (val_all_ids,
1476
         val_children) = inv._expand_fileids_to_parents_and_children(file_ids)
1477
        self.assertEqual(set(all_ids), val_all_ids)
1478
        entries = inv._getitems(val_all_ids)
1479
        expected_children = {}
1480
        for entry in entries:
1481
            s = expected_children.setdefault(entry.parent_id, [])
1482
            s.append(entry.file_id)
1483
        val_children = dict((k, sorted(v)) for k, v
1484
                            in val_children.iteritems())
1485
        expected_children = dict((k, sorted(v)) for k, v
1486
                            in expected_children.iteritems())
1487
        self.assertEqual(expected_children, val_children)
4634.51.3 by John Arbash Meinel
We have iteration to parents working, need to find children now.
1488
1489
    def test_make_simple_inventory(self):
4634.51.2 by John Arbash Meinel
Start laying the groundwork for testing the expansion code
1490
        inv = self.make_simple_inventory()
1491
        layout = []
1492
        for path, entry in inv.iter_entries_by_dir():
1493
            layout.append((path, entry.file_id))
1494
        self.assertEqual([
1495
            ('', 'TREE_ROOT'),
1496
            ('dir1', 'dir1-id'),
1497
            ('dir2', 'dir2-id'),
1498
            ('top', 'top-id'),
1499
            ('dir1/sub-dir1', 'sub-dir1-id'),
1500
            ('dir1/sub-file1', 'sub-file1-id'),
1501
            ('dir1/sub-file2', 'sub-file2-id'),
1502
            ('dir1/sub-dir1/subsub-file1', 'subsub-file1-id'),
1503
            ('dir2/sub2-file1', 'sub2-file1-id'),
1504
            ], layout)
4634.51.3 by John Arbash Meinel
We have iteration to parents working, need to find children now.
1505
1506
    def test__getitems(self):
1507
        inv = self.make_simple_inventory()
1508
        # Reading from disk
1509
        self.assert_Getitems(['dir1-id'], inv, ['dir1-id'])
1510
        self.assertTrue('dir1-id' in inv._fileid_to_entry_cache)
1511
        self.assertFalse('sub-file2-id' in inv._fileid_to_entry_cache)
1512
        # From cache
1513
        self.assert_Getitems(['dir1-id'], inv, ['dir1-id'])
1514
        # Mixed
1515
        self.assert_Getitems(['dir1-id', 'sub-file2-id'], inv,
1516
                             ['dir1-id', 'sub-file2-id'])
1517
        self.assertTrue('dir1-id' in inv._fileid_to_entry_cache)
1518
        self.assertTrue('sub-file2-id' in inv._fileid_to_entry_cache)
1519
1520
    def test_single_file(self):
1521
        inv = self.make_simple_inventory()
4634.51.5 by John Arbash Meinel
Change the api a bit.
1522
        self.assertExpand(['TREE_ROOT', 'top-id'], inv, ['top-id'])
4634.51.3 by John Arbash Meinel
We have iteration to parents working, need to find children now.
1523
1524
    def test_get_all_parents(self):
1525
        inv = self.make_simple_inventory()
4634.51.5 by John Arbash Meinel
Change the api a bit.
1526
        self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id',
1527
                           'subsub-file1-id',
1528
                          ], inv, ['subsub-file1-id'])
4634.51.4 by John Arbash Meinel
Implement an expansion function that works directly on the chk maps.
1529
1530
    def test_get_children(self):
1531
        inv = self.make_simple_inventory()
4634.51.5 by John Arbash Meinel
Change the api a bit.
1532
        self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id',
1533
                           'sub-file1-id', 'sub-file2-id', 'subsub-file1-id',
4634.51.4 by John Arbash Meinel
Implement an expansion function that works directly on the chk maps.
1534
                          ], inv, ['dir1-id'])
4634.51.8 by John Arbash Meinel
Catch a corner case that we were missing.
1535
1536
    def test_from_root(self):
1537
        inv = self.make_simple_inventory()
1538
        self.assertExpand(['TREE_ROOT', 'dir1-id', 'dir2-id', 'sub-dir1-id',
1539
                           'sub-file1-id', 'sub-file2-id', 'sub2-file1-id',
1540
                           'subsub-file1-id', 'top-id'], inv, ['TREE_ROOT'])
1541
1542
    def test_top_level_file(self):
1543
        inv = self.make_simple_inventory()
1544
        self.assertExpand(['TREE_ROOT', 'top-id'], inv, ['top-id'])
1545
1546
    def test_subsub_file(self):
1547
        inv = self.make_simple_inventory()
1548
        self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id',
1549
                           'subsub-file1-id'], inv, ['subsub-file1-id'])
1550
1551
    def test_sub_and_root(self):
1552
        inv = self.make_simple_inventory()
1553
        self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id', 'top-id',
1554
                           'subsub-file1-id'], inv, ['top-id', 'subsub-file1-id'])
5802.1.2 by Jelmer Vernooij
Add test for mutable_inventory_from_tree.
1555
1556
1557
class TestMutableInventoryFromTree(TestCaseWithTransport):
1558
1559
    def test_empty(self):
1560
        repository = self.make_repository('.')
1561
        tree = repository.revision_tree(revision.NULL_REVISION)
1562
        inv = mutable_inventory_from_tree(tree)
1563
        self.assertEquals(revision.NULL_REVISION, inv.revision_id)
1564
        self.assertEquals(0, len(inv))
1565
1566
    def test_some_files(self):
1567
        wt = self.make_branch_and_tree('.')
1568
        self.build_tree(['a'])
1569
        wt.add(['a'], ['thefileid'])
1570
        revid = wt.commit("commit")
1571
        tree = wt.branch.repository.revision_tree(revid)
1572
        inv = mutable_inventory_from_tree(tree)
1573
        self.assertEquals(revid, inv.revision_id)
1574
        self.assertEquals(2, len(inv))
1575
        self.assertEquals("a", inv['thefileid'].name)
1576
        # The inventory should be mutable and independent of
1577
        # the original tree
6405.2.10 by Jelmer Vernooij
Fix more tests.
1578
        self.assertFalse(tree.root_inventory['thefileid'].executable)
5802.1.2 by Jelmer Vernooij
Add test for mutable_inventory_from_tree.
1579
        inv['thefileid'].executable = True
6405.2.10 by Jelmer Vernooij
Fix more tests.
1580
        self.assertFalse(tree.root_inventory['thefileid'].executable)