/brz/remove-bazaar

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