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