/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1
# Copyright (C) 2006-2013, 2016 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
6280.9.4 by Jelmer Vernooij
use zlib instead.
27
import zlib
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
28
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
29
from .. import (
6436.3.1 by Jelmer Vernooij
Add remote get_branches call.
30
    bencode,
4792.1.1 by Andrew Bennetts
Show real branch/repo format description in 'info -v' over HPSS.
31
    branch,
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,
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
35
    repository,
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
36
    tests,
5273.1.7 by Vincent Ladeuil
No more use of the get_transport imported *symbol*, all uses are through
37
    transport,
4190.1.4 by Robert Collins
Cache ghosts when we can get them from a RemoteRepository in get_parent_map.
38
    treebuilder,
6670.4.1 by Jelmer Vernooij
Update imports.
39
    )
40
from ..branch import Branch
41
from ..bzr import (
42
    bzrdir,
43
    inventory,
44
    inventory_delta,
6670.4.14 by Jelmer Vernooij
Move remote to breezy.bzr.
45
    remote,
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.
46
    versionedfile,
6341.1.4 by Jelmer Vernooij
Move more functionality to vf_search.
47
    vf_search,
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
48
    )
6670.4.1 by Jelmer Vernooij
Update imports.
49
from ..bzr.bzrdir import (
5363.2.9 by Jelmer Vernooij
Fix some tests.
50
    BzrDir,
51
    BzrDirFormat,
6695.5.1 by Jelmer Vernooij
Move bzr format registration to breezy.bzr.
52
    )
53
from ..bzr import (
5363.2.9 by Jelmer Vernooij
Fix some tests.
54
    RemoteBzrProber,
55
    )
6670.4.1 by Jelmer Vernooij
Update imports.
56
from ..bzr.chk_serializer import chk_bencode_serializer
6670.4.14 by Jelmer Vernooij
Move remote to breezy.bzr.
57
from ..bzr.remote import (
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
58
    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.
59
    RemoteBranchFormat,
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
60
    RemoteBzrDir,
5712.3.17 by Jelmer Vernooij
more fixes.
61
    RemoteBzrDirFormat,
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
62
    RemoteRepository,
4183.5.1 by Robert Collins
Add RepositoryFormat.fast_deltas to signal fast delta creation.
63
    RemoteRepositoryFormat,
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
64
    )
6670.4.5 by Jelmer Vernooij
Move breezy.repofmt contents to breezy.bzr.
65
from ..bzr import groupcompress_repo, knitpack_repo
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
66
from ..revision import (
6280.9.1 by Jelmer Vernooij
Add remote side of Repository.iter_revisions.
67
    NULL_REVISION,
68
    Revision,
69
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
70
from ..sixish import (
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
71
    BytesIO,
72
    )
6670.4.16 by Jelmer Vernooij
Move smart to breezy.bzr.
73
from ..bzr.smart import medium, request
74
from ..bzr.smart.client import _SmartClient
75
from ..bzr.smart.repository import (
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
76
    SmartServerRepositoryGetParentMap,
77
    SmartServerRepositoryGetStream_1_19,
6282.6.37 by Jelmer Vernooij
Cope with empty results.
78
    _stream_to_byte_stream,
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
79
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
80
from . import (
5017.3.28 by Vincent Ladeuil
selftest -s bt.test_remote passing
81
    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.
82
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
83
from .scenarios import load_tests_apply_scenarios
84
from ..transport.memory import MemoryTransport
85
from ..transport.remote import (
3777.1.3 by Aaron Bentley
Use SSH default username from authentication.conf
86
    RemoteTransport,
87
    RemoteSSHTransport,
88
    RemoteTCPTransport,
5579.3.1 by Jelmer Vernooij
Remove unused imports.
89
    )
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
90
5559.2.2 by Martin Pool
Change to using standard load_tests_apply_scenarios.
91
92
load_tests = load_tests_apply_scenarios
93
94
95
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
96
97
    scenarios = [
4104.4.2 by Robert Collins
Fix test_source for 1.13 landing.
98
        ('HPSS-v2',
5559.2.2 by Martin Pool
Change to using standard load_tests_apply_scenarios.
99
            {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
4104.4.2 by Robert Collins
Fix test_source for 1.13 landing.
100
        ('HPSS-v3',
5559.2.2 by Martin Pool
Change to using standard load_tests_apply_scenarios.
101
            {'transport_server': test_server.SmartTCPServer_for_testing})]
102
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
103
104
    def setUp(self):
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
105
        super(BasicRemoteObjectTests, self).setUp()
106
        self.transport = self.get_transport()
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
107
        # 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
108
        self.local_wt = BzrDir.create_standalone_workingtree('.')
4986.2.1 by Martin Pool
Remove tearDown in tests in favor of addCleanup
109
        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.
110
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
111
    def test_create_remote_bzrdir(self):
5712.3.17 by Jelmer Vernooij
more fixes.
112
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
113
        self.assertIsInstance(b, BzrDir)
114
115
    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.
116
        # open a standalone branch in the working directory
5712.3.17 by Jelmer Vernooij
more fixes.
117
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
118
        branch = b.open_branch()
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
119
        self.assertIsInstance(branch, Branch)
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
120
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
121
    def test_remote_repository(self):
122
        b = BzrDir.open_from_transport(self.transport)
123
        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.
124
        revid = u'\xc823123123'.encode('utf8')
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
125
        self.assertFalse(repo.has_revision(revid))
126
        self.local_wt.commit(message='test commit', rev_id=revid)
127
        self.assertTrue(repo.has_revision(revid))
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
128
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
129
    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)
130
        """Should open a RemoteBzrDir over a RemoteTransport"""
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
131
        fmt = BzrDirFormat.find_format(self.transport)
6695.5.3 by Jelmer Vernooij
Fix last reference to bzrdir.RemoteBzrProber.
132
        self.assertTrue(RemoteBzrProber
5363.2.9 by Jelmer Vernooij
Fix some tests.
133
                        in controldir.ControlDirFormat._server_probers)
5712.3.17 by Jelmer Vernooij
more fixes.
134
        self.assertIsInstance(fmt, RemoteBzrDirFormat)
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
135
136
    def test_open_detected_smart_format(self):
137
        fmt = BzrDirFormat.find_format(self.transport)
138
        d = fmt.open(self.transport)
139
        self.assertIsInstance(d, BzrDir)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
140
2477.1.1 by Martin Pool
Add RemoteBranch repr
141
    def test_remote_branch_repr(self):
142
        b = BzrDir.open_from_transport(self.transport).open_branch()
143
        self.assertStartsWith(str(b), 'RemoteBranch(')
144
4964.2.1 by Martin Pool
Add RemoteBzrDir repr
145
    def test_remote_bzrdir_repr(self):
146
        b = BzrDir.open_from_transport(self.transport)
147
        self.assertStartsWith(str(b), 'RemoteBzrDir(')
148
4103.2.2 by Andrew Bennetts
Fix RemoteBranchFormat.supports_stacking()
149
    def test_remote_branch_format_supports_stacking(self):
150
        t = self.transport
151
        self.make_branch('unstackable', format='pack-0.92')
152
        b = BzrDir.open_from_transport(t.clone('unstackable')).open_branch()
153
        self.assertFalse(b._format.supports_stacking())
154
        self.make_branch('stackable', format='1.9')
155
        b = BzrDir.open_from_transport(t.clone('stackable')).open_branch()
156
        self.assertTrue(b._format.supports_stacking())
157
4118.1.1 by Andrew Bennetts
Fix performance regression (many small round-trips) when pushing to a remote pack, and tidy the tests.
158
    def test_remote_repo_format_supports_external_references(self):
159
        t = self.transport
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
160
        bd = self.make_controldir('unstackable', format='pack-0.92')
4118.1.1 by Andrew Bennetts
Fix performance regression (many small round-trips) when pushing to a remote pack, and tidy the tests.
161
        r = bd.create_repository()
162
        self.assertFalse(r._format.supports_external_lookups)
163
        r = BzrDir.open_from_transport(t.clone('unstackable')).open_repository()
164
        self.assertFalse(r._format.supports_external_lookups)
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
165
        bd = self.make_controldir('stackable', format='1.9')
4118.1.1 by Andrew Bennetts
Fix performance regression (many small round-trips) when pushing to a remote pack, and tidy the tests.
166
        r = bd.create_repository()
167
        self.assertTrue(r._format.supports_external_lookups)
168
        r = BzrDir.open_from_transport(t.clone('stackable')).open_repository()
169
        self.assertTrue(r._format.supports_external_lookups)
170
4301.3.1 by Andrew Bennetts
Implement RemoteBranch.set_append_revisions_only.
171
    def test_remote_branch_set_append_revisions_only(self):
172
        # Make a format 1.9 branch, which supports append_revisions_only
173
        branch = self.make_branch('branch', format='1.9')
174
        branch.set_append_revisions_only(True)
6372.4.2 by Jelmer Vernooij
Fix remaining tests.
175
        config = branch.get_config_stack()
4301.3.1 by Andrew Bennetts
Implement RemoteBranch.set_append_revisions_only.
176
        self.assertEqual(
6372.4.1 by Jelmer Vernooij
Convert 'append_revisions_only' over to config stacks.
177
            True, config.get('append_revisions_only'))
4301.3.1 by Andrew Bennetts
Implement RemoteBranch.set_append_revisions_only.
178
        branch.set_append_revisions_only(False)
6372.4.2 by Jelmer Vernooij
Fix remaining tests.
179
        config = branch.get_config_stack()
4301.3.1 by Andrew Bennetts
Implement RemoteBranch.set_append_revisions_only.
180
        self.assertEqual(
6372.4.1 by Jelmer Vernooij
Convert 'append_revisions_only' over to config stacks.
181
            False, config.get('append_revisions_only'))
4301.3.1 by Andrew Bennetts
Implement RemoteBranch.set_append_revisions_only.
182
183
    def test_remote_branch_set_append_revisions_only_upgrade_reqd(self):
184
        branch = self.make_branch('branch', format='knit')
185
        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.
186
            errors.UpgradeRequired, branch.set_append_revisions_only, True)
4301.3.1 by Andrew Bennetts
Implement RemoteBranch.set_append_revisions_only.
187
3691.2.4 by Martin Pool
Add FakeRemoteTransport to clarify test_remote
188
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
189
class FakeProtocol(object):
190
    """Lookalike SmartClientRequestProtocolOne allowing body reading tests."""
191
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
192
    def __init__(self, body, fake_client):
2535.4.2 by Andrew Bennetts
Nasty hackery to make stream_knit_data_for_revisions response use streaming.
193
        self.body = body
194
        self._body_buffer = None
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
195
        self._fake_client = fake_client
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
196
197
    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.
198
        if self._body_buffer is None:
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
199
            self._body_buffer = BytesIO(self.body)
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
200
        bytes = self._body_buffer.read(count)
201
        if self._body_buffer.tell() == len(self._body_buffer.getvalue()):
202
            self._fake_client.expecting_body = False
203
        return bytes
204
205
    def cancel_read_body(self):
206
        self._fake_client.expecting_body = False
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
207
2535.4.2 by Andrew Bennetts
Nasty hackery to make stream_knit_data_for_revisions response use streaming.
208
    def read_streamed_body(self):
209
        return self.body
210
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
211
2018.5.159 by Andrew Bennetts
Rename SmartClient to _SmartClient.
212
class FakeClient(_SmartClient):
213
    """Lookalike for _SmartClient allowing testing."""
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
214
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
215
    def __init__(self, fake_medium_base='fake base'):
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
216
        """Create a FakeClient."""
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
217
        self.responses = []
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
218
        self._calls = []
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
219
        self.expecting_body = False
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
220
        # if non-None, this is the list of expected calls, with only the
221
        # 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.
222
        # compute so is not included. If a call is None, that call can
223
        # be anything.
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
224
        self._expected_calls = None
3431.3.2 by Andrew Bennetts
Remove 'base' from _SmartClient entirely, now that the medium has it.
225
        _SmartClient.__init__(self, FakeMedium(self._calls, fake_medium_base))
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
226
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
227
    def add_expected_call(self, call_name, call_args, response_type,
228
        response_args, response_body=None):
229
        if self._expected_calls is None:
230
            self._expected_calls = []
231
        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
232
        self.responses.append((response_type, response_args, response_body))
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
233
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
234
    def add_success_response(self, *args):
235
        self.responses.append(('success', args, None))
236
237
    def add_success_response_with_body(self, body, *args):
238
        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.
239
        if self._expected_calls is not None:
240
            self._expected_calls.append(None)
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
241
242
    def add_error_response(self, *args):
243
        self.responses.append(('error', args))
244
245
    def add_unknown_method_response(self, verb):
246
        self.responses.append(('unknown', verb))
247
4523.3.2 by Andrew Bennetts
Adjust according to Robert's review.
248
    def finished_test(self):
249
        if self._expected_calls:
250
            raise AssertionError("%r finished but was still expecting %r"
251
                % (self, self._expected_calls[0]))
252
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.
253
    def _get_next_response(self):
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
254
        try:
255
            response_tuple = self.responses.pop(0)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
256
        except IndexError as e:
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
257
            raise AssertionError("%r didn't expect any more calls"
258
                % (self,))
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
259
        if response_tuple[0] == 'unknown':
260
            raise errors.UnknownSmartMethod(response_tuple[1])
261
        elif response_tuple[0] == 'error':
262
            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.
263
        return response_tuple
264
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
265
    def _check_call(self, method, args):
266
        if self._expected_calls is None:
267
            # the test should be updated to say what it expects
268
            return
269
        try:
270
            next_call = self._expected_calls.pop(0)
271
        except IndexError:
272
            raise AssertionError("%r didn't expect any more calls "
273
                "but got %r%r"
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
274
                % (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.
275
        if next_call is None:
276
            return
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
277
        if method != next_call[0] or args != next_call[1]:
278
            raise AssertionError("%r expected %r%r "
279
                "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
280
                % (self, next_call[0], next_call[1], method, args,))
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
281
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
282
    def call(self, method, *args):
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
283
        self._check_call(method, args)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
284
        self._calls.append(('call', method, args))
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
285
        return self._get_next_response()[1]
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
286
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
287
    def call_expecting_body(self, method, *args):
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
288
        self._check_call(method, args)
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
289
        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.
290
        result = self._get_next_response()
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
291
        self.expecting_body = True
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
292
        return result[1], FakeProtocol(result[2], self)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
293
4634.36.1 by Andrew Bennetts
Fix trivial bug in RemoteBranch._set_tags_bytes, and add some unit tests for it.
294
    def call_with_body_bytes(self, method, args, body):
295
        self._check_call(method, args)
296
        self._calls.append(('call_with_body_bytes', method, args, body))
297
        result = self._get_next_response()
298
        return result[1], FakeProtocol(result[2], self)
299
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
    def call_with_body_bytes_expecting_body(self, method, args, body):
3691.2.7 by Martin Pool
FakeClient can know what calls to expect
301
        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.
302
        self._calls.append(('call_with_body_bytes_expecting_body', method,
303
            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.
304
        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.
305
        self.expecting_body = True
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
306
        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.
307
3842.3.9 by Andrew Bennetts
Backing up the stream so that we can fallback correctly.
308
    def call_with_body_stream(self, args, stream):
309
        # Explicitly consume the stream before checking for an error, because
310
        # that's what happens a real medium.
311
        stream = list(stream)
312
        self._check_call(args[0], args[1:])
313
        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.
314
        result = self._get_next_response()
4144.3.3 by Andrew Bennetts
Tweaks based on review from Robert.
315
        # The second value returned from call_with_body_stream is supposed to
316
        # be a response_handler object, but so far no tests depend on that.
317
        response_handler = None 
318
        return result[1], response_handler
3842.3.9 by Andrew Bennetts
Backing up the stream so that we can fallback correctly.
319
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
320
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
321
class FakeMedium(medium.SmartClientMedium):
3104.4.2 by Andrew Bennetts
All tests passing.
322
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.
323
    def __init__(self, client_calls, base):
3453.4.1 by Andrew Bennetts
Better infrastructure on SmartClientMedium for tracking the remote version.
324
        medium.SmartClientMedium.__init__(self, base)
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
325
        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.
326
327
    def disconnect(self):
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
328
        self._client_calls.append(('disconnect medium',))
3104.4.2 by Andrew Bennetts
All tests passing.
329
330
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
class TestVfsHas(tests.TestCase):
332
333
    def test_unicode_path(self):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
334
        client = FakeClient('/')
335
        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.
336
        transport = RemoteTransport('bzr://localhost/', _client=client)
337
        filename = u'/hell\u00d8'.encode('utf8')
338
        result = transport.has(filename)
339
        self.assertEqual(
340
            [('call', 'has', (filename,))],
341
            client._calls)
342
        self.assertTrue(result)
343
344
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
345
class TestRemote(tests.TestCaseWithMemoryTransport):
4032.1.1 by John Arbash Meinel
Merge the removal of all trailing whitespace, and resolve conflicts.
346
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.
347
    def get_branch_format(self):
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
348
        reference_bzrdir_format = controldir.format_registry.get('default')()
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.
349
        return reference_bzrdir_format.get_branch_format()
350
4053.1.2 by Robert Collins
Actually make this branch work.
351
    def get_repo_format(self):
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
352
        reference_bzrdir_format = controldir.format_registry.get('default')()
4053.1.2 by Robert Collins
Actually make this branch work.
353
        return reference_bzrdir_format.repository_format
354
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
355
    def assertFinished(self, fake_client):
356
        """Assert that all of a FakeClient's expected calls have occurred."""
4523.3.2 by Andrew Bennetts
Adjust according to Robert's review.
357
        fake_client.finished_test()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
358
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
359
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
360
class Test_ClientMedium_remote_path_from_transport(tests.TestCase):
361
    """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.
362
363
    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.
364
        """Assert that the result of
365
        SmartClientMedium.remote_path_from_transport is the expected value for
366
        a given client_base and transport_base.
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
367
        """
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
368
        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
369
        t = transport.get_transport(transport_base)
370
        result = client_medium.remote_path_from_transport(t)
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
371
        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.
372
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
373
    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.
374
        """SmartClientMedium.remote_path_from_transport calculates a URL for
375
        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.
376
        """
377
        self.assertRemotePath('xyz/', 'bzr://host/path', 'bzr://host/xyz')
378
        self.assertRemotePath(
379
            'path/xyz/', 'bzr://host/path', 'bzr://host/path/xyz')
380
3431.3.11 by Andrew Bennetts
Push remote_path_from_transport logic into SmartClientMedium, removing special-casing of bzr+http from _SmartClient.
381
    def assertRemotePathHTTP(self, expected, transport_base, relpath):
382
        """Assert that the result of
383
        HttpTransportBase.remote_path_from_transport is the expected value for
384
        a given transport_base and relpath of that transport.  (Note that
385
        HttpTransportBase is a subclass of SmartClientMedium)
386
        """
5273.1.7 by Vincent Ladeuil
No more use of the get_transport imported *symbol*, all uses are through
387
        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.
388
        client_medium = base_transport.get_smart_medium()
389
        cloned_transport = base_transport.clone(relpath)
390
        result = client_medium.remote_path_from_transport(cloned_transport)
391
        self.assertEqual(expected, result)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
392
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
393
    def test_remote_path_from_transport_http(self):
394
        """Remote paths for HTTP transports are calculated differently to other
395
        transports.  They are just relative to the client base, not the root
396
        directory of the host.
397
        """
398
        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.
399
            self.assertRemotePathHTTP(
400
                '../xyz/', scheme + '//host/path', '../xyz/')
401
            self.assertRemotePathHTTP(
402
                'xyz/', scheme + '//host/path', 'xyz/')
3313.3.3 by Andrew Bennetts
Add tests for _SmartClient.remote_path_for_transport.
403
404
3453.4.1 by Andrew Bennetts
Better infrastructure on SmartClientMedium for tracking the remote version.
405
class Test_ClientMedium_remote_is_at_least(tests.TestCase):
406
    """Tests for the behaviour of client_medium.remote_is_at_least."""
407
408
    def test_initially_unlimited(self):
409
        """A fresh medium assumes that the remote side supports all
410
        versions.
411
        """
412
        client_medium = medium.SmartClientMedium('dummy base')
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
413
        self.assertFalse(client_medium._is_remote_before((99, 99)))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
414
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
415
    def test__remember_remote_is_before(self):
416
        """Calling _remember_remote_is_before ratchets down the known remote
417
        version.
418
        """
3453.4.1 by Andrew Bennetts
Better infrastructure on SmartClientMedium for tracking the remote version.
419
        client_medium = medium.SmartClientMedium('dummy base')
420
        # Mark the remote side as being less than 1.6.  The remote side may
421
        # still be 1.5.
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
422
        client_medium._remember_remote_is_before((1, 6))
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
423
        self.assertTrue(client_medium._is_remote_before((1, 6)))
424
        self.assertFalse(client_medium._is_remote_before((1, 5)))
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
425
        # Calling _remember_remote_is_before again with a lower value works.
426
        client_medium._remember_remote_is_before((1, 5))
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
427
        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.
428
        # If you call _remember_remote_is_before with a higher value it logs a
429
        # 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.
430
        self.assertNotContainsRe(self.get_log(), '_remember_remote_is_before')
431
        client_medium._remember_remote_is_before((1, 9))
432
        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.
433
        self.assertTrue(client_medium._is_remote_before((1, 5)))
3453.4.1 by Andrew Bennetts
Better infrastructure on SmartClientMedium for tracking the remote version.
434
435
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
436
class TestBzrDirCloningMetaDir(TestRemote):
437
438
    def test_backwards_compat(self):
439
        self.setup_smart_server_with_call_log()
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
440
        a_dir = self.make_controldir('.')
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
441
        self.reset_smart_call_log()
442
        verb = 'BzrDir.cloning_metadir'
443
        self.disable_verb(verb)
444
        format = a_dir.cloning_metadir()
445
        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.
446
            call.call.method == verb])
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
447
        self.assertEqual(1, call_count)
448
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
449
    def test_branch_reference(self):
450
        transport = self.get_transport('quack')
451
        referenced = self.make_branch('referenced')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
452
        expected = referenced.controldir.cloning_metadir()
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
453
        client = FakeClient(transport.base)
454
        client.add_expected_call(
455
            'BzrDir.cloning_metadir', ('quack/', 'False'),
456
            'error', ('BranchReference',)),
457
        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).
458
            'BzrDir.open_branchV3', ('quack/',),
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
459
            'success', ('ref', self.get_url('referenced'))),
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
460
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
461
            _client=client)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
462
        result = a_controldir.cloning_metadir()
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
463
        # We should have got a control dir matching the referenced branch.
464
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
465
        self.assertEqual(expected._repository_format, result._repository_format)
466
        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.
467
        self.assertFinished(client)
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
468
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
469
    def test_current_server(self):
470
        transport = self.get_transport('.')
471
        transport = transport.clone('quack')
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
472
        self.make_controldir('quack')
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
473
        client = FakeClient(transport.base)
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
474
        reference_bzrdir_format = controldir.format_registry.get('default')()
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
475
        control_name = reference_bzrdir_format.network_name()
476
        client.add_expected_call(
477
            'BzrDir.cloning_metadir', ('quack/', 'False'),
4084.2.2 by Robert Collins
Review feedback.
478
            'success', (control_name, '', ('branch', ''))),
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
479
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
480
            _client=client)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
481
        result = a_controldir.cloning_metadir()
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
482
        # We should have got a reference control dir with default branch and
483
        # repository formats.
484
        # This pokes a little, just to be sure.
485
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
4070.2.8 by Robert Collins
Really test the current BzrDir.cloning_metadir contract.
486
        self.assertEqual(None, result._repository_format)
487
        self.assertEqual(None, result._branch_format)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
488
        self.assertFinished(client)
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
489
6305.4.1 by Jelmer Vernooij
Print sensible error message when remote format is unknown.
490
    def test_unknown(self):
491
        transport = self.get_transport('quack')
492
        referenced = self.make_branch('referenced')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
493
        expected = referenced.controldir.cloning_metadir()
6305.4.1 by Jelmer Vernooij
Print sensible error message when remote format is unknown.
494
        client = FakeClient(transport.base)
495
        client.add_expected_call(
496
            'BzrDir.cloning_metadir', ('quack/', 'False'),
497
            'success', ('unknown', 'unknown', ('branch', ''))),
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
498
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
6305.4.1 by Jelmer Vernooij
Print sensible error message when remote format is unknown.
499
            _client=client)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
500
        self.assertRaises(errors.UnknownFormatError, a_controldir.cloning_metadir)
6305.4.1 by Jelmer Vernooij
Print sensible error message when remote format is unknown.
501
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
502
6305.5.10 by Jelmer Vernooij
Move to BzrDir.checkout_metadir.
503
class TestBzrDirCheckoutMetaDir(TestRemote):
504
505
    def test__get_checkout_format(self):
506
        transport = MemoryTransport()
507
        client = FakeClient(transport.base)
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
508
        reference_bzrdir_format = controldir.format_registry.get('default')()
6305.5.10 by Jelmer Vernooij
Move to BzrDir.checkout_metadir.
509
        control_name = reference_bzrdir_format.network_name()
510
        client.add_expected_call(
511
            'BzrDir.checkout_metadir', ('quack/', ),
512
            'success', (control_name, '', ''))
513
        transport.mkdir('quack')
514
        transport = transport.clone('quack')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
515
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
6305.5.10 by Jelmer Vernooij
Move to BzrDir.checkout_metadir.
516
            _client=client)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
517
        result = a_controldir.checkout_metadir()
6305.5.10 by Jelmer Vernooij
Move to BzrDir.checkout_metadir.
518
        # We should have got a reference control dir with default branch and
519
        # repository formats.
520
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
521
        self.assertEqual(None, result._repository_format)
522
        self.assertEqual(None, result._branch_format)
523
        self.assertFinished(client)
524
525
    def test_unknown_format(self):
526
        transport = MemoryTransport()
527
        client = FakeClient(transport.base)
528
        client.add_expected_call(
529
            'BzrDir.checkout_metadir', ('quack/',),
530
            'success', ('dontknow', '', ''))
531
        transport.mkdir('quack')
532
        transport = transport.clone('quack')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
533
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
6305.5.10 by Jelmer Vernooij
Move to BzrDir.checkout_metadir.
534
            _client=client)
535
        self.assertRaises(errors.UnknownFormatError,
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
536
            a_controldir.checkout_metadir)
6305.5.10 by Jelmer Vernooij
Move to BzrDir.checkout_metadir.
537
        self.assertFinished(client)
538
539
6436.3.1 by Jelmer Vernooij
Add remote get_branches call.
540
class TestBzrDirGetBranches(TestRemote):
541
542
    def test_get_branches(self):
543
        transport = MemoryTransport()
544
        client = FakeClient(transport.base)
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
545
        reference_bzrdir_format = controldir.format_registry.get('default')()
6436.3.2 by Jelmer Vernooij
Add HPSS call for BzrDir.get_branches.
546
        branch_name = reference_bzrdir_format.get_branch_format().network_name()
6436.3.1 by Jelmer Vernooij
Add remote get_branches call.
547
        client.add_success_response_with_body(
548
            bencode.bencode({
6436.3.2 by Jelmer Vernooij
Add HPSS call for BzrDir.get_branches.
549
                "foo": ("branch", branch_name),
550
                "": ("branch", branch_name)}), "success")
551
        client.add_success_response(
552
            'ok', '', 'no', 'no', 'no',
553
                reference_bzrdir_format.repository_format.network_name())
554
        client.add_error_response('NotStacked')
555
        client.add_success_response(
556
            'ok', '', 'no', 'no', 'no',
557
                reference_bzrdir_format.repository_format.network_name())
558
        client.add_error_response('NotStacked')
6436.3.1 by Jelmer Vernooij
Add remote get_branches call.
559
        transport.mkdir('quack')
560
        transport = transport.clone('quack')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
561
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
6436.3.1 by Jelmer Vernooij
Add remote get_branches call.
562
            _client=client)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
563
        result = a_controldir.get_branches()
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
564
        self.assertEqual({"", "foo"}, set(result.keys()))
6436.3.1 by Jelmer Vernooij
Add remote get_branches call.
565
        self.assertEqual(
6436.3.2 by Jelmer Vernooij
Add HPSS call for BzrDir.get_branches.
566
            [('call_expecting_body', 'BzrDir.get_branches', ('quack/',)),
567
             ('call', 'BzrDir.find_repositoryV3', ('quack/', )),
568
             ('call', 'Branch.get_stacked_on_url', ('quack/', )),
569
             ('call', 'BzrDir.find_repositoryV3', ('quack/', )),
570
             ('call', 'Branch.get_stacked_on_url', ('quack/', ))],
6436.3.1 by Jelmer Vernooij
Add remote get_branches call.
571
            client._calls)
572
573
6266.4.1 by Jelmer Vernooij
HPSS call 'BzrDir.destroy_branch'.
574
class TestBzrDirDestroyBranch(TestRemote):
575
576
    def test_destroy_default(self):
577
        transport = self.get_transport('quack')
578
        referenced = self.make_branch('referenced')
579
        client = FakeClient(transport.base)
580
        client.add_expected_call(
6266.4.5 by Jelmer Vernooij
Don't serialize None.
581
            'BzrDir.destroy_branch', ('quack/', ),
6266.4.1 by Jelmer Vernooij
HPSS call 'BzrDir.destroy_branch'.
582
            'success', ('ok',)),
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
583
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
6266.4.1 by Jelmer Vernooij
HPSS call 'BzrDir.destroy_branch'.
584
            _client=client)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
585
        a_controldir.destroy_branch()
6266.4.1 by Jelmer Vernooij
HPSS call 'BzrDir.destroy_branch'.
586
        self.assertFinished(client)
587
588
6266.3.1 by Jelmer Vernooij
Add HPSS call for BzrDir.has_workingtree.
589
class TestBzrDirHasWorkingTree(TestRemote):
590
591
    def test_has_workingtree(self):
592
        transport = self.get_transport('quack')
593
        client = FakeClient(transport.base)
594
        client.add_expected_call(
595
            'BzrDir.has_workingtree', ('quack/',),
596
            'success', ('yes',)),
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
597
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
6266.3.1 by Jelmer Vernooij
Add HPSS call for BzrDir.has_workingtree.
598
            _client=client)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
599
        self.assertTrue(a_controldir.has_workingtree())
6266.3.1 by Jelmer Vernooij
Add HPSS call for BzrDir.has_workingtree.
600
        self.assertFinished(client)
601
602
    def test_no_workingtree(self):
603
        transport = self.get_transport('quack')
604
        client = FakeClient(transport.base)
605
        client.add_expected_call(
606
            'BzrDir.has_workingtree', ('quack/',),
607
            'success', ('no',)),
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
608
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
6266.3.1 by Jelmer Vernooij
Add HPSS call for BzrDir.has_workingtree.
609
            _client=client)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
610
        self.assertFalse(a_controldir.has_workingtree())
6266.3.1 by Jelmer Vernooij
Add HPSS call for BzrDir.has_workingtree.
611
        self.assertFinished(client)
612
613
6266.2.1 by Jelmer Vernooij
New HPSS call BzrDir.destroy_repository.
614
class TestBzrDirDestroyRepository(TestRemote):
615
616
    def test_destroy_repository(self):
617
        transport = self.get_transport('quack')
618
        client = FakeClient(transport.base)
619
        client.add_expected_call(
6266.2.2 by Jelmer Vernooij
Fix tests.
620
            'BzrDir.destroy_repository', ('quack/',),
6266.2.1 by Jelmer Vernooij
New HPSS call BzrDir.destroy_repository.
621
            'success', ('ok',)),
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
622
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
6266.2.1 by Jelmer Vernooij
New HPSS call BzrDir.destroy_repository.
623
            _client=client)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
624
        a_controldir.destroy_repository()
6266.2.1 by Jelmer Vernooij
New HPSS call BzrDir.destroy_repository.
625
        self.assertFinished(client)
626
627
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.
628
class TestBzrDirOpen(TestRemote):
629
630
    def make_fake_client_and_transport(self, path='quack'):
631
        transport = MemoryTransport()
632
        transport.mkdir(path)
633
        transport = transport.clone(path)
634
        client = FakeClient(transport.base)
635
        return client, transport
636
637
    def test_absent(self):
638
        client, transport = self.make_fake_client_and_transport()
639
        client.add_expected_call(
640
            'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
641
        self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
5712.3.17 by Jelmer Vernooij
more fixes.
642
                RemoteBzrDirFormat(), _client=client, _force_probe=True)
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.
643
        self.assertFinished(client)
644
645
    def test_present_without_workingtree(self):
646
        client, transport = self.make_fake_client_and_transport()
647
        client.add_expected_call(
648
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
5712.3.17 by Jelmer Vernooij
more fixes.
649
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
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.
650
            _client=client, _force_probe=True)
651
        self.assertIsInstance(bd, RemoteBzrDir)
652
        self.assertFalse(bd.has_workingtree())
653
        self.assertRaises(errors.NoWorkingTree, bd.open_workingtree)
654
        self.assertFinished(client)
655
656
    def test_present_with_workingtree(self):
657
        client, transport = self.make_fake_client_and_transport()
658
        client.add_expected_call(
659
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
5712.3.17 by Jelmer Vernooij
more fixes.
660
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
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.
661
            _client=client, _force_probe=True)
662
        self.assertIsInstance(bd, RemoteBzrDir)
663
        self.assertTrue(bd.has_workingtree())
664
        self.assertRaises(errors.NotLocalUrl, bd.open_workingtree)
665
        self.assertFinished(client)
666
667
    def test_backwards_compat(self):
668
        client, transport = self.make_fake_client_and_transport()
669
        client.add_expected_call(
670
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
671
        client.add_expected_call(
672
            'BzrDir.open', ('quack/',), 'success', ('yes',))
5712.3.17 by Jelmer Vernooij
more fixes.
673
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
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.
674
            _client=client, _force_probe=True)
675
        self.assertIsInstance(bd, RemoteBzrDir)
676
        self.assertFinished(client)
677
4797.49.2 by Andrew Bennetts
Add test that demonstrates bug #528041.
678
    def test_backwards_compat_hpss_v2(self):
679
        client, transport = self.make_fake_client_and_transport()
680
        # Monkey-patch fake client to simulate real-world behaviour with v2
681
        # server: upon first RPC call detect the protocol version, and because
682
        # the version is 2 also do _remember_remote_is_before((1, 6)) before
683
        # continuing with the RPC.
684
        orig_check_call = client._check_call
685
        def check_call(method, args):
686
            client._medium._protocol_version = 2
687
            client._medium._remember_remote_is_before((1, 6))
688
            client._check_call = orig_check_call
689
            client._check_call(method, args)
690
        client._check_call = check_call
691
        client.add_expected_call(
692
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
693
        client.add_expected_call(
694
            'BzrDir.open', ('quack/',), 'success', ('yes',))
5712.3.17 by Jelmer Vernooij
more fixes.
695
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
4797.49.2 by Andrew Bennetts
Add test that demonstrates bug #528041.
696
            _client=client, _force_probe=True)
697
        self.assertIsInstance(bd, RemoteBzrDir)
698
        self.assertFinished(client)
699
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.
700
4053.1.2 by Robert Collins
Actually make this branch work.
701
class TestBzrDirOpenBranch(TestRemote):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
702
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.
703
    def test_backwards_compat(self):
704
        self.setup_smart_server_with_call_log()
705
        self.make_branch('.')
706
        a_dir = BzrDir.open(self.get_url('.'))
707
        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).
708
        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.
709
        self.disable_verb(verb)
710
        format = a_dir.open_branch()
711
        call_count = len([call for call in self.hpss_calls if
712
            call.call.method == verb])
713
        self.assertEqual(1, call_count)
714
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
715
    def test_branch_present(self):
4053.1.2 by Robert Collins
Actually make this branch work.
716
        reference_format = self.get_repo_format()
717
        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.
718
        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.
719
        transport = MemoryTransport()
720
        transport.mkdir('quack')
721
        transport = transport.clone('quack')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
722
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
723
        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).
724
            '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.
725
            'success', ('branch', branch_network_name))
3691.2.10 by Martin Pool
Update more test_remote tests
726
        client.add_expected_call(
4053.1.2 by Robert Collins
Actually make this branch work.
727
            'BzrDir.find_repositoryV3', ('quack/',),
728
            'success', ('ok', '', 'no', 'no', 'no', network_name))
3691.2.10 by Martin Pool
Update more test_remote tests
729
        client.add_expected_call(
730
            'Branch.get_stacked_on_url', ('quack/',),
731
            'error', ('NotStacked',))
5712.3.17 by Jelmer Vernooij
more fixes.
732
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
733
            _client=client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
734
        result = bzrdir.open_branch()
735
        self.assertIsInstance(result, RemoteBranch)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
736
        self.assertEqual(bzrdir, result.controldir)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
737
        self.assertFinished(client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
738
739
    def test_branch_missing(self):
740
        transport = MemoryTransport()
741
        transport.mkdir('quack')
742
        transport = transport.clone('quack')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
743
        client = FakeClient(transport.base)
744
        client.add_error_response('nobranch')
5712.3.17 by Jelmer Vernooij
more fixes.
745
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
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.
746
            _client=client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
747
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
748
        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).
749
            [('call', 'BzrDir.open_branchV3', ('quack/',))],
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
750
            client._calls)
751
3211.4.1 by Robert Collins
* ``RemoteBzrDir._get_tree_branch`` no longer triggers ``_ensure_real``,
752
    def test__get_tree_branch(self):
753
        # _get_tree_branch is a form of open_branch, but it should only ask for
754
        # branch opening, not any other network requests.
755
        calls = []
6305.3.4 by Jelmer Vernooij
Add possible_transports in a couple more places.
756
        def open_branch(name=None, possible_transports=None):
3211.4.1 by Robert Collins
* ``RemoteBzrDir._get_tree_branch`` no longer triggers ``_ensure_real``,
757
            calls.append("Called")
758
            return "a-branch"
759
        transport = MemoryTransport()
760
        # 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.
761
        client = FakeClient(transport.base)
5712.3.17 by Jelmer Vernooij
more fixes.
762
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
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.
763
            _client=client)
3211.4.1 by Robert Collins
* ``RemoteBzrDir._get_tree_branch`` no longer triggers ``_ensure_real``,
764
        # patch the open_branch call to record that it was called.
765
        bzrdir.open_branch = open_branch
766
        self.assertEqual((None, "a-branch"), bzrdir._get_tree_branch())
767
        self.assertEqual(["Called"], calls)
768
        self.assertEqual([], client._calls)
769
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.
770
    def test_url_quoting_of_path(self):
771
        # Relpaths on the wire should not be URL-escaped.  So "~" should be
772
        # 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.
773
        transport = RemoteTCPTransport('bzr://localhost/~hello/')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
774
        client = FakeClient(transport.base)
4053.1.2 by Robert Collins
Actually make this branch work.
775
        reference_format = self.get_repo_format()
776
        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.
777
        branch_network_name = self.get_branch_format().network_name()
3691.2.10 by Martin Pool
Update more test_remote tests
778
        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).
779
            '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.
780
            'success', ('branch', branch_network_name))
3691.2.10 by Martin Pool
Update more test_remote tests
781
        client.add_expected_call(
4053.1.2 by Robert Collins
Actually make this branch work.
782
            'BzrDir.find_repositoryV3', ('~hello/',),
783
            'success', ('ok', '', 'no', 'no', 'no', network_name))
3691.2.10 by Martin Pool
Update more test_remote tests
784
        client.add_expected_call(
785
            'Branch.get_stacked_on_url', ('~hello/',),
786
            'error', ('NotStacked',))
5712.3.17 by Jelmer Vernooij
more fixes.
787
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
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.
788
            _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.
789
        result = bzrdir.open_branch()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
790
        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.
791
3221.3.3 by Robert Collins
* Hook up the new remote method ``RemoteBzrDir.find_repositoryV2`` so
792
    def check_open_repository(self, rich_root, subtrees, external_lookup='no'):
4053.1.2 by Robert Collins
Actually make this branch work.
793
        reference_format = self.get_repo_format()
794
        network_name = reference_format.network_name()
3104.4.2 by Andrew Bennetts
All tests passing.
795
        transport = MemoryTransport()
796
        transport.mkdir('quack')
797
        transport = transport.clone('quack')
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
798
        if rich_root:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
799
            rich_response = 'yes'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
800
        else:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
801
            rich_response = 'no'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
802
        if subtrees:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
803
            subtree_response = 'yes'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
804
        else:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
805
            subtree_response = 'no'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
806
        client = FakeClient(transport.base)
807
        client.add_success_response(
4053.1.2 by Robert Collins
Actually make this branch work.
808
            'ok', '', rich_response, subtree_response, external_lookup,
809
            network_name)
5712.3.17 by Jelmer Vernooij
more fixes.
810
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
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.
811
            _client=client)
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
812
        result = bzrdir.open_repository()
813
        self.assertEqual(
4053.1.2 by Robert Collins
Actually make this branch work.
814
            [('call', 'BzrDir.find_repositoryV3', ('quack/',))],
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
815
            client._calls)
816
        self.assertIsInstance(result, RemoteRepository)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
817
        self.assertEqual(bzrdir, result.controldir)
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
818
        self.assertEqual(rich_root, result._format.rich_root_data)
2018.5.138 by Robert Collins
Merge bzr.dev.
819
        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.
820
821
    def test_open_repository_sets_format_attributes(self):
822
        self.check_open_repository(True, True)
823
        self.check_open_repository(False, True)
824
        self.check_open_repository(True, False)
825
        self.check_open_repository(False, False)
3221.3.3 by Robert Collins
* Hook up the new remote method ``RemoteBzrDir.find_repositoryV2`` so
826
        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.
827
2432.3.2 by Andrew Bennetts
Add test, and tidy implementation.
828
    def test_old_server(self):
829
        """RemoteBzrDirFormat should fail to probe if the server version is too
830
        old.
831
        """
832
        self.assertRaises(errors.NotBranchError,
5363.2.9 by Jelmer Vernooij
Fix some tests.
833
            RemoteBzrProber.probe_transport, OldServerTransport())
2432.3.2 by Andrew Bennetts
Add test, and tidy implementation.
834
835
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
836
class TestBzrDirCreateBranch(TestRemote):
837
838
    def test_backwards_compat(self):
839
        self.setup_smart_server_with_call_log()
840
        repo = self.make_repository('.')
841
        self.reset_smart_call_log()
842
        self.disable_verb('BzrDir.create_branch')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
843
        branch = repo.controldir.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.
844
        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.
845
            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.
846
        self.assertEqual(1, create_branch_call_count)
847
848
    def test_current_server(self):
849
        transport = self.get_transport('.')
850
        transport = transport.clone('quack')
851
        self.make_repository('quack')
852
        client = FakeClient(transport.base)
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
853
        reference_bzrdir_format = controldir.format_registry.get('default')()
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
854
        reference_format = reference_bzrdir_format.get_branch_format()
855
        network_name = reference_format.network_name()
856
        reference_repo_fmt = reference_bzrdir_format.repository_format
857
        reference_repo_name = reference_repo_fmt.network_name()
858
        client.add_expected_call(
859
            'BzrDir.create_branch', ('quack/', network_name),
860
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
861
            reference_repo_name))
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
862
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
863
            _client=client)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
864
        branch = a_controldir.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.
865
        # We should have got a remote branch
866
        self.assertIsInstance(branch, remote.RemoteBranch)
867
        # its format should have the settings from the response
868
        format = branch._format
869
        self.assertEqual(network_name, format.network_name())
870
5609.21.2 by Andrew Bennetts
Add test.
871
    def test_already_open_repo_and_reused_medium(self):
872
        """Bug 726584: create_branch(..., repository=repo) should work
873
        regardless of what the smart medium's base URL is.
874
        """
875
        self.transport_server = test_server.SmartTCPServer_for_testing
876
        transport = self.get_transport('.')
877
        repo = self.make_repository('quack')
878
        # Client's medium rooted a transport root (not at the bzrdir)
879
        client = FakeClient(transport.base)
880
        transport = transport.clone('quack')
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
881
        reference_bzrdir_format = controldir.format_registry.get('default')()
5609.21.2 by Andrew Bennetts
Add test.
882
        reference_format = reference_bzrdir_format.get_branch_format()
883
        network_name = reference_format.network_name()
884
        reference_repo_fmt = reference_bzrdir_format.repository_format
885
        reference_repo_name = reference_repo_fmt.network_name()
886
        client.add_expected_call(
887
            'BzrDir.create_branch', ('extra/quack/', network_name),
888
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
889
            reference_repo_name))
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
890
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
5609.21.2 by Andrew Bennetts
Add test.
891
            _client=client)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
892
        branch = a_controldir.create_branch(repository=repo)
5609.21.2 by Andrew Bennetts
Add test.
893
        # We should have got a remote branch
894
        self.assertIsInstance(branch, remote.RemoteBranch)
895
        # its format should have the settings from the response
896
        format = branch._format
897
        self.assertEqual(network_name, format.network_name())
898
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
899
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
900
class TestBzrDirCreateRepository(TestRemote):
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
901
902
    def test_backwards_compat(self):
903
        self.setup_smart_server_with_call_log()
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
904
        bzrdir = self.make_controldir('.')
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
905
        self.reset_smart_call_log()
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
906
        self.disable_verb('BzrDir.create_repository')
907
        repo = bzrdir.create_repository()
908
        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.
909
            call.call.method == 'BzrDir.create_repository'])
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
910
        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.
911
912
    def test_current_server(self):
913
        transport = self.get_transport('.')
914
        transport = transport.clone('quack')
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
915
        self.make_controldir('quack')
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
916
        client = FakeClient(transport.base)
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
917
        reference_bzrdir_format = controldir.format_registry.get('default')()
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
918
        reference_format = reference_bzrdir_format.repository_format
919
        network_name = reference_format.network_name()
920
        client.add_expected_call(
921
            'BzrDir.create_repository', ('quack/',
4599.4.20 by Robert Collins
Prep test_remote for 2a as default.
922
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
923
                'False'),
924
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
925
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
926
            _client=client)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
927
        repo = a_controldir.create_repository()
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
928
        # We should have got a remote repository
929
        self.assertIsInstance(repo, remote.RemoteRepository)
930
        # its format should have the settings from the response
931
        format = repo._format
4599.4.20 by Robert Collins
Prep test_remote for 2a as default.
932
        self.assertTrue(format.rich_root_data)
933
        self.assertTrue(format.supports_tree_reference)
934
        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.
935
        self.assertEqual(network_name, format.network_name())
936
937
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
938
class TestBzrDirOpenRepository(TestRemote):
939
940
    def test_backwards_compat_1_2_3(self):
941
        # fallback all the way to the first version.
942
        reference_format = self.get_repo_format()
943
        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.
944
        server_url = 'bzr://example.com/'
945
        self.permit_url(server_url)
946
        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.
947
        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.
948
        client.add_unknown_method_response('BzrDir.find_repositoryV2')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
949
        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.
950
        # A real repository instance will be created to determine the network
951
        # name.
952
        client.add_success_response_with_body(
953
            "Bazaar-NG meta directory, format 1\n", 'ok')
6213.1.61 by Jelmer Vernooij
Fix tests.
954
        client.add_success_response('stat', '0', '65535')
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
955
        client.add_success_response_with_body(
956
            reference_format.get_format_string(), 'ok')
957
        # PackRepository wants to do a stat
958
        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.
959
        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.
960
            _client=client)
5712.3.17 by Jelmer Vernooij
more fixes.
961
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
962
            _client=client)
963
        repo = bzrdir.open_repository()
964
        self.assertEqual(
965
            [('call', 'BzrDir.find_repositoryV3', ('quack/',)),
966
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
967
             ('call', 'BzrDir.find_repository', ('quack/',)),
968
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
6213.1.61 by Jelmer Vernooij
Fix tests.
969
             ('call', 'stat', ('/quack/.bzr',)),
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
970
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
971
             ('call', 'stat', ('/quack/.bzr/repository',)),
972
             ],
973
            client._calls)
974
        self.assertEqual(network_name, repo._format.network_name())
975
976
    def test_backwards_compat_2(self):
977
        # fallback to find_repositoryV2
978
        reference_format = self.get_repo_format()
979
        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.
980
        server_url = 'bzr://example.com/'
981
        self.permit_url(server_url)
982
        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.
983
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
984
        client.add_success_response('ok', '', 'no', 'no', 'no')
985
        # A real repository instance will be created to determine the network
986
        # name.
987
        client.add_success_response_with_body(
988
            "Bazaar-NG meta directory, format 1\n", 'ok')
6213.1.61 by Jelmer Vernooij
Fix tests.
989
        client.add_success_response('stat', '0', '65535')
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
990
        client.add_success_response_with_body(
991
            reference_format.get_format_string(), 'ok')
992
        # PackRepository wants to do a stat
993
        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.
994
        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.
995
            _client=client)
5712.3.17 by Jelmer Vernooij
more fixes.
996
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
997
            _client=client)
998
        repo = bzrdir.open_repository()
999
        self.assertEqual(
1000
            [('call', 'BzrDir.find_repositoryV3', ('quack/',)),
1001
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
1002
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
6213.1.61 by Jelmer Vernooij
Fix tests.
1003
             ('call', 'stat', ('/quack/.bzr',)),
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
1004
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
1005
             ('call', 'stat', ('/quack/.bzr/repository',)),
1006
             ],
1007
            client._calls)
1008
        self.assertEqual(network_name, repo._format.network_name())
1009
1010
    def test_current_server(self):
1011
        reference_format = self.get_repo_format()
1012
        network_name = reference_format.network_name()
1013
        transport = MemoryTransport()
1014
        transport.mkdir('quack')
1015
        transport = transport.clone('quack')
1016
        client = FakeClient(transport.base)
1017
        client.add_success_response('ok', '', 'no', 'no', 'no', network_name)
5712.3.17 by Jelmer Vernooij
more fixes.
1018
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
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.
1019
            _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.
1020
        repo = bzrdir.open_repository()
1021
        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.
1022
            [('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.
1023
            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.
1024
        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.
1025
1026
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
1027
class TestBzrDirFormatInitializeEx(TestRemote):
1028
1029
    def test_success(self):
1030
        """Simple test for typical successful call."""
5712.3.17 by Jelmer Vernooij
more fixes.
1031
        fmt = RemoteBzrDirFormat()
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
1032
        default_format_name = BzrDirFormat.get_default_format().network_name()
1033
        transport = self.get_transport()
1034
        client = FakeClient(transport.base)
1035
        client.add_expected_call(
4436.1.1 by Andrew Bennetts
Rename BzrDirFormat.initialize_ex verb to BzrDirFormat.initialize_ex_1.16.
1036
            'BzrDirFormat.initialize_ex_1.16',
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
1037
                (default_format_name, 'path', 'False', 'False', 'False', '',
1038
                 '', '', '', 'False'),
1039
            'success',
1040
                ('.', 'no', 'no', 'yes', 'repo fmt', 'repo bzrdir fmt',
1041
                 'bzrdir fmt', 'False', '', '', 'repo lock token'))
1042
        # XXX: It would be better to call fmt.initialize_on_transport_ex, but
1043
        # it's currently hard to test that without supplying a real remote
1044
        # transport connected to a real server.
1045
        result = fmt._initialize_on_transport_ex_rpc(client, 'path',
1046
            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.
1047
        self.assertFinished(client)
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
1048
1049
    def test_error(self):
1050
        """Error responses are translated, e.g. 'PermissionDenied' raises the
1051
        corresponding error from the client.
1052
        """
5712.3.17 by Jelmer Vernooij
more fixes.
1053
        fmt = RemoteBzrDirFormat()
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
1054
        default_format_name = BzrDirFormat.get_default_format().network_name()
1055
        transport = self.get_transport()
1056
        client = FakeClient(transport.base)
1057
        client.add_expected_call(
4436.1.1 by Andrew Bennetts
Rename BzrDirFormat.initialize_ex verb to BzrDirFormat.initialize_ex_1.16.
1058
            'BzrDirFormat.initialize_ex_1.16',
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
1059
                (default_format_name, 'path', 'False', 'False', 'False', '',
1060
                 '', '', '', 'False'),
1061
            'error',
1062
                ('PermissionDenied', 'path', 'extra info'))
1063
        # XXX: It would be better to call fmt.initialize_on_transport_ex, but
1064
        # it's currently hard to test that without supplying a real remote
1065
        # transport connected to a real server.
1066
        err = self.assertRaises(errors.PermissionDenied,
1067
            fmt._initialize_on_transport_ex_rpc, client, 'path', transport,
1068
            False, False, False, None, None, None, None, False)
1069
        self.assertEqual('path', err.path)
1070
        self.assertEqual(': extra info', err.extra)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1071
        self.assertFinished(client)
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
1072
4384.1.3 by Andrew Bennetts
Add test suggested by John.
1073
    def test_error_from_real_server(self):
1074
        """Integration test for error translation."""
1075
        transport = self.make_smart_server('foo')
1076
        transport = transport.clone('no-such-path')
5712.3.17 by Jelmer Vernooij
more fixes.
1077
        fmt = RemoteBzrDirFormat()
4384.1.3 by Andrew Bennetts
Add test suggested by John.
1078
        err = self.assertRaises(errors.NoSuchFile,
1079
            fmt.initialize_on_transport_ex, transport, create_prefix=False)
1080
4384.1.1 by Andrew Bennetts
Translate ErrorFromSmartServer in RemoteBzrDirFormat.
1081
2432.3.2 by Andrew Bennetts
Add test, and tidy implementation.
1082
class OldSmartClient(object):
1083
    """A fake smart client for test_old_version that just returns a version one
1084
    response to the 'hello' (query version) command.
1085
    """
1086
1087
    def get_request(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1088
        input_file = BytesIO(b'ok\x011\n')
1089
        output_file = BytesIO()
2432.3.2 by Andrew Bennetts
Add test, and tidy implementation.
1090
        client_medium = medium.SmartSimplePipesClientMedium(
1091
            input_file, output_file)
1092
        return medium.SmartClientStreamMediumRequest(client_medium)
1093
3241.1.1 by Andrew Bennetts
Shift protocol version querying from RemoteBzrDirFormat into SmartClientMedium.
1094
    def protocol_version(self):
1095
        return 1
1096
2432.3.2 by Andrew Bennetts
Add test, and tidy implementation.
1097
1098
class OldServerTransport(object):
1099
    """A fake transport for test_old_server that reports it's smart server
1100
    protocol version as version one.
1101
    """
1102
1103
    def __init__(self):
1104
        self.base = 'fake:'
1105
1106
    def get_smart_client(self):
1107
        return OldSmartClient()
1108
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1109
4288.1.1 by Robert Collins
Add support for a RemoteBzrDirConfig to support optimising push operations which need to look for default stacking locations.
1110
class RemoteBzrDirTestCase(TestRemote):
1111
1112
    def make_remote_bzrdir(self, transport, client):
1113
        """Make a RemotebzrDir using 'client' as the _client."""
5712.3.17 by Jelmer Vernooij
more fixes.
1114
        return RemoteBzrDir(transport, RemoteBzrDirFormat(),
4288.1.1 by Robert Collins
Add support for a RemoteBzrDirConfig to support optimising push operations which need to look for default stacking locations.
1115
            _client=client)
1116
1117
1118
class RemoteBranchTestCase(RemoteBzrDirTestCase):
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1119
4634.36.1 by Andrew Bennetts
Fix trivial bug in RemoteBranch._set_tags_bytes, and add some unit tests for it.
1120
    def lock_remote_branch(self, branch):
1121
        """Trick a RemoteBranch into thinking it is locked."""
1122
        branch._lock_mode = 'w'
1123
        branch._lock_count = 2
1124
        branch._lock_token = 'branch token'
1125
        branch._repo_lock_token = 'repo token'
1126
        branch.repository._lock_mode = 'w'
1127
        branch.repository._lock_count = 2
1128
        branch.repository._lock_token = 'repo token'
1129
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1130
    def make_remote_branch(self, transport, client):
1131
        """Make a RemoteBranch using 'client' as its _SmartClient.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1132
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1133
        A RemoteBzrDir and RemoteRepository will also be created to fill out
1134
        the RemoteBranch, albeit with stub values for some of their attributes.
1135
        """
1136
        # we do not want bzrdir to make any remote calls, so use False as its
1137
        # _client.  If it tries to make a remote call, this will fail
1138
        # 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.
1139
        bzrdir = self.make_remote_bzrdir(transport, False)
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1140
        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.
1141
        branch_format = self.get_branch_format()
1142
        format = RemoteBranchFormat(network_name=branch_format.network_name())
1143
        return RemoteBranch(bzrdir, repo, _client=client, format=format)
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1144
1145
6280.4.3 by Jelmer Vernooij
add Branch.break_lock.
1146
class TestBranchBreakLock(RemoteBranchTestCase):
1147
1148
    def test_break_lock(self):
1149
        transport_path = 'quack'
1150
        transport = MemoryTransport()
1151
        client = FakeClient(transport.base)
1152
        client.add_expected_call(
1153
            'Branch.get_stacked_on_url', ('quack/',),
1154
            'error', ('NotStacked',))
1155
        client.add_expected_call(
1156
            'Branch.break_lock', ('quack/',),
1157
            'success', ('ok',))
1158
        transport.mkdir('quack')
1159
        transport = transport.clone('quack')
1160
        branch = self.make_remote_branch(transport, client)
1161
        branch.break_lock()
1162
        self.assertFinished(client)
1163
1164
6280.6.1 by Jelmer Vernooij
Implement remote side of {Branch,Repository}.get_physical_lock_status.
1165
class TestBranchGetPhysicalLockStatus(RemoteBranchTestCase):
1166
1167
    def test_get_physical_lock_status_yes(self):
1168
        transport = MemoryTransport()
1169
        client = FakeClient(transport.base)
1170
        client.add_expected_call(
1171
            'Branch.get_stacked_on_url', ('quack/',),
1172
            'error', ('NotStacked',))
1173
        client.add_expected_call(
1174
            'Branch.get_physical_lock_status', ('quack/',),
1175
            'success', ('yes',))
1176
        transport.mkdir('quack')
1177
        transport = transport.clone('quack')
1178
        branch = self.make_remote_branch(transport, client)
1179
        result = branch.get_physical_lock_status()
1180
        self.assertFinished(client)
1181
        self.assertEqual(True, result)
1182
1183
    def test_get_physical_lock_status_no(self):
1184
        transport = MemoryTransport()
1185
        client = FakeClient(transport.base)
1186
        client.add_expected_call(
1187
            'Branch.get_stacked_on_url', ('quack/',),
1188
            'error', ('NotStacked',))
1189
        client.add_expected_call(
1190
            'Branch.get_physical_lock_status', ('quack/',),
1191
            'success', ('no',))
1192
        transport.mkdir('quack')
1193
        transport = transport.clone('quack')
1194
        branch = self.make_remote_branch(transport, client)
1195
        result = branch.get_physical_lock_status()
1196
        self.assertFinished(client)
1197
        self.assertEqual(False, result)
1198
1199
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1200
class TestBranchGetParent(RemoteBranchTestCase):
1201
1202
    def test_no_parent(self):
1203
        # in an empty branch we decode the response properly
1204
        transport = MemoryTransport()
1205
        client = FakeClient(transport.base)
1206
        client.add_expected_call(
1207
            'Branch.get_stacked_on_url', ('quack/',),
1208
            'error', ('NotStacked',))
1209
        client.add_expected_call(
1210
            'Branch.get_parent', ('quack/',),
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
1211
            'success', ('',))
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1212
        transport.mkdir('quack')
1213
        transport = transport.clone('quack')
1214
        branch = self.make_remote_branch(transport, client)
1215
        result = branch.get_parent()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1216
        self.assertFinished(client)
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1217
        self.assertEqual(None, result)
1218
1219
    def test_parent_relative(self):
1220
        transport = MemoryTransport()
1221
        client = FakeClient(transport.base)
1222
        client.add_expected_call(
1223
            'Branch.get_stacked_on_url', ('kwaak/',),
1224
            'error', ('NotStacked',))
1225
        client.add_expected_call(
1226
            'Branch.get_parent', ('kwaak/',),
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
1227
            'success', ('../foo/',))
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1228
        transport.mkdir('kwaak')
1229
        transport = transport.clone('kwaak')
1230
        branch = self.make_remote_branch(transport, client)
1231
        result = branch.get_parent()
1232
        self.assertEqual(transport.clone('../foo').base, result)
1233
1234
    def test_parent_absolute(self):
1235
        transport = MemoryTransport()
1236
        client = FakeClient(transport.base)
1237
        client.add_expected_call(
1238
            'Branch.get_stacked_on_url', ('kwaak/',),
1239
            'error', ('NotStacked',))
1240
        client.add_expected_call(
1241
            'Branch.get_parent', ('kwaak/',),
4083.1.7 by Andrew Bennetts
Fix same trivial bug [(x) != (x,)] in test_remote and test_smart.
1242
            'success', ('http://foo/',))
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1243
        transport.mkdir('kwaak')
1244
        transport = transport.clone('kwaak')
1245
        branch = self.make_remote_branch(transport, client)
1246
        result = branch.get_parent()
1247
        self.assertEqual('http://foo/', result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1248
        self.assertFinished(client)
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
1249
1250
1251
class TestBranchSetParentLocation(RemoteBranchTestCase):
1252
1253
    def test_no_parent(self):
1254
        # We call the verb when setting parent to None
1255
        transport = MemoryTransport()
1256
        client = FakeClient(transport.base)
1257
        client.add_expected_call(
1258
            'Branch.get_stacked_on_url', ('quack/',),
1259
            'error', ('NotStacked',))
1260
        client.add_expected_call(
1261
            'Branch.set_parent_location', ('quack/', 'b', 'r', ''),
1262
            'success', ())
1263
        transport.mkdir('quack')
1264
        transport = transport.clone('quack')
1265
        branch = self.make_remote_branch(transport, client)
1266
        branch._lock_token = 'b'
1267
        branch._repo_lock_token = 'r'
1268
        branch._set_parent_location(None)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1269
        self.assertFinished(client)
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
1270
1271
    def test_parent(self):
1272
        transport = MemoryTransport()
1273
        client = FakeClient(transport.base)
1274
        client.add_expected_call(
1275
            'Branch.get_stacked_on_url', ('kwaak/',),
1276
            'error', ('NotStacked',))
1277
        client.add_expected_call(
1278
            'Branch.set_parent_location', ('kwaak/', 'b', 'r', 'foo'),
1279
            'success', ())
1280
        transport.mkdir('kwaak')
1281
        transport = transport.clone('kwaak')
1282
        branch = self.make_remote_branch(transport, client)
1283
        branch._lock_token = 'b'
1284
        branch._repo_lock_token = 'r'
1285
        branch._set_parent_location('foo')
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1286
        self.assertFinished(client)
4288.1.7 by Robert Collins
Add new remote server verb Branch.set_parent_location, dropping roundtrips further on push operations.
1287
1288
    def test_backwards_compat(self):
1289
        self.setup_smart_server_with_call_log()
1290
        branch = self.make_branch('.')
1291
        self.reset_smart_call_log()
1292
        verb = 'Branch.set_parent_location'
1293
        self.disable_verb(verb)
6404.6.7 by Vincent Ladeuil
Change set/remove to require a lock for the branch config files.
1294
        branch.set_parent('http://foo/')
6404.6.2 by Vincent Ladeuil
Merge trunk resolving conflicts and fixing more test failures related to
1295
        self.assertLength(14, self.hpss_calls)
4078.2.1 by Robert Collins
Add a Branch.get_parent remote call for RemoteBranch.
1296
1297
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.
1298
class TestBranchGetTagsBytes(RemoteBranchTestCase):
1299
1300
    def test_backwards_compat(self):
1301
        self.setup_smart_server_with_call_log()
1302
        branch = self.make_branch('.')
1303
        self.reset_smart_call_log()
1304
        verb = 'Branch.get_tags_bytes'
1305
        self.disable_verb(verb)
1306
        branch.tags.get_tag_dict()
1307
        call_count = len([call for call in self.hpss_calls if
1308
            call.call.method == verb])
1309
        self.assertEqual(1, call_count)
1310
1311
    def test_trivial(self):
1312
        transport = MemoryTransport()
1313
        client = FakeClient(transport.base)
1314
        client.add_expected_call(
1315
            'Branch.get_stacked_on_url', ('quack/',),
1316
            'error', ('NotStacked',))
1317
        client.add_expected_call(
1318
            'Branch.get_tags_bytes', ('quack/',),
1319
            'success', ('',))
1320
        transport.mkdir('quack')
1321
        transport = transport.clone('quack')
1322
        branch = self.make_remote_branch(transport, client)
1323
        result = branch.tags.get_tag_dict()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1324
        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.
1325
        self.assertEqual({}, result)
1326
1327
4634.36.1 by Andrew Bennetts
Fix trivial bug in RemoteBranch._set_tags_bytes, and add some unit tests for it.
1328
class TestBranchSetTagsBytes(RemoteBranchTestCase):
1329
1330
    def test_trivial(self):
1331
        transport = MemoryTransport()
1332
        client = FakeClient(transport.base)
1333
        client.add_expected_call(
1334
            'Branch.get_stacked_on_url', ('quack/',),
1335
            'error', ('NotStacked',))
1336
        client.add_expected_call(
1337
            'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1338
            'success', ('',))
1339
        transport.mkdir('quack')
1340
        transport = transport.clone('quack')
1341
        branch = self.make_remote_branch(transport, client)
1342
        self.lock_remote_branch(branch)
1343
        branch._set_tags_bytes('tags bytes')
1344
        self.assertFinished(client)
1345
        self.assertEqual('tags bytes', client._calls[-1][-1])
1346
1347
    def test_backwards_compatible(self):
1348
        transport = MemoryTransport()
1349
        client = FakeClient(transport.base)
1350
        client.add_expected_call(
1351
            'Branch.get_stacked_on_url', ('quack/',),
1352
            'error', ('NotStacked',))
1353
        client.add_expected_call(
1354
            'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1355
            'unknown', ('Branch.set_tags_bytes',))
1356
        transport.mkdir('quack')
1357
        transport = transport.clone('quack')
1358
        branch = self.make_remote_branch(transport, client)
1359
        self.lock_remote_branch(branch)
1360
        class StubRealBranch(object):
1361
            def __init__(self):
1362
                self.calls = []
1363
            def _set_tags_bytes(self, bytes):
1364
                self.calls.append(('set_tags_bytes', bytes))
1365
        real_branch = StubRealBranch()
1366
        branch._real_branch = real_branch
1367
        branch._set_tags_bytes('tags bytes')
1368
        # Call a second time, to exercise the 'remote version already inferred'
1369
        # code path.
1370
        branch._set_tags_bytes('tags bytes')
1371
        self.assertFinished(client)
1372
        self.assertEqual(
1373
            [('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1374
1375
5672.1.5 by Andrew Bennetts
Add some tests for RemoteBranch.heads_to_fetch, and add release-note.
1376
class TestBranchHeadsToFetch(RemoteBranchTestCase):
1377
1378
    def test_uses_last_revision_info_and_tags_by_default(self):
1379
        transport = MemoryTransport()
1380
        client = FakeClient(transport.base)
1381
        client.add_expected_call(
1382
            'Branch.get_stacked_on_url', ('quack/',),
1383
            'error', ('NotStacked',))
1384
        client.add_expected_call(
1385
            'Branch.last_revision_info', ('quack/',),
1386
            'success', ('ok', '1', 'rev-tip'))
6015.15.4 by John Arbash Meinel
Catch a couple more cases that test tag fetching.
1387
        client.add_expected_call(
1388
            'Branch.get_config_file', ('quack/',),
1389
            'success', ('ok',), '')
1390
        transport.mkdir('quack')
1391
        transport = transport.clone('quack')
1392
        branch = self.make_remote_branch(transport, client)
1393
        result = branch.heads_to_fetch()
1394
        self.assertFinished(client)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
1395
        self.assertEqual(({'rev-tip'}, set()), result)
6015.15.4 by John Arbash Meinel
Catch a couple more cases that test tag fetching.
1396
1397
    def test_uses_last_revision_info_and_tags_when_set(self):
1398
        transport = MemoryTransport()
1399
        client = FakeClient(transport.base)
1400
        client.add_expected_call(
1401
            'Branch.get_stacked_on_url', ('quack/',),
1402
            'error', ('NotStacked',))
1403
        client.add_expected_call(
1404
            'Branch.last_revision_info', ('quack/',),
1405
            'success', ('ok', '1', 'rev-tip'))
1406
        client.add_expected_call(
1407
            'Branch.get_config_file', ('quack/',),
1408
            'success', ('ok',), 'branch.fetch_tags = True')
5672.1.5 by Andrew Bennetts
Add some tests for RemoteBranch.heads_to_fetch, and add release-note.
1409
        # XXX: this will break if the default format's serialization of tags
1410
        # changes, or if the RPC for fetching tags changes from get_tags_bytes.
1411
        client.add_expected_call(
1412
            'Branch.get_tags_bytes', ('quack/',),
1413
            'success', ('d5:tag-17:rev-foo5:tag-27:rev-bare',))
1414
        transport.mkdir('quack')
1415
        transport = transport.clone('quack')
1416
        branch = self.make_remote_branch(transport, client)
1417
        result = branch.heads_to_fetch()
1418
        self.assertFinished(client)
1419
        self.assertEqual(
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
1420
            ({'rev-tip'}, {'rev-foo', 'rev-bar'}), result)
5672.1.5 by Andrew Bennetts
Add some tests for RemoteBranch.heads_to_fetch, and add release-note.
1421
1422
    def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
1423
        transport = MemoryTransport()
1424
        client = FakeClient(transport.base)
1425
        client.add_expected_call(
1426
            'Branch.get_stacked_on_url', ('quack/',),
1427
            'error', ('NotStacked',))
1428
        client.add_expected_call(
5741.1.11 by Jelmer Vernooij
Don't make heads_to_fetch() take a stop_revision.
1429
            'Branch.heads_to_fetch', ('quack/',),
5672.1.6 by Andrew Bennetts
Add another test.
1430
            'success', (['tip'], ['tagged-1', 'tagged-2']))
5672.1.5 by Andrew Bennetts
Add some tests for RemoteBranch.heads_to_fetch, and add release-note.
1431
        transport.mkdir('quack')
1432
        transport = transport.clone('quack')
1433
        branch = self.make_remote_branch(transport, client)
5672.1.7 by Andrew Bennetts
Use a more explicit method name.
1434
        branch._format._use_default_local_heads_to_fetch = lambda: False
5672.1.5 by Andrew Bennetts
Add some tests for RemoteBranch.heads_to_fetch, and add release-note.
1435
        result = branch.heads_to_fetch()
1436
        self.assertFinished(client)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
1437
        self.assertEqual(({'tip'}, {'tagged-1', 'tagged-2'}), result)
5672.1.6 by Andrew Bennetts
Add another test.
1438
6015.15.1 by John Arbash Meinel
Start working on a config entry for testing whether we should fetch tags or not.
1439
    def make_branch_with_tags(self):
5672.1.6 by Andrew Bennetts
Add another test.
1440
        self.setup_smart_server_with_call_log()
1441
        # Make a branch with a single revision.
1442
        builder = self.make_branch_builder('foo')
1443
        builder.start_series()
1444
        builder.build_snapshot('tip', None, [
1445
            ('add', ('', 'root-id', 'directory', ''))])
1446
        builder.finish_series()
1447
        branch = builder.get_branch()
1448
        # Add two tags to that branch
1449
        branch.tags.set_tag('tag-1', 'rev-1')
1450
        branch.tags.set_tag('tag-2', 'rev-2')
6015.15.1 by John Arbash Meinel
Start working on a config entry for testing whether we should fetch tags or not.
1451
        return branch
1452
1453
    def test_backwards_compatible(self):
6404.6.2 by Vincent Ladeuil
Merge trunk resolving conflicts and fixing more test failures related to
1454
        br = self.make_branch_with_tags()
6404.6.7 by Vincent Ladeuil
Change set/remove to require a lock for the branch config files.
1455
        br.get_config_stack().set('branch.fetch_tags', True)
6404.6.2 by Vincent Ladeuil
Merge trunk resolving conflicts and fixing more test failures related to
1456
        self.addCleanup(br.lock_read().unlock)
5672.1.6 by Andrew Bennetts
Add another test.
1457
        # Disable the heads_to_fetch verb
1458
        verb = 'Branch.heads_to_fetch'
1459
        self.disable_verb(verb)
1460
        self.reset_smart_call_log()
6404.6.2 by Vincent Ladeuil
Merge trunk resolving conflicts and fixing more test failures related to
1461
        result = br.heads_to_fetch()
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
1462
        self.assertEqual(({'tip'}, {'rev-1', 'rev-2'}), result)
5672.1.6 by Andrew Bennetts
Add another test.
1463
        self.assertEqual(
6404.6.2 by Vincent Ladeuil
Merge trunk resolving conflicts and fixing more test failures related to
1464
            ['Branch.last_revision_info', 'Branch.get_tags_bytes'],
6015.15.1 by John Arbash Meinel
Start working on a config entry for testing whether we should fetch tags or not.
1465
            [call.call.method for call in self.hpss_calls])
1466
1467
    def test_backwards_compatible_no_tags(self):
6404.6.2 by Vincent Ladeuil
Merge trunk resolving conflicts and fixing more test failures related to
1468
        br = self.make_branch_with_tags()
6404.6.7 by Vincent Ladeuil
Change set/remove to require a lock for the branch config files.
1469
        br.get_config_stack().set('branch.fetch_tags', False)
6404.6.2 by Vincent Ladeuil
Merge trunk resolving conflicts and fixing more test failures related to
1470
        self.addCleanup(br.lock_read().unlock)
6015.15.1 by John Arbash Meinel
Start working on a config entry for testing whether we should fetch tags or not.
1471
        # Disable the heads_to_fetch verb
1472
        verb = 'Branch.heads_to_fetch'
1473
        self.disable_verb(verb)
1474
        self.reset_smart_call_log()
6404.6.2 by Vincent Ladeuil
Merge trunk resolving conflicts and fixing more test failures related to
1475
        result = br.heads_to_fetch()
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
1476
        self.assertEqual(({'tip'}, set()), result)
6015.15.1 by John Arbash Meinel
Start working on a config entry for testing whether we should fetch tags or not.
1477
        self.assertEqual(
6404.6.2 by Vincent Ladeuil
Merge trunk resolving conflicts and fixing more test failures related to
1478
            ['Branch.last_revision_info'],
5672.1.6 by Andrew Bennetts
Add another test.
1479
            [call.call.method for call in self.hpss_calls])
5672.1.5 by Andrew Bennetts
Add some tests for RemoteBranch.heads_to_fetch, and add release-note.
1480
1481
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1482
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1483
1484
    def test_empty_branch(self):
1485
        # in an empty branch we decode the response properly
1486
        transport = MemoryTransport()
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1487
        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
1488
        client.add_expected_call(
1489
            'Branch.get_stacked_on_url', ('quack/',),
1490
            'error', ('NotStacked',))
1491
        client.add_expected_call(
1492
            'Branch.last_revision_info', ('quack/',),
1493
            'success', ('ok', '0', 'null:'))
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1494
        transport.mkdir('quack')
1495
        transport = transport.clone('quack')
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1496
        branch = self.make_remote_branch(transport, client)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1497
        result = branch.last_revision_info()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1498
        self.assertFinished(client)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1499
        self.assertEqual((0, NULL_REVISION), result)
1500
1501
    def test_non_empty_branch(self):
1502
        # 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.
1503
        revid = u'\xc8'.encode('utf8')
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1504
        transport = MemoryTransport()
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1505
        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
1506
        client.add_expected_call(
1507
            'Branch.get_stacked_on_url', ('kwaak/',),
1508
            'error', ('NotStacked',))
1509
        client.add_expected_call(
1510
            'Branch.last_revision_info', ('kwaak/',),
1511
            'success', ('ok', '2', revid))
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1512
        transport.mkdir('kwaak')
1513
        transport = transport.clone('kwaak')
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1514
        branch = self.make_remote_branch(transport, client)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1515
        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.
1516
        self.assertEqual((2, revid), result)
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
1517
1518
4053.1.2 by Robert Collins
Actually make this branch work.
1519
class TestBranch_get_stacked_on_url(TestRemote):
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
1520
    """Test Branch._get_stacked_on_url rpc"""
1521
3691.2.10 by Martin Pool
Update more test_remote tests
1522
    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.
1523
        # test that asking for a stacked on url the server can't access works.
1524
        # This isn't perfect, but then as we're in the same process there
1525
        # really isn't anything we can do to be 100% sure that the server
1526
        # doesn't just open in - this test probably needs to be rewritten using
1527
        # a spawn()ed server.
1528
        stacked_branch = self.make_branch('stacked', format='1.9')
1529
        memory_branch = self.make_branch('base', format='1.9')
1530
        vfs_url = self.get_vfs_only_url('base')
1531
        stacked_branch.set_stacked_on_url(vfs_url)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
1532
        transport = stacked_branch.controldir.root_transport
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
1533
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1534
        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.
1535
            'Branch.get_stacked_on_url', ('stacked/',),
1536
            'success', ('ok', vfs_url))
1537
        # XXX: Multiple calls are bad, this second call documents what is
1538
        # today.
1539
        client.add_expected_call(
1540
            'Branch.get_stacked_on_url', ('stacked/',),
1541
            'success', ('ok', vfs_url))
5712.3.17 by Jelmer Vernooij
more fixes.
1542
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
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.
1543
            _client=client)
4118.1.5 by Andrew Bennetts
Fix test_remote tests.
1544
        repo_fmt = remote.RemoteRepositoryFormat()
1545
        repo_fmt._custom_format = stacked_branch.repository._format
1546
        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.
1547
            _client=client)
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
1548
        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.
1549
        self.assertEqual(vfs_url, result)
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
1550
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
1551
    def test_backwards_compatible(self):
1552
        # like with bzr1.6 with no Branch.get_stacked_on_url rpc
1553
        base_branch = self.make_branch('base', format='1.6')
1554
        stacked_branch = self.make_branch('stacked', format='1.6')
1555
        stacked_branch.set_stacked_on_url('../base')
1556
        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.
1557
        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
1558
        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).
1559
            '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.
1560
            'success', ('branch', branch_network_name))
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
1561
        client.add_expected_call(
4053.1.2 by Robert Collins
Actually make this branch work.
1562
            'BzrDir.find_repositoryV3', ('stacked/',),
4118.1.5 by Andrew Bennetts
Fix test_remote tests.
1563
            'success', ('ok', '', 'no', 'no', 'yes',
4053.1.2 by Robert Collins
Actually make this branch work.
1564
                stacked_branch.repository._format.network_name()))
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
1565
        # called twice, once from constructor and then again by us
1566
        client.add_expected_call(
1567
            'Branch.get_stacked_on_url', ('stacked/',),
1568
            'unknown', ('Branch.get_stacked_on_url',))
1569
        client.add_expected_call(
1570
            'Branch.get_stacked_on_url', ('stacked/',),
1571
            'unknown', ('Branch.get_stacked_on_url',))
1572
        # this will also do vfs access, but that goes direct to the transport
1573
        # 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.
1574
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
5712.3.17 by Jelmer Vernooij
more fixes.
1575
            RemoteBzrDirFormat(), _client=client)
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
1576
        branch = bzrdir.open_branch()
1577
        result = branch.get_stacked_on_url()
1578
        self.assertEqual('../base', result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1579
        self.assertFinished(client)
3691.2.12 by Martin Pool
Add test for coping without Branch.get_stacked_on_url
1580
        # it's in the fallback list both for the RemoteRepository and its vfs
1581
        # repository
1582
        self.assertEqual(1, len(branch.repository._fallback_repositories))
1583
        self.assertEqual(1,
1584
            len(branch.repository._real_repository._fallback_repositories))
1585
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1586
    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.
1587
        base_branch = self.make_branch('base')
1588
        stacked_branch = self.make_branch('stacked')
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1589
        stacked_branch.set_stacked_on_url('../base')
4053.1.2 by Robert Collins
Actually make this branch work.
1590
        reference_format = self.get_repo_format()
1591
        network_name = reference_format.network_name()
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1592
        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.
1593
        branch_network_name = self.get_branch_format().network_name()
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1594
        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).
1595
            '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.
1596
            'success', ('branch', branch_network_name))
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1597
        client.add_expected_call(
4053.1.2 by Robert Collins
Actually make this branch work.
1598
            'BzrDir.find_repositoryV3', ('stacked/',),
5158.4.3 by Andrew Bennetts
Fix test_remote tests that accidentally assumed it was ok to stack mismatched formats.
1599
            'success', ('ok', '', 'yes', 'no', 'yes', network_name))
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1600
        # called twice, once from constructor and then again by us
1601
        client.add_expected_call(
1602
            'Branch.get_stacked_on_url', ('stacked/',),
1603
            'success', ('ok', '../base'))
1604
        client.add_expected_call(
1605
            'Branch.get_stacked_on_url', ('stacked/',),
1606
            '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.
1607
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
5712.3.17 by Jelmer Vernooij
more fixes.
1608
            RemoteBzrDirFormat(), _client=client)
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1609
        branch = bzrdir.open_branch()
1610
        result = branch.get_stacked_on_url()
1611
        self.assertEqual('../base', result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1612
        self.assertFinished(client)
4226.1.2 by Robert Collins
Fix test_remote failing because of less _real_repository objects.
1613
        # it's in the fallback list both for the RemoteRepository.
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1614
        self.assertEqual(1, len(branch.repository._fallback_repositories))
4226.1.2 by Robert Collins
Fix test_remote failing because of less _real_repository objects.
1615
        # And we haven't had to construct a real repository.
1616
        self.assertEqual(None, branch.repository._real_repository)
3691.2.11 by Martin Pool
More tests around RemoteBranch stacking.
1617
3691.2.5 by Martin Pool
Add Branch.get_stacked_on_url rpc and tests for same
1618
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1619
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.
1620
1621
    def test_set_empty(self):
5718.7.12 by Jelmer Vernooij
Fix use of _set_last_revision.
1622
        # _set_last_revision_info('null:') is translated to calling
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1623
        # Branch.set_last_revision(path, '') on the wire.
3104.4.2 by Andrew Bennetts
All tests passing.
1624
        transport = MemoryTransport()
1625
        transport.mkdir('branch')
1626
        transport = transport.clone('branch')
1627
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1628
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1629
        client.add_expected_call(
1630
            'Branch.get_stacked_on_url', ('branch/',),
1631
            'error', ('NotStacked',))
1632
        client.add_expected_call(
1633
            'Branch.lock_write', ('branch/', '', ''),
1634
            'success', ('ok', 'branch token', 'repo token'))
1635
        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.
1636
            'Branch.last_revision_info',
1637
            ('branch/',),
1638
            'success', ('ok', '0', 'null:'))
1639
        client.add_expected_call(
3691.2.10 by Martin Pool
Update more test_remote tests
1640
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'null:',),
1641
            'success', ('ok',))
1642
        client.add_expected_call(
1643
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1644
            'success', ('ok',))
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1645
        branch = self.make_remote_branch(transport, client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1646
        branch.lock_write()
5718.7.12 by Jelmer Vernooij
Fix use of _set_last_revision.
1647
        result = branch._set_last_revision(NULL_REVISION)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1648
        branch.unlock()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1649
        self.assertEqual(None, result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1650
        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.
1651
1652
    def test_set_nonempty(self):
5718.7.4 by Jelmer Vernooij
Branch.set_revision_history.
1653
        # set_last_revision_info(N, rev-idN) is translated to calling
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1654
        # Branch.set_last_revision(path, rev-idN) on the wire.
3104.4.2 by Andrew Bennetts
All tests passing.
1655
        transport = MemoryTransport()
1656
        transport.mkdir('branch')
1657
        transport = transport.clone('branch')
1658
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1659
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1660
        client.add_expected_call(
1661
            'Branch.get_stacked_on_url', ('branch/',),
1662
            'error', ('NotStacked',))
1663
        client.add_expected_call(
1664
            'Branch.lock_write', ('branch/', '', ''),
1665
            'success', ('ok', 'branch token', 'repo token'))
1666
        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.
1667
            'Branch.last_revision_info',
1668
            ('branch/',),
1669
            'success', ('ok', '0', 'null:'))
1670
        lines = ['rev-id2']
1671
        encoded_body = bz2.compress('\n'.join(lines))
1672
        client.add_success_response_with_body(encoded_body, 'ok')
1673
        client.add_expected_call(
3691.2.10 by Martin Pool
Update more test_remote tests
1674
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id2',),
1675
            'success', ('ok',))
1676
        client.add_expected_call(
1677
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1678
            'success', ('ok',))
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1679
        branch = self.make_remote_branch(transport, client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1680
        # Lock the branch, reset the record of remote calls.
1681
        branch.lock_write()
5718.7.12 by Jelmer Vernooij
Fix use of _set_last_revision.
1682
        result = branch._set_last_revision('rev-id2')
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1683
        branch.unlock()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1684
        self.assertEqual(None, result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1685
        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.
1686
1687
    def test_no_such_revision(self):
1688
        transport = MemoryTransport()
1689
        transport.mkdir('branch')
1690
        transport = transport.clone('branch')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1691
        # A response of 'NoSuchRevision' is translated into an exception.
1692
        client = FakeClient(transport.base)
3691.2.9 by Martin Pool
Convert and update more test_remote tests
1693
        client.add_expected_call(
1694
            'Branch.get_stacked_on_url', ('branch/',),
1695
            'error', ('NotStacked',))
1696
        client.add_expected_call(
1697
            'Branch.lock_write', ('branch/', '', ''),
1698
            'success', ('ok', 'branch token', 'repo token'))
1699
        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.
1700
            'Branch.last_revision_info',
1701
            ('branch/',),
1702
            'success', ('ok', '0', 'null:'))
1703
        # get_graph calls to construct the revision history, for the set_rh
1704
        # hook
1705
        lines = ['rev-id']
1706
        encoded_body = bz2.compress('\n'.join(lines))
1707
        client.add_success_response_with_body(encoded_body, 'ok')
1708
        client.add_expected_call(
3691.2.9 by Martin Pool
Convert and update more test_remote tests
1709
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
1710
            'error', ('NoSuchRevision', 'rev-id'))
1711
        client.add_expected_call(
1712
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1713
            'success', ('ok',))
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1714
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1715
        branch = self.make_remote_branch(transport, client)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1716
        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.
1717
        self.assertRaises(
5718.7.12 by Jelmer Vernooij
Fix use of _set_last_revision.
1718
            errors.NoSuchRevision, branch._set_last_revision, 'rev-id')
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1719
        branch.unlock()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1720
        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.
1721
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1722
    def test_tip_change_rejected(self):
1723
        """TipChangeRejected responses cause a TipChangeRejected exception to
1724
        be raised.
1725
        """
1726
        transport = MemoryTransport()
1727
        transport.mkdir('branch')
1728
        transport = transport.clone('branch')
1729
        client = FakeClient(transport.base)
1730
        rejection_msg_unicode = u'rejection message\N{INTERROBANG}'
1731
        rejection_msg_utf8 = rejection_msg_unicode.encode('utf8')
3691.2.10 by Martin Pool
Update more test_remote tests
1732
        client.add_expected_call(
1733
            'Branch.get_stacked_on_url', ('branch/',),
1734
            'error', ('NotStacked',))
1735
        client.add_expected_call(
1736
            'Branch.lock_write', ('branch/', '', ''),
1737
            'success', ('ok', 'branch token', 'repo token'))
1738
        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.
1739
            'Branch.last_revision_info',
1740
            ('branch/',),
1741
            'success', ('ok', '0', 'null:'))
1742
        lines = ['rev-id']
1743
        encoded_body = bz2.compress('\n'.join(lines))
1744
        client.add_success_response_with_body(encoded_body, 'ok')
1745
        client.add_expected_call(
3691.2.10 by Martin Pool
Update more test_remote tests
1746
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
1747
            'error', ('TipChangeRejected', rejection_msg_utf8))
1748
        client.add_expected_call(
1749
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1750
            'success', ('ok',))
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1751
        branch = self.make_remote_branch(transport, client)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1752
        branch.lock_write()
1753
        # The 'TipChangeRejected' error response triggered by calling
5718.7.4 by Jelmer Vernooij
Branch.set_revision_history.
1754
        # set_last_revision_info causes a TipChangeRejected exception.
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1755
        err = self.assertRaises(
5718.7.4 by Jelmer Vernooij
Branch.set_revision_history.
1756
            errors.TipChangeRejected,
5718.7.12 by Jelmer Vernooij
Fix use of _set_last_revision.
1757
            branch._set_last_revision, 'rev-id')
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1758
        # The UTF-8 message from the response has been decoded into a unicode
1759
        # object.
1760
        self.assertIsInstance(err.msg, unicode)
1761
        self.assertEqual(rejection_msg_unicode, err.msg)
3691.2.10 by Martin Pool
Update more test_remote tests
1762
        branch.unlock()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1763
        self.assertFinished(client)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1764
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1765
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1766
class TestBranchSetLastRevisionInfo(RemoteBranchTestCase):
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1767
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1768
    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.
1769
        # set_last_revision_info(num, 'rev-id') is translated to calling
1770
        # 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'.
1771
        transport = MemoryTransport()
1772
        transport.mkdir('branch')
1773
        transport = transport.clone('branch')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1774
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1775
        # get_stacked_on_url
1776
        client.add_error_response('NotStacked')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1777
        # lock_write
1778
        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.
1779
        # query the current revision
1780
        client.add_success_response('ok', '0', 'null:')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1781
        # set_last_revision
1782
        client.add_success_response('ok')
1783
        # unlock
1784
        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.
1785
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1786
        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.
1787
        # Lock the branch, reset the record of remote calls.
1788
        branch.lock_write()
1789
        client._calls = []
1790
        result = branch.set_last_revision_info(1234, 'a-revision-id')
1791
        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.
1792
            [('call', 'Branch.last_revision_info', ('branch/',)),
1793
             ('call', 'Branch.set_last_revision_info',
3297.4.1 by Andrew Bennetts
Merge 'Add Branch.set_last_revision_info smart method'.
1794
                ('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.
1795
                 '1234', 'a-revision-id'))],
1796
            client._calls)
1797
        self.assertEqual(None, result)
1798
1799
    def test_no_such_revision(self):
1800
        # A response of 'NoSuchRevision' is translated into an exception.
1801
        transport = MemoryTransport()
1802
        transport.mkdir('branch')
1803
        transport = transport.clone('branch')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1804
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1805
        # get_stacked_on_url
1806
        client.add_error_response('NotStacked')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1807
        # lock_write
1808
        client.add_success_response('ok', 'branch token', 'repo token')
1809
        # set_last_revision
1810
        client.add_error_response('NoSuchRevision', 'revid')
1811
        # unlock
1812
        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.
1813
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1814
        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.
1815
        # Lock the branch, reset the record of remote calls.
1816
        branch.lock_write()
1817
        client._calls = []
1818
1819
        self.assertRaises(
1820
            errors.NoSuchRevision, branch.set_last_revision_info, 123, 'revid')
1821
        branch.unlock()
1822
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1823
    def test_backwards_compatibility(self):
1824
        """If the server does not support the Branch.set_last_revision_info
1825
        verb (which is new in 1.4), then the client falls back to VFS methods.
1826
        """
1827
        # This test is a little messy.  Unlike most tests in this file, it
1828
        # doesn't purely test what a Remote* object sends over the wire, and
1829
        # how it reacts to responses from the wire.  It instead relies partly
1830
        # on asserting that the RemoteBranch will call
1831
        # self._real_branch.set_last_revision_info(...).
1832
1833
        # First, set up our RemoteBranch with a FakeClient that raises
1834
        # UnknownSmartMethod, and a StubRealBranch that logs how it is called.
1835
        transport = MemoryTransport()
1836
        transport.mkdir('branch')
1837
        transport = transport.clone('branch')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1838
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1839
        client.add_expected_call(
1840
            'Branch.get_stacked_on_url', ('branch/',),
1841
            'error', ('NotStacked',))
1842
        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.
1843
            'Branch.last_revision_info',
1844
            ('branch/',),
1845
            'success', ('ok', '0', 'null:'))
1846
        client.add_expected_call(
3691.2.10 by Martin Pool
Update more test_remote tests
1847
            'Branch.set_last_revision_info',
1848
            ('branch/', 'branch token', 'repo token', '1234', 'a-revision-id',),
1849
            'unknown', 'Branch.set_last_revision_info')
1850
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1851
        branch = self.make_remote_branch(transport, client)
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1852
        class StubRealBranch(object):
1853
            def __init__(self):
1854
                self.calls = []
1855
            def set_last_revision_info(self, revno, revision_id):
1856
                self.calls.append(
1857
                    ('set_last_revision_info', revno, revision_id))
3441.5.5 by Andrew Bennetts
Some small tweaks and comments.
1858
            def _clear_cached_state(self):
1859
                pass
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1860
        real_branch = StubRealBranch()
1861
        branch._real_branch = real_branch
1862
        self.lock_remote_branch(branch)
1863
1864
        # Call set_last_revision_info, and verify it behaved as expected.
1865
        result = branch.set_last_revision_info(1234, 'a-revision-id')
1866
        self.assertEqual(
1867
            [('set_last_revision_info', 1234, 'a-revision-id')],
1868
            real_branch.calls)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1869
        self.assertFinished(client)
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1870
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1871
    def test_unexpected_error(self):
3697.2.6 by Martin Pool
Merge 261315 fix into 1.7 branch
1872
        # If the server sends an error the client doesn't understand, it gets
1873
        # turned into an UnknownErrorFromSmartServer, which is presented as a
1874
        # non-internal error to the user.
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1875
        transport = MemoryTransport()
1876
        transport.mkdir('branch')
1877
        transport = transport.clone('branch')
1878
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1879
        # get_stacked_on_url
1880
        client.add_error_response('NotStacked')
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1881
        # lock_write
1882
        client.add_success_response('ok', 'branch token', 'repo token')
1883
        # set_last_revision
1884
        client.add_error_response('UnexpectedError')
1885
        # unlock
1886
        client.add_success_response('ok')
1887
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1888
        branch = self.make_remote_branch(transport, client)
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1889
        # Lock the branch, reset the record of remote calls.
1890
        branch.lock_write()
1891
        client._calls = []
1892
1893
        err = self.assertRaises(
3690.1.2 by Andrew Bennetts
Rename UntranslateableErrorFromSmartServer -> UnknownErrorFromSmartServer.
1894
            errors.UnknownErrorFromSmartServer,
3245.4.53 by Andrew Bennetts
Add some missing 'raise' statements to test_remote.
1895
            branch.set_last_revision_info, 123, 'revid')
1896
        self.assertEqual(('UnexpectedError',), err.error_tuple)
1897
        branch.unlock()
1898
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1899
    def test_tip_change_rejected(self):
1900
        """TipChangeRejected responses cause a TipChangeRejected exception to
1901
        be raised.
1902
        """
1903
        transport = MemoryTransport()
1904
        transport.mkdir('branch')
1905
        transport = transport.clone('branch')
1906
        client = FakeClient(transport.base)
3691.2.10 by Martin Pool
Update more test_remote tests
1907
        # get_stacked_on_url
1908
        client.add_error_response('NotStacked')
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1909
        # lock_write
1910
        client.add_success_response('ok', 'branch token', 'repo token')
1911
        # set_last_revision
1912
        client.add_error_response('TipChangeRejected', 'rejection message')
1913
        # unlock
1914
        client.add_success_response('ok')
1915
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
1916
        branch = self.make_remote_branch(transport, client)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
1917
        # Lock the branch, reset the record of remote calls.
1918
        branch.lock_write()
1919
        self.addCleanup(branch.unlock)
1920
        client._calls = []
1921
1922
        # The 'TipChangeRejected' error response triggered by calling
1923
        # set_last_revision_info causes a TipChangeRejected exception.
1924
        err = self.assertRaises(
1925
            errors.TipChangeRejected,
1926
            branch.set_last_revision_info, 123, 'revid')
1927
        self.assertEqual('rejection message', err.msg)
1928
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1929
4226.2.1 by Robert Collins
Set branch config options via a smart method.
1930
class TestBranchGetSetConfig(RemoteBranchTestCase):
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1931
1932
    def test_get_branch_conf(self):
4226.1.5 by Robert Collins
Reinstate the use of the Branch.get_config_file verb.
1933
        # in an empty branch we decode the response properly
1934
        client = FakeClient()
1935
        client.add_expected_call(
1936
            'Branch.get_stacked_on_url', ('memory:///',),
1937
            'error', ('NotStacked',),)
1938
        client.add_success_response_with_body('# config file body', 'ok')
1939
        transport = MemoryTransport()
1940
        branch = self.make_remote_branch(transport, client)
1941
        config = branch.get_config()
1942
        config.has_explicit_nickname()
1943
        self.assertEqual(
1944
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
1945
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
1946
            client._calls)
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1947
4241.5.2 by Matt Nordhoff
Add a test
1948
    def test_get_multi_line_branch_conf(self):
1949
        # Make sure that multiple-line branch.conf files are supported
1950
        #
5243.1.2 by Martin
Point launchpad links in comments at production server rather than edge
1951
        # https://bugs.launchpad.net/bzr/+bug/354075
4241.5.2 by Matt Nordhoff
Add a test
1952
        client = FakeClient()
1953
        client.add_expected_call(
1954
            'Branch.get_stacked_on_url', ('memory:///',),
1955
            'error', ('NotStacked',),)
1956
        client.add_success_response_with_body('a = 1\nb = 2\nc = 3\n', 'ok')
1957
        transport = MemoryTransport()
1958
        branch = self.make_remote_branch(transport, client)
1959
        config = branch.get_config()
1960
        self.assertEqual(u'2', config.get_user_option('b'))
1961
4226.2.1 by Robert Collins
Set branch config options via a smart method.
1962
    def test_set_option(self):
1963
        client = FakeClient()
1964
        client.add_expected_call(
1965
            'Branch.get_stacked_on_url', ('memory:///',),
1966
            'error', ('NotStacked',),)
1967
        client.add_expected_call(
1968
            'Branch.lock_write', ('memory:///', '', ''),
1969
            'success', ('ok', 'branch token', 'repo token'))
1970
        client.add_expected_call(
1971
            'Branch.set_config_option', ('memory:///', 'branch token',
1972
            'repo token', 'foo', 'bar', ''),
1973
            'success', ())
1974
        client.add_expected_call(
1975
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
1976
            'success', ('ok',))
1977
        transport = MemoryTransport()
1978
        branch = self.make_remote_branch(transport, client)
1979
        branch.lock_write()
1980
        config = branch._get_config()
1981
        config.set_option('foo', 'bar')
1982
        branch.unlock()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
1983
        self.assertFinished(client)
4226.2.1 by Robert Collins
Set branch config options via a smart method.
1984
5227.1.2 by Andrew Bennetts
Add Branch.set_config_option_dict RPC (and VFS fallback), fixes #430382.
1985
    def test_set_option_with_dict(self):
1986
        client = FakeClient()
1987
        client.add_expected_call(
1988
            'Branch.get_stacked_on_url', ('memory:///',),
1989
            'error', ('NotStacked',),)
1990
        client.add_expected_call(
1991
            'Branch.lock_write', ('memory:///', '', ''),
1992
            'success', ('ok', 'branch token', 'repo token'))
1993
        encoded_dict_value = 'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
1994
        client.add_expected_call(
1995
            'Branch.set_config_option_dict', ('memory:///', 'branch token',
1996
            'repo token', encoded_dict_value, 'foo', ''),
1997
            'success', ())
1998
        client.add_expected_call(
1999
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
2000
            'success', ('ok',))
2001
        transport = MemoryTransport()
2002
        branch = self.make_remote_branch(transport, client)
2003
        branch.lock_write()
2004
        config = branch._get_config()
2005
        config.set_option(
2006
            {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'},
2007
            'foo')
2008
        branch.unlock()
2009
        self.assertFinished(client)
2010
4226.2.1 by Robert Collins
Set branch config options via a smart method.
2011
    def test_backwards_compat_set_option(self):
2012
        self.setup_smart_server_with_call_log()
2013
        branch = self.make_branch('.')
2014
        verb = 'Branch.set_config_option'
2015
        self.disable_verb(verb)
2016
        branch.lock_write()
2017
        self.addCleanup(branch.unlock)
2018
        self.reset_smart_call_log()
2019
        branch._get_config().set_option('value', 'name')
6213.1.61 by Jelmer Vernooij
Fix tests.
2020
        self.assertLength(11, self.hpss_calls)
4226.2.1 by Robert Collins
Set branch config options via a smart method.
2021
        self.assertEqual('value', branch._get_config().get_option('name'))
2022
5227.1.2 by Andrew Bennetts
Add Branch.set_config_option_dict RPC (and VFS fallback), fixes #430382.
2023
    def test_backwards_compat_set_option_with_dict(self):
2024
        self.setup_smart_server_with_call_log()
2025
        branch = self.make_branch('.')
2026
        verb = 'Branch.set_config_option_dict'
2027
        self.disable_verb(verb)
2028
        branch.lock_write()
2029
        self.addCleanup(branch.unlock)
2030
        self.reset_smart_call_log()
2031
        config = branch._get_config()
2032
        value_dict = {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
2033
        config.set_option(value_dict, 'name')
6213.1.61 by Jelmer Vernooij
Fix tests.
2034
        self.assertLength(11, self.hpss_calls)
5227.1.2 by Andrew Bennetts
Add Branch.set_config_option_dict RPC (and VFS fallback), fixes #430382.
2035
        self.assertEqual(value_dict, branch._get_config().get_option('name'))
2036
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
2037
6270.1.23 by Jelmer Vernooij
Add notes about Remote{Control,Branch}Store.
2038
class TestBranchGetPutConfigStore(RemoteBranchTestCase):
6270.1.10 by Jelmer Vernooij
Fix testing Branch.set_config_file.
2039
2040
    def test_get_branch_conf(self):
2041
        # in an empty branch we decode the response properly
2042
        client = FakeClient()
2043
        client.add_expected_call(
2044
            'Branch.get_stacked_on_url', ('memory:///',),
2045
            'error', ('NotStacked',),)
2046
        client.add_success_response_with_body('# config file body', 'ok')
2047
        transport = MemoryTransport()
2048
        branch = self.make_remote_branch(transport, client)
2049
        config = branch.get_config_stack()
2050
        config.get("email")
2051
        config.get("log_format")
2052
        self.assertEqual(
2053
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
2054
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
2055
            client._calls)
2056
2057
    def test_set_branch_conf(self):
2058
        client = FakeClient()
2059
        client.add_expected_call(
2060
            'Branch.get_stacked_on_url', ('memory:///',),
2061
            'error', ('NotStacked',),)
2062
        client.add_expected_call(
2063
            'Branch.lock_write', ('memory:///', '', ''),
2064
            'success', ('ok', 'branch token', 'repo token'))
2065
        client.add_expected_call(
2066
            'Branch.get_config_file', ('memory:///', ),
2067
            'success', ('ok', ), "# line 1\n")
2068
        client.add_expected_call(
6404.6.1 by Vincent Ladeuil
Tests passing for a first rough version of a cached branch config store. The changes here are too invasive and several parallel proposals have been made.
2069
            'Branch.get_config_file', ('memory:///', ),
2070
            'success', ('ok', ), "# line 1\n")
2071
        client.add_expected_call(
6270.1.17 by Jelmer Vernooij
s/set_config_file/put_config_file.
2072
            'Branch.put_config_file', ('memory:///', 'branch token',
6270.1.10 by Jelmer Vernooij
Fix testing Branch.set_config_file.
2073
            'repo token'),
6270.1.16 by Jelmer Vernooij
Expect 'ok' response from set_config_file.
2074
            'success', ('ok',))
6270.1.10 by Jelmer Vernooij
Fix testing Branch.set_config_file.
2075
        client.add_expected_call(
2076
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
2077
            'success', ('ok',))
2078
        transport = MemoryTransport()
2079
        branch = self.make_remote_branch(transport, client)
2080
        branch.lock_write()
2081
        config = branch.get_config_stack()
2082
        config.set('email', 'The Dude <lebowski@example.com>')
2083
        branch.unlock()
2084
        self.assertFinished(client)
2085
        self.assertEqual(
2086
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
2087
             ('call', 'Branch.lock_write', ('memory:///', '', '')),
2088
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',)),
6404.6.1 by Vincent Ladeuil
Tests passing for a first rough version of a cached branch config store. The changes here are too invasive and several parallel proposals have been made.
2089
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',)),
6270.1.18 by Jelmer Vernooij
Fix a test.
2090
             ('call_with_body_bytes_expecting_body', 'Branch.put_config_file',
6270.1.10 by Jelmer Vernooij
Fix testing Branch.set_config_file.
2091
                 ('memory:///', 'branch token', 'repo token'),
2092
                 '# line 1\nemail = The Dude <lebowski@example.com>\n'),
2093
             ('call', 'Branch.unlock', ('memory:///', 'branch token', 'repo token'))],
2094
            client._calls)
2095
2096
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
2097
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.
2098
2099
    def test_lock_write_unlockable(self):
2100
        transport = MemoryTransport()
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2101
        client = FakeClient(transport.base)
3691.2.9 by Martin Pool
Convert and update more test_remote tests
2102
        client.add_expected_call(
2103
            'Branch.get_stacked_on_url', ('quack/',),
2104
            'error', ('NotStacked',),)
2105
        client.add_expected_call(
2106
            'Branch.lock_write', ('quack/', '', ''),
2107
            '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.
2108
        transport.mkdir('quack')
2109
        transport = transport.clone('quack')
3692.1.1 by Andrew Bennetts
Make RemoteBranch.lock_write lock the repository too.
2110
        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.
2111
        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.
2112
        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.
2113
2114
6263.1.3 by Jelmer Vernooij
Add dotted revno test.
2115
class TestBranchRevisionIdToRevno(RemoteBranchTestCase):
2116
2117
    def test_simple(self):
2118
        transport = MemoryTransport()
2119
        client = FakeClient(transport.base)
2120
        client.add_expected_call(
2121
            'Branch.get_stacked_on_url', ('quack/',),
2122
            'error', ('NotStacked',),)
2123
        client.add_expected_call(
2124
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
2125
            'success', ('ok', '0',),)
2126
        client.add_expected_call(
2127
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
2128
            'error', ('NoSuchRevision', 'unknown',),)
2129
        transport.mkdir('quack')
2130
        transport = transport.clone('quack')
2131
        branch = self.make_remote_branch(transport, client)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2132
        self.assertEqual(0, branch.revision_id_to_revno('null:'))
6263.1.3 by Jelmer Vernooij
Add dotted revno test.
2133
        self.assertRaises(errors.NoSuchRevision,
2134
            branch.revision_id_to_revno, 'unknown')
2135
        self.assertFinished(client)
2136
2137
    def test_dotted(self):
2138
        transport = MemoryTransport()
2139
        client = FakeClient(transport.base)
2140
        client.add_expected_call(
2141
            'Branch.get_stacked_on_url', ('quack/',),
2142
            'error', ('NotStacked',),)
2143
        client.add_expected_call(
2144
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
2145
            'success', ('ok', '0',),)
2146
        client.add_expected_call(
2147
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
2148
            'error', ('NoSuchRevision', 'unknown',),)
2149
        transport.mkdir('quack')
2150
        transport = transport.clone('quack')
2151
        branch = self.make_remote_branch(transport, client)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2152
        self.assertEqual((0, ), branch.revision_id_to_dotted_revno('null:'))
6263.1.3 by Jelmer Vernooij
Add dotted revno test.
2153
        self.assertRaises(errors.NoSuchRevision,
2154
            branch.revision_id_to_dotted_revno, 'unknown')
2155
        self.assertFinished(client)
2156
6305.1.1 by Jelmer Vernooij
Add test for Branch.revision_id_to_dotted_revno fallback.
2157
    def test_dotted_no_smart_verb(self):
2158
        self.setup_smart_server_with_call_log()
2159
        branch = self.make_branch('.')
2160
        self.disable_verb('Branch.revision_id_to_revno')
2161
        self.reset_smart_call_log()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2162
        self.assertEqual((0, ),
6305.1.1 by Jelmer Vernooij
Add test for Branch.revision_id_to_dotted_revno fallback.
2163
            branch.revision_id_to_dotted_revno('null:'))
6213.1.61 by Jelmer Vernooij
Fix tests.
2164
        self.assertLength(8, self.hpss_calls)
6305.1.1 by Jelmer Vernooij
Add test for Branch.revision_id_to_dotted_revno fallback.
2165
6263.1.3 by Jelmer Vernooij
Add dotted revno test.
2166
4288.1.1 by Robert Collins
Add support for a RemoteBzrDirConfig to support optimising push operations which need to look for default stacking locations.
2167
class TestBzrDirGetSetConfig(RemoteBzrDirTestCase):
2168
2169
    def test__get_config(self):
2170
        client = FakeClient()
2171
        client.add_success_response_with_body('default_stack_on = /\n', 'ok')
2172
        transport = MemoryTransport()
2173
        bzrdir = self.make_remote_bzrdir(transport, client)
2174
        config = bzrdir.get_config()
2175
        self.assertEqual('/', config.get_default_stack_on())
2176
        self.assertEqual(
2177
            [('call_expecting_body', 'BzrDir.get_config_file', ('memory:///',))],
2178
            client._calls)
2179
2180
    def test_set_option_uses_vfs(self):
2181
        self.setup_smart_server_with_call_log()
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
2182
        bzrdir = self.make_controldir('.')
4288.1.1 by Robert Collins
Add support for a RemoteBzrDirConfig to support optimising push operations which need to look for default stacking locations.
2183
        self.reset_smart_call_log()
2184
        config = bzrdir.get_config()
2185
        config.set_default_stack_on('/')
6213.1.61 by Jelmer Vernooij
Fix tests.
2186
        self.assertLength(4, self.hpss_calls)
4288.1.1 by Robert Collins
Add support for a RemoteBzrDirConfig to support optimising push operations which need to look for default stacking locations.
2187
2188
    def test_backwards_compat_get_option(self):
2189
        self.setup_smart_server_with_call_log()
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
2190
        bzrdir = self.make_controldir('.')
4288.1.1 by Robert Collins
Add support for a RemoteBzrDirConfig to support optimising push operations which need to look for default stacking locations.
2191
        verb = 'BzrDir.get_config_file'
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
2192
        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.
2193
        self.reset_smart_call_log()
2194
        self.assertEqual(None,
2195
            bzrdir._get_config().get_option('default_stack_on'))
6213.1.61 by Jelmer Vernooij
Fix tests.
2196
        self.assertLength(4, self.hpss_calls)
4288.1.1 by Robert Collins
Add support for a RemoteBzrDirConfig to support optimising push operations which need to look for default stacking locations.
2197
2198
2466.2.2 by Andrew Bennetts
Add tests for RemoteTransport.is_readonly in the style of the other remote object tests.
2199
class TestTransportIsReadonly(tests.TestCase):
2200
2201
    def test_true(self):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2202
        client = FakeClient()
2203
        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.
2204
        transport = RemoteTransport('bzr://example.com/', medium=False,
2205
                                    _client=client)
2206
        self.assertEqual(True, transport.is_readonly())
2207
        self.assertEqual(
2208
            [('call', 'Transport.is_readonly', ())],
2209
            client._calls)
2210
2211
    def test_false(self):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2212
        client = FakeClient()
2213
        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.
2214
        transport = RemoteTransport('bzr://example.com/', medium=False,
2215
                                    _client=client)
2216
        self.assertEqual(False, transport.is_readonly())
2217
        self.assertEqual(
2218
            [('call', 'Transport.is_readonly', ())],
2219
            client._calls)
2220
2221
    def test_error_from_old_server(self):
2222
        """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
2223
2466.2.2 by Andrew Bennetts
Add tests for RemoteTransport.is_readonly in the style of the other remote object tests.
2224
        Clients should treat it as a "no" response, because is_readonly is only
2225
        advisory anyway (a transport could be read-write, but then the
2226
        underlying filesystem could be readonly anyway).
2227
        """
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2228
        client = FakeClient()
2229
        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.
2230
        transport = RemoteTransport('bzr://example.com/', medium=False,
2231
                                    _client=client)
2232
        self.assertEqual(False, transport.is_readonly())
2233
        self.assertEqual(
2234
            [('call', 'Transport.is_readonly', ())],
2235
            client._calls)
2236
2466.2.2 by Andrew Bennetts
Add tests for RemoteTransport.is_readonly in the style of the other remote object tests.
2237
3840.1.1 by Andrew Bennetts
Fix RemoteTransport's translation of errors involving paths; it wasn't passing orig_path to _translate_error.
2238
class TestTransportMkdir(tests.TestCase):
2239
2240
    def test_permissiondenied(self):
2241
        client = FakeClient()
2242
        client.add_error_response('PermissionDenied', 'remote path', 'extra')
2243
        transport = RemoteTransport('bzr://example.com/', medium=False,
2244
                                    _client=client)
2245
        exc = self.assertRaises(
2246
            errors.PermissionDenied, transport.mkdir, 'client path')
2247
        expected_error = errors.PermissionDenied('/client path', 'extra')
2248
        self.assertEqual(expected_error, exc)
2249
2250
3777.1.3 by Aaron Bentley
Use SSH default username from authentication.conf
2251
class TestRemoteSSHTransportAuthentication(tests.TestCaseInTempDir):
2252
4304.2.1 by Vincent Ladeuil
Fix bug #367726 by reverting some default user handling introduced
2253
    def test_defaults_to_none(self):
3777.1.3 by Aaron Bentley
Use SSH default username from authentication.conf
2254
        t = RemoteSSHTransport('bzr+ssh://example.com')
4304.2.1 by Vincent Ladeuil
Fix bug #367726 by reverting some default user handling introduced
2255
        self.assertIs(None, t._get_credentials()[0])
3777.1.3 by Aaron Bentley
Use SSH default username from authentication.conf
2256
2257
    def test_uses_authentication_config(self):
2258
        conf = config.AuthenticationConfig()
2259
        conf._get_config().update(
2260
            {'bzr+sshtest': {'scheme': 'ssh', 'user': 'bar', 'host':
2261
            'example.com'}})
2262
        conf._save()
2263
        t = RemoteSSHTransport('bzr+ssh://example.com')
2264
        self.assertEqual('bar', t._get_credentials()[0])
2265
2266
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
2267
class TestRemoteRepository(TestRemote):
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
2268
    """Base for testing RemoteRepository protocol usage.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2269
2270
    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
2271
    what is sent or expected to be require a thoughtful update to these tests
2272
    because they might break compatibility with different-versioned servers.
2273
    """
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
2274
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2275
    def setup_fake_client_and_repository(self, transport_path):
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
2276
        """Create the fake client and repository for testing with.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2277
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
2278
        There's no real server here; we just have canned responses sent
2279
        back one by one.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2280
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
2281
        :param transport_path: Path below the root of the MemoryTransport
2282
            where the repository will be created.
2283
        """
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
2284
        transport = MemoryTransport()
2285
        transport.mkdir(transport_path)
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2286
        client = FakeClient(transport.base)
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
2287
        transport = transport.clone(transport_path)
2288
        # we do not want bzrdir to make any remote calls
5712.3.17 by Jelmer Vernooij
more fixes.
2289
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
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.
2290
            _client=False)
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
2291
        repo = RemoteRepository(bzrdir, None, _client=client)
2292
        return repo, client
2293
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
2294
4792.1.1 by Andrew Bennetts
Show real branch/repo format description in 'info -v' over HPSS.
2295
def remoted_description(format):
2296
    return 'Remote: ' + format.get_format_description()
2297
2298
2299
class TestBranchFormat(tests.TestCase):
2300
2301
    def test_get_format_description(self):
2302
        remote_format = RemoteBranchFormat()
5662.2.2 by Jelmer Vernooij
Move most format registration functions to BranchFormatRegistry.
2303
        real_format = branch.format_registry.get_default()
4792.1.1 by Andrew Bennetts
Show real branch/repo format description in 'info -v' over HPSS.
2304
        remote_format._network_name = real_format.network_name()
2305
        self.assertEqual(remoted_description(real_format),
2306
            remote_format.get_format_description())
2307
2308
4183.5.1 by Robert Collins
Add RepositoryFormat.fast_deltas to signal fast delta creation.
2309
class TestRepositoryFormat(TestRemoteRepository):
2310
2311
    def test_fast_delta(self):
5546.1.1 by Andrew Bennetts
Remove RepositoryFormatCHK1 and RepositoryFormatCHK2.
2312
        true_name = groupcompress_repo.RepositoryFormat2a().network_name()
4183.5.1 by Robert Collins
Add RepositoryFormat.fast_deltas to signal fast delta creation.
2313
        true_format = RemoteRepositoryFormat()
2314
        true_format._network_name = true_name
2315
        self.assertEqual(True, true_format.fast_deltas)
5757.1.7 by Jelmer Vernooij
Fix more imports.
2316
        false_name = knitpack_repo.RepositoryFormatKnitPack1().network_name()
4183.5.1 by Robert Collins
Add RepositoryFormat.fast_deltas to signal fast delta creation.
2317
        false_format = RemoteRepositoryFormat()
2318
        false_format._network_name = false_name
2319
        self.assertEqual(False, false_format.fast_deltas)
2320
4792.1.1 by Andrew Bennetts
Show real branch/repo format description in 'info -v' over HPSS.
2321
    def test_get_format_description(self):
2322
        remote_repo_format = RemoteRepositoryFormat()
5651.3.9 by Jelmer Vernooij
Avoid using deprecated functions.
2323
        real_format = repository.format_registry.get_default()
4792.1.1 by Andrew Bennetts
Show real branch/repo format description in 'info -v' over HPSS.
2324
        remote_repo_format._network_name = real_format.network_name()
2325
        self.assertEqual(remoted_description(real_format),
2326
            remote_repo_format.get_format_description())
2327
4183.5.1 by Robert Collins
Add RepositoryFormat.fast_deltas to signal fast delta creation.
2328
6280.3.1 by Jelmer Vernooij
Add remote side of Repository.all_revision_ids.
2329
class TestRepositoryAllRevisionIds(TestRemoteRepository):
2330
2331
    def test_empty(self):
2332
        transport_path = 'quack'
2333
        repo, client = self.setup_fake_client_and_repository(transport_path)
2334
        client.add_success_response_with_body('', 'ok')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2335
        self.assertEqual([], repo.all_revision_ids())
6280.3.1 by Jelmer Vernooij
Add remote side of Repository.all_revision_ids.
2336
        self.assertEqual(
2337
            [('call_expecting_body', 'Repository.all_revision_ids',
2338
             ('quack/',))],
2339
            client._calls)
2340
2341
    def test_with_some_content(self):
2342
        transport_path = 'quack'
2343
        repo, client = self.setup_fake_client_and_repository(transport_path)
2344
        client.add_success_response_with_body(
2345
            'rev1\nrev2\nanotherrev\n', 'ok')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2346
        self.assertEqual(["rev1", "rev2", "anotherrev"],
6280.3.1 by Jelmer Vernooij
Add remote side of Repository.all_revision_ids.
2347
            repo.all_revision_ids())
2348
        self.assertEqual(
2349
            [('call_expecting_body', 'Repository.all_revision_ids',
2350
             ('quack/',))],
2351
            client._calls)
2352
2353
2018.12.2 by Andrew Bennetts
Remove some duplicate code in test_remote
2354
class TestRepositoryGatherStats(TestRemoteRepository):
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2355
2356
    def test_revid_none(self):
2357
        # ('ok',), body with revisions and size
2358
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2359
        repo, client = self.setup_fake_client_and_repository(transport_path)
2360
        client.add_success_response_with_body(
2361
            'revisions: 2\nsize: 18\n', 'ok')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2362
        result = repo.gather_stats(None)
2363
        self.assertEqual(
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
2364
            [('call_expecting_body', 'Repository.gather_stats',
3104.4.2 by Andrew Bennetts
All tests passing.
2365
             ('quack/','','no'))],
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2366
            client._calls)
2367
        self.assertEqual({'revisions': 2, 'size': 18}, result)
2368
2369
    def test_revid_no_committers(self):
2370
        # ('ok',), body without committers
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2371
        body = ('firstrev: 123456.300 3600\n'
2372
                'latestrev: 654231.400 0\n'
2373
                'revisions: 2\n'
2374
                'size: 18\n')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2375
        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.
2376
        revid = u'\xc8'.encode('utf8')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2377
        repo, client = self.setup_fake_client_and_repository(transport_path)
2378
        client.add_success_response_with_body(body, 'ok')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2379
        result = repo.gather_stats(revid)
2380
        self.assertEqual(
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
2381
            [('call_expecting_body', 'Repository.gather_stats',
3104.4.2 by Andrew Bennetts
All tests passing.
2382
              ('quick/', revid, 'no'))],
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2383
            client._calls)
2384
        self.assertEqual({'revisions': 2, 'size': 18,
2385
                          'firstrev': (123456.300, 3600),
2386
                          'latestrev': (654231.400, 0),},
2387
                         result)
2388
2389
    def test_revid_with_committers(self):
2390
        # ('ok',), body with committers
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2391
        body = ('committers: 128\n'
2392
                'firstrev: 123456.300 3600\n'
2393
                'latestrev: 654231.400 0\n'
2394
                'revisions: 2\n'
2395
                'size: 18\n')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2396
        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.
2397
        revid = u'\xc8'.encode('utf8')
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2398
        repo, client = self.setup_fake_client_and_repository(transport_path)
2399
        client.add_success_response_with_body(body, 'ok')
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2400
        result = repo.gather_stats(revid, True)
2401
        self.assertEqual(
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
2402
            [('call_expecting_body', 'Repository.gather_stats',
3104.4.2 by Andrew Bennetts
All tests passing.
2403
              ('buick/', revid, 'yes'))],
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
2404
            client._calls)
2405
        self.assertEqual({'revisions': 2, 'size': 18,
2406
                          'committers': 128,
2407
                          'firstrev': (123456.300, 3600),
2408
                          'latestrev': (654231.400, 0),},
2409
                         result)
2410
2411
6280.4.1 by Jelmer Vernooij
Add remote side of Repository.break_lock.
2412
class TestRepositoryBreakLock(TestRemoteRepository):
2413
2414
    def test_break_lock(self):
2415
        transport_path = 'quack'
2416
        repo, client = self.setup_fake_client_and_repository(transport_path)
2417
        client.add_success_response('ok')
2418
        repo.break_lock()
2419
        self.assertEqual(
6280.4.6 by Jelmer Vernooij
Fix test.
2420
            [('call', 'Repository.break_lock', ('quack/',))],
6280.4.1 by Jelmer Vernooij
Add remote side of Repository.break_lock.
2421
            client._calls)
2422
2423
6280.5.1 by Jelmer Vernooij
Add client side of Repository.get_serializer_format.
2424
class TestRepositoryGetSerializerFormat(TestRemoteRepository):
2425
2426
    def test_get_serializer_format(self):
2427
        transport_path = 'hill'
2428
        repo, client = self.setup_fake_client_and_repository(transport_path)
2429
        client.add_success_response('ok', '7')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2430
        self.assertEqual('7', repo.get_serializer_format())
6280.5.1 by Jelmer Vernooij
Add client side of Repository.get_serializer_format.
2431
        self.assertEqual(
2432
            [('call', 'VersionedFileRepository.get_serializer_format',
2433
              ('hill/', ))],
2434
            client._calls)
2435
2436
6300.1.1 by Jelmer Vernooij
Add remote implementation of RemoteRepository.reconcile.
2437
class TestRepositoryReconcile(TestRemoteRepository):
2438
2439
    def test_reconcile(self):
2440
        transport_path = 'hill'
2441
        repo, client = self.setup_fake_client_and_repository(transport_path)
6300.1.4 by Jelmer Vernooij
Add reconcile results.
2442
        body = ("garbage_inventories: 2\n"
2443
                "inconsistent_parents: 3\n")
6300.1.7 by Jelmer Vernooij
Fix test.
2444
        client.add_expected_call(
2445
            'Repository.lock_write', ('hill/', ''),
2446
            'success', ('ok', 'a token'))
6300.1.4 by Jelmer Vernooij
Add reconcile results.
2447
        client.add_success_response_with_body(body, 'ok')
2448
        reconciler = repo.reconcile()
6300.1.1 by Jelmer Vernooij
Add remote implementation of RemoteRepository.reconcile.
2449
        self.assertEqual(
6300.1.7 by Jelmer Vernooij
Fix test.
2450
            [('call', 'Repository.lock_write', ('hill/', '')),
2451
             ('call_expecting_body', 'Repository.reconcile',
2452
                ('hill/', 'a token'))],
6300.1.1 by Jelmer Vernooij
Add remote implementation of RemoteRepository.reconcile.
2453
            client._calls)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2454
        self.assertEqual(2, reconciler.garbage_inventories)
2455
        self.assertEqual(3, reconciler.inconsistent_parents)
6300.1.1 by Jelmer Vernooij
Add remote implementation of RemoteRepository.reconcile.
2456
2457
6263.3.2 by Jelmer Vernooij
Add new HPSS call 'Repository.get_revision_signature_text'.
2458
class TestRepositoryGetRevisionSignatureText(TestRemoteRepository):
2459
2460
    def test_text(self):
2461
        # ('ok',), body with signature text
2462
        transport_path = 'quack'
2463
        repo, client = self.setup_fake_client_and_repository(transport_path)
2464
        client.add_success_response_with_body(
2465
            'THETEXT', 'ok')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2466
        self.assertEqual("THETEXT", repo.get_signature_text("revid"))
6263.3.2 by Jelmer Vernooij
Add new HPSS call 'Repository.get_revision_signature_text'.
2467
        self.assertEqual(
2468
            [('call_expecting_body', 'Repository.get_revision_signature_text',
2469
             ('quack/', 'revid'))],
2470
            client._calls)
2471
2472
    def test_no_signature(self):
2473
        transport_path = 'quick'
2474
        repo, client = self.setup_fake_client_and_repository(transport_path)
2475
        client.add_error_response('nosuchrevision', 'unknown')
2476
        self.assertRaises(errors.NoSuchRevision, repo.get_signature_text,
2477
                "unknown")
2478
        self.assertEqual(
2479
            [('call_expecting_body', 'Repository.get_revision_signature_text',
2480
              ('quick/', 'unknown'))],
2481
            client._calls)
2482
2483
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
2484
class TestRepositoryGetGraph(TestRemoteRepository):
2485
2486
    def test_get_graph(self):
3835.1.6 by Aaron Bentley
Reduce inefficiency when doing make_parents_provider frequently
2487
        # 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.
2488
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2489
        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.
2490
        graph = repo.get_graph()
3835.1.6 by Aaron Bentley
Reduce inefficiency when doing make_parents_provider frequently
2491
        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.
2492
2493
6268.1.2 by Jelmer Vernooij
Initial work on Repository.add_signature_text.
2494
class TestRepositoryAddSignatureText(TestRemoteRepository):
2495
2496
    def test_add_signature_text(self):
2497
        transport_path = 'quack'
2498
        repo, client = self.setup_fake_client_and_repository(transport_path)
6280.10.32 by Jelmer Vernooij
Merge bzr.dev.
2499
        client.add_expected_call(
2500
            'Repository.lock_write', ('quack/', ''),
2501
            'success', ('ok', 'a token'))
2502
        client.add_expected_call(
2503
            'Repository.start_write_group', ('quack/', 'a token'),
2504
            'success', ('ok', ('token1', )))
2505
        client.add_expected_call(
2506
            'Repository.add_signature_text', ('quack/', 'a token', 'rev1',
2507
                'token1'),
2508
            'success', ('ok', ), None)
2509
        repo.lock_write()
2510
        repo.start_write_group()
6268.1.2 by Jelmer Vernooij
Initial work on Repository.add_signature_text.
2511
        self.assertIs(None,
2512
            repo.add_signature_text("rev1", "every bloody emperor"))
2513
        self.assertEqual(
6280.10.39 by Jelmer Vernooij
Merge bzr.dev.
2514
            ('call_with_body_bytes_expecting_body',
6280.10.32 by Jelmer Vernooij
Merge bzr.dev.
2515
              'Repository.add_signature_text',
2516
                ('quack/', 'a token', 'rev1', 'token1'),
2517
              'every bloody emperor'),
2518
            client._calls[-1])
6268.1.2 by Jelmer Vernooij
Initial work on Repository.add_signature_text.
2519
2520
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
2521
class TestRepositoryGetParentMap(TestRemoteRepository):
2522
2523
    def test_get_parent_map_caching(self):
2524
        # get_parent_map returns from cache until unlock()
2525
        # setup a reponse with two revisions
2526
        r1 = u'\u0e33'.encode('utf8')
2527
        r2 = u'\u0dab'.encode('utf8')
2528
        lines = [' '.join([r2, r1]), r1]
3211.5.2 by Robert Collins
Change RemoteRepository.get_parent_map to use bz2 not gzip for compression.
2529
        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.
2530
2531
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2532
        repo, client = self.setup_fake_client_and_repository(transport_path)
2533
        client.add_success_response_with_body(encoded_body, 'ok')
2534
        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.
2535
        repo.lock_read()
2536
        graph = repo.get_graph()
2537
        parents = graph.get_parent_map([r2])
2538
        self.assertEqual({r2: (r1,)}, parents)
2539
        # locking and unlocking deeper should not reset
2540
        repo.lock_read()
2541
        repo.unlock()
2542
        parents = graph.get_parent_map([r1])
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
2543
        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.
2544
        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.
2545
            [('call_with_body_bytes_expecting_body',
4190.1.6 by Robert Collins
Missed some unit tests.
2546
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
2547
              '\n\n0')],
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
2548
            client._calls)
2549
        repo.unlock()
2550
        # now we call again, and it should use the second response.
2551
        repo.lock_read()
2552
        graph = repo.get_graph()
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
2553
        parents = graph.get_parent_map([r1])
2554
        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.
2555
        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.
2556
            [('call_with_body_bytes_expecting_body',
4190.1.6 by Robert Collins
Missed some unit tests.
2557
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
2558
              '\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.
2559
             ('call_with_body_bytes_expecting_body',
4190.1.6 by Robert Collins
Missed some unit tests.
2560
              'Repository.get_parent_map', ('quack/', 'include-missing:', r1),
2561
              '\n\n0'),
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
2562
            ],
2563
            client._calls)
2564
        repo.unlock()
2565
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
2566
    def test_get_parent_map_reconnects_if_unknown_method(self):
2567
        transport_path = 'quack'
3948.3.7 by Martin Pool
Updated tests for RemoteRepository.get_parent_map on old servers.
2568
        rev_id = 'revision-id'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2569
        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.
2570
        client.add_unknown_method_response('Repository.get_parent_map')
2571
        client.add_success_response_with_body(rev_id, 'ok')
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
2572
        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.
2573
        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.
2574
        self.assertEqual(
3213.1.8 by Andrew Bennetts
Merge from bzr.dev.
2575
            [('call_with_body_bytes_expecting_body',
6015.23.17 by John Arbash Meinel
Code was relying on an empty parent map to yield an empty search.
2576
              'Repository.get_parent_map',
2577
              ('quack/', 'include-missing:', rev_id), '\n\n0'),
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
2578
             ('disconnect medium',),
2579
             ('call_expecting_body', 'Repository.get_revision_graph',
2580
              ('quack/', ''))],
2581
            client._calls)
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
2582
        # 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.
2583
        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.
2584
        self.assertEqual({rev_id: ('null:',)}, parents)
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
2585
2586
    def test_get_parent_map_fallback_parentless_node(self):
2587
        """get_parent_map falls back to get_revision_graph on old servers.  The
2588
        results from get_revision_graph are tweaked to match the get_parent_map
2589
        API.
2590
3389.1.3 by Andrew Bennetts
Remove XXX from test description.
2591
        Specifically, a {key: ()} result from get_revision_graph means "no
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
2592
        parents" for that key, which in get_parent_map results should be
3389.1.3 by Andrew Bennetts
Remove XXX from test description.
2593
        represented as {key: ('null:',)}.
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
2594
2595
        This is the test for https://bugs.launchpad.net/bzr/+bug/214894
2596
        """
2597
        rev_id = 'revision-id'
2598
        transport_path = 'quack'
3245.4.40 by Andrew Bennetts
Merge from bzr.dev.
2599
        repo, client = self.setup_fake_client_and_repository(transport_path)
2600
        client.add_success_response_with_body(rev_id, 'ok')
3453.4.9 by Andrew Bennetts
Rename _remote_is_not to _remember_remote_is_before.
2601
        client._medium._remember_remote_is_before((1, 2))
3948.3.7 by Martin Pool
Updated tests for RemoteRepository.get_parent_map on old servers.
2602
        parents = repo.get_parent_map([rev_id])
3389.1.2 by Andrew Bennetts
Add test for the bug John found.
2603
        self.assertEqual(
2604
            [('call_expecting_body', 'Repository.get_revision_graph',
2605
             ('quack/', ''))],
2606
            client._calls)
2607
        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.
2608
3297.2.3 by Andrew Bennetts
Test the code path that the typo is on.
2609
    def test_get_parent_map_unexpected_response(self):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2610
        repo, client = self.setup_fake_client_and_repository('path')
2611
        client.add_success_response('something unexpected!')
3297.2.3 by Andrew Bennetts
Test the code path that the typo is on.
2612
        self.assertRaises(
2613
            errors.UnexpectedSmartServerResponse,
2614
            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.
2615
4190.1.1 by Robert Collins
Negatively cache misses during read-locks in RemoteRepository.
2616
    def test_get_parent_map_negative_caches_missing_keys(self):
2617
        self.setup_smart_server_with_call_log()
2618
        repo = self.make_repository('foo')
2619
        self.assertIsInstance(repo, RemoteRepository)
2620
        repo.lock_read()
2621
        self.addCleanup(repo.unlock)
2622
        self.reset_smart_call_log()
2623
        graph = repo.get_graph()
2624
        self.assertEqual({},
2625
            graph.get_parent_map(['some-missing', 'other-missing']))
2626
        self.assertLength(1, self.hpss_calls)
2627
        # No call if we repeat this
2628
        self.reset_smart_call_log()
2629
        graph = repo.get_graph()
2630
        self.assertEqual({},
2631
            graph.get_parent_map(['some-missing', 'other-missing']))
2632
        self.assertLength(0, self.hpss_calls)
2633
        # Asking for more unknown keys makes a request.
2634
        self.reset_smart_call_log()
2635
        graph = repo.get_graph()
2636
        self.assertEqual({},
2637
            graph.get_parent_map(['some-missing', 'other-missing',
2638
                'more-missing']))
2639
        self.assertLength(1, self.hpss_calls)
2640
4214.2.1 by Andrew Bennetts
A long but failing test for the get_parent_map RPC bug.
2641
    def disableExtraResults(self):
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
2642
        self.overrideAttr(SmartServerRepositoryGetParentMap,
2643
                          'no_extra_results', True)
4214.2.1 by Andrew Bennetts
A long but failing test for the get_parent_map RPC bug.
2644
4214.2.5 by Andrew Bennetts
Fix the bug.
2645
    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.
2646
        self.setup_smart_server_with_call_log()
4214.2.4 by Andrew Bennetts
Further simplify the test to reproduce the bug.
2647
        # 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.
2648
        builder = self.make_branch_builder('foo')
2649
        builder.start_series()
2650
        builder.build_snapshot('first', None, [
2651
            ('add', ('', 'root-id', 'directory', ''))])
2652
        builder.finish_series()
2653
        branch = builder.get_branch()
2654
        repo = branch.repository
2655
        self.assertIsInstance(repo, RemoteRepository)
4214.2.3 by Andrew Bennetts
Further simplify test case, and add more comments.
2656
        # Stop the server from sending extra results.
2657
        self.disableExtraResults()
4214.2.1 by Andrew Bennetts
A long but failing test for the get_parent_map RPC bug.
2658
        repo.lock_read()
2659
        self.addCleanup(repo.unlock)
2660
        self.reset_smart_call_log()
2661
        graph = repo.get_graph()
4214.2.4 by Andrew Bennetts
Further simplify the test to reproduce the bug.
2662
        # Query for 'first' and 'null:'.  Because 'null:' is a parent of
4214.2.5 by Andrew Bennetts
Fix the bug.
2663
        # 'first' it will be a candidate for the stop_keys of subsequent
2664
        # requests, and because 'null:' was queried but not returned it will be
2665
        # cached as missing.
4214.2.1 by Andrew Bennetts
A long but failing test for the get_parent_map RPC bug.
2666
        self.assertEqual({'first': ('null:',)},
4214.2.4 by Andrew Bennetts
Further simplify the test to reproduce the bug.
2667
            graph.get_parent_map(['first', 'null:']))
2668
        # Now query for another key.  This request will pass along a recipe of
2669
        # start and stop keys describing the already cached results, and this
4214.2.5 by Andrew Bennetts
Fix the bug.
2670
        # 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.
2671
        # error from the server).
4214.2.5 by Andrew Bennetts
Fix the bug.
2672
        self.assertEqual({}, graph.get_parent_map(['another-key']))
4214.2.3 by Andrew Bennetts
Further simplify test case, and add more comments.
2673
        # This assertion guards against disableExtraResults silently failing to
2674
        # work, thus invalidating the test.
4214.2.4 by Andrew Bennetts
Further simplify the test to reproduce the bug.
2675
        self.assertLength(2, self.hpss_calls)
4214.2.1 by Andrew Bennetts
A long but failing test for the get_parent_map RPC bug.
2676
4190.1.4 by Robert Collins
Cache ghosts when we can get them from a RemoteRepository in get_parent_map.
2677
    def test_get_parent_map_gets_ghosts_from_result(self):
2678
        # asking for a revision should negatively cache close ghosts in its
2679
        # ancestry.
2680
        self.setup_smart_server_with_call_log()
2681
        tree = self.make_branch_and_memory_tree('foo')
2682
        tree.lock_write()
2683
        try:
2684
            builder = treebuilder.TreeBuilder()
2685
            builder.start_tree(tree)
2686
            builder.build([])
2687
            builder.finish_tree()
2688
            tree.set_parent_ids(['non-existant'], allow_leftmost_as_ghost=True)
2689
            rev_id = tree.commit('')
2690
        finally:
2691
            tree.unlock()
2692
        tree.lock_read()
2693
        self.addCleanup(tree.unlock)
2694
        repo = tree.branch.repository
2695
        self.assertIsInstance(repo, RemoteRepository)
2696
        # ask for rev_id
2697
        repo.get_parent_map([rev_id])
2698
        self.reset_smart_call_log()
2699
        # Now asking for rev_id's ghost parent should not make calls
2700
        self.assertEqual({}, repo.get_parent_map(['non-existant']))
2701
        self.assertLength(0, self.hpss_calls)
2702
6015.24.4 by John Arbash Meinel
For it to all work properly, we have to expose get_parent_map_cached on RemoteRepository.
2703
    def test_exposes_get_cached_parent_map(self):
2704
        """RemoteRepository exposes get_cached_parent_map from
2705
        _unstacked_provider
2706
        """
2707
        r1 = u'\u0e33'.encode('utf8')
2708
        r2 = u'\u0dab'.encode('utf8')
2709
        lines = [' '.join([r2, r1]), r1]
2710
        encoded_body = bz2.compress('\n'.join(lines))
2711
2712
        transport_path = 'quack'
2713
        repo, client = self.setup_fake_client_and_repository(transport_path)
2714
        client.add_success_response_with_body(encoded_body, 'ok')
2715
        repo.lock_read()
6015.24.5 by John Arbash Meinel
Bug #388269.
2716
        # get_cached_parent_map should *not* trigger an RPC
2717
        self.assertEqual({}, repo.get_cached_parent_map([r1]))
2718
        self.assertEqual([], client._calls)
6015.24.4 by John Arbash Meinel
For it to all work properly, we have to expose get_parent_map_cached on RemoteRepository.
2719
        self.assertEqual({r2: (r1,)}, repo.get_parent_map([r2]))
2720
        self.assertEqual({r1: (NULL_REVISION,)},
2721
            repo.get_cached_parent_map([r1]))
2722
        self.assertEqual(
2723
            [('call_with_body_bytes_expecting_body',
2724
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
2725
              '\n\n0')],
2726
            client._calls)
2727
        repo.unlock()
2728
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
2729
3835.1.15 by Aaron Bentley
Allow miss caching to be disabled.
2730
class TestGetParentMapAllowsNew(tests.TestCaseWithTransport):
2731
2732
    def test_allows_new_revisions(self):
2733
        """get_parent_map's results can be updated by commit."""
5017.3.28 by Vincent Ladeuil
selftest -s bt.test_remote passing
2734
        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,
2735
        self.start_server(smart_server)
3835.1.15 by Aaron Bentley
Allow miss caching to be disabled.
2736
        self.make_branch('branch')
2737
        branch = Branch.open(smart_server.get_url() + '/branch')
2738
        tree = branch.create_checkout('tree', lightweight=True)
2739
        tree.lock_write()
2740
        self.addCleanup(tree.unlock)
2741
        graph = tree.branch.repository.get_graph()
2742
        # This provides an opportunity for the missing rev-id to be cached.
2743
        self.assertEqual({}, graph.get_parent_map(['rev1']))
2744
        tree.commit('message', rev_id='rev1')
2745
        graph = tree.branch.repository.get_graph()
2746
        self.assertEqual({'rev1': ('null:',)}, graph.get_parent_map(['rev1']))
2747
2748
6280.9.1 by Jelmer Vernooij
Add remote side of Repository.iter_revisions.
2749
class TestRepositoryGetRevisions(TestRemoteRepository):
2750
2751
    def test_hpss_missing_revision(self):
2752
        transport_path = 'quack'
2753
        repo, client = self.setup_fake_client_and_repository(transport_path)
2754
        client.add_success_response_with_body(
2755
            '', 'ok', '10')
2756
        self.assertRaises(errors.NoSuchRevision, repo.get_revisions,
2757
            ['somerev1', 'anotherrev2'])
2758
        self.assertEqual(
2759
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
2760
             ('quack/', ), "somerev1\nanotherrev2")],
2761
            client._calls)
2762
2763
    def test_hpss_get_single_revision(self):
2764
        transport_path = 'quack'
2765
        repo, client = self.setup_fake_client_and_repository(transport_path)
2766
        somerev1 = Revision("somerev1")
2767
        somerev1.committer = "Joe Committer <joe@example.com>"
2768
        somerev1.timestamp = 1321828927
2769
        somerev1.timezone = -60
2770
        somerev1.inventory_sha1 = "691b39be74c67b1212a75fcb19c433aaed903c2b"
2771
        somerev1.message = "Message"
6280.9.4 by Jelmer Vernooij
use zlib instead.
2772
        body = zlib.compress(chk_bencode_serializer.write_revision_to_string(
6280.9.1 by Jelmer Vernooij
Add remote side of Repository.iter_revisions.
2773
            somerev1))
6280.9.8 by Jelmer Vernooij
Try to make two calls to zlib.decompressobj.decompress.
2774
        # Split up body into two bits to make sure the zlib compression object
2775
        # gets data fed twice.
6280.9.1 by Jelmer Vernooij
Add remote side of Repository.iter_revisions.
2776
        client.add_success_response_with_body(
6280.9.8 by Jelmer Vernooij
Try to make two calls to zlib.decompressobj.decompress.
2777
                [body[:10], body[10:]], 'ok', '10')
6280.9.1 by Jelmer Vernooij
Add remote side of Repository.iter_revisions.
2778
        revs = repo.get_revisions(['somerev1'])
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2779
        self.assertEqual(revs, [somerev1])
6280.9.1 by Jelmer Vernooij
Add remote side of Repository.iter_revisions.
2780
        self.assertEqual(
2781
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
2782
             ('quack/', ), "somerev1")],
2783
            client._calls)
2784
2785
3948.3.9 by Martin Pool
Undelete TestRepositoryGetRevisionGraph but make it use private client methods to simulate old clients
2786
class TestRepositoryGetRevisionGraph(TestRemoteRepository):
2787
2788
    def test_null_revision(self):
2789
        # a null revision has the predictable result {}, we should have no wire
2790
        # traffic when calling it with this argument
2791
        transport_path = 'empty'
2792
        repo, client = self.setup_fake_client_and_repository(transport_path)
2793
        client.add_success_response('notused')
2794
        # actual RemoteRepository.get_revision_graph is gone, but there's an
2795
        # equivalent private method for testing
2796
        result = repo._get_revision_graph(NULL_REVISION)
2797
        self.assertEqual([], client._calls)
2798
        self.assertEqual({}, result)
2799
2800
    def test_none_revision(self):
2801
        # with none we want the entire graph
2802
        r1 = u'\u0e33'.encode('utf8')
2803
        r2 = u'\u0dab'.encode('utf8')
2804
        lines = [' '.join([r2, r1]), r1]
2805
        encoded_body = '\n'.join(lines)
2806
2807
        transport_path = 'sinhala'
2808
        repo, client = self.setup_fake_client_and_repository(transport_path)
2809
        client.add_success_response_with_body(encoded_body, 'ok')
2810
        # actual RemoteRepository.get_revision_graph is gone, but there's an
2811
        # equivalent private method for testing
2812
        result = repo._get_revision_graph(None)
2813
        self.assertEqual(
2814
            [('call_expecting_body', 'Repository.get_revision_graph',
2815
             ('sinhala/', ''))],
2816
            client._calls)
2817
        self.assertEqual({r1: (), r2: (r1, )}, result)
2818
2819
    def test_specific_revision(self):
2820
        # with a specific revision we want the graph for that
2821
        # with none we want the entire graph
2822
        r11 = u'\u0e33'.encode('utf8')
2823
        r12 = u'\xc9'.encode('utf8')
2824
        r2 = u'\u0dab'.encode('utf8')
2825
        lines = [' '.join([r2, r11, r12]), r11, r12]
2826
        encoded_body = '\n'.join(lines)
2827
2828
        transport_path = 'sinhala'
2829
        repo, client = self.setup_fake_client_and_repository(transport_path)
2830
        client.add_success_response_with_body(encoded_body, 'ok')
2831
        result = repo._get_revision_graph(r2)
2832
        self.assertEqual(
2833
            [('call_expecting_body', 'Repository.get_revision_graph',
2834
             ('sinhala/', r2))],
2835
            client._calls)
2836
        self.assertEqual({r11: (), r12: (), r2: (r11, r12), }, result)
2837
2838
    def test_no_such_revision(self):
2839
        revid = '123'
2840
        transport_path = 'sinhala'
2841
        repo, client = self.setup_fake_client_and_repository(transport_path)
2842
        client.add_error_response('nosuchrevision', revid)
2843
        # also check that the right revision is reported in the error
2844
        self.assertRaises(errors.NoSuchRevision,
2845
            repo._get_revision_graph, revid)
2846
        self.assertEqual(
2847
            [('call_expecting_body', 'Repository.get_revision_graph',
2848
             ('sinhala/', revid))],
2849
            client._calls)
2850
2851
    def test_unexpected_error(self):
2852
        revid = '123'
2853
        transport_path = 'sinhala'
2854
        repo, client = self.setup_fake_client_and_repository(transport_path)
2855
        client.add_error_response('AnUnexpectedError')
2856
        e = self.assertRaises(errors.UnknownErrorFromSmartServer,
2857
            repo._get_revision_graph, revid)
2858
        self.assertEqual(('AnUnexpectedError',), e.error_tuple)
2859
2860
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2861
class TestRepositoryGetRevIdForRevno(TestRemoteRepository):
2862
2863
    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.
2864
        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.
2865
        client.add_expected_call(
2866
            'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2867
            'success', ('ok', 'rev-five'))
2868
        result = repo.get_rev_id_for_revno(5, (42, 'rev-foo'))
2869
        self.assertEqual((True, 'rev-five'), result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
2870
        self.assertFinished(client)
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2871
2872
    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.
2873
        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.
2874
        client.add_expected_call(
2875
            'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2876
            'success', ('history-incomplete', 10, 'rev-ten'))
2877
        result = repo.get_rev_id_for_revno(5, (42, 'rev-foo'))
2878
        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.
2879
        self.assertFinished(client)
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2880
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.
2881
    def test_history_incomplete_with_fallback(self):
2882
        """A 'history-incomplete' response causes the fallback repository to be
2883
        queried too, if one is set.
2884
        """
2885
        # Make a repo with a fallback repo, both using a FakeClient.
2886
        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.
2887
            ('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.
2888
        repo, client = self.setup_fake_client_and_repository('quack')
2889
        repo._format = format
2890
        fallback_repo, ignored = self.setup_fake_client_and_repository(
2891
            'fallback')
2892
        fallback_repo._client = client
5158.4.3 by Andrew Bennetts
Fix test_remote tests that accidentally assumed it was ok to stack mismatched formats.
2893
        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.
2894
        repo.add_fallback_repository(fallback_repo)
2895
        # First the client should ask the primary repo
2896
        client.add_expected_call(
2897
            'Repository.get_rev_id_for_revno', ('quack/', 1, (42, 'rev-foo')),
2898
            'success', ('history-incomplete', 2, 'rev-two'))
2899
        # Then it should ask the fallback, using revno/revid from the
2900
        # history-incomplete response as the known revno/revid.
2901
        client.add_expected_call(
2902
            'Repository.get_rev_id_for_revno',('fallback/', 1, (2, 'rev-two')),
2903
            'success', ('ok', 'rev-one'))
2904
        result = repo.get_rev_id_for_revno(1, (42, 'rev-foo'))
2905
        self.assertEqual((True, 'rev-one'), result)
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
2906
        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.
2907
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2908
    def test_nosuchrevision(self):
2909
        # 'nosuchrevision' is returned when the known-revid is not found in the
2910
        # 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.
2911
        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.
2912
        client.add_expected_call(
2913
            'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2914
            'error', ('nosuchrevision', 'rev-foo'))
2915
        self.assertRaises(
2916
            errors.NoSuchRevision,
2917
            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.
2918
        self.assertFinished(client)
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2919
4634.69.1 by Andrew Bennetts
Apply @needs_read_lock to RemoteBranch.get_rev_id.
2920
    def test_branch_fallback_locking(self):
2921
        """RemoteBranch.get_rev_id takes a read lock, and tries to call the
2922
        get_rev_id_for_revno verb.  If the verb is unknown the VFS fallback
2923
        will be invoked, which will fail if the repo is unlocked.
2924
        """
2925
        self.setup_smart_server_with_call_log()
2926
        tree = self.make_branch_and_memory_tree('.')
2927
        tree.lock_write()
5222.1.1 by Aaron Bentley
Refuse to commit trees with no root.
2928
        tree.add('')
4634.69.1 by Andrew Bennetts
Apply @needs_read_lock to RemoteBranch.get_rev_id.
2929
        rev1 = tree.commit('First')
2930
        rev2 = tree.commit('Second')
2931
        tree.unlock()
2932
        branch = tree.branch
2933
        self.assertFalse(branch.is_locked())
2934
        self.reset_smart_call_log()
2935
        verb = 'Repository.get_rev_id_for_revno'
2936
        self.disable_verb(verb)
2937
        self.assertEqual(rev1, branch.get_rev_id(1))
2938
        self.assertLength(1, [call for call in self.hpss_calls if
2939
                              call.call.method == verb])
2940
4419.2.7 by Andrew Bennetts
Add unit tests for RemoteRepository.get_rev_id_for_revno.
2941
6265.1.1 by Jelmer Vernooij
Add new HPSS call ``Repository.has_signature_for_revision_id``.
2942
class TestRepositoryHasSignatureForRevisionId(TestRemoteRepository):
2943
2944
    def test_has_signature_for_revision_id(self):
2945
        # ('yes', ) for Repository.has_signature_for_revision_id -> 'True'.
2946
        transport_path = 'quack'
2947
        repo, client = self.setup_fake_client_and_repository(transport_path)
2948
        client.add_success_response('yes')
2949
        result = repo.has_signature_for_revision_id('A')
2950
        self.assertEqual(
2951
            [('call', 'Repository.has_signature_for_revision_id',
2952
              ('quack/', 'A'))],
2953
            client._calls)
2954
        self.assertEqual(True, result)
2955
2956
    def test_is_not_shared(self):
2957
        # ('no', ) for Repository.has_signature_for_revision_id -> 'False'.
2958
        transport_path = 'qwack'
2959
        repo, client = self.setup_fake_client_and_repository(transport_path)
2960
        client.add_success_response('no')
2961
        result = repo.has_signature_for_revision_id('A')
2962
        self.assertEqual(
2963
            [('call', 'Repository.has_signature_for_revision_id',
2964
              ('qwack/', 'A'))],
2965
            client._calls)
2966
        self.assertEqual(False, result)
2967
2968
6280.6.1 by Jelmer Vernooij
Implement remote side of {Branch,Repository}.get_physical_lock_status.
2969
class TestRepositoryPhysicalLockStatus(TestRemoteRepository):
2970
2971
    def test_get_physical_lock_status_yes(self):
2972
        transport_path = 'qwack'
2973
        repo, client = self.setup_fake_client_and_repository(transport_path)
2974
        client.add_success_response('yes')
2975
        result = repo.get_physical_lock_status()
2976
        self.assertEqual(
2977
            [('call', 'Repository.get_physical_lock_status',
2978
              ('qwack/', ))],
2979
            client._calls)
2980
        self.assertEqual(True, result)
2981
2982
    def test_get_physical_lock_status_no(self):
2983
        transport_path = 'qwack'
2984
        repo, client = self.setup_fake_client_and_repository(transport_path)
2985
        client.add_success_response('no')
2986
        result = repo.get_physical_lock_status()
2987
        self.assertEqual(
2988
            [('call', 'Repository.get_physical_lock_status',
2989
              ('qwack/', ))],
2990
            client._calls)
2991
        self.assertEqual(False, result)
2992
2993
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
2994
class TestRepositoryIsShared(TestRemoteRepository):
2995
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
2996
    def test_is_shared(self):
2997
        # ('yes', ) for Repository.is_shared -> 'True'.
2998
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
2999
        repo, client = self.setup_fake_client_and_repository(transport_path)
3000
        client.add_success_response('yes')
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
3001
        result = repo.is_shared()
3002
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
3003
            [('call', 'Repository.is_shared', ('quack/',))],
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
3004
            client._calls)
3005
        self.assertEqual(True, result)
3006
3007
    def test_is_not_shared(self):
3008
        # ('no', ) for Repository.is_shared -> 'False'.
3009
        transport_path = 'qwack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3010
        repo, client = self.setup_fake_client_and_repository(transport_path)
3011
        client.add_success_response('no')
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
3012
        result = repo.is_shared()
3013
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
3014
            [('call', 'Repository.is_shared', ('qwack/',))],
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
3015
            client._calls)
3016
        self.assertEqual(False, result)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
3017
3018
6263.2.1 by Jelmer Vernooij
Add hpss call ``Repository.make_working_trees``
3019
class TestRepositoryMakeWorkingTrees(TestRemoteRepository):
3020
3021
    def test_make_working_trees(self):
3022
        # ('yes', ) for Repository.make_working_trees -> 'True'.
3023
        transport_path = 'quack'
3024
        repo, client = self.setup_fake_client_and_repository(transport_path)
3025
        client.add_success_response('yes')
3026
        result = repo.make_working_trees()
3027
        self.assertEqual(
3028
            [('call', 'Repository.make_working_trees', ('quack/',))],
3029
            client._calls)
3030
        self.assertEqual(True, result)
3031
3032
    def test_no_working_trees(self):
3033
        # ('no', ) for Repository.make_working_trees -> 'False'.
3034
        transport_path = 'qwack'
3035
        repo, client = self.setup_fake_client_and_repository(transport_path)
3036
        client.add_success_response('no')
3037
        result = repo.make_working_trees()
3038
        self.assertEqual(
3039
            [('call', 'Repository.make_working_trees', ('qwack/',))],
3040
            client._calls)
3041
        self.assertEqual(False, result)
3042
3043
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
3044
class TestRepositoryLockWrite(TestRemoteRepository):
3045
3046
    def test_lock_write(self):
3047
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3048
        repo, client = self.setup_fake_client_and_repository(transport_path)
3049
        client.add_success_response('ok', 'a token')
5200.3.3 by Robert Collins
Lock methods on ``Tree``, ``Branch`` and ``Repository`` are now
3050
        token = repo.lock_write().repository_token
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
3051
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
3052
            [('call', 'Repository.lock_write', ('quack/', ''))],
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
3053
            client._calls)
5200.3.3 by Robert Collins
Lock methods on ``Tree``, ``Branch`` and ``Repository`` are now
3054
        self.assertEqual('a token', token)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
3055
3056
    def test_lock_write_already_locked(self):
3057
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3058
        repo, client = self.setup_fake_client_and_repository(transport_path)
3059
        client.add_error_response('LockContention')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
3060
        self.assertRaises(errors.LockContention, repo.lock_write)
3061
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
3062
            [('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.
3063
            client._calls)
3064
3065
    def test_lock_write_unlockable(self):
3066
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3067
        repo, client = self.setup_fake_client_and_repository(transport_path)
3068
        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.
3069
        self.assertRaises(errors.UnlockableTransport, repo.lock_write)
3070
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
3071
            [('call', 'Repository.lock_write', ('quack/', ''))],
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
3072
            client._calls)
3073
3074
6280.7.1 by Jelmer Vernooij
Implement RemoteRepository side of write group HPSS methods.
3075
class TestRepositoryWriteGroups(TestRemoteRepository):
3076
3077
    def test_start_write_group(self):
3078
        transport_path = 'quack'
3079
        repo, client = self.setup_fake_client_and_repository(transport_path)
3080
        client.add_expected_call(
6280.7.2 by Jelmer Vernooij
Add HPSS calls ``Repository.start_write_group``, ``Repository.abort_write_group`` and ``Repository.commit_write_group``.
3081
            'Repository.lock_write', ('quack/', ''),
3082
            'success', ('ok', 'a token'))
3083
        client.add_expected_call(
3084
            'Repository.start_write_group', ('quack/', 'a token'),
6280.10.32 by Jelmer Vernooij
Merge bzr.dev.
3085
            'success', ('ok', ('token1', )))
6280.7.2 by Jelmer Vernooij
Add HPSS calls ``Repository.start_write_group``, ``Repository.abort_write_group`` and ``Repository.commit_write_group``.
3086
        repo.lock_write()
6280.7.1 by Jelmer Vernooij
Implement RemoteRepository side of write group HPSS methods.
3087
        repo.start_write_group()
3088
6280.7.8 by Jelmer Vernooij
make sure start_write_group falls back to real_repository if write groups aren't suspendable.
3089
    def test_start_write_group_unsuspendable(self):
3090
        # Some repositories do not support suspending write
3091
        # groups. For those, fall back to the "real" repository.
3092
        transport_path = 'quack'
3093
        repo, client = self.setup_fake_client_and_repository(transport_path)
3094
        def stub_ensure_real():
3095
            client._calls.append(('_ensure_real',))
3096
            repo._real_repository = _StubRealPackRepository(client._calls)
3097
        repo._ensure_real = stub_ensure_real
3098
        client.add_expected_call(
3099
            'Repository.lock_write', ('quack/', ''),
3100
            'success', ('ok', 'a token'))
3101
        client.add_expected_call(
3102
            'Repository.start_write_group', ('quack/', 'a token'),
3103
            'error', ('UnsuspendableWriteGroup',))
3104
        repo.lock_write()
3105
        repo.start_write_group()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3106
        self.assertEqual(client._calls[-2:], [ 
6280.7.8 by Jelmer Vernooij
make sure start_write_group falls back to real_repository if write groups aren't suspendable.
3107
            ('_ensure_real',),
3108
            ('start_write_group',)])
3109
6280.7.1 by Jelmer Vernooij
Implement RemoteRepository side of write group HPSS methods.
3110
    def test_commit_write_group(self):
3111
        transport_path = 'quack'
3112
        repo, client = self.setup_fake_client_and_repository(transport_path)
3113
        client.add_expected_call(
6280.7.2 by Jelmer Vernooij
Add HPSS calls ``Repository.start_write_group``, ``Repository.abort_write_group`` and ``Repository.commit_write_group``.
3114
            'Repository.lock_write', ('quack/', ''),
3115
            'success', ('ok', 'a token'))
3116
        client.add_expected_call(
3117
            'Repository.start_write_group', ('quack/', 'a token'),
6280.7.6 by Jelmer Vernooij
Fix remaining tests.
3118
            'success', ('ok', ['token1']))
6280.7.2 by Jelmer Vernooij
Add HPSS calls ``Repository.start_write_group``, ``Repository.abort_write_group`` and ``Repository.commit_write_group``.
3119
        client.add_expected_call(
6280.7.6 by Jelmer Vernooij
Fix remaining tests.
3120
            'Repository.commit_write_group', ('quack/', 'a token', ['token1']),
6280.7.1 by Jelmer Vernooij
Implement RemoteRepository side of write group HPSS methods.
3121
            'success', ('ok',))
6280.7.2 by Jelmer Vernooij
Add HPSS calls ``Repository.start_write_group``, ``Repository.abort_write_group`` and ``Repository.commit_write_group``.
3122
        repo.lock_write()
3123
        repo.start_write_group()
6280.7.1 by Jelmer Vernooij
Implement RemoteRepository side of write group HPSS methods.
3124
        repo.commit_write_group()
3125
3126
    def test_abort_write_group(self):
3127
        transport_path = 'quack'
3128
        repo, client = self.setup_fake_client_and_repository(transport_path)
3129
        client.add_expected_call(
6280.7.2 by Jelmer Vernooij
Add HPSS calls ``Repository.start_write_group``, ``Repository.abort_write_group`` and ``Repository.commit_write_group``.
3130
            'Repository.lock_write', ('quack/', ''),
3131
            'success', ('ok', 'a token'))
3132
        client.add_expected_call(
3133
            'Repository.start_write_group', ('quack/', 'a token'),
6280.7.6 by Jelmer Vernooij
Fix remaining tests.
3134
            'success', ('ok', ['token1']))
6280.7.2 by Jelmer Vernooij
Add HPSS calls ``Repository.start_write_group``, ``Repository.abort_write_group`` and ``Repository.commit_write_group``.
3135
        client.add_expected_call(
6280.7.6 by Jelmer Vernooij
Fix remaining tests.
3136
            'Repository.abort_write_group', ('quack/', 'a token', ['token1']),
6280.7.1 by Jelmer Vernooij
Implement RemoteRepository side of write group HPSS methods.
3137
            'success', ('ok',))
6280.7.2 by Jelmer Vernooij
Add HPSS calls ``Repository.start_write_group``, ``Repository.abort_write_group`` and ``Repository.commit_write_group``.
3138
        repo.lock_write()
3139
        repo.start_write_group()
6280.7.1 by Jelmer Vernooij
Implement RemoteRepository side of write group HPSS methods.
3140
        repo.abort_write_group(False)
3141
3142
    def test_suspend_write_group(self):
3143
        transport_path = 'quack'
3144
        repo, client = self.setup_fake_client_and_repository(transport_path)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3145
        self.assertEqual([], repo.suspend_write_group())
6280.7.1 by Jelmer Vernooij
Implement RemoteRepository side of write group HPSS methods.
3146
3147
    def test_resume_write_group(self):
3148
        transport_path = 'quack'
3149
        repo, client = self.setup_fake_client_and_repository(transport_path)
6280.7.6 by Jelmer Vernooij
Fix remaining tests.
3150
        client.add_expected_call(
3151
            'Repository.lock_write', ('quack/', ''),
3152
            'success', ('ok', 'a token'))
3153
        client.add_expected_call(
3154
            'Repository.check_write_group', ('quack/', 'a token', ['token1']),
3155
            'success', ('ok',))
3156
        repo.lock_write()
3157
        repo.resume_write_group(['token1'])
6280.7.1 by Jelmer Vernooij
Implement RemoteRepository side of write group HPSS methods.
3158
3159
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
3160
class TestRepositorySetMakeWorkingTrees(TestRemoteRepository):
3161
3162
    def test_backwards_compat(self):
3163
        self.setup_smart_server_with_call_log()
3164
        repo = self.make_repository('.')
3165
        self.reset_smart_call_log()
3166
        verb = 'Repository.set_make_working_trees'
3167
        self.disable_verb(verb)
3168
        repo.set_make_working_trees(True)
3169
        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.
3170
            call.call.method == verb])
4017.3.4 by Robert Collins
Create a verb for Repository.set_make_working_trees.
3171
        self.assertEqual(1, call_count)
3172
3173
    def test_current(self):
3174
        transport_path = 'quack'
3175
        repo, client = self.setup_fake_client_and_repository(transport_path)
3176
        client.add_expected_call(
3177
            'Repository.set_make_working_trees', ('quack/', 'True'),
3178
            'success', ('ok',))
3179
        client.add_expected_call(
3180
            'Repository.set_make_working_trees', ('quack/', 'False'),
3181
            'success', ('ok',))
3182
        repo.set_make_working_trees(True)
3183
        repo.set_make_working_trees(False)
3184
3185
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
3186
class TestRepositoryUnlock(TestRemoteRepository):
3187
3188
    def test_unlock(self):
3189
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3190
        repo, client = self.setup_fake_client_and_repository(transport_path)
3191
        client.add_success_response('ok', 'a token')
3192
        client.add_success_response('ok')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
3193
        repo.lock_write()
3194
        repo.unlock()
3195
        self.assertEqual(
3104.4.2 by Andrew Bennetts
All tests passing.
3196
            [('call', 'Repository.lock_write', ('quack/', '')),
3197
             ('call', 'Repository.unlock', ('quack/', 'a token'))],
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
3198
            client._calls)
3199
3200
    def test_unlock_wrong_token(self):
3201
        # If somehow the token is wrong, unlock will raise TokenMismatch.
3202
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3203
        repo, client = self.setup_fake_client_and_repository(transport_path)
3204
        client.add_success_response('ok', 'a token')
3205
        client.add_error_response('TokenMismatch')
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
3206
        repo.lock_write()
3207
        self.assertRaises(errors.TokenMismatch, repo.unlock)
3208
3209
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
3210
class TestRepositoryHasRevision(TestRemoteRepository):
3211
3212
    def test_none(self):
3213
        # repo.has_revision(None) should not cause any traffic.
3214
        transport_path = 'quack'
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3215
        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.
3216
3217
        # The null revision is always there, so has_revision(None) == True.
3172.3.3 by Robert Collins
Missed one occurence of None -> NULL_REVISION.
3218
        self.assertEqual(True, repo.has_revision(NULL_REVISION))
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
3219
3220
        # The remote repo shouldn't be accessed.
3221
        self.assertEqual([], client._calls)
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
3222
3223
6280.10.7 by Jelmer Vernooij
Fix remote.
3224
class TestRepositoryIterFilesBytes(TestRemoteRepository):
6280.10.1 by Jelmer Vernooij
Add remote side of Repository.iter_file_bytes.
3225
    """Test Repository.iter_file_bytes."""
3226
3227
    def test_single(self):
3228
        transport_path = 'quack'
3229
        repo, client = self.setup_fake_client_and_repository(transport_path)
3230
        client.add_expected_call(
6280.10.19 by Jelmer Vernooij
Convert remote side to zlib.
3231
            'Repository.iter_files_bytes', ('quack/', ),
3232
            'success', ('ok',), iter(["ok\x000", "\n", zlib.compress("mydata" * 10)]))
6280.10.1 by Jelmer Vernooij
Add remote side of Repository.iter_file_bytes.
3233
        for (identifier, byte_stream) in repo.iter_files_bytes([("somefile",
3234
                "somerev", "myid")]):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3235
            self.assertEqual("myid", identifier)
3236
            self.assertEqual("".join(byte_stream), "mydata" * 10)
6280.10.1 by Jelmer Vernooij
Add remote side of Repository.iter_file_bytes.
3237
6280.10.3 by Jelmer Vernooij
Fix iter_file_bytes.
3238
    def test_missing(self):
3239
        transport_path = 'quack'
3240
        repo, client = self.setup_fake_client_and_repository(transport_path)
3241
        client.add_expected_call(
6280.10.19 by Jelmer Vernooij
Convert remote side to zlib.
3242
            'Repository.iter_files_bytes',
6280.10.7 by Jelmer Vernooij
Fix remote.
3243
                ('quack/', ),
3244
            'error', ('RevisionNotPresent', 'somefile', 'somerev'),
6280.10.11 by Jelmer Vernooij
mark absent entries.
3245
            iter(["absent\0somefile\0somerev\n"]))
6280.10.3 by Jelmer Vernooij
Fix iter_file_bytes.
3246
        self.assertRaises(errors.RevisionNotPresent, list,
3247
                repo.iter_files_bytes(
3248
                [("somefile", "somerev", "myid")]))
3249
6280.10.1 by Jelmer Vernooij
Add remote side of Repository.iter_file_bytes.
3250
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
3251
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.
3252
    """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.
3253
    tests.
3254
    """
3255
    
3256
    def checkInsertEmptyStream(self, repo, client):
3257
        """Insert an empty stream, checking the result.
3258
3259
        This checks that there are no resume_tokens or missing_keys, and that
3260
        the client is finished.
3261
        """
3262
        sink = repo._get_sink()
5651.3.9 by Jelmer Vernooij
Avoid using deprecated functions.
3263
        fmt = repository.format_registry.get_default()
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
3264
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
3265
        self.assertEqual([], resume_tokens)
3266
        self.assertEqual(set(), missing_keys)
3267
        self.assertFinished(client)
3268
3269
3270
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.
3271
    """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).
3272
    not available.
3273
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.
3274
    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).
3275
    """
3276
3277
    def setUp(self):
6552.1.4 by Vincent Ladeuil
Remaining tests matching setup(self) that can be rewritten with super().
3278
        super(TestRepositoryInsertStream, self).setUp()
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.
3279
        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).
3280
3281
    def test_unlocked_repo(self):
3282
        transport_path = 'quack'
3283
        repo, client = self.setup_fake_client_and_repository(transport_path)
3284
        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.
3285
            'Repository.insert_stream_1.19', ('quack/', ''),
3286
            '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).
3287
        client.add_expected_call(
3288
            'Repository.insert_stream', ('quack/', ''),
3289
            'success', ('ok',))
3290
        client.add_expected_call(
3291
            'Repository.insert_stream', ('quack/', ''),
3292
            'success', ('ok',))
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
3293
        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).
3294
3295
    def test_locked_repo_with_no_lock_token(self):
3296
        transport_path = 'quack'
3297
        repo, client = self.setup_fake_client_and_repository(transport_path)
3298
        client.add_expected_call(
3299
            'Repository.lock_write', ('quack/', ''),
3300
            'success', ('ok', ''))
3301
        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.
3302
            'Repository.insert_stream_1.19', ('quack/', ''),
3303
            '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).
3304
        client.add_expected_call(
3305
            'Repository.insert_stream', ('quack/', ''),
3306
            'success', ('ok',))
3307
        client.add_expected_call(
3308
            'Repository.insert_stream', ('quack/', ''),
3309
            'success', ('ok',))
3310
        repo.lock_write()
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
3311
        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).
3312
3313
    def test_locked_repo_with_lock_token(self):
3314
        transport_path = 'quack'
3315
        repo, client = self.setup_fake_client_and_repository(transport_path)
3316
        client.add_expected_call(
3317
            'Repository.lock_write', ('quack/', ''),
3318
            'success', ('ok', 'a token'))
3319
        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.
3320
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
3321
            '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).
3322
        client.add_expected_call(
3323
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
3324
            'success', ('ok',))
3325
        client.add_expected_call(
3326
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
3327
            'success', ('ok',))
3328
        repo.lock_write()
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
3329
        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).
3330
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
3331
    def test_stream_with_inventory_deltas(self):
4476.3.71 by Andrew Bennetts
Clearer comments prompted by Robert's review.
3332
        """'inventory-deltas' substreams cannot be sent to the
3333
        Repository.insert_stream verb, because not all servers that implement
3334
        that verb will accept them.  So when one is encountered the RemoteSink
3335
        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.
3336
        """
3337
        transport_path = 'quack'
3338
        repo, client = self.setup_fake_client_and_repository(transport_path)
3339
        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.
3340
            'Repository.insert_stream_1.19', ('quack/', ''),
3341
            '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.
3342
        client.add_expected_call(
3343
            'Repository.insert_stream', ('quack/', ''),
3344
            'success', ('ok',))
3345
        client.add_expected_call(
3346
            'Repository.insert_stream', ('quack/', ''),
3347
            'success', ('ok',))
3348
        # Create a fake real repository for insert_stream to fall back on, so
3349
        # that we can directly see the records the RemoteSink passes to the
3350
        # real sink.
3351
        class FakeRealSink:
3352
            def __init__(self):
3353
                self.records = []
3354
            def insert_stream(self, stream, src_format, resume_tokens):
3355
                for substream_kind, substream in stream:
3356
                    self.records.append(
3357
                        (substream_kind, [record.key for record in substream]))
3358
                return ['fake tokens'], ['fake missing keys']
3359
        fake_real_sink = FakeRealSink()
3360
        class FakeRealRepository:
3361
            def _get_sink(self):
3362
                return fake_real_sink
4634.35.20 by Andrew Bennetts
Fix test_remote.
3363
            def is_in_write_group(self):
3364
                return False
3365
            def refresh_data(self):
3366
                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.
3367
        repo._real_repository = FakeRealRepository()
3368
        sink = repo._get_sink()
5651.3.9 by Jelmer Vernooij
Avoid using deprecated functions.
3369
        fmt = repository.format_registry.get_default()
4476.3.36 by Andrew Bennetts
Add a somewhat complex test to exercise the fallback-to-vfs logic in RemoteSink when an inventory-delta is encountered and the 1.18 verb isn't accepted.
3370
        stream = self.make_stream_with_inv_deltas(fmt)
3371
        resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
3372
        # Every record from the first inventory delta should have been sent to
3373
        # the VFS sink.
3374
        expected_records = [
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
3375
            ('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.
3376
            ('texts', [('some-rev', 'some-file')])]
3377
        self.assertEqual(expected_records, fake_real_sink.records)
3378
        # The return values from the real sink's insert_stream are propagated
3379
        # back to the original caller.
3380
        self.assertEqual(['fake tokens'], resume_tokens)
3381
        self.assertEqual(['fake missing keys'], missing_keys)
4476.3.40 by Andrew Bennetts
Merge bzr.dev.
3382
        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.
3383
3384
    def make_stream_with_inv_deltas(self, fmt):
3385
        """Make a simple stream with an inventory delta followed by more
3386
        records and more substreams to test that all records and substreams
3387
        from that point on are used.
3388
3389
        This sends, in order:
3390
           * inventories substream: rev1, rev2, rev3.  rev2 and rev3 are
3391
             inventory-deltas.
3392
           * texts substream: (some-rev, some-file)
3393
        """
3394
        # 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.
3395
        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.
3396
        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.
3397
        def stream_with_inv_delta():
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
3398
            yield ('inventories', inventories_substream())
3399
            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.
3400
            yield ('texts', [
3401
                versionedfile.FulltextContentFactory(
3402
                    ('some-rev', 'some-file'), (), None, 'content')])
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
3403
        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.
3404
            # An empty inventory fulltext.  This will be streamed normally.
3405
            text = fmt._serializer.write_inventory_to_string(inv)
3406
            yield versionedfile.FulltextContentFactory(
3407
                ('rev1',), (), None, text)
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
3408
        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.
3409
            # An inventory delta.  This can't be streamed via this verb, so it
3410
            # will trigger a fallback to VFS insert_stream.
3411
            entry = inv.make_entry(
3412
                'directory', 'newdir', inv.root.file_id, 'newdir-id')
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
3413
            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.
3414
            delta = [(None, 'newdir', 'newdir-id', entry)]
4476.3.76 by Andrew Bennetts
Split out InventoryDeltaDeserializer from InventoryDeltaSerializer.
3415
            serializer = inventory_delta.InventoryDeltaSerializer(
3416
                versioned_root=True, tree_references=False)
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
3417
            lines = serializer.delta_to_lines('rev1', 'rev2', delta)
3418
            yield versionedfile.ChunkedContentFactory(
3419
                ('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.
3420
            # Another delta.
4476.3.56 by Andrew Bennetts
Update test_stream_with_inventory_deltas for inventory-deltas substream.
3421
            lines = serializer.delta_to_lines('rev1', 'rev3', delta)
3422
            yield versionedfile.ChunkedContentFactory(
3423
                ('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.
3424
        return stream_with_inv_delta()
3425
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).
3426
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.
3427
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).
3428
3429
    def test_unlocked_repo(self):
3430
        transport_path = 'quack'
3431
        repo, client = self.setup_fake_client_and_repository(transport_path)
3432
        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.
3433
            '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).
3434
            'success', ('ok',))
3435
        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.
3436
            '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).
3437
            'success', ('ok',))
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
3438
        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).
3439
3440
    def test_locked_repo_with_no_lock_token(self):
3441
        transport_path = 'quack'
3442
        repo, client = self.setup_fake_client_and_repository(transport_path)
3443
        client.add_expected_call(
3444
            'Repository.lock_write', ('quack/', ''),
3445
            'success', ('ok', ''))
3446
        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.
3447
            '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).
3448
            'success', ('ok',))
3449
        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.
3450
            '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).
3451
            'success', ('ok',))
3452
        repo.lock_write()
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
3453
        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).
3454
3455
    def test_locked_repo_with_lock_token(self):
3456
        transport_path = 'quack'
3457
        repo, client = self.setup_fake_client_and_repository(transport_path)
3458
        client.add_expected_call(
3459
            'Repository.lock_write', ('quack/', ''),
3460
            'success', ('ok', 'a token'))
3461
        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.
3462
            '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).
3463
            'success', ('ok',))
3464
        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.
3465
            '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.
3466
            'success', ('ok',))
3467
        repo.lock_write()
4476.3.79 by Andrew Bennetts
Remove a bit of duplication from Repository.insert_stream* tests.
3468
        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.
3469
3470
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
3471
class TestRepositoryTarball(TestRemoteRepository):
3472
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
3473
    # This is a canned tarball reponse we can validate against
2018.18.18 by Martin Pool
reformat
3474
    tarball_content = (
2018.18.23 by Martin Pool
review cleanups
3475
        'QlpoOTFBWSZTWdGkj3wAAWF/k8aQACBIB//A9+8cIX/v33AACEAYABAECEACNz'
3476
        'JqsgJJFPTSnk1A3qh6mTQAAAANPUHkagkSTEkaA09QaNAAAGgAAAcwCYCZGAEY'
3477
        'mJhMJghpiaYBUkKammSHqNMZQ0NABkNAeo0AGneAevnlwQoGzEzNVzaYxp/1Uk'
3478
        'xXzA1CQX0BJMZZLcPBrluJir5SQyijWHYZ6ZUtVqqlYDdB2QoCwa9GyWwGYDMA'
3479
        'OQYhkpLt/OKFnnlT8E0PmO8+ZNSo2WWqeCzGB5fBXZ3IvV7uNJVE7DYnWj6qwB'
3480
        'k5DJDIrQ5OQHHIjkS9KqwG3mc3t+F1+iujb89ufyBNIKCgeZBWrl5cXxbMGoMs'
3481
        'c9JuUkg5YsiVcaZJurc6KLi6yKOkgCUOlIlOpOoXyrTJjK8ZgbklReDdwGmFgt'
3482
        'dkVsAIslSVCd4AtACSLbyhLHryfb14PKegrVDba+U8OL6KQtzdM5HLjAc8/p6n'
3483
        '0lgaWU8skgO7xupPTkyuwheSckejFLK5T4ZOo0Gda9viaIhpD1Qn7JqqlKAJqC'
3484
        'QplPKp2nqBWAfwBGaOwVrz3y1T+UZZNismXHsb2Jq18T+VaD9k4P8DqE3g70qV'
3485
        'JLurpnDI6VS5oqDDPVbtVjMxMxMg4rzQVipn2Bv1fVNK0iq3Gl0hhnnHKm/egy'
3486
        'nWQ7QH/F3JFOFCQ0aSPfA='
3487
        ).decode('base64')
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
3488
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
3489
    def test_repository_tarball(self):
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
3490
        # Test that Repository.tarball generates the right operations
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
3491
        transport_path = 'repo'
2018.18.14 by Martin Pool
merge hpss again; restore incorrectly removed RemoteRepository.break_lock
3492
        expected_calls = [('call_expecting_body', 'Repository.tarball',
3104.4.2 by Andrew Bennetts
All tests passing.
3493
                           ('repo/', 'bz2',),),
2018.18.7 by Martin Pool
(broken) Start addng client proxy test for Repository.tarball
3494
            ]
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3495
        repo, client = self.setup_fake_client_and_repository(transport_path)
3496
        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
3497
        # Now actually ask for the tarball
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3498
        tarball_file = repo._get_tarball('bz2')
2018.18.25 by Martin Pool
Repository.tarball fixes for python2.4
3499
        try:
3500
            self.assertEqual(expected_calls, client._calls)
3501
            self.assertEqual(self.tarball_content, tarball_file.read())
3502
        finally:
3503
            tarball_file.close()
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
3504
3505
3506
class TestRemoteRepositoryCopyContent(tests.TestCaseWithTransport):
3507
    """RemoteRepository.copy_content_into optimizations"""
3508
2018.18.10 by Martin Pool
copy_content_into from Remote repositories by using temporary directories on both ends.
3509
    def test_copy_content_remote_to_local(self):
5017.3.28 by Vincent Ladeuil
selftest -s bt.test_remote passing
3510
        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.
3511
        src_repo = self.make_repository('repo1')
3512
        src_repo = repository.Repository.open(self.get_url('repo1'))
3513
        # At the moment the tarball-based copy_content_into can't write back
3514
        # into a smart server.  It would be good if it could upload the
3515
        # tarball; once that works we'd have to create repositories of
3516
        # different formats. -- mbp 20070410
3517
        dest_url = self.get_vfs_only_url('repo2')
3518
        dest_bzrdir = BzrDir.create(dest_url)
3519
        dest_repo = dest_bzrdir.create_repository()
3520
        self.assertFalse(isinstance(dest_repo, RemoteRepository))
3521
        self.assertTrue(isinstance(src_repo, RemoteRepository))
3522
        src_repo.copy_content_into(dest_repo)
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
3523
3524
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
3525
class _StubRealPackRepository(object):
3526
3527
    def __init__(self, calls):
4145.1.6 by Robert Collins
More test fallout, but all caught now.
3528
        self.calls = calls
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
3529
        self._pack_collection = _StubPackCollection(calls)
3530
6280.7.8 by Jelmer Vernooij
make sure start_write_group falls back to real_repository if write groups aren't suspendable.
3531
    def start_write_group(self):
3532
        self.calls.append(('start_write_group',))
3533
4145.1.6 by Robert Collins
More test fallout, but all caught now.
3534
    def is_in_write_group(self):
3535
        return False
3536
3537
    def refresh_data(self):
3538
        self.calls.append(('pack collection reload_pack_names',))
3539
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
3540
3541
class _StubPackCollection(object):
3542
3543
    def __init__(self, calls):
3544
        self.calls = calls
3545
3546
    def autopack(self):
3547
        self.calls.append(('pack collection autopack',))
3548
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3549
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
3550
class TestRemotePackRepositoryAutoPack(TestRemoteRepository):
3551
    """Tests for RemoteRepository.autopack implementation."""
3552
3553
    def test_ok(self):
3554
        """When the server returns 'ok' and there's no _real_repository, then
3555
        nothing else happens: the autopack method is done.
3556
        """
3557
        transport_path = 'quack'
3558
        repo, client = self.setup_fake_client_and_repository(transport_path)
3559
        client.add_expected_call(
3801.1.13 by Andrew Bennetts
Revert returning of pack-names from the RPC.
3560
            'PackRepository.autopack', ('quack/',), 'success', ('ok',))
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
3561
        repo.autopack()
4523.3.1 by Andrew Bennetts
Change FakeClient.finished_test into a more typical assertion method on TestRemote.
3562
        self.assertFinished(client)
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
3563
3564
    def test_ok_with_real_repo(self):
3565
        """When the server returns 'ok' and there is a _real_repository, then
3566
        the _real_repository's reload_pack_name's method will be called.
3567
        """
3568
        transport_path = 'quack'
3569
        repo, client = self.setup_fake_client_and_repository(transport_path)
3570
        client.add_expected_call(
3571
            'PackRepository.autopack', ('quack/',),
3801.1.13 by Andrew Bennetts
Revert returning of pack-names from the RPC.
3572
            'success', ('ok',))
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
3573
        repo._real_repository = _StubRealPackRepository(client._calls)
3574
        repo.autopack()
3575
        self.assertEqual(
3576
            [('call', 'PackRepository.autopack', ('quack/',)),
3801.1.13 by Andrew Bennetts
Revert returning of pack-names from the RPC.
3577
             ('pack collection reload_pack_names',)],
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
3578
            client._calls)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3579
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
3580
    def test_backwards_compatibility(self):
3581
        """If the server does not recognise the PackRepository.autopack verb,
3582
        fallback to the real_repository's implementation.
3583
        """
3584
        transport_path = 'quack'
3585
        repo, client = self.setup_fake_client_and_repository(transport_path)
3586
        client.add_unknown_method_response('PackRepository.autopack')
3587
        def stub_ensure_real():
3588
            client._calls.append(('_ensure_real',))
3589
            repo._real_repository = _StubRealPackRepository(client._calls)
3590
        repo._ensure_real = stub_ensure_real
3591
        repo.autopack()
3592
        self.assertEqual(
3593
            [('call', 'PackRepository.autopack', ('quack/',)),
3594
             ('_ensure_real',),
3595
             ('pack collection autopack',)],
3596
            client._calls)
3597
5677.2.2 by Martin
Give clearer message when remote server reports a MemoryError
3598
    def test_oom_error_reporting(self):
3599
        """An out-of-memory condition on the server is reported clearly"""
3600
        transport_path = 'quack'
3601
        repo, client = self.setup_fake_client_and_repository(transport_path)
3602
        client.add_expected_call(
3603
            'PackRepository.autopack', ('quack/',),
3604
            'error', ('MemoryError',))
3605
        err = self.assertRaises(errors.BzrError, repo.autopack)
3606
        self.assertContainsRe(str(err), "^remote server out of mem")
3607
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
3608
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3609
class TestErrorTranslationBase(tests.TestCaseWithMemoryTransport):
6670.4.14 by Jelmer Vernooij
Move remote to breezy.bzr.
3610
    """Base class for unit tests for breezy.bzr.remote._translate_error."""
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3611
3612
    def translateTuple(self, error_tuple, **context):
3613
        """Call _translate_error with an ErrorFromSmartServer built from the
3614
        given error_tuple.
3615
3616
        :param error_tuple: A tuple of a smart server response, as would be
3617
            passed to an ErrorFromSmartServer.
3618
        :kwargs context: context items to call _translate_error with.
3619
3620
        :returns: The error raised by _translate_error.
3621
        """
3622
        # Raise the ErrorFromSmartServer before passing it as an argument,
3623
        # because _translate_error may need to re-raise it with a bare 'raise'
3624
        # statement.
3625
        server_error = errors.ErrorFromSmartServer(error_tuple)
3626
        translated_error = self.translateErrorFromSmartServer(
3627
            server_error, **context)
3628
        return translated_error
3629
3630
    def translateErrorFromSmartServer(self, error_object, **context):
3631
        """Like translateTuple, but takes an already constructed
3632
        ErrorFromSmartServer rather than a tuple.
3633
        """
3634
        try:
3635
            raise error_object
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
3636
        except errors.ErrorFromSmartServer as server_error:
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3637
            translated_error = self.assertRaises(
3638
                errors.BzrError, remote._translate_error, server_error,
3639
                **context)
3640
        return translated_error
3641
3801.1.4 by Andrew Bennetts
Add tests for autopack RPC.
3642
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3643
class TestErrorTranslationSuccess(TestErrorTranslationBase):
6670.4.14 by Jelmer Vernooij
Move remote to breezy.bzr.
3644
    """Unit tests for breezy.bzr.remote._translate_error.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3645
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
3646
    Given an ErrorFromSmartServer (which has an error tuple from a smart
3647
    server) and some context, _translate_error raises more specific errors from
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
3648
    breezy.errors.
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3649
3650
    This test case covers the cases where _translate_error succeeds in
3651
    translating an ErrorFromSmartServer to something better.  See
3652
    TestErrorTranslationRobustness for other cases.
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
3653
    """
3654
3655
    def test_NoSuchRevision(self):
3656
        branch = self.make_branch('')
3657
        revid = 'revid'
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3658
        translated_error = self.translateTuple(
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
3659
            ('NoSuchRevision', revid), branch=branch)
3660
        expected_error = errors.NoSuchRevision(branch, revid)
3661
        self.assertEqual(expected_error, translated_error)
3662
3663
    def test_nosuchrevision(self):
3664
        repository = self.make_repository('')
3665
        revid = 'revid'
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3666
        translated_error = self.translateTuple(
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
3667
            ('nosuchrevision', revid), repository=repository)
3668
        expected_error = errors.NoSuchRevision(repository, revid)
3669
        self.assertEqual(expected_error, translated_error)
3670
3671
    def test_nobranch(self):
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
3672
        bzrdir = self.make_controldir('')
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3673
        translated_error = self.translateTuple(('nobranch',), bzrdir=bzrdir)
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
3674
        expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
3675
        self.assertEqual(expected_error, translated_error)
3676
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).
3677
    def test_nobranch_one_arg(self):
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
3678
        bzrdir = self.make_controldir('')
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).
3679
        translated_error = self.translateTuple(
3680
            ('nobranch', 'extra detail'), bzrdir=bzrdir)
3681
        expected_error = errors.NotBranchError(
3682
            path=bzrdir.root_transport.base,
3683
            detail='extra detail')
3684
        self.assertEqual(expected_error, translated_error)
3685
5677.2.5 by Martin
Add more tests for remote._translate_error including for MemoryError handling
3686
    def test_norepository(self):
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
3687
        bzrdir = self.make_controldir('')
5677.2.5 by Martin
Add more tests for remote._translate_error including for MemoryError handling
3688
        translated_error = self.translateTuple(('norepository',),
3689
            bzrdir=bzrdir)
3690
        expected_error = errors.NoRepositoryPresent(bzrdir)
3691
        self.assertEqual(expected_error, translated_error)
3692
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
3693
    def test_LockContention(self):
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3694
        translated_error = self.translateTuple(('LockContention',))
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
3695
        expected_error = errors.LockContention('(remote lock)')
3696
        self.assertEqual(expected_error, translated_error)
3697
3698
    def test_UnlockableTransport(self):
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
3699
        bzrdir = self.make_controldir('')
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3700
        translated_error = self.translateTuple(
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
3701
            ('UnlockableTransport',), bzrdir=bzrdir)
3702
        expected_error = errors.UnlockableTransport(bzrdir.root_transport)
3703
        self.assertEqual(expected_error, translated_error)
3704
3705
    def test_LockFailed(self):
3706
        lock = 'str() of a server lock'
3707
        why = 'str() of why'
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3708
        translated_error = self.translateTuple(('LockFailed', lock, why))
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
3709
        expected_error = errors.LockFailed(lock, why)
3710
        self.assertEqual(expected_error, translated_error)
3711
3712
    def test_TokenMismatch(self):
3713
        token = 'a lock token'
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3714
        translated_error = self.translateTuple(('TokenMismatch',), token=token)
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
3715
        expected_error = errors.TokenMismatch(token, '(remote token)')
3716
        self.assertEqual(expected_error, translated_error)
3717
3718
    def test_Diverged(self):
3719
        branch = self.make_branch('a')
3720
        other_branch = self.make_branch('b')
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3721
        translated_error = self.translateTuple(
3533.3.3 by Andrew Bennetts
Add unit tests for bzrlib.remote._translate_error.
3722
            ('Diverged',), branch=branch, other_branch=other_branch)
3723
        expected_error = errors.DivergedBranches(branch, other_branch)
3724
        self.assertEqual(expected_error, translated_error)
3725
5677.2.5 by Martin
Add more tests for remote._translate_error including for MemoryError handling
3726
    def test_NotStacked(self):
3727
        branch = self.make_branch('')
3728
        translated_error = self.translateTuple(('NotStacked',), branch=branch)
3729
        expected_error = errors.NotStacked(branch)
3730
        self.assertEqual(expected_error, translated_error)
3731
3786.4.2 by Andrew Bennetts
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
3732
    def test_ReadError_no_args(self):
3733
        path = 'a path'
3734
        translated_error = self.translateTuple(('ReadError',), path=path)
3735
        expected_error = errors.ReadError(path)
3736
        self.assertEqual(expected_error, translated_error)
3737
3738
    def test_ReadError(self):
3739
        path = 'a path'
3740
        translated_error = self.translateTuple(('ReadError', path))
3741
        expected_error = errors.ReadError(path)
3742
        self.assertEqual(expected_error, translated_error)
3743
4650.2.1 by Robert Collins
Deserialise IncompatibleRepositories errors in the client, generating
3744
    def test_IncompatibleRepositories(self):
3745
        translated_error = self.translateTuple(('IncompatibleRepositories',
3746
            "repo1", "repo2", "details here"))
3747
        expected_error = errors.IncompatibleRepositories("repo1", "repo2",
3748
            "details here")
3749
        self.assertEqual(expected_error, translated_error)
3750
3786.4.2 by Andrew Bennetts
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
3751
    def test_PermissionDenied_no_args(self):
3752
        path = 'a path'
5677.2.5 by Martin
Add more tests for remote._translate_error including for MemoryError handling
3753
        translated_error = self.translateTuple(('PermissionDenied',),
3754
            path=path)
3786.4.2 by Andrew Bennetts
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
3755
        expected_error = errors.PermissionDenied(path)
3756
        self.assertEqual(expected_error, translated_error)
3757
3758
    def test_PermissionDenied_one_arg(self):
3759
        path = 'a path'
3760
        translated_error = self.translateTuple(('PermissionDenied', path))
3761
        expected_error = errors.PermissionDenied(path)
3762
        self.assertEqual(expected_error, translated_error)
3763
3764
    def test_PermissionDenied_one_arg_and_context(self):
3765
        """Given a choice between a path from the local context and a path on
3766
        the wire, _translate_error prefers the path from the local context.
3767
        """
3768
        local_path = 'local path'
3769
        remote_path = 'remote path'
3770
        translated_error = self.translateTuple(
3771
            ('PermissionDenied', remote_path), path=local_path)
3772
        expected_error = errors.PermissionDenied(local_path)
3773
        self.assertEqual(expected_error, translated_error)
3774
3775
    def test_PermissionDenied_two_args(self):
3776
        path = 'a path'
3777
        extra = 'a string with extra info'
3778
        translated_error = self.translateTuple(
3779
            ('PermissionDenied', path, extra))
3780
        expected_error = errors.PermissionDenied(path, extra)
3781
        self.assertEqual(expected_error, translated_error)
3782
5677.2.5 by Martin
Add more tests for remote._translate_error including for MemoryError handling
3783
    # GZ 2011-03-02: TODO test for PermissionDenied with non-ascii 'extra'
3784
3785
    def test_NoSuchFile_context_path(self):
3786
        local_path = "local path"
3787
        translated_error = self.translateTuple(('ReadError', "remote path"),
3788
            path=local_path)
3789
        expected_error = errors.ReadError(local_path)
3790
        self.assertEqual(expected_error, translated_error)
3791
3792
    def test_NoSuchFile_without_context(self):
3793
        remote_path = "remote path"
3794
        translated_error = self.translateTuple(('ReadError', remote_path))
3795
        expected_error = errors.ReadError(remote_path)
3796
        self.assertEqual(expected_error, translated_error)
3797
3798
    def test_ReadOnlyError(self):
3799
        translated_error = self.translateTuple(('ReadOnlyError',))
3800
        expected_error = errors.TransportNotPossible("readonly transport")
3801
        self.assertEqual(expected_error, translated_error)
3802
3803
    def test_MemoryError(self):
3804
        translated_error = self.translateTuple(('MemoryError',))
5677.2.9 by Martin
Add hint to possible ways forward for user in remote MemoryError message
3805
        self.assertStartsWith(str(translated_error),
3806
            "remote server out of memory")
5677.2.5 by Martin
Add more tests for remote._translate_error including for MemoryError handling
3807
5677.2.8 by Martin
More tests for handling of unexpected remote errors
3808
    def test_generic_IndexError_no_classname(self):
5677.2.5 by Martin
Add more tests for remote._translate_error including for MemoryError handling
3809
        err = errors.ErrorFromSmartServer(('error', "list index out of range"))
3810
        translated_error = self.translateErrorFromSmartServer(err)
3811
        expected_error = errors.UnknownErrorFromSmartServer(err)
3812
        self.assertEqual(expected_error, translated_error)
3813
3814
    # GZ 2011-03-02: TODO test generic non-ascii error string
3815
5677.2.8 by Martin
More tests for handling of unexpected remote errors
3816
    def test_generic_KeyError(self):
3817
        err = errors.ErrorFromSmartServer(('error', 'KeyError', "1"))
3818
        translated_error = self.translateErrorFromSmartServer(err)
3819
        expected_error = errors.UnknownErrorFromSmartServer(err)
3820
        self.assertEqual(expected_error, translated_error)
3821
3786.4.2 by Andrew Bennetts
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
3822
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3823
class TestErrorTranslationRobustness(TestErrorTranslationBase):
6670.4.14 by Jelmer Vernooij
Move remote to breezy.bzr.
3824
    """Unit tests for breezy.bzr.remote._translate_error's robustness.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3825
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3826
    TestErrorTranslationSuccess is for cases where _translate_error can
3827
    translate successfully.  This class about how _translate_err behaves when
3828
    it fails to translate: it re-raises the original error.
3829
    """
3830
3831
    def test_unrecognised_server_error(self):
3832
        """If the error code from the server is not recognised, the original
3833
        ErrorFromSmartServer is propagated unmodified.
3834
        """
3835
        error_tuple = ('An unknown error tuple',)
3690.1.2 by Andrew Bennetts
Rename UntranslateableErrorFromSmartServer -> UnknownErrorFromSmartServer.
3836
        server_error = errors.ErrorFromSmartServer(error_tuple)
3837
        translated_error = self.translateErrorFromSmartServer(server_error)
3838
        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.
3839
        self.assertEqual(expected_error, translated_error)
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3840
3841
    def test_context_missing_a_key(self):
3842
        """In case of a bug in the client, or perhaps an unexpected response
3843
        from a server, _translate_error returns the original error tuple from
3844
        the server and mutters a warning.
3845
        """
3846
        # To translate a NoSuchRevision error _translate_error needs a 'branch'
3847
        # in the context dict.  So let's give it an empty context dict instead
3848
        # to exercise its error recovery.
3849
        empty_context = {}
3850
        error_tuple = ('NoSuchRevision', 'revid')
3851
        server_error = errors.ErrorFromSmartServer(error_tuple)
3852
        translated_error = self.translateErrorFromSmartServer(server_error)
3853
        self.assertEqual(server_error, translated_error)
3854
        # In addition to re-raising ErrorFromSmartServer, some debug info has
3855
        # been muttered to the log file for developer to look at.
3856
        self.assertContainsRe(
4794.1.15 by Robert Collins
Review feedback.
3857
            self.get_log(),
3533.3.4 by Andrew Bennetts
Add tests for _translate_error's robustness.
3858
            "Missing key 'branch' in context")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3859
3786.4.2 by Andrew Bennetts
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
3860
    def test_path_missing(self):
3861
        """Some translations (PermissionDenied, ReadError) can determine the
3862
        'path' variable from either the wire or the local context.  If neither
3863
        has it, then an error is raised.
3864
        """
3865
        error_tuple = ('ReadError',)
3866
        server_error = errors.ErrorFromSmartServer(error_tuple)
3867
        translated_error = self.translateErrorFromSmartServer(server_error)
3868
        self.assertEqual(server_error, translated_error)
3869
        # In addition to re-raising ErrorFromSmartServer, some debug info has
3870
        # been muttered to the log file for developer to look at.
4794.1.15 by Robert Collins
Review feedback.
3871
        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.
3872
3691.2.2 by Martin Pool
Fix some problems in access to stacked repositories over hpss (#261315)
3873
3874
class TestStacking(tests.TestCaseWithTransport):
3875
    """Tests for operations on stacked remote repositories.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3876
3691.2.2 by Martin Pool
Fix some problems in access to stacked repositories over hpss (#261315)
3877
    The underlying format type must support stacking.
3878
    """
3879
3880
    def test_access_stacked_remote(self):
3881
        # based on <http://launchpad.net/bugs/261315>
3882
        # make a branch stacked on another repository containing an empty
3883
        # revision, then open it over hpss - we should be able to see that
3884
        # revision.
3885
        base_transport = self.get_transport()
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3886
        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)
3887
        base_builder.start_series()
3888
        base_revid = base_builder.build_snapshot('rev-id', None,
3889
            [('add', ('', None, 'directory', None))],
3890
            'message')
3891
        base_builder.finish_series()
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3892
        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)
3893
        stacked_branch.set_stacked_on_url('../base')
3894
        # start a server looking at this
5017.3.28 by Vincent Ladeuil
selftest -s bt.test_remote passing
3895
        smart_server = test_server.SmartTCPServer_for_testing()
4659.1.3 by Robert Collins
Review feedback.
3896
        self.start_server(smart_server)
3691.2.2 by Martin Pool
Fix some problems in access to stacked repositories over hpss (#261315)
3897
        remote_bzrdir = BzrDir.open(smart_server.get_url() + '/stacked')
3898
        # can get its branch and repository
3899
        remote_branch = remote_bzrdir.open_branch()
3900
        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
3901
        remote_repo.lock_read()
3902
        try:
3903
            # it should have an appropriate fallback repository, which should also
3904
            # be a RemoteRepository
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
3905
            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
3906
            self.assertIsInstance(remote_repo._fallback_repositories[0],
3907
                RemoteRepository)
3908
            # and it has the revision committed to the underlying repository;
3909
            # these have varying implementations so we try several of them
3910
            self.assertTrue(remote_repo.has_revisions([base_revid]))
3911
            self.assertTrue(remote_repo.has_revision(base_revid))
3912
            self.assertEqual(remote_repo.get_revision(base_revid).message,
3913
                'message')
3914
        finally:
3915
            remote_repo.unlock()
3835.1.2 by Aaron Bentley
Add tests for get_parent_map
3916
3835.1.7 by Aaron Bentley
Updates from review
3917
    def prepare_stacked_remote_branch(self):
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3918
        """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.
3919
        self.setup_smart_server_with_call_log()
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3920
        tree1 = self.make_branch_and_tree('tree1', format='1.9')
3835.1.2 by Aaron Bentley
Add tests for get_parent_map
3921
        tree1.commit('rev1', rev_id='rev1')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
3922
        tree2 = tree1.branch.controldir.sprout('tree2', stacked=True
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3923
            ).open_workingtree()
4595.4.4 by Robert Collins
Disable committing directly to stacked branches from lightweight checkouts.
3924
        local_tree = tree2.branch.create_checkout('local')
3925
        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.
3926
        branch2 = Branch.open(self.get_url('tree2'))
3835.1.2 by Aaron Bentley
Add tests for get_parent_map
3927
        branch2.lock_read()
3928
        self.addCleanup(branch2.unlock)
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3929
        return tree1.branch, branch2
3835.1.7 by Aaron Bentley
Updates from review
3930
3931
    def test_stacked_get_parent_map(self):
3932
        # 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.
3933
        _, branch = self.prepare_stacked_remote_branch()
3835.1.7 by Aaron Bentley
Updates from review
3934
        repo = branch.repository
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
3935
        self.assertEqual({'rev1'}, set(repo.get_parent_map(['rev1'])))
3835.1.7 by Aaron Bentley
Updates from review
3936
3835.1.10 by Aaron Bentley
Move CachingExtraParentsProvider to Graph
3937
    def test_unstacked_get_parent_map(self):
3938
        # _unstacked_provider.get_parent_map ignores stacking
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3939
        _, branch = self.prepare_stacked_remote_branch()
3835.1.10 by Aaron Bentley
Move CachingExtraParentsProvider to Graph
3940
        provider = branch.repository._unstacked_provider
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
3941
        self.assertEqual(set(), set(provider.get_parent_map(['rev1'])))
3834.3.3 by John Arbash Meinel
Merge bzr.dev, resolve conflict in tests.
3942
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3943
    def fetch_stream_to_rev_order(self, stream):
3944
        result = []
3945
        for kind, substream in stream:
3946
            if not kind == 'revisions':
3947
                list(substream)
3948
            else:
3949
                for content in substream:
3950
                    result.append(content.key[-1])
3951
        return result
3952
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)
3953
    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.
3954
        """Get a list of the revisions in a stream to format format.
3955
3956
        :param format: The format of the target.
3957
        :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)
3958
        :param branch_factory: A callable to create a trunk and stacked branch
3959
            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.
3960
        :result: The revision ids in the stream, in the order seen,
3961
            the topological order of revisions in the source.
3962
        """
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
3963
        unordered_format = controldir.format_registry.get(format)()
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3964
        target_repository_format = unordered_format.repository_format
3965
        # Cross check
3966
        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)
3967
        if branch_factory is None:
3968
            branch_factory = self.prepare_stacked_remote_branch
3969
        _, stacked = branch_factory()
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3970
        source = stacked.repository._get_source(target_repository_format)
3971
        tip = stacked.last_revision()
5972.3.25 by Jelmer Vernooij
Fix another use of get_ancestry.
3972
        stacked.repository._ensure_real()
3973
        graph = stacked.repository.get_graph()
3974
        revs = [r for (r,ps) in graph.iter_ancestry([tip])
3975
                if r != NULL_REVISION]
3976
        revs.reverse()
6341.1.4 by Jelmer Vernooij
Move more functionality to vf_search.
3977
        search = vf_search.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.
3978
        self.reset_smart_call_log()
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3979
        stream = source.get_stream(search)
3980
        # We trust that if a revision is in the stream the rest of the new
3981
        # content for it is too, as per our main fetch tests; here we are
3982
        # checking that the revisions are actually included at all, and their
3983
        # order.
3984
        return self.fetch_stream_to_rev_order(stream), revs
3985
3986
    def test_stacked_get_stream_unordered(self):
3987
        # Repository._get_source.get_stream() from a stacked repository with
3988
        # unordered yields the full data from both stacked and stacked upon
3989
        # sources.
3990
        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.
3991
        self.assertEqual(set(expected_revs), set(rev_ord))
3992
        # Getting unordered results should have made a streaming data request
3993
        # from the server, then one from the backing branch.
3994
        self.assertLength(2, self.hpss_calls)
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
3995
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)
3996
    def test_stacked_on_stacked_get_stream_unordered(self):
3997
        # Repository._get_source.get_stream() from a stacked repository which
3998
        # is itself stacked yields the full data from all three sources.
3999
        def make_stacked_stacked():
4000
            _, stacked = self.prepare_stacked_remote_branch()
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
4001
            tree = stacked.controldir.sprout('tree3', stacked=True
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)
4002
                ).open_workingtree()
4595.4.4 by Robert Collins
Disable committing directly to stacked branches from lightweight checkouts.
4003
            local_tree = tree.branch.create_checkout('local-tree3')
4004
            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)
4005
            branch = Branch.open(self.get_url('tree3'))
4006
            branch.lock_read()
4857.2.3 by John Arbash Meinel
Found the failed-to-unlocked branches in test_remote.
4007
            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)
4008
            return None, branch
4009
        rev_ord, expected_revs = self.get_ordered_revs('1.9', 'unordered',
4010
            branch_factory=make_stacked_stacked)
4011
        self.assertEqual(set(expected_revs), set(rev_ord))
4012
        # Getting unordered results should have made a streaming data request
4013
        # from the server, and one from each backing repo
4014
        self.assertLength(3, self.hpss_calls)
4015
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
4016
    def test_stacked_get_stream_topological(self):
4017
        # Repository._get_source.get_stream() from a stacked repository with
4018
        # topological sorting yields the full data from both stacked and
4019
        # stacked upon sources in topological order.
4020
        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.
4021
        self.assertEqual(expected_revs, rev_ord)
4595.4.4 by Robert Collins
Disable committing directly to stacked branches from lightweight checkouts.
4022
        # Getting topological sort requires VFS calls still - one of which is
4023
        # pushing up from the bound branch.
5972.3.25 by Jelmer Vernooij
Fix another use of get_ancestry.
4024
        self.assertLength(14, self.hpss_calls)
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
4025
4026
    def test_stacked_get_stream_groupcompress(self):
4027
        # Repository._get_source.get_stream() from a stacked repository with
4028
        # groupcompress sorting yields the full data from both stacked and
4029
        # stacked upon sources in groupcompress order.
4030
        raise tests.TestSkipped('No groupcompress ordered format available')
4031
        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.
4032
        self.assertEqual(expected_revs, reversed(rev_ord))
4033
        # Getting unordered results should have made a streaming data request
4034
        # from the backing branch, and one from the stacked on branch.
4035
        self.assertLength(2, self.hpss_calls)
4152.1.1 by Robert Collins
Add specific tests for fetch streaming in the bzr protocol client.
4036
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.
4037
    def test_stacked_pull_more_than_stacking_has_bug_360791(self):
4038
        # When pulling some fixed amount of content that is more than the
4039
        # source has (because some is coming from a fallback branch, no error
4040
        # should be received. This was reported as bug 360791.
4041
        # Need three branches: a trunk, a stacked branch, and a preexisting
4042
        # branch pulling content from stacked and trunk.
4043
        self.setup_smart_server_with_call_log()
4044
        trunk = self.make_branch_and_tree('trunk', format="1.9-rich-root")
4045
        r1 = trunk.commit('start')
4046
        stacked_branch = trunk.branch.create_clone_on_transport(
4047
            self.get_transport('stacked'), stacked_on=trunk.branch.base)
4048
        local = self.make_branch('local', format='1.9-rich-root')
4049
        local.repository.fetch(stacked_branch.repository,
4050
            stacked_branch.last_revision())
4051
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.
4052
4053
class TestRemoteBranchEffort(tests.TestCaseWithTransport):
4054
4055
    def setUp(self):
4056
        super(TestRemoteBranchEffort, self).setUp()
4057
        # Create a smart server that publishes whatever the backing VFS server
4058
        # does.
5017.3.28 by Vincent Ladeuil
selftest -s bt.test_remote passing
4059
        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,
4060
        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.
4061
        # Log all HPSS calls into self.hpss_calls.
4062
        _SmartClient.hooks.install_named_hook(
4063
            'call', self.capture_hpss_call, None)
4064
        self.hpss_calls = []
4065
4066
    def capture_hpss_call(self, params):
4067
        self.hpss_calls.append(params.method)
4068
4069
    def test_copy_content_into_avoids_revision_history(self):
4070
        local = self.make_branch('local')
5539.2.5 by Andrew Bennetts
Add test to test_remote, fix another shallow bug.
4071
        builder = self.make_branch_builder('remote')
4072
        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.
4073
        remote_branch_url = self.smart_server.get_url() + 'remote'
4074
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
4075
        local.repository.fetch(remote_branch.repository)
4076
        self.hpss_calls = []
4077
        remote_branch.copy_content_into(local)
3834.3.3 by John Arbash Meinel
Merge bzr.dev, resolve conflict in tests.
4078
        self.assertFalse('Branch.revision_history' in self.hpss_calls)
5539.2.5 by Andrew Bennetts
Add test to test_remote, fix another shallow bug.
4079
5539.2.6 by Andrew Bennetts
Better test name.
4080
    def test_fetch_everything_needs_just_one_call(self):
5539.2.5 by Andrew Bennetts
Add test to test_remote, fix another shallow bug.
4081
        local = self.make_branch('local')
4082
        builder = self.make_branch_builder('remote')
4083
        builder.build_commit(message="Commit.")
4084
        remote_branch_url = self.smart_server.get_url() + 'remote'
4085
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
4086
        self.hpss_calls = []
6015.5.1 by Vincent Ladeuil
Merge 2.3 into 2.4
4087
        local.repository.fetch(
4088
            remote_branch.repository,
6341.1.4 by Jelmer Vernooij
Move more functionality to vf_search.
4089
            fetch_spec=vf_search.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.
4090
        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.
4091
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
4092
    def override_verb(self, verb_name, verb):
4093
        request_handlers = request.request_handlers
4094
        orig_verb = request_handlers.get(verb_name)
6206.1.11 by Jelmer Vernooij
Preserve info when restoring verbs after disabling/overriding.
4095
        orig_info = request_handlers.get_info(verb_name)
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
4096
        request_handlers.register(verb_name, verb, override_existing=True)
4097
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
6206.1.11 by Jelmer Vernooij
Preserve info when restoring verbs after disabling/overriding.
4098
                override_existing=True, info=orig_info)
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
4099
5539.2.13 by Andrew Bennetts
Add a test for compatibility with pre-2.3 servers.
4100
    def test_fetch_everything_backwards_compat(self):
5536.3.3 by Andrew Bennetts
Merge lp:bzr.
4101
        """Can fetch with EverythingResult even with pre 2.4 servers.
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
4102
        
5536.3.3 by Andrew Bennetts
Merge lp:bzr.
4103
        Pre-2.4 do not support 'everything' searches with the
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
4104
        Repository.get_stream_1.19 verb.
5539.2.13 by Andrew Bennetts
Add a test for compatibility with pre-2.3 servers.
4105
        """
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
4106
        verb_log = []
4107
        class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
4108
            """A version of the Repository.get_stream_1.19 verb patched to
5536.3.3 by Andrew Bennetts
Merge lp:bzr.
4109
            reject 'everything' searches the way 2.3 and earlier do.
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
4110
            """
6015.5.1 by Vincent Ladeuil
Merge 2.3 into 2.4
4111
            def recreate_search(self, repository, search_bytes,
4112
                                discard_excess=False):
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
4113
                verb_log.append(search_bytes.split('\n', 1)[0])
4114
                if search_bytes == 'everything':
6015.5.1 by Vincent Ladeuil
Merge 2.3 into 2.4
4115
                    return (None,
4116
                            request.FailedSmartServerResponse(('BadSearch',)))
5536.2.7 by Andrew Bennetts
Fix test_fetch_everything_backwards_compat to actually test what it is intended to test.
4117
                return super(OldGetStreamVerb,
4118
                        self).recreate_search(repository, search_bytes,
4119
                            discard_excess=discard_excess)
4120
        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.
4121
        local = self.make_branch('local')
4122
        builder = self.make_branch_builder('remote')
4123
        builder.build_commit(message="Commit.")
4124
        remote_branch_url = self.smart_server.get_url() + 'remote'
4125
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
4126
        self.hpss_calls = []
6015.5.1 by Vincent Ladeuil
Merge 2.3 into 2.4
4127
        local.repository.fetch(
4128
            remote_branch.repository,
6341.1.4 by Jelmer Vernooij
Move more functionality to vf_search.
4129
            fetch_spec=vf_search.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.
4130
        # make sure the overridden verb was used
4131
        self.assertLength(1, verb_log)
4132
        # more than one HPSS call is needed, but because it's a VFS callback
4133
        # its hard to predict exactly how many.
4134
        self.assertTrue(len(self.hpss_calls) > 1)
5539.2.13 by Andrew Bennetts
Add a test for compatibility with pre-2.3 servers.
4135
5609.50.1 by Vincent Ladeuil
Be more tolerant about ``bound_location`` from config files
4136
5609.50.4 by Vincent Ladeuil
Add more tests for accepted bound_location variations.
4137
class TestUpdateBoundBranchWithModifiedBoundLocation(
4138
    tests.TestCaseWithTransport):
4139
    """Ensure correct handling of bound_location modifications.
4140
4141
    This is tested against a smart server as http://pad.lv/786980 was about a
4142
    ReadOnlyError (write attempt during a read-only transaction) which can only
4143
    happen in this context.
4144
    """
4145
4146
    def setUp(self):
4147
        super(TestUpdateBoundBranchWithModifiedBoundLocation, self).setUp()
5609.50.1 by Vincent Ladeuil
Be more tolerant about ``bound_location`` from config files
4148
        self.transport_server = test_server.SmartTCPServer_for_testing
5609.50.4 by Vincent Ladeuil
Add more tests for accepted bound_location variations.
4149
4150
    def make_master_and_checkout(self, master_name, checkout_name):
4151
        # Create the master branch and its associated checkout
4152
        self.master = self.make_branch_and_tree(master_name)
4153
        self.checkout = self.master.branch.create_checkout(checkout_name)
4154
        # Modify the master branch so there is something to update
4155
        self.master.commit('add stuff')
4156
        self.last_revid = self.master.commit('even more stuff')
4157
        self.bound_location = self.checkout.branch.get_bound_location()
4158
4159
    def assertUpdateSucceeds(self, new_location):
6404.6.7 by Vincent Ladeuil
Change set/remove to require a lock for the branch config files.
4160
        self.checkout.branch.set_bound_location(new_location)
4161
        self.checkout.update()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4162
        self.assertEqual(self.last_revid, self.checkout.last_revision())
5609.50.4 by Vincent Ladeuil
Add more tests for accepted bound_location variations.
4163
4164
    def test_without_final_slash(self):
4165
        self.make_master_and_checkout('master', 'checkout')
5609.50.1 by Vincent Ladeuil
Be more tolerant about ``bound_location`` from config files
4166
        # For unclear reasons some users have a bound_location without a final
4167
        # '/', simulate that by forcing such a value
5609.50.4 by Vincent Ladeuil
Add more tests for accepted bound_location variations.
4168
        self.assertEndsWith(self.bound_location, '/')
4169
        self.assertUpdateSucceeds(self.bound_location.rstrip('/'))
4170
4171
    def test_plus_sign(self):
4172
        self.make_master_and_checkout('+master', 'checkout')
4173
        self.assertUpdateSucceeds(self.bound_location.replace('%2B', '+', 1))
4174
4175
    def test_tilda(self):
4176
        # Embed ~ in the middle of the path just to avoid any $HOME
4177
        # interpretation
4178
        self.make_master_and_checkout('mas~ter', 'checkout')
4179
        self.assertUpdateSucceeds(self.bound_location.replace('%2E', '~', 1))
6284.1.1 by Jelmer Vernooij
Allow registering custom error handlers in the HPSS client.
4180
4181
4182
class TestWithCustomErrorHandler(RemoteBranchTestCase):
4183
4184
    def test_no_context(self):
4185
        class OutOfCoffee(errors.BzrError):
4186
            """A dummy exception for testing."""
4187
4188
            def __init__(self, urgency):
4189
                self.urgency = urgency
4190
        remote.no_context_error_translators.register("OutOfCoffee",
4191
            lambda err: OutOfCoffee(err.error_args[0]))
4192
        transport = MemoryTransport()
4193
        client = FakeClient(transport.base)
4194
        client.add_expected_call(
4195
            'Branch.get_stacked_on_url', ('quack/',),
4196
            'error', ('NotStacked',))
4197
        client.add_expected_call(
4198
            'Branch.last_revision_info',
4199
            ('quack/',),
4200
            'error', ('OutOfCoffee', 'low'))
4201
        transport.mkdir('quack')
4202
        transport = transport.clone('quack')
4203
        branch = self.make_remote_branch(transport, client)
4204
        self.assertRaises(OutOfCoffee, branch.last_revision_info)
4205
        self.assertFinished(client)
4206
4207
    def test_with_context(self):
4208
        class OutOfTea(errors.BzrError):
4209
            def __init__(self, branch, urgency):
4210
                self.branch = branch
4211
                self.urgency = urgency
4212
        remote.error_translators.register("OutOfTea",
4213
            lambda err, find, path: OutOfTea(err.error_args[0],
4214
                find("branch")))
4215
        transport = MemoryTransport()
4216
        client = FakeClient(transport.base)
4217
        client.add_expected_call(
4218
            'Branch.get_stacked_on_url', ('quack/',),
4219
            'error', ('NotStacked',))
4220
        client.add_expected_call(
4221
            'Branch.last_revision_info',
4222
            ('quack/',),
4223
            'error', ('OutOfTea', 'low'))
4224
        transport.mkdir('quack')
4225
        transport = transport.clone('quack')
4226
        branch = self.make_remote_branch(transport, client)
4227
        self.assertRaises(OutOfTea, branch.last_revision_info)
4228
        self.assertFinished(client)
6305.2.1 by Jelmer Vernooij
add remote call for Repository.pack.
4229
4230
4231
class TestRepositoryPack(TestRemoteRepository):
4232
4233
    def test_pack(self):
4234
        transport_path = 'quack'
4235
        repo, client = self.setup_fake_client_and_repository(transport_path)
4236
        client.add_expected_call(
4237
            'Repository.lock_write', ('quack/', ''),
4238
            'success', ('ok', 'token'))
4239
        client.add_expected_call(
6305.2.4 by Jelmer Vernooij
Fix tests.
4240
            'Repository.pack', ('quack/', 'token', 'False'),
6305.2.3 by Jelmer Vernooij
Store hint in body.
4241
            'success', ('ok',), )
6305.2.4 by Jelmer Vernooij
Fix tests.
4242
        client.add_expected_call(
4243
            'Repository.unlock', ('quack/', 'token'),
4244
            'success', ('ok', ))
6305.2.1 by Jelmer Vernooij
add remote call for Repository.pack.
4245
        repo.pack()
4246
4247
    def test_pack_with_hint(self):
4248
        transport_path = 'quack'
4249
        repo, client = self.setup_fake_client_and_repository(transport_path)
4250
        client.add_expected_call(
4251
            'Repository.lock_write', ('quack/', ''),
4252
            'success', ('ok', 'token'))
4253
        client.add_expected_call(
6305.2.4 by Jelmer Vernooij
Fix tests.
4254
            'Repository.pack', ('quack/', 'token', 'False'),
6305.2.3 by Jelmer Vernooij
Store hint in body.
4255
            'success', ('ok',), )
6305.2.4 by Jelmer Vernooij
Fix tests.
4256
        client.add_expected_call(
4257
            'Repository.unlock', ('quack/', 'token', 'False'),
4258
            'success', ('ok', ))
6305.2.1 by Jelmer Vernooij
add remote call for Repository.pack.
4259
        repo.pack(['hinta', 'hintb'])
6282.6.8 by Jelmer Vernooij
Adjust _iter_inventories contract slightly, don't raise NoSuchRevision immediately
4260
4261
6282.6.9 by Jelmer Vernooij
More tests.
4262
class TestRepositoryIterInventories(TestRemoteRepository):
4263
    """Test Repository.iter_inventories."""
6282.6.8 by Jelmer Vernooij
Adjust _iter_inventories contract slightly, don't raise NoSuchRevision immediately
4264
4265
    def _serialize_inv_delta(self, old_name, new_name, delta):
4266
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
4267
        return "".join(serializer.delta_to_lines(old_name, new_name, delta))
4268
6282.6.9 by Jelmer Vernooij
More tests.
4269
    def test_single_empty(self):
6282.6.8 by Jelmer Vernooij
Adjust _iter_inventories contract slightly, don't raise NoSuchRevision immediately
4270
        transport_path = 'quack'
4271
        repo, client = self.setup_fake_client_and_repository(transport_path)
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
4272
        fmt = controldir.format_registry.get('2a')().repository_format
6282.6.37 by Jelmer Vernooij
Cope with empty results.
4273
        repo._format = fmt
6282.6.43 by Jelmer Vernooij
Fix stream name.
4274
        stream = [('inventory-deltas', [
6282.6.37 by Jelmer Vernooij
Cope with empty results.
4275
            versionedfile.FulltextContentFactory('somerevid', None, None,
4276
                self._serialize_inv_delta('null:', 'somerevid', []))])]
6282.6.8 by Jelmer Vernooij
Adjust _iter_inventories contract slightly, don't raise NoSuchRevision immediately
4277
        client.add_expected_call(
6282.6.31 by Jelmer Vernooij
Use record streams in get_inventories call.
4278
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
6282.6.8 by Jelmer Vernooij
Adjust _iter_inventories contract slightly, don't raise NoSuchRevision immediately
4279
            'success', ('ok', ),
6282.6.37 by Jelmer Vernooij
Cope with empty results.
4280
            _stream_to_byte_stream(stream, fmt))
6282.6.9 by Jelmer Vernooij
More tests.
4281
        ret = list(repo.iter_inventories(["somerevid"]))
4282
        self.assertLength(1, ret)
4283
        inv = ret[0]
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4284
        self.assertEqual("somerevid", inv.revision_id)
6282.6.9 by Jelmer Vernooij
More tests.
4285
4286
    def test_empty(self):
4287
        transport_path = 'quack'
4288
        repo, client = self.setup_fake_client_and_repository(transport_path)
4289
        ret = list(repo.iter_inventories([]))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4290
        self.assertEqual(ret, [])
6282.6.9 by Jelmer Vernooij
More tests.
4291
4292
    def test_missing(self):
4293
        transport_path = 'quack'
4294
        repo, client = self.setup_fake_client_and_repository(transport_path)
4295
        client.add_expected_call(
6282.6.31 by Jelmer Vernooij
Use record streams in get_inventories call.
4296
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
6282.6.9 by Jelmer Vernooij
More tests.
4297
            'success', ('ok', ), iter([]))
4298
        self.assertRaises(errors.NoSuchRevision, list, repo.iter_inventories(
4299
            ["somerevid"]))