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