/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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
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 (
2694.5.4 by Jelmer Vernooij
Move bzrlib.util.bencode to bzrlib._bencode_py.
32
    bencode,
2692.1.2 by Andrew Bennetts
Merge from bzr.dev.
33
    bzrdir,
34
    errors,
35
    pack,
36
    smart,
37
    tests,
38
    urlutils,
4634.19.1 by Robert Collins
Combine adjacent substreams of the same type in bzrlib.smart.repository._byte_stream_to_stream.
39
    versionedfile,
2692.1.2 by Andrew Bennetts
Merge from bzr.dev.
40
    )
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
41
from bzrlib.branch import Branch, BranchReferenceFormat
2692.1.22 by Andrew Bennetts
Reinstate imports needed to run test_smart alone.
42
import bzrlib.smart.branch
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
43
import bzrlib.smart.bzrdir, bzrlib.smart.bzrdir as smart_dir
44
import bzrlib.smart.packrepository
2692.1.22 by Andrew Bennetts
Reinstate imports needed to run test_smart alone.
45
import bzrlib.smart.repository
4760.2.5 by Andrew Bennetts
Add some more tests.
46
import bzrlib.smart.vfs
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
47
from bzrlib.smart.request import (
48
    FailedSmartServerResponse,
49
    SmartServerRequest,
50
    SmartServerResponse,
51
    SuccessfulSmartServerResponse,
52
    )
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
53
from bzrlib.tests import (
54
    split_suite_by_re,
55
    )
4634.47.4 by Andrew Bennetts
Make more of bzrlib/tests/test_smart.py use MemoryTransport.
56
from bzrlib.transport import chroot, get_transport, local, memory
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
4084.5.1 by Robert Collins
Bulk update all test adaptation into a single approach, using multiply_tests rather than test adapters.
63
    scenarios = [
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
64
        ("find_repository", {
65
            "_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV1}),
66
        ("find_repositoryV2", {
67
            "_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV2}),
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
68
        ("find_repositoryV3", {
69
            "_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV3}),
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
70
        ]
71
    to_adapt, result = split_suite_by_re(standard_tests,
72
        "TestSmartServerRequestFindRepository")
73
    v2_only, v1_and_2 = split_suite_by_re(to_adapt,
74
        "_v2")
4084.5.1 by Robert Collins
Bulk update all test adaptation into a single approach, using multiply_tests rather than test adapters.
75
    tests.multiply_tests(v1_and_2, scenarios, result)
76
    # The first scenario is only applicable to v1 protocols, it is deleted
77
    # since.
78
    tests.multiply_tests(v2_only, scenarios[1:], result)
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
79
    return result
80
81
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
82
class TestCaseWithChrootedTransport(tests.TestCaseWithTransport):
83
84
    def setUp(self):
4634.47.4 by Andrew Bennetts
Make more of bzrlib/tests/test_smart.py use MemoryTransport.
85
        self.vfs_transport_factory = memory.MemoryServer
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
86
        tests.TestCaseWithTransport.setUp(self)
87
        self._chroot_server = None
88
89
    def get_transport(self, relpath=None):
90
        if self._chroot_server is None:
91
            backing_transport = tests.TestCaseWithTransport.get_transport(self)
92
            self._chroot_server = chroot.ChrootServer(backing_transport)
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
93
            self.start_server(self._chroot_server)
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
94
        t = get_transport(self._chroot_server.get_url())
95
        if relpath is not None:
96
            t = t.clone(relpath)
97
        return t
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
98
99
4634.47.4 by Andrew Bennetts
Make more of bzrlib/tests/test_smart.py use MemoryTransport.
100
class TestCaseWithSmartMedium(tests.TestCaseWithMemoryTransport):
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
101
102
    def setUp(self):
103
        super(TestCaseWithSmartMedium, self).setUp()
104
        # We're allowed to set  the transport class here, so that we don't use
105
        # the default or a parameterized class, but rather use the
106
        # TestCaseWithTransport infrastructure to set up a smart server and
107
        # transport.
3245.4.28 by Andrew Bennetts
Remove another XXX, and include test ID in smart server thread names.
108
        self.transport_server = self.make_transport_server
109
110
    def make_transport_server(self):
111
        return smart.server.SmartTCPServer_for_testing('-' + self.id())
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
112
113
    def get_smart_medium(self):
114
        """Get a smart medium to use in tests."""
115
        return self.get_transport().get_smart_medium()
116
117
4634.19.1 by Robert Collins
Combine adjacent substreams of the same type in bzrlib.smart.repository._byte_stream_to_stream.
118
class TestByteStreamToStream(tests.TestCase):
119
120
    def test_repeated_substreams_same_kind_are_one_stream(self):
121
        # Make a stream - an iterable of bytestrings.
122
        stream = [('text', [versionedfile.FulltextContentFactory(('k1',), None,
123
            None, 'foo')]),('text', [
124
            versionedfile.FulltextContentFactory(('k2',), None, None, 'bar')])]
125
        fmt = bzrdir.format_registry.get('pack-0.92')().repository_format
126
        bytes = smart.repository._stream_to_byte_stream(stream, fmt)
127
        streams = []
128
        # Iterate the resulting iterable; checking that we get only one stream
129
        # out.
130
        fmt, stream = smart.repository._byte_stream_to_stream(bytes)
131
        for kind, substream in stream:
132
            streams.append((kind, list(substream)))
133
        self.assertLength(1, streams)
134
        self.assertLength(2, streams[0][1])
135
136
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
137
class TestSmartServerResponse(tests.TestCase):
138
139
    def test__eq__(self):
140
        self.assertEqual(SmartServerResponse(('ok', )),
141
            SmartServerResponse(('ok', )))
142
        self.assertEqual(SmartServerResponse(('ok', ), 'body'),
143
            SmartServerResponse(('ok', ), 'body'))
144
        self.assertNotEqual(SmartServerResponse(('ok', )),
145
            SmartServerResponse(('notok', )))
146
        self.assertNotEqual(SmartServerResponse(('ok', ), 'body'),
147
            SmartServerResponse(('ok', )))
2018.5.41 by Robert Collins
Fix SmartServerResponse.__eq__ to handle None.
148
        self.assertNotEqual(None,
149
            SmartServerResponse(('ok', )))
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
150
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
151
    def test__str__(self):
152
        """SmartServerResponses can be stringified."""
153
        self.assertEqual(
3691.2.6 by Martin Pool
Disable RemoteBranch stacking, but get get_stacked_on_url working, and passing back exceptions
154
            "<SuccessfulSmartServerResponse args=('args',) body='body'>",
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
155
            str(SuccessfulSmartServerResponse(('args',), 'body')))
156
        self.assertEqual(
3691.2.6 by Martin Pool
Disable RemoteBranch stacking, but get get_stacked_on_url working, and passing back exceptions
157
            "<FailedSmartServerResponse args=('args',) body='body'>",
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
158
            str(FailedSmartServerResponse(('args',), 'body')))
159
160
161
class TestSmartServerRequest(tests.TestCaseWithMemoryTransport):
162
163
    def test_translate_client_path(self):
164
        transport = self.get_transport()
165
        request = SmartServerRequest(transport, 'foo/')
166
        self.assertEqual('./', request.translate_client_path('foo/'))
167
        self.assertRaises(
168
            errors.InvalidURLJoin, request.translate_client_path, 'foo/..')
169
        self.assertRaises(
170
            errors.PathNotChild, request.translate_client_path, '/')
171
        self.assertRaises(
172
            errors.PathNotChild, request.translate_client_path, 'bar/')
173
        self.assertEqual('./baz', request.translate_client_path('foo/baz'))
4760.2.2 by Michael Hudson
test
174
        e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'.encode('utf-8')
175
        self.assertEqual('./' + urlutils.escape(e_acute),
176
                         request.translate_client_path('foo/' + e_acute))
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
177
4760.2.5 by Andrew Bennetts
Add some more tests.
178
    def test_translate_client_path_vfs(self):
179
        """VfsRequests receive escaped paths rather than raw UTF-8."""
180
        transport = self.get_transport()
181
        request = smart.vfs.VfsRequest(transport, 'foo/')
182
        e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'.encode('utf-8')
183
        escaped = urlutils.escape('foo/' + e_acute)
184
        self.assertEqual('./' + urlutils.escape(e_acute),
185
                         request.translate_client_path(escaped))
186
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
187
    def test_transport_from_client_path(self):
188
        transport = self.get_transport()
189
        request = SmartServerRequest(transport, 'foo/')
190
        self.assertEqual(
191
            transport.base,
192
            request.transport_from_client_path('foo/').base)
193
194
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
195
class TestSmartServerBzrDirRequestCloningMetaDir(
196
    tests.TestCaseWithMemoryTransport):
197
    """Tests for BzrDir.cloning_metadir."""
198
199
    def test_cloning_metadir(self):
200
        """When there is a bzrdir present, the call succeeds."""
201
        backing = self.get_transport()
202
        dir = self.make_bzrdir('.')
203
        local_result = dir.cloning_metadir()
204
        request_class = smart_dir.SmartServerBzrDirRequestCloningMetaDir
205
        request = request_class(backing)
206
        expected = SuccessfulSmartServerResponse(
207
            (local_result.network_name(),
208
            local_result.repository_format.network_name(),
4084.2.2 by Robert Collins
Review feedback.
209
            ('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).
210
        self.assertEqual(expected, request.execute('', 'False'))
211
212
    def test_cloning_metadir_reference(self):
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
213
        """The request fails when bzrdir contains a branch reference."""
4070.7.4 by Andrew Bennetts
Deal with branch references better in BzrDir.cloning_metadir RPC (changes protocol).
214
        backing = self.get_transport()
215
        referenced_branch = self.make_branch('referenced')
216
        dir = self.make_bzrdir('.')
217
        local_result = dir.cloning_metadir()
218
        reference = BranchReferenceFormat().initialize(dir, referenced_branch)
219
        reference_url = BranchReferenceFormat().get_reference(dir)
220
        # The server shouldn't try to follow the branch reference, so it's fine
221
        # if the referenced branch isn't reachable.
222
        backing.rename('referenced', 'moved')
223
        request_class = smart_dir.SmartServerBzrDirRequestCloningMetaDir
224
        request = request_class(backing)
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
225
        expected = FailedSmartServerResponse(('BranchReference',))
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
226
        self.assertEqual(expected, request.execute('', 'False'))
227
228
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
229
class TestSmartServerRequestCreateRepository(tests.TestCaseWithMemoryTransport):
230
    """Tests for BzrDir.create_repository."""
231
232
    def test_makes_repository(self):
233
        """When there is a bzrdir present, the call succeeds."""
234
        backing = self.get_transport()
235
        self.make_bzrdir('.')
236
        request_class = bzrlib.smart.bzrdir.SmartServerRequestCreateRepository
237
        request = request_class(backing)
4606.3.1 by Robert Collins
Make test_smart tests more stable when the default format changes.
238
        reference_bzrdir_format = bzrdir.format_registry.get('pack-0.92')()
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
239
        reference_format = reference_bzrdir_format.repository_format
240
        network_name = reference_format.network_name()
241
        expected = SuccessfulSmartServerResponse(
242
            ('ok', 'no', 'no', 'no', network_name))
243
        self.assertEqual(expected, request.execute('', network_name, 'True'))
244
245
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
246
class TestSmartServerRequestFindRepository(tests.TestCaseWithMemoryTransport):
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
247
    """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.
248
249
    def test_no_repository(self):
250
        """When there is no repository to be found, ('norepository', ) is returned."""
251
        backing = self.get_transport()
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
252
        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.
253
        self.make_bzrdir('.')
254
        self.assertEqual(SmartServerResponse(('norepository', )),
2692.1.19 by Andrew Bennetts
Tweak for consistency suggested by John's review.
255
            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.
256
257
    def test_nonshared_repository(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
258
        # nonshared repositorys only allow 'find' to return a handle when the
259
        # 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.
260
        # the repository is at.
261
        backing = self.get_transport()
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
262
        request = self._request_class(backing)
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
263
        result = self._make_repository_and_result()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
264
        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.
265
        self.make_bzrdir('subdir')
266
        self.assertEqual(SmartServerResponse(('norepository', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
267
            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.
268
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
269
    def _make_repository_and_result(self, shared=False, format=None):
270
        """Convenience function to setup a repository.
271
272
        :result: The SmartServerResponse to expect when opening it.
273
        """
274
        repo = self.make_repository('.', shared=shared, format=format)
275
        if repo.supports_rich_root():
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
276
            rich_root = 'yes'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
277
        else:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
278
            rich_root = 'no'
2018.5.138 by Robert Collins
Merge bzr.dev.
279
        if repo._format.supports_tree_reference:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
280
            subtrees = 'yes'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
281
        else:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
282
            subtrees = 'no'
4606.3.1 by Robert Collins
Make test_smart tests more stable when the default format changes.
283
        if repo._format.supports_external_lookups:
284
            external = 'yes'
285
        else:
286
            external = 'no'
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
287
        if (smart.bzrdir.SmartServerRequestFindRepositoryV3 ==
288
            self._request_class):
289
            return SuccessfulSmartServerResponse(
4606.3.1 by Robert Collins
Make test_smart tests more stable when the default format changes.
290
                ('ok', '', rich_root, subtrees, external,
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
291
                 repo._format.network_name()))
292
        elif (smart.bzrdir.SmartServerRequestFindRepositoryV2 ==
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
293
            self._request_class):
294
            # All tests so far are on formats, and for non-external
295
            # repositories.
296
            return SuccessfulSmartServerResponse(
4606.3.1 by Robert Collins
Make test_smart tests more stable when the default format changes.
297
                ('ok', '', rich_root, subtrees, external))
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
298
        else:
299
            return SuccessfulSmartServerResponse(('ok', '', rich_root, subtrees))
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
300
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
301
    def test_shared_repository(self):
302
        """When there is a shared repository, we get 'ok', 'relpath-to-repo'."""
303
        backing = self.get_transport()
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
304
        request = self._request_class(backing)
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
305
        result = self._make_repository_and_result(shared=True)
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
306
        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.
307
        self.make_bzrdir('subdir')
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
308
        result2 = SmartServerResponse(result.args[0:1] + ('..', ) + result.args[2:])
309
        self.assertEqual(result2,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
310
            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.
311
        self.make_bzrdir('subdir/deeper')
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
312
        result3 = SmartServerResponse(result.args[0:1] + ('../..', ) + result.args[2:])
313
        self.assertEqual(result3,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
314
            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.
315
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
316
    def test_rich_root_and_subtree_encoding(self):
317
        """Test for the format attributes for rich root and subtree support."""
318
        backing = self.get_transport()
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
319
        request = self._request_class(backing)
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
320
        result = self._make_repository_and_result(format='dirstate-with-subtree')
321
        # check the test will be valid
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
322
        self.assertEqual('yes', result.args[2])
323
        self.assertEqual('yes', result.args[3])
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
324
        self.assertEqual(result, request.execute(''))
325
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
326
    def test_supports_external_lookups_no_v2(self):
327
        """Test for the supports_external_lookups attribute."""
328
        backing = self.get_transport()
329
        request = self._request_class(backing)
330
        result = self._make_repository_and_result(format='dirstate-with-subtree')
331
        # check the test will be valid
332
        self.assertEqual('no', result.args[4])
2692.1.24 by Andrew Bennetts
Merge from bzr.dev.
333
        self.assertEqual(result, request.execute(''))
334
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
335
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
336
class TestSmartServerBzrDirRequestGetConfigFile(
337
    tests.TestCaseWithMemoryTransport):
338
    """Tests for BzrDir.get_config_file."""
339
340
    def test_present(self):
341
        backing = self.get_transport()
342
        dir = self.make_bzrdir('.')
343
        dir.get_config().set_default_stack_on("/")
344
        local_result = dir._get_config()._get_config_file().read()
345
        request_class = smart_dir.SmartServerBzrDirRequestConfigFile
346
        request = request_class(backing)
347
        expected = SuccessfulSmartServerResponse((), local_result)
348
        self.assertEqual(expected, request.execute(''))
349
350
    def test_missing(self):
351
        backing = self.get_transport()
352
        dir = self.make_bzrdir('.')
353
        request_class = smart_dir.SmartServerBzrDirRequestConfigFile
354
        request = request_class(backing)
355
        expected = SuccessfulSmartServerResponse((), '')
356
        self.assertEqual(expected, request.execute(''))
357
358
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
359
class TestSmartServerRequestInitializeBzrDir(tests.TestCaseWithMemoryTransport):
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
360
361
    def test_empty_dir(self):
362
        """Initializing an empty dir should succeed and do it."""
363
        backing = self.get_transport()
364
        request = smart.bzrdir.SmartServerRequestInitializeBzrDir(backing)
365
        self.assertEqual(SmartServerResponse(('ok', )),
2692.1.20 by Andrew Bennetts
Tweak for consistency suggested by John's review.
366
            request.execute(''))
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
367
        made_dir = bzrdir.BzrDir.open_from_transport(backing)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
368
        # 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 :).
369
        # default formart.
370
        self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
371
        self.assertRaises(errors.NotBranchError, made_dir.open_branch)
372
        self.assertRaises(errors.NoRepositoryPresent, made_dir.open_repository)
373
374
    def test_missing_dir(self):
375
        """Initializing a missing directory should fail like the bzrdir api."""
376
        backing = self.get_transport()
377
        request = smart.bzrdir.SmartServerRequestInitializeBzrDir(backing)
378
        self.assertRaises(errors.NoSuchFile,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
379
            request.execute, 'subdir')
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
380
381
    def test_initialized_dir(self):
382
        """Initializing an extant bzrdir should fail like the bzrdir api."""
383
        backing = self.get_transport()
384
        request = smart.bzrdir.SmartServerRequestInitializeBzrDir(backing)
385
        self.make_bzrdir('subdir')
386
        self.assertRaises(errors.FileExists,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
387
            request.execute, 'subdir')
388
389
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
390
class TestSmartServerRequestBzrDirInitializeEx(tests.TestCaseWithMemoryTransport):
4436.1.1 by Andrew Bennetts
Rename BzrDirFormat.initialize_ex verb to BzrDirFormat.initialize_ex_1.16.
391
    """Basic tests for BzrDir.initialize_ex_1.16 in the smart server.
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
392
4294.2.10 by Robert Collins
Review feedback.
393
    The main unit tests in test_bzrdir exercise the API comprehensively.
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
394
    """
395
396
    def test_empty_dir(self):
397
        """Initializing an empty dir should succeed and do it."""
398
        backing = self.get_transport()
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
399
        name = self.make_bzrdir('reference')._format.network_name()
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
400
        request = smart.bzrdir.SmartServerRequestBzrDirInitializeEx(backing)
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
401
        self.assertEqual(SmartServerResponse(('', '', '', '', '', '', name,
4307.2.2 by Robert Collins
Lock repositories created by BzrDirFormat.initialize_on_transport_ex.
402
            'False', '', '', '')),
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
403
            request.execute(name, '', 'True', 'False', 'False', '', '', '', '',
404
            'False'))
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
405
        made_dir = bzrdir.BzrDir.open_from_transport(backing)
406
        # no branch, tree or repository is expected with the current
4294.2.10 by Robert Collins
Review feedback.
407
        # default format.
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
408
        self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
409
        self.assertRaises(errors.NotBranchError, made_dir.open_branch)
410
        self.assertRaises(errors.NoRepositoryPresent, made_dir.open_repository)
411
412
    def test_missing_dir(self):
413
        """Initializing a missing directory should fail like the bzrdir api."""
414
        backing = self.get_transport()
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
415
        name = self.make_bzrdir('reference')._format.network_name()
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
416
        request = smart.bzrdir.SmartServerRequestBzrDirInitializeEx(backing)
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
417
        self.assertRaises(errors.NoSuchFile, request.execute, name,
418
            'subdir/dir', 'False', 'False', 'False', '', '', '', '', 'False')
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
419
420
    def test_initialized_dir(self):
4416.3.4 by Jonathan Lange
Fix a typo.
421
        """Initializing an extant directory should fail like the bzrdir api."""
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
422
        backing = self.get_transport()
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
423
        name = self.make_bzrdir('reference')._format.network_name()
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
424
        request = smart.bzrdir.SmartServerRequestBzrDirInitializeEx(backing)
425
        self.make_bzrdir('subdir')
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
426
        self.assertRaises(errors.FileExists, request.execute, name, 'subdir',
427
            'False', 'False', 'False', '', '', '', '', 'False')
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
428
4634.47.5 by Andrew Bennetts
Add tests, and fix BzrDirMeta1.has_workingtree which was failing if the local transport is decorated with a ChrootTransport or similar.
429
430
class TestSmartServerRequestOpenBzrDir(tests.TestCaseWithMemoryTransport):
431
    
432
    def test_no_directory(self):
433
        backing = self.get_transport()
434
        request = smart.bzrdir.SmartServerRequestOpenBzrDir(backing)
435
        self.assertEqual(SmartServerResponse(('no', )),
436
            request.execute('does-not-exist'))
437
438
    def test_empty_directory(self):
439
        backing = self.get_transport()
440
        backing.mkdir('empty')
441
        request = smart.bzrdir.SmartServerRequestOpenBzrDir(backing)
442
        self.assertEqual(SmartServerResponse(('no', )),
443
            request.execute('empty'))
444
445
    def test_outside_root_client_path(self):
446
        backing = self.get_transport()
447
        request = smart.bzrdir.SmartServerRequestOpenBzrDir(backing,
448
            root_client_path='root')
449
        self.assertEqual(SmartServerResponse(('no', )),
450
            request.execute('not-root'))
451
452
    
453
class TestSmartServerRequestOpenBzrDir_2_1(tests.TestCaseWithMemoryTransport):
454
    
455
    def test_no_directory(self):
456
        backing = self.get_transport()
457
        request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing)
458
        self.assertEqual(SmartServerResponse(('no', )),
459
            request.execute('does-not-exist'))
460
461
    def test_empty_directory(self):
462
        backing = self.get_transport()
463
        backing.mkdir('empty')
464
        request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing)
465
        self.assertEqual(SmartServerResponse(('no', )),
466
            request.execute('empty'))
467
468
    def test_present_without_workingtree(self):
469
        backing = self.get_transport()
470
        request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing)
471
        self.make_bzrdir('.')
472
        self.assertEqual(SmartServerResponse(('yes', 'no')),
473
            request.execute(''))
474
4634.47.6 by Andrew Bennetts
Give 'no' response for paths outside the root_client_path.
475
    def test_outside_root_client_path(self):
4634.47.5 by Andrew Bennetts
Add tests, and fix BzrDirMeta1.has_workingtree which was failing if the local transport is decorated with a ChrootTransport or similar.
476
        backing = self.get_transport()
477
        request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing,
478
            root_client_path='root')
4634.47.6 by Andrew Bennetts
Give 'no' response for paths outside the root_client_path.
479
        self.assertEqual(SmartServerResponse(('no',)),
480
            request.execute('not-root'))
4634.47.5 by Andrew Bennetts
Add tests, and fix BzrDirMeta1.has_workingtree which was failing if the local transport is decorated with a ChrootTransport or similar.
481
482
    
483
class TestSmartServerRequestOpenBzrDir_2_1_disk(TestCaseWithChrootedTransport):
484
485
    def test_present_with_workingtree(self):
486
        self.vfs_transport_factory = local.LocalURLServer
487
        backing = self.get_transport()
488
        request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing)
489
        bd = self.make_bzrdir('.')
490
        bd.create_repository()
491
        bd.create_branch()
492
        bd.create_workingtree()
493
        self.assertEqual(SmartServerResponse(('yes', 'yes')),
494
            request.execute(''))
495
496
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
497
class TestSmartServerRequestOpenBranch(TestCaseWithChrootedTransport):
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
498
499
    def test_no_branch(self):
500
        """When there is no branch, ('nobranch', ) is returned."""
501
        backing = self.get_transport()
502
        request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
503
        self.make_bzrdir('.')
504
        self.assertEqual(SmartServerResponse(('nobranch', )),
2692.1.20 by Andrew Bennetts
Tweak for consistency suggested by John's review.
505
            request.execute(''))
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
506
507
    def test_branch(self):
508
        """When there is a branch, 'ok' is returned."""
509
        backing = self.get_transport()
510
        request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
511
        self.make_branch('.')
512
        self.assertEqual(SmartServerResponse(('ok', '')),
2692.1.20 by Andrew Bennetts
Tweak for consistency suggested by John's review.
513
            request.execute(''))
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
514
515
    def test_branch_reference(self):
516
        """When there is a branch reference, the reference URL is returned."""
4634.47.4 by Andrew Bennetts
Make more of bzrlib/tests/test_smart.py use MemoryTransport.
517
        self.vfs_transport_factory = local.LocalURLServer
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
518
        backing = self.get_transport()
519
        request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
520
        branch = self.make_branch('branch')
521
        checkout = branch.create_checkout('reference',lightweight=True)
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
522
        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.
523
        self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
524
        self.assertEqual(SmartServerResponse(('ok', reference_url)),
2692.1.20 by Andrew Bennetts
Tweak for consistency suggested by John's review.
525
            request.execute('reference'))
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
526
527
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.
528
class TestSmartServerRequestOpenBranchV2(TestCaseWithChrootedTransport):
529
530
    def test_no_branch(self):
531
        """When there is no branch, ('nobranch', ) is returned."""
532
        backing = self.get_transport()
533
        self.make_bzrdir('.')
534
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
535
        self.assertEqual(SmartServerResponse(('nobranch', )),
536
            request.execute(''))
537
538
    def test_branch(self):
539
        """When there is a branch, 'ok' is returned."""
540
        backing = self.get_transport()
541
        expected = self.make_branch('.')._format.network_name()
542
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
543
        self.assertEqual(SuccessfulSmartServerResponse(('branch', expected)),
544
            request.execute(''))
545
546
    def test_branch_reference(self):
547
        """When there is a branch reference, the reference URL is returned."""
4634.47.4 by Andrew Bennetts
Make more of bzrlib/tests/test_smart.py use MemoryTransport.
548
        self.vfs_transport_factory = local.LocalURLServer
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.
549
        backing = self.get_transport()
550
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
551
        branch = self.make_branch('branch')
552
        checkout = branch.create_checkout('reference',lightweight=True)
553
        reference_url = BranchReferenceFormat().get_reference(checkout.bzrdir)
554
        self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
555
        self.assertEqual(SuccessfulSmartServerResponse(('ref', reference_url)),
556
            request.execute('reference'))
557
4160.2.1 by Andrew Bennetts
Failing test for BzrDir.open_branchV2 RPC not opening stacked-on branch.
558
    def test_stacked_branch(self):
559
        """Opening a stacked branch does not open the stacked-on branch."""
560
        trunk = self.make_branch('trunk')
4599.4.30 by Robert Collins
Remove hard coded format in test_smart's test_stacked_branch now the default format stacks.
561
        feature = self.make_branch('feature')
4160.2.1 by Andrew Bennetts
Failing test for BzrDir.open_branchV2 RPC not opening stacked-on branch.
562
        feature.set_stacked_on_url(trunk.base)
563
        opened_branches = []
564
        Branch.hooks.install_named_hook('open', opened_branches.append, None)
565
        backing = self.get_transport()
566
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
4160.2.4 by Andrew Bennetts
Use BzrDir pre_open hook to jail request code from accessing transports other than the backing transport.
567
        request.setup_jail()
568
        try:
569
            response = request.execute('feature')
570
        finally:
571
            request.teardown_jail()
4160.2.1 by Andrew Bennetts
Failing test for BzrDir.open_branchV2 RPC not opening stacked-on branch.
572
        expected_format = feature._format.network_name()
573
        self.assertEqual(
574
            SuccessfulSmartServerResponse(('branch', expected_format)),
575
            response)
576
        self.assertLength(1, opened_branches)
577
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.
578
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
579
class TestSmartServerRequestRevisionHistory(tests.TestCaseWithMemoryTransport):
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
580
581
    def test_empty(self):
582
        """For an empty branch, the body is empty."""
583
        backing = self.get_transport()
584
        request = smart.branch.SmartServerRequestRevisionHistory(backing)
585
        self.make_branch('.')
586
        self.assertEqual(SmartServerResponse(('ok', ), ''),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
587
            request.execute(''))
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
588
589
    def test_not_empty(self):
590
        """For a non-empty branch, the body is empty."""
591
        backing = self.get_transport()
592
        request = smart.branch.SmartServerRequestRevisionHistory(backing)
593
        tree = self.make_branch_and_memory_tree('.')
594
        tree.lock_write()
595
        tree.add('')
596
        r1 = tree.commit('1st commit')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
597
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
598
        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.
599
        self.assertEqual(
600
            SmartServerResponse(('ok', ), ('\x00'.join([r1, r2]))),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
601
            request.execute(''))
602
603
604
class TestSmartServerBranchRequest(tests.TestCaseWithMemoryTransport):
2018.5.49 by Wouter van Heyst
Refactor SmartServerBranchRequest out from SmartServerRequestRevisionHistory to
605
606
    def test_no_branch(self):
607
        """When there is a bzrdir and no branch, NotBranchError is raised."""
608
        backing = self.get_transport()
609
        request = smart.branch.SmartServerBranchRequest(backing)
610
        self.make_bzrdir('.')
611
        self.assertRaises(errors.NotBranchError,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
612
            request.execute, '')
2018.5.49 by Wouter van Heyst
Refactor SmartServerBranchRequest out from SmartServerRequestRevisionHistory to
613
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
614
    def test_branch_reference(self):
615
        """When there is a branch reference, NotBranchError is raised."""
616
        backing = self.get_transport()
2018.5.49 by Wouter van Heyst
Refactor SmartServerBranchRequest out from SmartServerRequestRevisionHistory to
617
        request = smart.branch.SmartServerBranchRequest(backing)
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
618
        branch = self.make_branch('branch')
619
        checkout = branch.create_checkout('reference',lightweight=True)
620
        self.assertRaises(errors.NotBranchError,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
621
            request.execute, 'checkout')
622
623
624
class TestSmartServerBranchRequestLastRevisionInfo(tests.TestCaseWithMemoryTransport):
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
625
626
    def test_empty(self):
2018.5.170 by Andrew Bennetts
Use 'null:' instead of '' to mean NULL_REVISION on the wire.
627
        """For an empty branch, the result is ('ok', '0', 'null:')."""
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
628
        backing = self.get_transport()
629
        request = smart.branch.SmartServerBranchRequestLastRevisionInfo(backing)
630
        self.make_branch('.')
2018.5.170 by Andrew Bennetts
Use 'null:' instead of '' to mean NULL_REVISION on the wire.
631
        self.assertEqual(SmartServerResponse(('ok', '0', 'null:')),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
632
            request.execute(''))
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
633
634
    def test_not_empty(self):
635
        """For a non-empty branch, the result is ('ok', 'revno', 'revid')."""
636
        backing = self.get_transport()
637
        request = smart.branch.SmartServerBranchRequestLastRevisionInfo(backing)
638
        tree = self.make_branch_and_memory_tree('.')
639
        tree.lock_write()
640
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
641
        rev_id_utf8 = u'\xc8'.encode('utf-8')
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
642
        r1 = tree.commit('1st commit')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
643
        r2 = tree.commit('2nd commit', rev_id=rev_id_utf8)
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
644
        tree.unlock()
645
        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.
646
            SmartServerResponse(('ok', '2', rev_id_utf8)),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
647
            request.execute(''))
648
649
650
class TestSmartServerBranchRequestGetConfigFile(tests.TestCaseWithMemoryTransport):
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
651
652
    def test_default(self):
653
        """With no file, we get empty content."""
654
        backing = self.get_transport()
655
        request = smart.branch.SmartServerBranchGetConfigFile(backing)
656
        branch = self.make_branch('.')
657
        # there should be no file by default
658
        content = ''
659
        self.assertEqual(SmartServerResponse(('ok', ), content),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
660
            request.execute(''))
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
661
662
    def test_with_content(self):
663
        # SmartServerBranchGetConfigFile should return the content from
664
        # 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
665
        # perform more complex processing.
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
666
        backing = self.get_transport()
667
        request = smart.branch.SmartServerBranchGetConfigFile(backing)
668
        branch = self.make_branch('.')
3407.2.5 by Martin Pool
Deprecate LockableFiles.put_utf8
669
        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).
670
        self.assertEqual(SmartServerResponse(('ok', ), 'foo bar baz'),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
671
            request.execute(''))
672
673
4226.2.1 by Robert Collins
Set branch config options via a smart method.
674
class TestLockedBranch(tests.TestCaseWithMemoryTransport):
675
676
    def get_lock_tokens(self, branch):
677
        branch_token = branch.lock_write()
678
        repo_token = branch.repository.lock_write()
679
        branch.repository.unlock()
680
        return branch_token, repo_token
681
682
683
class TestSmartServerBranchRequestSetConfigOption(TestLockedBranch):
684
685
    def test_value_name(self):
686
        branch = self.make_branch('.')
687
        request = smart.branch.SmartServerBranchRequestSetConfigOption(
688
            branch.bzrdir.root_transport)
689
        branch_token, repo_token = self.get_lock_tokens(branch)
690
        config = branch._get_config()
691
        result = request.execute('', branch_token, repo_token, 'bar', 'foo',
692
            '')
693
        self.assertEqual(SuccessfulSmartServerResponse(()), result)
694
        self.assertEqual('bar', config.get_option('foo'))
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
695
        # Cleanup
696
        branch.unlock()
4226.2.1 by Robert Collins
Set branch config options via a smart method.
697
698
    def test_value_name_section(self):
699
        branch = self.make_branch('.')
700
        request = smart.branch.SmartServerBranchRequestSetConfigOption(
701
            branch.bzrdir.root_transport)
702
        branch_token, repo_token = self.get_lock_tokens(branch)
703
        config = branch._get_config()
704
        result = request.execute('', branch_token, repo_token, 'bar', 'foo',
705
            'gam')
706
        self.assertEqual(SuccessfulSmartServerResponse(()), result)
707
        self.assertEqual('bar', config.get_option('foo', 'gam'))
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
708
        # Cleanup
709
        branch.unlock()
4226.2.1 by Robert Collins
Set branch config options via a smart method.
710
711
4556.2.2 by Andrew Bennetts
Handle failures more gracefully.
712
class TestSmartServerBranchRequestSetTagsBytes(TestLockedBranch):
713
    # Only called when the branch format and tags match [yay factory
714
    # methods] so only need to test straight forward cases.
715
716
    def test_set_bytes(self):
717
        base_branch = self.make_branch('base')
718
        tag_bytes = base_branch._get_tags_bytes()
719
        # get_lock_tokens takes out a lock.
720
        branch_token, repo_token = self.get_lock_tokens(base_branch)
721
        request = smart.branch.SmartServerBranchSetTagsBytes(
722
            self.get_transport())
723
        response = request.execute('base', branch_token, repo_token)
724
        self.assertEqual(None, response)
725
        response = request.do_chunk(tag_bytes)
726
        self.assertEqual(None, response)
727
        response = request.do_end()
728
        self.assertEquals(
729
            SuccessfulSmartServerResponse(()), response)
730
        base_branch.unlock()
731
732
    def test_lock_failed(self):
733
        base_branch = self.make_branch('base')
734
        base_branch.lock_write()
735
        tag_bytes = base_branch._get_tags_bytes()
736
        request = smart.branch.SmartServerBranchSetTagsBytes(
737
            self.get_transport())
738
        self.assertRaises(errors.TokenMismatch, request.execute,
739
            'base', 'wrong token', 'wrong token')
740
        # The request handler will keep processing the message parts, so even
741
        # if the request fails immediately do_chunk and do_end are still
742
        # called.
743
        request.do_chunk(tag_bytes)
744
        request.do_end()
745
        base_branch.unlock()
746
747
748
4226.2.1 by Robert Collins
Set branch config options via a smart method.
749
class SetLastRevisionTestBase(TestLockedBranch):
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
750
    """Base test case for verbs that implement set_last_revision."""
751
752
    def setUp(self):
753
        tests.TestCaseWithMemoryTransport.setUp(self)
754
        backing_transport = self.get_transport()
755
        self.request = self.request_class(backing_transport)
756
        self.tree = self.make_branch_and_memory_tree('.')
757
758
    def lock_branch(self):
4226.2.1 by Robert Collins
Set branch config options via a smart method.
759
        return self.get_lock_tokens(self.tree.branch)
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
760
761
    def unlock_branch(self):
762
        self.tree.branch.unlock()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
763
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
764
    def set_last_revision(self, revision_id, revno):
765
        branch_token, repo_token = self.lock_branch()
766
        response = self._set_last_revision(
767
            revision_id, revno, branch_token, repo_token)
768
        self.unlock_branch()
769
        return response
770
771
    def assertRequestSucceeds(self, revision_id, revno):
772
        response = self.set_last_revision(revision_id, revno)
773
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)), response)
774
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
775
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
776
class TestSetLastRevisionVerbMixin(object):
777
    """Mixin test case for verbs that implement set_last_revision."""
778
779
    def test_set_null_to_null(self):
780
        """An empty branch can have its last revision set to 'null:'."""
781
        self.assertRequestSucceeds('null:', 0)
782
783
    def test_NoSuchRevision(self):
784
        """If the revision_id is not present, the verb returns NoSuchRevision.
785
        """
786
        revision_id = 'non-existent revision'
787
        self.assertEqual(
788
            FailedSmartServerResponse(('NoSuchRevision', revision_id)),
789
            self.set_last_revision(revision_id, 1))
790
791
    def make_tree_with_two_commits(self):
792
        self.tree.lock_write()
793
        self.tree.add('')
794
        rev_id_utf8 = u'\xc8'.encode('utf-8')
795
        r1 = self.tree.commit('1st commit', rev_id=rev_id_utf8)
796
        r2 = self.tree.commit('2nd commit', rev_id='rev-2')
797
        self.tree.unlock()
798
799
    def test_branch_last_revision_info_is_updated(self):
800
        """A branch's tip can be set to a revision that is present in its
801
        repository.
802
        """
803
        # Make a branch with an empty revision history, but two revisions in
804
        # its repository.
805
        self.make_tree_with_two_commits()
806
        rev_id_utf8 = u'\xc8'.encode('utf-8')
807
        self.tree.branch.set_revision_history([])
808
        self.assertEqual(
809
            (0, 'null:'), self.tree.branch.last_revision_info())
810
        # We can update the branch to a revision that is present in the
811
        # repository.
812
        self.assertRequestSucceeds(rev_id_utf8, 1)
813
        self.assertEqual(
814
            (1, rev_id_utf8), self.tree.branch.last_revision_info())
815
816
    def test_branch_last_revision_info_rewind(self):
817
        """A branch's tip can be set to a revision that is an ancestor of the
818
        current tip.
819
        """
820
        self.make_tree_with_two_commits()
821
        rev_id_utf8 = u'\xc8'.encode('utf-8')
822
        self.assertEqual(
823
            (2, 'rev-2'), self.tree.branch.last_revision_info())
824
        self.assertRequestSucceeds(rev_id_utf8, 1)
825
        self.assertEqual(
826
            (1, rev_id_utf8), self.tree.branch.last_revision_info())
827
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
828
    def test_TipChangeRejected(self):
829
        """If a pre_change_branch_tip hook raises TipChangeRejected, the verb
830
        returns TipChangeRejected.
831
        """
832
        rejection_message = u'rejection message\N{INTERROBANG}'
833
        def hook_that_rejects(params):
834
            raise errors.TipChangeRejected(rejection_message)
835
        Branch.hooks.install_named_hook(
836
            'pre_change_branch_tip', hook_that_rejects, None)
837
        self.assertEqual(
838
            FailedSmartServerResponse(
839
                ('TipChangeRejected', rejection_message.encode('utf-8'))),
840
            self.set_last_revision('null:', 0))
841
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
842
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
843
class TestSmartServerBranchRequestSetLastRevision(
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
844
        SetLastRevisionTestBase, TestSetLastRevisionVerbMixin):
845
    """Tests for Branch.set_last_revision verb."""
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
846
847
    request_class = smart.branch.SmartServerBranchRequestSetLastRevision
848
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
849
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
850
        return self.request.execute(
851
            '', branch_token, repo_token, revision_id)
852
853
854
class TestSmartServerBranchRequestSetLastRevisionInfo(
855
        SetLastRevisionTestBase, TestSetLastRevisionVerbMixin):
856
    """Tests for Branch.set_last_revision_info verb."""
857
858
    request_class = smart.branch.SmartServerBranchRequestSetLastRevisionInfo
859
860
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
861
        return self.request.execute(
862
            '', branch_token, repo_token, revno, revision_id)
863
864
    def test_NoSuchRevision(self):
865
        """Branch.set_last_revision_info does not have to return
866
        NoSuchRevision if the revision_id is absent.
867
        """
868
        raise tests.TestNotApplicable()
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
869
870
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.
871
class TestSmartServerBranchRequestSetLastRevisionEx(
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
872
        SetLastRevisionTestBase, TestSetLastRevisionVerbMixin):
873
    """Tests for Branch.set_last_revision_ex verb."""
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
874
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.
875
    request_class = smart.branch.SmartServerBranchRequestSetLastRevisionEx
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
876
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
877
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
878
        return self.request.execute(
879
            '', branch_token, repo_token, revision_id, 0, 0)
880
881
    def assertRequestSucceeds(self, revision_id, revno):
882
        response = self.set_last_revision(revision_id, revno)
883
        self.assertEqual(
884
            SuccessfulSmartServerResponse(('ok', revno, revision_id)),
885
            response)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
886
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
887
    def test_branch_last_revision_info_rewind(self):
888
        """A branch's tip can be set to a revision that is an ancestor of the
889
        current tip, but only if allow_overwrite_descendant is passed.
890
        """
891
        self.make_tree_with_two_commits()
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
892
        rev_id_utf8 = u'\xc8'.encode('utf-8')
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
893
        self.assertEqual(
894
            (2, 'rev-2'), self.tree.branch.last_revision_info())
895
        # If allow_overwrite_descendant flag is 0, then trying to set the tip
896
        # to an older revision ID has no effect.
897
        branch_token, repo_token = self.lock_branch()
898
        response = self.request.execute(
899
            '', branch_token, repo_token, rev_id_utf8, 0, 0)
900
        self.assertEqual(
901
            SuccessfulSmartServerResponse(('ok', 2, 'rev-2')),
902
            response)
903
        self.assertEqual(
904
            (2, 'rev-2'), self.tree.branch.last_revision_info())
905
906
        # If allow_overwrite_descendant flag is 1, then setting the tip to an
907
        # ancestor works.
908
        response = self.request.execute(
909
            '', branch_token, repo_token, rev_id_utf8, 0, 1)
910
        self.assertEqual(
911
            SuccessfulSmartServerResponse(('ok', 1, rev_id_utf8)),
912
            response)
913
        self.unlock_branch()
914
        self.assertEqual(
915
            (1, rev_id_utf8), self.tree.branch.last_revision_info())
916
3441.5.31 by Andrew Bennetts
Add test for allow_diverged flag.
917
    def make_branch_with_divergent_history(self):
918
        """Make a branch with divergent history in its repo.
919
920
        The branch's tip will be 'child-2', and the repo will also contain
921
        'child-1', which diverges from a common base revision.
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
922
        """
923
        self.tree.lock_write()
924
        self.tree.add('')
925
        r1 = self.tree.commit('1st commit')
926
        revno_1, revid_1 = self.tree.branch.last_revision_info()
927
        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.
928
        # Undo the second commit
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
929
        self.tree.branch.set_last_revision_info(revno_1, revid_1)
930
        self.tree.set_parent_ids([revid_1])
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
931
        # Make a new second commit, child-2.  child-2 has diverged from
932
        # child-1.
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
933
        new_r2 = self.tree.commit('2nd commit', rev_id='child-2')
934
        self.tree.unlock()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
935
3441.5.31 by Andrew Bennetts
Add test for allow_diverged flag.
936
    def test_not_allow_diverged(self):
937
        """If allow_diverged is not passed, then setting a divergent history
938
        returns a Diverged error.
939
        """
940
        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.
941
        self.assertEqual(
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
942
            FailedSmartServerResponse(('Diverged',)),
943
            self.set_last_revision('child-1', 2))
944
        # The branch tip was not changed.
945
        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.
946
3441.5.31 by Andrew Bennetts
Add test for allow_diverged flag.
947
    def test_allow_diverged(self):
948
        """If allow_diverged is passed, then setting a divergent history
949
        succeeds.
950
        """
951
        self.make_branch_with_divergent_history()
952
        branch_token, repo_token = self.lock_branch()
953
        response = self.request.execute(
954
            '', branch_token, repo_token, 'child-1', 1, 0)
955
        self.assertEqual(
956
            SuccessfulSmartServerResponse(('ok', 2, 'child-1')),
957
            response)
958
        self.unlock_branch()
959
        # The branch tip was changed.
960
        self.assertEqual('child-1', self.tree.branch.last_revision())
961
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
962
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
963
class TestSmartServerBranchRequestGetParent(tests.TestCaseWithMemoryTransport):
964
965
    def test_get_parent_none(self):
966
        base_branch = self.make_branch('base')
967
        request = smart.branch.SmartServerBranchGetParent(self.get_transport())
968
        response = request.execute('base')
969
        self.assertEquals(
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
970
            SuccessfulSmartServerResponse(('',)), response)
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
971
972
    def test_get_parent_something(self):
973
        base_branch = self.make_branch('base')
974
        base_branch.set_parent(self.get_url('foo'))
975
        request = smart.branch.SmartServerBranchGetParent(self.get_transport())
976
        response = request.execute('base')
977
        self.assertEquals(
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
978
            SuccessfulSmartServerResponse(("../foo",)),
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
979
            response)
980
981
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
982
class TestSmartServerBranchRequestSetParent(tests.TestCaseWithMemoryTransport):
983
984
    def test_set_parent_none(self):
985
        branch = self.make_branch('base', format="1.9")
4288.1.9 by Robert Collins
Fix up test usable of _set_parent_location on unlocked branches.
986
        branch.lock_write()
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
987
        branch._set_parent_location('foo')
4288.1.9 by Robert Collins
Fix up test usable of _set_parent_location on unlocked branches.
988
        branch.unlock()
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
989
        request = smart.branch.SmartServerBranchRequestSetParentLocation(
990
            self.get_transport())
991
        branch_token = branch.lock_write()
992
        repo_token = branch.repository.lock_write()
993
        try:
994
            response = request.execute('base', branch_token, repo_token, '')
995
        finally:
996
            branch.repository.unlock()
997
            branch.unlock()
998
        self.assertEqual(SuccessfulSmartServerResponse(()), response)
999
        self.assertEqual(None, branch.get_parent())
1000
1001
    def test_set_parent_something(self):
1002
        branch = self.make_branch('base', format="1.9")
1003
        request = smart.branch.SmartServerBranchRequestSetParentLocation(
1004
            self.get_transport())
1005
        branch_token = branch.lock_write()
1006
        repo_token = branch.repository.lock_write()
1007
        try:
1008
            response = request.execute('base', branch_token, repo_token,
1009
            'http://bar/')
1010
        finally:
1011
            branch.repository.unlock()
1012
            branch.unlock()
1013
        self.assertEqual(SuccessfulSmartServerResponse(()), response)
1014
        self.assertEqual('http://bar/', branch.get_parent())
1015
1016
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.
1017
class TestSmartServerBranchRequestGetTagsBytes(tests.TestCaseWithMemoryTransport):
4556.2.2 by Andrew Bennetts
Handle failures more gracefully.
1018
    # Only called when the branch format and tags match [yay factory
1019
    # methods] so only need to test straight forward cases.
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.
1020
1021
    def test_get_bytes(self):
1022
        base_branch = self.make_branch('base')
1023
        request = smart.branch.SmartServerBranchGetTagsBytes(
1024
            self.get_transport())
1025
        response = request.execute('base')
1026
        self.assertEquals(
1027
            SuccessfulSmartServerResponse(('',)), response)
1028
1029
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
1030
class TestSmartServerBranchRequestGetStackedOnURL(tests.TestCaseWithMemoryTransport):
1031
1032
    def test_get_stacked_on_url(self):
1033
        base_branch = self.make_branch('base', format='1.6')
1034
        stacked_branch = self.make_branch('stacked', format='1.6')
1035
        # typically should be relative
1036
        stacked_branch.set_stacked_on_url('../base')
1037
        request = smart.branch.SmartServerBranchRequestGetStackedOnURL(
1038
            self.get_transport())
1039
        response = request.execute('stacked')
1040
        self.assertEquals(
1041
            SmartServerResponse(('ok', '../base')),
1042
            response)
1043
1044
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1045
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1046
1047
    def setUp(self):
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1048
        tests.TestCaseWithMemoryTransport.setUp(self)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1049
1050
    def test_lock_write_on_unlocked_branch(self):
1051
        backing = self.get_transport()
1052
        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.
1053
        branch = self.make_branch('.', format='knit')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1054
        repository = branch.repository
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1055
        response = request.execute('')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1056
        branch_nonce = branch.control_files._lock.peek().get('nonce')
1057
        repository_nonce = repository.control_files._lock.peek().get('nonce')
1058
        self.assertEqual(
1059
            SmartServerResponse(('ok', branch_nonce, repository_nonce)),
1060
            response)
1061
        # The branch (and associated repository) is now locked.  Verify that
1062
        # with a new branch object.
1063
        new_branch = repository.bzrdir.open_branch()
1064
        self.assertRaises(errors.LockContention, new_branch.lock_write)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1065
        # Cleanup
1066
        request = smart.branch.SmartServerBranchRequestUnlock(backing)
1067
        response = request.execute('', branch_nonce, repository_nonce)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1068
1069
    def test_lock_write_on_locked_branch(self):
1070
        backing = self.get_transport()
1071
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
1072
        branch = self.make_branch('.')
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1073
        branch_token = branch.lock_write()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1074
        branch.leave_lock_in_place()
1075
        branch.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1076
        response = request.execute('')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1077
        self.assertEqual(
1078
            SmartServerResponse(('LockContention',)), response)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1079
        # Cleanup
1080
        branch.lock_write(branch_token)
1081
        branch.dont_leave_lock_in_place()
1082
        branch.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1083
1084
    def test_lock_write_with_tokens_on_locked_branch(self):
1085
        backing = self.get_transport()
1086
        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.
1087
        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).
1088
        branch_token = branch.lock_write()
1089
        repo_token = branch.repository.lock_write()
1090
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1091
        branch.leave_lock_in_place()
1092
        branch.repository.leave_lock_in_place()
1093
        branch.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1094
        response = request.execute('',
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1095
                                   branch_token, repo_token)
1096
        self.assertEqual(
1097
            SmartServerResponse(('ok', branch_token, repo_token)), response)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1098
        # Cleanup
1099
        branch.repository.lock_write(repo_token)
1100
        branch.repository.dont_leave_lock_in_place()
1101
        branch.repository.unlock()
1102
        branch.lock_write(branch_token)
1103
        branch.dont_leave_lock_in_place()
1104
        branch.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1105
1106
    def test_lock_write_with_mismatched_tokens_on_locked_branch(self):
1107
        backing = self.get_transport()
1108
        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.
1109
        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).
1110
        branch_token = branch.lock_write()
1111
        repo_token = branch.repository.lock_write()
1112
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1113
        branch.leave_lock_in_place()
1114
        branch.repository.leave_lock_in_place()
1115
        branch.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1116
        response = request.execute('',
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1117
                                   branch_token+'xxx', repo_token)
1118
        self.assertEqual(
1119
            SmartServerResponse(('TokenMismatch',)), response)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1120
        # Cleanup
1121
        branch.repository.lock_write(repo_token)
1122
        branch.repository.dont_leave_lock_in_place()
1123
        branch.repository.unlock()
1124
        branch.lock_write(branch_token)
1125
        branch.dont_leave_lock_in_place()
1126
        branch.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1127
1128
    def test_lock_write_on_locked_repo(self):
1129
        backing = self.get_transport()
1130
        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.
1131
        branch = self.make_branch('.', format='knit')
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1132
        repo = branch.repository
1133
        repo_token = repo.lock_write()
1134
        repo.leave_lock_in_place()
1135
        repo.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1136
        response = request.execute('')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1137
        self.assertEqual(
1138
            SmartServerResponse(('LockContention',)), response)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1139
        # Cleanup
1140
        repo.lock_write(repo_token)
1141
        repo.dont_leave_lock_in_place()
1142
        repo.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1143
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.
1144
    def test_lock_write_on_readonly_transport(self):
1145
        backing = self.get_readonly_transport()
1146
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
1147
        branch = self.make_branch('.')
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1148
        root = self.get_transport().clone('/')
1149
        path = urlutils.relative_url(root.base, self.get_transport().base)
1150
        response = request.execute(path)
2872.5.3 by Martin Pool
Pass back LockFailed from smart server lock methods
1151
        error_name, lock_str, why_str = response.args
1152
        self.assertFalse(response.is_successful())
1153
        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.
1154
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1155
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1156
class TestSmartServerBranchRequestUnlock(tests.TestCaseWithMemoryTransport):
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1157
1158
    def setUp(self):
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1159
        tests.TestCaseWithMemoryTransport.setUp(self)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1160
1161
    def test_unlock_on_locked_branch_and_repo(self):
1162
        backing = self.get_transport()
1163
        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.
1164
        branch = self.make_branch('.', format='knit')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1165
        # 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).
1166
        branch_token = branch.lock_write()
1167
        repo_token = branch.repository.lock_write()
1168
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1169
        # Unlock the branch (and repo) object, leaving the physical locks
1170
        # in place.
1171
        branch.leave_lock_in_place()
1172
        branch.repository.leave_lock_in_place()
1173
        branch.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1174
        response = request.execute('',
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1175
                                   branch_token, repo_token)
1176
        self.assertEqual(
1177
            SmartServerResponse(('ok',)), response)
1178
        # The branch is now unlocked.  Verify that with a new branch
1179
        # object.
1180
        new_branch = branch.bzrdir.open_branch()
1181
        new_branch.lock_write()
1182
        new_branch.unlock()
1183
1184
    def test_unlock_on_unlocked_branch_unlocked_repo(self):
1185
        backing = self.get_transport()
1186
        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.
1187
        branch = self.make_branch('.', format='knit')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1188
        response = request.execute(
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1189
            '', 'branch token', 'repo token')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1190
        self.assertEqual(
1191
            SmartServerResponse(('TokenMismatch',)), response)
1192
1193
    def test_unlock_on_unlocked_branch_locked_repo(self):
1194
        backing = self.get_transport()
1195
        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.
1196
        branch = self.make_branch('.', format='knit')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1197
        # Lock the repository.
1198
        repo_token = branch.repository.lock_write()
1199
        branch.repository.leave_lock_in_place()
1200
        branch.repository.unlock()
1201
        # Issue branch lock_write request on the unlocked branch (with locked
1202
        # repo).
1203
        response = request.execute(
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1204
            '', 'branch token', repo_token)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1205
        self.assertEqual(
1206
            SmartServerResponse(('TokenMismatch',)), response)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1207
        # Cleanup
1208
        branch.repository.lock_write(repo_token)
1209
        branch.repository.dont_leave_lock_in_place()
1210
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1211
1212
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1213
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).
1214
1215
    def test_no_repository(self):
1216
        """Raise NoRepositoryPresent when there is a bzrdir and no repo."""
1217
        # we test this using a shared repository above the named path,
1218
        # thus checking the right search logic is used - that is, that
1219
        # its the exact path being looked at and the server is not
1220
        # searching.
1221
        backing = self.get_transport()
2018.5.58 by Wouter van Heyst
Small test fixes to reflect naming and documentation
1222
        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).
1223
        self.make_repository('.', shared=True)
1224
        self.make_bzrdir('subdir')
1225
        self.assertRaises(errors.NoRepositoryPresent,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1226
            request.execute, 'subdir')
1227
1228
3441.5.4 by Andrew Bennetts
Fix test failures, and add some tests for the remote graph heads RPC.
1229
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.
1230
3211.5.3 by Robert Collins
Adjust size of batch and change gzip comments to bzip2.
1231
    def test_trivial_bzipped(self):
1232
        # 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.
1233
        backing = self.get_transport()
1234
        request = smart.repository.SmartServerRepositoryGetParentMap(backing)
1235
        tree = self.make_branch_and_memory_tree('.')
1236
1237
        self.assertEqual(None,
2692.1.24 by Andrew Bennetts
Merge from bzr.dev.
1238
            request.execute('', 'missing-id'))
4190.1.3 by Robert Collins
Allow optional inclusion of ghost data in server get_parent_map calls.
1239
        # Note that it returns a body that is 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.
1240
        self.assertEqual(
3211.5.2 by Robert Collins
Change RemoteRepository.get_parent_map to use bz2 not gzip for compression.
1241
            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.
1242
            request.do_body('\n\n0\n'))
1243
4190.1.3 by Robert Collins
Allow optional inclusion of ghost data in server get_parent_map calls.
1244
    def test_trivial_include_missing(self):
1245
        backing = self.get_transport()
1246
        request = smart.repository.SmartServerRepositoryGetParentMap(backing)
1247
        tree = self.make_branch_and_memory_tree('.')
1248
1249
        self.assertEqual(None,
1250
            request.execute('', 'missing-id', 'include-missing:'))
1251
        self.assertEqual(
1252
            SuccessfulSmartServerResponse(('ok', ),
1253
                bz2.compress('missing:missing-id')),
1254
            request.do_body('\n\n0\n'))
1255
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.
1256
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1257
class TestSmartServerRepositoryGetRevisionGraph(tests.TestCaseWithMemoryTransport):
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1258
1259
    def test_none_argument(self):
1260
        backing = self.get_transport()
1261
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
1262
        tree = self.make_branch_and_memory_tree('.')
1263
        tree.lock_write()
1264
        tree.add('')
1265
        r1 = tree.commit('1st commit')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1266
        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)
1267
        tree.unlock()
1268
1269
        # the lines of revision_id->revision_parent_list has no guaranteed
1270
        # order coming out of a dict, so sort both our test and response
1271
        lines = sorted([' '.join([r2, r1]), r1])
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1272
        response = request.execute('', '')
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1273
        response.body = '\n'.join(sorted(response.body.split('\n')))
1274
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
1275
        self.assertEqual(
1276
            SmartServerResponse(('ok', ), '\n'.join(lines)), response)
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1277
1278
    def test_specific_revision_argument(self):
1279
        backing = self.get_transport()
1280
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
1281
        tree = self.make_branch_and_memory_tree('.')
1282
        tree.lock_write()
1283
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1284
        rev_id_utf8 = u'\xc9'.encode('utf-8')
1285
        r1 = tree.commit('1st commit', rev_id=rev_id_utf8)
1286
        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)
1287
        tree.unlock()
1288
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1289
        self.assertEqual(SmartServerResponse(('ok', ), rev_id_utf8),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1290
            request.execute('', rev_id_utf8))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1291
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1292
    def test_no_such_revision(self):
1293
        backing = self.get_transport()
1294
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
1295
        tree = self.make_branch_and_memory_tree('.')
1296
        tree.lock_write()
1297
        tree.add('')
1298
        r1 = tree.commit('1st commit')
1299
        tree.unlock()
1300
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1301
        # Note that it still returns body (of zero bytes).
1302
        self.assertEqual(
1303
            SmartServerResponse(('nosuchrevision', 'missingrevision', ), ''),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1304
            request.execute('', 'missingrevision'))
1305
1306
4419.2.6 by Andrew Bennetts
Add tests for server-side logic, and fix the bugs exposed by those tests.
1307
class TestSmartServerRepositoryGetRevIdForRevno(tests.TestCaseWithMemoryTransport):
1308
1309
    def test_revno_found(self):
1310
        backing = self.get_transport()
1311
        request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
1312
        tree = self.make_branch_and_memory_tree('.')
1313
        tree.lock_write()
1314
        tree.add('')
1315
        rev1_id_utf8 = u'\xc8'.encode('utf-8')
1316
        rev2_id_utf8 = u'\xc9'.encode('utf-8')
1317
        tree.commit('1st commit', rev_id=rev1_id_utf8)
1318
        tree.commit('2nd commit', rev_id=rev2_id_utf8)
1319
        tree.unlock()
1320
1321
        self.assertEqual(SmartServerResponse(('ok', rev1_id_utf8)),
1322
            request.execute('', 1, (2, rev2_id_utf8)))
1323
1324
    def test_known_revid_missing(self):
1325
        backing = self.get_transport()
1326
        request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
1327
        repo = self.make_repository('.')
1328
        self.assertEqual(
1329
            FailedSmartServerResponse(('nosuchrevision', 'ghost')),
1330
            request.execute('', 1, (2, 'ghost')))
1331
1332
    def test_history_incomplete(self):
1333
        backing = self.get_transport()
1334
        request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
1335
        parent = self.make_branch_and_memory_tree('parent', format='1.9')
4526.9.21 by Robert Collins
Fix test_smart's test_history_incomplete to generate a good tree before committing.
1336
        parent.lock_write()
1337
        parent.add([''], ['TREE_ROOT'])
4419.2.6 by Andrew Bennetts
Add tests for server-side logic, and fix the bugs exposed by those tests.
1338
        r1 = parent.commit(message='first commit')
1339
        r2 = parent.commit(message='second commit')
4526.9.21 by Robert Collins
Fix test_smart's test_history_incomplete to generate a good tree before committing.
1340
        parent.unlock()
4419.2.6 by Andrew Bennetts
Add tests for server-side logic, and fix the bugs exposed by those tests.
1341
        local = self.make_branch_and_memory_tree('local', format='1.9')
1342
        local.branch.pull(parent.branch)
1343
        local.set_parent_ids([r2])
1344
        r3 = local.commit(message='local commit')
1345
        local.branch.create_clone_on_transport(
1346
            self.get_transport('stacked'), stacked_on=self.get_url('parent'))
1347
        self.assertEqual(
1348
            SmartServerResponse(('history-incomplete', 2, r2)),
1349
            request.execute('stacked', 1, (3, r3)))
1350
4476.3.68 by Andrew Bennetts
Review comments from John.
1351
4070.9.14 by Andrew Bennetts
Tweaks requested by Robert's review.
1352
class TestSmartServerRepositoryGetStream(tests.TestCaseWithMemoryTransport):
1353
1354
    def make_two_commit_repo(self):
1355
        tree = self.make_branch_and_memory_tree('.')
1356
        tree.lock_write()
1357
        tree.add('')
1358
        r1 = tree.commit('1st commit')
1359
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
1360
        tree.unlock()
1361
        repo = tree.branch.repository
1362
        return repo, r1, r2
1363
1364
    def test_ancestry_of(self):
1365
        """The search argument may be a 'ancestry-of' some heads'."""
1366
        backing = self.get_transport()
1367
        request = smart.repository.SmartServerRepositoryGetStream(backing)
1368
        repo, r1, r2 = self.make_two_commit_repo()
1369
        fetch_spec = ['ancestry-of', r2]
1370
        lines = '\n'.join(fetch_spec)
1371
        request.execute('', repo._format.network_name())
1372
        response = request.do_body(lines)
1373
        self.assertEqual(('ok',), response.args)
1374
        stream_bytes = ''.join(response.body_stream)
1375
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
1376
1377
    def test_search(self):
1378
        """The search argument may be a 'search' of some explicit keys."""
1379
        backing = self.get_transport()
1380
        request = smart.repository.SmartServerRepositoryGetStream(backing)
1381
        repo, r1, r2 = self.make_two_commit_repo()
1382
        fetch_spec = ['search', '%s %s' % (r1, r2), 'null:', '2']
1383
        lines = '\n'.join(fetch_spec)
1384
        request.execute('', repo._format.network_name())
1385
        response = request.do_body(lines)
1386
        self.assertEqual(('ok',), response.args)
1387
        stream_bytes = ''.join(response.body_stream)
1388
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
1389
1390
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1391
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).
1392
1393
    def test_missing_revision(self):
1394
        """For a missing revision, ('no', ) is returned."""
1395
        backing = self.get_transport()
1396
        request = smart.repository.SmartServerRequestHasRevision(backing)
1397
        self.make_repository('.')
1398
        self.assertEqual(SmartServerResponse(('no', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1399
            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).
1400
1401
    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.
1402
        """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).
1403
        backing = self.get_transport()
1404
        request = smart.repository.SmartServerRequestHasRevision(backing)
1405
        tree = self.make_branch_and_memory_tree('.')
1406
        tree.lock_write()
1407
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1408
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
1409
        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).
1410
        tree.unlock()
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1411
        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.
1412
        self.assertEqual(SmartServerResponse(('yes', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1413
            request.execute('', rev_id_utf8))
1414
1415
1416
class TestSmartServerRepositoryGatherStats(tests.TestCaseWithMemoryTransport):
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1417
1418
    def test_empty_revid(self):
1419
        """With an empty revid, we get only size an number and revisions"""
1420
        backing = self.get_transport()
1421
        request = smart.repository.SmartServerRepositoryGatherStats(backing)
1422
        repository = self.make_repository('.')
1423
        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.
1424
        expected_body = 'revisions: 0\n'
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1425
        self.assertEqual(SmartServerResponse(('ok', ), expected_body),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1426
                         request.execute('', '', 'no'))
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1427
1428
    def test_revid_with_committers(self):
1429
        """For a revid we get more infos."""
1430
        backing = self.get_transport()
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1431
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1432
        request = smart.repository.SmartServerRepositoryGatherStats(backing)
1433
        tree = self.make_branch_and_memory_tree('.')
1434
        tree.lock_write()
1435
        tree.add('')
1436
        # Let's build a predictable result
1437
        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.
1438
        tree.commit('a commit', timestamp=654321.4, timezone=0,
1439
                    rev_id=rev_id_utf8)
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1440
        tree.unlock()
1441
1442
        stats = tree.branch.repository.gather_stats()
1443
        expected_body = ('firstrev: 123456.200 3600\n'
1444
                         '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.
1445
                         'revisions: 2\n')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1446
        self.assertEqual(SmartServerResponse(('ok', ), expected_body),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1447
                         request.execute('',
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1448
                                         rev_id_utf8, 'no'))
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1449
1450
    def test_not_empty_repository_with_committers(self):
1451
        """For a revid and requesting committers we get the whole thing."""
1452
        backing = self.get_transport()
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1453
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1454
        request = smart.repository.SmartServerRepositoryGatherStats(backing)
1455
        tree = self.make_branch_and_memory_tree('.')
1456
        tree.lock_write()
1457
        tree.add('')
1458
        # Let's build a predictable result
1459
        tree.commit('a commit', timestamp=123456.2, timezone=3600,
1460
                    committer='foo')
1461
        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.
1462
                    committer='bar', rev_id=rev_id_utf8)
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1463
        tree.unlock()
1464
        stats = tree.branch.repository.gather_stats()
1465
1466
        expected_body = ('committers: 2\n'
1467
                         'firstrev: 123456.200 3600\n'
1468
                         '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.
1469
                         'revisions: 2\n')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1470
        self.assertEqual(SmartServerResponse(('ok', ), expected_body),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1471
                         request.execute('',
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1472
                                         rev_id_utf8, 'yes'))
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1473
1474
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1475
class TestSmartServerRepositoryIsShared(tests.TestCaseWithMemoryTransport):
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1476
1477
    def test_is_shared(self):
1478
        """For a shared repository, ('yes', ) is returned."""
1479
        backing = self.get_transport()
1480
        request = smart.repository.SmartServerRepositoryIsShared(backing)
1481
        self.make_repository('.', shared=True)
1482
        self.assertEqual(SmartServerResponse(('yes', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1483
            request.execute('', ))
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1484
1485
    def test_is_not_shared(self):
2018.5.58 by Wouter van Heyst
Small test fixes to reflect naming and documentation
1486
        """For a shared repository, ('no', ) is returned."""
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1487
        backing = self.get_transport()
1488
        request = smart.repository.SmartServerRepositoryIsShared(backing)
1489
        self.make_repository('.', shared=False)
1490
        self.assertEqual(SmartServerResponse(('no', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1491
            request.execute('', ))
1492
1493
1494
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1495
1496
    def test_lock_write_on_unlocked_repo(self):
1497
        backing = self.get_transport()
1498
        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.
1499
        repository = self.make_repository('.', format='knit')
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1500
        response = request.execute('')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1501
        nonce = repository.control_files._lock.peek().get('nonce')
1502
        self.assertEqual(SmartServerResponse(('ok', nonce)), response)
1503
        # The repository is now locked.  Verify that with a new repository
1504
        # object.
1505
        new_repo = repository.bzrdir.open_repository()
1506
        self.assertRaises(errors.LockContention, new_repo.lock_write)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1507
        # Cleanup
1508
        request = smart.repository.SmartServerRepositoryUnlock(backing)
1509
        response = request.execute('', nonce)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1510
1511
    def test_lock_write_on_locked_repo(self):
1512
        backing = self.get_transport()
1513
        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.
1514
        repository = self.make_repository('.', format='knit')
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1515
        repo_token = repository.lock_write()
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1516
        repository.leave_lock_in_place()
1517
        repository.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1518
        response = request.execute('')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1519
        self.assertEqual(
1520
            SmartServerResponse(('LockContention',)), response)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1521
        # Cleanup
1522
        repository.lock_write(repo_token)
1523
        repository.dont_leave_lock_in_place()
1524
        repository.unlock()
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1525
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.
1526
    def test_lock_write_on_readonly_transport(self):
1527
        backing = self.get_readonly_transport()
1528
        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.
1529
        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.
1530
        response = request.execute('')
2872.5.3 by Martin Pool
Pass back LockFailed from smart server lock methods
1531
        self.assertFalse(response.is_successful())
1532
        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.
1533
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1534
4144.3.1 by Andrew Bennetts
Add Repository.insert_stream_locked server-side implementation, plus tests for server-side _translate_error.
1535
class TestInsertStreamBase(tests.TestCaseWithMemoryTransport):
1536
1537
    def make_empty_byte_stream(self, repo):
1538
        byte_stream = smart.repository._stream_to_byte_stream([], repo._format)
1539
        return ''.join(byte_stream)
1540
1541
1542
class TestSmartServerRepositoryInsertStream(TestInsertStreamBase):
1543
1544
    def test_insert_stream_empty(self):
1545
        backing = self.get_transport()
1546
        request = smart.repository.SmartServerRepositoryInsertStream(backing)
1547
        repository = self.make_repository('.')
1548
        response = request.execute('', '')
1549
        self.assertEqual(None, response)
1550
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1551
        self.assertEqual(None, response)
1552
        response = request.do_end()
1553
        self.assertEqual(SmartServerResponse(('ok', )), response)
1554
        
1555
1556
class TestSmartServerRepositoryInsertStreamLocked(TestInsertStreamBase):
1557
1558
    def test_insert_stream_empty(self):
1559
        backing = self.get_transport()
1560
        request = smart.repository.SmartServerRepositoryInsertStreamLocked(
1561
            backing)
1562
        repository = self.make_repository('.', format='knit')
1563
        lock_token = repository.lock_write()
1564
        response = request.execute('', '', lock_token)
1565
        self.assertEqual(None, response)
1566
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1567
        self.assertEqual(None, response)
1568
        response = request.do_end()
1569
        self.assertEqual(SmartServerResponse(('ok', )), response)
1570
        repository.unlock()
1571
1572
    def test_insert_stream_with_wrong_lock_token(self):
1573
        backing = self.get_transport()
1574
        request = smart.repository.SmartServerRepositoryInsertStreamLocked(
1575
            backing)
1576
        repository = self.make_repository('.', format='knit')
1577
        lock_token = repository.lock_write()
1578
        self.assertRaises(
1579
            errors.TokenMismatch, request.execute, '', '', 'wrong-token')
1580
        repository.unlock()
1581
1582
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1583
class TestSmartServerRepositoryUnlock(tests.TestCaseWithMemoryTransport):
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1584
1585
    def setUp(self):
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1586
        tests.TestCaseWithMemoryTransport.setUp(self)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1587
1588
    def test_unlock_on_locked_repo(self):
1589
        backing = self.get_transport()
1590
        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.
1591
        repository = self.make_repository('.', format='knit')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1592
        token = repository.lock_write()
1593
        repository.leave_lock_in_place()
1594
        repository.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1595
        response = request.execute('', token)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1596
        self.assertEqual(
1597
            SmartServerResponse(('ok',)), response)
1598
        # The repository is now unlocked.  Verify that with a new repository
1599
        # object.
1600
        new_repo = repository.bzrdir.open_repository()
1601
        new_repo.lock_write()
1602
        new_repo.unlock()
1603
1604
    def test_unlock_on_unlocked_repo(self):
1605
        backing = self.get_transport()
1606
        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.
1607
        repository = self.make_repository('.', format='knit')
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1608
        response = request.execute('', 'some token')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1609
        self.assertEqual(
1610
            SmartServerResponse(('TokenMismatch',)), response)
1611
1612
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1613
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.
1614
1615
    def test_is_readonly_no(self):
1616
        backing = self.get_transport()
1617
        request = smart.request.SmartServerIsReadonly(backing)
1618
        response = request.execute()
1619
        self.assertEqual(
1620
            SmartServerResponse(('no',)), response)
1621
1622
    def test_is_readonly_yes(self):
1623
        backing = self.get_readonly_transport()
1624
        request = smart.request.SmartServerIsReadonly(backing)
1625
        response = request.execute()
1626
        self.assertEqual(
1627
            SmartServerResponse(('yes',)), response)
1628
1629
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
1630
class TestSmartServerRepositorySetMakeWorkingTrees(tests.TestCaseWithMemoryTransport):
1631
1632
    def test_set_false(self):
1633
        backing = self.get_transport()
1634
        repo = self.make_repository('.', shared=True)
1635
        repo.set_make_working_trees(True)
1636
        request_class = smart.repository.SmartServerRepositorySetMakeWorkingTrees
1637
        request = request_class(backing)
1638
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)),
1639
            request.execute('', 'False'))
1640
        repo = repo.bzrdir.open_repository()
1641
        self.assertFalse(repo.make_working_trees())
1642
1643
    def test_set_true(self):
1644
        backing = self.get_transport()
1645
        repo = self.make_repository('.', shared=True)
1646
        repo.set_make_working_trees(False)
1647
        request_class = smart.repository.SmartServerRepositorySetMakeWorkingTrees
1648
        request = request_class(backing)
1649
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)),
1650
            request.execute('', 'True'))
1651
        repo = repo.bzrdir.open_repository()
1652
        self.assertTrue(repo.make_working_trees())
1653
1654
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1655
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1656
1657
    def make_repo_needing_autopacking(self, path='.'):
1658
        # Make a repo in need of autopacking.
1659
        tree = self.make_branch_and_tree('.', format='pack-0.92')
1660
        repo = tree.branch.repository
1661
        # monkey-patch the pack collection to disable autopacking
1662
        repo._pack_collection._max_pack_count = lambda count: count
1663
        for x in range(10):
1664
            tree.commit('commit %s' % x)
1665
        self.assertEqual(10, len(repo._pack_collection.names()))
1666
        del repo._pack_collection._max_pack_count
1667
        return repo
1668
1669
    def test_autopack_needed(self):
1670
        repo = self.make_repo_needing_autopacking()
4145.1.6 by Robert Collins
More test fallout, but all caught now.
1671
        repo.lock_write()
1672
        self.addCleanup(repo.unlock)
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1673
        backing = self.get_transport()
1674
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1675
            backing)
1676
        response = request.execute('')
1677
        self.assertEqual(SmartServerResponse(('ok',)), response)
1678
        repo._pack_collection.reload_pack_names()
1679
        self.assertEqual(1, len(repo._pack_collection.names()))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1680
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1681
    def test_autopack_not_needed(self):
1682
        tree = self.make_branch_and_tree('.', format='pack-0.92')
1683
        repo = tree.branch.repository
4145.1.6 by Robert Collins
More test fallout, but all caught now.
1684
        repo.lock_write()
1685
        self.addCleanup(repo.unlock)
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1686
        for x in range(9):
1687
            tree.commit('commit %s' % x)
1688
        backing = self.get_transport()
1689
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1690
            backing)
1691
        response = request.execute('')
1692
        self.assertEqual(SmartServerResponse(('ok',)), response)
1693
        repo._pack_collection.reload_pack_names()
1694
        self.assertEqual(9, len(repo._pack_collection.names()))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1695
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1696
    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.
1697
        """A request to autopack a non-pack repo is a no-op."""
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1698
        repo = self.make_repository('.', format='knit')
1699
        backing = self.get_transport()
1700
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1701
            backing)
1702
        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.
1703
        self.assertEqual(SmartServerResponse(('ok',)), response)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1704
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1705
4760.2.5 by Andrew Bennetts
Add some more tests.
1706
class TestSmartServerVfsGet(tests.TestCaseWithMemoryTransport):
1707
1708
    def test_unicode_path(self):
1709
        """VFS requests expect unicode paths to be escaped."""
1710
        filename = u'foo\N{INTERROBANG}'
1711
        filename_escaped = urlutils.escape(filename)
1712
        backing = self.get_transport()
1713
        request = smart.vfs.GetRequest(backing)
1714
        backing.put_bytes_non_atomic(filename_escaped, 'contents')
1715
        self.assertEqual(SmartServerResponse(('ok', ), 'contents'),
1716
            request.execute(filename_escaped))
1717
1718
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
1719
class TestHandlers(tests.TestCase):
1720
    """Tests for the request.request_handlers object."""
1721
3526.3.1 by Andrew Bennetts
Remove registrations of defunct HPSS verbs.
1722
    def test_all_registrations_exist(self):
1723
        """All registered request_handlers can be found."""
1724
        # If there's a typo in a register_lazy call, this loop will fail with
1725
        # an AttributeError.
1726
        for key, item in smart.request.request_handlers.iteritems():
1727
            pass
1728
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1729
    def assertHandlerEqual(self, verb, handler):
1730
        self.assertEqual(smart.request.request_handlers.get(verb), handler)
1731
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
1732
    def test_registered_methods(self):
1733
        """Test that known methods are registered to the correct object."""
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1734
        self.assertHandlerEqual('Branch.get_config_file',
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1735
            smart.branch.SmartServerBranchGetConfigFile)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1736
        self.assertHandlerEqual('Branch.get_parent',
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1737
            smart.branch.SmartServerBranchGetParent)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1738
        self.assertHandlerEqual('Branch.get_tags_bytes',
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.
1739
            smart.branch.SmartServerBranchGetTagsBytes)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1740
        self.assertHandlerEqual('Branch.lock_write',
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1741
            smart.branch.SmartServerBranchRequestLockWrite)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1742
        self.assertHandlerEqual('Branch.last_revision_info',
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1743
            smart.branch.SmartServerBranchRequestLastRevisionInfo)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1744
        self.assertHandlerEqual('Branch.revision_history',
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
1745
            smart.branch.SmartServerRequestRevisionHistory)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1746
        self.assertHandlerEqual('Branch.set_config_option',
4226.2.1 by Robert Collins
Set branch config options via a smart method.
1747
            smart.branch.SmartServerBranchRequestSetConfigOption)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1748
        self.assertHandlerEqual('Branch.set_last_revision',
2018.5.77 by Wouter van Heyst
Fix typo in request_handlers registration of Branch.set_last_revision, and test that registration
1749
            smart.branch.SmartServerBranchRequestSetLastRevision)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1750
        self.assertHandlerEqual('Branch.set_last_revision_info',
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1751
            smart.branch.SmartServerBranchRequestSetLastRevisionInfo)
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
1752
        self.assertHandlerEqual('Branch.set_last_revision_ex',
1753
            smart.branch.SmartServerBranchRequestSetLastRevisionEx)
1754
        self.assertHandlerEqual('Branch.set_parent_location',
1755
            smart.branch.SmartServerBranchRequestSetParentLocation)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1756
        self.assertHandlerEqual('Branch.unlock',
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1757
            smart.branch.SmartServerBranchRequestUnlock)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1758
        self.assertHandlerEqual('BzrDir.find_repository',
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
1759
            smart.bzrdir.SmartServerRequestFindRepositoryV1)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1760
        self.assertHandlerEqual('BzrDir.find_repositoryV2',
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
1761
            smart.bzrdir.SmartServerRequestFindRepositoryV2)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1762
        self.assertHandlerEqual('BzrDirFormat.initialize',
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
1763
            smart.bzrdir.SmartServerRequestInitializeBzrDir)
4436.1.1 by Andrew Bennetts
Rename BzrDirFormat.initialize_ex verb to BzrDirFormat.initialize_ex_1.16.
1764
        self.assertHandlerEqual('BzrDirFormat.initialize_ex_1.16',
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
1765
            smart.bzrdir.SmartServerRequestBzrDirInitializeEx)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1766
        self.assertHandlerEqual('BzrDir.cloning_metadir',
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
1767
            smart.bzrdir.SmartServerBzrDirRequestCloningMetaDir)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1768
        self.assertHandlerEqual('BzrDir.get_config_file',
1769
            smart.bzrdir.SmartServerBzrDirRequestConfigFile)
1770
        self.assertHandlerEqual('BzrDir.open_branch',
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
1771
            smart.bzrdir.SmartServerRequestOpenBranch)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1772
        self.assertHandlerEqual('BzrDir.open_branchV2',
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.
1773
            smart.bzrdir.SmartServerRequestOpenBranchV2)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1774
        self.assertHandlerEqual('PackRepository.autopack',
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1775
            smart.packrepository.SmartServerPackRepositoryAutopack)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1776
        self.assertHandlerEqual('Repository.gather_stats',
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1777
            smart.repository.SmartServerRepositoryGatherStats)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1778
        self.assertHandlerEqual('Repository.get_parent_map',
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
1779
            smart.repository.SmartServerRepositoryGetParentMap)
4419.2.6 by Andrew Bennetts
Add tests for server-side logic, and fix the bugs exposed by those tests.
1780
        self.assertHandlerEqual('Repository.get_rev_id_for_revno',
1781
            smart.repository.SmartServerRepositoryGetRevIdForRevno)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1782
        self.assertHandlerEqual('Repository.get_revision_graph',
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1783
            smart.repository.SmartServerRepositoryGetRevisionGraph)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1784
        self.assertHandlerEqual('Repository.get_stream',
4144.3.1 by Andrew Bennetts
Add Repository.insert_stream_locked server-side implementation, plus tests for server-side _translate_error.
1785
            smart.repository.SmartServerRepositoryGetStream)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1786
        self.assertHandlerEqual('Repository.has_revision',
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
1787
            smart.repository.SmartServerRequestHasRevision)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1788
        self.assertHandlerEqual('Repository.insert_stream',
4144.3.1 by Andrew Bennetts
Add Repository.insert_stream_locked server-side implementation, plus tests for server-side _translate_error.
1789
            smart.repository.SmartServerRepositoryInsertStream)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1790
        self.assertHandlerEqual('Repository.insert_stream_locked',
4144.3.1 by Andrew Bennetts
Add Repository.insert_stream_locked server-side implementation, plus tests for server-side _translate_error.
1791
            smart.repository.SmartServerRepositoryInsertStreamLocked)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1792
        self.assertHandlerEqual('Repository.is_shared',
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1793
            smart.repository.SmartServerRepositoryIsShared)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1794
        self.assertHandlerEqual('Repository.lock_write',
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1795
            smart.repository.SmartServerRepositoryLockWrite)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1796
        self.assertHandlerEqual('Repository.tarball',
2535.3.69 by Andrew Bennetts
Add check for Repository.stream_knit_data_for_revisions to TestHandlers.test_registered_methods.
1797
            smart.repository.SmartServerRepositoryTarball)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1798
        self.assertHandlerEqual('Repository.unlock',
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1799
            smart.repository.SmartServerRepositoryUnlock)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1800
        self.assertHandlerEqual('Transport.is_readonly',
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.
1801
            smart.request.SmartServerIsReadonly)