/brz/remove-bazaar

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