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