~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_inv.py

  • Committer: Martin Pool
  • Date: 2009-07-19 01:05:42 UTC
  • mto: This revision was merged to the branch mainline in revision 4558.
  • Revision ID: mbp@sourcefrog.net-20090719010542-34bzx1i5ynfvs6zd
TextUIFactory should cope with EOF when in get_boolean

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
2
 
 
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 
 
17
 
from bzrlib.selftest import TestBase
18
 
 
19
 
from bzrlib.inventory import Inventory, InventoryEntry
20
 
 
21
 
 
22
 
class TestIsWithin(TestBase):
23
 
    def runTest(self):
24
 
        from bzrlib.osutils import is_inside_any
25
 
        
26
 
        for dirs, fn in [(['src', 'doc'], 'src/foo.c'),
27
 
                         (['src'], 'src/foo.c'),
28
 
                         (['src'], 'src'),
29
 
                         ]:
30
 
            self.assert_(is_inside_any(dirs, fn))
31
 
            
32
 
        for dirs, fn in [(['src'], 'srccontrol'),
33
 
                         (['src'], 'srccontrol/foo')]:
34
 
            self.assertFalse(is_inside_any(dirs, fn))
35
 
            
36
 
            
37
 
            
38
 
class TestInventoryIds(TestBase):
39
 
    def runTest(self):
40
 
        """Test detection of files within selected directories."""
41
 
        inv = Inventory()
42
 
        
43
 
        for args in [('src', 'directory', 'src-id'), 
44
 
                     ('doc', 'directory', 'doc-id'), 
45
 
                     ('src/hello.c', 'file'),
46
 
                     ('src/bye.c', 'file', 'bye-id'),
47
 
                     ('Makefile', 'file')]:
48
 
            inv.add_path(*args)
49
 
            
50
 
        self.assertEqual(inv.path2id('src'), 'src-id')
51
 
        self.assertEqual(inv.path2id('src/bye.c'), 'bye-id')
52
 
        
53
 
        self.assert_('src-id' in inv)
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
 
 
18
from bzrlib import (
 
19
    chk_map,
 
20
    bzrdir,
 
21
    errors,
 
22
    inventory,
 
23
    osutils,
 
24
    repository,
 
25
    revision,
 
26
    )
 
27
from bzrlib.inventory import (CHKInventory, Inventory, ROOT_ID, InventoryFile,
 
28
    InventoryDirectory, InventoryEntry, TreeReference)
 
29
from bzrlib.tests import (
 
30
    TestCase,
 
31
    TestCaseWithTransport,
 
32
    condition_isinstance,
 
33
    multiply_tests,
 
34
    split_suite_by_condition,
 
35
    )
 
36
from bzrlib.tests.per_workingtree import workingtree_formats
 
37
 
 
38
 
 
39
def load_tests(standard_tests, module, loader):
 
40
    """Parameterise some inventory tests."""
 
41
    to_adapt, result = split_suite_by_condition(standard_tests,
 
42
        condition_isinstance(TestDeltaApplication))
 
43
    scenarios = [
 
44
        ('Inventory', {'apply_delta':apply_inventory_Inventory}),
 
45
        ]
 
46
    # Working tree basis delta application
 
47
    # Repository add_inv_by_delta.
 
48
    # Reduce form of the per_repository test logic - that logic needs to be
 
49
    # be able to get /just/ repositories whereas these tests are fine with
 
50
    # just creating trees.
 
51
    formats = set()
 
52
    for _, format in repository.format_registry.iteritems():
 
53
        scenarios.append((str(format.__name__), {
 
54
            'apply_delta':apply_inventory_Repository_add_inventory_by_delta,
 
55
            'format':format}))
 
56
    for format in workingtree_formats():
 
57
        scenarios.append((str(format.__class__.__name__), {
 
58
            'apply_delta':apply_inventory_WT_basis,
 
59
            'format':format}))
 
60
    return multiply_tests(to_adapt, scenarios, result)
 
61
 
 
62
 
 
63
def apply_inventory_Inventory(self, basis, delta):
 
64
    """Apply delta to basis and return the result.
 
65
    
 
66
    :param basis: An inventory to be used as the basis.
 
67
    :param delta: The inventory delta to apply:
 
68
    :return: An inventory resulting from the application.
 
69
    """
 
70
    basis.apply_delta(delta)
 
71
    return basis
 
72
 
 
73
 
 
74
def apply_inventory_WT_basis(self, basis, delta):
 
75
    """Apply delta to basis and return the result.
 
76
 
 
77
    This sets the parent and then calls update_basis_by_delta.
 
78
    It also puts the basis in the repository under both 'basis' and 'result' to
 
79
    allow safety checks made by the WT to succeed, and finally ensures that all
 
80
    items in the delta with a new path are present in the WT before calling
 
81
    update_basis_by_delta.
 
82
    
 
83
    :param basis: An inventory to be used as the basis.
 
84
    :param delta: The inventory delta to apply:
 
85
    :return: An inventory resulting from the application.
 
86
    """
 
87
    control = self.make_bzrdir('tree', format=self.format._matchingbzrdir)
 
88
    control.create_repository()
 
89
    control.create_branch()
 
90
    tree = self.format.initialize(control)
 
91
    tree.lock_write()
 
92
    try:
 
93
        repo = tree.branch.repository
 
94
        repo.start_write_group()
 
95
        try:
 
96
            rev = revision.Revision('basis', timestamp=0, timezone=None,
 
97
                message="", committer="foo@example.com")
 
98
            basis.revision_id = 'basis'
 
99
            repo.add_revision('basis', rev, basis)
 
100
            # Add a revision for the result, with the basis content - 
 
101
            # update_basis_by_delta doesn't check that the delta results in
 
102
            # result, and we want inconsistent deltas to get called on the
 
103
            # tree, or else the code isn't actually checked.
 
104
            rev = revision.Revision('result', timestamp=0, timezone=None,
 
105
                message="", committer="foo@example.com")
 
106
            basis.revision_id = 'result'
 
107
            repo.add_revision('result', rev, basis)
 
108
        except:
 
109
            repo.abort_write_group()
 
110
            raise
 
111
        else:
 
112
            repo.commit_write_group()
 
113
        # Set the basis state as the trees current state
 
114
        tree._write_inventory(basis)
 
115
        # This reads basis from the repo and puts it into the tree's local
 
116
        # cache, if it has one.
 
117
        tree.set_parent_ids(['basis'])
 
118
        paths = {}
 
119
        parents = set()
 
120
        for old, new, id, entry in delta:
 
121
            if entry is None:
 
122
                continue
 
123
            paths[new] = (entry.file_id, entry.kind)
 
124
            parents.add(osutils.dirname(new))
 
125
        parents = osutils.minimum_path_selection(parents)
 
126
        parents.discard('')
 
127
        # Put place holders in the tree to permit adding the other entries.
 
128
        for pos, parent in enumerate(parents):
 
129
            if not tree.path2id(parent):
 
130
                # add a synthetic directory in the tree so we can can put the
 
131
                # tree0 entries in place for dirstate.
 
132
                tree.add([parent], ["id%d" % pos], ["directory"])
 
133
        if paths:
 
134
            # Many deltas may cause this mini-apply to fail, but we want to see what
 
135
            # the delta application code says, not the prep that we do to deal with 
 
136
            # limitations of dirstate's update_basis code.
 
137
            for path, (file_id, kind) in sorted(paths.items()):
 
138
                try:
 
139
                    tree.add([path], [file_id], [kind])
 
140
                except (KeyboardInterrupt, SystemExit):
 
141
                    raise
 
142
                except:
 
143
                    pass
 
144
    finally:
 
145
        tree.unlock()
 
146
    # Fresh lock, reads disk again.
 
147
    tree.lock_write()
 
148
    try:
 
149
        tree.update_basis_by_delta('result', delta)
 
150
    finally:
 
151
        tree.unlock()
 
152
    # reload tree - ensure we get what was written.
 
153
    tree = tree.bzrdir.open_workingtree()
 
154
    basis_tree = tree.basis_tree()
 
155
    basis_tree.lock_read()
 
156
    self.addCleanup(basis_tree.unlock)
 
157
    # Note, that if the tree does not have a local cache, the trick above of
 
158
    # setting the result as the basis, will come back to bite us. That said,
 
159
    # all the implementations in bzr do have a local cache.
 
160
    return basis_tree.inventory
 
161
 
 
162
 
 
163
def apply_inventory_Repository_add_inventory_by_delta(self, basis, delta):
 
164
    """Apply delta to basis and return the result.
 
165
    
 
166
    This inserts basis as a whole inventory and then uses
 
167
    add_inventory_by_delta to add delta.
 
168
 
 
169
    :param basis: An inventory to be used as the basis.
 
170
    :param delta: The inventory delta to apply:
 
171
    :return: An inventory resulting from the application.
 
172
    """
 
173
    format = self.format()
 
174
    control = self.make_bzrdir('tree', format=format._matchingbzrdir)
 
175
    repo = format.initialize(control)
 
176
    repo.lock_write()
 
177
    try:
 
178
        repo.start_write_group()
 
179
        try:
 
180
            rev = revision.Revision('basis', timestamp=0, timezone=None,
 
181
                message="", committer="foo@example.com")
 
182
            basis.revision_id = 'basis'
 
183
            repo.add_revision('basis', rev, basis)
 
184
        except:
 
185
            repo.abort_write_group()
 
186
            raise
 
187
        else:
 
188
            repo.commit_write_group()
 
189
    finally:
 
190
        repo.unlock()
 
191
    repo.lock_write()
 
192
    try:
 
193
        repo.start_write_group()
 
194
        try:
 
195
            inv_sha1 = repo.add_inventory_by_delta('basis', delta,
 
196
                'result', ['basis'])
 
197
        except:
 
198
            repo.abort_write_group()
 
199
            raise
 
200
        else:
 
201
            repo.commit_write_group()
 
202
    finally:
 
203
        repo.unlock()
 
204
    # Fresh lock, reads disk again.
 
205
    repo = repo.bzrdir.open_repository()
 
206
    repo.lock_read()
 
207
    self.addCleanup(repo.unlock)
 
208
    return repo.get_inventory('result')
 
209
 
 
210
 
 
211
class TestDeltaApplication(TestCaseWithTransport):
 
212
 
 
213
    def get_empty_inventory(self, reference_inv=None):
 
214
        """Get an empty inventory.
 
215
 
 
216
        Note that tests should not depend on the revision of the root for
 
217
        setting up test conditions, as it has to be flexible to accomodate non
 
218
        rich root repositories.
 
219
 
 
220
        :param reference_inv: If not None, get the revision for the root from
 
221
            this inventory. This is useful for dealing with older repositories
 
222
            that routinely discarded the root entry data. If None, the root's
 
223
            revision is set to 'basis'.
 
224
        """
 
225
        inv = inventory.Inventory()
 
226
        if reference_inv is not None:
 
227
            inv.root.revision = reference_inv.root.revision
 
228
        else:
 
229
            inv.root.revision = 'basis'
 
230
        return inv
 
231
 
 
232
    def test_empty_delta(self):
 
233
        inv = self.get_empty_inventory()
 
234
        delta = []
 
235
        inv = self.apply_delta(self, inv, delta)
 
236
        inv2 = self.get_empty_inventory(inv)
 
237
        self.assertEqual([], inv2._make_delta(inv))
 
238
 
 
239
    def test_repeated_file_id(self):
 
240
        inv = self.get_empty_inventory()
 
241
        file1 = inventory.InventoryFile('id', 'path1', inv.root.file_id)
 
242
        file1.revision = 'result'
 
243
        file1.text_size = 0
 
244
        file1.text_sha1 = ""
 
245
        file2 = inventory.InventoryFile('id', 'path2', inv.root.file_id)
 
246
        file2.revision = 'result'
 
247
        file2.text_size = 0
 
248
        file2.text_sha1 = ""
 
249
        delta = [(None, u'path1', 'id', file1), (None, u'path2', 'id', file2)]
 
250
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
251
            inv, delta)
 
252
 
 
253
    def test_repeated_new_path(self):
 
254
        inv = self.get_empty_inventory()
 
255
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
256
        file1.revision = 'result'
 
257
        file1.text_size = 0
 
258
        file1.text_sha1 = ""
 
259
        file2 = inventory.InventoryFile('id2', 'path', inv.root.file_id)
 
260
        file2.revision = 'result'
 
261
        file2.text_size = 0
 
262
        file2.text_sha1 = ""
 
263
        delta = [(None, u'path', 'id1', file1), (None, u'path', 'id2', file2)]
 
264
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
265
            inv, delta)
 
266
 
 
267
    def test_repeated_old_path(self):
 
268
        inv = self.get_empty_inventory()
 
269
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
270
        file1.revision = 'result'
 
271
        file1.text_size = 0
 
272
        file1.text_sha1 = ""
 
273
        # We can't *create* a source inventory with the same path, but
 
274
        # a badly generated partial delta might claim the same source twice.
 
275
        # This would be buggy in two ways: the path is repeated in the delta,
 
276
        # And the path for one of the file ids doesn't match the source
 
277
        # location. Alternatively, we could have a repeated fileid, but that
 
278
        # is separately checked for.
 
279
        file2 = inventory.InventoryFile('id2', 'path2', inv.root.file_id)
 
280
        file2.revision = 'result'
 
281
        file2.text_size = 0
 
282
        file2.text_sha1 = ""
 
283
        inv.add(file1)
 
284
        inv.add(file2)
 
285
        delta = [(u'path', None, 'id1', None), (u'path', None, 'id2', None)]
 
286
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
287
            inv, delta)
 
288
 
 
289
    def test_mismatched_id_entry_id(self):
 
290
        inv = self.get_empty_inventory()
 
291
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
292
        file1.revision = 'result'
 
293
        file1.text_size = 0
 
294
        file1.text_sha1 = ""
 
295
        delta = [(None, u'path', 'id', file1)]
 
296
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
297
            inv, delta)
 
298
 
 
299
    def test_parent_is_not_directory(self):
 
300
        inv = self.get_empty_inventory()
 
301
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
302
        file1.revision = 'result'
 
303
        file1.text_size = 0
 
304
        file1.text_sha1 = ""
 
305
        file2 = inventory.InventoryFile('id2', 'path2', 'id1')
 
306
        file2.revision = 'result'
 
307
        file2.text_size = 0
 
308
        file2.text_sha1 = ""
 
309
        inv.add(file1)
 
310
        delta = [(None, u'path/path2', 'id2', file2)]
 
311
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
312
            inv, delta)
 
313
 
 
314
    def test_parent_is_missing(self):
 
315
        inv = self.get_empty_inventory()
 
316
        file2 = inventory.InventoryFile('id2', 'path2', 'missingparent')
 
317
        file2.revision = 'result'
 
318
        file2.text_size = 0
 
319
        file2.text_sha1 = ""
 
320
        delta = [(None, u'path/path2', 'id2', file2)]
 
321
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
 
322
            inv, delta)
 
323
 
 
324
 
 
325
class TestInventoryEntry(TestCase):
 
326
 
 
327
    def test_file_kind_character(self):
 
328
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
 
329
        self.assertEqual(file.kind_character(), '')
 
330
 
 
331
    def test_dir_kind_character(self):
 
332
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
 
333
        self.assertEqual(dir.kind_character(), '/')
 
334
 
 
335
    def test_link_kind_character(self):
 
336
        dir = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
 
337
        self.assertEqual(dir.kind_character(), '')
 
338
 
 
339
    def test_dir_detect_changes(self):
 
340
        left = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
 
341
        left.text_sha1 = 123
 
342
        left.executable = True
 
343
        left.symlink_target='foo'
 
344
        right = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
 
345
        right.text_sha1 = 321
 
346
        right.symlink_target='bar'
 
347
        self.assertEqual((False, False), left.detect_changes(right))
 
348
        self.assertEqual((False, False), right.detect_changes(left))
 
349
 
 
350
    def test_file_detect_changes(self):
 
351
        left = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
 
352
        left.text_sha1 = 123
 
353
        right = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
 
354
        right.text_sha1 = 123
 
355
        self.assertEqual((False, False), left.detect_changes(right))
 
356
        self.assertEqual((False, False), right.detect_changes(left))
 
357
        left.executable = True
 
358
        self.assertEqual((False, True), left.detect_changes(right))
 
359
        self.assertEqual((False, True), right.detect_changes(left))
 
360
        right.text_sha1 = 321
 
361
        self.assertEqual((True, True), left.detect_changes(right))
 
362
        self.assertEqual((True, True), right.detect_changes(left))
 
363
 
 
364
    def test_symlink_detect_changes(self):
 
365
        left = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
 
366
        left.text_sha1 = 123
 
367
        left.executable = True
 
368
        left.symlink_target='foo'
 
369
        right = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
 
370
        right.text_sha1 = 321
 
371
        right.symlink_target='foo'
 
372
        self.assertEqual((False, False), left.detect_changes(right))
 
373
        self.assertEqual((False, False), right.detect_changes(left))
 
374
        left.symlink_target = 'different'
 
375
        self.assertEqual((True, False), left.detect_changes(right))
 
376
        self.assertEqual((True, False), right.detect_changes(left))
 
377
 
 
378
    def test_file_has_text(self):
 
379
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
 
380
        self.failUnless(file.has_text())
 
381
 
 
382
    def test_directory_has_text(self):
 
383
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
 
384
        self.failIf(dir.has_text())
 
385
 
 
386
    def test_link_has_text(self):
 
387
        link = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
 
388
        self.failIf(link.has_text())
 
389
 
 
390
    def test_make_entry(self):
 
391
        self.assertIsInstance(inventory.make_entry("file", "name", ROOT_ID),
 
392
            inventory.InventoryFile)
 
393
        self.assertIsInstance(inventory.make_entry("symlink", "name", ROOT_ID),
 
394
            inventory.InventoryLink)
 
395
        self.assertIsInstance(inventory.make_entry("directory", "name", ROOT_ID),
 
396
            inventory.InventoryDirectory)
 
397
 
 
398
    def test_make_entry_non_normalized(self):
 
399
        orig_normalized_filename = osutils.normalized_filename
 
400
 
 
401
        try:
 
402
            osutils.normalized_filename = osutils._accessible_normalized_filename
 
403
            entry = inventory.make_entry("file", u'a\u030a', ROOT_ID)
 
404
            self.assertEqual(u'\xe5', entry.name)
 
405
            self.assertIsInstance(entry, inventory.InventoryFile)
 
406
 
 
407
            osutils.normalized_filename = osutils._inaccessible_normalized_filename
 
408
            self.assertRaises(errors.InvalidNormalization,
 
409
                    inventory.make_entry, 'file', u'a\u030a', ROOT_ID)
 
410
        finally:
 
411
            osutils.normalized_filename = orig_normalized_filename
 
412
 
 
413
 
 
414
class TestDescribeChanges(TestCase):
 
415
 
 
416
    def test_describe_change(self):
 
417
        # we need to test the following change combinations:
 
418
        # rename
 
419
        # reparent
 
420
        # modify
 
421
        # gone
 
422
        # added
 
423
        # renamed/reparented and modified
 
424
        # change kind (perhaps can't be done yet?)
 
425
        # also, merged in combination with all of these?
 
426
        old_a = InventoryFile('a-id', 'a_file', ROOT_ID)
 
427
        old_a.text_sha1 = '123132'
 
428
        old_a.text_size = 0
 
429
        new_a = InventoryFile('a-id', 'a_file', ROOT_ID)
 
430
        new_a.text_sha1 = '123132'
 
431
        new_a.text_size = 0
 
432
 
 
433
        self.assertChangeDescription('unchanged', old_a, new_a)
 
434
 
 
435
        new_a.text_size = 10
 
436
        new_a.text_sha1 = 'abcabc'
 
437
        self.assertChangeDescription('modified', old_a, new_a)
 
438
 
 
439
        self.assertChangeDescription('added', None, new_a)
 
440
        self.assertChangeDescription('removed', old_a, None)
 
441
        # perhaps a bit questionable but seems like the most reasonable thing...
 
442
        self.assertChangeDescription('unchanged', None, None)
 
443
 
 
444
        # in this case it's both renamed and modified; show a rename and
 
445
        # modification:
 
446
        new_a.name = 'newfilename'
 
447
        self.assertChangeDescription('modified and renamed', old_a, new_a)
 
448
 
 
449
        # reparenting is 'renaming'
 
450
        new_a.name = old_a.name
 
451
        new_a.parent_id = 'somedir-id'
 
452
        self.assertChangeDescription('modified and renamed', old_a, new_a)
 
453
 
 
454
        # reset the content values so its not modified
 
455
        new_a.text_size = old_a.text_size
 
456
        new_a.text_sha1 = old_a.text_sha1
 
457
        new_a.name = old_a.name
 
458
 
 
459
        new_a.name = 'newfilename'
 
460
        self.assertChangeDescription('renamed', old_a, new_a)
 
461
 
 
462
        # reparenting is 'renaming'
 
463
        new_a.name = old_a.name
 
464
        new_a.parent_id = 'somedir-id'
 
465
        self.assertChangeDescription('renamed', old_a, new_a)
 
466
 
 
467
    def assertChangeDescription(self, expected_change, old_ie, new_ie):
 
468
        change = InventoryEntry.describe_change(old_ie, new_ie)
 
469
        self.assertEqual(expected_change, change)
 
470
 
 
471
 
 
472
class TestCHKInventory(TestCaseWithTransport):
 
473
 
 
474
    def get_chk_bytes(self):
 
475
        # The easiest way to get a CHK store is a development6 repository and
 
476
        # then work with the chk_bytes attribute directly.
 
477
        repo = self.make_repository(".", format="development6-rich-root")
 
478
        repo.lock_write()
 
479
        self.addCleanup(repo.unlock)
 
480
        repo.start_write_group()
 
481
        self.addCleanup(repo.abort_write_group)
 
482
        return repo.chk_bytes
 
483
 
 
484
    def read_bytes(self, chk_bytes, key):
 
485
        stream = chk_bytes.get_record_stream([key], 'unordered', True)
 
486
        return stream.next().get_bytes_as("fulltext")
 
487
 
 
488
    def test_deserialise_gives_CHKInventory(self):
 
489
        inv = Inventory()
 
490
        inv.revision_id = "revid"
 
491
        inv.root.revision = "rootrev"
 
492
        chk_bytes = self.get_chk_bytes()
 
493
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
494
        bytes = ''.join(chk_inv.to_lines())
 
495
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
 
496
        self.assertEqual("revid", new_inv.revision_id)
 
497
        self.assertEqual("directory", new_inv.root.kind)
 
498
        self.assertEqual(inv.root.file_id, new_inv.root.file_id)
 
499
        self.assertEqual(inv.root.parent_id, new_inv.root.parent_id)
 
500
        self.assertEqual(inv.root.name, new_inv.root.name)
 
501
        self.assertEqual("rootrev", new_inv.root.revision)
 
502
        self.assertEqual('plain', new_inv._search_key_name)
 
503
 
 
504
    def test_deserialise_wrong_revid(self):
 
505
        inv = Inventory()
 
506
        inv.revision_id = "revid"
 
507
        inv.root.revision = "rootrev"
 
508
        chk_bytes = self.get_chk_bytes()
 
509
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
510
        bytes = ''.join(chk_inv.to_lines())
 
511
        self.assertRaises(ValueError, CHKInventory.deserialise, chk_bytes,
 
512
            bytes, ("revid2",))
 
513
 
 
514
    def test_captures_rev_root_byid(self):
 
515
        inv = Inventory()
 
516
        inv.revision_id = "foo"
 
517
        inv.root.revision = "bar"
 
518
        chk_bytes = self.get_chk_bytes()
 
519
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
520
        lines = chk_inv.to_lines()
 
521
        self.assertEqual([
 
522
            'chkinventory:\n',
 
523
            'revision_id: foo\n',
 
524
            'root_id: TREE_ROOT\n',
 
525
            'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
 
526
            'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
 
527
            ], lines)
 
528
        chk_inv = CHKInventory.deserialise(chk_bytes, ''.join(lines), ('foo',))
 
529
        self.assertEqual('plain', chk_inv._search_key_name)
 
530
 
 
531
    def test_captures_parent_id_basename_index(self):
 
532
        inv = Inventory()
 
533
        inv.revision_id = "foo"
 
534
        inv.root.revision = "bar"
 
535
        chk_bytes = self.get_chk_bytes()
 
536
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
537
        lines = chk_inv.to_lines()
 
538
        self.assertEqual([
 
539
            'chkinventory:\n',
 
540
            'revision_id: foo\n',
 
541
            'root_id: TREE_ROOT\n',
 
542
            'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
 
543
            'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
 
544
            ], lines)
 
545
        chk_inv = CHKInventory.deserialise(chk_bytes, ''.join(lines), ('foo',))
 
546
        self.assertEqual('plain', chk_inv._search_key_name)
 
547
 
 
548
    def test_captures_search_key_name(self):
 
549
        inv = Inventory()
 
550
        inv.revision_id = "foo"
 
551
        inv.root.revision = "bar"
 
552
        chk_bytes = self.get_chk_bytes()
 
553
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv,
 
554
                                              search_key_name='hash-16-way')
 
555
        lines = chk_inv.to_lines()
 
556
        self.assertEqual([
 
557
            'chkinventory:\n',
 
558
            'search_key_name: hash-16-way\n',
 
559
            'root_id: TREE_ROOT\n',
 
560
            'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
 
561
            'revision_id: foo\n',
 
562
            'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
 
563
            ], lines)
 
564
        chk_inv = CHKInventory.deserialise(chk_bytes, ''.join(lines), ('foo',))
 
565
        self.assertEqual('hash-16-way', chk_inv._search_key_name)
 
566
 
 
567
    def test_directory_children_on_demand(self):
 
568
        inv = Inventory()
 
569
        inv.revision_id = "revid"
 
570
        inv.root.revision = "rootrev"
 
571
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
572
        inv["fileid"].revision = "filerev"
 
573
        inv["fileid"].executable = True
 
574
        inv["fileid"].text_sha1 = "ffff"
 
575
        inv["fileid"].text_size = 1
 
576
        chk_bytes = self.get_chk_bytes()
 
577
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
578
        bytes = ''.join(chk_inv.to_lines())
 
579
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
 
580
        root_entry = new_inv[inv.root.file_id]
 
581
        self.assertEqual(None, root_entry._children)
 
582
        self.assertEqual(['file'], root_entry.children.keys())
 
583
        file_direct = new_inv["fileid"]
 
584
        file_found = root_entry.children['file']
 
585
        self.assertEqual(file_direct.kind, file_found.kind)
 
586
        self.assertEqual(file_direct.file_id, file_found.file_id)
 
587
        self.assertEqual(file_direct.parent_id, file_found.parent_id)
 
588
        self.assertEqual(file_direct.name, file_found.name)
 
589
        self.assertEqual(file_direct.revision, file_found.revision)
 
590
        self.assertEqual(file_direct.text_sha1, file_found.text_sha1)
 
591
        self.assertEqual(file_direct.text_size, file_found.text_size)
 
592
        self.assertEqual(file_direct.executable, file_found.executable)
 
593
 
 
594
    def test_from_inventory_maximum_size(self):
 
595
        # from_inventory supports the maximum_size parameter.
 
596
        inv = Inventory()
 
597
        inv.revision_id = "revid"
 
598
        inv.root.revision = "rootrev"
 
599
        chk_bytes = self.get_chk_bytes()
 
600
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv, 120)
 
601
        chk_inv.id_to_entry._ensure_root()
 
602
        self.assertEqual(120, chk_inv.id_to_entry._root_node.maximum_size)
 
603
        self.assertEqual(1, chk_inv.id_to_entry._root_node._key_width)
 
604
        p_id_basename = chk_inv.parent_id_basename_to_file_id
 
605
        p_id_basename._ensure_root()
 
606
        self.assertEqual(120, p_id_basename._root_node.maximum_size)
 
607
        self.assertEqual(2, p_id_basename._root_node._key_width)
 
608
 
 
609
    def test___iter__(self):
 
610
        inv = Inventory()
 
611
        inv.revision_id = "revid"
 
612
        inv.root.revision = "rootrev"
 
613
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
614
        inv["fileid"].revision = "filerev"
 
615
        inv["fileid"].executable = True
 
616
        inv["fileid"].text_sha1 = "ffff"
 
617
        inv["fileid"].text_size = 1
 
618
        chk_bytes = self.get_chk_bytes()
 
619
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
620
        bytes = ''.join(chk_inv.to_lines())
 
621
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
 
622
        fileids = list(new_inv.__iter__())
 
623
        fileids.sort()
 
624
        self.assertEqual([inv.root.file_id, "fileid"], fileids)
 
625
 
 
626
    def test__len__(self):
 
627
        inv = Inventory()
 
628
        inv.revision_id = "revid"
 
629
        inv.root.revision = "rootrev"
 
630
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
631
        inv["fileid"].revision = "filerev"
 
632
        inv["fileid"].executable = True
 
633
        inv["fileid"].text_sha1 = "ffff"
 
634
        inv["fileid"].text_size = 1
 
635
        chk_bytes = self.get_chk_bytes()
 
636
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
637
        self.assertEqual(2, len(chk_inv))
 
638
 
 
639
    def test___getitem__(self):
 
640
        inv = Inventory()
 
641
        inv.revision_id = "revid"
 
642
        inv.root.revision = "rootrev"
 
643
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
644
        inv["fileid"].revision = "filerev"
 
645
        inv["fileid"].executable = True
 
646
        inv["fileid"].text_sha1 = "ffff"
 
647
        inv["fileid"].text_size = 1
 
648
        chk_bytes = self.get_chk_bytes()
 
649
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
650
        bytes = ''.join(chk_inv.to_lines())
 
651
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
 
652
        root_entry = new_inv[inv.root.file_id]
 
653
        file_entry = new_inv["fileid"]
 
654
        self.assertEqual("directory", root_entry.kind)
 
655
        self.assertEqual(inv.root.file_id, root_entry.file_id)
 
656
        self.assertEqual(inv.root.parent_id, root_entry.parent_id)
 
657
        self.assertEqual(inv.root.name, root_entry.name)
 
658
        self.assertEqual("rootrev", root_entry.revision)
 
659
        self.assertEqual("file", file_entry.kind)
 
660
        self.assertEqual("fileid", file_entry.file_id)
 
661
        self.assertEqual(inv.root.file_id, file_entry.parent_id)
 
662
        self.assertEqual("file", file_entry.name)
 
663
        self.assertEqual("filerev", file_entry.revision)
 
664
        self.assertEqual("ffff", file_entry.text_sha1)
 
665
        self.assertEqual(1, file_entry.text_size)
 
666
        self.assertEqual(True, file_entry.executable)
 
667
        self.assertRaises(errors.NoSuchId, new_inv.__getitem__, 'missing')
 
668
 
 
669
    def test_has_id_true(self):
 
670
        inv = Inventory()
 
671
        inv.revision_id = "revid"
 
672
        inv.root.revision = "rootrev"
 
673
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
674
        inv["fileid"].revision = "filerev"
 
675
        inv["fileid"].executable = True
 
676
        inv["fileid"].text_sha1 = "ffff"
 
677
        inv["fileid"].text_size = 1
 
678
        chk_bytes = self.get_chk_bytes()
 
679
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
680
        self.assertTrue(chk_inv.has_id('fileid'))
 
681
        self.assertTrue(chk_inv.has_id(inv.root.file_id))
 
682
 
 
683
    def test_has_id_not(self):
 
684
        inv = Inventory()
 
685
        inv.revision_id = "revid"
 
686
        inv.root.revision = "rootrev"
 
687
        chk_bytes = self.get_chk_bytes()
 
688
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
689
        self.assertFalse(chk_inv.has_id('fileid'))
 
690
 
 
691
    def test_id2path(self):
 
692
        inv = Inventory()
 
693
        inv.revision_id = "revid"
 
694
        inv.root.revision = "rootrev"
 
695
        direntry = InventoryDirectory("dirid", "dir", inv.root.file_id)
 
696
        fileentry = InventoryFile("fileid", "file", "dirid")
 
697
        inv.add(direntry)
 
698
        inv.add(fileentry)
 
699
        inv["fileid"].revision = "filerev"
 
700
        inv["fileid"].executable = True
 
701
        inv["fileid"].text_sha1 = "ffff"
 
702
        inv["fileid"].text_size = 1
 
703
        inv["dirid"].revision = "filerev"
 
704
        chk_bytes = self.get_chk_bytes()
 
705
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
706
        bytes = ''.join(chk_inv.to_lines())
 
707
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
 
708
        self.assertEqual('', new_inv.id2path(inv.root.file_id))
 
709
        self.assertEqual('dir', new_inv.id2path('dirid'))
 
710
        self.assertEqual('dir/file', new_inv.id2path('fileid'))
 
711
 
 
712
    def test_path2id(self):
 
713
        inv = Inventory()
 
714
        inv.revision_id = "revid"
 
715
        inv.root.revision = "rootrev"
 
716
        direntry = InventoryDirectory("dirid", "dir", inv.root.file_id)
 
717
        fileentry = InventoryFile("fileid", "file", "dirid")
 
718
        inv.add(direntry)
 
719
        inv.add(fileentry)
 
720
        inv["fileid"].revision = "filerev"
 
721
        inv["fileid"].executable = True
 
722
        inv["fileid"].text_sha1 = "ffff"
 
723
        inv["fileid"].text_size = 1
 
724
        inv["dirid"].revision = "filerev"
 
725
        chk_bytes = self.get_chk_bytes()
 
726
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
727
        bytes = ''.join(chk_inv.to_lines())
 
728
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
 
729
        self.assertEqual(inv.root.file_id, new_inv.path2id(''))
 
730
        self.assertEqual('dirid', new_inv.path2id('dir'))
 
731
        self.assertEqual('fileid', new_inv.path2id('dir/file'))
 
732
 
 
733
    def test_create_by_apply_delta_sets_root(self):
 
734
        inv = Inventory()
 
735
        inv.revision_id = "revid"
 
736
        chk_bytes = self.get_chk_bytes()
 
737
        base_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
738
        inv.add_path("", "directory", "myrootid", None)
 
739
        inv.revision_id = "expectedid"
 
740
        reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
741
        delta = [(None, "",  "myrootid", inv.root)]
 
742
        new_inv = base_inv.create_by_apply_delta(delta, "expectedid")
 
743
        self.assertEquals(reference_inv.root, new_inv.root)
 
744
 
 
745
    def test_create_by_apply_delta_empty_add_child(self):
 
746
        inv = Inventory()
 
747
        inv.revision_id = "revid"
 
748
        inv.root.revision = "rootrev"
 
749
        chk_bytes = self.get_chk_bytes()
 
750
        base_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
751
        a_entry = InventoryFile("A-id", "A", inv.root.file_id)
 
752
        a_entry.revision = "filerev"
 
753
        a_entry.executable = True
 
754
        a_entry.text_sha1 = "ffff"
 
755
        a_entry.text_size = 1
 
756
        inv.add(a_entry)
 
757
        inv.revision_id = "expectedid"
 
758
        reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
759
        delta = [(None, "A",  "A-id", a_entry)]
 
760
        new_inv = base_inv.create_by_apply_delta(delta, "expectedid")
 
761
        # new_inv should be the same as reference_inv.
 
762
        self.assertEqual(reference_inv.revision_id, new_inv.revision_id)
 
763
        self.assertEqual(reference_inv.root_id, new_inv.root_id)
 
764
        reference_inv.id_to_entry._ensure_root()
 
765
        new_inv.id_to_entry._ensure_root()
 
766
        self.assertEqual(reference_inv.id_to_entry._root_node._key,
 
767
            new_inv.id_to_entry._root_node._key)
 
768
 
 
769
    def test_create_by_apply_delta_empty_add_child_updates_parent_id(self):
 
770
        inv = Inventory()
 
771
        inv.revision_id = "revid"
 
772
        inv.root.revision = "rootrev"
 
773
        chk_bytes = self.get_chk_bytes()
 
774
        base_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
775
        a_entry = InventoryFile("A-id", "A", inv.root.file_id)
 
776
        a_entry.revision = "filerev"
 
777
        a_entry.executable = True
 
778
        a_entry.text_sha1 = "ffff"
 
779
        a_entry.text_size = 1
 
780
        inv.add(a_entry)
 
781
        inv.revision_id = "expectedid"
 
782
        reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
783
        delta = [(None, "A",  "A-id", a_entry)]
 
784
        new_inv = base_inv.create_by_apply_delta(delta, "expectedid")
 
785
        reference_inv.id_to_entry._ensure_root()
 
786
        reference_inv.parent_id_basename_to_file_id._ensure_root()
 
787
        new_inv.id_to_entry._ensure_root()
 
788
        new_inv.parent_id_basename_to_file_id._ensure_root()
 
789
        # new_inv should be the same as reference_inv.
 
790
        self.assertEqual(reference_inv.revision_id, new_inv.revision_id)
 
791
        self.assertEqual(reference_inv.root_id, new_inv.root_id)
 
792
        self.assertEqual(reference_inv.id_to_entry._root_node._key,
 
793
            new_inv.id_to_entry._root_node._key)
 
794
        self.assertEqual(reference_inv.parent_id_basename_to_file_id._root_node._key,
 
795
            new_inv.parent_id_basename_to_file_id._root_node._key)
 
796
 
 
797
    def test_iter_changes(self):
 
798
        # Low level bootstrapping smoke test; comprehensive generic tests via
 
799
        # InterTree are coming.
 
800
        inv = Inventory()
 
801
        inv.revision_id = "revid"
 
802
        inv.root.revision = "rootrev"
 
803
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
804
        inv["fileid"].revision = "filerev"
 
805
        inv["fileid"].executable = True
 
806
        inv["fileid"].text_sha1 = "ffff"
 
807
        inv["fileid"].text_size = 1
 
808
        inv2 = Inventory()
 
809
        inv2.revision_id = "revid2"
 
810
        inv2.root.revision = "rootrev"
 
811
        inv2.add(InventoryFile("fileid", "file", inv.root.file_id))
 
812
        inv2["fileid"].revision = "filerev2"
 
813
        inv2["fileid"].executable = False
 
814
        inv2["fileid"].text_sha1 = "bbbb"
 
815
        inv2["fileid"].text_size = 2
 
816
        # get fresh objects.
 
817
        chk_bytes = self.get_chk_bytes()
 
818
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
819
        bytes = ''.join(chk_inv.to_lines())
 
820
        inv_1 = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
 
821
        chk_inv2 = CHKInventory.from_inventory(chk_bytes, inv2)
 
822
        bytes = ''.join(chk_inv2.to_lines())
 
823
        inv_2 = CHKInventory.deserialise(chk_bytes, bytes, ("revid2",))
 
824
        self.assertEqual([('fileid', (u'file', u'file'), True, (True, True),
 
825
            ('TREE_ROOT', 'TREE_ROOT'), (u'file', u'file'), ('file', 'file'),
 
826
            (False, True))],
 
827
            list(inv_1.iter_changes(inv_2)))
 
828
 
 
829
    def test_parent_id_basename_to_file_id_index_enabled(self):
 
830
        inv = Inventory()
 
831
        inv.revision_id = "revid"
 
832
        inv.root.revision = "rootrev"
 
833
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
834
        inv["fileid"].revision = "filerev"
 
835
        inv["fileid"].executable = True
 
836
        inv["fileid"].text_sha1 = "ffff"
 
837
        inv["fileid"].text_size = 1
 
838
        # get fresh objects.
 
839
        chk_bytes = self.get_chk_bytes()
 
840
        tmp_inv = CHKInventory.from_inventory(chk_bytes, inv)
 
841
        bytes = ''.join(tmp_inv.to_lines())
 
842
        chk_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
 
843
        self.assertIsInstance(chk_inv.parent_id_basename_to_file_id, chk_map.CHKMap)
 
844
        self.assertEqual(
 
845
            {('', ''): 'TREE_ROOT', ('TREE_ROOT', 'file'): 'fileid'},
 
846
            dict(chk_inv.parent_id_basename_to_file_id.iteritems()))
 
847
 
 
848
    def test_file_entry_to_bytes(self):
 
849
        inv = CHKInventory(None)
 
850
        ie = inventory.InventoryFile('file-id', 'filename', 'parent-id')
 
851
        ie.executable = True
 
852
        ie.revision = 'file-rev-id'
 
853
        ie.text_sha1 = 'abcdefgh'
 
854
        ie.text_size = 100
 
855
        bytes = inv._entry_to_bytes(ie)
 
856
        self.assertEqual('file: file-id\nparent-id\nfilename\n'
 
857
                         'file-rev-id\nabcdefgh\n100\nY', bytes)
 
858
        ie2 = inv._bytes_to_entry(bytes)
 
859
        self.assertEqual(ie, ie2)
 
860
        self.assertIsInstance(ie2.name, unicode)
 
861
        self.assertEqual(('filename', 'file-id', 'file-rev-id'),
 
862
                         inv._bytes_to_utf8name_key(bytes))
 
863
 
 
864
    def test_file2_entry_to_bytes(self):
 
865
        inv = CHKInventory(None)
 
866
        # \u30a9 == 'omega'
 
867
        ie = inventory.InventoryFile('file-id', u'\u03a9name', 'parent-id')
 
868
        ie.executable = False
 
869
        ie.revision = 'file-rev-id'
 
870
        ie.text_sha1 = '123456'
 
871
        ie.text_size = 25
 
872
        bytes = inv._entry_to_bytes(ie)
 
873
        self.assertEqual('file: file-id\nparent-id\n\xce\xa9name\n'
 
874
                         'file-rev-id\n123456\n25\nN', bytes)
 
875
        ie2 = inv._bytes_to_entry(bytes)
 
876
        self.assertEqual(ie, ie2)
 
877
        self.assertIsInstance(ie2.name, unicode)
 
878
        self.assertEqual(('\xce\xa9name', 'file-id', 'file-rev-id'),
 
879
                         inv._bytes_to_utf8name_key(bytes))
 
880
 
 
881
    def test_dir_entry_to_bytes(self):
 
882
        inv = CHKInventory(None)
 
883
        ie = inventory.InventoryDirectory('dir-id', 'dirname', 'parent-id')
 
884
        ie.revision = 'dir-rev-id'
 
885
        bytes = inv._entry_to_bytes(ie)
 
886
        self.assertEqual('dir: dir-id\nparent-id\ndirname\ndir-rev-id', bytes)
 
887
        ie2 = inv._bytes_to_entry(bytes)
 
888
        self.assertEqual(ie, ie2)
 
889
        self.assertIsInstance(ie2.name, unicode)
 
890
        self.assertEqual(('dirname', 'dir-id', 'dir-rev-id'),
 
891
                         inv._bytes_to_utf8name_key(bytes))
 
892
 
 
893
    def test_dir2_entry_to_bytes(self):
 
894
        inv = CHKInventory(None)
 
895
        ie = inventory.InventoryDirectory('dir-id', u'dir\u03a9name',
 
896
                                          None)
 
897
        ie.revision = 'dir-rev-id'
 
898
        bytes = inv._entry_to_bytes(ie)
 
899
        self.assertEqual('dir: dir-id\n\ndir\xce\xa9name\n'
 
900
                         'dir-rev-id', bytes)
 
901
        ie2 = inv._bytes_to_entry(bytes)
 
902
        self.assertEqual(ie, ie2)
 
903
        self.assertIsInstance(ie2.name, unicode)
 
904
        self.assertIs(ie2.parent_id, None)
 
905
        self.assertEqual(('dir\xce\xa9name', 'dir-id', 'dir-rev-id'),
 
906
                         inv._bytes_to_utf8name_key(bytes))
 
907
 
 
908
    def test_symlink_entry_to_bytes(self):
 
909
        inv = CHKInventory(None)
 
910
        ie = inventory.InventoryLink('link-id', 'linkname', 'parent-id')
 
911
        ie.revision = 'link-rev-id'
 
912
        ie.symlink_target = u'target/path'
 
913
        bytes = inv._entry_to_bytes(ie)
 
914
        self.assertEqual('symlink: link-id\nparent-id\nlinkname\n'
 
915
                         'link-rev-id\ntarget/path', bytes)
 
916
        ie2 = inv._bytes_to_entry(bytes)
 
917
        self.assertEqual(ie, ie2)
 
918
        self.assertIsInstance(ie2.name, unicode)
 
919
        self.assertIsInstance(ie2.symlink_target, unicode)
 
920
        self.assertEqual(('linkname', 'link-id', 'link-rev-id'),
 
921
                         inv._bytes_to_utf8name_key(bytes))
 
922
 
 
923
    def test_symlink2_entry_to_bytes(self):
 
924
        inv = CHKInventory(None)
 
925
        ie = inventory.InventoryLink('link-id', u'link\u03a9name', 'parent-id')
 
926
        ie.revision = 'link-rev-id'
 
927
        ie.symlink_target = u'target/\u03a9path'
 
928
        bytes = inv._entry_to_bytes(ie)
 
929
        self.assertEqual('symlink: link-id\nparent-id\nlink\xce\xa9name\n'
 
930
                         'link-rev-id\ntarget/\xce\xa9path', bytes)
 
931
        ie2 = inv._bytes_to_entry(bytes)
 
932
        self.assertEqual(ie, ie2)
 
933
        self.assertIsInstance(ie2.name, unicode)
 
934
        self.assertIsInstance(ie2.symlink_target, unicode)
 
935
        self.assertEqual(('link\xce\xa9name', 'link-id', 'link-rev-id'),
 
936
                         inv._bytes_to_utf8name_key(bytes))
 
937
 
 
938
    def test_tree_reference_entry_to_bytes(self):
 
939
        inv = CHKInventory(None)
 
940
        ie = inventory.TreeReference('tree-root-id', u'tree\u03a9name',
 
941
                                     'parent-id')
 
942
        ie.revision = 'tree-rev-id'
 
943
        ie.reference_revision = 'ref-rev-id'
 
944
        bytes = inv._entry_to_bytes(ie)
 
945
        self.assertEqual('tree: tree-root-id\nparent-id\ntree\xce\xa9name\n'
 
946
                         'tree-rev-id\nref-rev-id', bytes)
 
947
        ie2 = inv._bytes_to_entry(bytes)
 
948
        self.assertEqual(ie, ie2)
 
949
        self.assertIsInstance(ie2.name, unicode)
 
950
        self.assertEqual(('tree\xce\xa9name', 'tree-root-id', 'tree-rev-id'),
 
951
                         inv._bytes_to_utf8name_key(bytes))