/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
1
# Copyright (C) 2008 Canonical Ltd
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
    )
3801.1.18 by Andrew Bennetts
Add a test that ensures that the autopack RPC is actually used for all pack formats.
41
from bzrlib.smart import (
42
    client,
43
    server,
44
    )
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
45
from bzrlib.tests import (
46
    TestCase,
47
    TestCaseWithTransport,
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
48
    TestNotApplicable,
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
49
    TestSkipped,
50
    )
51
from bzrlib.transport import (
52
    fakenfs,
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.
53
    memory,
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
54
    get_transport,
55
    )
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.
56
from bzrlib.tests.per_repository import TestCaseWithRepository
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
57
58
59
class TestPackRepository(TestCaseWithTransport):
60
    """Tests to be repeated across all pack-based formats.
61
62
    The following are populated from the test scenario:
63
64
    :ivar format_name: Registered name fo the format to test.
65
    :ivar format_string: On-disk format marker.
66
    :ivar format_supports_external_lookups: Boolean.
67
    """
68
69
    def get_format(self):
70
        return bzrdir.format_registry.make_bzrdir(self.format_name)
71
72
    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.
73
        """Packs do not need ordered data retrieval."""
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
74
        format = self.get_format()
75
        repo = self.make_repository('.', format=format)
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
76
        self.assertEqual('unordered', repo._format._fetch_order)
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
77
78
    def test_attribute__fetch_uses_deltas(self):
79
        """Packs reuse deltas."""
80
        format = self.get_format()
81
        repo = self.make_repository('.', format=format)
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
82
        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
83
84
    def test_disk_layout(self):
85
        format = self.get_format()
86
        repo = self.make_repository('.', format=format)
87
        # in case of side effects of locking.
88
        repo.lock_write()
89
        repo.unlock()
90
        t = repo.bzrdir.get_repository_transport(None)
91
        self.check_format(t)
92
        # XXX: no locks left when unlocked at the moment
93
        # self.assertEqualDiff('', t.get('lock').read())
94
        self.check_databases(t)
95
96
    def check_format(self, t):
97
        self.assertEqualDiff(
98
            self.format_string, # from scenario
99
            t.get('format').read())
100
101
    def assertHasNoKndx(self, t, knit_name):
102
        """Assert that knit_name has no index on t."""
103
        self.assertFalse(t.has(knit_name + '.kndx'))
104
105
    def assertHasNoKnit(self, t, knit_name):
106
        """Assert that knit_name exists on t."""
107
        # no default content
108
        self.assertFalse(t.has(knit_name + '.knit'))
109
110
    def check_databases(self, t):
111
        """check knit content for a repository."""
112
        # check conversion worked
113
        self.assertHasNoKndx(t, 'inventory')
114
        self.assertHasNoKnit(t, 'inventory')
115
        self.assertHasNoKndx(t, 'revisions')
116
        self.assertHasNoKnit(t, 'revisions')
117
        self.assertHasNoKndx(t, 'signatures')
118
        self.assertHasNoKnit(t, 'signatures')
119
        self.assertFalse(t.has('knits'))
120
        # revision-indexes file-container directory
121
        self.assertEqual([],
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
122
            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
123
        self.assertTrue(S_ISDIR(t.stat('packs').st_mode))
124
        self.assertTrue(S_ISDIR(t.stat('upload').st_mode))
125
        self.assertTrue(S_ISDIR(t.stat('indices').st_mode))
126
        self.assertTrue(S_ISDIR(t.stat('obsolete_packs').st_mode))
127
128
    def test_shared_disk_layout(self):
129
        format = self.get_format()
130
        repo = self.make_repository('.', shared=True, format=format)
131
        # we want:
132
        t = repo.bzrdir.get_repository_transport(None)
133
        self.check_format(t)
134
        # XXX: no locks left when unlocked at the moment
135
        # self.assertEqualDiff('', t.get('lock').read())
136
        # We should have a 'shared-storage' marker file.
137
        self.assertEqualDiff('', t.get('shared-storage').read())
138
        self.check_databases(t)
139
140
    def test_shared_no_tree_disk_layout(self):
141
        format = self.get_format()
142
        repo = self.make_repository('.', shared=True, format=format)
143
        repo.set_make_working_trees(False)
144
        # we want:
145
        t = repo.bzrdir.get_repository_transport(None)
146
        self.check_format(t)
147
        # XXX: no locks left when unlocked at the moment
148
        # self.assertEqualDiff('', t.get('lock').read())
149
        # We should have a 'shared-storage' marker file.
150
        self.assertEqualDiff('', t.get('shared-storage').read())
151
        # We should have a marker for the no-working-trees flag.
152
        self.assertEqualDiff('', t.get('no-working-trees').read())
153
        # The marker should go when we toggle the setting.
154
        repo.set_make_working_trees(True)
155
        self.assertFalse(t.has('no-working-trees'))
156
        self.check_databases(t)
157
158
    def test_adding_revision_creates_pack_indices(self):
159
        format = self.get_format()
160
        tree = self.make_branch_and_tree('.', format=format)
161
        trans = tree.branch.repository.bzrdir.get_repository_transport(None)
162
        self.assertEqual([],
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
163
            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
164
        tree.commit('foobarbaz')
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
165
        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
166
        index_nodes = list(index.iter_all_entries())
167
        self.assertEqual(1, len(index_nodes))
168
        node = index_nodes[0]
169
        name = node[1][0]
170
        # the pack sizes should be listed in the index
171
        pack_value = node[2]
172
        sizes = [int(digits) for digits in pack_value.split(' ')]
173
        for size, suffix in zip(sizes, ['.rix', '.iix', '.tix', '.six']):
174
            stat = trans.stat('indices/%s%s' % (name, suffix))
175
            self.assertEqual(size, stat.st_size)
176
177
    def test_pulling_nothing_leads_to_no_new_names(self):
178
        format = self.get_format()
179
        tree1 = self.make_branch_and_tree('1', format=format)
180
        tree2 = self.make_branch_and_tree('2', format=format)
181
        tree1.branch.repository.fetch(tree2.branch.repository)
182
        trans = tree1.branch.repository.bzrdir.get_repository_transport(None)
183
        self.assertEqual([],
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
184
            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
185
186
    def test_commit_across_pack_shape_boundary_autopacks(self):
187
        format = self.get_format()
188
        tree = self.make_branch_and_tree('.', format=format)
189
        trans = tree.branch.repository.bzrdir.get_repository_transport(None)
190
        # This test could be a little cheaper by replacing the packs
191
        # attribute on the repository to allow a different pack distribution
192
        # and max packs policy - so we are checking the policy is honoured
193
        # in the test. But for now 11 commits is not a big deal in a single
194
        # test.
195
        for x in range(9):
196
            tree.commit('commit %s' % x)
197
        # there should be 9 packs:
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
198
        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
199
        self.assertEqual(9, len(list(index.iter_all_entries())))
200
        # insert some files in obsolete_packs which should be removed by pack.
201
        trans.put_bytes('obsolete_packs/foo', '123')
202
        trans.put_bytes('obsolete_packs/bar', '321')
203
        # committing one more should coalesce to 1 of 10.
204
        tree.commit('commit triggering pack')
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
205
        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
206
        self.assertEqual(1, len(list(index.iter_all_entries())))
207
        # packing should not damage data
208
        tree = tree.bzrdir.open_workingtree()
209
        check_result = tree.branch.repository.check(
210
            [tree.branch.last_revision()])
3735.2.81 by Vincent Ladeuil
Fix test failing on files present in obsolete_packs directory.
211
        nb_files = 5 # .pack, .rix, .iix, .tix, .six
212
        if tree.branch.repository._format.supports_chks:
213
            nb_files += 1 # .cix
214
        # 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
215
        obsolete_files = list(trans.list_dir('obsolete_packs'))
216
        self.assertFalse('foo' in obsolete_files)
217
        self.assertFalse('bar' in obsolete_files)
3735.2.81 by Vincent Ladeuil
Fix test failing on files present in obsolete_packs directory.
218
        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
219
        # XXX: Todo check packs obsoleted correctly - old packs and indices
220
        # in the obsolete_packs directory.
221
        large_pack_name = list(index.iter_all_entries())[0][1][0]
222
        # finally, committing again should not touch the large pack.
223
        tree.commit('commit not triggering pack')
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
224
        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
225
        self.assertEqual(2, len(list(index.iter_all_entries())))
226
        pack_names = [node[1][0] for node in index.iter_all_entries()]
227
        self.assertTrue(large_pack_name in pack_names)
228
229
    def test_fail_obsolete_deletion(self):
230
        # failing to delete obsolete packs is not fatal
231
        format = self.get_format()
232
        server = fakenfs.FakeNFSServer()
233
        server.setUp()
234
        self.addCleanup(server.tearDown)
235
        transport = get_transport(server.get_url())
236
        bzrdir = self.get_format().initialize_on_transport(transport)
237
        repo = bzrdir.create_repository()
238
        repo_transport = bzrdir.get_repository_transport(None)
239
        self.assertTrue(repo_transport.has('obsolete_packs'))
240
        # these files are in use by another client and typically can't be deleted
241
        repo_transport.put_bytes('obsolete_packs/.nfsblahblah', 'contents')
242
        repo._pack_collection._clear_obsolete_packs()
243
        self.assertTrue(repo_transport.has('obsolete_packs/.nfsblahblah'))
244
245
    def test_pack_after_two_commits_packs_everything(self):
246
        format = self.get_format()
247
        tree = self.make_branch_and_tree('.', format=format)
248
        trans = tree.branch.repository.bzrdir.get_repository_transport(None)
249
        tree.commit('start')
250
        tree.commit('more work')
251
        tree.branch.repository.pack()
252
        # there should be 1 pack:
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
253
        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
254
        self.assertEqual(1, len(list(index.iter_all_entries())))
255
        self.assertEqual(2, len(tree.branch.repository.all_revision_ids()))
256
257
    def test_pack_layout(self):
258
        format = self.get_format()
259
        tree = self.make_branch_and_tree('.', format=format)
260
        trans = tree.branch.repository.bzrdir.get_repository_transport(None)
261
        tree.commit('start', rev_id='1')
262
        tree.commit('more work', rev_id='2')
263
        tree.branch.repository.pack()
264
        tree.lock_read()
265
        self.addCleanup(tree.unlock)
266
        pack = tree.branch.repository._pack_collection.get_pack_by_name(
267
            tree.branch.repository._pack_collection.names()[0])
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
268
        # 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
269
        # disk is a good idea.
270
        for _1, key, val, refs in pack.revision_index.iter_all_entries():
271
            if key == ('1',):
272
                pos_1 = int(val[1:].split()[0])
273
            else:
274
                pos_2 = int(val[1:].split()[0])
275
        self.assertTrue(pos_2 < pos_1)
276
277
    def test_pack_repositories_support_multiple_write_locks(self):
278
        format = self.get_format()
279
        self.make_repository('.', shared=True, format=format)
280
        r1 = repository.Repository.open('.')
281
        r2 = repository.Repository.open('.')
282
        r1.lock_write()
283
        self.addCleanup(r1.unlock)
284
        r2.lock_write()
285
        r2.unlock()
286
287
    def _add_text(self, repo, fileid):
288
        """Add a text to the repository within a write group."""
289
        repo.texts.add_lines((fileid, 'samplerev+'+fileid), [], [])
290
291
    def test_concurrent_writers_merge_new_packs(self):
292
        format = self.get_format()
293
        self.make_repository('.', shared=True, format=format)
294
        r1 = repository.Repository.open('.')
295
        r2 = repository.Repository.open('.')
296
        r1.lock_write()
297
        try:
298
            # access enough data to load the names list
299
            list(r1.all_revision_ids())
300
            r2.lock_write()
301
            try:
302
                # access enough data to load the names list
303
                list(r2.all_revision_ids())
304
                r1.start_write_group()
305
                try:
306
                    r2.start_write_group()
307
                    try:
308
                        self._add_text(r1, 'fileidr1')
309
                        self._add_text(r2, 'fileidr2')
310
                    except:
311
                        r2.abort_write_group()
312
                        raise
313
                except:
314
                    r1.abort_write_group()
315
                    raise
316
                # both r1 and r2 have open write groups with data in them
317
                # created while the other's write group was open.
318
                # Commit both which requires a merge to the pack-names.
319
                try:
320
                    r1.commit_write_group()
321
                except:
322
                    r1.abort_write_group()
323
                    r2.abort_write_group()
324
                    raise
325
                r2.commit_write_group()
326
                # tell r1 to reload from disk
327
                r1._pack_collection.reset()
328
                # Now both repositories should know about both names
329
                r1._pack_collection.ensure_loaded()
330
                r2._pack_collection.ensure_loaded()
331
                self.assertEqual(r1._pack_collection.names(), r2._pack_collection.names())
332
                self.assertEqual(2, len(r1._pack_collection.names()))
333
            finally:
334
                r2.unlock()
335
        finally:
336
            r1.unlock()
337
338
    def test_concurrent_writer_second_preserves_dropping_a_pack(self):
339
        format = self.get_format()
340
        self.make_repository('.', shared=True, format=format)
341
        r1 = repository.Repository.open('.')
342
        r2 = repository.Repository.open('.')
343
        # add a pack to drop
344
        r1.lock_write()
345
        try:
346
            r1.start_write_group()
347
            try:
348
                self._add_text(r1, 'fileidr1')
349
            except:
350
                r1.abort_write_group()
351
                raise
352
            else:
353
                r1.commit_write_group()
354
            r1._pack_collection.ensure_loaded()
355
            name_to_drop = r1._pack_collection.all_packs()[0].name
356
        finally:
357
            r1.unlock()
358
        r1.lock_write()
359
        try:
360
            # access enough data to load the names list
361
            list(r1.all_revision_ids())
362
            r2.lock_write()
363
            try:
364
                # access enough data to load the names list
365
                list(r2.all_revision_ids())
366
                r1._pack_collection.ensure_loaded()
367
                try:
368
                    r2.start_write_group()
369
                    try:
370
                        # in r1, drop the pack
371
                        r1._pack_collection._remove_pack_from_memory(
372
                            r1._pack_collection.get_pack_by_name(name_to_drop))
373
                        # in r2, add a pack
374
                        self._add_text(r2, 'fileidr2')
375
                    except:
376
                        r2.abort_write_group()
377
                        raise
378
                except:
379
                    r1._pack_collection.reset()
380
                    raise
381
                # r1 has a changed names list, and r2 an open write groups with
382
                # changes.
383
                # save r1, and then commit the r2 write group, which requires a
384
                # merge to the pack-names, which should not reinstate
385
                # name_to_drop
386
                try:
387
                    r1._pack_collection._save_pack_names()
388
                    r1._pack_collection.reset()
389
                except:
390
                    r2.abort_write_group()
391
                    raise
392
                try:
393
                    r2.commit_write_group()
394
                except:
395
                    r2.abort_write_group()
396
                    raise
397
                # Now both repositories should now about just one name.
398
                r1._pack_collection.ensure_loaded()
399
                r2._pack_collection.ensure_loaded()
400
                self.assertEqual(r1._pack_collection.names(), r2._pack_collection.names())
401
                self.assertEqual(1, len(r1._pack_collection.names()))
402
                self.assertFalse(name_to_drop in r1._pack_collection.names())
403
            finally:
404
                r2.unlock()
405
        finally:
406
            r1.unlock()
407
3789.1.1 by John Arbash Meinel
add the failing acceptance test for the first portion.
408
    def test_concurrent_pack_triggers_reload(self):
409
        # create 2 packs, which we will then collapse
410
        tree = self.make_branch_and_tree('tree')
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
411
        tree.lock_write()
3789.1.1 by John Arbash Meinel
add the failing acceptance test for the first portion.
412
        try:
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
413
            rev1 = tree.commit('one')
414
            rev2 = tree.commit('two')
415
            r2 = repository.Repository.open('tree')
3789.1.1 by John Arbash Meinel
add the failing acceptance test for the first portion.
416
            r2.lock_read()
417
            try:
418
                # Now r2 has read the pack-names file, but will need to reload
419
                # it after r1 has repacked
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
420
                tree.branch.repository.pack()
421
                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.
422
            finally:
423
                r2.unlock()
424
        finally:
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
425
            tree.unlock()
3789.1.1 by John Arbash Meinel
add the failing acceptance test for the first portion.
426
3789.2.8 by John Arbash Meinel
Add a test that KnitPackRepository.get_record_stream retries when appropriate.
427
    def test_concurrent_pack_during_get_record_reloads(self):
428
        tree = self.make_branch_and_tree('tree')
429
        tree.lock_write()
430
        try:
431
            rev1 = tree.commit('one')
432
            rev2 = tree.commit('two')
3789.2.14 by John Arbash Meinel
Update AggregateIndex to pass the reload_func into _DirectPackAccess
433
            keys = [(rev1,), (rev2,)]
3789.2.8 by John Arbash Meinel
Add a test that KnitPackRepository.get_record_stream retries when appropriate.
434
            r2 = repository.Repository.open('tree')
435
            r2.lock_read()
436
            try:
437
                # At this point, we will start grabbing a record stream, and
438
                # trigger a repack mid-way
439
                packed = False
440
                result = {}
441
                record_stream = r2.revisions.get_record_stream(keys,
442
                                    'unordered', False)
443
                for record in record_stream:
444
                    result[record.key] = record
445
                    if not packed:
446
                        tree.branch.repository.pack()
447
                        packed = True
448
                # The first record will be found in the original location, but
449
                # 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
450
                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.
451
            finally:
452
                r2.unlock()
453
        finally:
454
            tree.unlock()
455
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
456
    def test_lock_write_does_not_physically_lock(self):
457
        repo = self.make_repository('.', format=self.get_format())
458
        repo.lock_write()
459
        self.addCleanup(repo.unlock)
460
        self.assertFalse(repo.get_physical_lock_status())
461
462
    def prepare_for_break_lock(self):
463
        # Setup the global ui factory state so that a break-lock method call
464
        # will find usable input in the input stream.
465
        old_factory = ui.ui_factory
466
        def restoreFactory():
467
            ui.ui_factory = old_factory
468
        self.addCleanup(restoreFactory)
469
        ui.ui_factory = ui.SilentUIFactory()
470
        ui.ui_factory.stdin = StringIO("y\n")
471
472
    def test_break_lock_breaks_physical_lock(self):
473
        repo = self.make_repository('.', format=self.get_format())
474
        repo._pack_collection.lock_names()
3650.4.1 by Aaron Bentley
Fix test kipple in test_break_lock_breaks_physical_lock
475
        repo.control_files.leave_in_place()
476
        repo.unlock()
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
477
        repo2 = repository.Repository.open('.')
478
        self.assertTrue(repo.get_physical_lock_status())
479
        self.prepare_for_break_lock()
480
        repo2.break_lock()
481
        self.assertFalse(repo.get_physical_lock_status())
482
483
    def test_broken_physical_locks_error_on__unlock_names_lock(self):
484
        repo = self.make_repository('.', format=self.get_format())
485
        repo._pack_collection.lock_names()
486
        self.assertTrue(repo.get_physical_lock_status())
487
        repo2 = repository.Repository.open('.')
488
        self.prepare_for_break_lock()
489
        repo2.break_lock()
490
        self.assertRaises(errors.LockBroken, repo._pack_collection._unlock_names)
491
492
    def test_fetch_without_find_ghosts_ignores_ghosts(self):
493
        # we want two repositories at this point:
494
        # one with a revision that is a ghost in the other
495
        # repository.
496
        # 'ghost' is present in has_ghost, 'ghost' is absent in 'missing_ghost'.
497
        # 'references' is present in both repositories, and 'tip' is present
498
        # just in has_ghost.
499
        # has_ghost       missing_ghost
500
        #------------------------------
501
        # 'ghost'             -
502
        # 'references'    'references'
503
        # 'tip'               -
504
        # In this test we fetch 'tip' which should not fetch 'ghost'
505
        has_ghost = self.make_repository('has_ghost', format=self.get_format())
506
        missing_ghost = self.make_repository('missing_ghost',
507
            format=self.get_format())
508
509
        def add_commit(repo, revision_id, parent_ids):
510
            repo.lock_write()
511
            repo.start_write_group()
512
            inv = inventory.Inventory(revision_id=revision_id)
513
            inv.root.revision = revision_id
514
            root_id = inv.root.file_id
515
            sha1 = repo.add_inventory(revision_id, inv, [])
516
            repo.texts.add_lines((root_id, revision_id), [], [])
517
            rev = _mod_revision.Revision(timestamp=0,
518
                                         timezone=None,
519
                                         committer="Foo Bar <foo@example.com>",
520
                                         message="Message",
521
                                         inventory_sha1=sha1,
522
                                         revision_id=revision_id)
523
            rev.parent_ids = parent_ids
524
            repo.add_revision(revision_id, rev)
525
            repo.commit_write_group()
526
            repo.unlock()
527
        add_commit(has_ghost, 'ghost', [])
528
        add_commit(has_ghost, 'references', ['ghost'])
529
        add_commit(missing_ghost, 'references', ['ghost'])
530
        add_commit(has_ghost, 'tip', ['references'])
531
        missing_ghost.fetch(has_ghost, 'tip')
532
        # missing ghost now has tip and not ghost.
533
        rev = missing_ghost.get_revision('tip')
534
        inv = missing_ghost.get_inventory('tip')
535
        self.assertRaises(errors.NoSuchRevision,
536
            missing_ghost.get_revision, 'ghost')
537
        self.assertRaises(errors.NoSuchRevision,
538
            missing_ghost.get_inventory, 'ghost')
539
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.
540
    def make_write_ready_repo(self):
541
        repo = self.make_repository('.', format=self.get_format())
542
        repo.lock_write()
543
        repo.start_write_group()
544
        return repo
545
546
    def test_missing_inventories_compression_parent_prevents_commit(self):
547
        repo = self.make_write_ready_repo()
548
        key = ('junk',)
549
        repo.inventories._index._missing_compression_parents.add(key)
550
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
551
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
552
        repo.abort_write_group()
553
        repo.unlock()
554
555
    def test_missing_revisions_compression_parent_prevents_commit(self):
556
        repo = self.make_write_ready_repo()
557
        key = ('junk',)
558
        repo.revisions._index._missing_compression_parents.add(key)
559
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
560
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
561
        repo.abort_write_group()
562
        repo.unlock()
563
564
    def test_missing_signatures_compression_parent_prevents_commit(self):
565
        repo = self.make_write_ready_repo()
566
        key = ('junk',)
567
        repo.signatures._index._missing_compression_parents.add(key)
568
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
569
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
570
        repo.abort_write_group()
571
        repo.unlock()
572
573
    def test_missing_text_compression_parent_prevents_commit(self):
574
        repo = self.make_write_ready_repo()
575
        key = ('some', 'junk')
576
        repo.texts._index._missing_compression_parents.add(key)
577
        self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
578
        e = self.assertRaises(errors.BzrCheckError, repo.commit_write_group)
579
        repo.abort_write_group()
580
        repo.unlock()
581
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
582
    def test_supports_external_lookups(self):
583
        repo = self.make_repository('.', format=self.get_format())
584
        self.assertEqual(self.format_supports_external_lookups,
585
            repo._format.supports_external_lookups)
586
3825.4.1 by Andrew Bennetts
Add suppress_errors to abort_write_group.
587
    def test_abort_write_group_does_not_raise_when_suppressed(self):
588
        """Similar to per_repository.test_write_group's test of the same name.
589
590
        Also requires that the exception is logged.
591
        """
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.
592
        self.vfs_transport_factory = memory.MemoryServer
3825.4.1 by Andrew Bennetts
Add suppress_errors to abort_write_group.
593
        repo = self.make_repository('repo')
594
        token = repo.lock_write()
595
        self.addCleanup(repo.unlock)
596
        repo.start_write_group()
597
        # Damage the repository on the filesystem
598
        self.get_transport('').rename('repo', 'foo')
599
        # abort_write_group will not raise an error
600
        self.assertEqual(None, repo.abort_write_group(suppress_errors=True))
601
        # But it does log an error
602
        log_file = self._get_log(keep_log_file=True)
603
        self.assertContainsRe(log_file, 'abort_write_group failed')
604
        self.assertContainsRe(log_file, r'INFO  bzr: ERROR \(ignored\):')
605
        if token is not None:
606
            repo.leave_lock_in_place()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
607
3825.4.1 by Andrew Bennetts
Add suppress_errors to abort_write_group.
608
    def test_abort_write_group_does_raise_when_not_suppressed(self):
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.
609
        self.vfs_transport_factory = memory.MemoryServer
3825.4.1 by Andrew Bennetts
Add suppress_errors to abort_write_group.
610
        repo = self.make_repository('repo')
611
        token = repo.lock_write()
612
        self.addCleanup(repo.unlock)
613
        repo.start_write_group()
614
        # Damage the repository on the filesystem
615
        self.get_transport('').rename('repo', 'foo')
616
        # abort_write_group will not raise an error
617
        self.assertRaises(Exception, repo.abort_write_group)
618
        if token is not None:
619
            repo.leave_lock_in_place()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
620
4002.1.1 by Andrew Bennetts
Implement suspend_write_group/resume_write_group.
621
    def test_suspend_write_group(self):
622
        self.vfs_transport_factory = memory.MemoryServer
623
        repo = self.make_repository('repo')
624
        token = repo.lock_write()
625
        self.addCleanup(repo.unlock)
626
        repo.start_write_group()
627
        repo.texts.add_lines(('file-id', 'revid'), (), ['lines'])
628
        wg_tokens = repo.suspend_write_group()
629
        expected_pack_name = wg_tokens[0] + '.pack'
630
        upload_transport = repo._pack_collection._upload_transport
631
        limbo_files = upload_transport.list_dir('')
632
        self.assertTrue(expected_pack_name in limbo_files, limbo_files)
633
        md5 = osutils.md5(upload_transport.get_bytes(expected_pack_name))
634
        self.assertEqual(wg_tokens[0], md5.hexdigest())
635
636
    def test_resume_write_group_then_abort(self):
637
        # Create a repo, start a write group, insert some data, suspend.
638
        self.vfs_transport_factory = memory.MemoryServer
639
        repo = self.make_repository('repo')
640
        token = repo.lock_write()
641
        self.addCleanup(repo.unlock)
642
        repo.start_write_group()
643
        text_key = ('file-id', 'revid')
644
        repo.texts.add_lines(text_key, (), ['lines'])
645
        wg_tokens = repo.suspend_write_group()
646
        # Get a fresh repository object for the repo on the filesystem.
647
        same_repo = repo.bzrdir.open_repository()
648
        # Resume
649
        same_repo.lock_write()
650
        self.addCleanup(same_repo.unlock)
651
        same_repo.resume_write_group(wg_tokens)
652
        same_repo.abort_write_group()
653
        self.assertEqual(
654
            [], same_repo._pack_collection._upload_transport.list_dir(''))
655
        self.assertEqual(
656
            [], same_repo._pack_collection._pack_transport.list_dir(''))
657
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.
658
    def test_resume_malformed_token(self):
659
        self.vfs_transport_factory = memory.MemoryServer
660
        # Make a repository with a suspended write group
661
        repo = self.make_repository('repo')
662
        token = repo.lock_write()
663
        self.addCleanup(repo.unlock)
664
        repo.start_write_group()
665
        text_key = ('file-id', 'revid')
666
        repo.texts.add_lines(text_key, (), ['lines'])
667
        wg_tokens = repo.suspend_write_group()
668
        # Make a new repository
669
        new_repo = self.make_repository('new_repo')
670
        token = new_repo.lock_write()
671
        self.addCleanup(new_repo.unlock)
672
        hacked_wg_token = (
673
            '../../../../repo/.bzr/repository/upload/' + wg_tokens[0])
674
        self.assertRaises(
4002.1.7 by Andrew Bennetts
Rename UnresumableWriteGroups to UnresumableWriteGroup.
675
            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.
676
            new_repo.resume_write_group, [hacked_wg_token])
677
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
678
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
679
class TestPackRepositoryStacking(TestCaseWithTransport):
680
681
    """Tests for stacking pack repositories"""
682
683
    def setUp(self):
684
        if not self.format_supports_external_lookups:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
685
            raise TestNotApplicable("%r doesn't support stacking"
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
686
                % (self.format_name,))
687
        super(TestPackRepositoryStacking, self).setUp()
688
689
    def get_format(self):
690
        return bzrdir.format_registry.make_bzrdir(self.format_name)
691
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
692
    def test_stack_checks_rich_root_compatibility(self):
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
693
        # early versions of the packing code relied on pack internals to
694
        # stack, but the current version should be able to stack on any
695
        # format.
696
        #
697
        # TODO: Possibly this should be run per-repository-format and raise
698
        # TestNotApplicable on formats that don't support stacking. -- mbp
699
        # 20080729
700
        repo = self.make_repository('repo', format=self.get_format())
701
        if repo.supports_rich_root():
702
            # can only stack on repositories that have compatible internal
703
            # metadata
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
704
            if getattr(repo._format, 'supports_tree_reference', False):
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
705
                if repo._format.supports_chks:
3735.17.6 by John Arbash Meinel
Continue tracking down all the references to development3/4
706
                    matching_format_name = 'development5-subtree'
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
707
                else:
708
                    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.
709
            else:
710
                matching_format_name = 'rich-root-pack'
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
711
            mismatching_format_name = 'pack-0.92'
712
        else:
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
713
            if repo._format.supports_chks:
3735.17.9 by John Arbash Meinel
Change the stacking code to use same-serializer formats for stacking.
714
                hash_key = repo._format._serializer.search_key_name
715
                # At the moment, we don't allow stacking between various hash
716
                # keys.
717
                if hash_key == 'plain':
718
                    matching_format_name = 'development5'
719
                elif hash_key == 'hash-16-way':
720
                    matching_format_name = 'development5-hash16'
721
                else:
722
                    if hash_key != 'hash-255-way':
723
                        raise AssertionError("unhandled hash key: %s"
724
                                             % (hash_key,))
725
                    matching_format_name = 'development5-hash255'
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
726
            else:
727
                matching_format_name = 'pack-0.92'
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
728
            mismatching_format_name = 'pack-0.92-subtree'
729
        base = self.make_repository('base', format=matching_format_name)
730
        repo.add_fallback_repository(base)
731
        # you can't stack on something with incompatible data
732
        bad_repo = self.make_repository('mismatch',
733
            format=mismatching_format_name)
734
        e = self.assertRaises(errors.IncompatibleRepositories,
735
            repo.add_fallback_repository, bad_repo)
736
        self.assertContainsRe(str(e),
737
            r'(?m)KnitPackRepository.*/mismatch/.*\nis not compatible with\n'
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
738
            r'.*Repository.*/repo/.*\n'
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
739
            r'different rich-root support')
740
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
741
    def test_stack_checks_serializers_compatibility(self):
742
        repo = self.make_repository('repo', format=self.get_format())
743
        if getattr(repo._format, 'supports_tree_reference', False):
744
            # can only stack on repositories that have compatible internal
745
            # metadata
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
746
            if repo._format.supports_chks:
3735.17.6 by John Arbash Meinel
Continue tracking down all the references to development3/4
747
                matching_format_name = 'development5-subtree'
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
748
            else:
749
                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.
750
            mismatching_format_name = 'rich-root-pack'
751
        else:
752
            if repo.supports_rich_root():
753
                matching_format_name = 'rich-root-pack'
754
                mismatching_format_name = 'pack-0.92-subtree'
755
            else:
756
                raise TestNotApplicable('No formats use non-v5 serializer'
757
                    ' without having rich-root also set')
758
        base = self.make_repository('base', format=matching_format_name)
759
        repo.add_fallback_repository(base)
760
        # you can't stack on something with incompatible data
761
        bad_repo = self.make_repository('mismatch',
762
            format=mismatching_format_name)
763
        e = self.assertRaises(errors.IncompatibleRepositories,
764
            repo.add_fallback_repository, bad_repo)
765
        self.assertContainsRe(str(e),
766
            r'(?m)KnitPackRepository.*/mismatch/.*\nis not compatible with\n'
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
767
            r'.*Repository.*/repo/.*\n'
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
768
            r'different serializers')
769
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
770
    def test_adding_pack_does_not_record_pack_names_from_other_repositories(self):
771
        base = self.make_branch_and_tree('base', format=self.get_format())
772
        base.commit('foo')
773
        referencing = self.make_branch_and_tree('repo', format=self.get_format())
774
        referencing.branch.repository.add_fallback_repository(base.branch.repository)
775
        referencing.commit('bar')
776
        new_instance = referencing.bzrdir.open_repository()
777
        new_instance.lock_read()
778
        self.addCleanup(new_instance.unlock)
779
        new_instance._pack_collection.ensure_loaded()
780
        self.assertEqual(1, len(new_instance._pack_collection.all_packs()))
781
782
    def test_autopack_only_considers_main_repo_packs(self):
3735.2.81 by Vincent Ladeuil
Fix test failing on files present in obsolete_packs directory.
783
        format = self.get_format()
784
        base = self.make_branch_and_tree('base', format=format)
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
785
        base.commit('foo')
3735.2.81 by Vincent Ladeuil
Fix test failing on files present in obsolete_packs directory.
786
        tree = self.make_branch_and_tree('repo', format=format)
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
787
        tree.branch.repository.add_fallback_repository(base.branch.repository)
788
        trans = tree.branch.repository.bzrdir.get_repository_transport(None)
789
        # This test could be a little cheaper by replacing the packs
790
        # attribute on the repository to allow a different pack distribution
791
        # and max packs policy - so we are checking the policy is honoured
792
        # in the test. But for now 11 commits is not a big deal in a single
793
        # test.
794
        for x in range(9):
795
            tree.commit('commit %s' % x)
796
        # there should be 9 packs:
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
797
        index = self.index_class(trans, 'pack-names', None)
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
798
        self.assertEqual(9, len(list(index.iter_all_entries())))
799
        # committing one more should coalesce to 1 of 10.
800
        tree.commit('commit triggering pack')
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
801
        index = self.index_class(trans, 'pack-names', None)
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
802
        self.assertEqual(1, len(list(index.iter_all_entries())))
803
        # packing should not damage data
804
        tree = tree.bzrdir.open_workingtree()
805
        check_result = tree.branch.repository.check(
806
            [tree.branch.last_revision()])
3735.2.81 by Vincent Ladeuil
Fix test failing on files present in obsolete_packs directory.
807
        nb_files = 5 # .pack, .rix, .iix, .tix, .six
808
        if tree.branch.repository._format.supports_chks:
809
            nb_files += 1 # .cix
810
        # 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
811
        obsolete_files = list(trans.list_dir('obsolete_packs'))
812
        self.assertFalse('foo' in obsolete_files)
813
        self.assertFalse('bar' in obsolete_files)
3735.2.81 by Vincent Ladeuil
Fix test failing on files present in obsolete_packs directory.
814
        self.assertEqual(10 * nb_files, len(obsolete_files))
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
815
        # XXX: Todo check packs obsoleted correctly - old packs and indices
816
        # in the obsolete_packs directory.
817
        large_pack_name = list(index.iter_all_entries())[0][1][0]
818
        # finally, committing again should not touch the large pack.
819
        tree.commit('commit not triggering pack')
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
820
        index = self.index_class(trans, 'pack-names', None)
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
821
        self.assertEqual(2, len(list(index.iter_all_entries())))
822
        pack_names = [node[1][0] for node in index.iter_all_entries()]
823
        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
824
825
3801.1.18 by Andrew Bennetts
Add a test that ensures that the autopack RPC is actually used for all pack formats.
826
class TestSmartServerAutopack(TestCaseWithTransport):
827
828
    def setUp(self):
829
        super(TestSmartServerAutopack, self).setUp()
830
        # Create a smart server that publishes whatever the backing VFS server
831
        # does.
832
        self.smart_server = server.SmartTCPServer_for_testing()
833
        self.smart_server.setUp(self.get_server())
834
        self.addCleanup(self.smart_server.tearDown)
835
        # Log all HPSS calls into self.hpss_calls.
836
        client._SmartClient.hooks.install_named_hook(
837
            'call', self.capture_hpss_call, None)
838
        self.hpss_calls = []
839
840
    def capture_hpss_call(self, params):
841
        self.hpss_calls.append(params.method)
842
843
    def get_format(self):
844
        return bzrdir.format_registry.make_bzrdir(self.format_name)
845
4029.2.1 by Robert Collins
Support streaming push to stacked branches.
846
    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.
847
        # Make local and remote repos
3735.2.98 by John Arbash Meinel
Merge bzr.dev 4032. Resolve the new streaming fetch.
848
        format = self.get_format()
3735.2.93 by Vincent Ladeuil
Make test_autopack_rpc_is_used_when_using_hpss raise KnowFailure for CHK repos.
849
        tree = self.make_branch_and_tree('local', format=format)
850
        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.
851
        remote_branch_url = self.smart_server.get_url() + 'remote'
852
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
853
        # Make 9 local revisions, and push them one at a time to the remote
854
        # repo to produce 9 pack files.
855
        for x in range(9):
856
            tree.commit('commit %s' % x)
857
            tree.branch.push(remote_branch)
858
        # Make one more push to trigger an autopack
859
        self.hpss_calls = []
860
        tree.commit('commit triggering pack')
861
        tree.branch.push(remote_branch)
4029.2.1 by Robert Collins
Support streaming push to stacked branches.
862
        autopack_calls = len([call for call in self.hpss_calls if call ==
863
            'PackRepository.autopack'])
864
        streaming_calls = len([call for call in self.hpss_calls if call ==
865
            'Repository.insert_stream'])
866
        if autopack_calls:
867
            # Non streaming server
868
            self.assertEqual(1, autopack_calls)
869
            self.assertEqual(0, streaming_calls)
870
        else:
871
            # Streaming was used, which autopacks on the remote end.
872
            self.assertEqual(0, autopack_calls)
873
            # NB: The 2 calls are because of the sanity check that the server
874
            # supports the verb (see remote.py:RemoteSink.insert_stream for
875
            # details).
876
            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.
877
878
4084.5.1 by Robert Collins
Bulk update all test adaptation into a single approach, using multiply_tests rather than test adapters.
879
def load_tests(basic_tests, module, loader):
3582.3.3 by Martin Pool
Reenable tests for stacking pack repositories
880
    # these give the bzrdir canned format name, and the repository on-disk
881
    # format string
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
882
    scenarios_params = [
883
         dict(format_name='pack-0.92',
884
              format_string="Bazaar pack repository format 1 (needs bzr 0.92)\n",
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
885
              format_supports_external_lookups=False,
886
              index_class=GraphIndex),
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
887
         dict(format_name='pack-0.92-subtree',
888
              format_string="Bazaar pack repository format 1 "
889
              "with subtree support (needs bzr 0.92)\n",
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
890
              format_supports_external_lookups=False,
891
              index_class=GraphIndex),
3582.3.2 by Martin Pool
Add 1.6 formats to pack repository tests
892
         dict(format_name='1.6',
893
              format_string="Bazaar RepositoryFormatKnitPack5 (bzr 1.6)\n",
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
894
              format_supports_external_lookups=True,
895
              index_class=GraphIndex),
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
896
         dict(format_name='1.6.1-rich-root',
3582.3.2 by Martin Pool
Add 1.6 formats to pack repository tests
897
              format_string="Bazaar RepositoryFormatKnitPack5RichRoot "
3606.10.5 by John Arbash Meinel
Switch out --1.6-rich-root for --1.6.1-rich-root.
898
                  "(bzr 1.6.1)\n",
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
899
              format_supports_external_lookups=True,
900
              index_class=GraphIndex),
3805.3.1 by John Arbash Meinel
Add repository 1.9 format, and update the documentation.
901
         dict(format_name='1.9',
902
              format_string="Bazaar RepositoryFormatKnitPack6 (bzr 1.9)\n",
903
              format_supports_external_lookups=True,
904
              index_class=BTreeGraphIndex),
905
         dict(format_name='1.9-rich-root',
906
              format_string="Bazaar RepositoryFormatKnitPack6RichRoot "
907
                  "(bzr 1.9)\n",
908
              format_supports_external_lookups=True,
909
              index_class=BTreeGraphIndex),
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
910
         dict(format_name='development2',
911
              format_string="Bazaar development format 2 "
912
                  "(needs bzr.dev from before 1.8)\n",
913
              format_supports_external_lookups=True,
914
              index_class=BTreeGraphIndex),
915
         dict(format_name='development2-subtree',
916
              format_string="Bazaar development format 2 "
917
                  "with subtree support (needs bzr.dev from before 1.8)\n",
918
              format_supports_external_lookups=True,
919
              index_class=BTreeGraphIndex),
3735.17.6 by John Arbash Meinel
Continue tracking down all the references to development3/4
920
         dict(format_name='development5',
3735.17.10 by John Arbash Meinel
Bring in Vincent's brisbane-core test fixes.
921
              # merge-bbc-dev4-to-bzr.dev
3735.17.6 by John Arbash Meinel
Continue tracking down all the references to development3/4
922
              format_string="Bazaar development format 5 "
923
                  "(needs bzr.dev from before 1.13)\n",
924
              format_supports_external_lookups=True,
925
              index_class=BTreeGraphIndex),
926
         dict(format_name='development5-subtree',
3735.17.10 by John Arbash Meinel
Bring in Vincent's brisbane-core test fixes.
927
              # merge-bbc-dev4-to-bzr.dev
3735.17.6 by John Arbash Meinel
Continue tracking down all the references to development3/4
928
              format_string="Bazaar development format 5 "
929
                  "with subtree support (needs bzr.dev from before 1.13)\n",
930
              format_supports_external_lookups=True,
931
              index_class=BTreeGraphIndex),
932
         dict(format_name='development5-hash16',
3735.17.10 by John Arbash Meinel
Bring in Vincent's brisbane-core test fixes.
933
              # merge-bbc-dev4-to-bzr.dev
3735.17.6 by John Arbash Meinel
Continue tracking down all the references to development3/4
934
              format_string="Bazaar development format 5 hash 16"
935
                            " (needs bzr.dev from before 1.13)\n",
936
              format_supports_external_lookups=True,
937
              index_class=BTreeGraphIndex),
938
         dict(format_name='development5-hash255',
3735.17.10 by John Arbash Meinel
Bring in Vincent's brisbane-core test fixes.
939
              # merge-bbc-dev4-to-bzr.dev
3735.17.6 by John Arbash Meinel
Continue tracking down all the references to development3/4
940
              format_string="Bazaar development format 5 hash 255"
941
                            " (needs bzr.dev from before 1.13)\n",
3735.2.40 by Robert Collins
Add development4 which has a parent_id to basename index on CHKInventory objects.
942
              format_supports_external_lookups=True,
943
              index_class=BTreeGraphIndex),
3582.3.1 by Martin Pool
Split pack repository tests into their own file and use scenarios
944
         ]
945
    # 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.
946
    scenarios = [(s['format_name'], s) for s in scenarios_params]
947
    return tests.multiply_tests(basic_tests, scenarios, loader.suiteClass())