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