/brz/remove-bazaar

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