/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2018.18.1 by Martin Pool
Add stub Repository.tarball smart method
1
# Copyright (C) 2006, 2007 Canonical Ltd
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
17
"""Tests for the smart wire/domain protocol.
18
19
This module contains tests for the domain-level smart requests and responses,
3015.2.12 by Robert Collins
Make test_smart use specific formats as needed to exercise locked and unlocked repositories.
20
such as the 'Branch.lock_write' request. Many of these use specific disk
21
formats to exercise calls that only make sense for formats with specific
22
properties.
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
23
24
Tests for low-level protocol encoding are found in test_smart_transport.
25
"""
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
26
3211.5.2 by Robert Collins
Change RemoteRepository.get_parent_map to use bz2 not gzip for compression.
27
import bz2
2692.1.18 by Andrew Bennetts
Merge from bzr.dev.
28
from cStringIO import StringIO
2018.18.2 by Martin Pool
smart method Repository.tarball actually returns the tarball
29
import tarfile
30
2692.1.2 by Andrew Bennetts
Merge from bzr.dev.
31
from bzrlib import (
32
    bzrdir,
33
    errors,
34
    pack,
35
    smart,
36
    tests,
37
    urlutils,
38
    )
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
39
from bzrlib.branch import Branch, BranchReferenceFormat
2692.1.22 by Andrew Bennetts
Reinstate imports needed to run test_smart alone.
40
import bzrlib.smart.branch
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
41
import bzrlib.smart.bzrdir, bzrlib.smart.bzrdir as smart_dir
42
import bzrlib.smart.packrepository
2692.1.22 by Andrew Bennetts
Reinstate imports needed to run test_smart alone.
43
import bzrlib.smart.repository
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
44
from bzrlib.smart.request import (
45
    FailedSmartServerResponse,
46
    SmartServerRequest,
47
    SmartServerResponse,
48
    SuccessfulSmartServerResponse,
49
    )
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
50
from bzrlib.tests import (
51
    split_suite_by_re,
52
    )
2692.1.3 by Andrew Bennetts
Fix imports so that tests in test_smart.py can be run alone.
53
from bzrlib.transport import chroot, get_transport
2535.3.15 by Andrew Bennetts
Add KnitVersionedFile.get_stream_as_bytes, start smart implementation of RemoteRepository.get_data_stream.
54
from bzrlib.util import bencode
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
55
56
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
57
def load_tests(standard_tests, module, loader):
58
    """Multiply tests version and protocol consistency."""
59
    # FindRepository tests.
60
    bzrdir_mod = bzrlib.smart.bzrdir
4084.5.1 by Robert Collins
Bulk update all test adaptation into a single approach, using multiply_tests rather than test adapters.
61
    scenarios = [
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
62
        ("find_repository", {
63
            "_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV1}),
64
        ("find_repositoryV2", {
65
            "_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV2}),
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
66
        ("find_repositoryV3", {
67
            "_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV3}),
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
68
        ]
69
    to_adapt, result = split_suite_by_re(standard_tests,
70
        "TestSmartServerRequestFindRepository")
71
    v2_only, v1_and_2 = split_suite_by_re(to_adapt,
72
        "_v2")
4084.5.1 by Robert Collins
Bulk update all test adaptation into a single approach, using multiply_tests rather than test adapters.
73
    tests.multiply_tests(v1_and_2, scenarios, result)
74
    # The first scenario is only applicable to v1 protocols, it is deleted
75
    # since.
76
    tests.multiply_tests(v2_only, scenarios[1:], result)
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
77
    return result
78
79
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
80
class TestCaseWithChrootedTransport(tests.TestCaseWithTransport):
81
82
    def setUp(self):
83
        tests.TestCaseWithTransport.setUp(self)
84
        self._chroot_server = None
85
86
    def get_transport(self, relpath=None):
87
        if self._chroot_server is None:
88
            backing_transport = tests.TestCaseWithTransport.get_transport(self)
89
            self._chroot_server = chroot.ChrootServer(backing_transport)
90
            self._chroot_server.setUp()
91
            self.addCleanup(self._chroot_server.tearDown)
92
        t = get_transport(self._chroot_server.get_url())
93
        if relpath is not None:
94
            t = t.clone(relpath)
95
        return t
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
96
97
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
98
class TestCaseWithSmartMedium(tests.TestCaseWithTransport):
99
100
    def setUp(self):
101
        super(TestCaseWithSmartMedium, self).setUp()
102
        # We're allowed to set  the transport class here, so that we don't use
103
        # the default or a parameterized class, but rather use the
104
        # TestCaseWithTransport infrastructure to set up a smart server and
105
        # transport.
3245.4.28 by Andrew Bennetts
Remove another XXX, and include test ID in smart server thread names.
106
        self.transport_server = self.make_transport_server
107
108
    def make_transport_server(self):
109
        return smart.server.SmartTCPServer_for_testing('-' + self.id())
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
110
111
    def get_smart_medium(self):
112
        """Get a smart medium to use in tests."""
113
        return self.get_transport().get_smart_medium()
114
115
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
116
class TestSmartServerResponse(tests.TestCase):
117
118
    def test__eq__(self):
119
        self.assertEqual(SmartServerResponse(('ok', )),
120
            SmartServerResponse(('ok', )))
121
        self.assertEqual(SmartServerResponse(('ok', ), 'body'),
122
            SmartServerResponse(('ok', ), 'body'))
123
        self.assertNotEqual(SmartServerResponse(('ok', )),
124
            SmartServerResponse(('notok', )))
125
        self.assertNotEqual(SmartServerResponse(('ok', ), 'body'),
126
            SmartServerResponse(('ok', )))
2018.5.41 by Robert Collins
Fix SmartServerResponse.__eq__ to handle None.
127
        self.assertNotEqual(None,
128
            SmartServerResponse(('ok', )))
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
129
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
130
    def test__str__(self):
131
        """SmartServerResponses can be stringified."""
132
        self.assertEqual(
3691.2.6 by Martin Pool
Disable RemoteBranch stacking, but get get_stacked_on_url working, and passing back exceptions
133
            "<SuccessfulSmartServerResponse args=('args',) body='body'>",
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
134
            str(SuccessfulSmartServerResponse(('args',), 'body')))
135
        self.assertEqual(
3691.2.6 by Martin Pool
Disable RemoteBranch stacking, but get get_stacked_on_url working, and passing back exceptions
136
            "<FailedSmartServerResponse args=('args',) body='body'>",
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
137
            str(FailedSmartServerResponse(('args',), 'body')))
138
139
140
class TestSmartServerRequest(tests.TestCaseWithMemoryTransport):
141
142
    def test_translate_client_path(self):
143
        transport = self.get_transport()
144
        request = SmartServerRequest(transport, 'foo/')
145
        self.assertEqual('./', request.translate_client_path('foo/'))
146
        self.assertRaises(
147
            errors.InvalidURLJoin, request.translate_client_path, 'foo/..')
148
        self.assertRaises(
149
            errors.PathNotChild, request.translate_client_path, '/')
150
        self.assertRaises(
151
            errors.PathNotChild, request.translate_client_path, 'bar/')
152
        self.assertEqual('./baz', request.translate_client_path('foo/baz'))
153
154
    def test_transport_from_client_path(self):
155
        transport = self.get_transport()
156
        request = SmartServerRequest(transport, 'foo/')
157
        self.assertEqual(
158
            transport.base,
159
            request.transport_from_client_path('foo/').base)
160
161
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
162
class TestSmartServerBzrDirRequestCloningMetaDir(
163
    tests.TestCaseWithMemoryTransport):
164
    """Tests for BzrDir.cloning_metadir."""
165
166
    def test_cloning_metadir(self):
167
        """When there is a bzrdir present, the call succeeds."""
168
        backing = self.get_transport()
169
        dir = self.make_bzrdir('.')
170
        local_result = dir.cloning_metadir()
171
        request_class = smart_dir.SmartServerBzrDirRequestCloningMetaDir
172
        request = request_class(backing)
173
        expected = SuccessfulSmartServerResponse(
174
            (local_result.network_name(),
175
            local_result.repository_format.network_name(),
4070.7.4 by Andrew Bennetts
Deal with branch references better in BzrDir.cloning_metadir RPC (changes protocol).
176
            ('direct', local_result.get_branch_format().network_name())))
177
        self.assertEqual(expected, request.execute('', 'False'))
178
179
    def test_cloning_metadir_reference(self):
180
        """The request works when bzrdir contains a branch reference."""
181
        backing = self.get_transport()
182
        referenced_branch = self.make_branch('referenced')
183
        dir = self.make_bzrdir('.')
184
        local_result = dir.cloning_metadir()
185
        reference = BranchReferenceFormat().initialize(dir, referenced_branch)
186
        reference_url = BranchReferenceFormat().get_reference(dir)
187
        # The server shouldn't try to follow the branch reference, so it's fine
188
        # if the referenced branch isn't reachable.
189
        backing.rename('referenced', 'moved')
190
        request_class = smart_dir.SmartServerBzrDirRequestCloningMetaDir
191
        request = request_class(backing)
192
        expected = SuccessfulSmartServerResponse(
193
            (local_result.network_name(),
194
            local_result.repository_format.network_name(),
195
            ('reference', reference_url)))
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
196
        self.assertEqual(expected, request.execute('', 'False'))
197
198
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
199
class TestSmartServerRequestCreateRepository(tests.TestCaseWithMemoryTransport):
200
    """Tests for BzrDir.create_repository."""
201
202
    def test_makes_repository(self):
203
        """When there is a bzrdir present, the call succeeds."""
204
        backing = self.get_transport()
205
        self.make_bzrdir('.')
206
        request_class = bzrlib.smart.bzrdir.SmartServerRequestCreateRepository
207
        request = request_class(backing)
208
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
209
        reference_format = reference_bzrdir_format.repository_format
210
        network_name = reference_format.network_name()
211
        expected = SuccessfulSmartServerResponse(
212
            ('ok', 'no', 'no', 'no', network_name))
213
        self.assertEqual(expected, request.execute('', network_name, 'True'))
214
215
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
216
class TestSmartServerRequestFindRepository(tests.TestCaseWithMemoryTransport):
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
217
    """Tests for BzrDir.find_repository."""
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
218
219
    def test_no_repository(self):
220
        """When there is no repository to be found, ('norepository', ) is returned."""
221
        backing = self.get_transport()
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
222
        request = self._request_class(backing)
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
223
        self.make_bzrdir('.')
224
        self.assertEqual(SmartServerResponse(('norepository', )),
2692.1.19 by Andrew Bennetts
Tweak for consistency suggested by John's review.
225
            request.execute(''))
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
226
227
    def test_nonshared_repository(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
228
        # nonshared repositorys only allow 'find' to return a handle when the
229
        # path the repository is being searched on is the same as that that
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
230
        # the repository is at.
231
        backing = self.get_transport()
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
232
        request = self._request_class(backing)
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
233
        result = self._make_repository_and_result()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
234
        self.assertEqual(result, request.execute(''))
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
235
        self.make_bzrdir('subdir')
236
        self.assertEqual(SmartServerResponse(('norepository', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
237
            request.execute('subdir'))
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
238
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
239
    def _make_repository_and_result(self, shared=False, format=None):
240
        """Convenience function to setup a repository.
241
242
        :result: The SmartServerResponse to expect when opening it.
243
        """
244
        repo = self.make_repository('.', shared=shared, format=format)
245
        if repo.supports_rich_root():
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
246
            rich_root = 'yes'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
247
        else:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
248
            rich_root = 'no'
2018.5.138 by Robert Collins
Merge bzr.dev.
249
        if repo._format.supports_tree_reference:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
250
            subtrees = 'yes'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
251
        else:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
252
            subtrees = 'no'
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
253
        if (smart.bzrdir.SmartServerRequestFindRepositoryV3 ==
254
            self._request_class):
255
            return SuccessfulSmartServerResponse(
256
                ('ok', '', rich_root, subtrees, 'no',
257
                 repo._format.network_name()))
258
        elif (smart.bzrdir.SmartServerRequestFindRepositoryV2 ==
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
259
            self._request_class):
260
            # All tests so far are on formats, and for non-external
261
            # repositories.
262
            return SuccessfulSmartServerResponse(
263
                ('ok', '', rich_root, subtrees, 'no'))
264
        else:
265
            return SuccessfulSmartServerResponse(('ok', '', rich_root, subtrees))
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
266
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
267
    def test_shared_repository(self):
268
        """When there is a shared repository, we get 'ok', 'relpath-to-repo'."""
269
        backing = self.get_transport()
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
270
        request = self._request_class(backing)
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
271
        result = self._make_repository_and_result(shared=True)
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
272
        self.assertEqual(result, request.execute(''))
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
273
        self.make_bzrdir('subdir')
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
274
        result2 = SmartServerResponse(result.args[0:1] + ('..', ) + result.args[2:])
275
        self.assertEqual(result2,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
276
            request.execute('subdir'))
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
277
        self.make_bzrdir('subdir/deeper')
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
278
        result3 = SmartServerResponse(result.args[0:1] + ('../..', ) + result.args[2:])
279
        self.assertEqual(result3,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
280
            request.execute('subdir/deeper'))
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
281
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
282
    def test_rich_root_and_subtree_encoding(self):
283
        """Test for the format attributes for rich root and subtree support."""
284
        backing = self.get_transport()
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
285
        request = self._request_class(backing)
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
286
        result = self._make_repository_and_result(format='dirstate-with-subtree')
287
        # check the test will be valid
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
288
        self.assertEqual('yes', result.args[2])
289
        self.assertEqual('yes', result.args[3])
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
290
        self.assertEqual(result, request.execute(''))
291
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
292
    def test_supports_external_lookups_no_v2(self):
293
        """Test for the supports_external_lookups attribute."""
294
        backing = self.get_transport()
295
        request = self._request_class(backing)
296
        result = self._make_repository_and_result(format='dirstate-with-subtree')
297
        # check the test will be valid
298
        self.assertEqual('no', result.args[4])
2692.1.24 by Andrew Bennetts
Merge from bzr.dev.
299
        self.assertEqual(result, request.execute(''))
300
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
301
302
class TestSmartServerRequestInitializeBzrDir(tests.TestCaseWithMemoryTransport):
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
303
304
    def test_empty_dir(self):
305
        """Initializing an empty dir should succeed and do it."""
306
        backing = self.get_transport()
307
        request = smart.bzrdir.SmartServerRequestInitializeBzrDir(backing)
308
        self.assertEqual(SmartServerResponse(('ok', )),
2692.1.20 by Andrew Bennetts
Tweak for consistency suggested by John's review.
309
            request.execute(''))
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
310
        made_dir = bzrdir.BzrDir.open_from_transport(backing)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
311
        # no branch, tree or repository is expected with the current
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
312
        # default formart.
313
        self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
314
        self.assertRaises(errors.NotBranchError, made_dir.open_branch)
315
        self.assertRaises(errors.NoRepositoryPresent, made_dir.open_repository)
316
317
    def test_missing_dir(self):
318
        """Initializing a missing directory should fail like the bzrdir api."""
319
        backing = self.get_transport()
320
        request = smart.bzrdir.SmartServerRequestInitializeBzrDir(backing)
321
        self.assertRaises(errors.NoSuchFile,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
322
            request.execute, 'subdir')
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
323
324
    def test_initialized_dir(self):
325
        """Initializing an extant bzrdir should fail like the bzrdir api."""
326
        backing = self.get_transport()
327
        request = smart.bzrdir.SmartServerRequestInitializeBzrDir(backing)
328
        self.make_bzrdir('subdir')
329
        self.assertRaises(errors.FileExists,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
330
            request.execute, 'subdir')
331
332
333
class TestSmartServerRequestOpenBranch(TestCaseWithChrootedTransport):
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
334
335
    def test_no_branch(self):
336
        """When there is no branch, ('nobranch', ) is returned."""
337
        backing = self.get_transport()
338
        request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
339
        self.make_bzrdir('.')
340
        self.assertEqual(SmartServerResponse(('nobranch', )),
2692.1.20 by Andrew Bennetts
Tweak for consistency suggested by John's review.
341
            request.execute(''))
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
342
343
    def test_branch(self):
344
        """When there is a branch, 'ok' is returned."""
345
        backing = self.get_transport()
346
        request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
347
        self.make_branch('.')
348
        self.assertEqual(SmartServerResponse(('ok', '')),
2692.1.20 by Andrew Bennetts
Tweak for consistency suggested by John's review.
349
            request.execute(''))
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
350
351
    def test_branch_reference(self):
352
        """When there is a branch reference, the reference URL is returned."""
353
        backing = self.get_transport()
354
        request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
355
        branch = self.make_branch('branch')
356
        checkout = branch.create_checkout('reference',lightweight=True)
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
357
        reference_url = BranchReferenceFormat().get_reference(checkout.bzrdir)
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
358
        self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
359
        self.assertEqual(SmartServerResponse(('ok', reference_url)),
2692.1.20 by Andrew Bennetts
Tweak for consistency suggested by John's review.
360
            request.execute('reference'))
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
361
362
363
class TestSmartServerRequestRevisionHistory(tests.TestCaseWithMemoryTransport):
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
364
365
    def test_empty(self):
366
        """For an empty branch, the body is empty."""
367
        backing = self.get_transport()
368
        request = smart.branch.SmartServerRequestRevisionHistory(backing)
369
        self.make_branch('.')
370
        self.assertEqual(SmartServerResponse(('ok', ), ''),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
371
            request.execute(''))
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
372
373
    def test_not_empty(self):
374
        """For a non-empty branch, the body is empty."""
375
        backing = self.get_transport()
376
        request = smart.branch.SmartServerRequestRevisionHistory(backing)
377
        tree = self.make_branch_and_memory_tree('.')
378
        tree.lock_write()
379
        tree.add('')
380
        r1 = tree.commit('1st commit')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
381
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
382
        tree.unlock()
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
383
        self.assertEqual(
384
            SmartServerResponse(('ok', ), ('\x00'.join([r1, r2]))),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
385
            request.execute(''))
386
387
388
class TestSmartServerBranchRequest(tests.TestCaseWithMemoryTransport):
2018.5.49 by Wouter van Heyst
Refactor SmartServerBranchRequest out from SmartServerRequestRevisionHistory to
389
390
    def test_no_branch(self):
391
        """When there is a bzrdir and no branch, NotBranchError is raised."""
392
        backing = self.get_transport()
393
        request = smart.branch.SmartServerBranchRequest(backing)
394
        self.make_bzrdir('.')
395
        self.assertRaises(errors.NotBranchError,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
396
            request.execute, '')
2018.5.49 by Wouter van Heyst
Refactor SmartServerBranchRequest out from SmartServerRequestRevisionHistory to
397
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
398
    def test_branch_reference(self):
399
        """When there is a branch reference, NotBranchError is raised."""
400
        backing = self.get_transport()
2018.5.49 by Wouter van Heyst
Refactor SmartServerBranchRequest out from SmartServerRequestRevisionHistory to
401
        request = smart.branch.SmartServerBranchRequest(backing)
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
402
        branch = self.make_branch('branch')
403
        checkout = branch.create_checkout('reference',lightweight=True)
404
        self.assertRaises(errors.NotBranchError,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
405
            request.execute, 'checkout')
406
407
408
class TestSmartServerBranchRequestLastRevisionInfo(tests.TestCaseWithMemoryTransport):
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
409
410
    def test_empty(self):
2018.5.170 by Andrew Bennetts
Use 'null:' instead of '' to mean NULL_REVISION on the wire.
411
        """For an empty branch, the result is ('ok', '0', 'null:')."""
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
412
        backing = self.get_transport()
413
        request = smart.branch.SmartServerBranchRequestLastRevisionInfo(backing)
414
        self.make_branch('.')
2018.5.170 by Andrew Bennetts
Use 'null:' instead of '' to mean NULL_REVISION on the wire.
415
        self.assertEqual(SmartServerResponse(('ok', '0', 'null:')),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
416
            request.execute(''))
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
417
418
    def test_not_empty(self):
419
        """For a non-empty branch, the result is ('ok', 'revno', 'revid')."""
420
        backing = self.get_transport()
421
        request = smart.branch.SmartServerBranchRequestLastRevisionInfo(backing)
422
        tree = self.make_branch_and_memory_tree('.')
423
        tree.lock_write()
424
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
425
        rev_id_utf8 = u'\xc8'.encode('utf-8')
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
426
        r1 = tree.commit('1st commit')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
427
        r2 = tree.commit('2nd commit', rev_id=rev_id_utf8)
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
428
        tree.unlock()
429
        self.assertEqual(
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
430
            SmartServerResponse(('ok', '2', rev_id_utf8)),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
431
            request.execute(''))
432
433
434
class TestSmartServerBranchRequestGetConfigFile(tests.TestCaseWithMemoryTransport):
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
435
436
    def test_default(self):
437
        """With no file, we get empty content."""
438
        backing = self.get_transport()
439
        request = smart.branch.SmartServerBranchGetConfigFile(backing)
440
        branch = self.make_branch('.')
441
        # there should be no file by default
442
        content = ''
443
        self.assertEqual(SmartServerResponse(('ok', ), content),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
444
            request.execute(''))
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
445
446
    def test_with_content(self):
447
        # SmartServerBranchGetConfigFile should return the content from
448
        # branch.control_files.get('branch.conf') for now - in the future it may
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
449
        # perform more complex processing.
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
450
        backing = self.get_transport()
451
        request = smart.branch.SmartServerBranchGetConfigFile(backing)
452
        branch = self.make_branch('.')
3407.2.5 by Martin Pool
Deprecate LockableFiles.put_utf8
453
        branch._transport.put_bytes('branch.conf', 'foo bar baz')
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
454
        self.assertEqual(SmartServerResponse(('ok', ), 'foo bar baz'),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
455
            request.execute(''))
456
457
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
458
class SetLastRevisionTestBase(tests.TestCaseWithMemoryTransport):
459
    """Base test case for verbs that implement set_last_revision."""
460
461
    def setUp(self):
462
        tests.TestCaseWithMemoryTransport.setUp(self)
463
        backing_transport = self.get_transport()
464
        self.request = self.request_class(backing_transport)
465
        self.tree = self.make_branch_and_memory_tree('.')
466
467
    def lock_branch(self):
468
        b = self.tree.branch
469
        branch_token = b.lock_write()
470
        repo_token = b.repository.lock_write()
471
        b.repository.unlock()
472
        return branch_token, repo_token
473
474
    def unlock_branch(self):
475
        self.tree.branch.unlock()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
476
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
477
    def set_last_revision(self, revision_id, revno):
478
        branch_token, repo_token = self.lock_branch()
479
        response = self._set_last_revision(
480
            revision_id, revno, branch_token, repo_token)
481
        self.unlock_branch()
482
        return response
483
484
    def assertRequestSucceeds(self, revision_id, revno):
485
        response = self.set_last_revision(revision_id, revno)
486
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)), response)
487
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
488
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
489
class TestSetLastRevisionVerbMixin(object):
490
    """Mixin test case for verbs that implement set_last_revision."""
491
492
    def test_set_null_to_null(self):
493
        """An empty branch can have its last revision set to 'null:'."""
494
        self.assertRequestSucceeds('null:', 0)
495
496
    def test_NoSuchRevision(self):
497
        """If the revision_id is not present, the verb returns NoSuchRevision.
498
        """
499
        revision_id = 'non-existent revision'
500
        self.assertEqual(
501
            FailedSmartServerResponse(('NoSuchRevision', revision_id)),
502
            self.set_last_revision(revision_id, 1))
503
504
    def make_tree_with_two_commits(self):
505
        self.tree.lock_write()
506
        self.tree.add('')
507
        rev_id_utf8 = u'\xc8'.encode('utf-8')
508
        r1 = self.tree.commit('1st commit', rev_id=rev_id_utf8)
509
        r2 = self.tree.commit('2nd commit', rev_id='rev-2')
510
        self.tree.unlock()
511
512
    def test_branch_last_revision_info_is_updated(self):
513
        """A branch's tip can be set to a revision that is present in its
514
        repository.
515
        """
516
        # Make a branch with an empty revision history, but two revisions in
517
        # its repository.
518
        self.make_tree_with_two_commits()
519
        rev_id_utf8 = u'\xc8'.encode('utf-8')
520
        self.tree.branch.set_revision_history([])
521
        self.assertEqual(
522
            (0, 'null:'), self.tree.branch.last_revision_info())
523
        # We can update the branch to a revision that is present in the
524
        # repository.
525
        self.assertRequestSucceeds(rev_id_utf8, 1)
526
        self.assertEqual(
527
            (1, rev_id_utf8), self.tree.branch.last_revision_info())
528
529
    def test_branch_last_revision_info_rewind(self):
530
        """A branch's tip can be set to a revision that is an ancestor of the
531
        current tip.
532
        """
533
        self.make_tree_with_two_commits()
534
        rev_id_utf8 = u'\xc8'.encode('utf-8')
535
        self.assertEqual(
536
            (2, 'rev-2'), self.tree.branch.last_revision_info())
537
        self.assertRequestSucceeds(rev_id_utf8, 1)
538
        self.assertEqual(
539
            (1, rev_id_utf8), self.tree.branch.last_revision_info())
540
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
541
    def test_TipChangeRejected(self):
542
        """If a pre_change_branch_tip hook raises TipChangeRejected, the verb
543
        returns TipChangeRejected.
544
        """
545
        rejection_message = u'rejection message\N{INTERROBANG}'
546
        def hook_that_rejects(params):
547
            raise errors.TipChangeRejected(rejection_message)
548
        Branch.hooks.install_named_hook(
549
            'pre_change_branch_tip', hook_that_rejects, None)
550
        self.assertEqual(
551
            FailedSmartServerResponse(
552
                ('TipChangeRejected', rejection_message.encode('utf-8'))),
553
            self.set_last_revision('null:', 0))
554
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
555
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
556
class TestSmartServerBranchRequestSetLastRevision(
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
557
        SetLastRevisionTestBase, TestSetLastRevisionVerbMixin):
558
    """Tests for Branch.set_last_revision verb."""
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
559
560
    request_class = smart.branch.SmartServerBranchRequestSetLastRevision
561
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
562
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
563
        return self.request.execute(
564
            '', branch_token, repo_token, revision_id)
565
566
567
class TestSmartServerBranchRequestSetLastRevisionInfo(
568
        SetLastRevisionTestBase, TestSetLastRevisionVerbMixin):
569
    """Tests for Branch.set_last_revision_info verb."""
570
571
    request_class = smart.branch.SmartServerBranchRequestSetLastRevisionInfo
572
573
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
574
        return self.request.execute(
575
            '', branch_token, repo_token, revno, revision_id)
576
577
    def test_NoSuchRevision(self):
578
        """Branch.set_last_revision_info does not have to return
579
        NoSuchRevision if the revision_id is absent.
580
        """
581
        raise tests.TestNotApplicable()
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
582
583
3441.5.25 by Andrew Bennetts
Rename Branch.set_last_revision_descendant verb to Branch.set_last_revision_ex. It's a cop out, but at least it's not misleading.
584
class TestSmartServerBranchRequestSetLastRevisionEx(
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
585
        SetLastRevisionTestBase, TestSetLastRevisionVerbMixin):
586
    """Tests for Branch.set_last_revision_ex verb."""
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
587
3441.5.25 by Andrew Bennetts
Rename Branch.set_last_revision_descendant verb to Branch.set_last_revision_ex. It's a cop out, but at least it's not misleading.
588
    request_class = smart.branch.SmartServerBranchRequestSetLastRevisionEx
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
589
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
590
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
591
        return self.request.execute(
592
            '', branch_token, repo_token, revision_id, 0, 0)
593
594
    def assertRequestSucceeds(self, revision_id, revno):
595
        response = self.set_last_revision(revision_id, revno)
596
        self.assertEqual(
597
            SuccessfulSmartServerResponse(('ok', revno, revision_id)),
598
            response)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
599
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
600
    def test_branch_last_revision_info_rewind(self):
601
        """A branch's tip can be set to a revision that is an ancestor of the
602
        current tip, but only if allow_overwrite_descendant is passed.
603
        """
604
        self.make_tree_with_two_commits()
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
605
        rev_id_utf8 = u'\xc8'.encode('utf-8')
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
606
        self.assertEqual(
607
            (2, 'rev-2'), self.tree.branch.last_revision_info())
608
        # If allow_overwrite_descendant flag is 0, then trying to set the tip
609
        # to an older revision ID has no effect.
610
        branch_token, repo_token = self.lock_branch()
611
        response = self.request.execute(
612
            '', branch_token, repo_token, rev_id_utf8, 0, 0)
613
        self.assertEqual(
614
            SuccessfulSmartServerResponse(('ok', 2, 'rev-2')),
615
            response)
616
        self.assertEqual(
617
            (2, 'rev-2'), self.tree.branch.last_revision_info())
618
619
        # If allow_overwrite_descendant flag is 1, then setting the tip to an
620
        # ancestor works.
621
        response = self.request.execute(
622
            '', branch_token, repo_token, rev_id_utf8, 0, 1)
623
        self.assertEqual(
624
            SuccessfulSmartServerResponse(('ok', 1, rev_id_utf8)),
625
            response)
626
        self.unlock_branch()
627
        self.assertEqual(
628
            (1, rev_id_utf8), self.tree.branch.last_revision_info())
629
3441.5.31 by Andrew Bennetts
Add test for allow_diverged flag.
630
    def make_branch_with_divergent_history(self):
631
        """Make a branch with divergent history in its repo.
632
633
        The branch's tip will be 'child-2', and the repo will also contain
634
        'child-1', which diverges from a common base revision.
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
635
        """
636
        self.tree.lock_write()
637
        self.tree.add('')
638
        r1 = self.tree.commit('1st commit')
639
        revno_1, revid_1 = self.tree.branch.last_revision_info()
640
        r2 = self.tree.commit('2nd commit', rev_id='child-1')
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
641
        # Undo the second commit
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
642
        self.tree.branch.set_last_revision_info(revno_1, revid_1)
643
        self.tree.set_parent_ids([revid_1])
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
644
        # Make a new second commit, child-2.  child-2 has diverged from
645
        # child-1.
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
646
        new_r2 = self.tree.commit('2nd commit', rev_id='child-2')
647
        self.tree.unlock()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
648
3441.5.31 by Andrew Bennetts
Add test for allow_diverged flag.
649
    def test_not_allow_diverged(self):
650
        """If allow_diverged is not passed, then setting a divergent history
651
        returns a Diverged error.
652
        """
653
        self.make_branch_with_divergent_history()
3297.4.3 by Andrew Bennetts
Add more tests, handle NoSuchRevision in case the remote branch's format can raise it.
654
        self.assertEqual(
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
655
            FailedSmartServerResponse(('Diverged',)),
656
            self.set_last_revision('child-1', 2))
657
        # The branch tip was not changed.
658
        self.assertEqual('child-2', self.tree.branch.last_revision())
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
659
3441.5.31 by Andrew Bennetts
Add test for allow_diverged flag.
660
    def test_allow_diverged(self):
661
        """If allow_diverged is passed, then setting a divergent history
662
        succeeds.
663
        """
664
        self.make_branch_with_divergent_history()
665
        branch_token, repo_token = self.lock_branch()
666
        response = self.request.execute(
667
            '', branch_token, repo_token, 'child-1', 1, 0)
668
        self.assertEqual(
669
            SuccessfulSmartServerResponse(('ok', 2, 'child-1')),
670
            response)
671
        self.unlock_branch()
672
        # The branch tip was changed.
673
        self.assertEqual('child-1', self.tree.branch.last_revision())
674
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
675
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
676
class TestSmartServerBranchRequestGetParent(tests.TestCaseWithMemoryTransport):
677
678
    def test_get_parent_none(self):
679
        base_branch = self.make_branch('base')
680
        request = smart.branch.SmartServerBranchGetParent(self.get_transport())
681
        response = request.execute('base')
682
        self.assertEquals(
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
683
            SuccessfulSmartServerResponse(('',)), response)
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
684
685
    def test_get_parent_something(self):
686
        base_branch = self.make_branch('base')
687
        base_branch.set_parent(self.get_url('foo'))
688
        request = smart.branch.SmartServerBranchGetParent(self.get_transport())
689
        response = request.execute('base')
690
        self.assertEquals(
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
691
            SuccessfulSmartServerResponse(("../foo",)),
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
692
            response)
693
694
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
695
class TestSmartServerBranchRequestGetStackedOnURL(tests.TestCaseWithMemoryTransport):
696
697
    def test_get_stacked_on_url(self):
698
        base_branch = self.make_branch('base', format='1.6')
699
        stacked_branch = self.make_branch('stacked', format='1.6')
700
        # typically should be relative
701
        stacked_branch.set_stacked_on_url('../base')
702
        request = smart.branch.SmartServerBranchRequestGetStackedOnURL(
703
            self.get_transport())
704
        response = request.execute('stacked')
705
        self.assertEquals(
706
            SmartServerResponse(('ok', '../base')),
707
            response)
708
709
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
710
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
711
712
    def setUp(self):
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
713
        tests.TestCaseWithMemoryTransport.setUp(self)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
714
715
    def test_lock_write_on_unlocked_branch(self):
716
        backing = self.get_transport()
717
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
3015.2.12 by Robert Collins
Make test_smart use specific formats as needed to exercise locked and unlocked repositories.
718
        branch = self.make_branch('.', format='knit')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
719
        repository = branch.repository
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
720
        response = request.execute('')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
721
        branch_nonce = branch.control_files._lock.peek().get('nonce')
722
        repository_nonce = repository.control_files._lock.peek().get('nonce')
723
        self.assertEqual(
724
            SmartServerResponse(('ok', branch_nonce, repository_nonce)),
725
            response)
726
        # The branch (and associated repository) is now locked.  Verify that
727
        # with a new branch object.
728
        new_branch = repository.bzrdir.open_branch()
729
        self.assertRaises(errors.LockContention, new_branch.lock_write)
730
731
    def test_lock_write_on_locked_branch(self):
732
        backing = self.get_transport()
733
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
734
        branch = self.make_branch('.')
735
        branch.lock_write()
736
        branch.leave_lock_in_place()
737
        branch.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
738
        response = request.execute('')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
739
        self.assertEqual(
740
            SmartServerResponse(('LockContention',)), response)
741
742
    def test_lock_write_with_tokens_on_locked_branch(self):
743
        backing = self.get_transport()
744
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
3015.2.12 by Robert Collins
Make test_smart use specific formats as needed to exercise locked and unlocked repositories.
745
        branch = self.make_branch('.', format='knit')
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
746
        branch_token = branch.lock_write()
747
        repo_token = branch.repository.lock_write()
748
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
749
        branch.leave_lock_in_place()
750
        branch.repository.leave_lock_in_place()
751
        branch.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
752
        response = request.execute('',
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
753
                                   branch_token, repo_token)
754
        self.assertEqual(
755
            SmartServerResponse(('ok', branch_token, repo_token)), response)
756
757
    def test_lock_write_with_mismatched_tokens_on_locked_branch(self):
758
        backing = self.get_transport()
759
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
3015.2.12 by Robert Collins
Make test_smart use specific formats as needed to exercise locked and unlocked repositories.
760
        branch = self.make_branch('.', format='knit')
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
761
        branch_token = branch.lock_write()
762
        repo_token = branch.repository.lock_write()
763
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
764
        branch.leave_lock_in_place()
765
        branch.repository.leave_lock_in_place()
766
        branch.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
767
        response = request.execute('',
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
768
                                   branch_token+'xxx', repo_token)
769
        self.assertEqual(
770
            SmartServerResponse(('TokenMismatch',)), response)
771
772
    def test_lock_write_on_locked_repo(self):
773
        backing = self.get_transport()
774
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
3015.2.12 by Robert Collins
Make test_smart use specific formats as needed to exercise locked and unlocked repositories.
775
        branch = self.make_branch('.', format='knit')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
776
        branch.repository.lock_write()
777
        branch.repository.leave_lock_in_place()
778
        branch.repository.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
779
        response = request.execute('')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
780
        self.assertEqual(
781
            SmartServerResponse(('LockContention',)), response)
782
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
783
    def test_lock_write_on_readonly_transport(self):
784
        backing = self.get_readonly_transport()
785
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
786
        branch = self.make_branch('.')
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
787
        root = self.get_transport().clone('/')
788
        path = urlutils.relative_url(root.base, self.get_transport().base)
789
        response = request.execute(path)
2872.5.3 by Martin Pool
Pass back LockFailed from smart server lock methods
790
        error_name, lock_str, why_str = response.args
791
        self.assertFalse(response.is_successful())
792
        self.assertEqual('LockFailed', error_name)
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
793
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
794
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
795
class TestSmartServerBranchRequestUnlock(tests.TestCaseWithMemoryTransport):
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
796
797
    def setUp(self):
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
798
        tests.TestCaseWithMemoryTransport.setUp(self)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
799
800
    def test_unlock_on_locked_branch_and_repo(self):
801
        backing = self.get_transport()
802
        request = smart.branch.SmartServerBranchRequestUnlock(backing)
3015.2.12 by Robert Collins
Make test_smart use specific formats as needed to exercise locked and unlocked repositories.
803
        branch = self.make_branch('.', format='knit')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
804
        # Lock the branch
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
805
        branch_token = branch.lock_write()
806
        repo_token = branch.repository.lock_write()
807
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
808
        # Unlock the branch (and repo) object, leaving the physical locks
809
        # in place.
810
        branch.leave_lock_in_place()
811
        branch.repository.leave_lock_in_place()
812
        branch.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
813
        response = request.execute('',
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
814
                                   branch_token, repo_token)
815
        self.assertEqual(
816
            SmartServerResponse(('ok',)), response)
817
        # The branch is now unlocked.  Verify that with a new branch
818
        # object.
819
        new_branch = branch.bzrdir.open_branch()
820
        new_branch.lock_write()
821
        new_branch.unlock()
822
823
    def test_unlock_on_unlocked_branch_unlocked_repo(self):
824
        backing = self.get_transport()
825
        request = smart.branch.SmartServerBranchRequestUnlock(backing)
3015.2.12 by Robert Collins
Make test_smart use specific formats as needed to exercise locked and unlocked repositories.
826
        branch = self.make_branch('.', format='knit')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
827
        response = request.execute(
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
828
            '', 'branch token', 'repo token')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
829
        self.assertEqual(
830
            SmartServerResponse(('TokenMismatch',)), response)
831
832
    def test_unlock_on_unlocked_branch_locked_repo(self):
833
        backing = self.get_transport()
834
        request = smart.branch.SmartServerBranchRequestUnlock(backing)
3015.2.12 by Robert Collins
Make test_smart use specific formats as needed to exercise locked and unlocked repositories.
835
        branch = self.make_branch('.', format='knit')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
836
        # Lock the repository.
837
        repo_token = branch.repository.lock_write()
838
        branch.repository.leave_lock_in_place()
839
        branch.repository.unlock()
840
        # Issue branch lock_write request on the unlocked branch (with locked
841
        # repo).
842
        response = request.execute(
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
843
            '', 'branch token', repo_token)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
844
        self.assertEqual(
845
            SmartServerResponse(('TokenMismatch',)), response)
846
847
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
848
class TestSmartServerRepositoryRequest(tests.TestCaseWithMemoryTransport):
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
849
850
    def test_no_repository(self):
851
        """Raise NoRepositoryPresent when there is a bzrdir and no repo."""
852
        # we test this using a shared repository above the named path,
853
        # thus checking the right search logic is used - that is, that
854
        # its the exact path being looked at and the server is not
855
        # searching.
856
        backing = self.get_transport()
2018.5.58 by Wouter van Heyst
Small test fixes to reflect naming and documentation
857
        request = smart.repository.SmartServerRepositoryRequest(backing)
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
858
        self.make_repository('.', shared=True)
859
        self.make_bzrdir('subdir')
860
        self.assertRaises(errors.NoRepositoryPresent,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
861
            request.execute, 'subdir')
862
863
3441.5.4 by Andrew Bennetts
Fix test failures, and add some tests for the remote graph heads RPC.
864
class TestSmartServerRepositoryGetParentMap(tests.TestCaseWithMemoryTransport):
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
865
3211.5.3 by Robert Collins
Adjust size of batch and change gzip comments to bzip2.
866
    def test_trivial_bzipped(self):
867
        # This tests that the wire encoding is actually bzipped
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
868
        backing = self.get_transport()
869
        request = smart.repository.SmartServerRepositoryGetParentMap(backing)
870
        tree = self.make_branch_and_memory_tree('.')
871
872
        self.assertEqual(None,
2692.1.24 by Andrew Bennetts
Merge from bzr.dev.
873
            request.execute('', 'missing-id'))
3211.5.3 by Robert Collins
Adjust size of batch and change gzip comments to bzip2.
874
        # Note that it returns a body (of '' bzipped).
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
875
        self.assertEqual(
3211.5.2 by Robert Collins
Change RemoteRepository.get_parent_map to use bz2 not gzip for compression.
876
            SuccessfulSmartServerResponse(('ok', ), bz2.compress('')),
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
877
            request.do_body('\n\n0\n'))
878
879
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
880
class TestSmartServerRepositoryGetRevisionGraph(tests.TestCaseWithMemoryTransport):
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
881
882
    def test_none_argument(self):
883
        backing = self.get_transport()
884
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
885
        tree = self.make_branch_and_memory_tree('.')
886
        tree.lock_write()
887
        tree.add('')
888
        r1 = tree.commit('1st commit')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
889
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
890
        tree.unlock()
891
892
        # the lines of revision_id->revision_parent_list has no guaranteed
893
        # order coming out of a dict, so sort both our test and response
894
        lines = sorted([' '.join([r2, r1]), r1])
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
895
        response = request.execute('', '')
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
896
        response.body = '\n'.join(sorted(response.body.split('\n')))
897
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
898
        self.assertEqual(
899
            SmartServerResponse(('ok', ), '\n'.join(lines)), response)
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
900
901
    def test_specific_revision_argument(self):
902
        backing = self.get_transport()
903
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
904
        tree = self.make_branch_and_memory_tree('.')
905
        tree.lock_write()
906
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
907
        rev_id_utf8 = u'\xc9'.encode('utf-8')
908
        r1 = tree.commit('1st commit', rev_id=rev_id_utf8)
909
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
910
        tree.unlock()
911
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
912
        self.assertEqual(SmartServerResponse(('ok', ), rev_id_utf8),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
913
            request.execute('', rev_id_utf8))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
914
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
915
    def test_no_such_revision(self):
916
        backing = self.get_transport()
917
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
918
        tree = self.make_branch_and_memory_tree('.')
919
        tree.lock_write()
920
        tree.add('')
921
        r1 = tree.commit('1st commit')
922
        tree.unlock()
923
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
924
        # Note that it still returns body (of zero bytes).
925
        self.assertEqual(
926
            SmartServerResponse(('nosuchrevision', 'missingrevision', ), ''),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
927
            request.execute('', 'missingrevision'))
928
929
930
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
931
932
    def test_missing_revision(self):
933
        """For a missing revision, ('no', ) is returned."""
934
        backing = self.get_transport()
935
        request = smart.repository.SmartServerRequestHasRevision(backing)
936
        self.make_repository('.')
937
        self.assertEqual(SmartServerResponse(('no', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
938
            request.execute('', 'revid'))
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
939
940
    def test_present_revision(self):
2018.5.158 by Andrew Bennetts
Return 'yes'/'no' rather than 'ok'/'no' from the Repository.has_revision smart command.
941
        """For a present revision, ('yes', ) is returned."""
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
942
        backing = self.get_transport()
943
        request = smart.repository.SmartServerRequestHasRevision(backing)
944
        tree = self.make_branch_and_memory_tree('.')
945
        tree.lock_write()
946
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
947
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
948
        r1 = tree.commit('a commit', rev_id=rev_id_utf8)
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
949
        tree.unlock()
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
950
        self.assertTrue(tree.branch.repository.has_revision(rev_id_utf8))
2018.5.158 by Andrew Bennetts
Return 'yes'/'no' rather than 'ok'/'no' from the Repository.has_revision smart command.
951
        self.assertEqual(SmartServerResponse(('yes', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
952
            request.execute('', rev_id_utf8))
953
954
955
class TestSmartServerRepositoryGatherStats(tests.TestCaseWithMemoryTransport):
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
956
957
    def test_empty_revid(self):
958
        """With an empty revid, we get only size an number and revisions"""
959
        backing = self.get_transport()
960
        request = smart.repository.SmartServerRepositoryGatherStats(backing)
961
        repository = self.make_repository('.')
962
        stats = repository.gather_stats()
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
963
        expected_body = 'revisions: 0\n'
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
964
        self.assertEqual(SmartServerResponse(('ok', ), expected_body),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
965
                         request.execute('', '', 'no'))
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
966
967
    def test_revid_with_committers(self):
968
        """For a revid we get more infos."""
969
        backing = self.get_transport()
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
970
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
971
        request = smart.repository.SmartServerRepositoryGatherStats(backing)
972
        tree = self.make_branch_and_memory_tree('.')
973
        tree.lock_write()
974
        tree.add('')
975
        # Let's build a predictable result
976
        tree.commit('a commit', timestamp=123456.2, timezone=3600)
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
977
        tree.commit('a commit', timestamp=654321.4, timezone=0,
978
                    rev_id=rev_id_utf8)
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
979
        tree.unlock()
980
981
        stats = tree.branch.repository.gather_stats()
982
        expected_body = ('firstrev: 123456.200 3600\n'
983
                         'latestrev: 654321.400 0\n'
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
984
                         'revisions: 2\n')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
985
        self.assertEqual(SmartServerResponse(('ok', ), expected_body),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
986
                         request.execute('',
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
987
                                         rev_id_utf8, 'no'))
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
988
989
    def test_not_empty_repository_with_committers(self):
990
        """For a revid and requesting committers we get the whole thing."""
991
        backing = self.get_transport()
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
992
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
993
        request = smart.repository.SmartServerRepositoryGatherStats(backing)
994
        tree = self.make_branch_and_memory_tree('.')
995
        tree.lock_write()
996
        tree.add('')
997
        # Let's build a predictable result
998
        tree.commit('a commit', timestamp=123456.2, timezone=3600,
999
                    committer='foo')
1000
        tree.commit('a commit', timestamp=654321.4, timezone=0,
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1001
                    committer='bar', rev_id=rev_id_utf8)
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1002
        tree.unlock()
1003
        stats = tree.branch.repository.gather_stats()
1004
1005
        expected_body = ('committers: 2\n'
1006
                         'firstrev: 123456.200 3600\n'
1007
                         'latestrev: 654321.400 0\n'
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1008
                         'revisions: 2\n')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1009
        self.assertEqual(SmartServerResponse(('ok', ), expected_body),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1010
                         request.execute('',
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1011
                                         rev_id_utf8, 'yes'))
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1012
1013
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1014
class TestSmartServerRepositoryIsShared(tests.TestCaseWithMemoryTransport):
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1015
1016
    def test_is_shared(self):
1017
        """For a shared repository, ('yes', ) is returned."""
1018
        backing = self.get_transport()
1019
        request = smart.repository.SmartServerRepositoryIsShared(backing)
1020
        self.make_repository('.', shared=True)
1021
        self.assertEqual(SmartServerResponse(('yes', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1022
            request.execute('', ))
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1023
1024
    def test_is_not_shared(self):
2018.5.58 by Wouter van Heyst
Small test fixes to reflect naming and documentation
1025
        """For a shared repository, ('no', ) is returned."""
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1026
        backing = self.get_transport()
1027
        request = smart.repository.SmartServerRepositoryIsShared(backing)
1028
        self.make_repository('.', shared=False)
1029
        self.assertEqual(SmartServerResponse(('no', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1030
            request.execute('', ))
1031
1032
1033
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1034
1035
    def setUp(self):
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1036
        tests.TestCaseWithMemoryTransport.setUp(self)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1037
1038
    def test_lock_write_on_unlocked_repo(self):
1039
        backing = self.get_transport()
1040
        request = smart.repository.SmartServerRepositoryLockWrite(backing)
3015.2.12 by Robert Collins
Make test_smart use specific formats as needed to exercise locked and unlocked repositories.
1041
        repository = self.make_repository('.', format='knit')
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1042
        response = request.execute('')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1043
        nonce = repository.control_files._lock.peek().get('nonce')
1044
        self.assertEqual(SmartServerResponse(('ok', nonce)), response)
1045
        # The repository is now locked.  Verify that with a new repository
1046
        # object.
1047
        new_repo = repository.bzrdir.open_repository()
1048
        self.assertRaises(errors.LockContention, new_repo.lock_write)
1049
1050
    def test_lock_write_on_locked_repo(self):
1051
        backing = self.get_transport()
1052
        request = smart.repository.SmartServerRepositoryLockWrite(backing)
3015.2.12 by Robert Collins
Make test_smart use specific formats as needed to exercise locked and unlocked repositories.
1053
        repository = self.make_repository('.', format='knit')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1054
        repository.lock_write()
1055
        repository.leave_lock_in_place()
1056
        repository.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1057
        response = request.execute('')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1058
        self.assertEqual(
1059
            SmartServerResponse(('LockContention',)), response)
1060
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
1061
    def test_lock_write_on_readonly_transport(self):
1062
        backing = self.get_readonly_transport()
1063
        request = smart.repository.SmartServerRepositoryLockWrite(backing)
3015.2.12 by Robert Collins
Make test_smart use specific formats as needed to exercise locked and unlocked repositories.
1064
        repository = self.make_repository('.', format='knit')
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
1065
        response = request.execute('')
2872.5.3 by Martin Pool
Pass back LockFailed from smart server lock methods
1066
        self.assertFalse(response.is_successful())
1067
        self.assertEqual('LockFailed', response.args[0])
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
1068
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1069
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1070
class TestSmartServerRepositoryUnlock(tests.TestCaseWithMemoryTransport):
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1071
1072
    def setUp(self):
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1073
        tests.TestCaseWithMemoryTransport.setUp(self)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1074
1075
    def test_unlock_on_locked_repo(self):
1076
        backing = self.get_transport()
1077
        request = smart.repository.SmartServerRepositoryUnlock(backing)
3015.2.12 by Robert Collins
Make test_smart use specific formats as needed to exercise locked and unlocked repositories.
1078
        repository = self.make_repository('.', format='knit')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1079
        token = repository.lock_write()
1080
        repository.leave_lock_in_place()
1081
        repository.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1082
        response = request.execute('', token)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1083
        self.assertEqual(
1084
            SmartServerResponse(('ok',)), response)
1085
        # The repository is now unlocked.  Verify that with a new repository
1086
        # object.
1087
        new_repo = repository.bzrdir.open_repository()
1088
        new_repo.lock_write()
1089
        new_repo.unlock()
1090
1091
    def test_unlock_on_unlocked_repo(self):
1092
        backing = self.get_transport()
1093
        request = smart.repository.SmartServerRepositoryUnlock(backing)
3015.2.12 by Robert Collins
Make test_smart use specific formats as needed to exercise locked and unlocked repositories.
1094
        repository = self.make_repository('.', format='knit')
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1095
        response = request.execute('', 'some token')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1096
        self.assertEqual(
1097
            SmartServerResponse(('TokenMismatch',)), response)
1098
1099
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1100
class TestSmartServerIsReadonly(tests.TestCaseWithMemoryTransport):
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
1101
1102
    def test_is_readonly_no(self):
1103
        backing = self.get_transport()
1104
        request = smart.request.SmartServerIsReadonly(backing)
1105
        response = request.execute()
1106
        self.assertEqual(
1107
            SmartServerResponse(('no',)), response)
1108
1109
    def test_is_readonly_yes(self):
1110
        backing = self.get_readonly_transport()
1111
        request = smart.request.SmartServerIsReadonly(backing)
1112
        response = request.execute()
1113
        self.assertEqual(
1114
            SmartServerResponse(('yes',)), response)
1115
1116
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
1117
class TestSmartServerRepositorySetMakeWorkingTrees(tests.TestCaseWithMemoryTransport):
1118
1119
    def test_set_false(self):
1120
        backing = self.get_transport()
1121
        repo = self.make_repository('.', shared=True)
1122
        repo.set_make_working_trees(True)
1123
        request_class = smart.repository.SmartServerRepositorySetMakeWorkingTrees
1124
        request = request_class(backing)
1125
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)),
1126
            request.execute('', 'False'))
1127
        repo = repo.bzrdir.open_repository()
1128
        self.assertFalse(repo.make_working_trees())
1129
1130
    def test_set_true(self):
1131
        backing = self.get_transport()
1132
        repo = self.make_repository('.', shared=True)
1133
        repo.set_make_working_trees(False)
1134
        request_class = smart.repository.SmartServerRepositorySetMakeWorkingTrees
1135
        request = request_class(backing)
1136
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)),
1137
            request.execute('', 'True'))
1138
        repo = repo.bzrdir.open_repository()
1139
        self.assertTrue(repo.make_working_trees())
1140
1141
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1142
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1143
1144
    def make_repo_needing_autopacking(self, path='.'):
1145
        # Make a repo in need of autopacking.
1146
        tree = self.make_branch_and_tree('.', format='pack-0.92')
1147
        repo = tree.branch.repository
1148
        # monkey-patch the pack collection to disable autopacking
1149
        repo._pack_collection._max_pack_count = lambda count: count
1150
        for x in range(10):
1151
            tree.commit('commit %s' % x)
1152
        self.assertEqual(10, len(repo._pack_collection.names()))
1153
        del repo._pack_collection._max_pack_count
1154
        return repo
1155
1156
    def test_autopack_needed(self):
1157
        repo = self.make_repo_needing_autopacking()
1158
        backing = self.get_transport()
1159
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1160
            backing)
1161
        response = request.execute('')
1162
        self.assertEqual(SmartServerResponse(('ok',)), response)
1163
        repo._pack_collection.reload_pack_names()
1164
        self.assertEqual(1, len(repo._pack_collection.names()))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1165
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1166
    def test_autopack_not_needed(self):
1167
        tree = self.make_branch_and_tree('.', format='pack-0.92')
1168
        repo = tree.branch.repository
1169
        for x in range(9):
1170
            tree.commit('commit %s' % x)
1171
        backing = self.get_transport()
1172
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1173
            backing)
1174
        response = request.execute('')
1175
        self.assertEqual(SmartServerResponse(('ok',)), response)
1176
        repo._pack_collection.reload_pack_names()
1177
        self.assertEqual(9, len(repo._pack_collection.names()))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1178
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1179
    def test_autopack_on_nonpack_format(self):
3801.1.20 by Andrew Bennetts
Return ('ok',) rather than an error the autopack RPC is used on a non-pack repo.
1180
        """A request to autopack a non-pack repo is a no-op."""
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1181
        repo = self.make_repository('.', format='knit')
1182
        backing = self.get_transport()
1183
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1184
            backing)
1185
        response = request.execute('')
3801.1.20 by Andrew Bennetts
Return ('ok',) rather than an error the autopack RPC is used on a non-pack repo.
1186
        self.assertEqual(SmartServerResponse(('ok',)), response)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1187
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1188
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
1189
class TestHandlers(tests.TestCase):
1190
    """Tests for the request.request_handlers object."""
1191
3526.3.1 by Andrew Bennetts
Remove registrations of defunct HPSS verbs.
1192
    def test_all_registrations_exist(self):
1193
        """All registered request_handlers can be found."""
1194
        # If there's a typo in a register_lazy call, this loop will fail with
1195
        # an AttributeError.
1196
        for key, item in smart.request.request_handlers.iteritems():
1197
            pass
1198
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
1199
    def test_registered_methods(self):
1200
        """Test that known methods are registered to the correct object."""
1201
        self.assertEqual(
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1202
            smart.request.request_handlers.get('Branch.get_config_file'),
1203
            smart.branch.SmartServerBranchGetConfigFile)
1204
        self.assertEqual(
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1205
            smart.request.request_handlers.get('Branch.get_parent'),
1206
            smart.branch.SmartServerBranchGetParent)
1207
        self.assertEqual(
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1208
            smart.request.request_handlers.get('Branch.lock_write'),
1209
            smart.branch.SmartServerBranchRequestLockWrite)
1210
        self.assertEqual(
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1211
            smart.request.request_handlers.get('Branch.last_revision_info'),
1212
            smart.branch.SmartServerBranchRequestLastRevisionInfo)
1213
        self.assertEqual(
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
1214
            smart.request.request_handlers.get('Branch.revision_history'),
1215
            smart.branch.SmartServerRequestRevisionHistory)
1216
        self.assertEqual(
2018.5.77 by Wouter van Heyst
Fix typo in request_handlers registration of Branch.set_last_revision, and test that registration
1217
            smart.request.request_handlers.get('Branch.set_last_revision'),
1218
            smart.branch.SmartServerBranchRequestSetLastRevision)
1219
        self.assertEqual(
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1220
            smart.request.request_handlers.get('Branch.set_last_revision_info'),
1221
            smart.branch.SmartServerBranchRequestSetLastRevisionInfo)
1222
        self.assertEqual(
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1223
            smart.request.request_handlers.get('Branch.unlock'),
1224
            smart.branch.SmartServerBranchRequestUnlock)
1225
        self.assertEqual(
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
1226
            smart.request.request_handlers.get('BzrDir.find_repository'),
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
1227
            smart.bzrdir.SmartServerRequestFindRepositoryV1)
1228
        self.assertEqual(
1229
            smart.request.request_handlers.get('BzrDir.find_repositoryV2'),
1230
            smart.bzrdir.SmartServerRequestFindRepositoryV2)
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
1231
        self.assertEqual(
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
1232
            smart.request.request_handlers.get('BzrDirFormat.initialize'),
1233
            smart.bzrdir.SmartServerRequestInitializeBzrDir)
1234
        self.assertEqual(
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
1235
            smart.request.request_handlers.get('BzrDir.cloning_metadir'),
1236
            smart.bzrdir.SmartServerBzrDirRequestCloningMetaDir)
1237
        self.assertEqual(
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
1238
            smart.request.request_handlers.get('BzrDir.open_branch'),
1239
            smart.bzrdir.SmartServerRequestOpenBranch)
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
1240
        self.assertEqual(
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1241
            smart.request.request_handlers.get('PackRepository.autopack'),
1242
            smart.packrepository.SmartServerPackRepositoryAutopack)
1243
        self.assertEqual(
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1244
            smart.request.request_handlers.get('Repository.gather_stats'),
1245
            smart.repository.SmartServerRepositoryGatherStats)
1246
        self.assertEqual(
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
1247
            smart.request.request_handlers.get('Repository.get_parent_map'),
1248
            smart.repository.SmartServerRepositoryGetParentMap)
1249
        self.assertEqual(
2535.3.69 by Andrew Bennetts
Add check for Repository.stream_knit_data_for_revisions to TestHandlers.test_registered_methods.
1250
            smart.request.request_handlers.get(
1251
                'Repository.get_revision_graph'),
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1252
            smart.repository.SmartServerRepositoryGetRevisionGraph)
1253
        self.assertEqual(
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
1254
            smart.request.request_handlers.get('Repository.has_revision'),
1255
            smart.repository.SmartServerRequestHasRevision)
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1256
        self.assertEqual(
1257
            smart.request.request_handlers.get('Repository.is_shared'),
1258
            smart.repository.SmartServerRepositoryIsShared)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1259
        self.assertEqual(
1260
            smart.request.request_handlers.get('Repository.lock_write'),
1261
            smart.repository.SmartServerRepositoryLockWrite)
1262
        self.assertEqual(
4060.1.5 by Robert Collins
Verb change name requested by Andrew.
1263
            smart.request.request_handlers.get('Repository.get_stream'),
1264
            smart.repository.SmartServerRepositoryGetStream)
4060.1.4 by Robert Collins
Streaming fetch from remote servers.
1265
        self.assertEqual(
2535.3.69 by Andrew Bennetts
Add check for Repository.stream_knit_data_for_revisions to TestHandlers.test_registered_methods.
1266
            smart.request.request_handlers.get('Repository.tarball'),
1267
            smart.repository.SmartServerRepositoryTarball)
1268
        self.assertEqual(
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1269
            smart.request.request_handlers.get('Repository.unlock'),
1270
            smart.repository.SmartServerRepositoryUnlock)
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
1271
        self.assertEqual(
1272
            smart.request.request_handlers.get('Transport.is_readonly'),
1273
            smart.request.SmartServerIsReadonly)