/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5557.1.7 by John Arbash Meinel
Merge in the bzr.dev 5582
1
# Copyright (C) 2006-2011 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 (
4792.1.1 by Andrew Bennetts
Show real branch/repo format description in 'info -v' over HPSS.
30
    branch,
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.
31
    bzrdir,
3777.1.3 by Aaron Bentley
Use SSH default username from authentication.conf
32
    config,
5363.2.9 by Jelmer Vernooij
Fix some tests.
33
    controldir,
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
34
    errors,
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
35
    graph,
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
36
    inventory,
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
37
    inventory_delta,
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
38
    remote,
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
39
    repository,
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
40
    tests,
5273.1.7 by Vincent Ladeuil
No more use of the get_transport imported *symbol*, all uses are through
41
    transport,
4190.1.4 by Robert Collins
Cache ghosts when we can get them from a RemoteRepository in get_parent_map.
42
    treebuilder,
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
43
    versionedfile,
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
44
    )
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
45
from bzrlib.branch import Branch
5363.2.9 by Jelmer Vernooij
Fix some tests.
46
from bzrlib.bzrdir import (
47
    BzrDir,
48
    BzrDirFormat,
49
    RemoteBzrProber,
50
    )
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
51
from bzrlib.remote import (
52
    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.
53
    RemoteBranchFormat,
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
54
    RemoteBzrDir,
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
55
    RemoteRepository,
4183.5.1 by Robert Collins
Add RepositoryFormat.fast_deltas to signal fast delta creation.
56
    RemoteRepositoryFormat,
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
57
    )
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
58
from bzrlib.repofmt import groupcompress_repo, pack_repo
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
59
from bzrlib.revision import NULL_REVISION
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
60
from bzrlib.smart import medium, request
2018.5.159 by Andrew Bennetts
Rename SmartClient to _SmartClient.
61
from bzrlib.smart.client import _SmartClient
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
62
from bzrlib.smart.repository import (
63
    SmartServerRepositoryGetParentMap,
64
    SmartServerRepositoryGetStream_1_19,
65
    )
4118.1.1 by Andrew Bennetts
Fix performance regression (many small round-trips) when pushing to a remote pack, and tidy the tests.
66
from bzrlib.tests import (
5017.3.28 by Vincent Ladeuil
selftest -s bt.test_remote passing
67
    test_server,
4118.1.1 by Andrew Bennetts
Fix performance regression (many small round-trips) when pushing to a remote pack, and tidy the tests.
68
    )
5559.2.2 by Martin Pool
Change to using standard load_tests_apply_scenarios.
69
from bzrlib.tests.scenarios import load_tests_apply_scenarios
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
70
from bzrlib.transport.memory import MemoryTransport
3777.1.3 by Aaron Bentley
Use SSH default username from authentication.conf
71
from bzrlib.transport.remote import (
72
    RemoteTransport,
73
    RemoteSSHTransport,
74
    RemoteTCPTransport,
5579.3.1 by Jelmer Vernooij
Remove unused imports.
75
    )
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
76
5559.2.2 by Martin Pool
Change to using standard load_tests_apply_scenarios.
77
78
load_tests = load_tests_apply_scenarios
79
80
81
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
82
83
    scenarios = [
4104.4.2 by Robert Collins
Fix test_source for 1.13 landing.
84
        ('HPSS-v2',
5559.2.2 by Martin Pool
Change to using standard load_tests_apply_scenarios.
85
            {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
4104.4.2 by Robert Collins
Fix test_source for 1.13 landing.
86
        ('HPSS-v3',
5559.2.2 by Martin Pool
Change to using standard load_tests_apply_scenarios.
87
            {'transport_server': test_server.SmartTCPServer_for_testing})]
88
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
89
90
    def setUp(self):
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
91
        super(BasicRemoteObjectTests, self).setUp()
92
        self.transport = self.get_transport()
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
93
        # 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
94
        self.local_wt = BzrDir.create_standalone_workingtree('.')
4986.2.1 by Martin Pool
Remove tearDown in tests in favor of addCleanup
95
        self.addCleanup(self.transport.disconnect)
2018.5.171 by Andrew Bennetts
Disconnect RemoteTransports in some tests to avoid tripping up test_strace with leftover threads from previous tests.
96
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
97
    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.
98
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
99
        self.assertIsInstance(b, BzrDir)
100
101
    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.
102
        # 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.
103
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
104
        branch = b.open_branch()
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
105
        self.assertIsInstance(branch, Branch)
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
106
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
107
    def test_remote_repository(self):
108
        b = BzrDir.open_from_transport(self.transport)
109
        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.
110
        revid = u'\xc823123123'.encode('utf8')
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
111
        self.assertFalse(repo.has_revision(revid))
112
        self.local_wt.commit(message='test commit', rev_id=revid)
113
        self.assertTrue(repo.has_revision(revid))
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
114
115
    def test_remote_branch_revision_history(self):
116
        b = BzrDir.open_from_transport(self.transport).open_branch()
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
117
        self.assertEqual([], b.revision_history())
118
        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.
119
        r2 = self.local_wt.commit('1st commit', rev_id=u'\xc8'.encode('utf8'))
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
120
        self.assertEqual([r1, r2], b.revision_history())
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
121
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
122
    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)
123
        """Should open a RemoteBzrDir over a RemoteTransport"""
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
124
        fmt = BzrDirFormat.find_format(self.transport)
5363.2.9 by Jelmer Vernooij
Fix some tests.
125
        self.assertTrue(bzrdir.RemoteBzrProber
126
                        in controldir.ControlDirFormat._server_probers)
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
127
        self.assertIsInstance(fmt, remote.RemoteBzrDirFormat)
128
129
    def test_open_detected_smart_format(self):
130
        fmt = BzrDirFormat.find_format(self.transport)
131
        d = fmt.open(self.transport)
132
        self.assertIsInstance(d, BzrDir)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
133
2477.1.1 by Martin Pool
Add RemoteBranch repr
134
    def test_remote_branch_repr(self):
135
        b = BzrDir.open_from_transport(self.transport).open_branch()
136
        self.assertStartsWith(str(b), 'RemoteBranch(')
137
4964.2.1 by Martin Pool
Add RemoteBzrDir repr
138
    def test_remote_bzrdir_repr(self):
139
        b = BzrDir.open_from_transport(self.transport)
140
        self.assertStartsWith(str(b), 'RemoteBzrDir(')
141
4103.2.2 by Andrew Bennetts
Fix RemoteBranchFormat.supports_stacking()
142
    def test_remote_branch_format_supports_stacking(self):
143
        t = self.transport
144
        self.make_branch('unstackable', format='pack-0.92')
145
        b = BzrDir.open_from_transport(t.clone('unstackable')).open_branch()
146
        self.assertFalse(b._format.supports_stacking())
147
        self.make_branch('stackable', format='1.9')
148
        b = BzrDir.open_from_transport(t.clone('stackable')).open_branch()
149
        self.assertTrue(b._format.supports_stacking())
150
4118.1.1 by Andrew Bennetts
Fix performance regression (many small round-trips) when pushing to a remote pack, and tidy the tests.
151
    def test_remote_repo_format_supports_external_references(self):
152
        t = self.transport
153
        bd = self.make_bzrdir('unstackable', format='pack-0.92')
154
        r = bd.create_repository()
155
        self.assertFalse(r._format.supports_external_lookups)
156
        r = BzrDir.open_from_transport(t.clone('unstackable')).open_repository()
157
        self.assertFalse(r._format.supports_external_lookups)
158
        bd = self.make_bzrdir('stackable', format='1.9')
159
        r = bd.create_repository()
160
        self.assertTrue(r._format.supports_external_lookups)
161
        r = BzrDir.open_from_transport(t.clone('stackable')).open_repository()
162
        self.assertTrue(r._format.supports_external_lookups)
163
4301.3.1 by Andrew Bennetts
Implement RemoteBranch.set_append_revisions_only.
164
    def test_remote_branch_set_append_revisions_only(self):
165
        # Make a format 1.9 branch, which supports append_revisions_only
166
        branch = self.make_branch('branch', format='1.9')
167
        config = branch.get_config()
168
        branch.set_append_revisions_only(True)
169
        self.assertEqual(
170
            'True', config.get_user_option('append_revisions_only'))
171
        branch.set_append_revisions_only(False)
172
        self.assertEqual(
173
            'False', config.get_user_option('append_revisions_only'))
174
175
    def test_remote_branch_set_append_revisions_only_upgrade_reqd(self):
176
        branch = self.make_branch('branch', format='knit')
177
        config = branch.get_config()
178
        self.assertRaises(
4301.3.3 by Andrew Bennetts
Move check onto base Branch class, and add a supports_set_append_revisions_only method to BranchFormat, as suggested by Robert.
179
            errors.UpgradeRequired, branch.set_append_revisions_only, True)
4301.3.1 by Andrew Bennetts
Implement RemoteBranch.set_append_revisions_only.
180
3691.2.4 by Martin Pool
Add FakeRemoteTransport to clarify test_remote
181
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
182
class FakeProtocol(object):
183
    """Lookalike SmartClientRequestProtocolOne allowing body reading tests."""
184
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
185
    def __init__(self, body, fake_client):
2535.4.2 by Andrew Bennetts
Nasty hackery to make stream_knit_data_for_revisions response use streaming.
186
        self.body = body
187
        self._body_buffer = None
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
188
        self._fake_client = fake_client
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
189
190
    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.
191
        if self._body_buffer is None:
192
            self._body_buffer = StringIO(self.body)
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
193
        bytes = self._body_buffer.read(count)
194
        if self._body_buffer.tell() == len(self._body_buffer.getvalue()):
195
            self._fake_client.expecting_body = False
196
        return bytes
197
198
    def cancel_read_body(self):
199
        self._fake_client.expecting_body = False
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
200
2535.4.2 by Andrew Bennetts
Nasty hackery to make stream_knit_data_for_revisions response use streaming.
201
    def read_streamed_body(self):
202
        return self.body
203
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
204
2018.5.159 by Andrew Bennetts
Rename SmartClient to _SmartClient.
205
class FakeClient(_SmartClient):
206
    """Lookalike for _SmartClient allowing testing."""
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
207
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
208
    def __init__(self, fake_medium_base='fake base'):
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
209
        """Create a FakeClient."""
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
210
        self.responses = []
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
211
        self._calls = []
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
212
        self.expecting_body = False
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
213
        # if non-None, this is the list of expected calls, with only the
214
        # 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.
215
        # compute so is not included. If a call is None, that call can
216
        # be anything.
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
217
        self._expected_calls = None
3431.3.2 by Andrew Bennetts
Remove 'base' from _SmartClient entirely, now that the medium has it.
218
        _SmartClient.__init__(self, FakeMedium(self._calls, fake_medium_base))
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
219
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
220
    def add_expected_call(self, call_name, call_args, response_type,
221
        response_args, response_body=None):
222
        if self._expected_calls is None:
223
            self._expected_calls = []
224
        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
225
        self.responses.append((response_type, response_args, response_body))
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
226
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
227
    def add_success_response(self, *args):
228
        self.responses.append(('success', args, None))
229
230
    def add_success_response_with_body(self, body, *args):
231
        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.
232
        if self._expected_calls is not None:
233
            self._expected_calls.append(None)
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
234
235
    def add_error_response(self, *args):
236
        self.responses.append(('error', args))
237
238
    def add_unknown_method_response(self, verb):
239
        self.responses.append(('unknown', verb))
240
4523.3.2 by Andrew Bennetts
Adjust according to Robert's review.
241
    def finished_test(self):
242
        if self._expected_calls:
243
            raise AssertionError("%r finished but was still expecting %r"
244
                % (self, self._expected_calls[0]))
245
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.
246
    def _get_next_response(self):
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
247
        try:
248
            response_tuple = self.responses.pop(0)
249
        except IndexError, e:
250
            raise AssertionError("%r didn't expect any more calls"
251
                % (self,))
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
252
        if response_tuple[0] == 'unknown':
253
            raise errors.UnknownSmartMethod(response_tuple[1])
254
        elif response_tuple[0] == 'error':
255
            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.
256
        return response_tuple
257
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
258
    def _check_call(self, method, args):
259
        if self._expected_calls is None:
260
            # the test should be updated to say what it expects
261
            return
262
        try:
263
            next_call = self._expected_calls.pop(0)
264
        except IndexError:
265
            raise AssertionError("%r didn't expect any more calls "
266
                "but got %r%r"
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
267
                % (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.
268
        if next_call is None:
269
            return
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
270
        if method != next_call[0] or args != next_call[1]:
271
            raise AssertionError("%r expected %r%r "
272
                "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
273
                % (self, next_call[0], next_call[1], method, args,))
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
274
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
275
    def call(self, method, *args):
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
276
        self._check_call(method, args)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
277
        self._calls.append(('call', method, args))
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
278
        return self._get_next_response()[1]
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
279
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
280
    def call_expecting_body(self, method, *args):
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
281
        self._check_call(method, args)
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
282
        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.
283
        result = self._get_next_response()
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
284
        self.expecting_body = True
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
285
        return result[1], FakeProtocol(result[2], self)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
286
4634.36.1 by Andrew Bennetts
Fix trivial bug in RemoteBranch._set_tags_bytes, and add some unit tests for it.
287
    def call_with_body_bytes(self, method, args, body):
288
        self._check_call(method, args)
289
        self._calls.append(('call_with_body_bytes', method, args, body))
290
        result = self._get_next_response()
291
        return result[1], FakeProtocol(result[2], self)
292
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.
293
    def call_with_body_bytes_expecting_body(self, method, args, body):
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
294
        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.
295
        self._calls.append(('call_with_body_bytes_expecting_body', method,
296
            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.
297
        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.
298
        self.expecting_body = True
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
299
        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.
300
3842.3.9 by Andrew Bennetts
Backing up the stream so that we can fallback correctly.
301
    def call_with_body_stream(self, args, stream):
302
        # Explicitly consume the stream before checking for an error, because
303
        # that's what happens a real medium.
304
        stream = list(stream)
305
        self._check_call(args[0], args[1:])
306
        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.
307
        result = self._get_next_response()
4144.3.3 by Andrew Bennetts
Tweaks based on review from Robert.
308
        # The second value returned from call_with_body_stream is supposed to
309
        # be a response_handler object, but so far no tests depend on that.
310
        response_handler = None 
311
        return result[1], response_handler
3842.3.9 by Andrew Bennetts
Backing up the stream so that we can fallback correctly.
312
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
313
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
314
class FakeMedium(medium.SmartClientMedium):
3104.4.2 by Andrew Bennetts
All tests passing.
315
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.
316
    def __init__(self, client_calls, base):
3453.4.1 by Andrew Bennetts
Better infrastructure on SmartClientMedium for tracking the remote version.
317
        medium.SmartClientMedium.__init__(self, base)
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
318
        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.
319
320
    def disconnect(self):
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
321
        self._client_calls.append(('disconnect medium',))
3104.4.2 by Andrew Bennetts
All tests passing.
322
323
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.
324
class TestVfsHas(tests.TestCase):
325
326
    def test_unicode_path(self):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
327
        client = FakeClient('/')
328
        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.
329
        transport = RemoteTransport('bzr://localhost/', _client=client)
330
        filename = u'/hell\u00d8'.encode('utf8')
331
        result = transport.has(filename)
332
        self.assertEqual(
333
            [('call', 'has', (filename,))],
334
            client._calls)
335
        self.assertTrue(result)
336
337
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
338
class TestRemote(tests.TestCaseWithMemoryTransport):
4032.1.1 by John Arbash Meinel
Merge the removal of all trailing whitespace, and resolve conflicts.
339
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.
340
    def get_branch_format(self):
341
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
342
        return reference_bzrdir_format.get_branch_format()
343
4053.1.2 by Robert Collins
Actually make this branch work.
344
    def get_repo_format(self):
345
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
346
        return reference_bzrdir_format.repository_format
347
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
348
    def assertFinished(self, fake_client):
349
        """Assert that all of a FakeClient's expected calls have occurred."""
4523.3.2 by Andrew Bennetts
Adjust according to Robert's review.
350
        fake_client.finished_test()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
351
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
352
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
353
class Test_ClientMedium_remote_path_from_transport(tests.TestCase):
354
    """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.
355
356
    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.
357
        """Assert that the result of
358
        SmartClientMedium.remote_path_from_transport is the expected value for
359
        a given client_base and transport_base.
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
360
        """
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
361
        client_medium = medium.SmartClientMedium(client_base)
5273.1.7 by Vincent Ladeuil
No more use of the get_transport imported *symbol*, all uses are through
362
        t = transport.get_transport(transport_base)
363
        result = client_medium.remote_path_from_transport(t)
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
364
        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.
365
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
366
    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.
367
        """SmartClientMedium.remote_path_from_transport calculates a URL for
368
        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.
369
        """
370
        self.assertRemotePath('xyz/', 'bzr://host/path', 'bzr://host/xyz')
371
        self.assertRemotePath(
372
            'path/xyz/', 'bzr://host/path', 'bzr://host/path/xyz')
373
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
374
    def assertRemotePathHTTP(self, expected, transport_base, relpath):
375
        """Assert that the result of
376
        HttpTransportBase.remote_path_from_transport is the expected value for
377
        a given transport_base and relpath of that transport.  (Note that
378
        HttpTransportBase is a subclass of SmartClientMedium)
379
        """
5273.1.7 by Vincent Ladeuil
No more use of the get_transport imported *symbol*, all uses are through
380
        base_transport = 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.
381
        client_medium = base_transport.get_smart_medium()
382
        cloned_transport = base_transport.clone(relpath)
383
        result = client_medium.remote_path_from_transport(cloned_transport)
384
        self.assertEqual(expected, result)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
385
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
386
    def test_remote_path_from_transport_http(self):
387
        """Remote paths for HTTP transports are calculated differently to other
388
        transports.  They are just relative to the client base, not the root
389
        directory of the host.
390
        """
391
        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.
392
            self.assertRemotePathHTTP(
393
                '../xyz/', scheme + '//host/path', '../xyz/')
394
            self.assertRemotePathHTTP(
395
                'xyz/', scheme + '//host/path', 'xyz/')
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
396
397
3453.4.1 by Andrew Bennetts
Better infrastructure on SmartClientMedium for tracking the remote version.
398
class Test_ClientMedium_remote_is_at_least(tests.TestCase):
399
    """Tests for the behaviour of client_medium.remote_is_at_least."""
400
401
    def test_initially_unlimited(self):
402
        """A fresh medium assumes that the remote side supports all
403
        versions.
404
        """
405
        client_medium = medium.SmartClientMedium('dummy base')
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
406
        self.assertFalse(client_medium._is_remote_before((99, 99)))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
407
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
408
    def test__remember_remote_is_before(self):
409
        """Calling _remember_remote_is_before ratchets down the known remote
410
        version.
411
        """
3453.4.1 by Andrew Bennetts
Better infrastructure on SmartClientMedium for tracking the remote version.
412
        client_medium = medium.SmartClientMedium('dummy base')
413
        # Mark the remote side as being less than 1.6.  The remote side may
414
        # still be 1.5.
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
415
        client_medium._remember_remote_is_before((1, 6))
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
416
        self.assertTrue(client_medium._is_remote_before((1, 6)))
417
        self.assertFalse(client_medium._is_remote_before((1, 5)))
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
418
        # Calling _remember_remote_is_before again with a lower value works.
419
        client_medium._remember_remote_is_before((1, 5))
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
420
        self.assertTrue(client_medium._is_remote_before((1, 5)))
4797.49.4 by Andrew Bennetts
Expand test a little further, and use consistent terminology in its comments.
421
        # If you call _remember_remote_is_before with a higher value it logs a
422
        # warning, and continues to remember the lower value.
4797.49.1 by Andrew Bennetts
First, fix _remember_remote_is_before to never raise AssertionError for what is a very minor bug.
423
        self.assertNotContainsRe(self.get_log(), '_remember_remote_is_before')
424
        client_medium._remember_remote_is_before((1, 9))
425
        self.assertContainsRe(self.get_log(), '_remember_remote_is_before')
4797.49.4 by Andrew Bennetts
Expand test a little further, and use consistent terminology in its comments.
426
        self.assertTrue(client_medium._is_remote_before((1, 5)))
3453.4.1 by Andrew Bennetts
Better infrastructure on SmartClientMedium for tracking the remote version.
427
428
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
429
class TestBzrDirCloningMetaDir(TestRemote):
430
431
    def test_backwards_compat(self):
432
        self.setup_smart_server_with_call_log()
433
        a_dir = self.make_bzrdir('.')
434
        self.reset_smart_call_log()
435
        verb = 'BzrDir.cloning_metadir'
436
        self.disable_verb(verb)
437
        format = a_dir.cloning_metadir()
438
        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.
439
            call.call.method == verb])
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
440
        self.assertEqual(1, call_count)
441
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
442
    def test_branch_reference(self):
443
        transport = self.get_transport('quack')
444
        referenced = self.make_branch('referenced')
445
        expected = referenced.bzrdir.cloning_metadir()
446
        client = FakeClient(transport.base)
447
        client.add_expected_call(
448
            'BzrDir.cloning_metadir', ('quack/', 'False'),
449
            'error', ('BranchReference',)),
450
        client.add_expected_call(
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
451
            'BzrDir.open_branchV3', ('quack/',),
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
452
            'success', ('ref', self.get_url('referenced'))),
453
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
454
            _client=client)
455
        result = a_bzrdir.cloning_metadir()
456
        # We should have got a control dir matching the referenced branch.
457
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
458
        self.assertEqual(expected._repository_format, result._repository_format)
459
        self.assertEqual(expected._branch_format, result._branch_format)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
460
        self.assertFinished(client)
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
461
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
462
    def test_current_server(self):
463
        transport = self.get_transport('.')
464
        transport = transport.clone('quack')
465
        self.make_bzrdir('quack')
466
        client = FakeClient(transport.base)
467
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
468
        control_name = reference_bzrdir_format.network_name()
469
        client.add_expected_call(
470
            'BzrDir.cloning_metadir', ('quack/', 'False'),
4084.2.2 by Robert Collins
Review feedback.
471
            'success', (control_name, '', ('branch', ''))),
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
472
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
473
            _client=client)
474
        result = a_bzrdir.cloning_metadir()
475
        # We should have got a reference control dir with default branch and
476
        # repository formats.
477
        # This pokes a little, just to be sure.
478
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
4070.2.8 by Robert Collins
Really test the current BzrDir.cloning_metadir contract.
479
        self.assertEqual(None, result._repository_format)
480
        self.assertEqual(None, result._branch_format)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
481
        self.assertFinished(client)
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
482
483
4634.47.5 by Andrew Bennetts
Add tests, and fix BzrDirMeta1.has_workingtree which was failing if the local transport is decorated with a ChrootTransport or similar.
484
class TestBzrDirOpen(TestRemote):
485
486
    def make_fake_client_and_transport(self, path='quack'):
487
        transport = MemoryTransport()
488
        transport.mkdir(path)
489
        transport = transport.clone(path)
490
        client = FakeClient(transport.base)
491
        return client, transport
492
493
    def test_absent(self):
494
        client, transport = self.make_fake_client_and_transport()
495
        client.add_expected_call(
496
            'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
497
        self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
498
                remote.RemoteBzrDirFormat(), _client=client, _force_probe=True)
499
        self.assertFinished(client)
500
501
    def test_present_without_workingtree(self):
502
        client, transport = self.make_fake_client_and_transport()
503
        client.add_expected_call(
504
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
505
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
506
            _client=client, _force_probe=True)
507
        self.assertIsInstance(bd, RemoteBzrDir)
508
        self.assertFalse(bd.has_workingtree())
509
        self.assertRaises(errors.NoWorkingTree, bd.open_workingtree)
510
        self.assertFinished(client)
511
512
    def test_present_with_workingtree(self):
513
        client, transport = self.make_fake_client_and_transport()
514
        client.add_expected_call(
515
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
516
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
517
            _client=client, _force_probe=True)
518
        self.assertIsInstance(bd, RemoteBzrDir)
519
        self.assertTrue(bd.has_workingtree())
520
        self.assertRaises(errors.NotLocalUrl, bd.open_workingtree)
521
        self.assertFinished(client)
522
523
    def test_backwards_compat(self):
524
        client, transport = self.make_fake_client_and_transport()
525
        client.add_expected_call(
526
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
527
        client.add_expected_call(
528
            'BzrDir.open', ('quack/',), 'success', ('yes',))
529
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
530
            _client=client, _force_probe=True)
531
        self.assertIsInstance(bd, RemoteBzrDir)
532
        self.assertFinished(client)
533
4797.49.2 by Andrew Bennetts
Add test that demonstrates bug #528041.
534
    def test_backwards_compat_hpss_v2(self):
535
        client, transport = self.make_fake_client_and_transport()
536
        # Monkey-patch fake client to simulate real-world behaviour with v2
537
        # server: upon first RPC call detect the protocol version, and because
538
        # the version is 2 also do _remember_remote_is_before((1, 6)) before
539
        # continuing with the RPC.
540
        orig_check_call = client._check_call
541
        def check_call(method, args):
542
            client._medium._protocol_version = 2
543
            client._medium._remember_remote_is_before((1, 6))
544
            client._check_call = orig_check_call
545
            client._check_call(method, args)
546
        client._check_call = check_call
547
        client.add_expected_call(
548
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
549
        client.add_expected_call(
550
            'BzrDir.open', ('quack/',), 'success', ('yes',))
551
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
552
            _client=client, _force_probe=True)
553
        self.assertIsInstance(bd, RemoteBzrDir)
554
        self.assertFinished(client)
555
4634.47.5 by Andrew Bennetts
Add tests, and fix BzrDirMeta1.has_workingtree which was failing if the local transport is decorated with a ChrootTransport or similar.
556
4053.1.2 by Robert Collins
Actually make this branch work.
557
class TestBzrDirOpenBranch(TestRemote):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
558
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.
559
    def test_backwards_compat(self):
560
        self.setup_smart_server_with_call_log()
561
        self.make_branch('.')
562
        a_dir = BzrDir.open(self.get_url('.'))
563
        self.reset_smart_call_log()
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
564
        verb = 'BzrDir.open_branchV3'
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.
565
        self.disable_verb(verb)
566
        format = a_dir.open_branch()
567
        call_count = len([call for call in self.hpss_calls if
568
            call.call.method == verb])
569
        self.assertEqual(1, call_count)
570
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
571
    def test_branch_present(self):
4053.1.2 by Robert Collins
Actually make this branch work.
572
        reference_format = self.get_repo_format()
573
        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.
574
        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.
575
        transport = MemoryTransport()
576
        transport.mkdir('quack')
577
        transport = transport.clone('quack')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
578
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
579
        client.add_expected_call(
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
580
            'BzrDir.open_branchV3', ('quack/',),
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.
581
            'success', ('branch', branch_network_name))
3691.2.10 by Martin Pool
Update more test_remote tests
582
        client.add_expected_call(
4053.1.2 by Robert Collins
Actually make this branch work.
583
            'BzrDir.find_repositoryV3', ('quack/',),
584
            'success', ('ok', '', 'no', 'no', 'no', network_name))
3691.2.10 by Martin Pool
Update more test_remote tests
585
        client.add_expected_call(
586
            'Branch.get_stacked_on_url', ('quack/',),
587
            '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.
588
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
589
            _client=client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
590
        result = bzrdir.open_branch()
591
        self.assertIsInstance(result, RemoteBranch)
592
        self.assertEqual(bzrdir, result.bzrdir)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
593
        self.assertFinished(client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
594
595
    def test_branch_missing(self):
596
        transport = MemoryTransport()
597
        transport.mkdir('quack')
598
        transport = transport.clone('quack')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
599
        client = FakeClient(transport.base)
600
        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.
601
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
602
            _client=client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
603
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
604
        self.assertEqual(
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
605
            [('call', 'BzrDir.open_branchV3', ('quack/',))],
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
606
            client._calls)
607
3211.4.1 by Robert Collins
* ``RemoteBzrDir._get_tree_branch`` no longer triggers ``_ensure_real``,
608
    def test__get_tree_branch(self):
609
        # _get_tree_branch is a form of open_branch, but it should only ask for
610
        # branch opening, not any other network requests.
611
        calls = []
5147.4.1 by Jelmer Vernooij
Pass branch names in more places.
612
        def open_branch(name=None):
3211.4.1 by Robert Collins
* ``RemoteBzrDir._get_tree_branch`` no longer triggers ``_ensure_real``,
613
            calls.append("Called")
614
            return "a-branch"
615
        transport = MemoryTransport()
616
        # 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.
617
        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.
618
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
619
            _client=client)
3211.4.1 by Robert Collins
* ``RemoteBzrDir._get_tree_branch`` no longer triggers ``_ensure_real``,
620
        # patch the open_branch call to record that it was called.
621
        bzrdir.open_branch = open_branch
622
        self.assertEqual((None, "a-branch"), bzrdir._get_tree_branch())
623
        self.assertEqual(["Called"], calls)
624
        self.assertEqual([], client._calls)
625
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.
626
    def test_url_quoting_of_path(self):
627
        # Relpaths on the wire should not be URL-escaped.  So "~" should be
628
        # 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.
629
        transport = RemoteTCPTransport('bzr://localhost/~hello/')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
630
        client = FakeClient(transport.base)
4053.1.2 by Robert Collins
Actually make this branch work.
631
        reference_format = self.get_repo_format()
632
        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.
633
        branch_network_name = self.get_branch_format().network_name()
3691.2.10 by Martin Pool
Update more test_remote tests
634
        client.add_expected_call(
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
635
            'BzrDir.open_branchV3', ('~hello/',),
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.
636
            'success', ('branch', branch_network_name))
3691.2.10 by Martin Pool
Update more test_remote tests
637
        client.add_expected_call(
4053.1.2 by Robert Collins
Actually make this branch work.
638
            'BzrDir.find_repositoryV3', ('~hello/',),
639
            'success', ('ok', '', 'no', 'no', 'no', network_name))
3691.2.10 by Martin Pool
Update more test_remote tests
640
        client.add_expected_call(
641
            'Branch.get_stacked_on_url', ('~hello/',),
642
            '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.
643
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
644
            _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.
645
        result = bzrdir.open_branch()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
646
        self.assertFinished(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.
647
3221.3.3 by Robert Collins
* Hook up the new remote method ``RemoteBzrDir.find_repositoryV2`` so
648
    def check_open_repository(self, rich_root, subtrees, external_lookup='no'):
4053.1.2 by Robert Collins
Actually make this branch work.
649
        reference_format = self.get_repo_format()
650
        network_name = reference_format.network_name()
3104.4.2 by Andrew Bennetts
All tests passing.
651
        transport = MemoryTransport()
652
        transport.mkdir('quack')
653
        transport = transport.clone('quack')
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
654
        if rich_root:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
655
            rich_response = 'yes'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
656
        else:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
657
            rich_response = 'no'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
658
        if subtrees:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
659
            subtree_response = 'yes'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
660
        else:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
661
            subtree_response = 'no'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
662
        client = FakeClient(transport.base)
663
        client.add_success_response(
4053.1.2 by Robert Collins
Actually make this branch work.
664
            'ok', '', rich_response, subtree_response, external_lookup,
665
            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.
666
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
667
            _client=client)
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
668
        result = bzrdir.open_repository()
669
        self.assertEqual(
4053.1.2 by Robert Collins
Actually make this branch work.
670
            [('call', 'BzrDir.find_repositoryV3', ('quack/',))],
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
671
            client._calls)
672
        self.assertIsInstance(result, RemoteRepository)
673
        self.assertEqual(bzrdir, result.bzrdir)
674
        self.assertEqual(rich_root, result._format.rich_root_data)
2018.5.138 by Robert Collins
Merge bzr.dev.
675
        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.
676
677
    def test_open_repository_sets_format_attributes(self):
678
        self.check_open_repository(True, True)
679
        self.check_open_repository(False, True)
680
        self.check_open_repository(True, False)
681
        self.check_open_repository(False, False)
3221.3.3 by Robert Collins
* Hook up the new remote method ``RemoteBzrDir.find_repositoryV2`` so
682
        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.
683
2432.3.2 by Andrew Bennetts
Add test, and tidy implementation.
684
    def test_old_server(self):
685
        """RemoteBzrDirFormat should fail to probe if the server version is too
686
        old.
687
        """
688
        self.assertRaises(errors.NotBranchError,
5363.2.9 by Jelmer Vernooij
Fix some tests.
689
            RemoteBzrProber.probe_transport, OldServerTransport())
2432.3.2 by Andrew Bennetts
Add test, and tidy implementation.
690
691
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
692
class TestBzrDirCreateBranch(TestRemote):
693
694
    def test_backwards_compat(self):
695
        self.setup_smart_server_with_call_log()
696
        repo = self.make_repository('.')
697
        self.reset_smart_call_log()
698
        self.disable_verb('BzrDir.create_branch')
699
        branch = repo.bzrdir.create_branch()
700
        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.
701
            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.
702
        self.assertEqual(1, create_branch_call_count)
703
704
    def test_current_server(self):
705
        transport = self.get_transport('.')
706
        transport = transport.clone('quack')
707
        self.make_repository('quack')
708
        client = FakeClient(transport.base)
709
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
710
        reference_format = reference_bzrdir_format.get_branch_format()
711
        network_name = reference_format.network_name()
712
        reference_repo_fmt = reference_bzrdir_format.repository_format
713
        reference_repo_name = reference_repo_fmt.network_name()
714
        client.add_expected_call(
715
            'BzrDir.create_branch', ('quack/', network_name),
716
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
717
            reference_repo_name))
718
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
719
            _client=client)
720
        branch = a_bzrdir.create_branch()
721
        # We should have got a remote branch
722
        self.assertIsInstance(branch, remote.RemoteBranch)
723
        # its format should have the settings from the response
724
        format = branch._format
725
        self.assertEqual(network_name, format.network_name())
726
5609.21.2 by Andrew Bennetts
Add test.
727
    def test_already_open_repo_and_reused_medium(self):
728
        """Bug 726584: create_branch(..., repository=repo) should work
729
        regardless of what the smart medium's base URL is.
730
        """
731
        self.transport_server = test_server.SmartTCPServer_for_testing
732
        transport = self.get_transport('.')
733
        repo = self.make_repository('quack')
734
        # Client's medium rooted a transport root (not at the bzrdir)
735
        client = FakeClient(transport.base)
736
        transport = transport.clone('quack')
737
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
738
        reference_format = reference_bzrdir_format.get_branch_format()
739
        network_name = reference_format.network_name()
740
        reference_repo_fmt = reference_bzrdir_format.repository_format
741
        reference_repo_name = reference_repo_fmt.network_name()
742
        client.add_expected_call(
743
            'BzrDir.create_branch', ('extra/quack/', network_name),
744
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
745
            reference_repo_name))
746
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
747
            _client=client)
748
        branch = a_bzrdir.create_branch(repository=repo)
749
        # We should have got a remote branch
750
        self.assertIsInstance(branch, remote.RemoteBranch)
751
        # its format should have the settings from the response
752
        format = branch._format
753
        self.assertEqual(network_name, format.network_name())
754
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
755
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
756
class TestBzrDirCreateRepository(TestRemote):
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
757
758
    def test_backwards_compat(self):
759
        self.setup_smart_server_with_call_log()
760
        bzrdir = self.make_bzrdir('.')
761
        self.reset_smart_call_log()
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
762
        self.disable_verb('BzrDir.create_repository')
763
        repo = bzrdir.create_repository()
764
        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.
765
            call.call.method == 'BzrDir.create_repository'])
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
766
        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.
767
768
    def test_current_server(self):
769
        transport = self.get_transport('.')
770
        transport = transport.clone('quack')
771
        self.make_bzrdir('quack')
772
        client = FakeClient(transport.base)
773
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
774
        reference_format = reference_bzrdir_format.repository_format
775
        network_name = reference_format.network_name()
776
        client.add_expected_call(
777
            'BzrDir.create_repository', ('quack/',
4599.4.20 by Robert Collins
Prep test_remote for 2a as default.
778
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
779
                'False'),
780
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
781
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
782
            _client=client)
783
        repo = a_bzrdir.create_repository()
784
        # We should have got a remote repository
785
        self.assertIsInstance(repo, remote.RemoteRepository)
786
        # its format should have the settings from the response
787
        format = repo._format
4599.4.20 by Robert Collins
Prep test_remote for 2a as default.
788
        self.assertTrue(format.rich_root_data)
789
        self.assertTrue(format.supports_tree_reference)
790
        self.assertTrue(format.supports_external_lookups)
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
791
        self.assertEqual(network_name, format.network_name())
792
793
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
794
class TestBzrDirOpenRepository(TestRemote):
795
796
    def test_backwards_compat_1_2_3(self):
797
        # fallback all the way to the first version.
798
        reference_format = self.get_repo_format()
799
        network_name = reference_format.network_name()
4691.2.1 by Robert Collins
Add stronger test isolation by interception BzrDir.open and checking the thing being opened is known to the test suite.
800
        server_url = 'bzr://example.com/'
801
        self.permit_url(server_url)
802
        client = FakeClient(server_url)
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
803
        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.
804
        client.add_unknown_method_response('BzrDir.find_repositoryV2')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
805
        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.
806
        # A real repository instance will be created to determine the network
807
        # name.
808
        client.add_success_response_with_body(
809
            "Bazaar-NG meta directory, format 1\n", 'ok')
810
        client.add_success_response_with_body(
811
            reference_format.get_format_string(), 'ok')
812
        # PackRepository wants to do a stat
813
        client.add_success_response('stat', '0', '65535')
4691.2.1 by Robert Collins
Add stronger test isolation by interception BzrDir.open and checking the thing being opened is known to the test suite.
814
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
815
            _client=client)
816
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
817
            _client=client)
818
        repo = bzrdir.open_repository()
819
        self.assertEqual(
820
            [('call', 'BzrDir.find_repositoryV3', ('quack/',)),
821
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
822
             ('call', 'BzrDir.find_repository', ('quack/',)),
823
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
824
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
825
             ('call', 'stat', ('/quack/.bzr/repository',)),
826
             ],
827
            client._calls)
828
        self.assertEqual(network_name, repo._format.network_name())
829
830
    def test_backwards_compat_2(self):
831
        # fallback to find_repositoryV2
832
        reference_format = self.get_repo_format()
833
        network_name = reference_format.network_name()
4691.2.1 by Robert Collins
Add stronger test isolation by interception BzrDir.open and checking the thing being opened is known to the test suite.
834
        server_url = 'bzr://example.com/'
835
        self.permit_url(server_url)
836
        client = FakeClient(server_url)
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
837
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
838
        client.add_success_response('ok', '', 'no', 'no', 'no')
839
        # A real repository instance will be created to determine the network
840
        # name.
841
        client.add_success_response_with_body(
842
            "Bazaar-NG meta directory, format 1\n", 'ok')
843
        client.add_success_response_with_body(
844
            reference_format.get_format_string(), 'ok')
845
        # PackRepository wants to do a stat
846
        client.add_success_response('stat', '0', '65535')
4691.2.1 by Robert Collins
Add stronger test isolation by interception BzrDir.open and checking the thing being opened is known to the test suite.
847
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
848
            _client=client)
849
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
850
            _client=client)
851
        repo = bzrdir.open_repository()
852
        self.assertEqual(
853
            [('call', 'BzrDir.find_repositoryV3', ('quack/',)),
854
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
855
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
856
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
857
             ('call', 'stat', ('/quack/.bzr/repository',)),
858
             ],
859
            client._calls)
860
        self.assertEqual(network_name, repo._format.network_name())
861
862
    def test_current_server(self):
863
        reference_format = self.get_repo_format()
864
        network_name = reference_format.network_name()
865
        transport = MemoryTransport()
866
        transport.mkdir('quack')
867
        transport = transport.clone('quack')
868
        client = FakeClient(transport.base)
869
        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.
870
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
871
            _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.
872
        repo = bzrdir.open_repository()
873
        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.
874
            [('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.
875
            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.
876
        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.
877
878
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
879
class TestBzrDirFormatInitializeEx(TestRemote):
880
881
    def test_success(self):
882
        """Simple test for typical successful call."""
883
        fmt = bzrdir.RemoteBzrDirFormat()
884
        default_format_name = BzrDirFormat.get_default_format().network_name()
885
        transport = self.get_transport()
886
        client = FakeClient(transport.base)
887
        client.add_expected_call(
4436.1.1 by Andrew Bennetts
Rename BzrDirFormat.initialize_ex verb to BzrDirFormat.initialize_ex_1.16.
888
            'BzrDirFormat.initialize_ex_1.16',
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
889
                (default_format_name, 'path', 'False', 'False', 'False', '',
890
                 '', '', '', 'False'),
891
            'success',
892
                ('.', 'no', 'no', 'yes', 'repo fmt', 'repo bzrdir fmt',
893
                 'bzrdir fmt', 'False', '', '', 'repo lock token'))
894
        # XXX: It would be better to call fmt.initialize_on_transport_ex, but
895
        # it's currently hard to test that without supplying a real remote
896
        # transport connected to a real server.
897
        result = fmt._initialize_on_transport_ex_rpc(client, 'path',
898
            transport, False, False, False, None, None, None, None, False)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
899
        self.assertFinished(client)
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
900
901
    def test_error(self):
902
        """Error responses are translated, e.g. 'PermissionDenied' raises the
903
        corresponding error from the client.
904
        """
905
        fmt = bzrdir.RemoteBzrDirFormat()
906
        default_format_name = BzrDirFormat.get_default_format().network_name()
907
        transport = self.get_transport()
908
        client = FakeClient(transport.base)
909
        client.add_expected_call(
4436.1.1 by Andrew Bennetts
Rename BzrDirFormat.initialize_ex verb to BzrDirFormat.initialize_ex_1.16.
910
            'BzrDirFormat.initialize_ex_1.16',
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
911
                (default_format_name, 'path', 'False', 'False', 'False', '',
912
                 '', '', '', 'False'),
913
            'error',
914
                ('PermissionDenied', 'path', 'extra info'))
915
        # XXX: It would be better to call fmt.initialize_on_transport_ex, but
916
        # it's currently hard to test that without supplying a real remote
917
        # transport connected to a real server.
918
        err = self.assertRaises(errors.PermissionDenied,
919
            fmt._initialize_on_transport_ex_rpc, client, 'path', transport,
920
            False, False, False, None, None, None, None, False)
921
        self.assertEqual('path', err.path)
922
        self.assertEqual(': extra info', err.extra)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
923
        self.assertFinished(client)
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
924
4384.1.3 by Andrew Bennetts
Add test suggested by John.
925
    def test_error_from_real_server(self):
926
        """Integration test for error translation."""
927
        transport = self.make_smart_server('foo')
928
        transport = transport.clone('no-such-path')
929
        fmt = bzrdir.RemoteBzrDirFormat()
930
        err = self.assertRaises(errors.NoSuchFile,
931
            fmt.initialize_on_transport_ex, transport, create_prefix=False)
932
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
933
2432.3.2 by Andrew Bennetts
Add test, and tidy implementation.
934
class OldSmartClient(object):
935
    """A fake smart client for test_old_version that just returns a version one
936
    response to the 'hello' (query version) command.
937
    """
938
939
    def get_request(self):
940
        input_file = StringIO('ok\x011\n')
941
        output_file = StringIO()
942
        client_medium = medium.SmartSimplePipesClientMedium(
943
            input_file, output_file)
944
        return medium.SmartClientStreamMediumRequest(client_medium)
945
3241.1.1 by Andrew Bennetts
Shift protocol version querying from RemoteBzrDirFormat into SmartClientMedium.
946
    def protocol_version(self):
947
        return 1
948
2432.3.2 by Andrew Bennetts
Add test, and tidy implementation.
949
950
class OldServerTransport(object):
951
    """A fake transport for test_old_server that reports it's smart server
952
    protocol version as version one.
953
    """
954
955
    def __init__(self):
956
        self.base = 'fake:'
957
958
    def get_smart_client(self):
959
        return OldSmartClient()
960
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
961
4288.1.1 by Robert Collins
Add support for a RemoteBzrDirConfig to support optimising push operations which need to look for default stacking locations.
962
class RemoteBzrDirTestCase(TestRemote):
963
964
    def make_remote_bzrdir(self, transport, client):
965
        """Make a RemotebzrDir using 'client' as the _client."""
966
        return RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
967
            _client=client)
968
969
970
class RemoteBranchTestCase(RemoteBzrDirTestCase):
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
971
4634.36.1 by Andrew Bennetts
Fix trivial bug in RemoteBranch._set_tags_bytes, and add some unit tests for it.
972
    def lock_remote_branch(self, branch):
973
        """Trick a RemoteBranch into thinking it is locked."""
974
        branch._lock_mode = 'w'
975
        branch._lock_count = 2
976
        branch._lock_token = 'branch token'
977
        branch._repo_lock_token = 'repo token'
978
        branch.repository._lock_mode = 'w'
979
        branch.repository._lock_count = 2
980
        branch.repository._lock_token = 'repo token'
981
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
982
    def make_remote_branch(self, transport, client):
983
        """Make a RemoteBranch using 'client' as its _SmartClient.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
984
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
985
        A RemoteBzrDir and RemoteRepository will also be created to fill out
986
        the RemoteBranch, albeit with stub values for some of their attributes.
987
        """
988
        # we do not want bzrdir to make any remote calls, so use False as its
989
        # _client.  If it tries to make a remote call, this will fail
990
        # immediately.
4288.1.1 by Robert Collins
Add support for a RemoteBzrDirConfig to support optimising push operations which need to look for default stacking locations.
991
        bzrdir = self.make_remote_bzrdir(transport, False)
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
992
        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.
993
        branch_format = self.get_branch_format()
994
        format = RemoteBranchFormat(network_name=branch_format.network_name())
995
        return RemoteBranch(bzrdir, repo, _client=client, format=format)
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
996
997
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
998
class TestBranchGetParent(RemoteBranchTestCase):
999
1000
    def test_no_parent(self):
1001
        # in an empty branch we decode the response properly
1002
        transport = MemoryTransport()
1003
        client = FakeClient(transport.base)
1004
        client.add_expected_call(
1005
            'Branch.get_stacked_on_url', ('quack/',),
1006
            'error', ('NotStacked',))
1007
        client.add_expected_call(
1008
            'Branch.get_parent', ('quack/',),
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
1009
            'success', ('',))
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1010
        transport.mkdir('quack')
1011
        transport = transport.clone('quack')
1012
        branch = self.make_remote_branch(transport, client)
1013
        result = branch.get_parent()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1014
        self.assertFinished(client)
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1015
        self.assertEqual(None, result)
1016
1017
    def test_parent_relative(self):
1018
        transport = MemoryTransport()
1019
        client = FakeClient(transport.base)
1020
        client.add_expected_call(
1021
            'Branch.get_stacked_on_url', ('kwaak/',),
1022
            'error', ('NotStacked',))
1023
        client.add_expected_call(
1024
            'Branch.get_parent', ('kwaak/',),
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
1025
            'success', ('../foo/',))
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1026
        transport.mkdir('kwaak')
1027
        transport = transport.clone('kwaak')
1028
        branch = self.make_remote_branch(transport, client)
1029
        result = branch.get_parent()
1030
        self.assertEqual(transport.clone('../foo').base, result)
1031
1032
    def test_parent_absolute(self):
1033
        transport = MemoryTransport()
1034
        client = FakeClient(transport.base)
1035
        client.add_expected_call(
1036
            'Branch.get_stacked_on_url', ('kwaak/',),
1037
            'error', ('NotStacked',))
1038
        client.add_expected_call(
1039
            'Branch.get_parent', ('kwaak/',),
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
1040
            'success', ('http://foo/',))
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1041
        transport.mkdir('kwaak')
1042
        transport = transport.clone('kwaak')
1043
        branch = self.make_remote_branch(transport, client)
1044
        result = branch.get_parent()
1045
        self.assertEqual('http://foo/', result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1046
        self.assertFinished(client)
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
1047
1048
1049
class TestBranchSetParentLocation(RemoteBranchTestCase):
1050
1051
    def test_no_parent(self):
1052
        # We call the verb when setting parent to None
1053
        transport = MemoryTransport()
1054
        client = FakeClient(transport.base)
1055
        client.add_expected_call(
1056
            'Branch.get_stacked_on_url', ('quack/',),
1057
            'error', ('NotStacked',))
1058
        client.add_expected_call(
1059
            'Branch.set_parent_location', ('quack/', 'b', 'r', ''),
1060
            'success', ())
1061
        transport.mkdir('quack')
1062
        transport = transport.clone('quack')
1063
        branch = self.make_remote_branch(transport, client)
1064
        branch._lock_token = 'b'
1065
        branch._repo_lock_token = 'r'
1066
        branch._set_parent_location(None)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1067
        self.assertFinished(client)
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
1068
1069
    def test_parent(self):
1070
        transport = MemoryTransport()
1071
        client = FakeClient(transport.base)
1072
        client.add_expected_call(
1073
            'Branch.get_stacked_on_url', ('kwaak/',),
1074
            'error', ('NotStacked',))
1075
        client.add_expected_call(
1076
            'Branch.set_parent_location', ('kwaak/', 'b', 'r', 'foo'),
1077
            'success', ())
1078
        transport.mkdir('kwaak')
1079
        transport = transport.clone('kwaak')
1080
        branch = self.make_remote_branch(transport, client)
1081
        branch._lock_token = 'b'
1082
        branch._repo_lock_token = 'r'
1083
        branch._set_parent_location('foo')
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1084
        self.assertFinished(client)
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
1085
1086
    def test_backwards_compat(self):
1087
        self.setup_smart_server_with_call_log()
1088
        branch = self.make_branch('.')
1089
        self.reset_smart_call_log()
1090
        verb = 'Branch.set_parent_location'
1091
        self.disable_verb(verb)
1092
        branch.set_parent('http://foo/')
1093
        self.assertLength(12, self.hpss_calls)
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1094
1095
4084.2.1 by Robert Collins
Make accessing a branch.tags.get_tag_dict use a smart[er] method rather than VFS calls and real objects.
1096
class TestBranchGetTagsBytes(RemoteBranchTestCase):
1097
1098
    def test_backwards_compat(self):
1099
        self.setup_smart_server_with_call_log()
1100
        branch = self.make_branch('.')
1101
        self.reset_smart_call_log()
1102
        verb = 'Branch.get_tags_bytes'
1103
        self.disable_verb(verb)
1104
        branch.tags.get_tag_dict()
1105
        call_count = len([call for call in self.hpss_calls if
1106
            call.call.method == verb])
1107
        self.assertEqual(1, call_count)
1108
1109
    def test_trivial(self):
1110
        transport = MemoryTransport()
1111
        client = FakeClient(transport.base)
1112
        client.add_expected_call(
1113
            'Branch.get_stacked_on_url', ('quack/',),
1114
            'error', ('NotStacked',))
1115
        client.add_expected_call(
1116
            'Branch.get_tags_bytes', ('quack/',),
1117
            'success', ('',))
1118
        transport.mkdir('quack')
1119
        transport = transport.clone('quack')
1120
        branch = self.make_remote_branch(transport, client)
1121
        result = branch.tags.get_tag_dict()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1122
        self.assertFinished(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.
1123
        self.assertEqual({}, result)
1124
1125
4634.36.1 by Andrew Bennetts
Fix trivial bug in RemoteBranch._set_tags_bytes, and add some unit tests for it.
1126
class TestBranchSetTagsBytes(RemoteBranchTestCase):
1127
1128
    def test_trivial(self):
1129
        transport = MemoryTransport()
1130
        client = FakeClient(transport.base)
1131
        client.add_expected_call(
1132
            'Branch.get_stacked_on_url', ('quack/',),
1133
            'error', ('NotStacked',))
1134
        client.add_expected_call(
1135
            'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1136
            'success', ('',))
1137
        transport.mkdir('quack')
1138
        transport = transport.clone('quack')
1139
        branch = self.make_remote_branch(transport, client)
1140
        self.lock_remote_branch(branch)
1141
        branch._set_tags_bytes('tags bytes')
1142
        self.assertFinished(client)
1143
        self.assertEqual('tags bytes', client._calls[-1][-1])
1144
1145
    def test_backwards_compatible(self):
1146
        transport = MemoryTransport()
1147
        client = FakeClient(transport.base)
1148
        client.add_expected_call(
1149
            'Branch.get_stacked_on_url', ('quack/',),
1150
            'error', ('NotStacked',))
1151
        client.add_expected_call(
1152
            'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1153
            'unknown', ('Branch.set_tags_bytes',))
1154
        transport.mkdir('quack')
1155
        transport = transport.clone('quack')
1156
        branch = self.make_remote_branch(transport, client)
1157
        self.lock_remote_branch(branch)
1158
        class StubRealBranch(object):
1159
            def __init__(self):
1160
                self.calls = []
1161
            def _set_tags_bytes(self, bytes):
1162
                self.calls.append(('set_tags_bytes', bytes))
1163
        real_branch = StubRealBranch()
1164
        branch._real_branch = real_branch
1165
        branch._set_tags_bytes('tags bytes')
1166
        # Call a second time, to exercise the 'remote version already inferred'
1167
        # code path.
1168
        branch._set_tags_bytes('tags bytes')
1169
        self.assertFinished(client)
1170
        self.assertEqual(
1171
            [('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1172
1173
5672.1.5 by Andrew Bennetts
Add some tests for RemoteBranch.heads_to_fetch, and add release-note.
1174
class TestBranchHeadsToFetch(RemoteBranchTestCase):
1175
1176
    def test_uses_last_revision_info_and_tags_by_default(self):
1177
        transport = MemoryTransport()
1178
        client = FakeClient(transport.base)
1179
        client.add_expected_call(
1180
            'Branch.get_stacked_on_url', ('quack/',),
1181
            'error', ('NotStacked',))
1182
        client.add_expected_call(
1183
            'Branch.last_revision_info', ('quack/',),
1184
            'success', ('ok', '1', 'rev-tip'))
1185
        # XXX: this will break if the default format's serialization of tags
1186
        # changes, or if the RPC for fetching tags changes from get_tags_bytes.
1187
        client.add_expected_call(
1188
            'Branch.get_tags_bytes', ('quack/',),
1189
            'success', ('d5:tag-17:rev-foo5:tag-27:rev-bare',))
1190
        transport.mkdir('quack')
1191
        transport = transport.clone('quack')
1192
        branch = self.make_remote_branch(transport, client)
1193
        result = branch.heads_to_fetch()
1194
        self.assertFinished(client)
1195
        self.assertEqual(
1196
            (set(['rev-tip']), set(['rev-foo', 'rev-bar'])), result)
1197
1198
    def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
1199
        transport = MemoryTransport()
1200
        client = FakeClient(transport.base)
1201
        client.add_expected_call(
1202
            'Branch.get_stacked_on_url', ('quack/',),
1203
            'error', ('NotStacked',))
1204
        client.add_expected_call(
1205
            'Branch.heads_to_fetch', ('quack/',),
5672.1.6 by Andrew Bennetts
Add another test.
1206
            'success', (['tip'], ['tagged-1', 'tagged-2']))
5672.1.5 by Andrew Bennetts
Add some tests for RemoteBranch.heads_to_fetch, and add release-note.
1207
        transport.mkdir('quack')
1208
        transport = transport.clone('quack')
1209
        branch = self.make_remote_branch(transport, client)
5672.1.7 by Andrew Bennetts
Use a more explicit method name.
1210
        branch._format._use_default_local_heads_to_fetch = lambda: False
5672.1.5 by Andrew Bennetts
Add some tests for RemoteBranch.heads_to_fetch, and add release-note.
1211
        result = branch.heads_to_fetch()
1212
        self.assertFinished(client)
5672.1.6 by Andrew Bennetts
Add another test.
1213
        self.assertEqual((set(['tip']), set(['tagged-1', 'tagged-2'])), result)
1214
1215
    def test_backwards_compatible(self):
1216
        self.setup_smart_server_with_call_log()
1217
        # Make a branch with a single revision.
1218
        builder = self.make_branch_builder('foo')
1219
        builder.start_series()
1220
        builder.build_snapshot('tip', None, [
1221
            ('add', ('', 'root-id', 'directory', ''))])
1222
        builder.finish_series()
1223
        branch = builder.get_branch()
1224
        # Add two tags to that branch
1225
        branch.tags.set_tag('tag-1', 'rev-1')
1226
        branch.tags.set_tag('tag-2', 'rev-2')
1227
        self.addCleanup(branch.lock_read().unlock)
1228
        # Disable the heads_to_fetch verb
1229
        verb = 'Branch.heads_to_fetch'
1230
        self.disable_verb(verb)
1231
        self.reset_smart_call_log()
1232
        result = branch.heads_to_fetch()
1233
        self.assertEqual((set(['tip']), set(['rev-1', 'rev-2'])), result)
1234
        self.assertEqual(
1235
            ['Branch.last_revision_info', 'Branch.get_tags_bytes'],
1236
            [call.call.method for call in self.hpss_calls])
5672.1.5 by Andrew Bennetts
Add some tests for RemoteBranch.heads_to_fetch, and add release-note.
1237
1238
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1239
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1240
1241
    def test_empty_branch(self):
1242
        # in an empty branch we decode the response properly
1243
        transport = MemoryTransport()
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1244
        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
1245
        client.add_expected_call(
1246
            'Branch.get_stacked_on_url', ('quack/',),
1247
            'error', ('NotStacked',))
1248
        client.add_expected_call(
1249
            'Branch.last_revision_info', ('quack/',),
1250
            'success', ('ok', '0', 'null:'))
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1251
        transport.mkdir('quack')
1252
        transport = transport.clone('quack')
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1253
        branch = self.make_remote_branch(transport, client)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1254
        result = branch.last_revision_info()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1255
        self.assertFinished(client)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1256
        self.assertEqual((0, NULL_REVISION), result)
1257
1258
    def test_non_empty_branch(self):
1259
        # 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.
1260
        revid = u'\xc8'.encode('utf8')
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1261
        transport = MemoryTransport()
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1262
        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
1263
        client.add_expected_call(
1264
            'Branch.get_stacked_on_url', ('kwaak/',),
1265
            'error', ('NotStacked',))
1266
        client.add_expected_call(
1267
            'Branch.last_revision_info', ('kwaak/',),
1268
            'success', ('ok', '2', revid))
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1269
        transport.mkdir('kwaak')
1270
        transport = transport.clone('kwaak')
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1271
        branch = self.make_remote_branch(transport, client)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1272
        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.
1273
        self.assertEqual((2, revid), result)
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1274
1275
4053.1.2 by Robert Collins
Actually make this branch work.
1276
class TestBranch_get_stacked_on_url(TestRemote):
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
1277
    """Test Branch._get_stacked_on_url rpc"""
1278
3691.2.10 by Martin Pool
Update more test_remote tests
1279
    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.
1280
        # test that asking for a stacked on url the server can't access works.
1281
        # This isn't perfect, but then as we're in the same process there
1282
        # really isn't anything we can do to be 100% sure that the server
1283
        # doesn't just open in - this test probably needs to be rewritten using
1284
        # a spawn()ed server.
1285
        stacked_branch = self.make_branch('stacked', format='1.9')
1286
        memory_branch = self.make_branch('base', format='1.9')
1287
        vfs_url = self.get_vfs_only_url('base')
1288
        stacked_branch.set_stacked_on_url(vfs_url)
1289
        transport = stacked_branch.bzrdir.root_transport
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
1290
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1291
        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.
1292
            'Branch.get_stacked_on_url', ('stacked/',),
1293
            'success', ('ok', vfs_url))
1294
        # XXX: Multiple calls are bad, this second call documents what is
1295
        # today.
1296
        client.add_expected_call(
1297
            'Branch.get_stacked_on_url', ('stacked/',),
1298
            'success', ('ok', vfs_url))
1299
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1300
            _client=client)
4118.1.5 by Andrew Bennetts
Fix test_remote tests.
1301
        repo_fmt = remote.RemoteRepositoryFormat()
1302
        repo_fmt._custom_format = stacked_branch.repository._format
1303
        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.
1304
            _client=client)
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
1305
        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.
1306
        self.assertEqual(vfs_url, result)
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
1307
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
1308
    def test_backwards_compatible(self):
1309
        # like with bzr1.6 with no Branch.get_stacked_on_url rpc
1310
        base_branch = self.make_branch('base', format='1.6')
1311
        stacked_branch = self.make_branch('stacked', format='1.6')
1312
        stacked_branch.set_stacked_on_url('../base')
1313
        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.
1314
        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
1315
        client.add_expected_call(
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
1316
            'BzrDir.open_branchV3', ('stacked/',),
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.
1317
            'success', ('branch', branch_network_name))
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
1318
        client.add_expected_call(
4053.1.2 by Robert Collins
Actually make this branch work.
1319
            'BzrDir.find_repositoryV3', ('stacked/',),
4118.1.5 by Andrew Bennetts
Fix test_remote tests.
1320
            'success', ('ok', '', 'no', 'no', 'yes',
4053.1.2 by Robert Collins
Actually make this branch work.
1321
                stacked_branch.repository._format.network_name()))
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
1322
        # called twice, once from constructor and then again by us
1323
        client.add_expected_call(
1324
            'Branch.get_stacked_on_url', ('stacked/',),
1325
            'unknown', ('Branch.get_stacked_on_url',))
1326
        client.add_expected_call(
1327
            'Branch.get_stacked_on_url', ('stacked/',),
1328
            'unknown', ('Branch.get_stacked_on_url',))
1329
        # this will also do vfs access, but that goes direct to the transport
1330
        # 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.
1331
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1332
            remote.RemoteBzrDirFormat(), _client=client)
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
1333
        branch = bzrdir.open_branch()
1334
        result = branch.get_stacked_on_url()
1335
        self.assertEqual('../base', result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1336
        self.assertFinished(client)
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
1337
        # it's in the fallback list both for the RemoteRepository and its vfs
1338
        # repository
1339
        self.assertEqual(1, len(branch.repository._fallback_repositories))
1340
        self.assertEqual(1,
1341
            len(branch.repository._real_repository._fallback_repositories))
1342
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1343
    def test_get_stacked_on_real_branch(self):
5158.4.3 by Andrew Bennetts
Fix test_remote tests that accidentally assumed it was ok to stack mismatched formats.
1344
        base_branch = self.make_branch('base')
1345
        stacked_branch = self.make_branch('stacked')
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1346
        stacked_branch.set_stacked_on_url('../base')
4053.1.2 by Robert Collins
Actually make this branch work.
1347
        reference_format = self.get_repo_format()
1348
        network_name = reference_format.network_name()
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1349
        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.
1350
        branch_network_name = self.get_branch_format().network_name()
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1351
        client.add_expected_call(
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
1352
            'BzrDir.open_branchV3', ('stacked/',),
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.
1353
            'success', ('branch', branch_network_name))
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1354
        client.add_expected_call(
4053.1.2 by Robert Collins
Actually make this branch work.
1355
            'BzrDir.find_repositoryV3', ('stacked/',),
5158.4.3 by Andrew Bennetts
Fix test_remote tests that accidentally assumed it was ok to stack mismatched formats.
1356
            'success', ('ok', '', 'yes', 'no', 'yes', network_name))
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1357
        # called twice, once from constructor and then again by us
1358
        client.add_expected_call(
1359
            'Branch.get_stacked_on_url', ('stacked/',),
1360
            'success', ('ok', '../base'))
1361
        client.add_expected_call(
1362
            'Branch.get_stacked_on_url', ('stacked/',),
1363
            '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.
1364
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1365
            remote.RemoteBzrDirFormat(), _client=client)
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1366
        branch = bzrdir.open_branch()
1367
        result = branch.get_stacked_on_url()
1368
        self.assertEqual('../base', result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1369
        self.assertFinished(client)
4226.1.2 by Robert Collins
Fix test_remote failing because of less _real_repository objects.
1370
        # it's in the fallback list both for the RemoteRepository.
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1371
        self.assertEqual(1, len(branch.repository._fallback_repositories))
4226.1.2 by Robert Collins
Fix test_remote failing because of less _real_repository objects.
1372
        # And we haven't had to construct a real repository.
1373
        self.assertEqual(None, branch.repository._real_repository)
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1374
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
1375
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1376
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.
1377
1378
    def test_set_empty(self):
1379
        # set_revision_history([]) is translated to calling
1380
        # Branch.set_last_revision(path, '') on the wire.
3104.4.2 by Andrew Bennetts
All tests passing.
1381
        transport = MemoryTransport()
1382
        transport.mkdir('branch')
1383
        transport = transport.clone('branch')
1384
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1385
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1386
        client.add_expected_call(
1387
            'Branch.get_stacked_on_url', ('branch/',),
1388
            'error', ('NotStacked',))
1389
        client.add_expected_call(
1390
            'Branch.lock_write', ('branch/', '', ''),
1391
            'success', ('ok', 'branch token', 'repo token'))
1392
        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.
1393
            'Branch.last_revision_info',
1394
            ('branch/',),
1395
            'success', ('ok', '0', 'null:'))
1396
        client.add_expected_call(
3691.2.10 by Martin Pool
Update more test_remote tests
1397
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'null:',),
1398
            'success', ('ok',))
1399
        client.add_expected_call(
1400
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1401
            'success', ('ok',))
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1402
        branch = self.make_remote_branch(transport, client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1403
        # This is a hack to work around the problem that RemoteBranch currently
1404
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1405
        branch._ensure_real = lambda: None
1406
        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.
1407
        result = branch.set_revision_history([])
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1408
        branch.unlock()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1409
        self.assertEqual(None, result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1410
        self.assertFinished(client)
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1411
1412
    def test_set_nonempty(self):
1413
        # set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
1414
        # Branch.set_last_revision(path, rev-idN) on the wire.
3104.4.2 by Andrew Bennetts
All tests passing.
1415
        transport = MemoryTransport()
1416
        transport.mkdir('branch')
1417
        transport = transport.clone('branch')
1418
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1419
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1420
        client.add_expected_call(
1421
            'Branch.get_stacked_on_url', ('branch/',),
1422
            'error', ('NotStacked',))
1423
        client.add_expected_call(
1424
            'Branch.lock_write', ('branch/', '', ''),
1425
            'success', ('ok', 'branch token', 'repo token'))
1426
        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.
1427
            'Branch.last_revision_info',
1428
            ('branch/',),
1429
            'success', ('ok', '0', 'null:'))
1430
        lines = ['rev-id2']
1431
        encoded_body = bz2.compress('\n'.join(lines))
1432
        client.add_success_response_with_body(encoded_body, 'ok')
1433
        client.add_expected_call(
3691.2.10 by Martin Pool
Update more test_remote tests
1434
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id2',),
1435
            'success', ('ok',))
1436
        client.add_expected_call(
1437
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1438
            'success', ('ok',))
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1439
        branch = self.make_remote_branch(transport, client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1440
        # This is a hack to work around the problem that RemoteBranch currently
1441
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1442
        branch._ensure_real = lambda: None
1443
        # Lock the branch, reset the record of remote calls.
1444
        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.
1445
        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.
1446
        branch.unlock()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1447
        self.assertEqual(None, result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1448
        self.assertFinished(client)
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1449
1450
    def test_no_such_revision(self):
1451
        transport = MemoryTransport()
1452
        transport.mkdir('branch')
1453
        transport = transport.clone('branch')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1454
        # A response of 'NoSuchRevision' is translated into an exception.
1455
        client = FakeClient(transport.base)
3691.2.9 by Martin Pool
Convert and update more test_remote tests
1456
        client.add_expected_call(
1457
            'Branch.get_stacked_on_url', ('branch/',),
1458
            'error', ('NotStacked',))
1459
        client.add_expected_call(
1460
            'Branch.lock_write', ('branch/', '', ''),
1461
            'success', ('ok', 'branch token', 'repo token'))
1462
        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.
1463
            'Branch.last_revision_info',
1464
            ('branch/',),
1465
            'success', ('ok', '0', 'null:'))
1466
        # get_graph calls to construct the revision history, for the set_rh
1467
        # hook
1468
        lines = ['rev-id']
1469
        encoded_body = bz2.compress('\n'.join(lines))
1470
        client.add_success_response_with_body(encoded_body, 'ok')
1471
        client.add_expected_call(
3691.2.9 by Martin Pool
Convert and update more test_remote tests
1472
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
1473
            'error', ('NoSuchRevision', 'rev-id'))
1474
        client.add_expected_call(
1475
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1476
            'success', ('ok',))
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1477
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1478
        branch = self.make_remote_branch(transport, client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1479
        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.
1480
        self.assertRaises(
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
1481
            errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1482
        branch.unlock()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1483
        self.assertFinished(client)
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1484
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1485
    def test_tip_change_rejected(self):
1486
        """TipChangeRejected responses cause a TipChangeRejected exception to
1487
        be raised.
1488
        """
1489
        transport = MemoryTransport()
1490
        transport.mkdir('branch')
1491
        transport = transport.clone('branch')
1492
        client = FakeClient(transport.base)
1493
        rejection_msg_unicode = u'rejection message\N{INTERROBANG}'
1494
        rejection_msg_utf8 = rejection_msg_unicode.encode('utf8')
3691.2.10 by Martin Pool
Update more test_remote tests
1495
        client.add_expected_call(
1496
            'Branch.get_stacked_on_url', ('branch/',),
1497
            'error', ('NotStacked',))
1498
        client.add_expected_call(
1499
            'Branch.lock_write', ('branch/', '', ''),
1500
            'success', ('ok', 'branch token', 'repo token'))
1501
        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.
1502
            'Branch.last_revision_info',
1503
            ('branch/',),
1504
            'success', ('ok', '0', 'null:'))
1505
        lines = ['rev-id']
1506
        encoded_body = bz2.compress('\n'.join(lines))
1507
        client.add_success_response_with_body(encoded_body, 'ok')
1508
        client.add_expected_call(
3691.2.10 by Martin Pool
Update more test_remote tests
1509
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
1510
            'error', ('TipChangeRejected', rejection_msg_utf8))
1511
        client.add_expected_call(
1512
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1513
            'success', ('ok',))
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1514
        branch = self.make_remote_branch(transport, client)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1515
        branch._ensure_real = lambda: None
1516
        branch.lock_write()
1517
        # The 'TipChangeRejected' error response triggered by calling
1518
        # set_revision_history causes a TipChangeRejected exception.
1519
        err = self.assertRaises(
1520
            errors.TipChangeRejected, branch.set_revision_history, ['rev-id'])
1521
        # The UTF-8 message from the response has been decoded into a unicode
1522
        # object.
1523
        self.assertIsInstance(err.msg, unicode)
1524
        self.assertEqual(rejection_msg_unicode, err.msg)
3691.2.10 by Martin Pool
Update more test_remote tests
1525
        branch.unlock()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1526
        self.assertFinished(client)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1527
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1528
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1529
class TestBranchSetLastRevisionInfo(RemoteBranchTestCase):
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1530
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1531
    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.
1532
        # set_last_revision_info(num, 'rev-id') is translated to calling
1533
        # 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'.
1534
        transport = MemoryTransport()
1535
        transport.mkdir('branch')
1536
        transport = transport.clone('branch')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1537
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1538
        # get_stacked_on_url
1539
        client.add_error_response('NotStacked')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1540
        # lock_write
1541
        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.
1542
        # query the current revision
1543
        client.add_success_response('ok', '0', 'null:')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1544
        # set_last_revision
1545
        client.add_success_response('ok')
1546
        # unlock
1547
        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.
1548
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1549
        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.
1550
        # Lock the branch, reset the record of remote calls.
1551
        branch.lock_write()
1552
        client._calls = []
1553
        result = branch.set_last_revision_info(1234, 'a-revision-id')
1554
        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.
1555
            [('call', 'Branch.last_revision_info', ('branch/',)),
1556
             ('call', 'Branch.set_last_revision_info',
3297.4.1 by Andrew Bennetts
Merge 'Add Branch.set_last_revision_info smart method'.
1557
                ('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.
1558
                 '1234', 'a-revision-id'))],
1559
            client._calls)
1560
        self.assertEqual(None, result)
1561
1562
    def test_no_such_revision(self):
1563
        # A response of 'NoSuchRevision' is translated into an exception.
1564
        transport = MemoryTransport()
1565
        transport.mkdir('branch')
1566
        transport = transport.clone('branch')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1567
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1568
        # get_stacked_on_url
1569
        client.add_error_response('NotStacked')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1570
        # lock_write
1571
        client.add_success_response('ok', 'branch token', 'repo token')
1572
        # set_last_revision
1573
        client.add_error_response('NoSuchRevision', 'revid')
1574
        # unlock
1575
        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.
1576
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1577
        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.
1578
        # Lock the branch, reset the record of remote calls.
1579
        branch.lock_write()
1580
        client._calls = []
1581
1582
        self.assertRaises(
1583
            errors.NoSuchRevision, branch.set_last_revision_info, 123, 'revid')
1584
        branch.unlock()
1585
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1586
    def test_backwards_compatibility(self):
1587
        """If the server does not support the Branch.set_last_revision_info
1588
        verb (which is new in 1.4), then the client falls back to VFS methods.
1589
        """
1590
        # This test is a little messy.  Unlike most tests in this file, it
1591
        # doesn't purely test what a Remote* object sends over the wire, and
1592
        # how it reacts to responses from the wire.  It instead relies partly
1593
        # on asserting that the RemoteBranch will call
1594
        # self._real_branch.set_last_revision_info(...).
1595
1596
        # First, set up our RemoteBranch with a FakeClient that raises
1597
        # UnknownSmartMethod, and a StubRealBranch that logs how it is called.
1598
        transport = MemoryTransport()
1599
        transport.mkdir('branch')
1600
        transport = transport.clone('branch')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1601
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1602
        client.add_expected_call(
1603
            'Branch.get_stacked_on_url', ('branch/',),
1604
            'error', ('NotStacked',))
1605
        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.
1606
            'Branch.last_revision_info',
1607
            ('branch/',),
1608
            'success', ('ok', '0', 'null:'))
1609
        client.add_expected_call(
3691.2.10 by Martin Pool
Update more test_remote tests
1610
            'Branch.set_last_revision_info',
1611
            ('branch/', 'branch token', 'repo token', '1234', 'a-revision-id',),
1612
            'unknown', 'Branch.set_last_revision_info')
1613
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1614
        branch = self.make_remote_branch(transport, client)
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1615
        class StubRealBranch(object):
1616
            def __init__(self):
1617
                self.calls = []
1618
            def set_last_revision_info(self, revno, revision_id):
1619
                self.calls.append(
1620
                    ('set_last_revision_info', revno, revision_id))
3441.5.5 by Andrew Bennetts
Some small tweaks and comments.
1621
            def _clear_cached_state(self):
1622
                pass
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1623
        real_branch = StubRealBranch()
1624
        branch._real_branch = real_branch
1625
        self.lock_remote_branch(branch)
1626
1627
        # Call set_last_revision_info, and verify it behaved as expected.
1628
        result = branch.set_last_revision_info(1234, 'a-revision-id')
1629
        self.assertEqual(
1630
            [('set_last_revision_info', 1234, 'a-revision-id')],
1631
            real_branch.calls)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1632
        self.assertFinished(client)
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1633
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1634
    def test_unexpected_error(self):
3697.2.6 by Martin Pool
Merge 261315 fix into 1.7 branch
1635
        # If the server sends an error the client doesn't understand, it gets
1636
        # turned into an UnknownErrorFromSmartServer, which is presented as a
1637
        # non-internal error to the user.
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1638
        transport = MemoryTransport()
1639
        transport.mkdir('branch')
1640
        transport = transport.clone('branch')
1641
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1642
        # get_stacked_on_url
1643
        client.add_error_response('NotStacked')
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1644
        # lock_write
1645
        client.add_success_response('ok', 'branch token', 'repo token')
1646
        # set_last_revision
1647
        client.add_error_response('UnexpectedError')
1648
        # unlock
1649
        client.add_success_response('ok')
1650
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1651
        branch = self.make_remote_branch(transport, client)
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1652
        # Lock the branch, reset the record of remote calls.
1653
        branch.lock_write()
1654
        client._calls = []
1655
1656
        err = self.assertRaises(
3690.1.2 by Andrew Bennetts
Rename UntranslateableErrorFromSmartServer -> UnknownErrorFromSmartServer.
1657
            errors.UnknownErrorFromSmartServer,
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1658
            branch.set_last_revision_info, 123, 'revid')
1659
        self.assertEqual(('UnexpectedError',), err.error_tuple)
1660
        branch.unlock()
1661
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1662
    def test_tip_change_rejected(self):
1663
        """TipChangeRejected responses cause a TipChangeRejected exception to
1664
        be raised.
1665
        """
1666
        transport = MemoryTransport()
1667
        transport.mkdir('branch')
1668
        transport = transport.clone('branch')
1669
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1670
        # get_stacked_on_url
1671
        client.add_error_response('NotStacked')
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1672
        # lock_write
1673
        client.add_success_response('ok', 'branch token', 'repo token')
1674
        # set_last_revision
1675
        client.add_error_response('TipChangeRejected', 'rejection message')
1676
        # unlock
1677
        client.add_success_response('ok')
1678
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1679
        branch = self.make_remote_branch(transport, client)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1680
        # Lock the branch, reset the record of remote calls.
1681
        branch.lock_write()
1682
        self.addCleanup(branch.unlock)
1683
        client._calls = []
1684
1685
        # The 'TipChangeRejected' error response triggered by calling
1686
        # set_last_revision_info causes a TipChangeRejected exception.
1687
        err = self.assertRaises(
1688
            errors.TipChangeRejected,
1689
            branch.set_last_revision_info, 123, 'revid')
1690
        self.assertEqual('rejection message', err.msg)
1691
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1692
4226.2.1 by Robert Collins
Set branch config options via a smart method.
1693
class TestBranchGetSetConfig(RemoteBranchTestCase):
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1694
1695
    def test_get_branch_conf(self):
4226.1.5 by Robert Collins
Reinstate the use of the Branch.get_config_file verb.
1696
        # in an empty branch we decode the response properly
1697
        client = FakeClient()
1698
        client.add_expected_call(
1699
            'Branch.get_stacked_on_url', ('memory:///',),
1700
            'error', ('NotStacked',),)
1701
        client.add_success_response_with_body('# config file body', 'ok')
1702
        transport = MemoryTransport()
1703
        branch = self.make_remote_branch(transport, client)
1704
        config = branch.get_config()
1705
        config.has_explicit_nickname()
1706
        self.assertEqual(
1707
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
1708
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
1709
            client._calls)
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1710
4241.5.2 by Matt Nordhoff
Add a test
1711
    def test_get_multi_line_branch_conf(self):
1712
        # Make sure that multiple-line branch.conf files are supported
1713
        #
5243.1.2 by Martin
Point launchpad links in comments at production server rather than edge
1714
        # https://bugs.launchpad.net/bzr/+bug/354075
4241.5.2 by Matt Nordhoff
Add a test
1715
        client = FakeClient()
1716
        client.add_expected_call(
1717
            'Branch.get_stacked_on_url', ('memory:///',),
1718
            'error', ('NotStacked',),)
1719
        client.add_success_response_with_body('a = 1\nb = 2\nc = 3\n', 'ok')
1720
        transport = MemoryTransport()
1721
        branch = self.make_remote_branch(transport, client)
1722
        config = branch.get_config()
1723
        self.assertEqual(u'2', config.get_user_option('b'))
1724
4226.2.1 by Robert Collins
Set branch config options via a smart method.
1725
    def test_set_option(self):
1726
        client = FakeClient()
1727
        client.add_expected_call(
1728
            'Branch.get_stacked_on_url', ('memory:///',),
1729
            'error', ('NotStacked',),)
1730
        client.add_expected_call(
1731
            'Branch.lock_write', ('memory:///', '', ''),
1732
            'success', ('ok', 'branch token', 'repo token'))
1733
        client.add_expected_call(
1734
            'Branch.set_config_option', ('memory:///', 'branch token',
1735
            'repo token', 'foo', 'bar', ''),
1736
            'success', ())
1737
        client.add_expected_call(
1738
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
1739
            'success', ('ok',))
1740
        transport = MemoryTransport()
1741
        branch = self.make_remote_branch(transport, client)
1742
        branch.lock_write()
1743
        config = branch._get_config()
1744
        config.set_option('foo', 'bar')
1745
        branch.unlock()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1746
        self.assertFinished(client)
4226.2.1 by Robert Collins
Set branch config options via a smart method.
1747
5227.1.2 by Andrew Bennetts
Add Branch.set_config_option_dict RPC (and VFS fallback), fixes #430382.
1748
    def test_set_option_with_dict(self):
1749
        client = FakeClient()
1750
        client.add_expected_call(
1751
            'Branch.get_stacked_on_url', ('memory:///',),
1752
            'error', ('NotStacked',),)
1753
        client.add_expected_call(
1754
            'Branch.lock_write', ('memory:///', '', ''),
1755
            'success', ('ok', 'branch token', 'repo token'))
1756
        encoded_dict_value = 'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
1757
        client.add_expected_call(
1758
            'Branch.set_config_option_dict', ('memory:///', 'branch token',
1759
            'repo token', encoded_dict_value, 'foo', ''),
1760
            'success', ())
1761
        client.add_expected_call(
1762
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
1763
            'success', ('ok',))
1764
        transport = MemoryTransport()
1765
        branch = self.make_remote_branch(transport, client)
1766
        branch.lock_write()
1767
        config = branch._get_config()
1768
        config.set_option(
1769
            {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'},
1770
            'foo')
1771
        branch.unlock()
1772
        self.assertFinished(client)
1773
4226.2.1 by Robert Collins
Set branch config options via a smart method.
1774
    def test_backwards_compat_set_option(self):
1775
        self.setup_smart_server_with_call_log()
1776
        branch = self.make_branch('.')
1777
        verb = 'Branch.set_config_option'
1778
        self.disable_verb(verb)
1779
        branch.lock_write()
1780
        self.addCleanup(branch.unlock)
1781
        self.reset_smart_call_log()
1782
        branch._get_config().set_option('value', 'name')
1783
        self.assertLength(10, self.hpss_calls)
1784
        self.assertEqual('value', branch._get_config().get_option('name'))
1785
5227.1.2 by Andrew Bennetts
Add Branch.set_config_option_dict RPC (and VFS fallback), fixes #430382.
1786
    def test_backwards_compat_set_option_with_dict(self):
1787
        self.setup_smart_server_with_call_log()
1788
        branch = self.make_branch('.')
1789
        verb = 'Branch.set_config_option_dict'
1790
        self.disable_verb(verb)
1791
        branch.lock_write()
1792
        self.addCleanup(branch.unlock)
1793
        self.reset_smart_call_log()
1794
        config = branch._get_config()
1795
        value_dict = {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
1796
        config.set_option(value_dict, 'name')
1797
        self.assertLength(10, self.hpss_calls)
1798
        self.assertEqual(value_dict, branch._get_config().get_option('name'))
1799
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1800
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1801
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.
1802
1803
    def test_lock_write_unlockable(self):
1804
        transport = MemoryTransport()
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1805
        client = FakeClient(transport.base)
3691.2.9 by Martin Pool
Convert and update more test_remote tests
1806
        client.add_expected_call(
1807
            'Branch.get_stacked_on_url', ('quack/',),
1808
            'error', ('NotStacked',),)
1809
        client.add_expected_call(
1810
            'Branch.lock_write', ('quack/', '', ''),
1811
            '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.
1812
        transport.mkdir('quack')
1813
        transport = transport.clone('quack')
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1814
        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.
1815
        self.assertRaises(errors.UnlockableTransport, branch.lock_write)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1816
        self.assertFinished(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.
1817
1818
4288.1.1 by Robert Collins
Add support for a RemoteBzrDirConfig to support optimising push operations which need to look for default stacking locations.
1819
class TestBzrDirGetSetConfig(RemoteBzrDirTestCase):
1820
1821
    def test__get_config(self):
1822
        client = FakeClient()
1823
        client.add_success_response_with_body('default_stack_on = /\n', 'ok')
1824
        transport = MemoryTransport()
1825
        bzrdir = self.make_remote_bzrdir(transport, client)
1826
        config = bzrdir.get_config()
1827
        self.assertEqual('/', config.get_default_stack_on())
1828
        self.assertEqual(
1829
            [('call_expecting_body', 'BzrDir.get_config_file', ('memory:///',))],
1830
            client._calls)
1831
1832
    def test_set_option_uses_vfs(self):
1833
        self.setup_smart_server_with_call_log()
1834
        bzrdir = self.make_bzrdir('.')
1835
        self.reset_smart_call_log()
1836
        config = bzrdir.get_config()
1837
        config.set_default_stack_on('/')
1838
        self.assertLength(3, self.hpss_calls)
1839
1840
    def test_backwards_compat_get_option(self):
1841
        self.setup_smart_server_with_call_log()
1842
        bzrdir = self.make_bzrdir('.')
1843
        verb = 'BzrDir.get_config_file'
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
1844
        self.disable_verb(verb)
4288.1.1 by Robert Collins
Add support for a RemoteBzrDirConfig to support optimising push operations which need to look for default stacking locations.
1845
        self.reset_smart_call_log()
1846
        self.assertEqual(None,
1847
            bzrdir._get_config().get_option('default_stack_on'))
1848
        self.assertLength(3, self.hpss_calls)
1849
1850
2466.2.2 by Andrew Bennetts
Add tests for RemoteTransport.is_readonly in the style of the other remote object tests.
1851
class TestTransportIsReadonly(tests.TestCase):
1852
1853
    def test_true(self):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1854
        client = FakeClient()
1855
        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.
1856
        transport = RemoteTransport('bzr://example.com/', medium=False,
1857
                                    _client=client)
1858
        self.assertEqual(True, transport.is_readonly())
1859
        self.assertEqual(
1860
            [('call', 'Transport.is_readonly', ())],
1861
            client._calls)
1862
1863
    def test_false(self):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1864
        client = FakeClient()
1865
        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.
1866
        transport = RemoteTransport('bzr://example.com/', medium=False,
1867
                                    _client=client)
1868
        self.assertEqual(False, transport.is_readonly())
1869
        self.assertEqual(
1870
            [('call', 'Transport.is_readonly', ())],
1871
            client._calls)
1872
1873
    def test_error_from_old_server(self):
1874
        """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
1875
2466.2.2 by Andrew Bennetts
Add tests for RemoteTransport.is_readonly in the style of the other remote object tests.
1876
        Clients should treat it as a "no" response, because is_readonly is only
1877
        advisory anyway (a transport could be read-write, but then the
1878
        underlying filesystem could be readonly anyway).
1879
        """
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1880
        client = FakeClient()
1881
        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.
1882
        transport = RemoteTransport('bzr://example.com/', medium=False,
1883
                                    _client=client)
1884
        self.assertEqual(False, transport.is_readonly())
1885
        self.assertEqual(
1886
            [('call', 'Transport.is_readonly', ())],
1887
            client._calls)
1888
2466.2.2 by Andrew Bennetts
Add tests for RemoteTransport.is_readonly in the style of the other remote object tests.
1889
3840.1.1 by Andrew Bennetts
Fix RemoteTransport's translation of errors involving paths; it wasn't passing orig_path to _translate_error.
1890
class TestTransportMkdir(tests.TestCase):
1891
1892
    def test_permissiondenied(self):
1893
        client = FakeClient()
1894
        client.add_error_response('PermissionDenied', 'remote path', 'extra')
1895
        transport = RemoteTransport('bzr://example.com/', medium=False,
1896
                                    _client=client)
1897
        exc = self.assertRaises(
1898
            errors.PermissionDenied, transport.mkdir, 'client path')
1899
        expected_error = errors.PermissionDenied('/client path', 'extra')
1900
        self.assertEqual(expected_error, exc)
1901
1902
3777.1.3 by Aaron Bentley
Use SSH default username from authentication.conf
1903
class TestRemoteSSHTransportAuthentication(tests.TestCaseInTempDir):
1904
4304.2.1 by Vincent Ladeuil
Fix bug #367726 by reverting some default user handling introduced
1905
    def test_defaults_to_none(self):
3777.1.3 by Aaron Bentley
Use SSH default username from authentication.conf
1906
        t = RemoteSSHTransport('bzr+ssh://example.com')
4304.2.1 by Vincent Ladeuil
Fix bug #367726 by reverting some default user handling introduced
1907
        self.assertIs(None, t._get_credentials()[0])
3777.1.3 by Aaron Bentley
Use SSH default username from authentication.conf
1908
1909
    def test_uses_authentication_config(self):
1910
        conf = config.AuthenticationConfig()
1911
        conf._get_config().update(
1912
            {'bzr+sshtest': {'scheme': 'ssh', 'user': 'bar', 'host':
1913
            'example.com'}})
1914
        conf._save()
1915
        t = RemoteSSHTransport('bzr+ssh://example.com')
1916
        self.assertEqual('bar', t._get_credentials()[0])
1917
1918
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
1919
class TestRemoteRepository(TestRemote):
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
1920
    """Base for testing RemoteRepository protocol usage.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1921
1922
    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
1923
    what is sent or expected to be require a thoughtful update to these tests
1924
    because they might break compatibility with different-versioned servers.
1925
    """
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1926
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1927
    def setup_fake_client_and_repository(self, transport_path):
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
1928
        """Create the fake client and repository for testing with.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1929
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
1930
        There's no real server here; we just have canned responses sent
1931
        back one by one.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1932
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
1933
        :param transport_path: Path below the root of the MemoryTransport
1934
            where the repository will be created.
1935
        """
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1936
        transport = MemoryTransport()
1937
        transport.mkdir(transport_path)
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1938
        client = FakeClient(transport.base)
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1939
        transport = transport.clone(transport_path)
1940
        # 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.
1941
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1942
            _client=False)
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1943
        repo = RemoteRepository(bzrdir, None, _client=client)
1944
        return repo, client
1945
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
1946
4792.1.1 by Andrew Bennetts
Show real branch/repo format description in 'info -v' over HPSS.
1947
def remoted_description(format):
1948
    return 'Remote: ' + format.get_format_description()
1949
1950
1951
class TestBranchFormat(tests.TestCase):
1952
1953
    def test_get_format_description(self):
1954
        remote_format = RemoteBranchFormat()
5662.2.2 by Jelmer Vernooij
Move most format registration functions to BranchFormatRegistry.
1955
        real_format = branch.format_registry.get_default()
4792.1.1 by Andrew Bennetts
Show real branch/repo format description in 'info -v' over HPSS.
1956
        remote_format._network_name = real_format.network_name()
1957
        self.assertEqual(remoted_description(real_format),
1958
            remote_format.get_format_description())
1959
1960
4183.5.1 by Robert Collins
Add RepositoryFormat.fast_deltas to signal fast delta creation.
1961
class TestRepositoryFormat(TestRemoteRepository):
1962
1963
    def test_fast_delta(self):
5546.1.1 by Andrew Bennetts
Remove RepositoryFormatCHK1 and RepositoryFormatCHK2.
1964
        true_name = groupcompress_repo.RepositoryFormat2a().network_name()
4183.5.1 by Robert Collins
Add RepositoryFormat.fast_deltas to signal fast delta creation.
1965
        true_format = RemoteRepositoryFormat()
1966
        true_format._network_name = true_name
1967
        self.assertEqual(True, true_format.fast_deltas)
1968
        false_name = pack_repo.RepositoryFormatKnitPack1().network_name()
1969
        false_format = RemoteRepositoryFormat()
1970
        false_format._network_name = false_name
1971
        self.assertEqual(False, false_format.fast_deltas)
1972
4792.1.1 by Andrew Bennetts
Show real branch/repo format description in 'info -v' over HPSS.
1973
    def test_get_format_description(self):
1974
        remote_repo_format = RemoteRepositoryFormat()
5651.3.9 by Jelmer Vernooij
Avoid using deprecated functions.
1975
        real_format = repository.format_registry.get_default()
4792.1.1 by Andrew Bennetts
Show real branch/repo format description in 'info -v' over HPSS.
1976
        remote_repo_format._network_name = real_format.network_name()
1977
        self.assertEqual(remoted_description(real_format),
1978
            remote_repo_format.get_format_description())
1979
4183.5.1 by Robert Collins
Add RepositoryFormat.fast_deltas to signal fast delta creation.
1980
2018.12.2 by Andrew Bennetts
Remove some duplicate code in test_remote
1981
class TestRepositoryGatherStats(TestRemoteRepository):
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
1982
1983
    def test_revid_none(self):
1984
        # ('ok',), body with revisions and size
1985
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1986
        repo, client = self.setup_fake_client_and_repository(transport_path)
1987
        client.add_success_response_with_body(
1988
            'revisions: 2\nsize: 18\n', 'ok')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
1989
        result = repo.gather_stats(None)
1990
        self.assertEqual(
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
1991
            [('call_expecting_body', 'Repository.gather_stats',
3104.4.2 by Andrew Bennetts
All tests passing.
1992
             ('quack/','','no'))],
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
1993
            client._calls)
1994
        self.assertEqual({'revisions': 2, 'size': 18}, result)
1995
1996
    def test_revid_no_committers(self):
1997
        # ('ok',), body without committers
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1998
        body = ('firstrev: 123456.300 3600\n'
1999
                'latestrev: 654231.400 0\n'
2000
                'revisions: 2\n'
2001
                'size: 18\n')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2002
        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.
2003
        revid = u'\xc8'.encode('utf8')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2004
        repo, client = self.setup_fake_client_and_repository(transport_path)
2005
        client.add_success_response_with_body(body, 'ok')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2006
        result = repo.gather_stats(revid)
2007
        self.assertEqual(
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
2008
            [('call_expecting_body', 'Repository.gather_stats',
3104.4.2 by Andrew Bennetts
All tests passing.
2009
              ('quick/', revid, 'no'))],
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2010
            client._calls)
2011
        self.assertEqual({'revisions': 2, 'size': 18,
2012
                          'firstrev': (123456.300, 3600),
2013
                          'latestrev': (654231.400, 0),},
2014
                         result)
2015
2016
    def test_revid_with_committers(self):
2017
        # ('ok',), body with committers
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2018
        body = ('committers: 128\n'
2019
                'firstrev: 123456.300 3600\n'
2020
                'latestrev: 654231.400 0\n'
2021
                'revisions: 2\n'
2022
                'size: 18\n')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2023
        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.
2024
        revid = u'\xc8'.encode('utf8')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2025
        repo, client = self.setup_fake_client_and_repository(transport_path)
2026
        client.add_success_response_with_body(body, 'ok')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2027
        result = repo.gather_stats(revid, True)
2028
        self.assertEqual(
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
2029
            [('call_expecting_body', 'Repository.gather_stats',
3104.4.2 by Andrew Bennetts
All tests passing.
2030
              ('buick/', revid, 'yes'))],
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2031
            client._calls)
2032
        self.assertEqual({'revisions': 2, 'size': 18,
2033
                          'committers': 128,
2034
                          'firstrev': (123456.300, 3600),
2035
                          'latestrev': (654231.400, 0),},
2036
                         result)
2037
2038
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
2039
class TestRepositoryGetGraph(TestRemoteRepository):
2040
2041
    def test_get_graph(self):
3835.1.6 by Aaron Bentley
Reduce inefficiency when doing make_parents_provider frequently
2042
        # 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.
2043
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2044
        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.
2045
        graph = repo.get_graph()
3835.1.6 by Aaron Bentley
Reduce inefficiency when doing make_parents_provider frequently
2046
        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.
2047
2048
2049
class TestRepositoryGetParentMap(TestRemoteRepository):
2050
2051
    def test_get_parent_map_caching(self):
2052
        # get_parent_map returns from cache until unlock()
2053
        # setup a reponse with two revisions
2054
        r1 = u'\u0e33'.encode('utf8')
2055
        r2 = u'\u0dab'.encode('utf8')
2056
        lines = [' '.join([r2, r1]), r1]
3211.5.2 by Robert Collins
Change RemoteRepository.get_parent_map to use bz2 not gzip for compression.
2057
        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.
2058
2059
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2060
        repo, client = self.setup_fake_client_and_repository(transport_path)
2061
        client.add_success_response_with_body(encoded_body, 'ok')
2062
        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.
2063
        repo.lock_read()
2064
        graph = repo.get_graph()
2065
        parents = graph.get_parent_map([r2])
2066
        self.assertEqual({r2: (r1,)}, parents)
2067
        # locking and unlocking deeper should not reset
2068
        repo.lock_read()
2069
        repo.unlock()
2070
        parents = graph.get_parent_map([r1])
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
2071
        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.
2072
        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.
2073
            [('call_with_body_bytes_expecting_body',
4190.1.6 by Robert Collins
Missed some unit tests.
2074
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
2075
              '\n\n0')],
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
2076
            client._calls)
2077
        repo.unlock()
2078
        # now we call again, and it should use the second response.
2079
        repo.lock_read()
2080
        graph = repo.get_graph()
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
2081
        parents = graph.get_parent_map([r1])
2082
        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.
2083
        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.
2084
            [('call_with_body_bytes_expecting_body',
4190.1.6 by Robert Collins
Missed some unit tests.
2085
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
2086
              '\n\n0'),
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.
2087
             ('call_with_body_bytes_expecting_body',
4190.1.6 by Robert Collins
Missed some unit tests.
2088
              'Repository.get_parent_map', ('quack/', 'include-missing:', r1),
2089
              '\n\n0'),
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
2090
            ],
2091
            client._calls)
2092
        repo.unlock()
2093
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
2094
    def test_get_parent_map_reconnects_if_unknown_method(self):
2095
        transport_path = 'quack'
3948.3.7 by Martin Pool
Updated tests for RemoteRepository.get_parent_map on old servers.
2096
        rev_id = 'revision-id'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2097
        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.
2098
        client.add_unknown_method_response('Repository.get_parent_map')
2099
        client.add_success_response_with_body(rev_id, 'ok')
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
2100
        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.
2101
        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.
2102
        self.assertEqual(
3213.1.8 by Andrew Bennetts
Merge from bzr.dev.
2103
            [('call_with_body_bytes_expecting_body',
4190.1.6 by Robert Collins
Missed some unit tests.
2104
              'Repository.get_parent_map', ('quack/', 'include-missing:',
2105
              rev_id), '\n\n0'),
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
2106
             ('disconnect medium',),
2107
             ('call_expecting_body', 'Repository.get_revision_graph',
2108
              ('quack/', ''))],
2109
            client._calls)
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
2110
        # 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.
2111
        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.
2112
        self.assertEqual({rev_id: ('null:',)}, parents)
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
2113
2114
    def test_get_parent_map_fallback_parentless_node(self):
2115
        """get_parent_map falls back to get_revision_graph on old servers.  The
2116
        results from get_revision_graph are tweaked to match the get_parent_map
2117
        API.
2118
3389.1.3 by Andrew Bennetts
Remove XXX from test description.
2119
        Specifically, a {key: ()} result from get_revision_graph means "no
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
2120
        parents" for that key, which in get_parent_map results should be
3389.1.3 by Andrew Bennetts
Remove XXX from test description.
2121
        represented as {key: ('null:',)}.
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
2122
2123
        This is the test for https://bugs.launchpad.net/bzr/+bug/214894
2124
        """
2125
        rev_id = 'revision-id'
2126
        transport_path = 'quack'
3245.4.40 by Andrew Bennetts
Merge from bzr.dev.
2127
        repo, client = self.setup_fake_client_and_repository(transport_path)
2128
        client.add_success_response_with_body(rev_id, 'ok')
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
2129
        client._medium._remember_remote_is_before((1, 2))
3948.3.7 by Martin Pool
Updated tests for RemoteRepository.get_parent_map on old servers.
2130
        parents = repo.get_parent_map([rev_id])
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
2131
        self.assertEqual(
2132
            [('call_expecting_body', 'Repository.get_revision_graph',
2133
             ('quack/', ''))],
2134
            client._calls)
2135
        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.
2136
3297.2.3 by Andrew Bennetts
Test the code path that the typo is on.
2137
    def test_get_parent_map_unexpected_response(self):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2138
        repo, client = self.setup_fake_client_and_repository('path')
2139
        client.add_success_response('something unexpected!')
3297.2.3 by Andrew Bennetts
Test the code path that the typo is on.
2140
        self.assertRaises(
2141
            errors.UnexpectedSmartServerResponse,
2142
            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.
2143
4190.1.1 by Robert Collins
Negatively cache misses during read-locks in RemoteRepository.
2144
    def test_get_parent_map_negative_caches_missing_keys(self):
2145
        self.setup_smart_server_with_call_log()
2146
        repo = self.make_repository('foo')
2147
        self.assertIsInstance(repo, RemoteRepository)
2148
        repo.lock_read()
2149
        self.addCleanup(repo.unlock)
2150
        self.reset_smart_call_log()
2151
        graph = repo.get_graph()
2152
        self.assertEqual({},
2153
            graph.get_parent_map(['some-missing', 'other-missing']))
2154
        self.assertLength(1, self.hpss_calls)
2155
        # No call if we repeat this
2156
        self.reset_smart_call_log()
2157
        graph = repo.get_graph()
2158
        self.assertEqual({},
2159
            graph.get_parent_map(['some-missing', 'other-missing']))
2160
        self.assertLength(0, self.hpss_calls)
2161
        # Asking for more unknown keys makes a request.
2162
        self.reset_smart_call_log()
2163
        graph = repo.get_graph()
2164
        self.assertEqual({},
2165
            graph.get_parent_map(['some-missing', 'other-missing',
2166
                'more-missing']))
2167
        self.assertLength(1, self.hpss_calls)
2168
4214.2.1 by Andrew Bennetts
A long but failing test for the get_parent_map RPC bug.
2169
    def disableExtraResults(self):
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
2170
        self.overrideAttr(SmartServerRepositoryGetParentMap,
2171
                          'no_extra_results', True)
4214.2.1 by Andrew Bennetts
A long but failing test for the get_parent_map RPC bug.
2172
4214.2.5 by Andrew Bennetts
Fix the bug.
2173
    def test_null_cached_missing_and_stop_key(self):
4214.2.1 by Andrew Bennetts
A long but failing test for the get_parent_map RPC bug.
2174
        self.setup_smart_server_with_call_log()
4214.2.4 by Andrew Bennetts
Further simplify the test to reproduce the bug.
2175
        # Make a branch with a single revision.
4214.2.1 by Andrew Bennetts
A long but failing test for the get_parent_map RPC bug.
2176
        builder = self.make_branch_builder('foo')
2177
        builder.start_series()
2178
        builder.build_snapshot('first', None, [
2179
            ('add', ('', 'root-id', 'directory', ''))])
2180
        builder.finish_series()
2181
        branch = builder.get_branch()
2182
        repo = branch.repository
2183
        self.assertIsInstance(repo, RemoteRepository)
4214.2.3 by Andrew Bennetts
Further simplify test case, and add more comments.
2184
        # Stop the server from sending extra results.
2185
        self.disableExtraResults()
4214.2.1 by Andrew Bennetts
A long but failing test for the get_parent_map RPC bug.
2186
        repo.lock_read()
2187
        self.addCleanup(repo.unlock)
2188
        self.reset_smart_call_log()
2189
        graph = repo.get_graph()
4214.2.4 by Andrew Bennetts
Further simplify the test to reproduce the bug.
2190
        # Query for 'first' and 'null:'.  Because 'null:' is a parent of
4214.2.5 by Andrew Bennetts
Fix the bug.
2191
        # 'first' it will be a candidate for the stop_keys of subsequent
2192
        # requests, and because 'null:' was queried but not returned it will be
2193
        # cached as missing.
4214.2.1 by Andrew Bennetts
A long but failing test for the get_parent_map RPC bug.
2194
        self.assertEqual({'first': ('null:',)},
4214.2.4 by Andrew Bennetts
Further simplify the test to reproduce the bug.
2195
            graph.get_parent_map(['first', 'null:']))
2196
        # Now query for another key.  This request will pass along a recipe of
2197
        # start and stop keys describing the already cached results, and this
4214.2.5 by Andrew Bennetts
Fix the bug.
2198
        # recipe's revision count must be correct (or else it will trigger an
4214.2.4 by Andrew Bennetts
Further simplify the test to reproduce the bug.
2199
        # error from the server).
4214.2.5 by Andrew Bennetts
Fix the bug.
2200
        self.assertEqual({}, graph.get_parent_map(['another-key']))
4214.2.3 by Andrew Bennetts
Further simplify test case, and add more comments.
2201
        # This assertion guards against disableExtraResults silently failing to
2202
        # work, thus invalidating the test.
4214.2.4 by Andrew Bennetts
Further simplify the test to reproduce the bug.
2203
        self.assertLength(2, self.hpss_calls)
4214.2.1 by Andrew Bennetts
A long but failing test for the get_parent_map RPC bug.
2204
4190.1.4 by Robert Collins
Cache ghosts when we can get them from a RemoteRepository in get_parent_map.
2205
    def test_get_parent_map_gets_ghosts_from_result(self):
2206
        # asking for a revision should negatively cache close ghosts in its
2207
        # ancestry.
2208
        self.setup_smart_server_with_call_log()
2209
        tree = self.make_branch_and_memory_tree('foo')
2210
        tree.lock_write()
2211
        try:
2212
            builder = treebuilder.TreeBuilder()
2213
            builder.start_tree(tree)
2214
            builder.build([])
2215
            builder.finish_tree()
2216
            tree.set_parent_ids(['non-existant'], allow_leftmost_as_ghost=True)
2217
            rev_id = tree.commit('')
2218
        finally:
2219
            tree.unlock()
2220
        tree.lock_read()
2221
        self.addCleanup(tree.unlock)
2222
        repo = tree.branch.repository
2223
        self.assertIsInstance(repo, RemoteRepository)
2224
        # ask for rev_id
2225
        repo.get_parent_map([rev_id])
2226
        self.reset_smart_call_log()
2227
        # Now asking for rev_id's ghost parent should not make calls
2228
        self.assertEqual({}, repo.get_parent_map(['non-existant']))
2229
        self.assertLength(0, self.hpss_calls)
2230
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
2231
3835.1.15 by Aaron Bentley
Allow miss caching to be disabled.
2232
class TestGetParentMapAllowsNew(tests.TestCaseWithTransport):
2233
2234
    def test_allows_new_revisions(self):
2235
        """get_parent_map's results can be updated by commit."""
5017.3.28 by Vincent Ladeuil
selftest -s bt.test_remote passing
2236
        smart_server = test_server.SmartTCPServer_for_testing()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
2237
        self.start_server(smart_server)
3835.1.15 by Aaron Bentley
Allow miss caching to be disabled.
2238
        self.make_branch('branch')
2239
        branch = Branch.open(smart_server.get_url() + '/branch')
2240
        tree = branch.create_checkout('tree', lightweight=True)
2241
        tree.lock_write()
2242
        self.addCleanup(tree.unlock)
2243
        graph = tree.branch.repository.get_graph()
2244
        # This provides an opportunity for the missing rev-id to be cached.
2245
        self.assertEqual({}, graph.get_parent_map(['rev1']))
2246
        tree.commit('message', rev_id='rev1')
2247
        graph = tree.branch.repository.get_graph()
2248
        self.assertEqual({'rev1': ('null:',)}, graph.get_parent_map(['rev1']))
2249
2250
3948.3.9 by Martin Pool
Undelete TestRepositoryGetRevisionGraph but make it use private client methods to simulate old clients
2251
class TestRepositoryGetRevisionGraph(TestRemoteRepository):
2252
2253
    def test_null_revision(self):
2254
        # a null revision has the predictable result {}, we should have no wire
2255
        # traffic when calling it with this argument
2256
        transport_path = 'empty'
2257
        repo, client = self.setup_fake_client_and_repository(transport_path)
2258
        client.add_success_response('notused')
2259
        # actual RemoteRepository.get_revision_graph is gone, but there's an
2260
        # equivalent private method for testing
2261
        result = repo._get_revision_graph(NULL_REVISION)
2262
        self.assertEqual([], client._calls)
2263
        self.assertEqual({}, result)
2264
2265
    def test_none_revision(self):
2266
        # with none we want the entire graph
2267
        r1 = u'\u0e33'.encode('utf8')
2268
        r2 = u'\u0dab'.encode('utf8')
2269
        lines = [' '.join([r2, r1]), r1]
2270
        encoded_body = '\n'.join(lines)
2271
2272
        transport_path = 'sinhala'
2273
        repo, client = self.setup_fake_client_and_repository(transport_path)
2274
        client.add_success_response_with_body(encoded_body, 'ok')
2275
        # actual RemoteRepository.get_revision_graph is gone, but there's an
2276
        # equivalent private method for testing
2277
        result = repo._get_revision_graph(None)
2278
        self.assertEqual(
2279
            [('call_expecting_body', 'Repository.get_revision_graph',
2280
             ('sinhala/', ''))],
2281
            client._calls)
2282
        self.assertEqual({r1: (), r2: (r1, )}, result)
2283
2284
    def test_specific_revision(self):
2285
        # with a specific revision we want the graph for that
2286
        # with none we want the entire graph
2287
        r11 = u'\u0e33'.encode('utf8')
2288
        r12 = u'\xc9'.encode('utf8')
2289
        r2 = u'\u0dab'.encode('utf8')
2290
        lines = [' '.join([r2, r11, r12]), r11, r12]
2291
        encoded_body = '\n'.join(lines)
2292
2293
        transport_path = 'sinhala'
2294
        repo, client = self.setup_fake_client_and_repository(transport_path)
2295
        client.add_success_response_with_body(encoded_body, 'ok')
2296
        result = repo._get_revision_graph(r2)
2297
        self.assertEqual(
2298
            [('call_expecting_body', 'Repository.get_revision_graph',
2299
             ('sinhala/', r2))],
2300
            client._calls)
2301
        self.assertEqual({r11: (), r12: (), r2: (r11, r12), }, result)
2302
2303
    def test_no_such_revision(self):
2304
        revid = '123'
2305
        transport_path = 'sinhala'
2306
        repo, client = self.setup_fake_client_and_repository(transport_path)
2307
        client.add_error_response('nosuchrevision', revid)
2308
        # also check that the right revision is reported in the error
2309
        self.assertRaises(errors.NoSuchRevision,
2310
            repo._get_revision_graph, revid)
2311
        self.assertEqual(
2312
            [('call_expecting_body', 'Repository.get_revision_graph',
2313
             ('sinhala/', revid))],
2314
            client._calls)
2315
2316
    def test_unexpected_error(self):
2317
        revid = '123'
2318
        transport_path = 'sinhala'
2319
        repo, client = self.setup_fake_client_and_repository(transport_path)
2320
        client.add_error_response('AnUnexpectedError')
2321
        e = self.assertRaises(errors.UnknownErrorFromSmartServer,
2322
            repo._get_revision_graph, revid)
2323
        self.assertEqual(('AnUnexpectedError',), e.error_tuple)
2324
2325
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2326
class TestRepositoryGetRevIdForRevno(TestRemoteRepository):
2327
2328
    def test_ok(self):
4419.2.8 by Andrew Bennetts
Add unit test for RemoteRepository.get_rev_id_for_revno using fallbacks if it gets a history-incomplete response.
2329
        repo, client = self.setup_fake_client_and_repository('quack')
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2330
        client.add_expected_call(
2331
            'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2332
            'success', ('ok', 'rev-five'))
2333
        result = repo.get_rev_id_for_revno(5, (42, 'rev-foo'))
2334
        self.assertEqual((True, 'rev-five'), result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
2335
        self.assertFinished(client)
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2336
2337
    def test_history_incomplete(self):
4419.2.8 by Andrew Bennetts
Add unit test for RemoteRepository.get_rev_id_for_revno using fallbacks if it gets a history-incomplete response.
2338
        repo, client = self.setup_fake_client_and_repository('quack')
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2339
        client.add_expected_call(
2340
            'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2341
            'success', ('history-incomplete', 10, 'rev-ten'))
2342
        result = repo.get_rev_id_for_revno(5, (42, 'rev-foo'))
2343
        self.assertEqual((False, (10, 'rev-ten')), result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
2344
        self.assertFinished(client)
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2345
4419.2.8 by Andrew Bennetts
Add unit test for RemoteRepository.get_rev_id_for_revno using fallbacks if it gets a history-incomplete response.
2346
    def test_history_incomplete_with_fallback(self):
2347
        """A 'history-incomplete' response causes the fallback repository to be
2348
        queried too, if one is set.
2349
        """
2350
        # Make a repo with a fallback repo, both using a FakeClient.
2351
        format = remote.response_tuple_to_repo_format(
5158.4.3 by Andrew Bennetts
Fix test_remote tests that accidentally assumed it was ok to stack mismatched formats.
2352
            ('yes', 'no', 'yes', self.get_repo_format().network_name()))
4419.2.8 by Andrew Bennetts
Add unit test for RemoteRepository.get_rev_id_for_revno using fallbacks if it gets a history-incomplete response.
2353
        repo, client = self.setup_fake_client_and_repository('quack')
2354
        repo._format = format
2355
        fallback_repo, ignored = self.setup_fake_client_and_repository(
2356
            'fallback')
2357
        fallback_repo._client = client
5158.4.3 by Andrew Bennetts
Fix test_remote tests that accidentally assumed it was ok to stack mismatched formats.
2358
        fallback_repo._format = format
4419.2.8 by Andrew Bennetts
Add unit test for RemoteRepository.get_rev_id_for_revno using fallbacks if it gets a history-incomplete response.
2359
        repo.add_fallback_repository(fallback_repo)
2360
        # First the client should ask the primary repo
2361
        client.add_expected_call(
2362
            'Repository.get_rev_id_for_revno', ('quack/', 1, (42, 'rev-foo')),
2363
            'success', ('history-incomplete', 2, 'rev-two'))
2364
        # Then it should ask the fallback, using revno/revid from the
2365
        # history-incomplete response as the known revno/revid.
2366
        client.add_expected_call(
2367
            'Repository.get_rev_id_for_revno',('fallback/', 1, (2, 'rev-two')),
2368
            'success', ('ok', 'rev-one'))
2369
        result = repo.get_rev_id_for_revno(1, (42, 'rev-foo'))
2370
        self.assertEqual((True, 'rev-one'), result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
2371
        self.assertFinished(client)
4419.2.8 by Andrew Bennetts
Add unit test for RemoteRepository.get_rev_id_for_revno using fallbacks if it gets a history-incomplete response.
2372
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2373
    def test_nosuchrevision(self):
2374
        # 'nosuchrevision' is returned when the known-revid is not found in the
2375
        # remote repo.  The client translates that response to NoSuchRevision.
4419.2.8 by Andrew Bennetts
Add unit test for RemoteRepository.get_rev_id_for_revno using fallbacks if it gets a history-incomplete response.
2376
        repo, client = self.setup_fake_client_and_repository('quack')
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2377
        client.add_expected_call(
2378
            'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2379
            'error', ('nosuchrevision', 'rev-foo'))
2380
        self.assertRaises(
2381
            errors.NoSuchRevision,
2382
            repo.get_rev_id_for_revno, 5, (42, 'rev-foo'))
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
2383
        self.assertFinished(client)
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2384
4634.69.1 by Andrew Bennetts
Apply @needs_read_lock to RemoteBranch.get_rev_id.
2385
    def test_branch_fallback_locking(self):
2386
        """RemoteBranch.get_rev_id takes a read lock, and tries to call the
2387
        get_rev_id_for_revno verb.  If the verb is unknown the VFS fallback
2388
        will be invoked, which will fail if the repo is unlocked.
2389
        """
2390
        self.setup_smart_server_with_call_log()
2391
        tree = self.make_branch_and_memory_tree('.')
2392
        tree.lock_write()
5222.1.1 by Aaron Bentley
Refuse to commit trees with no root.
2393
        tree.add('')
4634.69.1 by Andrew Bennetts
Apply @needs_read_lock to RemoteBranch.get_rev_id.
2394
        rev1 = tree.commit('First')
2395
        rev2 = tree.commit('Second')
2396
        tree.unlock()
2397
        branch = tree.branch
2398
        self.assertFalse(branch.is_locked())
2399
        self.reset_smart_call_log()
2400
        verb = 'Repository.get_rev_id_for_revno'
2401
        self.disable_verb(verb)
2402
        self.assertEqual(rev1, branch.get_rev_id(1))
2403
        self.assertLength(1, [call for call in self.hpss_calls if
2404
                              call.call.method == verb])
2405
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2406
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
2407
class TestRepositoryIsShared(TestRemoteRepository):
2408
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
2409
    def test_is_shared(self):
2410
        # ('yes', ) for Repository.is_shared -> 'True'.
2411
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2412
        repo, client = self.setup_fake_client_and_repository(transport_path)
2413
        client.add_success_response('yes')
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
2414
        result = repo.is_shared()
2415
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
2416
            [('call', 'Repository.is_shared', ('quack/',))],
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
2417
            client._calls)
2418
        self.assertEqual(True, result)
2419
2420
    def test_is_not_shared(self):
2421
        # ('no', ) for Repository.is_shared -> 'False'.
2422
        transport_path = 'qwack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2423
        repo, client = self.setup_fake_client_and_repository(transport_path)
2424
        client.add_success_response('no')
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
2425
        result = repo.is_shared()
2426
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
2427
            [('call', 'Repository.is_shared', ('qwack/',))],
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
2428
            client._calls)
2429
        self.assertEqual(False, result)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
2430
2431
2432
class TestRepositoryLockWrite(TestRemoteRepository):
2433
2434
    def test_lock_write(self):
2435
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2436
        repo, client = self.setup_fake_client_and_repository(transport_path)
2437
        client.add_success_response('ok', 'a token')
5200.3.3 by Robert Collins
Lock methods on ``Tree``, ``Branch`` and ``Repository`` are now
2438
        token = repo.lock_write().repository_token
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
2439
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
2440
            [('call', 'Repository.lock_write', ('quack/', ''))],
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
2441
            client._calls)
5200.3.3 by Robert Collins
Lock methods on ``Tree``, ``Branch`` and ``Repository`` are now
2442
        self.assertEqual('a token', token)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
2443
2444
    def test_lock_write_already_locked(self):
2445
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2446
        repo, client = self.setup_fake_client_and_repository(transport_path)
2447
        client.add_error_response('LockContention')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
2448
        self.assertRaises(errors.LockContention, repo.lock_write)
2449
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
2450
            [('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.
2451
            client._calls)
2452
2453
    def test_lock_write_unlockable(self):
2454
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2455
        repo, client = self.setup_fake_client_and_repository(transport_path)
2456
        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.
2457
        self.assertRaises(errors.UnlockableTransport, repo.lock_write)
2458
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
2459
            [('call', 'Repository.lock_write', ('quack/', ''))],
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
2460
            client._calls)
2461
2462
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
2463
class TestRepositorySetMakeWorkingTrees(TestRemoteRepository):
2464
2465
    def test_backwards_compat(self):
2466
        self.setup_smart_server_with_call_log()
2467
        repo = self.make_repository('.')
2468
        self.reset_smart_call_log()
2469
        verb = 'Repository.set_make_working_trees'
2470
        self.disable_verb(verb)
2471
        repo.set_make_working_trees(True)
2472
        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.
2473
            call.call.method == verb])
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
2474
        self.assertEqual(1, call_count)
2475
2476
    def test_current(self):
2477
        transport_path = 'quack'
2478
        repo, client = self.setup_fake_client_and_repository(transport_path)
2479
        client.add_expected_call(
2480
            'Repository.set_make_working_trees', ('quack/', 'True'),
2481
            'success', ('ok',))
2482
        client.add_expected_call(
2483
            'Repository.set_make_working_trees', ('quack/', 'False'),
2484
            'success', ('ok',))
2485
        repo.set_make_working_trees(True)
2486
        repo.set_make_working_trees(False)
2487
2488
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
2489
class TestRepositoryUnlock(TestRemoteRepository):
2490
2491
    def test_unlock(self):
2492
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2493
        repo, client = self.setup_fake_client_and_repository(transport_path)
2494
        client.add_success_response('ok', 'a token')
2495
        client.add_success_response('ok')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
2496
        repo.lock_write()
2497
        repo.unlock()
2498
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
2499
            [('call', 'Repository.lock_write', ('quack/', '')),
2500
             ('call', 'Repository.unlock', ('quack/', 'a token'))],
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
2501
            client._calls)
2502
2503
    def test_unlock_wrong_token(self):
2504
        # If somehow the token is wrong, unlock will raise TokenMismatch.
2505
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2506
        repo, client = self.setup_fake_client_and_repository(transport_path)
2507
        client.add_success_response('ok', 'a token')
2508
        client.add_error_response('TokenMismatch')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
2509
        repo.lock_write()
2510
        self.assertRaises(errors.TokenMismatch, repo.unlock)
2511
2512
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
2513
class TestRepositoryHasRevision(TestRemoteRepository):
2514
2515
    def test_none(self):
2516
        # repo.has_revision(None) should not cause any traffic.
2517
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2518
        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.
2519
2520
        # The null revision is always there, so has_revision(None) == True.
3172.3.3 by Robert Collins
Missed one occurence of None -> NULL_REVISION.
2521
        self.assertEqual(True, repo.has_revision(NULL_REVISION))
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
2522
2523
        # The remote repo shouldn't be accessed.
2524
        self.assertEqual([], client._calls)
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
2525
2526
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
2527
class TestRepositoryInsertStreamBase(TestRemoteRepository):
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2528
    """Base class for Repository.insert_stream and .insert_stream_1.19
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
2529
    tests.
2530
    """
2531
    
2532
    def checkInsertEmptyStream(self, repo, client):
2533
        """Insert an empty stream, checking the result.
2534
2535
        This checks that there are no resume_tokens or missing_keys, and that
2536
        the client is finished.
2537
        """
2538
        sink = repo._get_sink()
5651.3.9 by Jelmer Vernooij
Avoid using deprecated functions.
2539
        fmt = repository.format_registry.get_default()
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
2540
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2541
        self.assertEqual([], resume_tokens)
2542
        self.assertEqual(set(), missing_keys)
2543
        self.assertFinished(client)
2544
2545
2546
class TestRepositoryInsertStream(TestRepositoryInsertStreamBase):
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2547
    """Tests for using Repository.insert_stream verb when the _1.19 variant is
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2548
    not available.
2549
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2550
    This test case is very similar to TestRepositoryInsertStream_1_19.
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2551
    """
2552
2553
    def setUp(self):
2554
        TestRemoteRepository.setUp(self)
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2555
        self.disable_verb('Repository.insert_stream_1.19')
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2556
2557
    def test_unlocked_repo(self):
2558
        transport_path = 'quack'
2559
        repo, client = self.setup_fake_client_and_repository(transport_path)
2560
        client.add_expected_call(
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2561
            'Repository.insert_stream_1.19', ('quack/', ''),
2562
            'unknown', ('Repository.insert_stream_1.19',))
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2563
        client.add_expected_call(
2564
            'Repository.insert_stream', ('quack/', ''),
2565
            'success', ('ok',))
2566
        client.add_expected_call(
2567
            'Repository.insert_stream', ('quack/', ''),
2568
            'success', ('ok',))
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
2569
        self.checkInsertEmptyStream(repo, client)
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2570
2571
    def test_locked_repo_with_no_lock_token(self):
2572
        transport_path = 'quack'
2573
        repo, client = self.setup_fake_client_and_repository(transport_path)
2574
        client.add_expected_call(
2575
            'Repository.lock_write', ('quack/', ''),
2576
            'success', ('ok', ''))
2577
        client.add_expected_call(
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2578
            'Repository.insert_stream_1.19', ('quack/', ''),
2579
            'unknown', ('Repository.insert_stream_1.19',))
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2580
        client.add_expected_call(
2581
            'Repository.insert_stream', ('quack/', ''),
2582
            'success', ('ok',))
2583
        client.add_expected_call(
2584
            'Repository.insert_stream', ('quack/', ''),
2585
            'success', ('ok',))
2586
        repo.lock_write()
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
2587
        self.checkInsertEmptyStream(repo, client)
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2588
2589
    def test_locked_repo_with_lock_token(self):
2590
        transport_path = 'quack'
2591
        repo, client = self.setup_fake_client_and_repository(transport_path)
2592
        client.add_expected_call(
2593
            'Repository.lock_write', ('quack/', ''),
2594
            'success', ('ok', 'a token'))
2595
        client.add_expected_call(
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2596
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
2597
            'unknown', ('Repository.insert_stream_1.19',))
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2598
        client.add_expected_call(
2599
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
2600
            'success', ('ok',))
2601
        client.add_expected_call(
2602
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
2603
            'success', ('ok',))
2604
        repo.lock_write()
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
2605
        self.checkInsertEmptyStream(repo, client)
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2606
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
2607
    def test_stream_with_inventory_deltas(self):
4476.3.71 by Andrew Bennetts
Clearer comments prompted by Robert's review.
2608
        """'inventory-deltas' substreams cannot be sent to the
2609
        Repository.insert_stream verb, because not all servers that implement
2610
        that verb will accept them.  So when one is encountered the RemoteSink
2611
        immediately stops using that verb and falls back to VFS insert_stream.
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
2612
        """
2613
        transport_path = 'quack'
2614
        repo, client = self.setup_fake_client_and_repository(transport_path)
2615
        client.add_expected_call(
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2616
            'Repository.insert_stream_1.19', ('quack/', ''),
2617
            'unknown', ('Repository.insert_stream_1.19',))
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
2618
        client.add_expected_call(
2619
            'Repository.insert_stream', ('quack/', ''),
2620
            'success', ('ok',))
2621
        client.add_expected_call(
2622
            'Repository.insert_stream', ('quack/', ''),
2623
            'success', ('ok',))
2624
        # Create a fake real repository for insert_stream to fall back on, so
2625
        # that we can directly see the records the RemoteSink passes to the
2626
        # real sink.
2627
        class FakeRealSink:
2628
            def __init__(self):
2629
                self.records = []
2630
            def insert_stream(self, stream, src_format, resume_tokens):
2631
                for substream_kind, substream in stream:
2632
                    self.records.append(
2633
                        (substream_kind, [record.key for record in substream]))
2634
                return ['fake tokens'], ['fake missing keys']
2635
        fake_real_sink = FakeRealSink()
2636
        class FakeRealRepository:
2637
            def _get_sink(self):
2638
                return fake_real_sink
4634.35.20 by Andrew Bennetts
Fix test_remote.
2639
            def is_in_write_group(self):
2640
                return False
2641
            def refresh_data(self):
2642
                return True
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
2643
        repo._real_repository = FakeRealRepository()
2644
        sink = repo._get_sink()
5651.3.9 by Jelmer Vernooij
Avoid using deprecated functions.
2645
        fmt = repository.format_registry.get_default()
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
2646
        stream = self.make_stream_with_inv_deltas(fmt)
2647
        resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
2648
        # Every record from the first inventory delta should have been sent to
2649
        # the VFS sink.
2650
        expected_records = [
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
2651
            ('inventory-deltas', [('rev2',), ('rev3',)]),
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
2652
            ('texts', [('some-rev', 'some-file')])]
2653
        self.assertEqual(expected_records, fake_real_sink.records)
2654
        # The return values from the real sink's insert_stream are propagated
2655
        # back to the original caller.
2656
        self.assertEqual(['fake tokens'], resume_tokens)
2657
        self.assertEqual(['fake missing keys'], missing_keys)
4476.3.40 by Andrew Bennetts
Merge bzr.dev.
2658
        self.assertFinished(client)
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
2659
2660
    def make_stream_with_inv_deltas(self, fmt):
2661
        """Make a simple stream with an inventory delta followed by more
2662
        records and more substreams to test that all records and substreams
2663
        from that point on are used.
2664
2665
        This sends, in order:
2666
           * inventories substream: rev1, rev2, rev3.  rev2 and rev3 are
2667
             inventory-deltas.
2668
           * texts substream: (some-rev, some-file)
2669
        """
2670
        # Define a stream using generators so that it isn't rewindable.
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
2671
        inv = inventory.Inventory(revision_id='rev1')
4599.4.39 by Robert Collins
Use a valid for storage inventory in test_remote's new inventory streaming test.
2672
        inv.root.revision = 'rev1'
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
2673
        def stream_with_inv_delta():
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
2674
            yield ('inventories', inventories_substream())
2675
            yield ('inventory-deltas', inventory_delta_substream())
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
2676
            yield ('texts', [
2677
                versionedfile.FulltextContentFactory(
2678
                    ('some-rev', 'some-file'), (), None, 'content')])
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
2679
        def inventories_substream():
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
2680
            # An empty inventory fulltext.  This will be streamed normally.
2681
            text = fmt._serializer.write_inventory_to_string(inv)
2682
            yield versionedfile.FulltextContentFactory(
2683
                ('rev1',), (), None, text)
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
2684
        def inventory_delta_substream():
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
2685
            # An inventory delta.  This can't be streamed via this verb, so it
2686
            # will trigger a fallback to VFS insert_stream.
2687
            entry = inv.make_entry(
2688
                'directory', 'newdir', inv.root.file_id, 'newdir-id')
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
2689
            entry.revision = 'ghost'
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
2690
            delta = [(None, 'newdir', 'newdir-id', entry)]
4476.3.76 by Andrew Bennetts
Split out InventoryDeltaDeserializer from InventoryDeltaSerializer.
2691
            serializer = inventory_delta.InventoryDeltaSerializer(
2692
                versioned_root=True, tree_references=False)
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
2693
            lines = serializer.delta_to_lines('rev1', 'rev2', delta)
2694
            yield versionedfile.ChunkedContentFactory(
2695
                ('rev2',), (('rev1',)), None, lines)
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
2696
            # Another delta.
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
2697
            lines = serializer.delta_to_lines('rev1', 'rev3', delta)
2698
            yield versionedfile.ChunkedContentFactory(
2699
                ('rev3',), (('rev1',)), None, lines)
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
2700
        return stream_with_inv_delta()
2701
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2702
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2703
class TestRepositoryInsertStream_1_19(TestRepositoryInsertStreamBase):
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2704
2705
    def test_unlocked_repo(self):
2706
        transport_path = 'quack'
2707
        repo, client = self.setup_fake_client_and_repository(transport_path)
2708
        client.add_expected_call(
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2709
            'Repository.insert_stream_1.19', ('quack/', ''),
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2710
            'success', ('ok',))
2711
        client.add_expected_call(
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2712
            'Repository.insert_stream_1.19', ('quack/', ''),
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2713
            'success', ('ok',))
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
2714
        self.checkInsertEmptyStream(repo, client)
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2715
2716
    def test_locked_repo_with_no_lock_token(self):
2717
        transport_path = 'quack'
2718
        repo, client = self.setup_fake_client_and_repository(transport_path)
2719
        client.add_expected_call(
2720
            'Repository.lock_write', ('quack/', ''),
2721
            'success', ('ok', ''))
2722
        client.add_expected_call(
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2723
            'Repository.insert_stream_1.19', ('quack/', ''),
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2724
            'success', ('ok',))
2725
        client.add_expected_call(
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2726
            'Repository.insert_stream_1.19', ('quack/', ''),
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2727
            'success', ('ok',))
2728
        repo.lock_write()
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
2729
        self.checkInsertEmptyStream(repo, client)
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2730
2731
    def test_locked_repo_with_lock_token(self):
2732
        transport_path = 'quack'
2733
        repo, client = self.setup_fake_client_and_repository(transport_path)
2734
        client.add_expected_call(
2735
            'Repository.lock_write', ('quack/', ''),
2736
            'success', ('ok', 'a token'))
2737
        client.add_expected_call(
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2738
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
4476.3.32 by Andrew Bennetts
Move disable_verb into base TestCase to remove duplication, fix trivial test failures due to new insert_stream verb in test_remote (and also add some trivial tests for the new verb).
2739
            'success', ('ok',))
2740
        client.add_expected_call(
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
2741
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
4144.3.2 by Andrew Bennetts
Use Repository.insert_stream_locked if there is a lock_token for the remote repo.
2742
            'success', ('ok',))
2743
        repo.lock_write()
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
2744
        self.checkInsertEmptyStream(repo, client)
4144.3.2 by Andrew Bennetts
Use Repository.insert_stream_locked if there is a lock_token for the remote repo.
2745
2746
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
2747
class TestRepositoryTarball(TestRemoteRepository):
2748
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
2749
    # This is a canned tarball reponse we can validate against
2018.18.18 by Martin Pool
reformat
2750
    tarball_content = (
2018.18.23 by Martin Pool
review cleanups
2751
        'QlpoOTFBWSZTWdGkj3wAAWF/k8aQACBIB//A9+8cIX/v33AACEAYABAECEACNz'
2752
        'JqsgJJFPTSnk1A3qh6mTQAAAANPUHkagkSTEkaA09QaNAAAGgAAAcwCYCZGAEY'
2753
        'mJhMJghpiaYBUkKammSHqNMZQ0NABkNAeo0AGneAevnlwQoGzEzNVzaYxp/1Uk'
2754
        'xXzA1CQX0BJMZZLcPBrluJir5SQyijWHYZ6ZUtVqqlYDdB2QoCwa9GyWwGYDMA'
2755
        'OQYhkpLt/OKFnnlT8E0PmO8+ZNSo2WWqeCzGB5fBXZ3IvV7uNJVE7DYnWj6qwB'
2756
        'k5DJDIrQ5OQHHIjkS9KqwG3mc3t+F1+iujb89ufyBNIKCgeZBWrl5cXxbMGoMs'
2757
        'c9JuUkg5YsiVcaZJurc6KLi6yKOkgCUOlIlOpOoXyrTJjK8ZgbklReDdwGmFgt'
2758
        'dkVsAIslSVCd4AtACSLbyhLHryfb14PKegrVDba+U8OL6KQtzdM5HLjAc8/p6n'
2759
        '0lgaWU8skgO7xupPTkyuwheSckejFLK5T4ZOo0Gda9viaIhpD1Qn7JqqlKAJqC'
2760
        'QplPKp2nqBWAfwBGaOwVrz3y1T+UZZNismXHsb2Jq18T+VaD9k4P8DqE3g70qV'
2761
        'JLurpnDI6VS5oqDDPVbtVjMxMxMg4rzQVipn2Bv1fVNK0iq3Gl0hhnnHKm/egy'
2762
        'nWQ7QH/F3JFOFCQ0aSPfA='
2763
        ).decode('base64')
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
2764
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
2765
    def test_repository_tarball(self):
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
2766
        # Test that Repository.tarball generates the right operations
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
2767
        transport_path = 'repo'
2018.18.14 by Martin Pool
merge hpss again; restore incorrectly removed RemoteRepository.break_lock
2768
        expected_calls = [('call_expecting_body', 'Repository.tarball',
3104.4.2 by Andrew Bennetts
All tests passing.
2769
                           ('repo/', 'bz2',),),
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
2770
            ]
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2771
        repo, client = self.setup_fake_client_and_repository(transport_path)
2772
        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
2773
        # Now actually ask for the tarball
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2774
        tarball_file = repo._get_tarball('bz2')
2018.18.25 by Martin Pool
Repository.tarball fixes for python2.4
2775
        try:
2776
            self.assertEqual(expected_calls, client._calls)
2777
            self.assertEqual(self.tarball_content, tarball_file.read())
2778
        finally:
2779
            tarball_file.close()
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
2780
2781
2782
class TestRemoteRepositoryCopyContent(tests.TestCaseWithTransport):
2783
    """RemoteRepository.copy_content_into optimizations"""
2784
2018.18.10 by Martin Pool
copy_content_into from Remote repositories by using temporary directories on both ends.
2785
    def test_copy_content_remote_to_local(self):
5017.3.28 by Vincent Ladeuil
selftest -s bt.test_remote passing
2786
        self.transport_server = test_server.SmartTCPServer_for_testing
2018.18.10 by Martin Pool
copy_content_into from Remote repositories by using temporary directories on both ends.
2787
        src_repo = self.make_repository('repo1')
2788
        src_repo = repository.Repository.open(self.get_url('repo1'))
2789
        # At the moment the tarball-based copy_content_into can't write back
2790
        # into a smart server.  It would be good if it could upload the
2791
        # tarball; once that works we'd have to create repositories of
2792
        # different formats. -- mbp 20070410
2793
        dest_url = self.get_vfs_only_url('repo2')
2794
        dest_bzrdir = BzrDir.create(dest_url)
2795
        dest_repo = dest_bzrdir.create_repository()
2796
        self.assertFalse(isinstance(dest_repo, RemoteRepository))
2797
        self.assertTrue(isinstance(src_repo, RemoteRepository))
2798
        src_repo.copy_content_into(dest_repo)
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2799
2800
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
2801
class _StubRealPackRepository(object):
2802
2803
    def __init__(self, calls):
4145.1.6 by Robert Collins
More test fallout, but all caught now.
2804
        self.calls = calls
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
2805
        self._pack_collection = _StubPackCollection(calls)
2806
4145.1.6 by Robert Collins
More test fallout, but all caught now.
2807
    def is_in_write_group(self):
2808
        return False
2809
2810
    def refresh_data(self):
2811
        self.calls.append(('pack collection reload_pack_names',))
2812
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
2813
2814
class _StubPackCollection(object):
2815
2816
    def __init__(self, calls):
2817
        self.calls = calls
2818
2819
    def autopack(self):
2820
        self.calls.append(('pack collection autopack',))
2821
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2822
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
2823
class TestRemotePackRepositoryAutoPack(TestRemoteRepository):
2824
    """Tests for RemoteRepository.autopack implementation."""
2825
2826
    def test_ok(self):
2827
        """When the server returns 'ok' and there's no _real_repository, then
2828
        nothing else happens: the autopack method is done.
2829
        """
2830
        transport_path = 'quack'
2831
        repo, client = self.setup_fake_client_and_repository(transport_path)
2832
        client.add_expected_call(
3801.1.13 by Andrew Bennetts
Revert returning of pack-names from the RPC.
2833
            'PackRepository.autopack', ('quack/',), 'success', ('ok',))
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
2834
        repo.autopack()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
2835
        self.assertFinished(client)
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
2836
2837
    def test_ok_with_real_repo(self):
2838
        """When the server returns 'ok' and there is a _real_repository, then
2839
        the _real_repository's reload_pack_name's method will be called.
2840
        """
2841
        transport_path = 'quack'
2842
        repo, client = self.setup_fake_client_and_repository(transport_path)
2843
        client.add_expected_call(
2844
            'PackRepository.autopack', ('quack/',),
3801.1.13 by Andrew Bennetts
Revert returning of pack-names from the RPC.
2845
            'success', ('ok',))
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
2846
        repo._real_repository = _StubRealPackRepository(client._calls)
2847
        repo.autopack()
2848
        self.assertEqual(
2849
            [('call', 'PackRepository.autopack', ('quack/',)),
3801.1.13 by Andrew Bennetts
Revert returning of pack-names from the RPC.
2850
             ('pack collection reload_pack_names',)],
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
2851
            client._calls)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2852
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
2853
    def test_backwards_compatibility(self):
2854
        """If the server does not recognise the PackRepository.autopack verb,
2855
        fallback to the real_repository's implementation.
2856
        """
2857
        transport_path = 'quack'
2858
        repo, client = self.setup_fake_client_and_repository(transport_path)
2859
        client.add_unknown_method_response('PackRepository.autopack')
2860
        def stub_ensure_real():
2861
            client._calls.append(('_ensure_real',))
2862
            repo._real_repository = _StubRealPackRepository(client._calls)
2863
        repo._ensure_real = stub_ensure_real
2864
        repo.autopack()
2865
        self.assertEqual(
2866
            [('call', 'PackRepository.autopack', ('quack/',)),
2867
             ('_ensure_real',),
2868
             ('pack collection autopack',)],
2869
            client._calls)
2870
5677.2.2 by Martin
Give clearer message when remote server reports a MemoryError
2871
    def test_oom_error_reporting(self):
2872
        """An out-of-memory condition on the server is reported clearly"""
2873
        transport_path = 'quack'
2874
        repo, client = self.setup_fake_client_and_repository(transport_path)
2875
        client.add_expected_call(
2876
            'PackRepository.autopack', ('quack/',),
2877
            'error', ('MemoryError',))
2878
        err = self.assertRaises(errors.BzrError, repo.autopack)
2879
        self.assertContainsRe(str(err), "^remote server out of mem")
2880
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
2881
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2882
class TestErrorTranslationBase(tests.TestCaseWithMemoryTransport):
2883
    """Base class for unit tests for bzrlib.remote._translate_error."""
2884
2885
    def translateTuple(self, error_tuple, **context):
2886
        """Call _translate_error with an ErrorFromSmartServer built from the
2887
        given error_tuple.
2888
2889
        :param error_tuple: A tuple of a smart server response, as would be
2890
            passed to an ErrorFromSmartServer.
2891
        :kwargs context: context items to call _translate_error with.
2892
2893
        :returns: The error raised by _translate_error.
2894
        """
2895
        # Raise the ErrorFromSmartServer before passing it as an argument,
2896
        # because _translate_error may need to re-raise it with a bare 'raise'
2897
        # statement.
2898
        server_error = errors.ErrorFromSmartServer(error_tuple)
2899
        translated_error = self.translateErrorFromSmartServer(
2900
            server_error, **context)
2901
        return translated_error
2902
2903
    def translateErrorFromSmartServer(self, error_object, **context):
2904
        """Like translateTuple, but takes an already constructed
2905
        ErrorFromSmartServer rather than a tuple.
2906
        """
2907
        try:
2908
            raise error_object
2909
        except errors.ErrorFromSmartServer, server_error:
2910
            translated_error = self.assertRaises(
2911
                errors.BzrError, remote._translate_error, server_error,
2912
                **context)
2913
        return translated_error
2914
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
2915
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2916
class TestErrorTranslationSuccess(TestErrorTranslationBase):
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2917
    """Unit tests for bzrlib.remote._translate_error.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2918
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2919
    Given an ErrorFromSmartServer (which has an error tuple from a smart
2920
    server) and some context, _translate_error raises more specific errors from
2921
    bzrlib.errors.
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2922
2923
    This test case covers the cases where _translate_error succeeds in
2924
    translating an ErrorFromSmartServer to something better.  See
2925
    TestErrorTranslationRobustness for other cases.
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2926
    """
2927
2928
    def test_NoSuchRevision(self):
2929
        branch = self.make_branch('')
2930
        revid = 'revid'
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2931
        translated_error = self.translateTuple(
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2932
            ('NoSuchRevision', revid), branch=branch)
2933
        expected_error = errors.NoSuchRevision(branch, revid)
2934
        self.assertEqual(expected_error, translated_error)
2935
2936
    def test_nosuchrevision(self):
2937
        repository = self.make_repository('')
2938
        revid = 'revid'
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2939
        translated_error = self.translateTuple(
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2940
            ('nosuchrevision', revid), repository=repository)
2941
        expected_error = errors.NoSuchRevision(repository, revid)
2942
        self.assertEqual(expected_error, translated_error)
2943
2944
    def test_nobranch(self):
2945
        bzrdir = self.make_bzrdir('')
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2946
        translated_error = self.translateTuple(('nobranch',), bzrdir=bzrdir)
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2947
        expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
2948
        self.assertEqual(expected_error, translated_error)
2949
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
2950
    def test_nobranch_one_arg(self):
2951
        bzrdir = self.make_bzrdir('')
2952
        translated_error = self.translateTuple(
2953
            ('nobranch', 'extra detail'), bzrdir=bzrdir)
2954
        expected_error = errors.NotBranchError(
2955
            path=bzrdir.root_transport.base,
2956
            detail='extra detail')
2957
        self.assertEqual(expected_error, translated_error)
2958
5677.2.5 by Martin
Add more tests for remote._translate_error including for MemoryError handling
2959
    def test_norepository(self):
2960
        bzrdir = self.make_bzrdir('')
2961
        translated_error = self.translateTuple(('norepository',),
2962
            bzrdir=bzrdir)
2963
        expected_error = errors.NoRepositoryPresent(bzrdir)
2964
        self.assertEqual(expected_error, translated_error)
2965
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2966
    def test_LockContention(self):
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2967
        translated_error = self.translateTuple(('LockContention',))
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2968
        expected_error = errors.LockContention('(remote lock)')
2969
        self.assertEqual(expected_error, translated_error)
2970
2971
    def test_UnlockableTransport(self):
2972
        bzrdir = self.make_bzrdir('')
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2973
        translated_error = self.translateTuple(
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2974
            ('UnlockableTransport',), bzrdir=bzrdir)
2975
        expected_error = errors.UnlockableTransport(bzrdir.root_transport)
2976
        self.assertEqual(expected_error, translated_error)
2977
2978
    def test_LockFailed(self):
2979
        lock = 'str() of a server lock'
2980
        why = 'str() of why'
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2981
        translated_error = self.translateTuple(('LockFailed', lock, why))
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2982
        expected_error = errors.LockFailed(lock, why)
2983
        self.assertEqual(expected_error, translated_error)
2984
2985
    def test_TokenMismatch(self):
2986
        token = 'a lock token'
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2987
        translated_error = self.translateTuple(('TokenMismatch',), token=token)
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2988
        expected_error = errors.TokenMismatch(token, '(remote token)')
2989
        self.assertEqual(expected_error, translated_error)
2990
2991
    def test_Diverged(self):
2992
        branch = self.make_branch('a')
2993
        other_branch = self.make_branch('b')
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
2994
        translated_error = self.translateTuple(
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
2995
            ('Diverged',), branch=branch, other_branch=other_branch)
2996
        expected_error = errors.DivergedBranches(branch, other_branch)
2997
        self.assertEqual(expected_error, translated_error)
2998
5677.2.5 by Martin
Add more tests for remote._translate_error including for MemoryError handling
2999
    def test_NotStacked(self):
3000
        branch = self.make_branch('')
3001
        translated_error = self.translateTuple(('NotStacked',), branch=branch)
3002
        expected_error = errors.NotStacked(branch)
3003
        self.assertEqual(expected_error, translated_error)
3004
3786.4.2 by Andrew Bennetts
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
3005
    def test_ReadError_no_args(self):
3006
        path = 'a path'
3007
        translated_error = self.translateTuple(('ReadError',), path=path)
3008
        expected_error = errors.ReadError(path)
3009
        self.assertEqual(expected_error, translated_error)
3010
3011
    def test_ReadError(self):
3012
        path = 'a path'
3013
        translated_error = self.translateTuple(('ReadError', path))
3014
        expected_error = errors.ReadError(path)
3015
        self.assertEqual(expected_error, translated_error)
3016
4650.2.1 by Robert Collins
Deserialise IncompatibleRepositories errors in the client, generating
3017
    def test_IncompatibleRepositories(self):
3018
        translated_error = self.translateTuple(('IncompatibleRepositories',
3019
            "repo1", "repo2", "details here"))
3020
        expected_error = errors.IncompatibleRepositories("repo1", "repo2",
3021
            "details here")
3022
        self.assertEqual(expected_error, translated_error)
3023
3786.4.2 by Andrew Bennetts
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
3024
    def test_PermissionDenied_no_args(self):
3025
        path = 'a path'
5677.2.5 by Martin
Add more tests for remote._translate_error including for MemoryError handling
3026
        translated_error = self.translateTuple(('PermissionDenied',),
3027
            path=path)
3786.4.2 by Andrew Bennetts
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
3028
        expected_error = errors.PermissionDenied(path)
3029
        self.assertEqual(expected_error, translated_error)
3030
3031
    def test_PermissionDenied_one_arg(self):
3032
        path = 'a path'
3033
        translated_error = self.translateTuple(('PermissionDenied', path))
3034
        expected_error = errors.PermissionDenied(path)
3035
        self.assertEqual(expected_error, translated_error)
3036
3037
    def test_PermissionDenied_one_arg_and_context(self):
3038
        """Given a choice between a path from the local context and a path on
3039
        the wire, _translate_error prefers the path from the local context.
3040
        """
3041
        local_path = 'local path'
3042
        remote_path = 'remote path'
3043
        translated_error = self.translateTuple(
3044
            ('PermissionDenied', remote_path), path=local_path)
3045
        expected_error = errors.PermissionDenied(local_path)
3046
        self.assertEqual(expected_error, translated_error)
3047
3048
    def test_PermissionDenied_two_args(self):
3049
        path = 'a path'
3050
        extra = 'a string with extra info'
3051
        translated_error = self.translateTuple(
3052
            ('PermissionDenied', path, extra))
3053
        expected_error = errors.PermissionDenied(path, extra)
3054
        self.assertEqual(expected_error, translated_error)
3055
5677.2.5 by Martin
Add more tests for remote._translate_error including for MemoryError handling
3056
    # GZ 2011-03-02: TODO test for PermissionDenied with non-ascii 'extra'
3057
3058
    def test_NoSuchFile_context_path(self):
3059
        local_path = "local path"
3060
        translated_error = self.translateTuple(('ReadError', "remote path"),
3061
            path=local_path)
3062
        expected_error = errors.ReadError(local_path)
3063
        self.assertEqual(expected_error, translated_error)
3064
3065
    def test_NoSuchFile_without_context(self):
3066
        remote_path = "remote path"
3067
        translated_error = self.translateTuple(('ReadError', remote_path))
3068
        expected_error = errors.ReadError(remote_path)
3069
        self.assertEqual(expected_error, translated_error)
3070
3071
    def test_ReadOnlyError(self):
3072
        translated_error = self.translateTuple(('ReadOnlyError',))
3073
        expected_error = errors.TransportNotPossible("readonly transport")
3074
        self.assertEqual(expected_error, translated_error)
3075
3076
    def test_MemoryError(self):
3077
        translated_error = self.translateTuple(('MemoryError',))
5677.2.9 by Martin
Add hint to possible ways forward for user in remote MemoryError message
3078
        self.assertStartsWith(str(translated_error),
3079
            "remote server out of memory")
5677.2.5 by Martin
Add more tests for remote._translate_error including for MemoryError handling
3080
5677.2.8 by Martin
More tests for handling of unexpected remote errors
3081
    def test_generic_IndexError_no_classname(self):
5677.2.5 by Martin
Add more tests for remote._translate_error including for MemoryError handling
3082
        err = errors.ErrorFromSmartServer(('error', "list index out of range"))
3083
        translated_error = self.translateErrorFromSmartServer(err)
3084
        expected_error = errors.UnknownErrorFromSmartServer(err)
3085
        self.assertEqual(expected_error, translated_error)
3086
3087
    # GZ 2011-03-02: TODO test generic non-ascii error string
3088
5677.2.8 by Martin
More tests for handling of unexpected remote errors
3089
    def test_generic_KeyError(self):
3090
        err = errors.ErrorFromSmartServer(('error', 'KeyError', "1"))
3091
        translated_error = self.translateErrorFromSmartServer(err)
3092
        expected_error = errors.UnknownErrorFromSmartServer(err)
3093
        self.assertEqual(expected_error, translated_error)
3094
3786.4.2 by Andrew Bennetts
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
3095
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3096
class TestErrorTranslationRobustness(TestErrorTranslationBase):
3097
    """Unit tests for bzrlib.remote._translate_error's robustness.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3098
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3099
    TestErrorTranslationSuccess is for cases where _translate_error can
3100
    translate successfully.  This class about how _translate_err behaves when
3101
    it fails to translate: it re-raises the original error.
3102
    """
3103
3104
    def test_unrecognised_server_error(self):
3105
        """If the error code from the server is not recognised, the original
3106
        ErrorFromSmartServer is propagated unmodified.
3107
        """
3108
        error_tuple = ('An unknown error tuple',)
3690.1.2 by Andrew Bennetts
Rename UntranslateableErrorFromSmartServer -> UnknownErrorFromSmartServer.
3109
        server_error = errors.ErrorFromSmartServer(error_tuple)
3110
        translated_error = self.translateErrorFromSmartServer(server_error)
3111
        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.
3112
        self.assertEqual(expected_error, translated_error)
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3113
3114
    def test_context_missing_a_key(self):
3115
        """In case of a bug in the client, or perhaps an unexpected response
3116
        from a server, _translate_error returns the original error tuple from
3117
        the server and mutters a warning.
3118
        """
3119
        # To translate a NoSuchRevision error _translate_error needs a 'branch'
3120
        # in the context dict.  So let's give it an empty context dict instead
3121
        # to exercise its error recovery.
3122
        empty_context = {}
3123
        error_tuple = ('NoSuchRevision', 'revid')
3124
        server_error = errors.ErrorFromSmartServer(error_tuple)
3125
        translated_error = self.translateErrorFromSmartServer(server_error)
3126
        self.assertEqual(server_error, translated_error)
3127
        # In addition to re-raising ErrorFromSmartServer, some debug info has
3128
        # been muttered to the log file for developer to look at.
3129
        self.assertContainsRe(
4794.1.15 by Robert Collins
Review feedback.
3130
            self.get_log(),
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3131
            "Missing key 'branch' in context")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3132
3786.4.2 by Andrew Bennetts
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
3133
    def test_path_missing(self):
3134
        """Some translations (PermissionDenied, ReadError) can determine the
3135
        'path' variable from either the wire or the local context.  If neither
3136
        has it, then an error is raised.
3137
        """
3138
        error_tuple = ('ReadError',)
3139
        server_error = errors.ErrorFromSmartServer(error_tuple)
3140
        translated_error = self.translateErrorFromSmartServer(server_error)
3141
        self.assertEqual(server_error, translated_error)
3142
        # In addition to re-raising ErrorFromSmartServer, some debug info has
3143
        # been muttered to the log file for developer to look at.
4794.1.15 by Robert Collins
Review feedback.
3144
        self.assertContainsRe(self.get_log(), "Missing key 'path' in context")
3786.4.2 by Andrew Bennetts
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
3145
3691.2.2 by Martin Pool
Fix some problems in access to stacked repositories over hpss (#261315)
3146
3147
class TestStacking(tests.TestCaseWithTransport):
3148
    """Tests for operations on stacked remote repositories.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3149
3691.2.2 by Martin Pool
Fix some problems in access to stacked repositories over hpss (#261315)
3150
    The underlying format type must support stacking.
3151
    """
3152
3153
    def test_access_stacked_remote(self):
3154
        # based on <http://launchpad.net/bugs/261315>
3155
        # make a branch stacked on another repository containing an empty
3156
        # revision, then open it over hpss - we should be able to see that
3157
        # revision.
3158
        base_transport = self.get_transport()
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3159
        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)
3160
        base_builder.start_series()
3161
        base_revid = base_builder.build_snapshot('rev-id', None,
3162
            [('add', ('', None, 'directory', None))],
3163
            'message')
3164
        base_builder.finish_series()
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3165
        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)
3166
        stacked_branch.set_stacked_on_url('../base')
3167
        # start a server looking at this
5017.3.28 by Vincent Ladeuil
selftest -s bt.test_remote passing
3168
        smart_server = test_server.SmartTCPServer_for_testing()
4659.1.3 by Robert Collins
Review feedback.
3169
        self.start_server(smart_server)
3691.2.2 by Martin Pool
Fix some problems in access to stacked repositories over hpss (#261315)
3170
        remote_bzrdir = BzrDir.open(smart_server.get_url() + '/stacked')
3171
        # can get its branch and repository
3172
        remote_branch = remote_bzrdir.open_branch()
3173
        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
3174
        remote_repo.lock_read()
3175
        try:
3176
            # it should have an appropriate fallback repository, which should also
3177
            # be a RemoteRepository
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
3178
            self.assertLength(1, remote_repo._fallback_repositories)
3691.2.6 by Martin Pool
Disable RemoteBranch stacking, but get get_stacked_on_url working, and passing back exceptions
3179
            self.assertIsInstance(remote_repo._fallback_repositories[0],
3180
                RemoteRepository)
3181
            # and it has the revision committed to the underlying repository;
3182
            # these have varying implementations so we try several of them
3183
            self.assertTrue(remote_repo.has_revisions([base_revid]))
3184
            self.assertTrue(remote_repo.has_revision(base_revid))
3185
            self.assertEqual(remote_repo.get_revision(base_revid).message,
3186
                'message')
3187
        finally:
3188
            remote_repo.unlock()
3835.1.2 by Aaron Bentley
Add tests for get_parent_map
3189
3835.1.7 by Aaron Bentley
Updates from review
3190
    def prepare_stacked_remote_branch(self):
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3191
        """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.
3192
        self.setup_smart_server_with_call_log()
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3193
        tree1 = self.make_branch_and_tree('tree1', format='1.9')
3835.1.2 by Aaron Bentley
Add tests for get_parent_map
3194
        tree1.commit('rev1', rev_id='rev1')
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3195
        tree2 = tree1.branch.bzrdir.sprout('tree2', stacked=True
3196
            ).open_workingtree()
4595.4.4 by Robert Collins
Disable committing directly to stacked branches from lightweight checkouts.
3197
        local_tree = tree2.branch.create_checkout('local')
3198
        local_tree.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.
3199
        branch2 = Branch.open(self.get_url('tree2'))
3835.1.2 by Aaron Bentley
Add tests for get_parent_map
3200
        branch2.lock_read()
3201
        self.addCleanup(branch2.unlock)
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3202
        return tree1.branch, branch2
3835.1.7 by Aaron Bentley
Updates from review
3203
3204
    def test_stacked_get_parent_map(self):
3205
        # 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.
3206
        _, branch = self.prepare_stacked_remote_branch()
3835.1.7 by Aaron Bentley
Updates from review
3207
        repo = branch.repository
3835.1.2 by Aaron Bentley
Add tests for get_parent_map
3208
        self.assertEqual(['rev1'], repo.get_parent_map(['rev1']).keys())
3835.1.7 by Aaron Bentley
Updates from review
3209
3835.1.10 by Aaron Bentley
Move CachingExtraParentsProvider to Graph
3210
    def test_unstacked_get_parent_map(self):
3211
        # _unstacked_provider.get_parent_map ignores stacking
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3212
        _, branch = self.prepare_stacked_remote_branch()
3835.1.10 by Aaron Bentley
Move CachingExtraParentsProvider to Graph
3213
        provider = branch.repository._unstacked_provider
3835.1.8 by Aaron Bentley
Make UnstackedParentsProvider manage the cache
3214
        self.assertEqual([], provider.get_parent_map(['rev1']).keys())
3834.3.3 by John Arbash Meinel
Merge bzr.dev, resolve conflict in tests.
3215
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3216
    def fetch_stream_to_rev_order(self, stream):
3217
        result = []
3218
        for kind, substream in stream:
3219
            if not kind == 'revisions':
3220
                list(substream)
3221
            else:
3222
                for content in substream:
3223
                    result.append(content.key[-1])
3224
        return result
3225
4577.1.1 by Robert Collins
Fix fetching from smart servers where there is a chain of stacked repositories rather than a single stacking point. (Robert Collins, bug #406597)
3226
    def get_ordered_revs(self, format, order, branch_factory=None):
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3227
        """Get a list of the revisions in a stream to format format.
3228
3229
        :param format: The format of the target.
3230
        :param order: the order that target should have requested.
4577.1.1 by Robert Collins
Fix fetching from smart servers where there is a chain of stacked repositories rather than a single stacking point. (Robert Collins, bug #406597)
3231
        :param branch_factory: A callable to create a trunk and stacked branch
3232
            to fetch from. If none, self.prepare_stacked_remote_branch is used.
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3233
        :result: The revision ids in the stream, in the order seen,
3234
            the topological order of revisions in the source.
3235
        """
3236
        unordered_format = bzrdir.format_registry.get(format)()
3237
        target_repository_format = unordered_format.repository_format
3238
        # Cross check
3239
        self.assertEqual(order, target_repository_format._fetch_order)
4577.1.1 by Robert Collins
Fix fetching from smart servers where there is a chain of stacked repositories rather than a single stacking point. (Robert Collins, bug #406597)
3240
        if branch_factory is None:
3241
            branch_factory = self.prepare_stacked_remote_branch
3242
        _, stacked = branch_factory()
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3243
        source = stacked.repository._get_source(target_repository_format)
3244
        tip = stacked.last_revision()
3245
        revs = stacked.repository.get_ancestry(tip)
3246
        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.
3247
        self.reset_smart_call_log()
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3248
        stream = source.get_stream(search)
3249
        if None in revs:
3250
            revs.remove(None)
3251
        # We trust that if a revision is in the stream the rest of the new
3252
        # content for it is too, as per our main fetch tests; here we are
3253
        # checking that the revisions are actually included at all, and their
3254
        # order.
3255
        return self.fetch_stream_to_rev_order(stream), revs
3256
3257
    def test_stacked_get_stream_unordered(self):
3258
        # Repository._get_source.get_stream() from a stacked repository with
3259
        # unordered yields the full data from both stacked and stacked upon
3260
        # sources.
3261
        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.
3262
        self.assertEqual(set(expected_revs), set(rev_ord))
3263
        # Getting unordered results should have made a streaming data request
3264
        # from the server, then one from the backing branch.
3265
        self.assertLength(2, self.hpss_calls)
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3266
4577.1.1 by Robert Collins
Fix fetching from smart servers where there is a chain of stacked repositories rather than a single stacking point. (Robert Collins, bug #406597)
3267
    def test_stacked_on_stacked_get_stream_unordered(self):
3268
        # Repository._get_source.get_stream() from a stacked repository which
3269
        # is itself stacked yields the full data from all three sources.
3270
        def make_stacked_stacked():
3271
            _, stacked = self.prepare_stacked_remote_branch()
3272
            tree = stacked.bzrdir.sprout('tree3', stacked=True
3273
                ).open_workingtree()
4595.4.4 by Robert Collins
Disable committing directly to stacked branches from lightweight checkouts.
3274
            local_tree = tree.branch.create_checkout('local-tree3')
3275
            local_tree.commit('more local changes are better')
4577.1.1 by Robert Collins
Fix fetching from smart servers where there is a chain of stacked repositories rather than a single stacking point. (Robert Collins, bug #406597)
3276
            branch = Branch.open(self.get_url('tree3'))
3277
            branch.lock_read()
4857.2.3 by John Arbash Meinel
Found the failed-to-unlocked branches in test_remote.
3278
            self.addCleanup(branch.unlock)
4577.1.1 by Robert Collins
Fix fetching from smart servers where there is a chain of stacked repositories rather than a single stacking point. (Robert Collins, bug #406597)
3279
            return None, branch
3280
        rev_ord, expected_revs = self.get_ordered_revs('1.9', 'unordered',
3281
            branch_factory=make_stacked_stacked)
3282
        self.assertEqual(set(expected_revs), set(rev_ord))
3283
        # Getting unordered results should have made a streaming data request
3284
        # from the server, and one from each backing repo
3285
        self.assertLength(3, self.hpss_calls)
3286
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3287
    def test_stacked_get_stream_topological(self):
3288
        # Repository._get_source.get_stream() from a stacked repository with
3289
        # topological sorting yields the full data from both stacked and
3290
        # stacked upon sources in topological order.
3291
        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.
3292
        self.assertEqual(expected_revs, rev_ord)
4595.4.4 by Robert Collins
Disable committing directly to stacked branches from lightweight checkouts.
3293
        # Getting topological sort requires VFS calls still - one of which is
3294
        # pushing up from the bound branch.
3295
        self.assertLength(13, self.hpss_calls)
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3296
3297
    def test_stacked_get_stream_groupcompress(self):
3298
        # Repository._get_source.get_stream() from a stacked repository with
3299
        # groupcompress sorting yields the full data from both stacked and
3300
        # stacked upon sources in groupcompress order.
3301
        raise tests.TestSkipped('No groupcompress ordered format available')
3302
        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.
3303
        self.assertEqual(expected_revs, reversed(rev_ord))
3304
        # Getting unordered results should have made a streaming data request
3305
        # from the backing branch, and one from the stacked on branch.
3306
        self.assertLength(2, self.hpss_calls)
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3307
4332.2.1 by Robert Collins
Fix bug 360791 by not raising an error when a smart server is asked for more content than it has locally; the client is assumed to be monitoring what it gets.
3308
    def test_stacked_pull_more_than_stacking_has_bug_360791(self):
3309
        # When pulling some fixed amount of content that is more than the
3310
        # source has (because some is coming from a fallback branch, no error
3311
        # should be received. This was reported as bug 360791.
3312
        # Need three branches: a trunk, a stacked branch, and a preexisting
3313
        # branch pulling content from stacked and trunk.
3314
        self.setup_smart_server_with_call_log()
3315
        trunk = self.make_branch_and_tree('trunk', format="1.9-rich-root")
3316
        r1 = trunk.commit('start')
3317
        stacked_branch = trunk.branch.create_clone_on_transport(
3318
            self.get_transport('stacked'), stacked_on=trunk.branch.base)
3319
        local = self.make_branch('local', format='1.9-rich-root')
3320
        local.repository.fetch(stacked_branch.repository,
3321
            stacked_branch.last_revision())
3322
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.
3323
3324
class TestRemoteBranchEffort(tests.TestCaseWithTransport):
3325
3326
    def setUp(self):
3327
        super(TestRemoteBranchEffort, self).setUp()
3328
        # Create a smart server that publishes whatever the backing VFS server
3329
        # does.
5017.3.28 by Vincent Ladeuil
selftest -s bt.test_remote passing
3330
        self.smart_server = test_server.SmartTCPServer_for_testing()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
3331
        self.start_server(self.smart_server, self.get_server())
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.
3332
        # Log all HPSS calls into self.hpss_calls.
3333
        _SmartClient.hooks.install_named_hook(
3334
            'call', self.capture_hpss_call, None)
3335
        self.hpss_calls = []
3336
3337
    def capture_hpss_call(self, params):
3338
        self.hpss_calls.append(params.method)
3339
3340
    def test_copy_content_into_avoids_revision_history(self):
3341
        local = self.make_branch('local')
5539.2.5 by Andrew Bennetts
Add test to test_remote, fix another shallow bug.
3342
        builder = self.make_branch_builder('remote')
3343
        builder.build_commit(message="Commit.")
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.
3344
        remote_branch_url = self.smart_server.get_url() + 'remote'
3345
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3346
        local.repository.fetch(remote_branch.repository)
3347
        self.hpss_calls = []
3348
        remote_branch.copy_content_into(local)
3834.3.3 by John Arbash Meinel
Merge bzr.dev, resolve conflict in tests.
3349
        self.assertFalse('Branch.revision_history' in self.hpss_calls)
5539.2.5 by Andrew Bennetts
Add test to test_remote, fix another shallow bug.
3350
5539.2.6 by Andrew Bennetts
Better test name.
3351
    def test_fetch_everything_needs_just_one_call(self):
5539.2.5 by Andrew Bennetts
Add test to test_remote, fix another shallow bug.
3352
        local = self.make_branch('local')
3353
        builder = self.make_branch_builder('remote')
3354
        builder.build_commit(message="Commit.")
3355
        remote_branch_url = self.smart_server.get_url() + 'remote'
3356
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3357
        self.hpss_calls = []
3358
        local.repository.fetch(remote_branch.repository,
3359
                fetch_spec=graph.EverythingResult(remote_branch.repository))
5539.2.14 by Andrew Bennetts
Don't add a new verb; instead just teach the client to fallback if it gets a BadSearch error.
3360
        self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
5539.2.13 by Andrew Bennetts
Add a test for compatibility with pre-2.3 servers.
3361
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
3362
    def override_verb(self, verb_name, verb):
3363
        request_handlers = request.request_handlers
3364
        orig_verb = request_handlers.get(verb_name)
3365
        request_handlers.register(verb_name, verb, override_existing=True)
3366
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
3367
                override_existing=True)
3368
5539.2.13 by Andrew Bennetts
Add a test for compatibility with pre-2.3 servers.
3369
    def test_fetch_everything_backwards_compat(self):
5536.3.3 by Andrew Bennetts
Merge lp:bzr.
3370
        """Can fetch with EverythingResult even with pre 2.4 servers.
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
3371
        
5536.3.3 by Andrew Bennetts
Merge lp:bzr.
3372
        Pre-2.4 do not support 'everything' searches with the
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
3373
        Repository.get_stream_1.19 verb.
5539.2.13 by Andrew Bennetts
Add a test for compatibility with pre-2.3 servers.
3374
        """
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
3375
        verb_log = []
3376
        class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
3377
            """A version of the Repository.get_stream_1.19 verb patched to
5536.3.3 by Andrew Bennetts
Merge lp:bzr.
3378
            reject 'everything' searches the way 2.3 and earlier do.
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
3379
            """
3380
            def recreate_search(self, repository, search_bytes, discard_excess=False):
3381
                verb_log.append(search_bytes.split('\n', 1)[0])
3382
                if search_bytes == 'everything':
3383
                    return (None, request.FailedSmartServerResponse(('BadSearch',)))
3384
                return super(OldGetStreamVerb,
3385
                        self).recreate_search(repository, search_bytes,
3386
                            discard_excess=discard_excess)
3387
        self.override_verb('Repository.get_stream_1.19', OldGetStreamVerb)
5539.2.13 by Andrew Bennetts
Add a test for compatibility with pre-2.3 servers.
3388
        local = self.make_branch('local')
3389
        builder = self.make_branch_builder('remote')
3390
        builder.build_commit(message="Commit.")
3391
        remote_branch_url = self.smart_server.get_url() + 'remote'
3392
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3393
        self.hpss_calls = []
3394
        local.repository.fetch(remote_branch.repository,
3395
                fetch_spec=graph.EverythingResult(remote_branch.repository))
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
3396
        # make sure the overridden verb was used
3397
        self.assertLength(1, verb_log)
3398
        # more than one HPSS call is needed, but because it's a VFS callback
3399
        # its hard to predict exactly how many.
3400
        self.assertTrue(len(self.hpss_calls) > 1)
5539.2.13 by Andrew Bennetts
Add a test for compatibility with pre-2.3 servers.
3401