/brz/remove-bazaar

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