~bzr-pqm/bzr/bzr.dev

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
4734.4.5 by Brian de Alwis
Address comments from Aaron Bentley
527
    def test_notification_on_branch_from_repository(self):
4734.4.4 by Brian de Alwis
Added tests to ensure branching-from-repository error returns detail
528
        """When there is a repository, the error should return details."""
529
        backing = self.get_transport()
530
        request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
531
        repo = self.make_repository('.')
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
532
        self.assertEqual(SmartServerResponse(('nobranch',)),
4734.4.4 by Brian de Alwis
Added tests to ensure branching-from-repository error returns detail
533
            request.execute(''))
534
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
535
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.
536
class TestSmartServerRequestOpenBranchV2(TestCaseWithChrootedTransport):
537
538
    def test_no_branch(self):
539
        """When there is no branch, ('nobranch', ) is returned."""
540
        backing = self.get_transport()
541
        self.make_bzrdir('.')
542
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
543
        self.assertEqual(SmartServerResponse(('nobranch', )),
544
            request.execute(''))
545
546
    def test_branch(self):
547
        """When there is a branch, 'ok' is returned."""
548
        backing = self.get_transport()
549
        expected = self.make_branch('.')._format.network_name()
550
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
551
        self.assertEqual(SuccessfulSmartServerResponse(('branch', expected)),
552
            request.execute(''))
553
554
    def test_branch_reference(self):
555
        """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.
556
        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.
557
        backing = self.get_transport()
558
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
559
        branch = self.make_branch('branch')
560
        checkout = branch.create_checkout('reference',lightweight=True)
561
        reference_url = BranchReferenceFormat().get_reference(checkout.bzrdir)
562
        self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
563
        self.assertEqual(SuccessfulSmartServerResponse(('ref', reference_url)),
564
            request.execute('reference'))
565
4160.2.1 by Andrew Bennetts
Failing test for BzrDir.open_branchV2 RPC not opening stacked-on branch.
566
    def test_stacked_branch(self):
567
        """Opening a stacked branch does not open the stacked-on branch."""
568
        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.
569
        feature = self.make_branch('feature')
4160.2.1 by Andrew Bennetts
Failing test for BzrDir.open_branchV2 RPC not opening stacked-on branch.
570
        feature.set_stacked_on_url(trunk.base)
571
        opened_branches = []
572
        Branch.hooks.install_named_hook('open', opened_branches.append, None)
573
        backing = self.get_transport()
574
        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.
575
        request.setup_jail()
576
        try:
577
            response = request.execute('feature')
578
        finally:
579
            request.teardown_jail()
4160.2.1 by Andrew Bennetts
Failing test for BzrDir.open_branchV2 RPC not opening stacked-on branch.
580
        expected_format = feature._format.network_name()
581
        self.assertEqual(
582
            SuccessfulSmartServerResponse(('branch', expected_format)),
583
            response)
584
        self.assertLength(1, opened_branches)
585
4734.4.5 by Brian de Alwis
Address comments from Aaron Bentley
586
    def test_notification_on_branch_from_repository(self):
4734.4.4 by Brian de Alwis
Added tests to ensure branching-from-repository error returns detail
587
        """When there is a repository, the error should return details."""
588
        backing = self.get_transport()
589
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
590
        repo = self.make_repository('.')
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
591
        self.assertEqual(SmartServerResponse(('nobranch',)),
592
            request.execute(''))
593
594
595
class TestSmartServerRequestOpenBranchV3(TestCaseWithChrootedTransport):
596
597
    def test_no_branch(self):
598
        """When there is no branch, ('nobranch', ) is returned."""
599
        backing = self.get_transport()
600
        self.make_bzrdir('.')
601
        request = smart.bzrdir.SmartServerRequestOpenBranchV3(backing)
602
        self.assertEqual(SmartServerResponse(('nobranch',)),
603
            request.execute(''))
604
605
    def test_branch(self):
606
        """When there is a branch, 'ok' is returned."""
607
        backing = self.get_transport()
608
        expected = self.make_branch('.')._format.network_name()
609
        request = smart.bzrdir.SmartServerRequestOpenBranchV3(backing)
610
        self.assertEqual(SuccessfulSmartServerResponse(('branch', expected)),
611
            request.execute(''))
612
613
    def test_branch_reference(self):
614
        """When there is a branch reference, the reference URL is returned."""
615
        self.vfs_transport_factory = local.LocalURLServer
616
        backing = self.get_transport()
617
        request = smart.bzrdir.SmartServerRequestOpenBranchV3(backing)
618
        branch = self.make_branch('branch')
619
        checkout = branch.create_checkout('reference',lightweight=True)
620
        reference_url = BranchReferenceFormat().get_reference(checkout.bzrdir)
621
        self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
622
        self.assertEqual(SuccessfulSmartServerResponse(('ref', reference_url)),
623
            request.execute('reference'))
624
625
    def test_stacked_branch(self):
626
        """Opening a stacked branch does not open the stacked-on branch."""
627
        trunk = self.make_branch('trunk')
628
        feature = self.make_branch('feature')
629
        feature.set_stacked_on_url(trunk.base)
630
        opened_branches = []
631
        Branch.hooks.install_named_hook('open', opened_branches.append, None)
632
        backing = self.get_transport()
633
        request = smart.bzrdir.SmartServerRequestOpenBranchV3(backing)
634
        request.setup_jail()
635
        try:
636
            response = request.execute('feature')
637
        finally:
638
            request.teardown_jail()
639
        expected_format = feature._format.network_name()
640
        self.assertEqual(
641
            SuccessfulSmartServerResponse(('branch', expected_format)),
642
            response)
643
        self.assertLength(1, opened_branches)
644
645
    def test_notification_on_branch_from_repository(self):
646
        """When there is a repository, the error should return details."""
647
        backing = self.get_transport()
648
        request = smart.bzrdir.SmartServerRequestOpenBranchV3(backing)
649
        repo = self.make_repository('.')
650
        self.assertEqual(
651
            SmartServerResponse(('nobranch', 'location is a repository')),
4734.4.4 by Brian de Alwis
Added tests to ensure branching-from-repository error returns detail
652
            request.execute(''))
653
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.
654
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
655
class TestSmartServerRequestRevisionHistory(tests.TestCaseWithMemoryTransport):
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
656
657
    def test_empty(self):
658
        """For an empty branch, the body is empty."""
659
        backing = self.get_transport()
660
        request = smart.branch.SmartServerRequestRevisionHistory(backing)
661
        self.make_branch('.')
662
        self.assertEqual(SmartServerResponse(('ok', ), ''),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
663
            request.execute(''))
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
664
665
    def test_not_empty(self):
666
        """For a non-empty branch, the body is empty."""
667
        backing = self.get_transport()
668
        request = smart.branch.SmartServerRequestRevisionHistory(backing)
669
        tree = self.make_branch_and_memory_tree('.')
670
        tree.lock_write()
671
        tree.add('')
672
        r1 = tree.commit('1st commit')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
673
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
674
        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.
675
        self.assertEqual(
676
            SmartServerResponse(('ok', ), ('\x00'.join([r1, r2]))),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
677
            request.execute(''))
678
679
680
class TestSmartServerBranchRequest(tests.TestCaseWithMemoryTransport):
2018.5.49 by Wouter van Heyst
Refactor SmartServerBranchRequest out from SmartServerRequestRevisionHistory to
681
682
    def test_no_branch(self):
683
        """When there is a bzrdir and no branch, NotBranchError is raised."""
684
        backing = self.get_transport()
685
        request = smart.branch.SmartServerBranchRequest(backing)
686
        self.make_bzrdir('.')
687
        self.assertRaises(errors.NotBranchError,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
688
            request.execute, '')
2018.5.49 by Wouter van Heyst
Refactor SmartServerBranchRequest out from SmartServerRequestRevisionHistory to
689
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
690
    def test_branch_reference(self):
691
        """When there is a branch reference, NotBranchError is raised."""
692
        backing = self.get_transport()
2018.5.49 by Wouter van Heyst
Refactor SmartServerBranchRequest out from SmartServerRequestRevisionHistory to
693
        request = smart.branch.SmartServerBranchRequest(backing)
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
694
        branch = self.make_branch('branch')
695
        checkout = branch.create_checkout('reference',lightweight=True)
696
        self.assertRaises(errors.NotBranchError,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
697
            request.execute, 'checkout')
698
699
700
class TestSmartServerBranchRequestLastRevisionInfo(tests.TestCaseWithMemoryTransport):
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
701
702
    def test_empty(self):
2018.5.170 by Andrew Bennetts
Use 'null:' instead of '' to mean NULL_REVISION on the wire.
703
        """For an empty branch, the result is ('ok', '0', 'null:')."""
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
704
        backing = self.get_transport()
705
        request = smart.branch.SmartServerBranchRequestLastRevisionInfo(backing)
706
        self.make_branch('.')
2018.5.170 by Andrew Bennetts
Use 'null:' instead of '' to mean NULL_REVISION on the wire.
707
        self.assertEqual(SmartServerResponse(('ok', '0', 'null:')),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
708
            request.execute(''))
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
709
710
    def test_not_empty(self):
711
        """For a non-empty branch, the result is ('ok', 'revno', 'revid')."""
712
        backing = self.get_transport()
713
        request = smart.branch.SmartServerBranchRequestLastRevisionInfo(backing)
714
        tree = self.make_branch_and_memory_tree('.')
715
        tree.lock_write()
716
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
717
        rev_id_utf8 = u'\xc8'.encode('utf-8')
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
718
        r1 = tree.commit('1st commit')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
719
        r2 = tree.commit('2nd commit', rev_id=rev_id_utf8)
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
720
        tree.unlock()
721
        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.
722
            SmartServerResponse(('ok', '2', rev_id_utf8)),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
723
            request.execute(''))
724
725
726
class TestSmartServerBranchRequestGetConfigFile(tests.TestCaseWithMemoryTransport):
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
727
728
    def test_default(self):
729
        """With no file, we get empty content."""
730
        backing = self.get_transport()
731
        request = smart.branch.SmartServerBranchGetConfigFile(backing)
732
        branch = self.make_branch('.')
733
        # there should be no file by default
734
        content = ''
735
        self.assertEqual(SmartServerResponse(('ok', ), content),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
736
            request.execute(''))
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
737
738
    def test_with_content(self):
739
        # SmartServerBranchGetConfigFile should return the content from
740
        # 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
741
        # perform more complex processing.
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
742
        backing = self.get_transport()
743
        request = smart.branch.SmartServerBranchGetConfigFile(backing)
744
        branch = self.make_branch('.')
3407.2.5 by Martin Pool
Deprecate LockableFiles.put_utf8
745
        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).
746
        self.assertEqual(SmartServerResponse(('ok', ), 'foo bar baz'),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
747
            request.execute(''))
748
749
4226.2.1 by Robert Collins
Set branch config options via a smart method.
750
class TestLockedBranch(tests.TestCaseWithMemoryTransport):
751
752
    def get_lock_tokens(self, branch):
753
        branch_token = branch.lock_write()
754
        repo_token = branch.repository.lock_write()
755
        branch.repository.unlock()
756
        return branch_token, repo_token
757
758
759
class TestSmartServerBranchRequestSetConfigOption(TestLockedBranch):
760
761
    def test_value_name(self):
762
        branch = self.make_branch('.')
763
        request = smart.branch.SmartServerBranchRequestSetConfigOption(
764
            branch.bzrdir.root_transport)
765
        branch_token, repo_token = self.get_lock_tokens(branch)
766
        config = branch._get_config()
767
        result = request.execute('', branch_token, repo_token, 'bar', 'foo',
768
            '')
769
        self.assertEqual(SuccessfulSmartServerResponse(()), result)
770
        self.assertEqual('bar', config.get_option('foo'))
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
771
        # Cleanup
772
        branch.unlock()
4226.2.1 by Robert Collins
Set branch config options via a smart method.
773
774
    def test_value_name_section(self):
775
        branch = self.make_branch('.')
776
        request = smart.branch.SmartServerBranchRequestSetConfigOption(
777
            branch.bzrdir.root_transport)
778
        branch_token, repo_token = self.get_lock_tokens(branch)
779
        config = branch._get_config()
780
        result = request.execute('', branch_token, repo_token, 'bar', 'foo',
781
            'gam')
782
        self.assertEqual(SuccessfulSmartServerResponse(()), result)
783
        self.assertEqual('bar', config.get_option('foo', 'gam'))
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
784
        # Cleanup
785
        branch.unlock()
4226.2.1 by Robert Collins
Set branch config options via a smart method.
786
787
4556.2.2 by Andrew Bennetts
Handle failures more gracefully.
788
class TestSmartServerBranchRequestSetTagsBytes(TestLockedBranch):
789
    # Only called when the branch format and tags match [yay factory
790
    # methods] so only need to test straight forward cases.
791
792
    def test_set_bytes(self):
793
        base_branch = self.make_branch('base')
794
        tag_bytes = base_branch._get_tags_bytes()
795
        # get_lock_tokens takes out a lock.
796
        branch_token, repo_token = self.get_lock_tokens(base_branch)
797
        request = smart.branch.SmartServerBranchSetTagsBytes(
798
            self.get_transport())
799
        response = request.execute('base', branch_token, repo_token)
800
        self.assertEqual(None, response)
801
        response = request.do_chunk(tag_bytes)
802
        self.assertEqual(None, response)
803
        response = request.do_end()
804
        self.assertEquals(
805
            SuccessfulSmartServerResponse(()), response)
806
        base_branch.unlock()
807
808
    def test_lock_failed(self):
809
        base_branch = self.make_branch('base')
810
        base_branch.lock_write()
811
        tag_bytes = base_branch._get_tags_bytes()
812
        request = smart.branch.SmartServerBranchSetTagsBytes(
813
            self.get_transport())
814
        self.assertRaises(errors.TokenMismatch, request.execute,
815
            'base', 'wrong token', 'wrong token')
816
        # The request handler will keep processing the message parts, so even
817
        # if the request fails immediately do_chunk and do_end are still
818
        # called.
819
        request.do_chunk(tag_bytes)
820
        request.do_end()
821
        base_branch.unlock()
822
823
824
4226.2.1 by Robert Collins
Set branch config options via a smart method.
825
class SetLastRevisionTestBase(TestLockedBranch):
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
826
    """Base test case for verbs that implement set_last_revision."""
827
828
    def setUp(self):
829
        tests.TestCaseWithMemoryTransport.setUp(self)
830
        backing_transport = self.get_transport()
831
        self.request = self.request_class(backing_transport)
832
        self.tree = self.make_branch_and_memory_tree('.')
833
834
    def lock_branch(self):
4226.2.1 by Robert Collins
Set branch config options via a smart method.
835
        return self.get_lock_tokens(self.tree.branch)
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
836
837
    def unlock_branch(self):
838
        self.tree.branch.unlock()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
839
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
840
    def set_last_revision(self, revision_id, revno):
841
        branch_token, repo_token = self.lock_branch()
842
        response = self._set_last_revision(
843
            revision_id, revno, branch_token, repo_token)
844
        self.unlock_branch()
845
        return response
846
847
    def assertRequestSucceeds(self, revision_id, revno):
848
        response = self.set_last_revision(revision_id, revno)
849
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)), response)
850
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
851
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
852
class TestSetLastRevisionVerbMixin(object):
853
    """Mixin test case for verbs that implement set_last_revision."""
854
855
    def test_set_null_to_null(self):
856
        """An empty branch can have its last revision set to 'null:'."""
857
        self.assertRequestSucceeds('null:', 0)
858
859
    def test_NoSuchRevision(self):
860
        """If the revision_id is not present, the verb returns NoSuchRevision.
861
        """
862
        revision_id = 'non-existent revision'
863
        self.assertEqual(
864
            FailedSmartServerResponse(('NoSuchRevision', revision_id)),
865
            self.set_last_revision(revision_id, 1))
866
867
    def make_tree_with_two_commits(self):
868
        self.tree.lock_write()
869
        self.tree.add('')
870
        rev_id_utf8 = u'\xc8'.encode('utf-8')
871
        r1 = self.tree.commit('1st commit', rev_id=rev_id_utf8)
872
        r2 = self.tree.commit('2nd commit', rev_id='rev-2')
873
        self.tree.unlock()
874
875
    def test_branch_last_revision_info_is_updated(self):
876
        """A branch's tip can be set to a revision that is present in its
877
        repository.
878
        """
879
        # Make a branch with an empty revision history, but two revisions in
880
        # its repository.
881
        self.make_tree_with_two_commits()
882
        rev_id_utf8 = u'\xc8'.encode('utf-8')
883
        self.tree.branch.set_revision_history([])
884
        self.assertEqual(
885
            (0, 'null:'), self.tree.branch.last_revision_info())
886
        # We can update the branch to a revision that is present in the
887
        # repository.
888
        self.assertRequestSucceeds(rev_id_utf8, 1)
889
        self.assertEqual(
890
            (1, rev_id_utf8), self.tree.branch.last_revision_info())
891
892
    def test_branch_last_revision_info_rewind(self):
893
        """A branch's tip can be set to a revision that is an ancestor of the
894
        current tip.
895
        """
896
        self.make_tree_with_two_commits()
897
        rev_id_utf8 = u'\xc8'.encode('utf-8')
898
        self.assertEqual(
899
            (2, 'rev-2'), self.tree.branch.last_revision_info())
900
        self.assertRequestSucceeds(rev_id_utf8, 1)
901
        self.assertEqual(
902
            (1, rev_id_utf8), self.tree.branch.last_revision_info())
903
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
904
    def test_TipChangeRejected(self):
905
        """If a pre_change_branch_tip hook raises TipChangeRejected, the verb
906
        returns TipChangeRejected.
907
        """
908
        rejection_message = u'rejection message\N{INTERROBANG}'
909
        def hook_that_rejects(params):
910
            raise errors.TipChangeRejected(rejection_message)
911
        Branch.hooks.install_named_hook(
912
            'pre_change_branch_tip', hook_that_rejects, None)
913
        self.assertEqual(
914
            FailedSmartServerResponse(
915
                ('TipChangeRejected', rejection_message.encode('utf-8'))),
916
            self.set_last_revision('null:', 0))
917
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
918
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
919
class TestSmartServerBranchRequestSetLastRevision(
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
920
        SetLastRevisionTestBase, TestSetLastRevisionVerbMixin):
921
    """Tests for Branch.set_last_revision verb."""
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
922
923
    request_class = smart.branch.SmartServerBranchRequestSetLastRevision
924
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
925
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
926
        return self.request.execute(
927
            '', branch_token, repo_token, revision_id)
928
929
930
class TestSmartServerBranchRequestSetLastRevisionInfo(
931
        SetLastRevisionTestBase, TestSetLastRevisionVerbMixin):
932
    """Tests for Branch.set_last_revision_info verb."""
933
934
    request_class = smart.branch.SmartServerBranchRequestSetLastRevisionInfo
935
936
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
937
        return self.request.execute(
938
            '', branch_token, repo_token, revno, revision_id)
939
940
    def test_NoSuchRevision(self):
941
        """Branch.set_last_revision_info does not have to return
942
        NoSuchRevision if the revision_id is absent.
943
        """
944
        raise tests.TestNotApplicable()
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
945
946
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.
947
class TestSmartServerBranchRequestSetLastRevisionEx(
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
948
        SetLastRevisionTestBase, TestSetLastRevisionVerbMixin):
949
    """Tests for Branch.set_last_revision_ex verb."""
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
950
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.
951
    request_class = smart.branch.SmartServerBranchRequestSetLastRevisionEx
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
952
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
953
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
954
        return self.request.execute(
955
            '', branch_token, repo_token, revision_id, 0, 0)
956
957
    def assertRequestSucceeds(self, revision_id, revno):
958
        response = self.set_last_revision(revision_id, revno)
959
        self.assertEqual(
960
            SuccessfulSmartServerResponse(('ok', revno, revision_id)),
961
            response)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
962
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
963
    def test_branch_last_revision_info_rewind(self):
964
        """A branch's tip can be set to a revision that is an ancestor of the
965
        current tip, but only if allow_overwrite_descendant is passed.
966
        """
967
        self.make_tree_with_two_commits()
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
968
        rev_id_utf8 = u'\xc8'.encode('utf-8')
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
969
        self.assertEqual(
970
            (2, 'rev-2'), self.tree.branch.last_revision_info())
971
        # If allow_overwrite_descendant flag is 0, then trying to set the tip
972
        # to an older revision ID has no effect.
973
        branch_token, repo_token = self.lock_branch()
974
        response = self.request.execute(
975
            '', branch_token, repo_token, rev_id_utf8, 0, 0)
976
        self.assertEqual(
977
            SuccessfulSmartServerResponse(('ok', 2, 'rev-2')),
978
            response)
979
        self.assertEqual(
980
            (2, 'rev-2'), self.tree.branch.last_revision_info())
981
982
        # If allow_overwrite_descendant flag is 1, then setting the tip to an
983
        # ancestor works.
984
        response = self.request.execute(
985
            '', branch_token, repo_token, rev_id_utf8, 0, 1)
986
        self.assertEqual(
987
            SuccessfulSmartServerResponse(('ok', 1, rev_id_utf8)),
988
            response)
989
        self.unlock_branch()
990
        self.assertEqual(
991
            (1, rev_id_utf8), self.tree.branch.last_revision_info())
992
3441.5.31 by Andrew Bennetts
Add test for allow_diverged flag.
993
    def make_branch_with_divergent_history(self):
994
        """Make a branch with divergent history in its repo.
995
996
        The branch's tip will be 'child-2', and the repo will also contain
997
        'child-1', which diverges from a common base revision.
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
998
        """
999
        self.tree.lock_write()
1000
        self.tree.add('')
1001
        r1 = self.tree.commit('1st commit')
1002
        revno_1, revid_1 = self.tree.branch.last_revision_info()
1003
        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.
1004
        # Undo the second commit
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
1005
        self.tree.branch.set_last_revision_info(revno_1, revid_1)
1006
        self.tree.set_parent_ids([revid_1])
3441.5.6 by Andrew Bennetts
Greatly simplify RemoteBranch.update_revisions. Still needs more tests.
1007
        # Make a new second commit, child-2.  child-2 has diverged from
1008
        # child-1.
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
1009
        new_r2 = self.tree.commit('2nd commit', rev_id='child-2')
1010
        self.tree.unlock()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1011
3441.5.31 by Andrew Bennetts
Add test for allow_diverged flag.
1012
    def test_not_allow_diverged(self):
1013
        """If allow_diverged is not passed, then setting a divergent history
1014
        returns a Diverged error.
1015
        """
1016
        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.
1017
        self.assertEqual(
3441.5.30 by Andrew Bennetts
Improve tests for all Branch.set_last_revision* verbs.
1018
            FailedSmartServerResponse(('Diverged',)),
1019
            self.set_last_revision('child-1', 2))
1020
        # The branch tip was not changed.
1021
        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.
1022
3441.5.31 by Andrew Bennetts
Add test for allow_diverged flag.
1023
    def test_allow_diverged(self):
1024
        """If allow_diverged is passed, then setting a divergent history
1025
        succeeds.
1026
        """
1027
        self.make_branch_with_divergent_history()
1028
        branch_token, repo_token = self.lock_branch()
1029
        response = self.request.execute(
1030
            '', branch_token, repo_token, 'child-1', 1, 0)
1031
        self.assertEqual(
1032
            SuccessfulSmartServerResponse(('ok', 2, 'child-1')),
1033
            response)
1034
        self.unlock_branch()
1035
        # The branch tip was changed.
1036
        self.assertEqual('child-1', self.tree.branch.last_revision())
1037
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1038
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1039
class TestSmartServerBranchRequestGetParent(tests.TestCaseWithMemoryTransport):
1040
1041
    def test_get_parent_none(self):
1042
        base_branch = self.make_branch('base')
1043
        request = smart.branch.SmartServerBranchGetParent(self.get_transport())
1044
        response = request.execute('base')
1045
        self.assertEquals(
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
1046
            SuccessfulSmartServerResponse(('',)), response)
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1047
1048
    def test_get_parent_something(self):
1049
        base_branch = self.make_branch('base')
1050
        base_branch.set_parent(self.get_url('foo'))
1051
        request = smart.branch.SmartServerBranchGetParent(self.get_transport())
1052
        response = request.execute('base')
1053
        self.assertEquals(
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
1054
            SuccessfulSmartServerResponse(("../foo",)),
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1055
            response)
1056
1057
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
1058
class TestSmartServerBranchRequestSetParent(tests.TestCaseWithMemoryTransport):
1059
1060
    def test_set_parent_none(self):
1061
        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.
1062
        branch.lock_write()
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
1063
        branch._set_parent_location('foo')
4288.1.9 by Robert Collins
Fix up test usable of _set_parent_location on unlocked branches.
1064
        branch.unlock()
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
1065
        request = smart.branch.SmartServerBranchRequestSetParentLocation(
1066
            self.get_transport())
1067
        branch_token = branch.lock_write()
1068
        repo_token = branch.repository.lock_write()
1069
        try:
1070
            response = request.execute('base', branch_token, repo_token, '')
1071
        finally:
1072
            branch.repository.unlock()
1073
            branch.unlock()
1074
        self.assertEqual(SuccessfulSmartServerResponse(()), response)
1075
        self.assertEqual(None, branch.get_parent())
1076
1077
    def test_set_parent_something(self):
1078
        branch = self.make_branch('base', format="1.9")
1079
        request = smart.branch.SmartServerBranchRequestSetParentLocation(
1080
            self.get_transport())
1081
        branch_token = branch.lock_write()
1082
        repo_token = branch.repository.lock_write()
1083
        try:
1084
            response = request.execute('base', branch_token, repo_token,
1085
            'http://bar/')
1086
        finally:
1087
            branch.repository.unlock()
1088
            branch.unlock()
1089
        self.assertEqual(SuccessfulSmartServerResponse(()), response)
1090
        self.assertEqual('http://bar/', branch.get_parent())
1091
1092
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.
1093
class TestSmartServerBranchRequestGetTagsBytes(tests.TestCaseWithMemoryTransport):
4556.2.2 by Andrew Bennetts
Handle failures more gracefully.
1094
    # Only called when the branch format and tags match [yay factory
1095
    # 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.
1096
1097
    def test_get_bytes(self):
1098
        base_branch = self.make_branch('base')
1099
        request = smart.branch.SmartServerBranchGetTagsBytes(
1100
            self.get_transport())
1101
        response = request.execute('base')
1102
        self.assertEquals(
1103
            SuccessfulSmartServerResponse(('',)), response)
1104
1105
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
1106
class TestSmartServerBranchRequestGetStackedOnURL(tests.TestCaseWithMemoryTransport):
1107
1108
    def test_get_stacked_on_url(self):
1109
        base_branch = self.make_branch('base', format='1.6')
1110
        stacked_branch = self.make_branch('stacked', format='1.6')
1111
        # typically should be relative
1112
        stacked_branch.set_stacked_on_url('../base')
1113
        request = smart.branch.SmartServerBranchRequestGetStackedOnURL(
1114
            self.get_transport())
1115
        response = request.execute('stacked')
1116
        self.assertEquals(
1117
            SmartServerResponse(('ok', '../base')),
1118
            response)
1119
1120
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1121
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1122
1123
    def setUp(self):
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1124
        tests.TestCaseWithMemoryTransport.setUp(self)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1125
1126
    def test_lock_write_on_unlocked_branch(self):
1127
        backing = self.get_transport()
1128
        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.
1129
        branch = self.make_branch('.', format='knit')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1130
        repository = branch.repository
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1131
        response = request.execute('')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1132
        branch_nonce = branch.control_files._lock.peek().get('nonce')
1133
        repository_nonce = repository.control_files._lock.peek().get('nonce')
1134
        self.assertEqual(
1135
            SmartServerResponse(('ok', branch_nonce, repository_nonce)),
1136
            response)
1137
        # The branch (and associated repository) is now locked.  Verify that
1138
        # with a new branch object.
1139
        new_branch = repository.bzrdir.open_branch()
1140
        self.assertRaises(errors.LockContention, new_branch.lock_write)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1141
        # Cleanup
1142
        request = smart.branch.SmartServerBranchRequestUnlock(backing)
1143
        response = request.execute('', branch_nonce, repository_nonce)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1144
1145
    def test_lock_write_on_locked_branch(self):
1146
        backing = self.get_transport()
1147
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
1148
        branch = self.make_branch('.')
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1149
        branch_token = branch.lock_write()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1150
        branch.leave_lock_in_place()
1151
        branch.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1152
        response = request.execute('')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1153
        self.assertEqual(
1154
            SmartServerResponse(('LockContention',)), response)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1155
        # Cleanup
1156
        branch.lock_write(branch_token)
1157
        branch.dont_leave_lock_in_place()
1158
        branch.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1159
1160
    def test_lock_write_with_tokens_on_locked_branch(self):
1161
        backing = self.get_transport()
1162
        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.
1163
        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).
1164
        branch_token = branch.lock_write()
1165
        repo_token = branch.repository.lock_write()
1166
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1167
        branch.leave_lock_in_place()
1168
        branch.repository.leave_lock_in_place()
1169
        branch.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1170
        response = request.execute('',
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1171
                                   branch_token, repo_token)
1172
        self.assertEqual(
1173
            SmartServerResponse(('ok', branch_token, repo_token)), response)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1174
        # Cleanup
1175
        branch.repository.lock_write(repo_token)
1176
        branch.repository.dont_leave_lock_in_place()
1177
        branch.repository.unlock()
1178
        branch.lock_write(branch_token)
1179
        branch.dont_leave_lock_in_place()
1180
        branch.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1181
1182
    def test_lock_write_with_mismatched_tokens_on_locked_branch(self):
1183
        backing = self.get_transport()
1184
        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.
1185
        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).
1186
        branch_token = branch.lock_write()
1187
        repo_token = branch.repository.lock_write()
1188
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1189
        branch.leave_lock_in_place()
1190
        branch.repository.leave_lock_in_place()
1191
        branch.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1192
        response = request.execute('',
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1193
                                   branch_token+'xxx', repo_token)
1194
        self.assertEqual(
1195
            SmartServerResponse(('TokenMismatch',)), response)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1196
        # Cleanup
1197
        branch.repository.lock_write(repo_token)
1198
        branch.repository.dont_leave_lock_in_place()
1199
        branch.repository.unlock()
1200
        branch.lock_write(branch_token)
1201
        branch.dont_leave_lock_in_place()
1202
        branch.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1203
1204
    def test_lock_write_on_locked_repo(self):
1205
        backing = self.get_transport()
1206
        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.
1207
        branch = self.make_branch('.', format='knit')
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1208
        repo = branch.repository
1209
        repo_token = repo.lock_write()
1210
        repo.leave_lock_in_place()
1211
        repo.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1212
        response = request.execute('')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1213
        self.assertEqual(
1214
            SmartServerResponse(('LockContention',)), response)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1215
        # Cleanup
1216
        repo.lock_write(repo_token)
1217
        repo.dont_leave_lock_in_place()
1218
        repo.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1219
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.
1220
    def test_lock_write_on_readonly_transport(self):
1221
        backing = self.get_readonly_transport()
1222
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
1223
        branch = self.make_branch('.')
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1224
        root = self.get_transport().clone('/')
1225
        path = urlutils.relative_url(root.base, self.get_transport().base)
1226
        response = request.execute(path)
2872.5.3 by Martin Pool
Pass back LockFailed from smart server lock methods
1227
        error_name, lock_str, why_str = response.args
1228
        self.assertFalse(response.is_successful())
1229
        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.
1230
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1231
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1232
class TestSmartServerBranchRequestUnlock(tests.TestCaseWithMemoryTransport):
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1233
1234
    def setUp(self):
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1235
        tests.TestCaseWithMemoryTransport.setUp(self)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1236
1237
    def test_unlock_on_locked_branch_and_repo(self):
1238
        backing = self.get_transport()
1239
        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.
1240
        branch = self.make_branch('.', format='knit')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1241
        # 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).
1242
        branch_token = branch.lock_write()
1243
        repo_token = branch.repository.lock_write()
1244
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1245
        # Unlock the branch (and repo) object, leaving the physical locks
1246
        # in place.
1247
        branch.leave_lock_in_place()
1248
        branch.repository.leave_lock_in_place()
1249
        branch.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1250
        response = request.execute('',
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1251
                                   branch_token, repo_token)
1252
        self.assertEqual(
1253
            SmartServerResponse(('ok',)), response)
1254
        # The branch is now unlocked.  Verify that with a new branch
1255
        # object.
1256
        new_branch = branch.bzrdir.open_branch()
1257
        new_branch.lock_write()
1258
        new_branch.unlock()
1259
1260
    def test_unlock_on_unlocked_branch_unlocked_repo(self):
1261
        backing = self.get_transport()
1262
        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.
1263
        branch = self.make_branch('.', format='knit')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1264
        response = request.execute(
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1265
            '', 'branch token', 'repo token')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1266
        self.assertEqual(
1267
            SmartServerResponse(('TokenMismatch',)), response)
1268
1269
    def test_unlock_on_unlocked_branch_locked_repo(self):
1270
        backing = self.get_transport()
1271
        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.
1272
        branch = self.make_branch('.', format='knit')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1273
        # Lock the repository.
1274
        repo_token = branch.repository.lock_write()
1275
        branch.repository.leave_lock_in_place()
1276
        branch.repository.unlock()
1277
        # Issue branch lock_write request on the unlocked branch (with locked
1278
        # repo).
1279
        response = request.execute(
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1280
            '', 'branch token', repo_token)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1281
        self.assertEqual(
1282
            SmartServerResponse(('TokenMismatch',)), response)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1283
        # Cleanup
1284
        branch.repository.lock_write(repo_token)
1285
        branch.repository.dont_leave_lock_in_place()
1286
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1287
1288
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1289
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).
1290
1291
    def test_no_repository(self):
1292
        """Raise NoRepositoryPresent when there is a bzrdir and no repo."""
1293
        # we test this using a shared repository above the named path,
1294
        # thus checking the right search logic is used - that is, that
1295
        # its the exact path being looked at and the server is not
1296
        # searching.
1297
        backing = self.get_transport()
2018.5.58 by Wouter van Heyst
Small test fixes to reflect naming and documentation
1298
        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).
1299
        self.make_repository('.', shared=True)
1300
        self.make_bzrdir('subdir')
1301
        self.assertRaises(errors.NoRepositoryPresent,
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1302
            request.execute, 'subdir')
1303
1304
3441.5.4 by Andrew Bennetts
Fix test failures, and add some tests for the remote graph heads RPC.
1305
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.
1306
3211.5.3 by Robert Collins
Adjust size of batch and change gzip comments to bzip2.
1307
    def test_trivial_bzipped(self):
1308
        # 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.
1309
        backing = self.get_transport()
1310
        request = smart.repository.SmartServerRepositoryGetParentMap(backing)
1311
        tree = self.make_branch_and_memory_tree('.')
1312
1313
        self.assertEqual(None,
2692.1.24 by Andrew Bennetts
Merge from bzr.dev.
1314
            request.execute('', 'missing-id'))
4190.1.3 by Robert Collins
Allow optional inclusion of ghost data in server get_parent_map calls.
1315
        # 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.
1316
        self.assertEqual(
3211.5.2 by Robert Collins
Change RemoteRepository.get_parent_map to use bz2 not gzip for compression.
1317
            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.
1318
            request.do_body('\n\n0\n'))
1319
4190.1.3 by Robert Collins
Allow optional inclusion of ghost data in server get_parent_map calls.
1320
    def test_trivial_include_missing(self):
1321
        backing = self.get_transport()
1322
        request = smart.repository.SmartServerRepositoryGetParentMap(backing)
1323
        tree = self.make_branch_and_memory_tree('.')
1324
1325
        self.assertEqual(None,
1326
            request.execute('', 'missing-id', 'include-missing:'))
1327
        self.assertEqual(
1328
            SuccessfulSmartServerResponse(('ok', ),
1329
                bz2.compress('missing:missing-id')),
1330
            request.do_body('\n\n0\n'))
1331
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.
1332
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1333
class TestSmartServerRepositoryGetRevisionGraph(tests.TestCaseWithMemoryTransport):
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1334
1335
    def test_none_argument(self):
1336
        backing = self.get_transport()
1337
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
1338
        tree = self.make_branch_and_memory_tree('.')
1339
        tree.lock_write()
1340
        tree.add('')
1341
        r1 = tree.commit('1st commit')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1342
        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)
1343
        tree.unlock()
1344
1345
        # the lines of revision_id->revision_parent_list has no guaranteed
1346
        # order coming out of a dict, so sort both our test and response
1347
        lines = sorted([' '.join([r2, r1]), r1])
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1348
        response = request.execute('', '')
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1349
        response.body = '\n'.join(sorted(response.body.split('\n')))
1350
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
1351
        self.assertEqual(
1352
            SmartServerResponse(('ok', ), '\n'.join(lines)), response)
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1353
1354
    def test_specific_revision_argument(self):
1355
        backing = self.get_transport()
1356
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
1357
        tree = self.make_branch_and_memory_tree('.')
1358
        tree.lock_write()
1359
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1360
        rev_id_utf8 = u'\xc9'.encode('utf-8')
1361
        r1 = tree.commit('1st commit', rev_id=rev_id_utf8)
1362
        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)
1363
        tree.unlock()
1364
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1365
        self.assertEqual(SmartServerResponse(('ok', ), rev_id_utf8),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1366
            request.execute('', rev_id_utf8))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1367
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1368
    def test_no_such_revision(self):
1369
        backing = self.get_transport()
1370
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
1371
        tree = self.make_branch_and_memory_tree('.')
1372
        tree.lock_write()
1373
        tree.add('')
1374
        r1 = tree.commit('1st commit')
1375
        tree.unlock()
1376
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1377
        # Note that it still returns body (of zero bytes).
1378
        self.assertEqual(
1379
            SmartServerResponse(('nosuchrevision', 'missingrevision', ), ''),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1380
            request.execute('', 'missingrevision'))
1381
1382
4419.2.6 by Andrew Bennetts
Add tests for server-side logic, and fix the bugs exposed by those tests.
1383
class TestSmartServerRepositoryGetRevIdForRevno(tests.TestCaseWithMemoryTransport):
1384
1385
    def test_revno_found(self):
1386
        backing = self.get_transport()
1387
        request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
1388
        tree = self.make_branch_and_memory_tree('.')
1389
        tree.lock_write()
1390
        tree.add('')
1391
        rev1_id_utf8 = u'\xc8'.encode('utf-8')
1392
        rev2_id_utf8 = u'\xc9'.encode('utf-8')
1393
        tree.commit('1st commit', rev_id=rev1_id_utf8)
1394
        tree.commit('2nd commit', rev_id=rev2_id_utf8)
1395
        tree.unlock()
1396
1397
        self.assertEqual(SmartServerResponse(('ok', rev1_id_utf8)),
1398
            request.execute('', 1, (2, rev2_id_utf8)))
1399
1400
    def test_known_revid_missing(self):
1401
        backing = self.get_transport()
1402
        request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
1403
        repo = self.make_repository('.')
1404
        self.assertEqual(
1405
            FailedSmartServerResponse(('nosuchrevision', 'ghost')),
1406
            request.execute('', 1, (2, 'ghost')))
1407
1408
    def test_history_incomplete(self):
1409
        backing = self.get_transport()
1410
        request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
1411
        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.
1412
        parent.lock_write()
1413
        parent.add([''], ['TREE_ROOT'])
4419.2.6 by Andrew Bennetts
Add tests for server-side logic, and fix the bugs exposed by those tests.
1414
        r1 = parent.commit(message='first commit')
1415
        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.
1416
        parent.unlock()
4419.2.6 by Andrew Bennetts
Add tests for server-side logic, and fix the bugs exposed by those tests.
1417
        local = self.make_branch_and_memory_tree('local', format='1.9')
1418
        local.branch.pull(parent.branch)
1419
        local.set_parent_ids([r2])
1420
        r3 = local.commit(message='local commit')
1421
        local.branch.create_clone_on_transport(
1422
            self.get_transport('stacked'), stacked_on=self.get_url('parent'))
1423
        self.assertEqual(
1424
            SmartServerResponse(('history-incomplete', 2, r2)),
1425
            request.execute('stacked', 1, (3, r3)))
1426
4476.3.68 by Andrew Bennetts
Review comments from John.
1427
4070.9.14 by Andrew Bennetts
Tweaks requested by Robert's review.
1428
class TestSmartServerRepositoryGetStream(tests.TestCaseWithMemoryTransport):
1429
1430
    def make_two_commit_repo(self):
1431
        tree = self.make_branch_and_memory_tree('.')
1432
        tree.lock_write()
1433
        tree.add('')
1434
        r1 = tree.commit('1st commit')
1435
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
1436
        tree.unlock()
1437
        repo = tree.branch.repository
1438
        return repo, r1, r2
1439
1440
    def test_ancestry_of(self):
1441
        """The search argument may be a 'ancestry-of' some heads'."""
1442
        backing = self.get_transport()
1443
        request = smart.repository.SmartServerRepositoryGetStream(backing)
1444
        repo, r1, r2 = self.make_two_commit_repo()
1445
        fetch_spec = ['ancestry-of', r2]
1446
        lines = '\n'.join(fetch_spec)
1447
        request.execute('', repo._format.network_name())
1448
        response = request.do_body(lines)
1449
        self.assertEqual(('ok',), response.args)
1450
        stream_bytes = ''.join(response.body_stream)
1451
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
1452
1453
    def test_search(self):
1454
        """The search argument may be a 'search' of some explicit keys."""
1455
        backing = self.get_transport()
1456
        request = smart.repository.SmartServerRepositoryGetStream(backing)
1457
        repo, r1, r2 = self.make_two_commit_repo()
1458
        fetch_spec = ['search', '%s %s' % (r1, r2), 'null:', '2']
1459
        lines = '\n'.join(fetch_spec)
1460
        request.execute('', repo._format.network_name())
1461
        response = request.do_body(lines)
1462
        self.assertEqual(('ok',), response.args)
1463
        stream_bytes = ''.join(response.body_stream)
1464
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
1465
1466
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1467
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).
1468
1469
    def test_missing_revision(self):
1470
        """For a missing revision, ('no', ) is returned."""
1471
        backing = self.get_transport()
1472
        request = smart.repository.SmartServerRequestHasRevision(backing)
1473
        self.make_repository('.')
1474
        self.assertEqual(SmartServerResponse(('no', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1475
            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).
1476
1477
    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.
1478
        """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).
1479
        backing = self.get_transport()
1480
        request = smart.repository.SmartServerRequestHasRevision(backing)
1481
        tree = self.make_branch_and_memory_tree('.')
1482
        tree.lock_write()
1483
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1484
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
1485
        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).
1486
        tree.unlock()
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1487
        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.
1488
        self.assertEqual(SmartServerResponse(('yes', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1489
            request.execute('', rev_id_utf8))
1490
1491
1492
class TestSmartServerRepositoryGatherStats(tests.TestCaseWithMemoryTransport):
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1493
1494
    def test_empty_revid(self):
1495
        """With an empty revid, we get only size an number and revisions"""
1496
        backing = self.get_transport()
1497
        request = smart.repository.SmartServerRepositoryGatherStats(backing)
1498
        repository = self.make_repository('.')
1499
        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.
1500
        expected_body = 'revisions: 0\n'
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1501
        self.assertEqual(SmartServerResponse(('ok', ), expected_body),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1502
                         request.execute('', '', 'no'))
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1503
1504
    def test_revid_with_committers(self):
1505
        """For a revid we get more infos."""
1506
        backing = self.get_transport()
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1507
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1508
        request = smart.repository.SmartServerRepositoryGatherStats(backing)
1509
        tree = self.make_branch_and_memory_tree('.')
1510
        tree.lock_write()
1511
        tree.add('')
1512
        # Let's build a predictable result
1513
        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.
1514
        tree.commit('a commit', timestamp=654321.4, timezone=0,
1515
                    rev_id=rev_id_utf8)
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1516
        tree.unlock()
1517
1518
        stats = tree.branch.repository.gather_stats()
1519
        expected_body = ('firstrev: 123456.200 3600\n'
1520
                         '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.
1521
                         'revisions: 2\n')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1522
        self.assertEqual(SmartServerResponse(('ok', ), expected_body),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1523
                         request.execute('',
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1524
                                         rev_id_utf8, 'no'))
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1525
1526
    def test_not_empty_repository_with_committers(self):
1527
        """For a revid and requesting committers we get the whole thing."""
1528
        backing = self.get_transport()
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1529
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1530
        request = smart.repository.SmartServerRepositoryGatherStats(backing)
1531
        tree = self.make_branch_and_memory_tree('.')
1532
        tree.lock_write()
1533
        tree.add('')
1534
        # Let's build a predictable result
1535
        tree.commit('a commit', timestamp=123456.2, timezone=3600,
1536
                    committer='foo')
1537
        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.
1538
                    committer='bar', rev_id=rev_id_utf8)
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1539
        tree.unlock()
1540
        stats = tree.branch.repository.gather_stats()
1541
1542
        expected_body = ('committers: 2\n'
1543
                         'firstrev: 123456.200 3600\n'
1544
                         '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.
1545
                         'revisions: 2\n')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1546
        self.assertEqual(SmartServerResponse(('ok', ), expected_body),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1547
                         request.execute('',
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
1548
                                         rev_id_utf8, 'yes'))
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1549
1550
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1551
class TestSmartServerRepositoryIsShared(tests.TestCaseWithMemoryTransport):
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1552
1553
    def test_is_shared(self):
1554
        """For a shared repository, ('yes', ) is returned."""
1555
        backing = self.get_transport()
1556
        request = smart.repository.SmartServerRepositoryIsShared(backing)
1557
        self.make_repository('.', shared=True)
1558
        self.assertEqual(SmartServerResponse(('yes', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1559
            request.execute('', ))
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1560
1561
    def test_is_not_shared(self):
2018.5.58 by Wouter van Heyst
Small test fixes to reflect naming and documentation
1562
        """For a shared repository, ('no', ) is returned."""
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1563
        backing = self.get_transport()
1564
        request = smart.repository.SmartServerRepositoryIsShared(backing)
1565
        self.make_repository('.', shared=False)
1566
        self.assertEqual(SmartServerResponse(('no', )),
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1567
            request.execute('', ))
1568
1569
1570
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1571
1572
    def test_lock_write_on_unlocked_repo(self):
1573
        backing = self.get_transport()
1574
        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.
1575
        repository = self.make_repository('.', format='knit')
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1576
        response = request.execute('')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1577
        nonce = repository.control_files._lock.peek().get('nonce')
1578
        self.assertEqual(SmartServerResponse(('ok', nonce)), response)
1579
        # The repository is now locked.  Verify that with a new repository
1580
        # object.
1581
        new_repo = repository.bzrdir.open_repository()
1582
        self.assertRaises(errors.LockContention, new_repo.lock_write)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1583
        # Cleanup
1584
        request = smart.repository.SmartServerRepositoryUnlock(backing)
1585
        response = request.execute('', nonce)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1586
1587
    def test_lock_write_on_locked_repo(self):
1588
        backing = self.get_transport()
1589
        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.
1590
        repository = self.make_repository('.', format='knit')
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1591
        repo_token = repository.lock_write()
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1592
        repository.leave_lock_in_place()
1593
        repository.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1594
        response = request.execute('')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1595
        self.assertEqual(
1596
            SmartServerResponse(('LockContention',)), response)
4327.1.10 by Vincent Ladeuil
Fix 10 more lock-related test failures.
1597
        # Cleanup
1598
        repository.lock_write(repo_token)
1599
        repository.dont_leave_lock_in_place()
1600
        repository.unlock()
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1601
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.
1602
    def test_lock_write_on_readonly_transport(self):
1603
        backing = self.get_readonly_transport()
1604
        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.
1605
        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.
1606
        response = request.execute('')
2872.5.3 by Martin Pool
Pass back LockFailed from smart server lock methods
1607
        self.assertFalse(response.is_successful())
1608
        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.
1609
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1610
4144.3.1 by Andrew Bennetts
Add Repository.insert_stream_locked server-side implementation, plus tests for server-side _translate_error.
1611
class TestInsertStreamBase(tests.TestCaseWithMemoryTransport):
1612
1613
    def make_empty_byte_stream(self, repo):
1614
        byte_stream = smart.repository._stream_to_byte_stream([], repo._format)
1615
        return ''.join(byte_stream)
1616
1617
1618
class TestSmartServerRepositoryInsertStream(TestInsertStreamBase):
1619
1620
    def test_insert_stream_empty(self):
1621
        backing = self.get_transport()
1622
        request = smart.repository.SmartServerRepositoryInsertStream(backing)
1623
        repository = self.make_repository('.')
1624
        response = request.execute('', '')
1625
        self.assertEqual(None, response)
1626
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1627
        self.assertEqual(None, response)
1628
        response = request.do_end()
1629
        self.assertEqual(SmartServerResponse(('ok', )), response)
1630
        
1631
1632
class TestSmartServerRepositoryInsertStreamLocked(TestInsertStreamBase):
1633
1634
    def test_insert_stream_empty(self):
1635
        backing = self.get_transport()
1636
        request = smart.repository.SmartServerRepositoryInsertStreamLocked(
1637
            backing)
1638
        repository = self.make_repository('.', format='knit')
1639
        lock_token = repository.lock_write()
1640
        response = request.execute('', '', lock_token)
1641
        self.assertEqual(None, response)
1642
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1643
        self.assertEqual(None, response)
1644
        response = request.do_end()
1645
        self.assertEqual(SmartServerResponse(('ok', )), response)
1646
        repository.unlock()
1647
1648
    def test_insert_stream_with_wrong_lock_token(self):
1649
        backing = self.get_transport()
1650
        request = smart.repository.SmartServerRepositoryInsertStreamLocked(
1651
            backing)
1652
        repository = self.make_repository('.', format='knit')
1653
        lock_token = repository.lock_write()
1654
        self.assertRaises(
1655
            errors.TokenMismatch, request.execute, '', '', 'wrong-token')
1656
        repository.unlock()
1657
1658
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1659
class TestSmartServerRepositoryUnlock(tests.TestCaseWithMemoryTransport):
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1660
1661
    def setUp(self):
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1662
        tests.TestCaseWithMemoryTransport.setUp(self)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1663
1664
    def test_unlock_on_locked_repo(self):
1665
        backing = self.get_transport()
1666
        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.
1667
        repository = self.make_repository('.', format='knit')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1668
        token = repository.lock_write()
1669
        repository.leave_lock_in_place()
1670
        repository.unlock()
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1671
        response = request.execute('', token)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1672
        self.assertEqual(
1673
            SmartServerResponse(('ok',)), response)
1674
        # The repository is now unlocked.  Verify that with a new repository
1675
        # object.
1676
        new_repo = repository.bzrdir.open_repository()
1677
        new_repo.lock_write()
1678
        new_repo.unlock()
1679
1680
    def test_unlock_on_unlocked_repo(self):
1681
        backing = self.get_transport()
1682
        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.
1683
        repository = self.make_repository('.', format='knit')
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1684
        response = request.execute('', 'some token')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1685
        self.assertEqual(
1686
            SmartServerResponse(('TokenMismatch',)), response)
1687
1688
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1689
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.
1690
1691
    def test_is_readonly_no(self):
1692
        backing = self.get_transport()
1693
        request = smart.request.SmartServerIsReadonly(backing)
1694
        response = request.execute()
1695
        self.assertEqual(
1696
            SmartServerResponse(('no',)), response)
1697
1698
    def test_is_readonly_yes(self):
1699
        backing = self.get_readonly_transport()
1700
        request = smart.request.SmartServerIsReadonly(backing)
1701
        response = request.execute()
1702
        self.assertEqual(
1703
            SmartServerResponse(('yes',)), response)
1704
1705
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
1706
class TestSmartServerRepositorySetMakeWorkingTrees(tests.TestCaseWithMemoryTransport):
1707
1708
    def test_set_false(self):
1709
        backing = self.get_transport()
1710
        repo = self.make_repository('.', shared=True)
1711
        repo.set_make_working_trees(True)
1712
        request_class = smart.repository.SmartServerRepositorySetMakeWorkingTrees
1713
        request = request_class(backing)
1714
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)),
1715
            request.execute('', 'False'))
1716
        repo = repo.bzrdir.open_repository()
1717
        self.assertFalse(repo.make_working_trees())
1718
1719
    def test_set_true(self):
1720
        backing = self.get_transport()
1721
        repo = self.make_repository('.', shared=True)
1722
        repo.set_make_working_trees(False)
1723
        request_class = smart.repository.SmartServerRepositorySetMakeWorkingTrees
1724
        request = request_class(backing)
1725
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)),
1726
            request.execute('', 'True'))
1727
        repo = repo.bzrdir.open_repository()
1728
        self.assertTrue(repo.make_working_trees())
1729
1730
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1731
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1732
1733
    def make_repo_needing_autopacking(self, path='.'):
1734
        # Make a repo in need of autopacking.
1735
        tree = self.make_branch_and_tree('.', format='pack-0.92')
1736
        repo = tree.branch.repository
1737
        # monkey-patch the pack collection to disable autopacking
1738
        repo._pack_collection._max_pack_count = lambda count: count
1739
        for x in range(10):
1740
            tree.commit('commit %s' % x)
1741
        self.assertEqual(10, len(repo._pack_collection.names()))
1742
        del repo._pack_collection._max_pack_count
1743
        return repo
1744
1745
    def test_autopack_needed(self):
1746
        repo = self.make_repo_needing_autopacking()
4145.1.6 by Robert Collins
More test fallout, but all caught now.
1747
        repo.lock_write()
1748
        self.addCleanup(repo.unlock)
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1749
        backing = self.get_transport()
1750
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1751
            backing)
1752
        response = request.execute('')
1753
        self.assertEqual(SmartServerResponse(('ok',)), response)
1754
        repo._pack_collection.reload_pack_names()
1755
        self.assertEqual(1, len(repo._pack_collection.names()))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1756
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1757
    def test_autopack_not_needed(self):
1758
        tree = self.make_branch_and_tree('.', format='pack-0.92')
1759
        repo = tree.branch.repository
4145.1.6 by Robert Collins
More test fallout, but all caught now.
1760
        repo.lock_write()
1761
        self.addCleanup(repo.unlock)
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1762
        for x in range(9):
1763
            tree.commit('commit %s' % x)
1764
        backing = self.get_transport()
1765
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1766
            backing)
1767
        response = request.execute('')
1768
        self.assertEqual(SmartServerResponse(('ok',)), response)
1769
        repo._pack_collection.reload_pack_names()
1770
        self.assertEqual(9, len(repo._pack_collection.names()))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1771
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1772
    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.
1773
        """A request to autopack a non-pack repo is a no-op."""
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1774
        repo = self.make_repository('.', format='knit')
1775
        backing = self.get_transport()
1776
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1777
            backing)
1778
        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.
1779
        self.assertEqual(SmartServerResponse(('ok',)), response)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1780
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1781
4760.2.5 by Andrew Bennetts
Add some more tests.
1782
class TestSmartServerVfsGet(tests.TestCaseWithMemoryTransport):
1783
1784
    def test_unicode_path(self):
1785
        """VFS requests expect unicode paths to be escaped."""
1786
        filename = u'foo\N{INTERROBANG}'
1787
        filename_escaped = urlutils.escape(filename)
1788
        backing = self.get_transport()
1789
        request = smart.vfs.GetRequest(backing)
1790
        backing.put_bytes_non_atomic(filename_escaped, 'contents')
1791
        self.assertEqual(SmartServerResponse(('ok', ), 'contents'),
1792
            request.execute(filename_escaped))
1793
1794
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
1795
class TestHandlers(tests.TestCase):
1796
    """Tests for the request.request_handlers object."""
1797
3526.3.1 by Andrew Bennetts
Remove registrations of defunct HPSS verbs.
1798
    def test_all_registrations_exist(self):
1799
        """All registered request_handlers can be found."""
1800
        # If there's a typo in a register_lazy call, this loop will fail with
1801
        # an AttributeError.
1802
        for key, item in smart.request.request_handlers.iteritems():
1803
            pass
1804
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1805
    def assertHandlerEqual(self, verb, handler):
1806
        self.assertEqual(smart.request.request_handlers.get(verb), handler)
1807
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
1808
    def test_registered_methods(self):
1809
        """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()
1810
        self.assertHandlerEqual('Branch.get_config_file',
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1811
            smart.branch.SmartServerBranchGetConfigFile)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1812
        self.assertHandlerEqual('Branch.get_parent',
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1813
            smart.branch.SmartServerBranchGetParent)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1814
        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.
1815
            smart.branch.SmartServerBranchGetTagsBytes)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1816
        self.assertHandlerEqual('Branch.lock_write',
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1817
            smart.branch.SmartServerBranchRequestLockWrite)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1818
        self.assertHandlerEqual('Branch.last_revision_info',
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1819
            smart.branch.SmartServerBranchRequestLastRevisionInfo)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1820
        self.assertHandlerEqual('Branch.revision_history',
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
1821
            smart.branch.SmartServerRequestRevisionHistory)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1822
        self.assertHandlerEqual('Branch.set_config_option',
4226.2.1 by Robert Collins
Set branch config options via a smart method.
1823
            smart.branch.SmartServerBranchRequestSetConfigOption)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1824
        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
1825
            smart.branch.SmartServerBranchRequestSetLastRevision)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1826
        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.
1827
            smart.branch.SmartServerBranchRequestSetLastRevisionInfo)
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
1828
        self.assertHandlerEqual('Branch.set_last_revision_ex',
1829
            smart.branch.SmartServerBranchRequestSetLastRevisionEx)
1830
        self.assertHandlerEqual('Branch.set_parent_location',
1831
            smart.branch.SmartServerBranchRequestSetParentLocation)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1832
        self.assertHandlerEqual('Branch.unlock',
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1833
            smart.branch.SmartServerBranchRequestUnlock)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1834
        self.assertHandlerEqual('BzrDir.find_repository',
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
1835
            smart.bzrdir.SmartServerRequestFindRepositoryV1)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1836
        self.assertHandlerEqual('BzrDir.find_repositoryV2',
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
1837
            smart.bzrdir.SmartServerRequestFindRepositoryV2)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1838
        self.assertHandlerEqual('BzrDirFormat.initialize',
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
1839
            smart.bzrdir.SmartServerRequestInitializeBzrDir)
4436.1.1 by Andrew Bennetts
Rename BzrDirFormat.initialize_ex verb to BzrDirFormat.initialize_ex_1.16.
1840
        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.
1841
            smart.bzrdir.SmartServerRequestBzrDirInitializeEx)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1842
        self.assertHandlerEqual('BzrDir.cloning_metadir',
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
1843
            smart.bzrdir.SmartServerBzrDirRequestCloningMetaDir)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1844
        self.assertHandlerEqual('BzrDir.get_config_file',
1845
            smart.bzrdir.SmartServerBzrDirRequestConfigFile)
1846
        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.
1847
            smart.bzrdir.SmartServerRequestOpenBranch)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1848
        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.
1849
            smart.bzrdir.SmartServerRequestOpenBranchV2)
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
1850
        self.assertHandlerEqual('BzrDir.open_branchV3',
1851
            smart.bzrdir.SmartServerRequestOpenBranchV3)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1852
        self.assertHandlerEqual('PackRepository.autopack',
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1853
            smart.packrepository.SmartServerPackRepositoryAutopack)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1854
        self.assertHandlerEqual('Repository.gather_stats',
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
1855
            smart.repository.SmartServerRepositoryGatherStats)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1856
        self.assertHandlerEqual('Repository.get_parent_map',
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
1857
            smart.repository.SmartServerRepositoryGetParentMap)
4419.2.6 by Andrew Bennetts
Add tests for server-side logic, and fix the bugs exposed by those tests.
1858
        self.assertHandlerEqual('Repository.get_rev_id_for_revno',
1859
            smart.repository.SmartServerRepositoryGetRevIdForRevno)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1860
        self.assertHandlerEqual('Repository.get_revision_graph',
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1861
            smart.repository.SmartServerRepositoryGetRevisionGraph)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1862
        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.
1863
            smart.repository.SmartServerRepositoryGetStream)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1864
        self.assertHandlerEqual('Repository.has_revision',
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
1865
            smart.repository.SmartServerRequestHasRevision)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1866
        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.
1867
            smart.repository.SmartServerRepositoryInsertStream)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1868
        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.
1869
            smart.repository.SmartServerRepositoryInsertStreamLocked)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1870
        self.assertHandlerEqual('Repository.is_shared',
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1871
            smart.repository.SmartServerRepositoryIsShared)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1872
        self.assertHandlerEqual('Repository.lock_write',
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1873
            smart.repository.SmartServerRepositoryLockWrite)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1874
        self.assertHandlerEqual('Repository.tarball',
2535.3.69 by Andrew Bennetts
Add check for Repository.stream_knit_data_for_revisions to TestHandlers.test_registered_methods.
1875
            smart.repository.SmartServerRepositoryTarball)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1876
        self.assertHandlerEqual('Repository.unlock',
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1877
            smart.repository.SmartServerRepositoryUnlock)
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1878
        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.
1879
            smart.request.SmartServerIsReadonly)