/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2008, 2009, 2010 Canonical Ltd
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
2
#
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.
7
#
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.
12
#
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
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
16
17
"""Tests for pack repositories.
18
19
These tests are repeated for all pack-based repository formats.
20
"""
21
3582.3.4 by Martin Pool
Use cStringIO rather than StringIO
22
from cStringIO import StringIO
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
23
from stat import S_ISDIR
24
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
25
from bzrlib.btree_index import BTreeGraphIndex
26
from bzrlib.index import GraphIndex
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
27
from bzrlib import (
28
    bzrdir,
29
    errors,
30
    inventory,
4002.1.1 by Andrew Bennetts
Implement suspend_write_group/resume_write_group.
31
    osutils,
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
32
    progress,
33
    repository,
34
    revision as _mod_revision,
35
    symbol_versioning,
36
    tests,
37
    ui,
38
    upgrade,
39
    workingtree,
40
    )
4360.4.6 by John Arbash Meinel
Change how 'missing.*parent_prevents_commit' determines what to skip.
41
from bzrlib.repofmt import (
42
    pack_repo,
43
    groupcompress_repo,
44
    )
4597.1.10 by John Arbash Meinel
Fix some tests that were failing because we checked against RepositoryFormatCHK1
45
from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2a
3801.1.18 by Andrew Bennetts
Add a test that ensures that the autopack RPC is actually used for all pack formats.
46
from bzrlib.smart import (
47
    client,
48
    )
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
49
from bzrlib.tests import (
50
    TestCase,
51
    TestCaseWithTransport,
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
52
    TestNotApplicable,
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
53
    TestSkipped,
54
    )
55
from bzrlib.transport import (
56
    get_transport,
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
57
    memory,
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
58
    )
5017.3.44 by Vincent Ladeuil
-s bt.per_pack_repos passing
59
from bzrlib.tests import test_server
3825.4.2 by Andrew Bennetts
Run the abort_write_group tests against a memory transport to avoid platform-specific limits on changing files that may be in use.
60
from bzrlib.tests.per_repository import TestCaseWithRepository
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
61
62
63
class TestPackRepository(TestCaseWithTransport):
64
    """Tests to be repeated across all pack-based formats.
65
66
    The following are populated from the test scenario:
67
68
    :ivar format_name: Registered name fo the format to test.
69
    :ivar format_string: On-disk format marker.
70
    :ivar format_supports_external_lookups: Boolean.
71
    """
72
73
    def get_format(self):
74
        return bzrdir.format_registry.make_bzrdir(self.format_name)
75
76
    def test_attribute__fetch_order(self):
3606.7.3 by John Arbash Meinel
We don't have to fetch in topological order, as long as we fix all of the delta logic pieces.
77
        """Packs do not need ordered data retrieval."""
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
78
        format = self.get_format()
79
        repo = self.make_repository('.', format=format)
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
80
        self.assertEqual('unordered', repo._format._fetch_order)
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
81
82
    def test_attribute__fetch_uses_deltas(self):
83
        """Packs reuse deltas."""
84
        format = self.get_format()
85
        repo = self.make_repository('.', format=format)
4597.1.10 by John Arbash Meinel
Fix some tests that were failing because we checked against RepositoryFormatCHK1
86
        if isinstance(format.repository_format, RepositoryFormat2a):
4265.1.4 by John Arbash Meinel
Special case the CHK1 format to allow it to not fetch using deltas.
87
            # TODO: This is currently a workaround. CHK format repositories
88
            #       ignore the 'deltas' flag, but during conversions, we can't
89
            #       do unordered delta fetches. Remove this clause once we
90
            #       improve the inter-format fetching.
91
            self.assertEqual(False, repo._format._fetch_uses_deltas)
92
        else:
93
            self.assertEqual(True, repo._format._fetch_uses_deltas)
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
94
95
    def test_disk_layout(self):
96
        format = self.get_format()
97
        repo = self.make_repository('.', format=format)
98
        # in case of side effects of locking.
99
        repo.lock_write()
100
        repo.unlock()
101
        t = repo.bzrdir.get_repository_transport(None)
102
        self.check_format(t)
103
        # XXX: no locks left when unlocked at the moment
104
        # self.assertEqualDiff('', t.get('lock').read())
105
        self.check_databases(t)
106
107
    def check_format(self, t):
108
        self.assertEqualDiff(
109
            self.format_string, # from scenario
110
            t.get('format').read())
111
112
    def assertHasNoKndx(self, t, knit_name):
113
        """Assert that knit_name has no index on t."""
114
        self.assertFalse(t.has(knit_name + '.kndx'))
115
116
    def assertHasNoKnit(self, t, knit_name):
117
        """Assert that knit_name exists on t."""
118
        # no default content
119
        self.assertFalse(t.has(knit_name + '.knit'))
120
121
    def check_databases(self, t):
122
        """check knit content for a repository."""
123
        # check conversion worked
124
        self.assertHasNoKndx(t, 'inventory')
125
        self.assertHasNoKnit(t, 'inventory')
126
        self.assertHasNoKndx(t, 'revisions')
127
        self.assertHasNoKnit(t, 'revisions')
128
        self.assertHasNoKndx(t, 'signatures')
129
        self.assertHasNoKnit(t, 'signatures')
130
        self.assertFalse(t.has('knits'))
131
        # revision-indexes file-container directory
132
        self.assertEqual([],
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
133
            list(self.index_class(t, 'pack-names', None).iter_all_entries()))
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
134
        self.assertTrue(S_ISDIR(t.stat('packs').st_mode))
135
        self.assertTrue(S_ISDIR(t.stat('upload').st_mode))
136
        self.assertTrue(S_ISDIR(t.stat('indices').st_mode))
137
        self.assertTrue(S_ISDIR(t.stat('obsolete_packs').st_mode))
138
139
    def test_shared_disk_layout(self):
140
        format = self.get_format()
141
        repo = self.make_repository('.', shared=True, format=format)
142
        # we want:
143
        t = repo.bzrdir.get_repository_transport(None)
144
        self.check_format(t)
145
        # XXX: no locks left when unlocked at the moment
146
        # self.assertEqualDiff('', t.get('lock').read())
147
        # We should have a 'shared-storage' marker file.
148
        self.assertEqualDiff('', t.get('shared-storage').read())
149
        self.check_databases(t)
150
151
    def test_shared_no_tree_disk_layout(self):
152
        format = self.get_format()
153
        repo = self.make_repository('.', shared=True, format=format)
154
        repo.set_make_working_trees(False)
155
        # we want:
156
        t = repo.bzrdir.get_repository_transport(None)
157
        self.check_format(t)
158
        # XXX: no locks left when unlocked at the moment
159
        # self.assertEqualDiff('', t.get('lock').read())
160
        # We should have a 'shared-storage' marker file.
161
        self.assertEqualDiff('', t.get('shared-storage').read())
162
        # We should have a marker for the no-working-trees flag.
163
        self.assertEqualDiff('', t.get('no-working-trees').read())
164
        # The marker should go when we toggle the setting.
165
        repo.set_make_working_trees(True)
166
        self.assertFalse(t.has('no-working-trees'))
167
        self.check_databases(t)
168
169
    def test_adding_revision_creates_pack_indices(self):
170
        format = self.get_format()
171
        tree = self.make_branch_and_tree('.', format=format)
172
        trans = tree.branch.repository.bzrdir.get_repository_transport(None)
173
        self.assertEqual([],
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
174
            list(self.index_class(trans, 'pack-names', None).iter_all_entries()))
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
175
        tree.commit('foobarbaz')
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
176
        index = self.index_class(trans, 'pack-names', None)
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
177
        index_nodes = list(index.iter_all_entries())
178
        self.assertEqual(1, len(index_nodes))
179
        node = index_nodes[0]
180
        name = node[1][0]
181
        # the pack sizes should be listed in the index
182
        pack_value = node[2]
183
        sizes = [int(digits) for digits in pack_value.split(' ')]
184
        for size, suffix in zip(sizes, ['.rix', '.iix', '.tix', '.six']):
185
            stat = trans.stat('indices/%s%s' % (name, suffix))
186
            self.assertEqual(size, stat.st_size)
187
188
    def test_pulling_nothing_leads_to_no_new_names(self):
189
        format = self.get_format()
190
        tree1 = self.make_branch_and_tree('1', format=format)
191
        tree2 = self.make_branch_and_tree('2', format=format)
192
        tree1.branch.repository.fetch(tree2.branch.repository)
193
        trans = tree1.branch.repository.bzrdir.get_repository_transport(None)
194
        self.assertEqual([],
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
195
            list(self.index_class(trans, 'pack-names', None).iter_all_entries()))
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
196
197
    def test_commit_across_pack_shape_boundary_autopacks(self):
198
        format = self.get_format()
199
        tree = self.make_branch_and_tree('.', format=format)
200
        trans = tree.branch.repository.bzrdir.get_repository_transport(None)
201
        # This test could be a little cheaper by replacing the packs
202
        # attribute on the repository to allow a different pack distribution
203
        # and max packs policy - so we are checking the policy is honoured
204
        # in the test. But for now 11 commits is not a big deal in a single
205
        # test.
206
        for x in range(9):
207
            tree.commit('commit %s' % x)
208
        # there should be 9 packs:
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
209
        index = self.index_class(trans, 'pack-names', None)
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
210
        self.assertEqual(9, len(list(index.iter_all_entries())))
211
        # insert some files in obsolete_packs which should be removed by pack.
212
        trans.put_bytes('obsolete_packs/foo', '123')
213
        trans.put_bytes('obsolete_packs/bar', '321')
214
        # committing one more should coalesce to 1 of 10.
215
        tree.commit('commit triggering pack')
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
216
        index = self.index_class(trans, 'pack-names', None)
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
217
        self.assertEqual(1, len(list(index.iter_all_entries())))
218
        # packing should not damage data
219
        tree = tree.bzrdir.open_workingtree()
220
        check_result = tree.branch.repository.check(
221
            [tree.branch.last_revision()])
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
222
        nb_files = 5 # .pack, .rix, .iix, .tix, .six
223
        if tree.branch.repository._format.supports_chks:
224
            nb_files += 1 # .cix
225
        # We should have 10 x nb_files files in the obsolete_packs directory.
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
226
        obsolete_files = list(trans.list_dir('obsolete_packs'))
227
        self.assertFalse('foo' in obsolete_files)
228
        self.assertFalse('bar' in obsolete_files)
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
229
        self.assertEqual(10 * nb_files, len(obsolete_files))
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
230
        # XXX: Todo check packs obsoleted correctly - old packs and indices
231
        # in the obsolete_packs directory.
232
        large_pack_name = list(index.iter_all_entries())[0][1][0]
233
        # finally, committing again should not touch the large pack.
234
        tree.commit('commit not triggering pack')
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
235
        index = self.index_class(trans, 'pack-names', None)
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
236
        self.assertEqual(2, len(list(index.iter_all_entries())))
237
        pack_names = [node[1][0] for node in index.iter_all_entries()]
238
        self.assertTrue(large_pack_name in pack_names)
239
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
240
    def test_commit_write_group_returns_new_pack_names(self):
4634.30.1 by Robert Collins
Properly pack 2a repositories during conversion operations. (Robert Collins. #423818)
241
        # This test doesn't need real disk.
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
242
        self.vfs_transport_factory = memory.MemoryServer
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
243
        format = self.get_format()
4634.30.1 by Robert Collins
Properly pack 2a repositories during conversion operations. (Robert Collins. #423818)
244
        repo = self.make_repository('foo', format=format)
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
245
        repo.lock_write()
246
        try:
4634.30.1 by Robert Collins
Properly pack 2a repositories during conversion operations. (Robert Collins. #423818)
247
            # All current pack repository styles autopack at 10 revisions; and
248
            # autopack as well as regular commit write group needs to return
249
            # the new pack name. Looping is a little ugly, but we don't have a
250
            # clean way to test both the autopack logic and the normal code
251
            # path without doing this loop.
252
            for pos in range(10):
253
                revid = str(pos)
254
                repo.start_write_group()
255
                try:
256
                    inv = inventory.Inventory(revision_id=revid)
257
                    inv.root.revision = revid
258
                    repo.texts.add_lines((inv.root.file_id, revid), [], [])
259
                    rev = _mod_revision.Revision(timestamp=0, timezone=None,
260
                        committer="Foo Bar <foo@example.com>", message="Message",
261
                        revision_id=revid)
262
                    rev.parent_ids = ()
263
                    repo.add_revision(revid, rev, inv=inv)
264
                except:
265
                    repo.abort_write_group()
266
                    raise
267
                else:
268
                    old_names = repo._pack_collection._names.keys()
269
                    result = repo.commit_write_group()
270
                    cur_names = repo._pack_collection._names.keys()
271
                    new_names = list(set(cur_names) - set(old_names))
272
                    self.assertEqual(new_names, result)
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
273
        finally:
274
            repo.unlock()
275
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
276
    def test_fail_obsolete_deletion(self):
277
        # failing to delete obsolete packs is not fatal
278
        format = self.get_format()
5017.3.44 by Vincent Ladeuil
-s bt.per_pack_repos passing
279
        server = test_server.FakeNFSServer()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
280
        self.start_server(server)
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
281
        transport = get_transport(server.get_url())
282
        bzrdir = self.get_format().initialize_on_transport(transport)
283
        repo = bzrdir.create_repository()
284
        repo_transport = bzrdir.get_repository_transport(None)
285
        self.assertTrue(repo_transport.has('obsolete_packs'))
286
        # these files are in use by another client and typically can't be deleted
287
        repo_transport.put_bytes('obsolete_packs/.nfsblahblah', 'contents')
288
        repo._pack_collection._clear_obsolete_packs()
289
        self.assertTrue(repo_transport.has('obsolete_packs/.nfsblahblah'))
290
291
    def test_pack_after_two_commits_packs_everything(self):
292
        format = self.get_format()
293
        tree = self.make_branch_and_tree('.', format=format)
294
        trans = tree.branch.repository.bzrdir.get_repository_transport(None)
295
        tree.commit('start')
296
        tree.commit('more work')
297
        tree.branch.repository.pack()
298
        # there should be 1 pack:
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
299
        index = self.index_class(trans, 'pack-names', None)
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
300
        self.assertEqual(1, len(list(index.iter_all_entries())))
301
        self.assertEqual(2, len(tree.branch.repository.all_revision_ids()))
302
4597.1.6 by John Arbash Meinel
Add a test that inventory texts are preserved during pack.
303
    def test_pack_preserves_all_inventories(self):
304
        # This is related to bug:
305
        #   https://bugs.launchpad.net/bzr/+bug/412198
306
        # Stacked repositories need to keep the inventory for parents, even
307
        # after a pack operation. However, it is harder to test that, then just
308
        # test that all inventory texts are preserved.
309
        format = self.get_format()
310
        builder = self.make_branch_builder('source', format=format)
311
        builder.start_series()
312
        builder.build_snapshot('A-id', None, [
313
            ('add', ('', 'root-id', 'directory', None))])
314
        builder.build_snapshot('B-id', None, [
315
            ('add', ('file', 'file-id', 'file', 'B content\n'))])
316
        builder.build_snapshot('C-id', None, [
317
            ('modify', ('file-id', 'C content\n'))])
318
        builder.finish_series()
319
        b = builder.get_branch()
320
        b.lock_read()
321
        self.addCleanup(b.unlock)
322
        repo = self.make_repository('repo', shared=True, format=format)
323
        repo.lock_write()
324
        self.addCleanup(repo.unlock)
325
        repo.fetch(b.repository, revision_id='B-id')
326
        inv = b.repository.iter_inventories(['C-id']).next()
327
        repo.start_write_group()
328
        repo.add_inventory('C-id', inv, ['B-id'])
329
        repo.commit_write_group()
330
        self.assertEqual([('A-id',), ('B-id',), ('C-id',)],
331
                         sorted(repo.inventories.keys()))
332
        repo.pack()
333
        self.assertEqual([('A-id',), ('B-id',), ('C-id',)],
334
                         sorted(repo.inventories.keys()))
335
        # Content should be preserved as well
336
        self.assertEqual(inv, repo.iter_inventories(['C-id']).next())
337
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
338
    def test_pack_layout(self):
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
339
        # Test that the ordering of revisions in pack repositories is
340
        # tip->ancestor
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
341
        format = self.get_format()
342
        tree = self.make_branch_and_tree('.', format=format)
343
        trans = tree.branch.repository.bzrdir.get_repository_transport(None)
344
        tree.commit('start', rev_id='1')
345
        tree.commit('more work', rev_id='2')
346
        tree.branch.repository.pack()
347
        tree.lock_read()
348
        self.addCleanup(tree.unlock)
349
        pack = tree.branch.repository._pack_collection.get_pack_by_name(
350
            tree.branch.repository._pack_collection.names()[0])
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
351
        # revision access tends to be tip->ancestor, so ordering that way on
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
352
        # disk is a good idea.
353
        for _1, key, val, refs in pack.revision_index.iter_all_entries():
4597.1.10 by John Arbash Meinel
Fix some tests that were failing because we checked against RepositoryFormatCHK1
354
            if type(format.repository_format) is RepositoryFormat2a:
4350.2.1 by John Arbash Meinel
Update a test to support CHK formats.
355
                # group_start, group_len, internal_start, internal_len
356
                pos = map(int, val.split())
357
            else:
358
                # eol_flag, start, len
359
                pos = int(val[1:].split()[0])
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
360
            if key == ('1',):
4350.2.1 by John Arbash Meinel
Update a test to support CHK formats.
361
                pos_1 = pos
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
362
            else:
4350.2.1 by John Arbash Meinel
Update a test to support CHK formats.
363
                pos_2 = pos
364
        self.assertTrue(pos_2 < pos_1, 'rev 1 came before rev 2 %s > %s'
365
                                       % (pos_1, pos_2))
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
366
367
    def test_pack_repositories_support_multiple_write_locks(self):
368
        format = self.get_format()
369
        self.make_repository('.', shared=True, format=format)
370
        r1 = repository.Repository.open('.')
371
        r2 = repository.Repository.open('.')
372
        r1.lock_write()
373
        self.addCleanup(r1.unlock)
374
        r2.lock_write()
375
        r2.unlock()
376
377
    def _add_text(self, repo, fileid):
378
        """Add a text to the repository within a write group."""
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
379
        repo.texts.add_lines((fileid, 'samplerev+'+fileid), [],
380
            ['smaplerev+'+fileid])
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
381
382
    def test_concurrent_writers_merge_new_packs(self):
383
        format = self.get_format()
384
        self.make_repository('.', shared=True, format=format)
385
        r1 = repository.Repository.open('.')
386
        r2 = repository.Repository.open('.')
387
        r1.lock_write()
388
        try:
389
            # access enough data to load the names list
390
            list(r1.all_revision_ids())
391
            r2.lock_write()
392
            try:
393
                # access enough data to load the names list
394
                list(r2.all_revision_ids())
395
                r1.start_write_group()
396
                try:
397
                    r2.start_write_group()
398
                    try:
399
                        self._add_text(r1, 'fileidr1')
400
                        self._add_text(r2, 'fileidr2')
401
                    except:
402
                        r2.abort_write_group()
403
                        raise
404
                except:
405
                    r1.abort_write_group()
406
                    raise
407
                # both r1 and r2 have open write groups with data in them
408
                # created while the other's write group was open.
409
                # Commit both which requires a merge to the pack-names.
410
                try:
411
                    r1.commit_write_group()
412
                except:
413
                    r1.abort_write_group()
414
                    r2.abort_write_group()
415
                    raise
416
                r2.commit_write_group()
417
                # tell r1 to reload from disk
418
                r1._pack_collection.reset()
419
                # Now both repositories should know about both names
420
                r1._pack_collection.ensure_loaded()
421
                r2._pack_collection.ensure_loaded()
422
                self.assertEqual(r1._pack_collection.names(), r2._pack_collection.names())
423
                self.assertEqual(2, len(r1._pack_collection.names()))
424
            finally:
425
                r2.unlock()
426
        finally:
427
            r1.unlock()
428
429
    def test_concurrent_writer_second_preserves_dropping_a_pack(self):
430
        format = self.get_format()
431
        self.make_repository('.', shared=True, format=format)
432
        r1 = repository.Repository.open('.')
433
        r2 = repository.Repository.open('.')
434
        # add a pack to drop
435
        r1.lock_write()
436
        try:
437
            r1.start_write_group()
438
            try:
439
                self._add_text(r1, 'fileidr1')
440
            except:
441
                r1.abort_write_group()
442
                raise
443
            else:
444
                r1.commit_write_group()
445
            r1._pack_collection.ensure_loaded()
446
            name_to_drop = r1._pack_collection.all_packs()[0].name
447
        finally:
448
            r1.unlock()
449
        r1.lock_write()
450
        try:
451
            # access enough data to load the names list
452
            list(r1.all_revision_ids())
453
            r2.lock_write()
454
            try:
455
                # access enough data to load the names list
456
                list(r2.all_revision_ids())
457
                r1._pack_collection.ensure_loaded()
458
                try:
459
                    r2.start_write_group()
460
                    try:
461
                        # in r1, drop the pack
462
                        r1._pack_collection._remove_pack_from_memory(
463
                            r1._pack_collection.get_pack_by_name(name_to_drop))
464
                        # in r2, add a pack
465
                        self._add_text(r2, 'fileidr2')
466
                    except:
467
                        r2.abort_write_group()
468
                        raise
469
                except:
470
                    r1._pack_collection.reset()
471
                    raise
472
                # r1 has a changed names list, and r2 an open write groups with
473
                # changes.
474
                # save r1, and then commit the r2 write group, which requires a
475
                # merge to the pack-names, which should not reinstate
476
                # name_to_drop
477
                try:
478
                    r1._pack_collection._save_pack_names()
479
                    r1._pack_collection.reset()
480
                except:
481
                    r2.abort_write_group()
482
                    raise
483
                try:
484
                    r2.commit_write_group()
485
                except:
486
                    r2.abort_write_group()
487
                    raise
488
                # Now both repositories should now about just one name.
489
                r1._pack_collection.ensure_loaded()
490
                r2._pack_collection.ensure_loaded()
491
                self.assertEqual(r1._pack_collection.names(), r2._pack_collection.names())
492
                self.assertEqual(1, len(r1._pack_collection.names()))
493
                self.assertFalse(name_to_drop in r1._pack_collection.names())
494
            finally:
495
                r2.unlock()
496
        finally:
497
            r1.unlock()
498
3789.1.1 by John Arbash Meinel
add the failing acceptance test for the first portion.
499
    def test_concurrent_pack_triggers_reload(self):
500
        # create 2 packs, which we will then collapse
501
        tree = self.make_branch_and_tree('tree')
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
502
        tree.lock_write()
3789.1.1 by John Arbash Meinel
add the failing acceptance test for the first portion.
503
        try:
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
504
            rev1 = tree.commit('one')
505
            rev2 = tree.commit('two')
506
            r2 = repository.Repository.open('tree')
3789.1.1 by John Arbash Meinel
add the failing acceptance test for the first portion.
507
            r2.lock_read()
508
            try:
509
                # Now r2 has read the pack-names file, but will need to reload
510
                # it after r1 has repacked
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
511
                tree.branch.repository.pack()
512
                self.assertEqual({rev2:(rev1,)}, r2.get_parent_map([rev2]))
3789.1.1 by John Arbash Meinel
add the failing acceptance test for the first portion.
513
            finally:
514
                r2.unlock()
515
        finally:
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
516
            tree.unlock()
3789.1.1 by John Arbash Meinel
add the failing acceptance test for the first portion.
517
3789.2.8 by John Arbash Meinel
Add a test that KnitPackRepository.get_record_stream retries when appropriate.
518
    def test_concurrent_pack_during_get_record_reloads(self):
519
        tree = self.make_branch_and_tree('tree')
520
        tree.lock_write()
521
        try:
522
            rev1 = tree.commit('one')
523
            rev2 = tree.commit('two')
3789.2.14 by John Arbash Meinel
Update AggregateIndex to pass the reload_func into _DirectPackAccess
524
            keys = [(rev1,), (rev2,)]
3789.2.8 by John Arbash Meinel
Add a test that KnitPackRepository.get_record_stream retries when appropriate.
525
            r2 = repository.Repository.open('tree')
526
            r2.lock_read()
527
            try:
528
                # At this point, we will start grabbing a record stream, and
529
                # trigger a repack mid-way
530
                packed = False
531
                result = {}
532
                record_stream = r2.revisions.get_record_stream(keys,
533
                                    'unordered', False)
534
                for record in record_stream:
535
                    result[record.key] = record
536
                    if not packed:
537
                        tree.branch.repository.pack()
538
                        packed = True
539
                # The first record will be found in the original location, but
540
                # after the pack, we have to reload to find the next record
3789.2.14 by John Arbash Meinel
Update AggregateIndex to pass the reload_func into _DirectPackAccess
541
                self.assertEqual(sorted(keys), sorted(result.keys()))
3789.2.8 by John Arbash Meinel
Add a test that KnitPackRepository.get_record_stream retries when appropriate.
542
            finally:
543
                r2.unlock()
544
        finally:
545
            tree.unlock()
546
4634.113.2 by John Arbash Meinel
Add a test which triggers the behavior.
547
    def test_concurrent_pack_during_autopack(self):
548
        tree = self.make_branch_and_tree('tree')
549
        tree.lock_write()
550
        try:
551
            for i in xrange(9):
552
                tree.commit('rev %d' % (i,))
553
            r2 = repository.Repository.open('tree')
554
            r2.lock_write()
555
            try:
556
                # Monkey patch so that pack occurs while the other repo is
557
                # autopacking. This is slightly bad, but all current pack
558
                # repository implementations have a _pack_collection, and we
559
                # test that it gets triggered. So if a future format changes
560
                # things, the test will fail rather than succeed accidentally.
561
                autopack_count = [0]
562
                r1 = tree.branch.repository
563
                orig = r1._pack_collection.pack_distribution
564
                def trigger_during_auto(*args, **kwargs):
565
                    ret = orig(*args, **kwargs)
566
                    if not autopack_count[0]:
567
                        r2.pack()
568
                    autopack_count[0] += 1
569
                    return ret
570
                r1._pack_collection.pack_distribution = trigger_during_auto
571
                tree.commit('autopack-rev')
572
                # This triggers 2 autopacks. The first one causes r2.pack() to
573
                # fire, but r2 doesn't see the new pack file yet. The
574
                # autopack restarts and sees there are 2 files and there
575
                # should be only 1 for 10 commits. So it goes ahead and
576
                # finishes autopacking.
577
                self.assertEqual([2], autopack_count)
578
            finally:
579
                r2.unlock()
580
        finally:
581
            tree.unlock()
582
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
583
    def test_lock_write_does_not_physically_lock(self):
584
        repo = self.make_repository('.', format=self.get_format())
585
        repo.lock_write()
586
        self.addCleanup(repo.unlock)
587
        self.assertFalse(repo.get_physical_lock_status())
588
589
    def prepare_for_break_lock(self):
590
        # Setup the global ui factory state so that a break-lock method call
591
        # will find usable input in the input stream.
4449.3.27 by Martin Pool
More test updates to use CannedInputUIFactory
592
        ui.ui_factory = ui.CannedInputUIFactory([True])
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
593
594
    def test_break_lock_breaks_physical_lock(self):
595
        repo = self.make_repository('.', format=self.get_format())
596
        repo._pack_collection.lock_names()
3650.4.1 by Aaron Bentley
Fix test kipple in test_break_lock_breaks_physical_lock
597
        repo.control_files.leave_in_place()
598
        repo.unlock()
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
599
        repo2 = repository.Repository.open('.')
600
        self.assertTrue(repo.get_physical_lock_status())
601
        self.prepare_for_break_lock()
602
        repo2.break_lock()
603
        self.assertFalse(repo.get_physical_lock_status())
604
605
    def test_broken_physical_locks_error_on__unlock_names_lock(self):
606
        repo = self.make_repository('.', format=self.get_format())
607
        repo._pack_collection.lock_names()
608
        self.assertTrue(repo.get_physical_lock_status())
609
        repo2 = repository.Repository.open('.')
610
        self.prepare_for_break_lock()
611
        repo2.break_lock()
612
        self.assertRaises(errors.LockBroken, repo._pack_collection._unlock_names)
613
614
    def test_fetch_without_find_ghosts_ignores_ghosts(self):
615
        # we want two repositories at this point:
616
        # one with a revision that is a ghost in the other
617
        # repository.
618
        # 'ghost' is present in has_ghost, 'ghost' is absent in 'missing_ghost'.
619
        # 'references' is present in both repositories, and 'tip' is present
620
        # just in has_ghost.
621
        # has_ghost       missing_ghost
622
        #------------------------------
623
        # 'ghost'             -
624
        # 'references'    'references'
625
        # 'tip'               -
626
        # In this test we fetch 'tip' which should not fetch 'ghost'
627
        has_ghost = self.make_repository('has_ghost', format=self.get_format())
628
        missing_ghost = self.make_repository('missing_ghost',
629
            format=self.get_format())
630
631
        def add_commit(repo, revision_id, parent_ids):
632
            repo.lock_write()
633
            repo.start_write_group()
634
            inv = inventory.Inventory(revision_id=revision_id)
635
            inv.root.revision = revision_id
636
            root_id = inv.root.file_id
637
            sha1 = repo.add_inventory(revision_id, inv, [])
638
            repo.texts.add_lines((root_id, revision_id), [], [])
639
            rev = _mod_revision.Revision(timestamp=0,
640
                                         timezone=None,
641
                                         committer="Foo Bar <foo@example.com>",
642
                                         message="Message",
643
                                         inventory_sha1=sha1,
644
                                         revision_id=revision_id)
645
            rev.parent_ids = parent_ids
646
            repo.add_revision(revision_id, rev)
647
            repo.commit_write_group()
648
            repo.unlock()
649
        add_commit(has_ghost, 'ghost', [])
650
        add_commit(has_ghost, 'references', ['ghost'])
651
        add_commit(missing_ghost, 'references', ['ghost'])
652
        add_commit(has_ghost, 'tip', ['references'])
653
        missing_ghost.fetch(has_ghost, 'tip')
654
        # missing ghost now has tip and not ghost.
655
        rev = missing_ghost.get_revision('tip')
656
        inv = missing_ghost.get_inventory('tip')
657
        self.assertRaises(errors.NoSuchRevision,
658
            missing_ghost.get_revision, 'ghost')
659
        self.assertRaises(errors.NoSuchRevision,
660
            missing_ghost.get_inventory, 'ghost')
661
4011.5.6 by Andrew Bennetts
Make sure it's not possible to commit a pack write group when any versioned file has missing compression parents.
662
    def make_write_ready_repo(self):
4360.4.6 by John Arbash Meinel
Change how 'missing.*parent_prevents_commit' determines what to skip.
663
        format = self.get_format()
4597.1.10 by John Arbash Meinel
Fix some tests that were failing because we checked against RepositoryFormatCHK1
664
        if isinstance(format.repository_format, RepositoryFormat2a):
4360.4.6 by John Arbash Meinel
Change how 'missing.*parent_prevents_commit' determines what to skip.
665
            raise TestNotApplicable("No missing compression parents")
666
        repo = self.make_repository('.', format=format)
4011.5.6 by Andrew Bennetts
Make sure it's not possible to commit a pack write group when any versioned file has missing compression parents.
667
        repo.lock_write()
4360.4.6 by John Arbash Meinel
Change how 'missing.*parent_prevents_commit' determines what to skip.
668
        self.addCleanup(repo.unlock)
4011.5.6 by Andrew Bennetts
Make sure it's not possible to commit a pack write group when any versioned file has missing compression parents.
669
        repo.start_write_group()
4360.4.6 by John Arbash Meinel
Change how 'missing.*parent_prevents_commit' determines what to skip.
670
        self.addCleanup(repo.abort_write_group)
4011.5.6 by Andrew Bennetts
Make sure it's not possible to commit a pack write group when any versioned file has missing compression parents.
671
        return repo
672
673
    def test_missing_inventories_compression_parent_prevents_commit(self):
674
        repo = self.make_write_ready_repo()
675
        key = ('junk',)
676
        repo.inventories._index._missing_compression_parents.add(key)
677
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
678
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
679
680
    def test_missing_revisions_compression_parent_prevents_commit(self):
681
        repo = self.make_write_ready_repo()
682
        key = ('junk',)
683
        repo.revisions._index._missing_compression_parents.add(key)
684
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
685
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
686
687
    def test_missing_signatures_compression_parent_prevents_commit(self):
688
        repo = self.make_write_ready_repo()
689
        key = ('junk',)
690
        repo.signatures._index._missing_compression_parents.add(key)
691
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
692
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
693
694
    def test_missing_text_compression_parent_prevents_commit(self):
695
        repo = self.make_write_ready_repo()
696
        key = ('some', 'junk')
697
        repo.texts._index._missing_compression_parents.add(key)
698
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
699
        e = self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
700
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
701
    def test_supports_external_lookups(self):
702
        repo = self.make_repository('.', format=self.get_format())
703
        self.assertEqual(self.format_supports_external_lookups,
704
            repo._format.supports_external_lookups)
705
3825.4.1 by Andrew Bennetts
Add suppress_errors to abort_write_group.
706
    def test_abort_write_group_does_not_raise_when_suppressed(self):
707
        """Similar to per_repository.test_write_group's test of the same name.
708
709
        Also requires that the exception is logged.
710
        """
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
711
        self.vfs_transport_factory = memory.MemoryServer
4343.3.7 by John Arbash Meinel
Update the suspend/resume/commit/abort_write_group tests for CHK1.
712
        repo = self.make_repository('repo', format=self.get_format())
3825.4.1 by Andrew Bennetts
Add suppress_errors to abort_write_group.
713
        token = repo.lock_write()
714
        self.addCleanup(repo.unlock)
715
        repo.start_write_group()
716
        # Damage the repository on the filesystem
717
        self.get_transport('').rename('repo', 'foo')
718
        # abort_write_group will not raise an error
719
        self.assertEqual(None, repo.abort_write_group(suppress_errors=True))
720
        # But it does log an error
4794.1.15 by Robert Collins
Review feedback.
721
        log = self.get_log()
4794.1.8 by Robert Collins
Move the passing of test logs to the result to be via the getDetails API and remove all public use of TestCase._get_log.
722
        self.assertContainsRe(log, 'abort_write_group failed')
723
        self.assertContainsRe(log, r'INFO  bzr: ERROR \(ignored\):')
3825.4.1 by Andrew Bennetts
Add suppress_errors to abort_write_group.
724
        if token is not None:
725
            repo.leave_lock_in_place()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
726
3825.4.1 by Andrew Bennetts
Add suppress_errors to abort_write_group.
727
    def test_abort_write_group_does_raise_when_not_suppressed(self):
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
728
        self.vfs_transport_factory = memory.MemoryServer
4343.3.7 by John Arbash Meinel
Update the suspend/resume/commit/abort_write_group tests for CHK1.
729
        repo = self.make_repository('repo', format=self.get_format())
3825.4.1 by Andrew Bennetts
Add suppress_errors to abort_write_group.
730
        token = repo.lock_write()
731
        self.addCleanup(repo.unlock)
732
        repo.start_write_group()
733
        # Damage the repository on the filesystem
734
        self.get_transport('').rename('repo', 'foo')
735
        # abort_write_group will not raise an error
736
        self.assertRaises(Exception, repo.abort_write_group)
737
        if token is not None:
738
            repo.leave_lock_in_place()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
739
4002.1.1 by Andrew Bennetts
Implement suspend_write_group/resume_write_group.
740
    def test_suspend_write_group(self):
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
741
        self.vfs_transport_factory = memory.MemoryServer
4343.3.7 by John Arbash Meinel
Update the suspend/resume/commit/abort_write_group tests for CHK1.
742
        repo = self.make_repository('repo', format=self.get_format())
4002.1.1 by Andrew Bennetts
Implement suspend_write_group/resume_write_group.
743
        token = repo.lock_write()
744
        self.addCleanup(repo.unlock)
745
        repo.start_write_group()
746
        repo.texts.add_lines(('file-id', 'revid'), (), ['lines'])
747
        wg_tokens = repo.suspend_write_group()
748
        expected_pack_name = wg_tokens[0] + '.pack'
4343.3.7 by John Arbash Meinel
Update the suspend/resume/commit/abort_write_group tests for CHK1.
749
        expected_names = [wg_tokens[0] + ext for ext in
750
                            ('.rix', '.iix', '.tix', '.six')]
751
        if repo.chk_bytes is not None:
752
            expected_names.append(wg_tokens[0] + '.cix')
753
        expected_names.append(expected_pack_name)
4002.1.1 by Andrew Bennetts
Implement suspend_write_group/resume_write_group.
754
        upload_transport = repo._pack_collection._upload_transport
755
        limbo_files = upload_transport.list_dir('')
4343.3.7 by John Arbash Meinel
Update the suspend/resume/commit/abort_write_group tests for CHK1.
756
        self.assertEqual(sorted(expected_names), sorted(limbo_files))
4002.1.1 by Andrew Bennetts
Implement suspend_write_group/resume_write_group.
757
        md5 = osutils.md5(upload_transport.get_bytes(expected_pack_name))
758
        self.assertEqual(wg_tokens[0], md5.hexdigest())
759
4343.3.8 by John Arbash Meinel
Some cleanup passes.
760
    def test_resume_chk_bytes(self):
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
761
        self.vfs_transport_factory = memory.MemoryServer
4343.3.8 by John Arbash Meinel
Some cleanup passes.
762
        repo = self.make_repository('repo', format=self.get_format())
763
        if repo.chk_bytes is None:
764
            raise TestNotApplicable('no chk_bytes for this repository')
765
        token = repo.lock_write()
766
        self.addCleanup(repo.unlock)
767
        repo.start_write_group()
768
        text = 'a bit of text\n'
769
        key = ('sha1:' + osutils.sha_string(text),)
770
        repo.chk_bytes.add_lines(key, (), [text])
771
        wg_tokens = repo.suspend_write_group()
772
        same_repo = repo.bzrdir.open_repository()
773
        same_repo.lock_write()
774
        self.addCleanup(same_repo.unlock)
775
        same_repo.resume_write_group(wg_tokens)
776
        self.assertEqual([key], list(same_repo.chk_bytes.keys()))
777
        self.assertEqual(
778
            text, same_repo.chk_bytes.get_record_stream([key],
779
                'unordered', True).next().get_bytes_as('fulltext'))
780
        same_repo.abort_write_group()
781
        self.assertEqual([], list(same_repo.chk_bytes.keys()))
782
4002.1.1 by Andrew Bennetts
Implement suspend_write_group/resume_write_group.
783
    def test_resume_write_group_then_abort(self):
784
        # Create a repo, start a write group, insert some data, suspend.
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
785
        self.vfs_transport_factory = memory.MemoryServer
4343.3.7 by John Arbash Meinel
Update the suspend/resume/commit/abort_write_group tests for CHK1.
786
        repo = self.make_repository('repo', format=self.get_format())
4002.1.1 by Andrew Bennetts
Implement suspend_write_group/resume_write_group.
787
        token = repo.lock_write()
788
        self.addCleanup(repo.unlock)
789
        repo.start_write_group()
790
        text_key = ('file-id', 'revid')
791
        repo.texts.add_lines(text_key, (), ['lines'])
792
        wg_tokens = repo.suspend_write_group()
793
        # Get a fresh repository object for the repo on the filesystem.
794
        same_repo = repo.bzrdir.open_repository()
795
        # Resume
796
        same_repo.lock_write()
797
        self.addCleanup(same_repo.unlock)
798
        same_repo.resume_write_group(wg_tokens)
799
        same_repo.abort_write_group()
800
        self.assertEqual(
801
            [], same_repo._pack_collection._upload_transport.list_dir(''))
802
        self.assertEqual(
803
            [], same_repo._pack_collection._pack_transport.list_dir(''))
804
4343.3.7 by John Arbash Meinel
Update the suspend/resume/commit/abort_write_group tests for CHK1.
805
    def test_commit_resumed_write_group(self):
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
806
        self.vfs_transport_factory = memory.MemoryServer
4343.3.7 by John Arbash Meinel
Update the suspend/resume/commit/abort_write_group tests for CHK1.
807
        repo = self.make_repository('repo', format=self.get_format())
808
        token = repo.lock_write()
809
        self.addCleanup(repo.unlock)
810
        repo.start_write_group()
811
        text_key = ('file-id', 'revid')
812
        repo.texts.add_lines(text_key, (), ['lines'])
813
        wg_tokens = repo.suspend_write_group()
814
        # Get a fresh repository object for the repo on the filesystem.
815
        same_repo = repo.bzrdir.open_repository()
816
        # Resume
817
        same_repo.lock_write()
818
        self.addCleanup(same_repo.unlock)
819
        same_repo.resume_write_group(wg_tokens)
820
        same_repo.commit_write_group()
821
        expected_pack_name = wg_tokens[0] + '.pack'
822
        expected_names = [wg_tokens[0] + ext for ext in
823
                            ('.rix', '.iix', '.tix', '.six')]
824
        if repo.chk_bytes is not None:
825
            expected_names.append(wg_tokens[0] + '.cix')
826
        self.assertEqual(
827
            [], same_repo._pack_collection._upload_transport.list_dir(''))
828
        index_names = repo._pack_collection._index_transport.list_dir('')
829
        self.assertEqual(sorted(expected_names), sorted(index_names))
830
        pack_names = repo._pack_collection._pack_transport.list_dir('')
831
        self.assertEqual([expected_pack_name], pack_names)
832
4002.1.5 by Andrew Bennetts
Fix possible security issue with resuming write groups: make sure the token is well-formed so that it's not possible to steal a write group from another repo.
833
    def test_resume_malformed_token(self):
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
834
        self.vfs_transport_factory = memory.MemoryServer
4002.1.5 by Andrew Bennetts
Fix possible security issue with resuming write groups: make sure the token is well-formed so that it's not possible to steal a write group from another repo.
835
        # Make a repository with a suspended write group
4343.3.7 by John Arbash Meinel
Update the suspend/resume/commit/abort_write_group tests for CHK1.
836
        repo = self.make_repository('repo', format=self.get_format())
4002.1.5 by Andrew Bennetts
Fix possible security issue with resuming write groups: make sure the token is well-formed so that it's not possible to steal a write group from another repo.
837
        token = repo.lock_write()
838
        self.addCleanup(repo.unlock)
839
        repo.start_write_group()
840
        text_key = ('file-id', 'revid')
841
        repo.texts.add_lines(text_key, (), ['lines'])
842
        wg_tokens = repo.suspend_write_group()
843
        # Make a new repository
4343.3.7 by John Arbash Meinel
Update the suspend/resume/commit/abort_write_group tests for CHK1.
844
        new_repo = self.make_repository('new_repo', format=self.get_format())
4002.1.5 by Andrew Bennetts
Fix possible security issue with resuming write groups: make sure the token is well-formed so that it's not possible to steal a write group from another repo.
845
        token = new_repo.lock_write()
846
        self.addCleanup(new_repo.unlock)
847
        hacked_wg_token = (
848
            '../../../../repo/.bzr/repository/upload/' + wg_tokens[0])
849
        self.assertRaises(
4002.1.7 by Andrew Bennetts
Rename UnresumableWriteGroups to UnresumableWriteGroup.
850
            errors.UnresumableWriteGroup,
4002.1.5 by Andrew Bennetts
Fix possible security issue with resuming write groups: make sure the token is well-formed so that it's not possible to steal a write group from another repo.
851
            new_repo.resume_write_group, [hacked_wg_token])
852
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
853
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
854
class TestPackRepositoryStacking(TestCaseWithTransport):
855
856
    """Tests for stacking pack repositories"""
857
858
    def setUp(self):
859
        if not self.format_supports_external_lookups:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
860
            raise TestNotApplicable("%r doesn't support stacking"
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
861
                % (self.format_name,))
862
        super(TestPackRepositoryStacking, self).setUp()
863
864
    def get_format(self):
865
        return bzrdir.format_registry.make_bzrdir(self.format_name)
866
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
867
    def test_stack_checks_rich_root_compatibility(self):
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
868
        # early versions of the packing code relied on pack internals to
869
        # stack, but the current version should be able to stack on any
870
        # format.
871
        #
872
        # TODO: Possibly this should be run per-repository-format and raise
873
        # TestNotApplicable on formats that don't support stacking. -- mbp
874
        # 20080729
875
        repo = self.make_repository('repo', format=self.get_format())
876
        if repo.supports_rich_root():
877
            # can only stack on repositories that have compatible internal
878
            # metadata
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
879
            if getattr(repo._format, 'supports_tree_reference', False):
4343.3.27 by John Arbash Meinel
Now that dev6 supports external references, the tests for
880
                matching_format_name = 'pack-0.92-subtree'
881
            else:
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
882
                if repo._format.supports_chks:
4597.1.6 by John Arbash Meinel
Add a test that inventory texts are preserved during pack.
883
                    matching_format_name = '2a'
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
884
                else:
4343.3.27 by John Arbash Meinel
Now that dev6 supports external references, the tests for
885
                    matching_format_name = 'rich-root-pack'
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
886
            mismatching_format_name = 'pack-0.92'
887
        else:
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
888
            # We don't have a non-rich-root CHK format.
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
889
            if repo._format.supports_chks:
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
890
                raise AssertionError("no non-rich-root CHK formats known")
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
891
            else:
892
                matching_format_name = 'pack-0.92'
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
893
            mismatching_format_name = 'pack-0.92-subtree'
894
        base = self.make_repository('base', format=matching_format_name)
895
        repo.add_fallback_repository(base)
896
        # you can't stack on something with incompatible data
897
        bad_repo = self.make_repository('mismatch',
898
            format=mismatching_format_name)
899
        e = self.assertRaises(errors.IncompatibleRepositories,
900
            repo.add_fallback_repository, bad_repo)
901
        self.assertContainsRe(str(e),
902
            r'(?m)KnitPackRepository.*/mismatch/.*\nis not compatible with\n'
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
903
            r'.*Repository.*/repo/.*\n'
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
904
            r'different rich-root support')
905
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
906
    def test_stack_checks_serializers_compatibility(self):
907
        repo = self.make_repository('repo', format=self.get_format())
908
        if getattr(repo._format, 'supports_tree_reference', False):
909
            # can only stack on repositories that have compatible internal
910
            # metadata
4343.3.27 by John Arbash Meinel
Now that dev6 supports external references, the tests for
911
            matching_format_name = 'pack-0.92-subtree'
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
912
            mismatching_format_name = 'rich-root-pack'
913
        else:
914
            if repo.supports_rich_root():
4343.3.27 by John Arbash Meinel
Now that dev6 supports external references, the tests for
915
                if repo._format.supports_chks:
4597.1.6 by John Arbash Meinel
Add a test that inventory texts are preserved during pack.
916
                    matching_format_name = '2a'
4343.3.27 by John Arbash Meinel
Now that dev6 supports external references, the tests for
917
                else:
918
                    matching_format_name = 'rich-root-pack'
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
919
                mismatching_format_name = 'pack-0.92-subtree'
920
            else:
921
                raise TestNotApplicable('No formats use non-v5 serializer'
922
                    ' without having rich-root also set')
923
        base = self.make_repository('base', format=matching_format_name)
924
        repo.add_fallback_repository(base)
925
        # you can't stack on something with incompatible data
926
        bad_repo = self.make_repository('mismatch',
927
            format=mismatching_format_name)
928
        e = self.assertRaises(errors.IncompatibleRepositories,
929
            repo.add_fallback_repository, bad_repo)
930
        self.assertContainsRe(str(e),
931
            r'(?m)KnitPackRepository.*/mismatch/.*\nis not compatible with\n'
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
932
            r'.*Repository.*/repo/.*\n'
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
933
            r'different serializers')
934
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
935
    def test_adding_pack_does_not_record_pack_names_from_other_repositories(self):
936
        base = self.make_branch_and_tree('base', format=self.get_format())
937
        base.commit('foo')
938
        referencing = self.make_branch_and_tree('repo', format=self.get_format())
939
        referencing.branch.repository.add_fallback_repository(base.branch.repository)
4595.4.4 by Robert Collins
Disable committing directly to stacked branches from lightweight checkouts.
940
        local_tree = referencing.branch.create_checkout('local')
941
        local_tree.commit('bar')
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
942
        new_instance = referencing.bzrdir.open_repository()
943
        new_instance.lock_read()
944
        self.addCleanup(new_instance.unlock)
945
        new_instance._pack_collection.ensure_loaded()
946
        self.assertEqual(1, len(new_instance._pack_collection.all_packs()))
947
948
    def test_autopack_only_considers_main_repo_packs(self):
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
949
        format = self.get_format()
950
        base = self.make_branch_and_tree('base', format=format)
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
951
        base.commit('foo')
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
952
        tree = self.make_branch_and_tree('repo', format=format)
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
953
        tree.branch.repository.add_fallback_repository(base.branch.repository)
954
        trans = tree.branch.repository.bzrdir.get_repository_transport(None)
955
        # This test could be a little cheaper by replacing the packs
956
        # attribute on the repository to allow a different pack distribution
957
        # and max packs policy - so we are checking the policy is honoured
958
        # in the test. But for now 11 commits is not a big deal in a single
959
        # test.
4595.4.4 by Robert Collins
Disable committing directly to stacked branches from lightweight checkouts.
960
        local_tree = tree.branch.create_checkout('local')
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
961
        for x in range(9):
4595.4.4 by Robert Collins
Disable committing directly to stacked branches from lightweight checkouts.
962
            local_tree.commit('commit %s' % x)
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
963
        # there should be 9 packs:
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
964
        index = self.index_class(trans, 'pack-names', None)
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
965
        self.assertEqual(9, len(list(index.iter_all_entries())))
966
        # committing one more should coalesce to 1 of 10.
4595.4.4 by Robert Collins
Disable committing directly to stacked branches from lightweight checkouts.
967
        local_tree.commit('commit triggering pack')
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
968
        index = self.index_class(trans, 'pack-names', None)
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
969
        self.assertEqual(1, len(list(index.iter_all_entries())))
970
        # packing should not damage data
971
        tree = tree.bzrdir.open_workingtree()
972
        check_result = tree.branch.repository.check(
973
            [tree.branch.last_revision()])
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
974
        nb_files = 5 # .pack, .rix, .iix, .tix, .six
975
        if tree.branch.repository._format.supports_chks:
976
            nb_files += 1 # .cix
977
        # We should have 10 x nb_files files in the obsolete_packs directory.
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
978
        obsolete_files = list(trans.list_dir('obsolete_packs'))
979
        self.assertFalse('foo' in obsolete_files)
980
        self.assertFalse('bar' in obsolete_files)
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
981
        self.assertEqual(10 * nb_files, len(obsolete_files))
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
982
        # XXX: Todo check packs obsoleted correctly - old packs and indices
983
        # in the obsolete_packs directory.
984
        large_pack_name = list(index.iter_all_entries())[0][1][0]
985
        # finally, committing again should not touch the large pack.
4595.4.4 by Robert Collins
Disable committing directly to stacked branches from lightweight checkouts.
986
        local_tree.commit('commit not triggering pack')
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
987
        index = self.index_class(trans, 'pack-names', None)
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
988
        self.assertEqual(2, len(list(index.iter_all_entries())))
989
        pack_names = [node[1][0] for node in index.iter_all_entries()]
990
        self.assertTrue(large_pack_name in pack_names)
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
991
992
4343.3.33 by John Arbash Meinel
Clear KeyDependencies on abort/suspend/commit_write_group.
993
class TestKeyDependencies(TestCaseWithTransport):
994
995
    def get_format(self):
996
        return bzrdir.format_registry.make_bzrdir(self.format_name)
997
998
    def create_source_and_target(self):
999
        builder = self.make_branch_builder('source', format=self.get_format())
1000
        builder.start_series()
1001
        builder.build_snapshot('A-id', None, [
1002
            ('add', ('', 'root-id', 'directory', None))])
1003
        builder.build_snapshot('B-id', ['A-id', 'ghost-id'], [])
1004
        builder.finish_series()
4634.29.16 by Andrew Bennetts
Fix buggy TestKeyDependencies test, tweak error string and comment.
1005
        repo = self.make_repository('target', format=self.get_format())
4343.3.33 by John Arbash Meinel
Clear KeyDependencies on abort/suspend/commit_write_group.
1006
        b = builder.get_branch()
1007
        b.lock_read()
1008
        self.addCleanup(b.unlock)
1009
        repo.lock_write()
1010
        self.addCleanup(repo.unlock)
1011
        return b.repository, repo
1012
1013
    def test_key_dependencies_cleared_on_abort(self):
1014
        source_repo, target_repo = self.create_source_and_target()
1015
        target_repo.start_write_group()
1016
        try:
1017
            stream = source_repo.revisions.get_record_stream([('B-id',)],
1018
                                                             'unordered', True)
1019
            target_repo.revisions.insert_record_stream(stream)
1020
            key_refs = target_repo.revisions._index._key_dependencies
1021
            self.assertEqual([('B-id',)], sorted(key_refs.get_referrers()))
1022
        finally:
1023
            target_repo.abort_write_group()
1024
        self.assertEqual([], sorted(key_refs.get_referrers()))
1025
1026
    def test_key_dependencies_cleared_on_suspend(self):
1027
        source_repo, target_repo = self.create_source_and_target()
1028
        target_repo.start_write_group()
1029
        try:
1030
            stream = source_repo.revisions.get_record_stream([('B-id',)],
1031
                                                             'unordered', True)
1032
            target_repo.revisions.insert_record_stream(stream)
1033
            key_refs = target_repo.revisions._index._key_dependencies
1034
            self.assertEqual([('B-id',)], sorted(key_refs.get_referrers()))
1035
        finally:
1036
            target_repo.suspend_write_group()
1037
        self.assertEqual([], sorted(key_refs.get_referrers()))
1038
1039
    def test_key_dependencies_cleared_on_commit(self):
1040
        source_repo, target_repo = self.create_source_and_target()
1041
        target_repo.start_write_group()
1042
        try:
4634.29.16 by Andrew Bennetts
Fix buggy TestKeyDependencies test, tweak error string and comment.
1043
            # Copy all texts, inventories, and chks so that nothing is missing
1044
            # for revision B-id.
1045
            for vf_name in ['texts', 'chk_bytes', 'inventories']:
1046
                source_vf = getattr(source_repo, vf_name, None)
1047
                if source_vf is None:
1048
                    continue
1049
                target_vf = getattr(target_repo, vf_name)
1050
                stream = source_vf.get_record_stream(
1051
                    source_vf.keys(), 'unordered', True)
1052
                target_vf.insert_record_stream(stream)
1053
            # Copy just revision B-id
1054
            stream = source_repo.revisions.get_record_stream(
1055
                [('B-id',)], 'unordered', True)
4343.3.33 by John Arbash Meinel
Clear KeyDependencies on abort/suspend/commit_write_group.
1056
            target_repo.revisions.insert_record_stream(stream)
1057
            key_refs = target_repo.revisions._index._key_dependencies
1058
            self.assertEqual([('B-id',)], sorted(key_refs.get_referrers()))
1059
        finally:
1060
            target_repo.commit_write_group()
1061
        self.assertEqual([], sorted(key_refs.get_referrers()))
1062
1063
3801.1.18 by Andrew Bennetts
Add a test that ensures that the autopack RPC is actually used for all pack formats.
1064
class TestSmartServerAutopack(TestCaseWithTransport):
1065
1066
    def setUp(self):
1067
        super(TestSmartServerAutopack, self).setUp()
1068
        # Create a smart server that publishes whatever the backing VFS server
1069
        # does.
5017.3.44 by Vincent Ladeuil
-s bt.per_pack_repos passing
1070
        self.smart_server = test_server.SmartTCPServer_for_testing()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
1071
        self.start_server(self.smart_server, self.get_server())
3801.1.18 by Andrew Bennetts
Add a test that ensures that the autopack RPC is actually used for all pack formats.
1072
        # Log all HPSS calls into self.hpss_calls.
1073
        client._SmartClient.hooks.install_named_hook(
1074
            'call', self.capture_hpss_call, None)
1075
        self.hpss_calls = []
1076
1077
    def capture_hpss_call(self, params):
1078
        self.hpss_calls.append(params.method)
1079
1080
    def get_format(self):
1081
        return bzrdir.format_registry.make_bzrdir(self.format_name)
1082
4029.2.1 by Robert Collins
Support streaming push to stacked branches.
1083
    def test_autopack_or_streaming_rpc_is_used_when_using_hpss(self):
3801.1.18 by Andrew Bennetts
Add a test that ensures that the autopack RPC is actually used for all pack formats.
1084
        # Make local and remote repos
3735.2.98 by John Arbash Meinel
Merge bzr.dev 4032. Resolve the new streaming fetch.
1085
        format = self.get_format()
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
1086
        tree = self.make_branch_and_tree('local', format=format)
1087
        self.make_branch_and_tree('remote', format=format)
3801.1.18 by Andrew Bennetts
Add a test that ensures that the autopack RPC is actually used for all pack formats.
1088
        remote_branch_url = self.smart_server.get_url() + 'remote'
1089
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
1090
        # Make 9 local revisions, and push them one at a time to the remote
1091
        # repo to produce 9 pack files.
1092
        for x in range(9):
1093
            tree.commit('commit %s' % x)
1094
            tree.branch.push(remote_branch)
1095
        # Make one more push to trigger an autopack
1096
        self.hpss_calls = []
1097
        tree.commit('commit triggering pack')
1098
        tree.branch.push(remote_branch)
4029.2.1 by Robert Collins
Support streaming push to stacked branches.
1099
        autopack_calls = len([call for call in self.hpss_calls if call ==
1100
            'PackRepository.autopack'])
4476.3.66 by Andrew Bennetts
Fix trivial test failure by making the test recognise the new insert_stream_1.18 verb.
1101
        streaming_calls = len([call for call in self.hpss_calls if call in
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
1102
            ('Repository.insert_stream', 'Repository.insert_stream_1.19')])
4029.2.1 by Robert Collins
Support streaming push to stacked branches.
1103
        if autopack_calls:
1104
            # Non streaming server
1105
            self.assertEqual(1, autopack_calls)
1106
            self.assertEqual(0, streaming_calls)
1107
        else:
1108
            # Streaming was used, which autopacks on the remote end.
1109
            self.assertEqual(0, autopack_calls)
1110
            # NB: The 2 calls are because of the sanity check that the server
1111
            # supports the verb (see remote.py:RemoteSink.insert_stream for
1112
            # details).
1113
            self.assertEqual(2, streaming_calls)
3801.1.18 by Andrew Bennetts
Add a test that ensures that the autopack RPC is actually used for all pack formats.
1114
1115
4084.5.1 by Robert Collins
Bulk update all test adaptation into a single approach, using multiply_tests rather than test adapters.
1116
def load_tests(basic_tests, module, loader):
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
1117
    # these give the bzrdir canned format name, and the repository on-disk
1118
    # format string
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
1119
    scenarios_params = [
1120
         dict(format_name='pack-0.92',
1121
              format_string="Bazaar pack repository format 1 (needs bzr 0.92)\n",
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
1122
              format_supports_external_lookups=False,
1123
              index_class=GraphIndex),
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
1124
         dict(format_name='pack-0.92-subtree',
1125
              format_string="Bazaar pack repository format 1 "
1126
              "with subtree support (needs bzr 0.92)\n",
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
1127
              format_supports_external_lookups=False,
1128
              index_class=GraphIndex),
3582.3.2 by Martin Pool
Add 1.6 formats to pack repository tests
1129
         dict(format_name='1.6',
1130
              format_string="Bazaar RepositoryFormatKnitPack5 (bzr 1.6)\n",
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
1131
              format_supports_external_lookups=True,
1132
              index_class=GraphIndex),
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
1133
         dict(format_name='1.6.1-rich-root',
3582.3.2 by Martin Pool
Add 1.6 formats to pack repository tests
1134
              format_string="Bazaar RepositoryFormatKnitPack5RichRoot "
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
1135
                  "(bzr 1.6.1)\n",
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
1136
              format_supports_external_lookups=True,
1137
              index_class=GraphIndex),
3805.3.1 by John Arbash Meinel
Add repository 1.9 format, and update the documentation.
1138
         dict(format_name='1.9',
1139
              format_string="Bazaar RepositoryFormatKnitPack6 (bzr 1.9)\n",
1140
              format_supports_external_lookups=True,
1141
              index_class=BTreeGraphIndex),
1142
         dict(format_name='1.9-rich-root',
1143
              format_string="Bazaar RepositoryFormatKnitPack6RichRoot "
1144
                  "(bzr 1.9)\n",
1145
              format_supports_external_lookups=True,
1146
              index_class=BTreeGraphIndex),
4597.1.6 by John Arbash Meinel
Add a test that inventory texts are preserved during pack.
1147
         dict(format_name='2a',
1148
              format_string="Bazaar repository format 2a "
1149
                "(needs bzr 1.16 or later)\n",
4343.3.8 by John Arbash Meinel
Some cleanup passes.
1150
              format_supports_external_lookups=True,
3735.2.40 by Robert Collins
Add development4 which has a parent_id to basename index on CHKInventory objects.
1151
              index_class=BTreeGraphIndex),
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
1152
         ]
1153
    # name of the scenario is the format name
4084.5.1 by Robert Collins
Bulk update all test adaptation into a single approach, using multiply_tests rather than test adapters.
1154
    scenarios = [(s['format_name'], s) for s in scenarios_params]
1155
    return tests.multiply_tests(basic_tests, scenarios, loader.suiteClass())