/brz/remove-bazaar

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