/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
3407.2.2 by Martin Pool
Remove special case in RemoteBranchLockableFiles for branch.conf
1
# Copyright (C) 2006, 2007, 2008 Canonical Ltd
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for remote bzrdir/branch/repo/etc
18
19
These are proxy objects which act on remote objects by sending messages
20
through a smart client.  The proxies are to be created when attempting to open
4032.1.2 by John Arbash Meinel
Track down a few more files that have trailing whitespace.
21
the object given a transport that supports smartserver rpc operations.
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
22
23
These tests correspond to tests.test_smart, which exercises the server side.
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
24
"""
25
3211.5.2 by Robert Collins
Change RemoteRepository.get_parent_map to use bz2 not gzip for compression.
26
import bz2
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
27
from cStringIO import StringIO
28
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
29
from bzrlib import (
3834.3.2 by Andrew Bennetts
Preserve BzrBranch5's _synchronize_history code without affecting Branch or BzrBranch7; add effort test for RemoteBranch.copy_content_into.
30
    bzrdir,
3777.1.3 by Aaron Bentley
Use SSH default username from authentication.conf
31
    config,
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
32
    errors,
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
33
    graph,
2535.3.39 by Andrew Bennetts
Tidy some XXXs.
34
    pack,
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
35
    remote,
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
36
    repository,
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
37
    smart,
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
38
    tests,
3691.2.4 by Martin Pool
Add FakeRemoteTransport to clarify test_remote
39
    urlutils,
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
40
    )
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
41
from bzrlib.branch import Branch
42
from bzrlib.bzrdir import BzrDir, BzrDirFormat
43
from bzrlib.remote import (
44
    RemoteBranch,
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.
45
    RemoteBranchFormat,
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
46
    RemoteBzrDir,
47
    RemoteBzrDirFormat,
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
48
    RemoteRepository,
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
49
    )
50
from bzrlib.revision import NULL_REVISION
2432.3.2 by Andrew Bennetts
Add test, and tidy implementation.
51
from bzrlib.smart import server, medium
2018.5.159 by Andrew Bennetts
Rename SmartClient to _SmartClient.
52
from bzrlib.smart.client import _SmartClient
3287.6.4 by Robert Collins
Fix up deprecation warnings for get_revision_graph.
53
from bzrlib.symbol_versioning import one_four
4118.1.1 by Andrew Bennetts
Fix performance regression (many small round-trips) when pushing to a remote pack, and tidy the tests.
54
from bzrlib.tests import (
55
    condition_isinstance,
56
    split_suite_by_condition,
57
    multiply_tests,
58
    )
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
59
from bzrlib.transport import get_transport, http
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
60
from bzrlib.transport.memory import MemoryTransport
3777.1.3 by Aaron Bentley
Use SSH default username from authentication.conf
61
from bzrlib.transport.remote import (
62
    RemoteTransport,
63
    RemoteSSHTransport,
64
    RemoteTCPTransport,
65
)
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
66
4118.1.1 by Andrew Bennetts
Fix performance regression (many small round-trips) when pushing to a remote pack, and tidy the tests.
67
def load_tests(standard_tests, module, loader):
68
    to_adapt, result = split_suite_by_condition(
69
        standard_tests, condition_isinstance(BasicRemoteObjectTests))
70
    smart_server_version_scenarios = [
71
        ('HPSS-v2', 
72
            {'transport_server': server.SmartTCPServer_for_testing_v2_only}),
73
        ('HPSS-v3', 
74
            {'transport_server': server.SmartTCPServer_for_testing})]
75
    return multiply_tests(to_adapt, smart_server_version_scenarios, result)
76
2018.5.24 by Andrew Bennetts
Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts)
77
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
78
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
79
80
    def setUp(self):
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
81
        super(BasicRemoteObjectTests, self).setUp()
82
        self.transport = self.get_transport()
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
83
        # make a branch that can be opened over the smart transport
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
84
        self.local_wt = BzrDir.create_standalone_workingtree('.')
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
85
2018.5.171 by Andrew Bennetts
Disconnect RemoteTransports in some tests to avoid tripping up test_strace with leftover threads from previous tests.
86
    def tearDown(self):
87
        self.transport.disconnect()
88
        tests.TestCaseWithTransport.tearDown(self)
89
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
90
    def test_create_remote_bzrdir(self):
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
91
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
92
        self.assertIsInstance(b, BzrDir)
93
94
    def test_open_remote_branch(self):
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
95
        # open a standalone branch in the working directory
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
96
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
97
        branch = b.open_branch()
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
98
        self.assertIsInstance(branch, Branch)
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
99
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
100
    def test_remote_repository(self):
101
        b = BzrDir.open_from_transport(self.transport)
102
        repo = b.open_repository()
2018.5.106 by Andrew Bennetts
Update tests in test_remote to use utf-8 byte strings for revision IDs, rather than unicode strings.
103
        revid = u'\xc823123123'.encode('utf8')
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
104
        self.assertFalse(repo.has_revision(revid))
105
        self.local_wt.commit(message='test commit', rev_id=revid)
106
        self.assertTrue(repo.has_revision(revid))
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
107
108
    def test_remote_branch_revision_history(self):
109
        b = BzrDir.open_from_transport(self.transport).open_branch()
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
110
        self.assertEqual([], b.revision_history())
111
        r1 = self.local_wt.commit('1st commit')
2018.5.106 by Andrew Bennetts
Update tests in test_remote to use utf-8 byte strings for revision IDs, rather than unicode strings.
112
        r2 = self.local_wt.commit('1st commit', rev_id=u'\xc8'.encode('utf8'))
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
113
        self.assertEqual([r1, r2], b.revision_history())
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
114
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
115
    def test_find_correct_format(self):
2018.5.20 by Andrew Bennetts
Move bzrlib/transport/smart/_smart.py to bzrlib/transport/remote.py and rename SmartTransport to RemoteTransport (Robert Collins, Andrew Bennetts)
116
        """Should open a RemoteBzrDir over a RemoteTransport"""
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
117
        fmt = BzrDirFormat.find_format(self.transport)
2018.5.169 by Andrew Bennetts
Add a _server_formats flag to BzrDir.open_from_transport and BzrDirFormat.find_format, make RemoteBranch.control_files into a property.
118
        self.assertTrue(RemoteBzrDirFormat
119
                        in BzrDirFormat._control_server_formats)
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
120
        self.assertIsInstance(fmt, remote.RemoteBzrDirFormat)
121
122
    def test_open_detected_smart_format(self):
123
        fmt = BzrDirFormat.find_format(self.transport)
124
        d = fmt.open(self.transport)
125
        self.assertIsInstance(d, BzrDir)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
126
2477.1.1 by Martin Pool
Add RemoteBranch repr
127
    def test_remote_branch_repr(self):
128
        b = BzrDir.open_from_transport(self.transport).open_branch()
129
        self.assertStartsWith(str(b), 'RemoteBranch(')
130
4103.2.2 by Andrew Bennetts
Fix RemoteBranchFormat.supports_stacking()
131
    def test_remote_branch_format_supports_stacking(self):
132
        t = self.transport
133
        self.make_branch('unstackable', format='pack-0.92')
134
        b = BzrDir.open_from_transport(t.clone('unstackable')).open_branch()
135
        self.assertFalse(b._format.supports_stacking())
136
        self.make_branch('stackable', format='1.9')
137
        b = BzrDir.open_from_transport(t.clone('stackable')).open_branch()
138
        self.assertTrue(b._format.supports_stacking())
139
4118.1.1 by Andrew Bennetts
Fix performance regression (many small round-trips) when pushing to a remote pack, and tidy the tests.
140
    def test_remote_repo_format_supports_external_references(self):
141
        t = self.transport
142
        bd = self.make_bzrdir('unstackable', format='pack-0.92')
143
        r = bd.create_repository()
144
        self.assertFalse(r._format.supports_external_lookups)
145
        r = BzrDir.open_from_transport(t.clone('unstackable')).open_repository()
146
        self.assertFalse(r._format.supports_external_lookups)
147
        bd = self.make_bzrdir('stackable', format='1.9')
148
        r = bd.create_repository()
149
        self.assertTrue(r._format.supports_external_lookups)
150
        r = BzrDir.open_from_transport(t.clone('stackable')).open_repository()
151
        self.assertTrue(r._format.supports_external_lookups)
152
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
153
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
154
class FakeProtocol(object):
155
    """Lookalike SmartClientRequestProtocolOne allowing body reading tests."""
156
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
157
    def __init__(self, body, fake_client):
2535.4.2 by Andrew Bennetts
Nasty hackery to make stream_knit_data_for_revisions response use streaming.
158
        self.body = body
159
        self._body_buffer = None
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
160
        self._fake_client = fake_client
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
161
162
    def read_body_bytes(self, count=-1):
2535.4.2 by Andrew Bennetts
Nasty hackery to make stream_knit_data_for_revisions response use streaming.
163
        if self._body_buffer is None:
164
            self._body_buffer = StringIO(self.body)
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
165
        bytes = self._body_buffer.read(count)
166
        if self._body_buffer.tell() == len(self._body_buffer.getvalue()):
167
            self._fake_client.expecting_body = False
168
        return bytes
169
170
    def cancel_read_body(self):
171
        self._fake_client.expecting_body = False
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
172
2535.4.2 by Andrew Bennetts
Nasty hackery to make stream_knit_data_for_revisions response use streaming.
173
    def read_streamed_body(self):
174
        return self.body
175
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
176
2018.5.159 by Andrew Bennetts
Rename SmartClient to _SmartClient.
177
class FakeClient(_SmartClient):
178
    """Lookalike for _SmartClient allowing testing."""
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
179
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
180
    def __init__(self, fake_medium_base='fake base'):
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
181
        """Create a FakeClient."""
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
182
        self.responses = []
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
183
        self._calls = []
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
184
        self.expecting_body = False
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
185
        # if non-None, this is the list of expected calls, with only the
186
        # method name and arguments included.  the body might be hard to
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
187
        # compute so is not included. If a call is None, that call can
188
        # be anything.
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
189
        self._expected_calls = None
3431.3.2 by Andrew Bennetts
Remove 'base' from _SmartClient entirely, now that the medium has it.
190
        _SmartClient.__init__(self, FakeMedium(self._calls, fake_medium_base))
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
191
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
192
    def add_expected_call(self, call_name, call_args, response_type,
193
        response_args, response_body=None):
194
        if self._expected_calls is None:
195
            self._expected_calls = []
196
        self._expected_calls.append((call_name, call_args))
3691.2.8 by Martin Pool
Update some test_remote tests for Branch.get_stacked_on_url and with clearer assertions
197
        self.responses.append((response_type, response_args, response_body))
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
198
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
199
    def add_success_response(self, *args):
200
        self.responses.append(('success', args, None))
201
202
    def add_success_response_with_body(self, body, *args):
203
        self.responses.append(('success', args, body))
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
204
        if self._expected_calls is not None:
205
            self._expected_calls.append(None)
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
206
207
    def add_error_response(self, *args):
208
        self.responses.append(('error', args))
209
210
    def add_unknown_method_response(self, verb):
211
        self.responses.append(('unknown', verb))
212
3691.2.8 by Martin Pool
Update some test_remote tests for Branch.get_stacked_on_url and with clearer assertions
213
    def finished_test(self):
214
        if self._expected_calls:
215
            raise AssertionError("%r finished but was still expecting %r"
216
                % (self, self._expected_calls[0]))
217
3297.3.3 by Andrew Bennetts
SmartClientRequestProtocol*.read_response_tuple can now raise UnknownSmartMethod. Callers no longer need to do their own ad hoc unknown smart method error detection.
218
    def _get_next_response(self):
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
219
        try:
220
            response_tuple = self.responses.pop(0)
221
        except IndexError, e:
222
            raise AssertionError("%r didn't expect any more calls"
223
                % (self,))
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
224
        if response_tuple[0] == 'unknown':
225
            raise errors.UnknownSmartMethod(response_tuple[1])
226
        elif response_tuple[0] == 'error':
227
            raise errors.ErrorFromSmartServer(response_tuple[1])
3297.3.3 by Andrew Bennetts
SmartClientRequestProtocol*.read_response_tuple can now raise UnknownSmartMethod. Callers no longer need to do their own ad hoc unknown smart method error detection.
228
        return response_tuple
229
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
230
    def _check_call(self, method, args):
231
        if self._expected_calls is None:
232
            # the test should be updated to say what it expects
233
            return
234
        try:
235
            next_call = self._expected_calls.pop(0)
236
        except IndexError:
237
            raise AssertionError("%r didn't expect any more calls "
238
                "but got %r%r"
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
239
                % (self, method, args,))
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
240
        if next_call is None:
241
            return
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
242
        if method != next_call[0] or args != next_call[1]:
243
            raise AssertionError("%r expected %r%r "
244
                "but got %r%r"
3691.2.8 by Martin Pool
Update some test_remote tests for Branch.get_stacked_on_url and with clearer assertions
245
                % (self, next_call[0], next_call[1], method, args,))
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
246
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
247
    def call(self, method, *args):
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
248
        self._check_call(method, args)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
249
        self._calls.append(('call', method, args))
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
250
        return self._get_next_response()[1]
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
251
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
252
    def call_expecting_body(self, method, *args):
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
253
        self._check_call(method, args)
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
254
        self._calls.append(('call_expecting_body', method, args))
3297.3.3 by Andrew Bennetts
SmartClientRequestProtocol*.read_response_tuple can now raise UnknownSmartMethod. Callers no longer need to do their own ad hoc unknown smart method error detection.
255
        result = self._get_next_response()
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
256
        self.expecting_body = True
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
257
        return result[1], FakeProtocol(result[2], self)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
258
3184.1.10 by Robert Collins
Change the smart server verb for Repository.stream_revisions_chunked to use SearchResults as the request mechanism for downloads.
259
    def call_with_body_bytes_expecting_body(self, method, args, body):
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
260
        self._check_call(method, args)
3184.1.10 by Robert Collins
Change the smart server verb for Repository.stream_revisions_chunked to use SearchResults as the request mechanism for downloads.
261
        self._calls.append(('call_with_body_bytes_expecting_body', method,
262
            args, body))
3297.3.3 by Andrew Bennetts
SmartClientRequestProtocol*.read_response_tuple can now raise UnknownSmartMethod. Callers no longer need to do their own ad hoc unknown smart method error detection.
263
        result = self._get_next_response()
3184.1.10 by Robert Collins
Change the smart server verb for Repository.stream_revisions_chunked to use SearchResults as the request mechanism for downloads.
264
        self.expecting_body = True
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
265
        return result[1], FakeProtocol(result[2], self)
3184.1.10 by Robert Collins
Change the smart server verb for Repository.stream_revisions_chunked to use SearchResults as the request mechanism for downloads.
266
3842.3.9 by Andrew Bennetts
Backing up the stream so that we can fallback correctly.
267
    def call_with_body_stream(self, args, stream):
268
        # Explicitly consume the stream before checking for an error, because
269
        # that's what happens a real medium.
270
        stream = list(stream)
271
        self._check_call(args[0], args[1:])
272
        self._calls.append(('call_with_body_stream', args[0], args[1:], stream))
4144.3.2 by Andrew Bennetts
Use Repository.insert_stream_locked if there is a lock_token for the remote repo.
273
        result = self._get_next_response()
274
        return result[1], None
3842.3.9 by Andrew Bennetts
Backing up the stream so that we can fallback correctly.
275
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
276
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
277
class FakeMedium(medium.SmartClientMedium):
3104.4.2 by Andrew Bennetts
All tests passing.
278
3431.3.1 by Andrew Bennetts
First rough cut of a fix for bug #230550, by adding .base to SmartClientMedia rather than relying on other objects to track this accurately while reusing client media.
279
    def __init__(self, client_calls, base):
3453.4.1 by Andrew Bennetts
Better infrastructure on SmartClientMedium for tracking the remote version.
280
        medium.SmartClientMedium.__init__(self, base)
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
281
        self._client_calls = client_calls
3213.1.1 by Andrew Bennetts
Recover (by reconnecting) if the server turns out not to understand the new requests in 1.2 that send bodies.
282
283
    def disconnect(self):
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
284
        self._client_calls.append(('disconnect medium',))
3104.4.2 by Andrew Bennetts
All tests passing.
285
286
3192.2.1 by Andrew Bennetts
Don't transmit URL-escaped relpaths in the smart protocol, which is back to how things worked in bzr 1.1 and earlier.
287
class TestVfsHas(tests.TestCase):
288
289
    def test_unicode_path(self):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
290
        client = FakeClient('/')
291
        client.add_success_response('yes',)
3192.2.1 by Andrew Bennetts
Don't transmit URL-escaped relpaths in the smart protocol, which is back to how things worked in bzr 1.1 and earlier.
292
        transport = RemoteTransport('bzr://localhost/', _client=client)
293
        filename = u'/hell\u00d8'.encode('utf8')
294
        result = transport.has(filename)
295
        self.assertEqual(
296
            [('call', 'has', (filename,))],
297
            client._calls)
298
        self.assertTrue(result)
299
300
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
301
class TestRemote(tests.TestCaseWithMemoryTransport):
4032.1.1 by John Arbash Meinel
Merge the removal of all trailing whitespace, and resolve conflicts.
302
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.
303
    def get_branch_format(self):
304
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
305
        return reference_bzrdir_format.get_branch_format()
306
4053.1.2 by Robert Collins
Actually make this branch work.
307
    def get_repo_format(self):
308
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
309
        return reference_bzrdir_format.repository_format
310
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
311
    def disable_verb(self, verb):
312
        """Disable a verb for one test."""
313
        request_handlers = smart.request.request_handlers
314
        orig_method = request_handlers.get(verb)
315
        request_handlers.remove(verb)
316
        def restoreVerb():
317
            request_handlers.register(verb, orig_method)
318
        self.addCleanup(restoreVerb)
319
320
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
321
class Test_ClientMedium_remote_path_from_transport(tests.TestCase):
322
    """Tests for the behaviour of client_medium.remote_path_from_transport."""
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
323
324
    def assertRemotePath(self, expected, client_base, transport_base):
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
325
        """Assert that the result of
326
        SmartClientMedium.remote_path_from_transport is the expected value for
327
        a given client_base and transport_base.
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
328
        """
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
329
        client_medium = medium.SmartClientMedium(client_base)
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
330
        transport = get_transport(transport_base)
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
331
        result = client_medium.remote_path_from_transport(transport)
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
332
        self.assertEqual(expected, result)
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
333
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
334
    def test_remote_path_from_transport(self):
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
335
        """SmartClientMedium.remote_path_from_transport calculates a URL for
336
        the given transport relative to the root of the client base URL.
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
337
        """
338
        self.assertRemotePath('xyz/', 'bzr://host/path', 'bzr://host/xyz')
339
        self.assertRemotePath(
340
            'path/xyz/', 'bzr://host/path', 'bzr://host/path/xyz')
341
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
342
    def assertRemotePathHTTP(self, expected, transport_base, relpath):
343
        """Assert that the result of
344
        HttpTransportBase.remote_path_from_transport is the expected value for
345
        a given transport_base and relpath of that transport.  (Note that
346
        HttpTransportBase is a subclass of SmartClientMedium)
347
        """
348
        base_transport = get_transport(transport_base)
349
        client_medium = base_transport.get_smart_medium()
350
        cloned_transport = base_transport.clone(relpath)
351
        result = client_medium.remote_path_from_transport(cloned_transport)
352
        self.assertEqual(expected, result)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
353
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
354
    def test_remote_path_from_transport_http(self):
355
        """Remote paths for HTTP transports are calculated differently to other
356
        transports.  They are just relative to the client base, not the root
357
        directory of the host.
358
        """
359
        for scheme in ['http:', 'https:', 'bzr+http:', 'bzr+https:']:
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
360
            self.assertRemotePathHTTP(
361
                '../xyz/', scheme + '//host/path', '../xyz/')
362
            self.assertRemotePathHTTP(
363
                'xyz/', scheme + '//host/path', 'xyz/')
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
364
365
3453.4.1 by Andrew Bennetts
Better infrastructure on SmartClientMedium for tracking the remote version.
366
class Test_ClientMedium_remote_is_at_least(tests.TestCase):
367
    """Tests for the behaviour of client_medium.remote_is_at_least."""
368
369
    def test_initially_unlimited(self):
370
        """A fresh medium assumes that the remote side supports all
371
        versions.
372
        """
373
        client_medium = medium.SmartClientMedium('dummy base')
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
374
        self.assertFalse(client_medium._is_remote_before((99, 99)))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
375
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
376
    def test__remember_remote_is_before(self):
377
        """Calling _remember_remote_is_before ratchets down the known remote
378
        version.
379
        """
3453.4.1 by Andrew Bennetts
Better infrastructure on SmartClientMedium for tracking the remote version.
380
        client_medium = medium.SmartClientMedium('dummy base')
381
        # Mark the remote side as being less than 1.6.  The remote side may
382
        # still be 1.5.
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
383
        client_medium._remember_remote_is_before((1, 6))
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
384
        self.assertTrue(client_medium._is_remote_before((1, 6)))
385
        self.assertFalse(client_medium._is_remote_before((1, 5)))
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
386
        # Calling _remember_remote_is_before again with a lower value works.
387
        client_medium._remember_remote_is_before((1, 5))
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
388
        self.assertTrue(client_medium._is_remote_before((1, 5)))
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
389
        # You cannot call _remember_remote_is_before with a larger value.
3453.4.1 by Andrew Bennetts
Better infrastructure on SmartClientMedium for tracking the remote version.
390
        self.assertRaises(
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
391
            AssertionError, client_medium._remember_remote_is_before, (1, 9))
3453.4.1 by Andrew Bennetts
Better infrastructure on SmartClientMedium for tracking the remote version.
392
393
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
394
class TestBzrDirCloningMetaDir(TestRemote):
395
396
    def test_backwards_compat(self):
397
        self.setup_smart_server_with_call_log()
398
        a_dir = self.make_bzrdir('.')
399
        self.reset_smart_call_log()
400
        verb = 'BzrDir.cloning_metadir'
401
        self.disable_verb(verb)
402
        format = a_dir.cloning_metadir()
403
        call_count = len([call for call in self.hpss_calls if
4070.3.1 by Robert Collins
Alter branch sprouting with an alternate fix for stacked branches that does not require multiple copy_content_into and set_parent calls, reducing IO and round trips.
404
            call.call.method == verb])
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
405
        self.assertEqual(1, call_count)
406
407
    def test_current_server(self):
408
        transport = self.get_transport('.')
409
        transport = transport.clone('quack')
410
        self.make_bzrdir('quack')
411
        client = FakeClient(transport.base)
412
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
413
        control_name = reference_bzrdir_format.network_name()
414
        client.add_expected_call(
415
            'BzrDir.cloning_metadir', ('quack/', 'False'),
4084.2.2 by Robert Collins
Review feedback.
416
            'success', (control_name, '', ('branch', ''))),
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
417
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
418
            _client=client)
419
        result = a_bzrdir.cloning_metadir()
420
        # We should have got a reference control dir with default branch and
421
        # repository formats.
422
        # This pokes a little, just to be sure.
423
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
4070.2.8 by Robert Collins
Really test the current BzrDir.cloning_metadir contract.
424
        self.assertEqual(None, result._repository_format)
425
        self.assertEqual(None, result._branch_format)
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
426
        client.finished_test()
427
428
4053.1.2 by Robert Collins
Actually make this branch work.
429
class TestBzrDirOpenBranch(TestRemote):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
430
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.
431
    def test_backwards_compat(self):
432
        self.setup_smart_server_with_call_log()
433
        self.make_branch('.')
434
        a_dir = BzrDir.open(self.get_url('.'))
435
        self.reset_smart_call_log()
436
        verb = 'BzrDir.open_branchV2'
437
        self.disable_verb(verb)
438
        format = a_dir.open_branch()
439
        call_count = len([call for call in self.hpss_calls if
440
            call.call.method == verb])
441
        self.assertEqual(1, call_count)
442
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
443
    def test_branch_present(self):
4053.1.2 by Robert Collins
Actually make this branch work.
444
        reference_format = self.get_repo_format()
445
        network_name = reference_format.network_name()
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.
446
        branch_network_name = self.get_branch_format().network_name()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
447
        transport = MemoryTransport()
448
        transport.mkdir('quack')
449
        transport = transport.clone('quack')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
450
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
451
        client.add_expected_call(
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.
452
            'BzrDir.open_branchV2', ('quack/',),
453
            'success', ('branch', branch_network_name))
3691.2.10 by Martin Pool
Update more test_remote tests
454
        client.add_expected_call(
4053.1.2 by Robert Collins
Actually make this branch work.
455
            'BzrDir.find_repositoryV3', ('quack/',),
456
            'success', ('ok', '', 'no', 'no', 'no', network_name))
3691.2.10 by Martin Pool
Update more test_remote tests
457
        client.add_expected_call(
458
            'Branch.get_stacked_on_url', ('quack/',),
459
            'error', ('NotStacked',))
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
460
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
461
            _client=client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
462
        result = bzrdir.open_branch()
463
        self.assertIsInstance(result, RemoteBranch)
464
        self.assertEqual(bzrdir, result.bzrdir)
3691.2.10 by Martin Pool
Update more test_remote tests
465
        client.finished_test()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
466
467
    def test_branch_missing(self):
468
        transport = MemoryTransport()
469
        transport.mkdir('quack')
470
        transport = transport.clone('quack')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
471
        client = FakeClient(transport.base)
472
        client.add_error_response('nobranch')
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
473
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
474
            _client=client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
475
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
476
        self.assertEqual(
4084.2.1 by Robert Collins
Make accessing a branch.tags.get_tag_dict use a smart[er] method rather than VFS calls and real objects.
477
            [('call', 'BzrDir.open_branchV2', ('quack/',))],
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
478
            client._calls)
479
3211.4.1 by Robert Collins
* ``RemoteBzrDir._get_tree_branch`` no longer triggers ``_ensure_real``,
480
    def test__get_tree_branch(self):
481
        # _get_tree_branch is a form of open_branch, but it should only ask for
482
        # branch opening, not any other network requests.
483
        calls = []
484
        def open_branch():
485
            calls.append("Called")
486
            return "a-branch"
487
        transport = MemoryTransport()
488
        # no requests on the network - catches other api calls being made.
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
489
        client = FakeClient(transport.base)
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
490
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
491
            _client=client)
3211.4.1 by Robert Collins
* ``RemoteBzrDir._get_tree_branch`` no longer triggers ``_ensure_real``,
492
        # patch the open_branch call to record that it was called.
493
        bzrdir.open_branch = open_branch
494
        self.assertEqual((None, "a-branch"), bzrdir._get_tree_branch())
495
        self.assertEqual(["Called"], calls)
496
        self.assertEqual([], client._calls)
497
3192.2.1 by Andrew Bennetts
Don't transmit URL-escaped relpaths in the smart protocol, which is back to how things worked in bzr 1.1 and earlier.
498
    def test_url_quoting_of_path(self):
499
        # Relpaths on the wire should not be URL-escaped.  So "~" should be
500
        # transmitted as "~", not "%7E".
3431.3.1 by Andrew Bennetts
First rough cut of a fix for bug #230550, by adding .base to SmartClientMedia rather than relying on other objects to track this accurately while reusing client media.
501
        transport = RemoteTCPTransport('bzr://localhost/~hello/')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
502
        client = FakeClient(transport.base)
4053.1.2 by Robert Collins
Actually make this branch work.
503
        reference_format = self.get_repo_format()
504
        network_name = reference_format.network_name()
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.
505
        branch_network_name = self.get_branch_format().network_name()
3691.2.10 by Martin Pool
Update more test_remote tests
506
        client.add_expected_call(
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.
507
            'BzrDir.open_branchV2', ('~hello/',),
508
            'success', ('branch', branch_network_name))
3691.2.10 by Martin Pool
Update more test_remote tests
509
        client.add_expected_call(
4053.1.2 by Robert Collins
Actually make this branch work.
510
            'BzrDir.find_repositoryV3', ('~hello/',),
511
            'success', ('ok', '', 'no', 'no', 'no', network_name))
3691.2.10 by Martin Pool
Update more test_remote tests
512
        client.add_expected_call(
513
            'Branch.get_stacked_on_url', ('~hello/',),
514
            'error', ('NotStacked',))
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
515
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
516
            _client=client)
3192.2.1 by Andrew Bennetts
Don't transmit URL-escaped relpaths in the smart protocol, which is back to how things worked in bzr 1.1 and earlier.
517
        result = bzrdir.open_branch()
3691.2.10 by Martin Pool
Update more test_remote tests
518
        client.finished_test()
3192.2.1 by Andrew Bennetts
Don't transmit URL-escaped relpaths in the smart protocol, which is back to how things worked in bzr 1.1 and earlier.
519
3221.3.3 by Robert Collins
* Hook up the new remote method ``RemoteBzrDir.find_repositoryV2`` so
520
    def check_open_repository(self, rich_root, subtrees, external_lookup='no'):
4053.1.2 by Robert Collins
Actually make this branch work.
521
        reference_format = self.get_repo_format()
522
        network_name = reference_format.network_name()
3104.4.2 by Andrew Bennetts
All tests passing.
523
        transport = MemoryTransport()
524
        transport.mkdir('quack')
525
        transport = transport.clone('quack')
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
526
        if rich_root:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
527
            rich_response = 'yes'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
528
        else:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
529
            rich_response = 'no'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
530
        if subtrees:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
531
            subtree_response = 'yes'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
532
        else:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
533
            subtree_response = 'no'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
534
        client = FakeClient(transport.base)
535
        client.add_success_response(
4053.1.2 by Robert Collins
Actually make this branch work.
536
            'ok', '', rich_response, subtree_response, external_lookup,
537
            network_name)
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
538
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
539
            _client=client)
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
540
        result = bzrdir.open_repository()
541
        self.assertEqual(
4053.1.2 by Robert Collins
Actually make this branch work.
542
            [('call', 'BzrDir.find_repositoryV3', ('quack/',))],
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
543
            client._calls)
544
        self.assertIsInstance(result, RemoteRepository)
545
        self.assertEqual(bzrdir, result.bzrdir)
546
        self.assertEqual(rich_root, result._format.rich_root_data)
2018.5.138 by Robert Collins
Merge bzr.dev.
547
        self.assertEqual(subtrees, result._format.supports_tree_reference)
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
548
549
    def test_open_repository_sets_format_attributes(self):
550
        self.check_open_repository(True, True)
551
        self.check_open_repository(False, True)
552
        self.check_open_repository(True, False)
553
        self.check_open_repository(False, False)
3221.3.3 by Robert Collins
* Hook up the new remote method ``RemoteBzrDir.find_repositoryV2`` so
554
        self.check_open_repository(False, False, 'yes')
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
555
2432.3.2 by Andrew Bennetts
Add test, and tidy implementation.
556
    def test_old_server(self):
557
        """RemoteBzrDirFormat should fail to probe if the server version is too
558
        old.
559
        """
560
        self.assertRaises(errors.NotBranchError,
561
            RemoteBzrDirFormat.probe_transport, OldServerTransport())
562
563
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
564
class TestBzrDirCreateBranch(TestRemote):
565
566
    def test_backwards_compat(self):
567
        self.setup_smart_server_with_call_log()
568
        repo = self.make_repository('.')
569
        self.reset_smart_call_log()
570
        self.disable_verb('BzrDir.create_branch')
571
        branch = repo.bzrdir.create_branch()
572
        create_branch_call_count = len([call for call in self.hpss_calls if
4070.3.1 by Robert Collins
Alter branch sprouting with an alternate fix for stacked branches that does not require multiple copy_content_into and set_parent calls, reducing IO and round trips.
573
            call.call.method == 'BzrDir.create_branch'])
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
574
        self.assertEqual(1, create_branch_call_count)
575
576
    def test_current_server(self):
577
        transport = self.get_transport('.')
578
        transport = transport.clone('quack')
579
        self.make_repository('quack')
580
        client = FakeClient(transport.base)
581
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
582
        reference_format = reference_bzrdir_format.get_branch_format()
583
        network_name = reference_format.network_name()
584
        reference_repo_fmt = reference_bzrdir_format.repository_format
585
        reference_repo_name = reference_repo_fmt.network_name()
586
        client.add_expected_call(
587
            'BzrDir.create_branch', ('quack/', network_name),
588
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
589
            reference_repo_name))
590
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
591
            _client=client)
592
        branch = a_bzrdir.create_branch()
593
        # We should have got a remote branch
594
        self.assertIsInstance(branch, remote.RemoteBranch)
595
        # its format should have the settings from the response
596
        format = branch._format
597
        self.assertEqual(network_name, format.network_name())
598
599
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
600
class TestBzrDirCreateRepository(TestRemote):
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
601
602
    def test_backwards_compat(self):
603
        self.setup_smart_server_with_call_log()
604
        bzrdir = self.make_bzrdir('.')
605
        self.reset_smart_call_log()
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
606
        self.disable_verb('BzrDir.create_repository')
607
        repo = bzrdir.create_repository()
608
        create_repo_call_count = len([call for call in self.hpss_calls if
4070.3.1 by Robert Collins
Alter branch sprouting with an alternate fix for stacked branches that does not require multiple copy_content_into and set_parent calls, reducing IO and round trips.
609
            call.call.method == 'BzrDir.create_repository'])
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
610
        self.assertEqual(1, create_repo_call_count)
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
611
612
    def test_current_server(self):
613
        transport = self.get_transport('.')
614
        transport = transport.clone('quack')
615
        self.make_bzrdir('quack')
616
        client = FakeClient(transport.base)
617
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
618
        reference_format = reference_bzrdir_format.repository_format
619
        network_name = reference_format.network_name()
620
        client.add_expected_call(
621
            'BzrDir.create_repository', ('quack/',
622
                'Bazaar pack repository format 1 (needs bzr 0.92)\n', 'False'),
623
            'success', ('ok', 'no', 'no', 'no', network_name))
624
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
625
            _client=client)
626
        repo = a_bzrdir.create_repository()
627
        # We should have got a remote repository
628
        self.assertIsInstance(repo, remote.RemoteRepository)
629
        # its format should have the settings from the response
630
        format = repo._format
631
        self.assertFalse(format.rich_root_data)
632
        self.assertFalse(format.supports_tree_reference)
633
        self.assertFalse(format.supports_external_lookups)
634
        self.assertEqual(network_name, format.network_name())
635
636
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
637
class TestBzrDirOpenRepository(TestRemote):
638
639
    def test_backwards_compat_1_2_3(self):
640
        # fallback all the way to the first version.
641
        reference_format = self.get_repo_format()
642
        network_name = reference_format.network_name()
643
        client = FakeClient('bzr://example.com/')
644
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
645
        client.add_unknown_method_response('BzrDir.find_repositoryV2')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
646
        client.add_success_response('ok', '', 'no', 'no')
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
647
        # A real repository instance will be created to determine the network
648
        # name.
649
        client.add_success_response_with_body(
650
            "Bazaar-NG meta directory, format 1\n", 'ok')
651
        client.add_success_response_with_body(
652
            reference_format.get_format_string(), 'ok')
653
        # PackRepository wants to do a stat
654
        client.add_success_response('stat', '0', '65535')
655
        remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
656
            _client=client)
657
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
658
            _client=client)
659
        repo = bzrdir.open_repository()
660
        self.assertEqual(
661
            [('call', 'BzrDir.find_repositoryV3', ('quack/',)),
662
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
663
             ('call', 'BzrDir.find_repository', ('quack/',)),
664
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
665
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
666
             ('call', 'stat', ('/quack/.bzr/repository',)),
667
             ],
668
            client._calls)
669
        self.assertEqual(network_name, repo._format.network_name())
670
671
    def test_backwards_compat_2(self):
672
        # fallback to find_repositoryV2
673
        reference_format = self.get_repo_format()
674
        network_name = reference_format.network_name()
675
        client = FakeClient('bzr://example.com/')
676
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
677
        client.add_success_response('ok', '', 'no', 'no', 'no')
678
        # A real repository instance will be created to determine the network
679
        # name.
680
        client.add_success_response_with_body(
681
            "Bazaar-NG meta directory, format 1\n", 'ok')
682
        client.add_success_response_with_body(
683
            reference_format.get_format_string(), 'ok')
684
        # PackRepository wants to do a stat
685
        client.add_success_response('stat', '0', '65535')
686
        remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
687
            _client=client)
688
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
689
            _client=client)
690
        repo = bzrdir.open_repository()
691
        self.assertEqual(
692
            [('call', 'BzrDir.find_repositoryV3', ('quack/',)),
693
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
694
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
695
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
696
             ('call', 'stat', ('/quack/.bzr/repository',)),
697
             ],
698
            client._calls)
699
        self.assertEqual(network_name, repo._format.network_name())
700
701
    def test_current_server(self):
702
        reference_format = self.get_repo_format()
703
        network_name = reference_format.network_name()
704
        transport = MemoryTransport()
705
        transport.mkdir('quack')
706
        transport = transport.clone('quack')
707
        client = FakeClient(transport.base)
708
        client.add_success_response('ok', '', 'no', 'no', 'no', network_name)
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
709
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
710
            _client=client)
3297.3.3 by Andrew Bennetts
SmartClientRequestProtocol*.read_response_tuple can now raise UnknownSmartMethod. Callers no longer need to do their own ad hoc unknown smart method error detection.
711
        repo = bzrdir.open_repository()
712
        self.assertEqual(
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
713
            [('call', 'BzrDir.find_repositoryV3', ('quack/',))],
3297.3.3 by Andrew Bennetts
SmartClientRequestProtocol*.read_response_tuple can now raise UnknownSmartMethod. Callers no longer need to do their own ad hoc unknown smart method error detection.
714
            client._calls)
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
715
        self.assertEqual(network_name, repo._format.network_name())
3297.3.3 by Andrew Bennetts
SmartClientRequestProtocol*.read_response_tuple can now raise UnknownSmartMethod. Callers no longer need to do their own ad hoc unknown smart method error detection.
716
717
2432.3.2 by Andrew Bennetts
Add test, and tidy implementation.
718
class OldSmartClient(object):
719
    """A fake smart client for test_old_version that just returns a version one
720
    response to the 'hello' (query version) command.
721
    """
722
723
    def get_request(self):
724
        input_file = StringIO('ok\x011\n')
725
        output_file = StringIO()
726
        client_medium = medium.SmartSimplePipesClientMedium(
727
            input_file, output_file)
728
        return medium.SmartClientStreamMediumRequest(client_medium)
729
3241.1.1 by Andrew Bennetts
Shift protocol version querying from RemoteBzrDirFormat into SmartClientMedium.
730
    def protocol_version(self):
731
        return 1
732
2432.3.2 by Andrew Bennetts
Add test, and tidy implementation.
733
734
class OldServerTransport(object):
735
    """A fake transport for test_old_server that reports it's smart server
736
    protocol version as version one.
737
    """
738
739
    def __init__(self):
740
        self.base = 'fake:'
741
742
    def get_smart_client(self):
743
        return OldSmartClient()
744
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
745
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.
746
class RemoteBranchTestCase(TestRemote):
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
747
748
    def make_remote_branch(self, transport, client):
749
        """Make a RemoteBranch using 'client' as its _SmartClient.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
750
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
751
        A RemoteBzrDir and RemoteRepository will also be created to fill out
752
        the RemoteBranch, albeit with stub values for some of their attributes.
753
        """
754
        # we do not want bzrdir to make any remote calls, so use False as its
755
        # _client.  If it tries to make a remote call, this will fail
756
        # immediately.
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
757
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
758
            _client=False)
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
759
        repo = RemoteRepository(bzrdir, None, _client=client)
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.
760
        branch_format = self.get_branch_format()
761
        format = RemoteBranchFormat(network_name=branch_format.network_name())
762
        return RemoteBranch(bzrdir, repo, _client=client, format=format)
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
763
764
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
765
class TestBranchGetParent(RemoteBranchTestCase):
766
767
    def test_no_parent(self):
768
        # in an empty branch we decode the response properly
769
        transport = MemoryTransport()
770
        client = FakeClient(transport.base)
771
        client.add_expected_call(
772
            'Branch.get_stacked_on_url', ('quack/',),
773
            'error', ('NotStacked',))
774
        client.add_expected_call(
775
            'Branch.get_parent', ('quack/',),
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
776
            'success', ('',))
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
777
        transport.mkdir('quack')
778
        transport = transport.clone('quack')
779
        branch = self.make_remote_branch(transport, client)
780
        result = branch.get_parent()
781
        client.finished_test()
782
        self.assertEqual(None, result)
783
784
    def test_parent_relative(self):
785
        transport = MemoryTransport()
786
        client = FakeClient(transport.base)
787
        client.add_expected_call(
788
            'Branch.get_stacked_on_url', ('kwaak/',),
789
            'error', ('NotStacked',))
790
        client.add_expected_call(
791
            'Branch.get_parent', ('kwaak/',),
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
792
            'success', ('../foo/',))
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
793
        transport.mkdir('kwaak')
794
        transport = transport.clone('kwaak')
795
        branch = self.make_remote_branch(transport, client)
796
        result = branch.get_parent()
797
        self.assertEqual(transport.clone('../foo').base, result)
798
799
    def test_parent_absolute(self):
800
        transport = MemoryTransport()
801
        client = FakeClient(transport.base)
802
        client.add_expected_call(
803
            'Branch.get_stacked_on_url', ('kwaak/',),
804
            'error', ('NotStacked',))
805
        client.add_expected_call(
806
            'Branch.get_parent', ('kwaak/',),
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
807
            'success', ('http://foo/',))
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
808
        transport.mkdir('kwaak')
809
        transport = transport.clone('kwaak')
810
        branch = self.make_remote_branch(transport, client)
811
        result = branch.get_parent()
812
        self.assertEqual('http://foo/', result)
813
814
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.
815
class TestBranchGetTagsBytes(RemoteBranchTestCase):
816
817
    def test_backwards_compat(self):
818
        self.setup_smart_server_with_call_log()
819
        branch = self.make_branch('.')
820
        self.reset_smart_call_log()
821
        verb = 'Branch.get_tags_bytes'
822
        self.disable_verb(verb)
823
        branch.tags.get_tag_dict()
824
        call_count = len([call for call in self.hpss_calls if
825
            call.call.method == verb])
826
        self.assertEqual(1, call_count)
827
828
    def test_trivial(self):
829
        transport = MemoryTransport()
830
        client = FakeClient(transport.base)
831
        client.add_expected_call(
832
            'Branch.get_stacked_on_url', ('quack/',),
833
            'error', ('NotStacked',))
834
        client.add_expected_call(
835
            'Branch.get_tags_bytes', ('quack/',),
836
            'success', ('',))
837
        transport.mkdir('quack')
838
        transport = transport.clone('quack')
839
        branch = self.make_remote_branch(transport, client)
840
        result = branch.tags.get_tag_dict()
841
        client.finished_test()
842
        self.assertEqual({}, result)
843
844
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
845
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
846
847
    def test_empty_branch(self):
848
        # in an empty branch we decode the response properly
849
        transport = MemoryTransport()
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
850
        client = FakeClient(transport.base)
3691.2.8 by Martin Pool
Update some test_remote tests for Branch.get_stacked_on_url and with clearer assertions
851
        client.add_expected_call(
852
            'Branch.get_stacked_on_url', ('quack/',),
853
            'error', ('NotStacked',))
854
        client.add_expected_call(
855
            'Branch.last_revision_info', ('quack/',),
856
            'success', ('ok', '0', 'null:'))
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
857
        transport.mkdir('quack')
858
        transport = transport.clone('quack')
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
859
        branch = self.make_remote_branch(transport, client)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
860
        result = branch.last_revision_info()
3691.2.8 by Martin Pool
Update some test_remote tests for Branch.get_stacked_on_url and with clearer assertions
861
        client.finished_test()
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
862
        self.assertEqual((0, NULL_REVISION), result)
863
864
    def test_non_empty_branch(self):
865
        # in a non-empty branch we also decode the response properly
2018.5.106 by Andrew Bennetts
Update tests in test_remote to use utf-8 byte strings for revision IDs, rather than unicode strings.
866
        revid = u'\xc8'.encode('utf8')
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
867
        transport = MemoryTransport()
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
868
        client = FakeClient(transport.base)
3691.2.8 by Martin Pool
Update some test_remote tests for Branch.get_stacked_on_url and with clearer assertions
869
        client.add_expected_call(
870
            'Branch.get_stacked_on_url', ('kwaak/',),
871
            'error', ('NotStacked',))
872
        client.add_expected_call(
873
            'Branch.last_revision_info', ('kwaak/',),
874
            'success', ('ok', '2', revid))
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
875
        transport.mkdir('kwaak')
876
        transport = transport.clone('kwaak')
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
877
        branch = self.make_remote_branch(transport, client)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
878
        result = branch.last_revision_info()
2018.5.106 by Andrew Bennetts
Update tests in test_remote to use utf-8 byte strings for revision IDs, rather than unicode strings.
879
        self.assertEqual((2, revid), result)
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
880
881
4053.1.2 by Robert Collins
Actually make this branch work.
882
class TestBranch_get_stacked_on_url(TestRemote):
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
883
    """Test Branch._get_stacked_on_url rpc"""
884
3691.2.10 by Martin Pool
Update more test_remote tests
885
    def test_get_stacked_on_invalid_url(self):
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
886
        # test that asking for a stacked on url the server can't access works.
887
        # This isn't perfect, but then as we're in the same process there
888
        # really isn't anything we can do to be 100% sure that the server
889
        # doesn't just open in - this test probably needs to be rewritten using
890
        # a spawn()ed server.
891
        stacked_branch = self.make_branch('stacked', format='1.9')
892
        memory_branch = self.make_branch('base', format='1.9')
893
        vfs_url = self.get_vfs_only_url('base')
894
        stacked_branch.set_stacked_on_url(vfs_url)
895
        transport = stacked_branch.bzrdir.root_transport
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
896
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
897
        client.add_expected_call(
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
898
            'Branch.get_stacked_on_url', ('stacked/',),
899
            'success', ('ok', vfs_url))
900
        # XXX: Multiple calls are bad, this second call documents what is
901
        # today.
902
        client.add_expected_call(
903
            'Branch.get_stacked_on_url', ('stacked/',),
904
            'success', ('ok', vfs_url))
905
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
906
            _client=client)
4118.1.5 by Andrew Bennetts
Fix test_remote tests.
907
        repo_fmt = remote.RemoteRepositoryFormat()
908
        repo_fmt._custom_format = stacked_branch.repository._format
909
        branch = RemoteBranch(bzrdir, RemoteRepository(bzrdir, repo_fmt),
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
910
            _client=client)
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
911
        result = branch.get_stacked_on_url()
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
912
        self.assertEqual(vfs_url, result)
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
913
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
914
    def test_backwards_compatible(self):
915
        # like with bzr1.6 with no Branch.get_stacked_on_url rpc
916
        base_branch = self.make_branch('base', format='1.6')
917
        stacked_branch = self.make_branch('stacked', format='1.6')
918
        stacked_branch.set_stacked_on_url('../base')
919
        client = FakeClient(self.get_url())
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.
920
        branch_network_name = self.get_branch_format().network_name()
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
921
        client.add_expected_call(
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.
922
            'BzrDir.open_branchV2', ('stacked/',),
923
            'success', ('branch', branch_network_name))
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
924
        client.add_expected_call(
4053.1.2 by Robert Collins
Actually make this branch work.
925
            'BzrDir.find_repositoryV3', ('stacked/',),
4118.1.5 by Andrew Bennetts
Fix test_remote tests.
926
            'success', ('ok', '', 'no', 'no', 'yes',
4053.1.2 by Robert Collins
Actually make this branch work.
927
                stacked_branch.repository._format.network_name()))
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
928
        # called twice, once from constructor and then again by us
929
        client.add_expected_call(
930
            'Branch.get_stacked_on_url', ('stacked/',),
931
            'unknown', ('Branch.get_stacked_on_url',))
932
        client.add_expected_call(
933
            'Branch.get_stacked_on_url', ('stacked/',),
934
            'unknown', ('Branch.get_stacked_on_url',))
935
        # this will also do vfs access, but that goes direct to the transport
936
        # and isn't seen by the FakeClient.
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
937
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
938
            remote.RemoteBzrDirFormat(), _client=client)
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
939
        branch = bzrdir.open_branch()
940
        result = branch.get_stacked_on_url()
941
        self.assertEqual('../base', result)
942
        client.finished_test()
943
        # it's in the fallback list both for the RemoteRepository and its vfs
944
        # repository
945
        self.assertEqual(1, len(branch.repository._fallback_repositories))
946
        self.assertEqual(1,
947
            len(branch.repository._real_repository._fallback_repositories))
948
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
949
    def test_get_stacked_on_real_branch(self):
950
        base_branch = self.make_branch('base', format='1.6')
951
        stacked_branch = self.make_branch('stacked', format='1.6')
952
        stacked_branch.set_stacked_on_url('../base')
4053.1.2 by Robert Collins
Actually make this branch work.
953
        reference_format = self.get_repo_format()
954
        network_name = reference_format.network_name()
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
955
        client = FakeClient(self.get_url())
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.
956
        branch_network_name = self.get_branch_format().network_name()
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
957
        client.add_expected_call(
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.
958
            'BzrDir.open_branchV2', ('stacked/',),
959
            'success', ('branch', branch_network_name))
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
960
        client.add_expected_call(
4053.1.2 by Robert Collins
Actually make this branch work.
961
            'BzrDir.find_repositoryV3', ('stacked/',),
4118.1.5 by Andrew Bennetts
Fix test_remote tests.
962
            'success', ('ok', '', 'no', 'no', 'yes', network_name))
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
963
        # called twice, once from constructor and then again by us
964
        client.add_expected_call(
965
            'Branch.get_stacked_on_url', ('stacked/',),
966
            'success', ('ok', '../base'))
967
        client.add_expected_call(
968
            'Branch.get_stacked_on_url', ('stacked/',),
969
            'success', ('ok', '../base'))
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
970
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
971
            remote.RemoteBzrDirFormat(), _client=client)
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
972
        branch = bzrdir.open_branch()
973
        result = branch.get_stacked_on_url()
974
        self.assertEqual('../base', result)
975
        client.finished_test()
976
        # it's in the fallback list both for the RemoteRepository and its vfs
977
        # repository
978
        self.assertEqual(1, len(branch.repository._fallback_repositories))
979
        self.assertEqual(1,
980
            len(branch.repository._real_repository._fallback_repositories))
981
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
982
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
983
class TestBranchSetLastRevision(RemoteBranchTestCase):
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
984
985
    def test_set_empty(self):
986
        # set_revision_history([]) is translated to calling
987
        # Branch.set_last_revision(path, '') on the wire.
3104.4.2 by Andrew Bennetts
All tests passing.
988
        transport = MemoryTransport()
989
        transport.mkdir('branch')
990
        transport = transport.clone('branch')
991
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
992
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
993
        client.add_expected_call(
994
            'Branch.get_stacked_on_url', ('branch/',),
995
            'error', ('NotStacked',))
996
        client.add_expected_call(
997
            'Branch.lock_write', ('branch/', '', ''),
998
            'success', ('ok', 'branch token', 'repo token'))
999
        client.add_expected_call(
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
1000
            'Branch.last_revision_info',
1001
            ('branch/',),
1002
            'success', ('ok', '0', 'null:'))
1003
        client.add_expected_call(
3691.2.10 by Martin Pool
Update more test_remote tests
1004
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'null:',),
1005
            'success', ('ok',))
1006
        client.add_expected_call(
1007
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1008
            'success', ('ok',))
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1009
        branch = self.make_remote_branch(transport, client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1010
        # This is a hack to work around the problem that RemoteBranch currently
1011
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1012
        branch._ensure_real = lambda: None
1013
        branch.lock_write()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1014
        result = branch.set_revision_history([])
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1015
        branch.unlock()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1016
        self.assertEqual(None, result)
3691.2.10 by Martin Pool
Update more test_remote tests
1017
        client.finished_test()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1018
1019
    def test_set_nonempty(self):
1020
        # set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
1021
        # Branch.set_last_revision(path, rev-idN) on the wire.
3104.4.2 by Andrew Bennetts
All tests passing.
1022
        transport = MemoryTransport()
1023
        transport.mkdir('branch')
1024
        transport = transport.clone('branch')
1025
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1026
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1027
        client.add_expected_call(
1028
            'Branch.get_stacked_on_url', ('branch/',),
1029
            'error', ('NotStacked',))
1030
        client.add_expected_call(
1031
            'Branch.lock_write', ('branch/', '', ''),
1032
            'success', ('ok', 'branch token', 'repo token'))
1033
        client.add_expected_call(
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
1034
            'Branch.last_revision_info',
1035
            ('branch/',),
1036
            'success', ('ok', '0', 'null:'))
1037
        lines = ['rev-id2']
1038
        encoded_body = bz2.compress('\n'.join(lines))
1039
        client.add_success_response_with_body(encoded_body, 'ok')
1040
        client.add_expected_call(
3691.2.10 by Martin Pool
Update more test_remote tests
1041
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id2',),
1042
            'success', ('ok',))
1043
        client.add_expected_call(
1044
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1045
            'success', ('ok',))
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1046
        branch = self.make_remote_branch(transport, client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1047
        # This is a hack to work around the problem that RemoteBranch currently
1048
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1049
        branch._ensure_real = lambda: None
1050
        # Lock the branch, reset the record of remote calls.
1051
        branch.lock_write()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1052
        result = branch.set_revision_history(['rev-id1', 'rev-id2'])
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1053
        branch.unlock()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1054
        self.assertEqual(None, result)
3691.2.10 by Martin Pool
Update more test_remote tests
1055
        client.finished_test()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1056
1057
    def test_no_such_revision(self):
1058
        transport = MemoryTransport()
1059
        transport.mkdir('branch')
1060
        transport = transport.clone('branch')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1061
        # A response of 'NoSuchRevision' is translated into an exception.
1062
        client = FakeClient(transport.base)
3691.2.9 by Martin Pool
Convert and update more test_remote tests
1063
        client.add_expected_call(
1064
            'Branch.get_stacked_on_url', ('branch/',),
1065
            'error', ('NotStacked',))
1066
        client.add_expected_call(
1067
            'Branch.lock_write', ('branch/', '', ''),
1068
            'success', ('ok', 'branch token', 'repo token'))
1069
        client.add_expected_call(
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
1070
            'Branch.last_revision_info',
1071
            ('branch/',),
1072
            'success', ('ok', '0', 'null:'))
1073
        # get_graph calls to construct the revision history, for the set_rh
1074
        # hook
1075
        lines = ['rev-id']
1076
        encoded_body = bz2.compress('\n'.join(lines))
1077
        client.add_success_response_with_body(encoded_body, 'ok')
1078
        client.add_expected_call(
3691.2.9 by Martin Pool
Convert and update more test_remote tests
1079
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
1080
            'error', ('NoSuchRevision', 'rev-id'))
1081
        client.add_expected_call(
1082
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1083
            'success', ('ok',))
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1084
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1085
        branch = self.make_remote_branch(transport, client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1086
        branch.lock_write()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1087
        self.assertRaises(
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1088
            errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1089
        branch.unlock()
3691.2.9 by Martin Pool
Convert and update more test_remote tests
1090
        client.finished_test()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1091
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1092
    def test_tip_change_rejected(self):
1093
        """TipChangeRejected responses cause a TipChangeRejected exception to
1094
        be raised.
1095
        """
1096
        transport = MemoryTransport()
1097
        transport.mkdir('branch')
1098
        transport = transport.clone('branch')
1099
        client = FakeClient(transport.base)
1100
        rejection_msg_unicode = u'rejection message\N{INTERROBANG}'
1101
        rejection_msg_utf8 = rejection_msg_unicode.encode('utf8')
3691.2.10 by Martin Pool
Update more test_remote tests
1102
        client.add_expected_call(
1103
            'Branch.get_stacked_on_url', ('branch/',),
1104
            'error', ('NotStacked',))
1105
        client.add_expected_call(
1106
            'Branch.lock_write', ('branch/', '', ''),
1107
            'success', ('ok', 'branch token', 'repo token'))
1108
        client.add_expected_call(
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
1109
            'Branch.last_revision_info',
1110
            ('branch/',),
1111
            'success', ('ok', '0', 'null:'))
1112
        lines = ['rev-id']
1113
        encoded_body = bz2.compress('\n'.join(lines))
1114
        client.add_success_response_with_body(encoded_body, 'ok')
1115
        client.add_expected_call(
3691.2.10 by Martin Pool
Update more test_remote tests
1116
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
1117
            'error', ('TipChangeRejected', rejection_msg_utf8))
1118
        client.add_expected_call(
1119
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1120
            'success', ('ok',))
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1121
        branch = self.make_remote_branch(transport, client)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1122
        branch._ensure_real = lambda: None
1123
        branch.lock_write()
1124
        # The 'TipChangeRejected' error response triggered by calling
1125
        # set_revision_history causes a TipChangeRejected exception.
1126
        err = self.assertRaises(
1127
            errors.TipChangeRejected, branch.set_revision_history, ['rev-id'])
1128
        # The UTF-8 message from the response has been decoded into a unicode
1129
        # object.
1130
        self.assertIsInstance(err.msg, unicode)
1131
        self.assertEqual(rejection_msg_unicode, err.msg)
3691.2.10 by Martin Pool
Update more test_remote tests
1132
        branch.unlock()
1133
        client.finished_test()
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1134
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1135
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1136
class TestBranchSetLastRevisionInfo(RemoteBranchTestCase):
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1137
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1138
    def test_set_last_revision_info(self):
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1139
        # set_last_revision_info(num, 'rev-id') is translated to calling
1140
        # Branch.set_last_revision_info(num, 'rev-id') on the wire.
3297.4.1 by Andrew Bennetts
Merge 'Add Branch.set_last_revision_info smart method'.
1141
        transport = MemoryTransport()
1142
        transport.mkdir('branch')
1143
        transport = transport.clone('branch')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1144
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1145
        # get_stacked_on_url
1146
        client.add_error_response('NotStacked')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1147
        # lock_write
1148
        client.add_success_response('ok', 'branch token', 'repo token')
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
1149
        # query the current revision
1150
        client.add_success_response('ok', '0', 'null:')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1151
        # set_last_revision
1152
        client.add_success_response('ok')
1153
        # unlock
1154
        client.add_success_response('ok')
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1155
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1156
        branch = self.make_remote_branch(transport, client)
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1157
        # Lock the branch, reset the record of remote calls.
1158
        branch.lock_write()
1159
        client._calls = []
1160
        result = branch.set_last_revision_info(1234, 'a-revision-id')
1161
        self.assertEqual(
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
1162
            [('call', 'Branch.last_revision_info', ('branch/',)),
1163
             ('call', 'Branch.set_last_revision_info',
3297.4.1 by Andrew Bennetts
Merge 'Add Branch.set_last_revision_info smart method'.
1164
                ('branch/', 'branch token', 'repo token',
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1165
                 '1234', 'a-revision-id'))],
1166
            client._calls)
1167
        self.assertEqual(None, result)
1168
1169
    def test_no_such_revision(self):
1170
        # A response of 'NoSuchRevision' is translated into an exception.
1171
        transport = MemoryTransport()
1172
        transport.mkdir('branch')
1173
        transport = transport.clone('branch')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1174
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1175
        # get_stacked_on_url
1176
        client.add_error_response('NotStacked')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1177
        # lock_write
1178
        client.add_success_response('ok', 'branch token', 'repo token')
1179
        # set_last_revision
1180
        client.add_error_response('NoSuchRevision', 'revid')
1181
        # unlock
1182
        client.add_success_response('ok')
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1183
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1184
        branch = self.make_remote_branch(transport, client)
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1185
        # Lock the branch, reset the record of remote calls.
1186
        branch.lock_write()
1187
        client._calls = []
1188
1189
        self.assertRaises(
1190
            errors.NoSuchRevision, branch.set_last_revision_info, 123, 'revid')
1191
        branch.unlock()
1192
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1193
    def lock_remote_branch(self, branch):
1194
        """Trick a RemoteBranch into thinking it is locked."""
1195
        branch._lock_mode = 'w'
1196
        branch._lock_count = 2
1197
        branch._lock_token = 'branch token'
1198
        branch._repo_lock_token = 'repo token'
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1199
        branch.repository._lock_mode = 'w'
1200
        branch.repository._lock_count = 2
1201
        branch.repository._lock_token = 'repo token'
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1202
1203
    def test_backwards_compatibility(self):
1204
        """If the server does not support the Branch.set_last_revision_info
1205
        verb (which is new in 1.4), then the client falls back to VFS methods.
1206
        """
1207
        # This test is a little messy.  Unlike most tests in this file, it
1208
        # doesn't purely test what a Remote* object sends over the wire, and
1209
        # how it reacts to responses from the wire.  It instead relies partly
1210
        # on asserting that the RemoteBranch will call
1211
        # self._real_branch.set_last_revision_info(...).
1212
1213
        # First, set up our RemoteBranch with a FakeClient that raises
1214
        # UnknownSmartMethod, and a StubRealBranch that logs how it is called.
1215
        transport = MemoryTransport()
1216
        transport.mkdir('branch')
1217
        transport = transport.clone('branch')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1218
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1219
        client.add_expected_call(
1220
            'Branch.get_stacked_on_url', ('branch/',),
1221
            'error', ('NotStacked',))
1222
        client.add_expected_call(
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
1223
            'Branch.last_revision_info',
1224
            ('branch/',),
1225
            'success', ('ok', '0', 'null:'))
1226
        client.add_expected_call(
3691.2.10 by Martin Pool
Update more test_remote tests
1227
            'Branch.set_last_revision_info',
1228
            ('branch/', 'branch token', 'repo token', '1234', 'a-revision-id',),
1229
            'unknown', 'Branch.set_last_revision_info')
1230
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1231
        branch = self.make_remote_branch(transport, client)
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1232
        class StubRealBranch(object):
1233
            def __init__(self):
1234
                self.calls = []
1235
            def set_last_revision_info(self, revno, revision_id):
1236
                self.calls.append(
1237
                    ('set_last_revision_info', revno, revision_id))
3441.5.5 by Andrew Bennetts
Some small tweaks and comments.
1238
            def _clear_cached_state(self):
1239
                pass
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1240
        real_branch = StubRealBranch()
1241
        branch._real_branch = real_branch
1242
        self.lock_remote_branch(branch)
1243
1244
        # Call set_last_revision_info, and verify it behaved as expected.
1245
        result = branch.set_last_revision_info(1234, 'a-revision-id')
1246
        self.assertEqual(
1247
            [('set_last_revision_info', 1234, 'a-revision-id')],
1248
            real_branch.calls)
3691.2.10 by Martin Pool
Update more test_remote tests
1249
        client.finished_test()
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1250
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1251
    def test_unexpected_error(self):
3697.2.6 by Martin Pool
Merge 261315 fix into 1.7 branch
1252
        # If the server sends an error the client doesn't understand, it gets
1253
        # turned into an UnknownErrorFromSmartServer, which is presented as a
1254
        # non-internal error to the user.
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1255
        transport = MemoryTransport()
1256
        transport.mkdir('branch')
1257
        transport = transport.clone('branch')
1258
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1259
        # get_stacked_on_url
1260
        client.add_error_response('NotStacked')
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1261
        # lock_write
1262
        client.add_success_response('ok', 'branch token', 'repo token')
1263
        # set_last_revision
1264
        client.add_error_response('UnexpectedError')
1265
        # unlock
1266
        client.add_success_response('ok')
1267
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1268
        branch = self.make_remote_branch(transport, client)
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1269
        # Lock the branch, reset the record of remote calls.
1270
        branch.lock_write()
1271
        client._calls = []
1272
1273
        err = self.assertRaises(
3690.1.2 by Andrew Bennetts
Rename UntranslateableErrorFromSmartServer -> UnknownErrorFromSmartServer.
1274
            errors.UnknownErrorFromSmartServer,
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1275
            branch.set_last_revision_info, 123, 'revid')
1276
        self.assertEqual(('UnexpectedError',), err.error_tuple)
1277
        branch.unlock()
1278
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1279
    def test_tip_change_rejected(self):
1280
        """TipChangeRejected responses cause a TipChangeRejected exception to
1281
        be raised.
1282
        """
1283
        transport = MemoryTransport()
1284
        transport.mkdir('branch')
1285
        transport = transport.clone('branch')
1286
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1287
        # get_stacked_on_url
1288
        client.add_error_response('NotStacked')
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1289
        # lock_write
1290
        client.add_success_response('ok', 'branch token', 'repo token')
1291
        # set_last_revision
1292
        client.add_error_response('TipChangeRejected', 'rejection message')
1293
        # unlock
1294
        client.add_success_response('ok')
1295
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1296
        branch = self.make_remote_branch(transport, client)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1297
        # Lock the branch, reset the record of remote calls.
1298
        branch.lock_write()
1299
        self.addCleanup(branch.unlock)
1300
        client._calls = []
1301
1302
        # The 'TipChangeRejected' error response triggered by calling
1303
        # set_last_revision_info causes a TipChangeRejected exception.
1304
        err = self.assertRaises(
1305
            errors.TipChangeRejected,
1306
            branch.set_last_revision_info, 123, 'revid')
1307
        self.assertEqual('rejection message', err.msg)
1308
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1309
2018.5.169 by Andrew Bennetts
Add a _server_formats flag to BzrDir.open_from_transport and BzrDirFormat.find_format, make RemoteBranch.control_files into a property.
1310
class TestBranchControlGetBranchConf(tests.TestCaseWithMemoryTransport):
3408.3.1 by Martin Pool
Remove erroneous handling of branch.conf for RemoteBranch
1311
    """Getting the branch configuration should use an abstract method not vfs.
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1312
    """
1313
1314
    def test_get_branch_conf(self):
3408.3.1 by Martin Pool
Remove erroneous handling of branch.conf for RemoteBranch
1315
        raise tests.KnownFailure('branch.conf is not retrieved by get_config_file')
3407.2.10 by Martin Pool
Merge trunk
1316
        ## # We should see that branch.get_config() does a single rpc to get the
1317
        ## # remote configuration file, abstracting away where that is stored on
1318
        ## # the server.  However at the moment it always falls back to using the
1319
        ## # vfs, and this would need some changes in config.py.
3408.3.1 by Martin Pool
Remove erroneous handling of branch.conf for RemoteBranch
1320
3407.2.10 by Martin Pool
Merge trunk
1321
        ## # in an empty branch we decode the response properly
1322
        ## client = FakeClient([(('ok', ), '# config file body')], self.get_url())
1323
        ## # we need to make a real branch because the remote_branch.control_files
1324
        ## # will trigger _ensure_real.
1325
        ## branch = self.make_branch('quack')
1326
        ## transport = branch.bzrdir.root_transport
1327
        ## # we do not want bzrdir to make any remote calls
1328
        ## bzrdir = RemoteBzrDir(transport, _client=False)
1329
        ## branch = RemoteBranch(bzrdir, None, _client=client)
1330
        ## config = branch.get_config()
1331
        ## self.assertEqual(
1332
        ##     [('call_expecting_body', 'Branch.get_config_file', ('quack/',))],
1333
        ##     client._calls)
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1334
1335
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1336
class TestBranchLockWrite(RemoteBranchTestCase):
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.
1337
1338
    def test_lock_write_unlockable(self):
1339
        transport = MemoryTransport()
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1340
        client = FakeClient(transport.base)
3691.2.9 by Martin Pool
Convert and update more test_remote tests
1341
        client.add_expected_call(
1342
            'Branch.get_stacked_on_url', ('quack/',),
1343
            'error', ('NotStacked',),)
1344
        client.add_expected_call(
1345
            'Branch.lock_write', ('quack/', '', ''),
1346
            'error', ('UnlockableTransport',))
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.
1347
        transport.mkdir('quack')
1348
        transport = transport.clone('quack')
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1349
        branch = self.make_remote_branch(transport, client)
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.
1350
        self.assertRaises(errors.UnlockableTransport, branch.lock_write)
3691.2.9 by Martin Pool
Convert and update more test_remote tests
1351
        client.finished_test()
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.
1352
1353
2466.2.2 by Andrew Bennetts
Add tests for RemoteTransport.is_readonly in the style of the other remote object tests.
1354
class TestTransportIsReadonly(tests.TestCase):
1355
1356
    def test_true(self):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1357
        client = FakeClient()
1358
        client.add_success_response('yes')
2466.2.2 by Andrew Bennetts
Add tests for RemoteTransport.is_readonly in the style of the other remote object tests.
1359
        transport = RemoteTransport('bzr://example.com/', medium=False,
1360
                                    _client=client)
1361
        self.assertEqual(True, transport.is_readonly())
1362
        self.assertEqual(
1363
            [('call', 'Transport.is_readonly', ())],
1364
            client._calls)
1365
1366
    def test_false(self):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1367
        client = FakeClient()
1368
        client.add_success_response('no')
2466.2.2 by Andrew Bennetts
Add tests for RemoteTransport.is_readonly in the style of the other remote object tests.
1369
        transport = RemoteTransport('bzr://example.com/', medium=False,
1370
                                    _client=client)
1371
        self.assertEqual(False, transport.is_readonly())
1372
        self.assertEqual(
1373
            [('call', 'Transport.is_readonly', ())],
1374
            client._calls)
1375
1376
    def test_error_from_old_server(self):
1377
        """bzr 0.15 and earlier servers don't recognise the is_readonly verb.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1378
2466.2.2 by Andrew Bennetts
Add tests for RemoteTransport.is_readonly in the style of the other remote object tests.
1379
        Clients should treat it as a "no" response, because is_readonly is only
1380
        advisory anyway (a transport could be read-write, but then the
1381
        underlying filesystem could be readonly anyway).
1382
        """
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1383
        client = FakeClient()
1384
        client.add_unknown_method_response('Transport.is_readonly')
2471.2.1 by Andrew Bennetts
Fix trivial incompatibility with bzr 0.11 servers, which give a slightly different error to bzr 0.15 servers.
1385
        transport = RemoteTransport('bzr://example.com/', medium=False,
1386
                                    _client=client)
1387
        self.assertEqual(False, transport.is_readonly())
1388
        self.assertEqual(
1389
            [('call', 'Transport.is_readonly', ())],
1390
            client._calls)
1391
2466.2.2 by Andrew Bennetts
Add tests for RemoteTransport.is_readonly in the style of the other remote object tests.
1392
3840.1.1 by Andrew Bennetts
Fix RemoteTransport's translation of errors involving paths; it wasn't passing orig_path to _translate_error.
1393
class TestTransportMkdir(tests.TestCase):
1394
1395
    def test_permissiondenied(self):
1396
        client = FakeClient()
1397
        client.add_error_response('PermissionDenied', 'remote path', 'extra')
1398
        transport = RemoteTransport('bzr://example.com/', medium=False,
1399
                                    _client=client)
1400
        exc = self.assertRaises(
1401
            errors.PermissionDenied, transport.mkdir, 'client path')
1402
        expected_error = errors.PermissionDenied('/client path', 'extra')
1403
        self.assertEqual(expected_error, exc)
1404
1405
3777.1.3 by Aaron Bentley
Use SSH default username from authentication.conf
1406
class TestRemoteSSHTransportAuthentication(tests.TestCaseInTempDir):
1407
1408
    def test_defaults_to_none(self):
1409
        t = RemoteSSHTransport('bzr+ssh://example.com')
1410
        self.assertIs(None, t._get_credentials()[0])
1411
1412
    def test_uses_authentication_config(self):
1413
        conf = config.AuthenticationConfig()
1414
        conf._get_config().update(
1415
            {'bzr+sshtest': {'scheme': 'ssh', 'user': 'bar', 'host':
1416
            'example.com'}})
1417
        conf._save()
1418
        t = RemoteSSHTransport('bzr+ssh://example.com')
1419
        self.assertEqual('bar', t._get_credentials()[0])
1420
1421
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
1422
class TestRemoteRepository(TestRemote):
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
1423
    """Base for testing RemoteRepository protocol usage.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1424
1425
    These tests contain frozen requests and responses.  We want any changes to
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
1426
    what is sent or expected to be require a thoughtful update to these tests
1427
    because they might break compatibility with different-versioned servers.
1428
    """
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1429
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1430
    def setup_fake_client_and_repository(self, transport_path):
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
1431
        """Create the fake client and repository for testing with.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1432
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
1433
        There's no real server here; we just have canned responses sent
1434
        back one by one.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1435
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
1436
        :param transport_path: Path below the root of the MemoryTransport
1437
            where the repository will be created.
1438
        """
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1439
        transport = MemoryTransport()
1440
        transport.mkdir(transport_path)
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1441
        client = FakeClient(transport.base)
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1442
        transport = transport.clone(transport_path)
1443
        # we do not want bzrdir to make any remote calls
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
1444
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1445
            _client=False)
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1446
        repo = RemoteRepository(bzrdir, None, _client=client)
1447
        return repo, client
1448
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1449
2018.12.2 by Andrew Bennetts
Remove some duplicate code in test_remote
1450
class TestRepositoryGatherStats(TestRemoteRepository):
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
1451
1452
    def test_revid_none(self):
1453
        # ('ok',), body with revisions and size
1454
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1455
        repo, client = self.setup_fake_client_and_repository(transport_path)
1456
        client.add_success_response_with_body(
1457
            'revisions: 2\nsize: 18\n', 'ok')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
1458
        result = repo.gather_stats(None)
1459
        self.assertEqual(
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
1460
            [('call_expecting_body', 'Repository.gather_stats',
3104.4.2 by Andrew Bennetts
All tests passing.
1461
             ('quack/','','no'))],
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
1462
            client._calls)
1463
        self.assertEqual({'revisions': 2, 'size': 18}, result)
1464
1465
    def test_revid_no_committers(self):
1466
        # ('ok',), body without committers
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1467
        body = ('firstrev: 123456.300 3600\n'
1468
                'latestrev: 654231.400 0\n'
1469
                'revisions: 2\n'
1470
                'size: 18\n')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
1471
        transport_path = 'quick'
2018.5.106 by Andrew Bennetts
Update tests in test_remote to use utf-8 byte strings for revision IDs, rather than unicode strings.
1472
        revid = u'\xc8'.encode('utf8')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1473
        repo, client = self.setup_fake_client_and_repository(transport_path)
1474
        client.add_success_response_with_body(body, 'ok')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
1475
        result = repo.gather_stats(revid)
1476
        self.assertEqual(
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
1477
            [('call_expecting_body', 'Repository.gather_stats',
3104.4.2 by Andrew Bennetts
All tests passing.
1478
              ('quick/', revid, 'no'))],
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
1479
            client._calls)
1480
        self.assertEqual({'revisions': 2, 'size': 18,
1481
                          'firstrev': (123456.300, 3600),
1482
                          'latestrev': (654231.400, 0),},
1483
                         result)
1484
1485
    def test_revid_with_committers(self):
1486
        # ('ok',), body with committers
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1487
        body = ('committers: 128\n'
1488
                'firstrev: 123456.300 3600\n'
1489
                'latestrev: 654231.400 0\n'
1490
                'revisions: 2\n'
1491
                'size: 18\n')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
1492
        transport_path = 'buick'
2018.5.106 by Andrew Bennetts
Update tests in test_remote to use utf-8 byte strings for revision IDs, rather than unicode strings.
1493
        revid = u'\xc8'.encode('utf8')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1494
        repo, client = self.setup_fake_client_and_repository(transport_path)
1495
        client.add_success_response_with_body(body, 'ok')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
1496
        result = repo.gather_stats(revid, True)
1497
        self.assertEqual(
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
1498
            [('call_expecting_body', 'Repository.gather_stats',
3104.4.2 by Andrew Bennetts
All tests passing.
1499
              ('buick/', revid, 'yes'))],
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
1500
            client._calls)
1501
        self.assertEqual({'revisions': 2, 'size': 18,
1502
                          'committers': 128,
1503
                          'firstrev': (123456.300, 3600),
1504
                          'latestrev': (654231.400, 0),},
1505
                         result)
1506
1507
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
1508
class TestRepositoryGetGraph(TestRemoteRepository):
1509
1510
    def test_get_graph(self):
3835.1.6 by Aaron Bentley
Reduce inefficiency when doing make_parents_provider frequently
1511
        # get_graph returns a graph with a custom parents provider.
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
1512
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1513
        repo, client = self.setup_fake_client_and_repository(transport_path)
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
1514
        graph = repo.get_graph()
3835.1.6 by Aaron Bentley
Reduce inefficiency when doing make_parents_provider frequently
1515
        self.assertNotEqual(graph._parents_provider, repo)
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
1516
1517
1518
class TestRepositoryGetParentMap(TestRemoteRepository):
1519
1520
    def test_get_parent_map_caching(self):
1521
        # get_parent_map returns from cache until unlock()
1522
        # setup a reponse with two revisions
1523
        r1 = u'\u0e33'.encode('utf8')
1524
        r2 = u'\u0dab'.encode('utf8')
1525
        lines = [' '.join([r2, r1]), r1]
3211.5.2 by Robert Collins
Change RemoteRepository.get_parent_map to use bz2 not gzip for compression.
1526
        encoded_body = bz2.compress('\n'.join(lines))
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
1527
1528
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1529
        repo, client = self.setup_fake_client_and_repository(transport_path)
1530
        client.add_success_response_with_body(encoded_body, 'ok')
1531
        client.add_success_response_with_body(encoded_body, 'ok')
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
1532
        repo.lock_read()
1533
        graph = repo.get_graph()
1534
        parents = graph.get_parent_map([r2])
1535
        self.assertEqual({r2: (r1,)}, parents)
1536
        # locking and unlocking deeper should not reset
1537
        repo.lock_read()
1538
        repo.unlock()
1539
        parents = graph.get_parent_map([r1])
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
1540
        self.assertEqual({r1: (NULL_REVISION,)}, parents)
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
1541
        self.assertEqual(
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.
1542
            [('call_with_body_bytes_expecting_body',
1543
              'Repository.get_parent_map', ('quack/', r2), '\n\n0')],
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
1544
            client._calls)
1545
        repo.unlock()
1546
        # now we call again, and it should use the second response.
1547
        repo.lock_read()
1548
        graph = repo.get_graph()
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
1549
        parents = graph.get_parent_map([r1])
1550
        self.assertEqual({r1: (NULL_REVISION,)}, parents)
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
1551
        self.assertEqual(
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.
1552
            [('call_with_body_bytes_expecting_body',
1553
              'Repository.get_parent_map', ('quack/', r2), '\n\n0'),
1554
             ('call_with_body_bytes_expecting_body',
1555
              'Repository.get_parent_map', ('quack/', r1), '\n\n0'),
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
1556
            ],
1557
            client._calls)
1558
        repo.unlock()
1559
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
1560
    def test_get_parent_map_reconnects_if_unknown_method(self):
1561
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1562
        repo, client = self.setup_fake_client_and_repository(transport_path)
3842.3.20 by Andrew Bennetts
Re-revert changes from another thread that accidentally got reinstated here.
1563
        client.add_unknown_method_response('Repository,get_parent_map')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1564
        client.add_success_response_with_body('', 'ok')
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
1565
        self.assertFalse(client._medium._is_remote_before((1, 2)))
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
1566
        rev_id = 'revision-id'
3297.3.5 by Andrew Bennetts
Suppress a deprecation warning.
1567
        expected_deprecations = [
1568
            'bzrlib.remote.RemoteRepository.get_revision_graph was deprecated '
1569
            'in version 1.4.']
1570
        parents = self.callDeprecated(
1571
            expected_deprecations, repo.get_parent_map, [rev_id])
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
1572
        self.assertEqual(
3213.1.8 by Andrew Bennetts
Merge from bzr.dev.
1573
            [('call_with_body_bytes_expecting_body',
1574
              'Repository.get_parent_map', ('quack/', rev_id), '\n\n0'),
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
1575
             ('disconnect medium',),
1576
             ('call_expecting_body', 'Repository.get_revision_graph',
1577
              ('quack/', ''))],
1578
            client._calls)
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
1579
        # The medium is now marked as being connected to an older server
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
1580
        self.assertTrue(client._medium._is_remote_before((1, 2)))
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
1581
1582
    def test_get_parent_map_fallback_parentless_node(self):
1583
        """get_parent_map falls back to get_revision_graph on old servers.  The
1584
        results from get_revision_graph are tweaked to match the get_parent_map
1585
        API.
1586
3389.1.3 by Andrew Bennetts
Remove XXX from test description.
1587
        Specifically, a {key: ()} result from get_revision_graph means "no
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
1588
        parents" for that key, which in get_parent_map results should be
3389.1.3 by Andrew Bennetts
Remove XXX from test description.
1589
        represented as {key: ('null:',)}.
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
1590
1591
        This is the test for https://bugs.launchpad.net/bzr/+bug/214894
1592
        """
1593
        rev_id = 'revision-id'
1594
        transport_path = 'quack'
3245.4.40 by Andrew Bennetts
Merge from bzr.dev.
1595
        repo, client = self.setup_fake_client_and_repository(transport_path)
1596
        client.add_success_response_with_body(rev_id, 'ok')
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
1597
        client._medium._remember_remote_is_before((1, 2))
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
1598
        expected_deprecations = [
1599
            'bzrlib.remote.RemoteRepository.get_revision_graph was deprecated '
1600
            'in version 1.4.']
1601
        parents = self.callDeprecated(
1602
            expected_deprecations, repo.get_parent_map, [rev_id])
1603
        self.assertEqual(
1604
            [('call_expecting_body', 'Repository.get_revision_graph',
1605
             ('quack/', ''))],
1606
            client._calls)
1607
        self.assertEqual({rev_id: ('null:',)}, parents)
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
1608
3297.2.3 by Andrew Bennetts
Test the code path that the typo is on.
1609
    def test_get_parent_map_unexpected_response(self):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1610
        repo, client = self.setup_fake_client_and_repository('path')
1611
        client.add_success_response('something unexpected!')
3297.2.3 by Andrew Bennetts
Test the code path that the typo is on.
1612
        self.assertRaises(
1613
            errors.UnexpectedSmartServerResponse,
1614
            repo.get_parent_map, ['a-revision-id'])
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
1615
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
1616
3835.1.15 by Aaron Bentley
Allow miss caching to be disabled.
1617
class TestGetParentMapAllowsNew(tests.TestCaseWithTransport):
1618
1619
    def test_allows_new_revisions(self):
1620
        """get_parent_map's results can be updated by commit."""
1621
        smart_server = server.SmartTCPServer_for_testing()
1622
        smart_server.setUp()
1623
        self.addCleanup(smart_server.tearDown)
1624
        self.make_branch('branch')
1625
        branch = Branch.open(smart_server.get_url() + '/branch')
1626
        tree = branch.create_checkout('tree', lightweight=True)
1627
        tree.lock_write()
1628
        self.addCleanup(tree.unlock)
1629
        graph = tree.branch.repository.get_graph()
1630
        # This provides an opportunity for the missing rev-id to be cached.
1631
        self.assertEqual({}, graph.get_parent_map(['rev1']))
1632
        tree.commit('message', rev_id='rev1')
1633
        graph = tree.branch.repository.get_graph()
1634
        self.assertEqual({'rev1': ('null:',)}, graph.get_parent_map(['rev1']))
1635
1636
2018.5.68 by Wouter van Heyst
Merge RemoteRepository.gather_stats.
1637
class TestRepositoryGetRevisionGraph(TestRemoteRepository):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1638
2018.5.68 by Wouter van Heyst
Merge RemoteRepository.gather_stats.
1639
    def test_null_revision(self):
1640
        # a null revision has the predictable result {}, we should have no wire
1641
        # traffic when calling it with this argument
1642
        transport_path = 'empty'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1643
        repo, client = self.setup_fake_client_and_repository(transport_path)
1644
        client.add_success_response('notused')
3287.6.4 by Robert Collins
Fix up deprecation warnings for get_revision_graph.
1645
        result = self.applyDeprecated(one_four, repo.get_revision_graph,
1646
            NULL_REVISION)
2018.5.68 by Wouter van Heyst
Merge RemoteRepository.gather_stats.
1647
        self.assertEqual([], client._calls)
1648
        self.assertEqual({}, result)
1649
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1650
    def test_none_revision(self):
1651
        # with none we want the entire graph
2018.5.106 by Andrew Bennetts
Update tests in test_remote to use utf-8 byte strings for revision IDs, rather than unicode strings.
1652
        r1 = u'\u0e33'.encode('utf8')
1653
        r2 = u'\u0dab'.encode('utf8')
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1654
        lines = [' '.join([r2, r1]), r1]
2018.5.106 by Andrew Bennetts
Update tests in test_remote to use utf-8 byte strings for revision IDs, rather than unicode strings.
1655
        encoded_body = '\n'.join(lines)
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1656
1657
        transport_path = 'sinhala'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1658
        repo, client = self.setup_fake_client_and_repository(transport_path)
1659
        client.add_success_response_with_body(encoded_body, 'ok')
3287.6.4 by Robert Collins
Fix up deprecation warnings for get_revision_graph.
1660
        result = self.applyDeprecated(one_four, repo.get_revision_graph)
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1661
        self.assertEqual(
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
1662
            [('call_expecting_body', 'Repository.get_revision_graph',
3104.4.2 by Andrew Bennetts
All tests passing.
1663
             ('sinhala/', ''))],
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1664
            client._calls)
2625.8.1 by Robert Collins
LIBRARY API BREAKS:
1665
        self.assertEqual({r1: (), r2: (r1, )}, result)
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1666
1667
    def test_specific_revision(self):
1668
        # with a specific revision we want the graph for that
1669
        # with none we want the entire graph
2018.5.106 by Andrew Bennetts
Update tests in test_remote to use utf-8 byte strings for revision IDs, rather than unicode strings.
1670
        r11 = u'\u0e33'.encode('utf8')
1671
        r12 = u'\xc9'.encode('utf8')
1672
        r2 = u'\u0dab'.encode('utf8')
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1673
        lines = [' '.join([r2, r11, r12]), r11, r12]
2018.5.106 by Andrew Bennetts
Update tests in test_remote to use utf-8 byte strings for revision IDs, rather than unicode strings.
1674
        encoded_body = '\n'.join(lines)
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1675
1676
        transport_path = 'sinhala'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1677
        repo, client = self.setup_fake_client_and_repository(transport_path)
1678
        client.add_success_response_with_body(encoded_body, 'ok')
3287.6.4 by Robert Collins
Fix up deprecation warnings for get_revision_graph.
1679
        result = self.applyDeprecated(one_four, repo.get_revision_graph, r2)
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1680
        self.assertEqual(
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
1681
            [('call_expecting_body', 'Repository.get_revision_graph',
3104.4.2 by Andrew Bennetts
All tests passing.
1682
             ('sinhala/', r2))],
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1683
            client._calls)
2625.8.1 by Robert Collins
LIBRARY API BREAKS:
1684
        self.assertEqual({r11: (), r12: (), r2: (r11, r12), }, result)
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1685
1686
    def test_no_such_revision(self):
1687
        revid = '123'
1688
        transport_path = 'sinhala'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1689
        repo, client = self.setup_fake_client_and_repository(transport_path)
1690
        client.add_error_response('nosuchrevision', revid)
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1691
        # also check that the right revision is reported in the error
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1692
        self.assertRaises(errors.NoSuchRevision,
3287.6.4 by Robert Collins
Fix up deprecation warnings for get_revision_graph.
1693
            self.applyDeprecated, one_four, repo.get_revision_graph, revid)
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1694
        self.assertEqual(
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
1695
            [('call_expecting_body', 'Repository.get_revision_graph',
3104.4.2 by Andrew Bennetts
All tests passing.
1696
             ('sinhala/', revid))],
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1697
            client._calls)
1698
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1699
    def test_unexpected_error(self):
1700
        revid = '123'
1701
        transport_path = 'sinhala'
1702
        repo, client = self.setup_fake_client_and_repository(transport_path)
1703
        client.add_error_response('AnUnexpectedError')
3690.1.2 by Andrew Bennetts
Rename UntranslateableErrorFromSmartServer -> UnknownErrorFromSmartServer.
1704
        e = self.assertRaises(errors.UnknownErrorFromSmartServer,
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1705
            self.applyDeprecated, one_four, repo.get_revision_graph, revid)
1706
        self.assertEqual(('AnUnexpectedError',), e.error_tuple)
1707
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1708
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1709
class TestRepositoryIsShared(TestRemoteRepository):
1710
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1711
    def test_is_shared(self):
1712
        # ('yes', ) for Repository.is_shared -> 'True'.
1713
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1714
        repo, client = self.setup_fake_client_and_repository(transport_path)
1715
        client.add_success_response('yes')
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1716
        result = repo.is_shared()
1717
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
1718
            [('call', 'Repository.is_shared', ('quack/',))],
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1719
            client._calls)
1720
        self.assertEqual(True, result)
1721
1722
    def test_is_not_shared(self):
1723
        # ('no', ) for Repository.is_shared -> 'False'.
1724
        transport_path = 'qwack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1725
        repo, client = self.setup_fake_client_and_repository(transport_path)
1726
        client.add_success_response('no')
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1727
        result = repo.is_shared()
1728
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
1729
            [('call', 'Repository.is_shared', ('qwack/',))],
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1730
            client._calls)
1731
        self.assertEqual(False, result)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1732
1733
1734
class TestRepositoryLockWrite(TestRemoteRepository):
1735
1736
    def test_lock_write(self):
1737
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1738
        repo, client = self.setup_fake_client_and_repository(transport_path)
1739
        client.add_success_response('ok', 'a token')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1740
        result = repo.lock_write()
1741
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
1742
            [('call', 'Repository.lock_write', ('quack/', ''))],
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1743
            client._calls)
1744
        self.assertEqual('a token', result)
1745
1746
    def test_lock_write_already_locked(self):
1747
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1748
        repo, client = self.setup_fake_client_and_repository(transport_path)
1749
        client.add_error_response('LockContention')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1750
        self.assertRaises(errors.LockContention, repo.lock_write)
1751
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
1752
            [('call', 'Repository.lock_write', ('quack/', ''))],
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.
1753
            client._calls)
1754
1755
    def test_lock_write_unlockable(self):
1756
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1757
        repo, client = self.setup_fake_client_and_repository(transport_path)
1758
        client.add_error_response('UnlockableTransport')
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.
1759
        self.assertRaises(errors.UnlockableTransport, repo.lock_write)
1760
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
1761
            [('call', 'Repository.lock_write', ('quack/', ''))],
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1762
            client._calls)
1763
1764
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
1765
class TestRepositorySetMakeWorkingTrees(TestRemoteRepository):
1766
1767
    def test_backwards_compat(self):
1768
        self.setup_smart_server_with_call_log()
1769
        repo = self.make_repository('.')
1770
        self.reset_smart_call_log()
1771
        verb = 'Repository.set_make_working_trees'
1772
        self.disable_verb(verb)
1773
        repo.set_make_working_trees(True)
1774
        call_count = len([call for call in self.hpss_calls if
4070.3.1 by Robert Collins
Alter branch sprouting with an alternate fix for stacked branches that does not require multiple copy_content_into and set_parent calls, reducing IO and round trips.
1775
            call.call.method == verb])
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
1776
        self.assertEqual(1, call_count)
1777
1778
    def test_current(self):
1779
        transport_path = 'quack'
1780
        repo, client = self.setup_fake_client_and_repository(transport_path)
1781
        client.add_expected_call(
1782
            'Repository.set_make_working_trees', ('quack/', 'True'),
1783
            'success', ('ok',))
1784
        client.add_expected_call(
1785
            'Repository.set_make_working_trees', ('quack/', 'False'),
1786
            'success', ('ok',))
1787
        repo.set_make_working_trees(True)
1788
        repo.set_make_working_trees(False)
1789
1790
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1791
class TestRepositoryUnlock(TestRemoteRepository):
1792
1793
    def test_unlock(self):
1794
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1795
        repo, client = self.setup_fake_client_and_repository(transport_path)
1796
        client.add_success_response('ok', 'a token')
1797
        client.add_success_response('ok')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1798
        repo.lock_write()
1799
        repo.unlock()
1800
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
1801
            [('call', 'Repository.lock_write', ('quack/', '')),
1802
             ('call', 'Repository.unlock', ('quack/', 'a token'))],
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1803
            client._calls)
1804
1805
    def test_unlock_wrong_token(self):
1806
        # If somehow the token is wrong, unlock will raise TokenMismatch.
1807
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1808
        repo, client = self.setup_fake_client_and_repository(transport_path)
1809
        client.add_success_response('ok', 'a token')
1810
        client.add_error_response('TokenMismatch')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1811
        repo.lock_write()
1812
        self.assertRaises(errors.TokenMismatch, repo.unlock)
1813
1814
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1815
class TestRepositoryHasRevision(TestRemoteRepository):
1816
1817
    def test_none(self):
1818
        # repo.has_revision(None) should not cause any traffic.
1819
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1820
        repo, client = self.setup_fake_client_and_repository(transport_path)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1821
1822
        # The null revision is always there, so has_revision(None) == True.
3172.3.3 by Robert Collins
Missed one occurence of None -> NULL_REVISION.
1823
        self.assertEqual(True, repo.has_revision(NULL_REVISION))
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1824
1825
        # The remote repo shouldn't be accessed.
1826
        self.assertEqual([], client._calls)
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
1827
1828
4144.3.2 by Andrew Bennetts
Use Repository.insert_stream_locked if there is a lock_token for the remote repo.
1829
class TestRepositoryInsertStream(TestRemoteRepository):
1830
1831
    def test_unlocked_repo(self):
1832
        transport_path = 'quack'
1833
        repo, client = self.setup_fake_client_and_repository(transport_path)
1834
        client.add_expected_call(
1835
            'Repository.insert_stream', ('quack/', ''),
1836
            'success', ('ok',))
1837
        client.add_expected_call(
1838
            'Repository.insert_stream', ('quack/', ''),
1839
            'success', ('ok',))
1840
        sink = repo._get_sink()
1841
        fmt = repository.RepositoryFormat.get_default_format()
1842
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
1843
        self.assertEqual([], resume_tokens)
1844
        self.assertEqual(set(), missing_keys)
1845
        client.finished_test()
1846
1847
    def test_locked_repo_with_no_lock_token(self):
1848
        transport_path = 'quack'
1849
        repo, client = self.setup_fake_client_and_repository(transport_path)
1850
        client.add_expected_call(
1851
            'Repository.lock_write', ('quack/', ''),
1852
            'success', ('ok', ''))
1853
        client.add_expected_call(
1854
            'Repository.insert_stream', ('quack/', ''),
1855
            'success', ('ok',))
1856
        client.add_expected_call(
1857
            'Repository.insert_stream', ('quack/', ''),
1858
            'success', ('ok',))
1859
        repo.lock_write()
1860
        sink = repo._get_sink()
1861
        fmt = repository.RepositoryFormat.get_default_format()
1862
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
1863
        self.assertEqual([], resume_tokens)
1864
        self.assertEqual(set(), missing_keys)
1865
        client.finished_test()
1866
1867
    def test_locked_repo_with_lock_token(self):
1868
        transport_path = 'quack'
1869
        repo, client = self.setup_fake_client_and_repository(transport_path)
1870
        client.add_expected_call(
1871
            'Repository.lock_write', ('quack/', ''),
1872
            'success', ('ok', 'a token'))
1873
        client.add_expected_call(
1874
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
1875
            'success', ('ok',))
1876
        client.add_expected_call(
1877
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
1878
            'success', ('ok',))
1879
        repo.lock_write()
1880
        sink = repo._get_sink()
1881
        fmt = repository.RepositoryFormat.get_default_format()
1882
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
1883
        self.assertEqual([], resume_tokens)
1884
        self.assertEqual(set(), missing_keys)
1885
        client.finished_test()
1886
1887
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
1888
class TestRepositoryTarball(TestRemoteRepository):
1889
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
1890
    # This is a canned tarball reponse we can validate against
2018.18.18 by Martin Pool
reformat
1891
    tarball_content = (
2018.18.23 by Martin Pool
review cleanups
1892
        'QlpoOTFBWSZTWdGkj3wAAWF/k8aQACBIB//A9+8cIX/v33AACEAYABAECEACNz'
1893
        'JqsgJJFPTSnk1A3qh6mTQAAAANPUHkagkSTEkaA09QaNAAAGgAAAcwCYCZGAEY'
1894
        'mJhMJghpiaYBUkKammSHqNMZQ0NABkNAeo0AGneAevnlwQoGzEzNVzaYxp/1Uk'
1895
        'xXzA1CQX0BJMZZLcPBrluJir5SQyijWHYZ6ZUtVqqlYDdB2QoCwa9GyWwGYDMA'
1896
        'OQYhkpLt/OKFnnlT8E0PmO8+ZNSo2WWqeCzGB5fBXZ3IvV7uNJVE7DYnWj6qwB'
1897
        'k5DJDIrQ5OQHHIjkS9KqwG3mc3t+F1+iujb89ufyBNIKCgeZBWrl5cXxbMGoMs'
1898
        'c9JuUkg5YsiVcaZJurc6KLi6yKOkgCUOlIlOpOoXyrTJjK8ZgbklReDdwGmFgt'
1899
        'dkVsAIslSVCd4AtACSLbyhLHryfb14PKegrVDba+U8OL6KQtzdM5HLjAc8/p6n'
1900
        '0lgaWU8skgO7xupPTkyuwheSckejFLK5T4ZOo0Gda9viaIhpD1Qn7JqqlKAJqC'
1901
        'QplPKp2nqBWAfwBGaOwVrz3y1T+UZZNismXHsb2Jq18T+VaD9k4P8DqE3g70qV'
1902
        'JLurpnDI6VS5oqDDPVbtVjMxMxMg4rzQVipn2Bv1fVNK0iq3Gl0hhnnHKm/egy'
1903
        'nWQ7QH/F3JFOFCQ0aSPfA='
1904
        ).decode('base64')
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
1905
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
1906
    def test_repository_tarball(self):
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
1907
        # Test that Repository.tarball generates the right operations
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
1908
        transport_path = 'repo'
2018.18.14 by Martin Pool
merge hpss again; restore incorrectly removed RemoteRepository.break_lock
1909
        expected_calls = [('call_expecting_body', 'Repository.tarball',
3104.4.2 by Andrew Bennetts
All tests passing.
1910
                           ('repo/', 'bz2',),),
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
1911
            ]
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1912
        repo, client = self.setup_fake_client_and_repository(transport_path)
1913
        client.add_success_response_with_body(self.tarball_content, 'ok')
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
1914
        # Now actually ask for the tarball
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1915
        tarball_file = repo._get_tarball('bz2')
2018.18.25 by Martin Pool
Repository.tarball fixes for python2.4
1916
        try:
1917
            self.assertEqual(expected_calls, client._calls)
1918
            self.assertEqual(self.tarball_content, tarball_file.read())
1919
        finally:
1920
            tarball_file.close()
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
1921
1922
1923
class TestRemoteRepositoryCopyContent(tests.TestCaseWithTransport):
1924
    """RemoteRepository.copy_content_into optimizations"""
1925
2018.18.10 by Martin Pool
copy_content_into from Remote repositories by using temporary directories on both ends.
1926
    def test_copy_content_remote_to_local(self):
1927
        self.transport_server = server.SmartTCPServer_for_testing
1928
        src_repo = self.make_repository('repo1')
1929
        src_repo = repository.Repository.open(self.get_url('repo1'))
1930
        # At the moment the tarball-based copy_content_into can't write back
1931
        # into a smart server.  It would be good if it could upload the
1932
        # tarball; once that works we'd have to create repositories of
1933
        # different formats. -- mbp 20070410
1934
        dest_url = self.get_vfs_only_url('repo2')
1935
        dest_bzrdir = BzrDir.create(dest_url)
1936
        dest_repo = dest_bzrdir.create_repository()
1937
        self.assertFalse(isinstance(dest_repo, RemoteRepository))
1938
        self.assertTrue(isinstance(src_repo, RemoteRepository))
1939
        src_repo.copy_content_into(dest_repo)
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
1940
1941
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1942
class _StubRealPackRepository(object):
1943
1944
    def __init__(self, calls):
1945
        self._pack_collection = _StubPackCollection(calls)
1946
1947
1948
class _StubPackCollection(object):
1949
1950
    def __init__(self, calls):
1951
        self.calls = calls
1952
1953
    def autopack(self):
1954
        self.calls.append(('pack collection autopack',))
1955
3801.1.13 by Andrew Bennetts
Revert returning of pack-names from the RPC.
1956
    def reload_pack_names(self):
1957
        self.calls.append(('pack collection reload_pack_names',))
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1958
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1959
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1960
class TestRemotePackRepositoryAutoPack(TestRemoteRepository):
1961
    """Tests for RemoteRepository.autopack implementation."""
1962
1963
    def test_ok(self):
1964
        """When the server returns 'ok' and there's no _real_repository, then
1965
        nothing else happens: the autopack method is done.
1966
        """
1967
        transport_path = 'quack'
1968
        repo, client = self.setup_fake_client_and_repository(transport_path)
1969
        client.add_expected_call(
3801.1.13 by Andrew Bennetts
Revert returning of pack-names from the RPC.
1970
            'PackRepository.autopack', ('quack/',), 'success', ('ok',))
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1971
        repo.autopack()
1972
        client.finished_test()
1973
1974
    def test_ok_with_real_repo(self):
1975
        """When the server returns 'ok' and there is a _real_repository, then
1976
        the _real_repository's reload_pack_name's method will be called.
1977
        """
1978
        transport_path = 'quack'
1979
        repo, client = self.setup_fake_client_and_repository(transport_path)
1980
        client.add_expected_call(
1981
            'PackRepository.autopack', ('quack/',),
3801.1.13 by Andrew Bennetts
Revert returning of pack-names from the RPC.
1982
            'success', ('ok',))
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1983
        repo._real_repository = _StubRealPackRepository(client._calls)
1984
        repo.autopack()
1985
        self.assertEqual(
1986
            [('call', 'PackRepository.autopack', ('quack/',)),
3801.1.13 by Andrew Bennetts
Revert returning of pack-names from the RPC.
1987
             ('pack collection reload_pack_names',)],
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1988
            client._calls)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1989
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
1990
    def test_backwards_compatibility(self):
1991
        """If the server does not recognise the PackRepository.autopack verb,
1992
        fallback to the real_repository's implementation.
1993
        """
1994
        transport_path = 'quack'
1995
        repo, client = self.setup_fake_client_and_repository(transport_path)
1996
        client.add_unknown_method_response('PackRepository.autopack')
1997
        def stub_ensure_real():
1998
            client._calls.append(('_ensure_real',))
1999
            repo._real_repository = _StubRealPackRepository(client._calls)
2000
        repo._ensure_real = stub_ensure_real
2001
        repo.autopack()
2002
        self.assertEqual(
2003
            [('call', 'PackRepository.autopack', ('quack/',)),
2004
             ('_ensure_real',),
2005
             ('pack collection autopack',)],
2006
            client._calls)
2007
2008
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2009
class TestErrorTranslationBase(tests.TestCaseWithMemoryTransport):
2010
    """Base class for unit tests for bzrlib.remote._translate_error."""
2011
2012
    def translateTuple(self, error_tuple, **context):
2013
        """Call _translate_error with an ErrorFromSmartServer built from the
2014
        given error_tuple.
2015
2016
        :param error_tuple: A tuple of a smart server response, as would be
2017
            passed to an ErrorFromSmartServer.
2018
        :kwargs context: context items to call _translate_error with.
2019
2020
        :returns: The error raised by _translate_error.
2021
        """
2022
        # Raise the ErrorFromSmartServer before passing it as an argument,
2023
        # because _translate_error may need to re-raise it with a bare 'raise'
2024
        # statement.
2025
        server_error = errors.ErrorFromSmartServer(error_tuple)
2026
        translated_error = self.translateErrorFromSmartServer(
2027
            server_error, **context)
2028
        return translated_error
2029
2030
    def translateErrorFromSmartServer(self, error_object, **context):
2031
        """Like translateTuple, but takes an already constructed
2032
        ErrorFromSmartServer rather than a tuple.
2033
        """
2034
        try:
2035
            raise error_object
2036
        except errors.ErrorFromSmartServer, server_error:
2037
            translated_error = self.assertRaises(
2038
                errors.BzrError, remote._translate_error, server_error,
2039
                **context)
2040
        return translated_error
2041
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
2042
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2043
class TestErrorTranslationSuccess(TestErrorTranslationBase):
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2044
    """Unit tests for bzrlib.remote._translate_error.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2045
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2046
    Given an ErrorFromSmartServer (which has an error tuple from a smart
2047
    server) and some context, _translate_error raises more specific errors from
2048
    bzrlib.errors.
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2049
2050
    This test case covers the cases where _translate_error succeeds in
2051
    translating an ErrorFromSmartServer to something better.  See
2052
    TestErrorTranslationRobustness for other cases.
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2053
    """
2054
2055
    def test_NoSuchRevision(self):
2056
        branch = self.make_branch('')
2057
        revid = 'revid'
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2058
        translated_error = self.translateTuple(
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2059
            ('NoSuchRevision', revid), branch=branch)
2060
        expected_error = errors.NoSuchRevision(branch, revid)
2061
        self.assertEqual(expected_error, translated_error)
2062
2063
    def test_nosuchrevision(self):
2064
        repository = self.make_repository('')
2065
        revid = 'revid'
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2066
        translated_error = self.translateTuple(
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2067
            ('nosuchrevision', revid), repository=repository)
2068
        expected_error = errors.NoSuchRevision(repository, revid)
2069
        self.assertEqual(expected_error, translated_error)
2070
2071
    def test_nobranch(self):
2072
        bzrdir = self.make_bzrdir('')
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2073
        translated_error = self.translateTuple(('nobranch',), bzrdir=bzrdir)
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2074
        expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
2075
        self.assertEqual(expected_error, translated_error)
2076
2077
    def test_LockContention(self):
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2078
        translated_error = self.translateTuple(('LockContention',))
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2079
        expected_error = errors.LockContention('(remote lock)')
2080
        self.assertEqual(expected_error, translated_error)
2081
2082
    def test_UnlockableTransport(self):
2083
        bzrdir = self.make_bzrdir('')
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2084
        translated_error = self.translateTuple(
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2085
            ('UnlockableTransport',), bzrdir=bzrdir)
2086
        expected_error = errors.UnlockableTransport(bzrdir.root_transport)
2087
        self.assertEqual(expected_error, translated_error)
2088
2089
    def test_LockFailed(self):
2090
        lock = 'str() of a server lock'
2091
        why = 'str() of why'
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2092
        translated_error = self.translateTuple(('LockFailed', lock, why))
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2093
        expected_error = errors.LockFailed(lock, why)
2094
        self.assertEqual(expected_error, translated_error)
2095
2096
    def test_TokenMismatch(self):
2097
        token = 'a lock token'
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2098
        translated_error = self.translateTuple(('TokenMismatch',), token=token)
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2099
        expected_error = errors.TokenMismatch(token, '(remote token)')
2100
        self.assertEqual(expected_error, translated_error)
2101
2102
    def test_Diverged(self):
2103
        branch = self.make_branch('a')
2104
        other_branch = self.make_branch('b')
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2105
        translated_error = self.translateTuple(
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2106
            ('Diverged',), branch=branch, other_branch=other_branch)
2107
        expected_error = errors.DivergedBranches(branch, other_branch)
2108
        self.assertEqual(expected_error, translated_error)
2109
3786.4.2 by Andrew Bennetts
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
2110
    def test_ReadError_no_args(self):
2111
        path = 'a path'
2112
        translated_error = self.translateTuple(('ReadError',), path=path)
2113
        expected_error = errors.ReadError(path)
2114
        self.assertEqual(expected_error, translated_error)
2115
2116
    def test_ReadError(self):
2117
        path = 'a path'
2118
        translated_error = self.translateTuple(('ReadError', path))
2119
        expected_error = errors.ReadError(path)
2120
        self.assertEqual(expected_error, translated_error)
2121
2122
    def test_PermissionDenied_no_args(self):
2123
        path = 'a path'
2124
        translated_error = self.translateTuple(('PermissionDenied',), path=path)
2125
        expected_error = errors.PermissionDenied(path)
2126
        self.assertEqual(expected_error, translated_error)
2127
2128
    def test_PermissionDenied_one_arg(self):
2129
        path = 'a path'
2130
        translated_error = self.translateTuple(('PermissionDenied', path))
2131
        expected_error = errors.PermissionDenied(path)
2132
        self.assertEqual(expected_error, translated_error)
2133
2134
    def test_PermissionDenied_one_arg_and_context(self):
2135
        """Given a choice between a path from the local context and a path on
2136
        the wire, _translate_error prefers the path from the local context.
2137
        """
2138
        local_path = 'local path'
2139
        remote_path = 'remote path'
2140
        translated_error = self.translateTuple(
2141
            ('PermissionDenied', remote_path), path=local_path)
2142
        expected_error = errors.PermissionDenied(local_path)
2143
        self.assertEqual(expected_error, translated_error)
2144
2145
    def test_PermissionDenied_two_args(self):
2146
        path = 'a path'
2147
        extra = 'a string with extra info'
2148
        translated_error = self.translateTuple(
2149
            ('PermissionDenied', path, extra))
2150
        expected_error = errors.PermissionDenied(path, extra)
2151
        self.assertEqual(expected_error, translated_error)
2152
2153
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2154
class TestErrorTranslationRobustness(TestErrorTranslationBase):
2155
    """Unit tests for bzrlib.remote._translate_error's robustness.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2156
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2157
    TestErrorTranslationSuccess is for cases where _translate_error can
2158
    translate successfully.  This class about how _translate_err behaves when
2159
    it fails to translate: it re-raises the original error.
2160
    """
2161
2162
    def test_unrecognised_server_error(self):
2163
        """If the error code from the server is not recognised, the original
2164
        ErrorFromSmartServer is propagated unmodified.
2165
        """
2166
        error_tuple = ('An unknown error tuple',)
3690.1.2 by Andrew Bennetts
Rename UntranslateableErrorFromSmartServer -> UnknownErrorFromSmartServer.
2167
        server_error = errors.ErrorFromSmartServer(error_tuple)
2168
        translated_error = self.translateErrorFromSmartServer(server_error)
2169
        expected_error = errors.UnknownErrorFromSmartServer(server_error)
3690.1.1 by Andrew Bennetts
Unexpected error responses from a smart server no longer cause the client to traceback.
2170
        self.assertEqual(expected_error, translated_error)
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2171
2172
    def test_context_missing_a_key(self):
2173
        """In case of a bug in the client, or perhaps an unexpected response
2174
        from a server, _translate_error returns the original error tuple from
2175
        the server and mutters a warning.
2176
        """
2177
        # To translate a NoSuchRevision error _translate_error needs a 'branch'
2178
        # in the context dict.  So let's give it an empty context dict instead
2179
        # to exercise its error recovery.
2180
        empty_context = {}
2181
        error_tuple = ('NoSuchRevision', 'revid')
2182
        server_error = errors.ErrorFromSmartServer(error_tuple)
2183
        translated_error = self.translateErrorFromSmartServer(server_error)
2184
        self.assertEqual(server_error, translated_error)
2185
        # In addition to re-raising ErrorFromSmartServer, some debug info has
2186
        # been muttered to the log file for developer to look at.
2187
        self.assertContainsRe(
2188
            self._get_log(keep_log_file=True),
2189
            "Missing key 'branch' in context")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2190
3786.4.2 by Andrew Bennetts
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
2191
    def test_path_missing(self):
2192
        """Some translations (PermissionDenied, ReadError) can determine the
2193
        'path' variable from either the wire or the local context.  If neither
2194
        has it, then an error is raised.
2195
        """
2196
        error_tuple = ('ReadError',)
2197
        server_error = errors.ErrorFromSmartServer(error_tuple)
2198
        translated_error = self.translateErrorFromSmartServer(server_error)
2199
        self.assertEqual(server_error, translated_error)
2200
        # In addition to re-raising ErrorFromSmartServer, some debug info has
2201
        # been muttered to the log file for developer to look at.
2202
        self.assertContainsRe(
2203
            self._get_log(keep_log_file=True), "Missing key 'path' in context")
2204
3691.2.2 by Martin Pool
Fix some problems in access to stacked repositories over hpss (#261315)
2205
2206
class TestStacking(tests.TestCaseWithTransport):
2207
    """Tests for operations on stacked remote repositories.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2208
3691.2.2 by Martin Pool
Fix some problems in access to stacked repositories over hpss (#261315)
2209
    The underlying format type must support stacking.
2210
    """
2211
2212
    def test_access_stacked_remote(self):
2213
        # based on <http://launchpad.net/bugs/261315>
2214
        # make a branch stacked on another repository containing an empty
2215
        # revision, then open it over hpss - we should be able to see that
2216
        # revision.
2217
        base_transport = self.get_transport()
2218
        base_builder = self.make_branch_builder('base', format='1.6')
2219
        base_builder.start_series()
2220
        base_revid = base_builder.build_snapshot('rev-id', None,
2221
            [('add', ('', None, 'directory', None))],
2222
            'message')
2223
        base_builder.finish_series()
2224
        stacked_branch = self.make_branch('stacked', format='1.6')
2225
        stacked_branch.set_stacked_on_url('../base')
2226
        # start a server looking at this
2227
        smart_server = server.SmartTCPServer_for_testing()
2228
        smart_server.setUp()
2229
        self.addCleanup(smart_server.tearDown)
2230
        remote_bzrdir = BzrDir.open(smart_server.get_url() + '/stacked')
2231
        # can get its branch and repository
2232
        remote_branch = remote_bzrdir.open_branch()
2233
        remote_repo = remote_branch.repository
3691.2.6 by Martin Pool
Disable RemoteBranch stacking, but get get_stacked_on_url working, and passing back exceptions
2234
        remote_repo.lock_read()
2235
        try:
2236
            # it should have an appropriate fallback repository, which should also
2237
            # be a RemoteRepository
2238
            self.assertEquals(len(remote_repo._fallback_repositories), 1)
2239
            self.assertIsInstance(remote_repo._fallback_repositories[0],
2240
                RemoteRepository)
2241
            # and it has the revision committed to the underlying repository;
2242
            # these have varying implementations so we try several of them
2243
            self.assertTrue(remote_repo.has_revisions([base_revid]))
2244
            self.assertTrue(remote_repo.has_revision(base_revid))
2245
            self.assertEqual(remote_repo.get_revision(base_revid).message,
2246
                'message')
2247
        finally:
2248
            remote_repo.unlock()
3835.1.2 by Aaron Bentley
Add tests for get_parent_map
2249
3835.1.7 by Aaron Bentley
Updates from review
2250
    def prepare_stacked_remote_branch(self):
3835.1.2 by Aaron Bentley
Add tests for get_parent_map
2251
        smart_server = server.SmartTCPServer_for_testing()
2252
        smart_server.setUp()
2253
        self.addCleanup(smart_server.tearDown)
2254
        tree1 = self.make_branch_and_tree('tree1')
2255
        tree1.commit('rev1', rev_id='rev1')
2256
        tree2 = self.make_branch_and_tree('tree2', format='1.6')
2257
        tree2.branch.set_stacked_on_url(tree1.branch.base)
2258
        branch2 = Branch.open(smart_server.get_url() + '/tree2')
2259
        branch2.lock_read()
2260
        self.addCleanup(branch2.unlock)
3835.1.7 by Aaron Bentley
Updates from review
2261
        return branch2
2262
2263
    def test_stacked_get_parent_map(self):
2264
        # the public implementation of get_parent_map obeys stacking
2265
        branch = self.prepare_stacked_remote_branch()
2266
        repo = branch.repository
3835.1.2 by Aaron Bentley
Add tests for get_parent_map
2267
        self.assertEqual(['rev1'], repo.get_parent_map(['rev1']).keys())
3835.1.7 by Aaron Bentley
Updates from review
2268
3835.1.10 by Aaron Bentley
Move CachingExtraParentsProvider to Graph
2269
    def test_unstacked_get_parent_map(self):
2270
        # _unstacked_provider.get_parent_map ignores stacking
3835.1.7 by Aaron Bentley
Updates from review
2271
        branch = self.prepare_stacked_remote_branch()
3835.1.10 by Aaron Bentley
Move CachingExtraParentsProvider to Graph
2272
        provider = branch.repository._unstacked_provider
3835.1.8 by Aaron Bentley
Make UnstackedParentsProvider manage the cache
2273
        self.assertEqual([], provider.get_parent_map(['rev1']).keys())
3834.3.3 by John Arbash Meinel
Merge bzr.dev, resolve conflict in tests.
2274
3834.3.2 by Andrew Bennetts
Preserve BzrBranch5's _synchronize_history code without affecting Branch or BzrBranch7; add effort test for RemoteBranch.copy_content_into.
2275
2276
class TestRemoteBranchEffort(tests.TestCaseWithTransport):
2277
2278
    def setUp(self):
2279
        super(TestRemoteBranchEffort, self).setUp()
2280
        # Create a smart server that publishes whatever the backing VFS server
2281
        # does.
2282
        self.smart_server = server.SmartTCPServer_for_testing()
2283
        self.smart_server.setUp(self.get_server())
2284
        self.addCleanup(self.smart_server.tearDown)
2285
        # Log all HPSS calls into self.hpss_calls.
2286
        _SmartClient.hooks.install_named_hook(
2287
            'call', self.capture_hpss_call, None)
2288
        self.hpss_calls = []
2289
2290
    def capture_hpss_call(self, params):
2291
        self.hpss_calls.append(params.method)
2292
2293
    def test_copy_content_into_avoids_revision_history(self):
2294
        local = self.make_branch('local')
2295
        remote_backing_tree = self.make_branch_and_tree('remote')
2296
        remote_backing_tree.commit("Commit.")
2297
        remote_branch_url = self.smart_server.get_url() + 'remote'
2298
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
2299
        local.repository.fetch(remote_branch.repository)
2300
        self.hpss_calls = []
2301
        remote_branch.copy_content_into(local)
3834.3.3 by John Arbash Meinel
Merge bzr.dev, resolve conflict in tests.
2302
        self.assertFalse('Branch.revision_history' in self.hpss_calls)