~bzr-pqm/bzr/bzr.dev

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