/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6614.1.1 by Vincent Ladeuil
Fix assert_ being deprecated by using assertTrue.
1
# Copyright (C) 2006-2016 Canonical Ltd
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
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
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
16
17
"""Tests for smart transport"""
18
19
# all of this deals with byte strings so this is safe
6133.4.55 by John Arbash Meinel
Now we've implemented the basic structure.
20
import doctest
4797.85.22 by John Arbash Meinel
Pull out portable_socket_pair.
21
import errno
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
22
import os
23
import socket
4797.85.9 by John Arbash Meinel
Start writing a test of how subprocess handles writing to a closed connection.
24
import subprocess
6133.4.10 by John Arbash Meinel
Handle the win32 not-a-socket errors. I think this is ~ready. At least for feedback.
25
import sys
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
26
import threading
6133.4.43 by John Arbash Meinel
Initial implementation of SIGHUP for bzr serve. bug #795025.
27
import time
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
28
6133.4.55 by John Arbash Meinel
Now we've implemented the basic structure.
29
from testtools.matchers import DocTestMatches
30
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
31
import breezy
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
32
from .. import (
6670.4.1 by Jelmer Vernooij
Update imports.
33
    controldir,
34
    debug,
35
    errors,
36
    osutils,
37
    tests,
38
    transport as _mod_transport,
39
    urlutils,
40
    )
41
from ..bzr import (
42
    bzrdir,
43
    )
6670.4.16 by Jelmer Vernooij
Move smart to breezy.bzr.
44
from ..bzr.smart import (
6670.4.1 by Jelmer Vernooij
Update imports.
45
    client,
46
    medium,
47
    message,
48
    protocol,
49
    request as _mod_request,
50
    server as _mod_server,
51
    vfs,
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
52
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
53
from . import (
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
54
    features,
5247.2.10 by Vincent Ladeuil
Use SmartTCPServer_for_testing instead of SmartTCPServer (broken).
55
    test_smart,
5247.3.47 by Vincent Ladeuil
Use SmartTCPServer_for_testing for TestSmartTCPServer.test_get_error_unexpected.
56
    test_server,
5247.2.10 by Vincent Ladeuil
Use SmartTCPServer_for_testing instead of SmartTCPServer (broken).
57
    )
6973.7.8 by Jelmer Vernooij
Fix more tests.
58
from ..sixish import (
59
    BytesIO,
60
    int2byte,
61
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
62
from ..transport import (
6670.4.1 by Jelmer Vernooij
Update imports.
63
    http,
64
    local,
65
    memory,
66
    remote,
67
    ssh,
68
    )
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
69
70
4797.85.11 by John Arbash Meinel
Maybe we can just use a regular pipe for testing, rather than spawning a subprocess.
71
def create_file_pipes():
72
    r, w = os.pipe()
4797.85.12 by John Arbash Meinel
Try to test _flush.
73
    # These must be opened without buffering, or we get undefined results
4797.85.11 by John Arbash Meinel
Maybe we can just use a regular pipe for testing, rather than spawning a subprocess.
74
    rf = os.fdopen(r, 'rb', 0)
75
    wf = os.fdopen(w, 'wb', 0)
76
    return rf, wf
77
78
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
79
def portable_socket_pair():
80
    """Return a pair of TCP sockets connected to each other.
81
82
    Unlike socket.socketpair, this should work on Windows.
83
    """
84
    listen_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
85
    listen_sock.bind(('127.0.0.1', 0))
86
    listen_sock.listen(1)
87
    client_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
88
    client_sock.connect(listen_sock.getsockname())
89
    server_sock, addr = listen_sock.accept()
90
    listen_sock.close()
91
    return server_sock, client_sock
92
93
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
94
class BytesIOSSHVendor(object):
95
    """A SSH vendor that uses BytesIO to buffer writes and answer reads."""
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
96
97
    def __init__(self, read_from, write_to):
98
        self.read_from = read_from
99
        self.write_to = write_to
100
        self.calls = []
101
102
    def connect_ssh(self, username, password, host, port, command):
103
        self.calls.append(('connect_ssh', username, password, host, port,
7143.15.2 by Jelmer Vernooij
Run autopep8.
104
                           command))
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
105
        return BytesIOSSHConnection(self)
106
107
108
class FirstRejectedBytesIOSSHVendor(BytesIOSSHVendor):
4797.85.24 by John Arbash Meinel
Show that we try to retry the request if the first attempt fails.
109
    """The first connection will be considered closed.
110
111
    The second connection will succeed normally.
112
    """
113
4797.85.25 by John Arbash Meinel
_send_request can't handle retrying during a read failure
114
    def __init__(self, read_from, write_to, fail_at_write=True):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
115
        super(FirstRejectedBytesIOSSHVendor, self).__init__(read_from,
7143.15.2 by Jelmer Vernooij
Run autopep8.
116
                                                            write_to)
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
117
        self.fail_at_write = fail_at_write
4797.85.24 by John Arbash Meinel
Show that we try to retry the request if the first attempt fails.
118
        self._first = True
119
120
    def connect_ssh(self, username, password, host, port, command):
121
        self.calls.append(('connect_ssh', username, password, host, port,
7143.15.2 by Jelmer Vernooij
Run autopep8.
122
                           command))
4797.85.24 by John Arbash Meinel
Show that we try to retry the request if the first attempt fails.
123
        if self._first:
124
            self._first = False
125
            return ClosedSSHConnection(self)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
126
        return BytesIOSSHConnection(self)
127
128
129
class BytesIOSSHConnection(ssh.SSHConnection):
130
    """A SSH connection that uses BytesIO to buffer writes and answer reads."""
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
131
132
    def __init__(self, vendor):
133
        self.vendor = vendor
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
134
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
135
    def close(self):
136
        self.vendor.calls.append(('close', ))
5284.5.1 by Andrew Bennetts
Use socketpairs (rather than pipes) for SSH subprocesses where possible, and formalise some internal APIs a little more.
137
        self.vendor.read_from.close()
138
        self.vendor.write_to.close()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
139
5284.5.1 by Andrew Bennetts
Use socketpairs (rather than pipes) for SSH subprocesses where possible, and formalise some internal APIs a little more.
140
    def get_sock_or_pipes(self):
141
        return 'pipes', (self.vendor.read_from, self.vendor.write_to)
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
142
143
5050.78.5 by John Arbash Meinel
Merge the 2.1-client-read-reconnect-819604 (bug #819604) to bzr-2.2
144
class ClosedSSHConnection(ssh.SSHConnection):
4797.85.24 by John Arbash Meinel
Show that we try to retry the request if the first attempt fails.
145
    """An SSH connection that just has closed channels."""
146
147
    def __init__(self, vendor):
148
        self.vendor = vendor
149
150
    def close(self):
151
        self.vendor.calls.append(('close', ))
152
5050.78.5 by John Arbash Meinel
Merge the 2.1-client-read-reconnect-819604 (bug #819604) to bzr-2.2
153
    def get_sock_or_pipes(self):
4797.85.24 by John Arbash Meinel
Show that we try to retry the request if the first attempt fails.
154
        # We create matching pipes, and then close the ssh side
155
        bzr_read, ssh_write = create_file_pipes()
4797.85.25 by John Arbash Meinel
_send_request can't handle retrying during a read failure
156
        # We always fail when bzr goes to read
4797.85.24 by John Arbash Meinel
Show that we try to retry the request if the first attempt fails.
157
        ssh_write.close()
4797.85.25 by John Arbash Meinel
_send_request can't handle retrying during a read failure
158
        if self.vendor.fail_at_write:
159
            # If set, we'll also fail when bzr goes to write
160
            ssh_read, bzr_write = create_file_pipes()
161
            ssh_read.close()
162
        else:
163
            bzr_write = self.vendor.write_to
5050.78.5 by John Arbash Meinel
Merge the 2.1-client-read-reconnect-819604 (bug #819604) to bzr-2.2
164
        return 'pipes', (bzr_read, bzr_write)
4797.85.24 by John Arbash Meinel
Show that we try to retry the request if the first attempt fails.
165
166
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
167
class _InvalidHostnameFeature(features.Feature):
3180.1.2 by Andrew Bennetts
Add a test, and also add InvalidHostnameFeature.
168
    """Does 'non_existent.invalid' fail to resolve?
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
169
3180.1.2 by Andrew Bennetts
Add a test, and also add InvalidHostnameFeature.
170
    RFC 2606 states that .invalid is reserved for invalid domain names, and
171
    also underscores are not a valid character in domain names.  Despite this,
172
    it's possible a badly misconfigured name server might decide to always
173
    return an address for any name, so this feature allows us to distinguish a
174
    broken system from a broken test.
175
    """
176
177
    def _probe(self):
178
        try:
179
            socket.gethostbyname('non_existent.invalid')
180
        except socket.gaierror:
181
            # The host name failed to resolve.  Good.
182
            return True
183
        else:
184
            return False
185
186
    def feature_name(self):
187
        return 'invalid hostname'
188
7143.15.2 by Jelmer Vernooij
Run autopep8.
189
3180.1.2 by Andrew Bennetts
Add a test, and also add InvalidHostnameFeature.
190
InvalidHostnameFeature = _InvalidHostnameFeature()
191
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
192
193
class SmartClientMediumTests(tests.TestCase):
194
    """Tests for SmartClientMedium.
195
196
    We should create a test scenario for this: we need a server module that
197
    construct the test-servers (like make_loopsocket_and_medium), and the list
198
    of SmartClientMedium classes to test.
199
    """
200
201
    def make_loopsocket_and_medium(self):
202
        """Create a loopback socket for testing, and a medium aimed at it."""
203
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
204
        sock.bind(('127.0.0.1', 0))
205
        sock.listen(1)
206
        port = sock.getsockname()[1]
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.
207
        client_medium = medium.SmartTCPClientMedium('127.0.0.1', port, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
208
        return sock, client_medium
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
209
210
    def receive_bytes_on_server(self, sock, bytes):
211
        """Accept a connection on sock and read 3 bytes.
212
213
        The bytes are appended to the list bytes.
214
215
        :return: a Thread which is running to do the accept and recv.
216
        """
217
        def _receive_bytes_on_server():
218
            connection, address = sock.accept()
5011.3.11 by Andrew Bennetts
Consolidate changes, try to minimise unnecessary changes and tidy up those that kept.
219
            bytes.append(osutils.recv_all(connection, 3))
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
220
            connection.close()
221
        t = threading.Thread(target=_receive_bytes_on_server)
222
        t.start()
223
        return t
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
224
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
225
    def test_construct_smart_simple_pipes_client_medium(self):
226
        # the SimplePipes client medium takes two pipes:
227
        # readable pipe, writeable pipe.
228
        # Constructing one should just save these and do nothing.
229
        # We test this by passing in None.
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.
230
        client_medium = medium.SmartSimplePipesClientMedium(None, None, None)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
231
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
232
    def test_simple_pipes_client_request_type(self):
233
        # SimplePipesClient should use SmartClientStreamMediumRequest's.
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.
234
        client_medium = medium.SmartSimplePipesClientMedium(None, None, None)
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
235
        request = client_medium.get_request()
236
        self.assertIsInstance(request, medium.SmartClientStreamMediumRequest)
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
237
238
    def test_simple_pipes_client_get_concurrent_requests(self):
239
        # the simple_pipes client does not support pipelined requests:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
240
        # but it does support serial requests: we construct one after
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
241
        # another is finished. This is a smoke test testing the integration
242
        # of the SmartClientStreamMediumRequest and the SmartClientStreamMedium
243
        # classes - as the sibling classes share this logic, they do not have
244
        # explicit tests for this.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
245
        output = BytesIO()
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.
246
        client_medium = medium.SmartSimplePipesClientMedium(
247
            None, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
248
        request = client_medium.get_request()
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
249
        request.finished_writing()
250
        request.finished_reading()
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
251
        request2 = client_medium.get_request()
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
252
        request2.finished_writing()
253
        request2.finished_reading()
254
255
    def test_simple_pipes_client__accept_bytes_writes_to_writable(self):
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
256
        # accept_bytes writes to the writeable pipe.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
257
        output = BytesIO()
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.
258
        client_medium = medium.SmartSimplePipesClientMedium(
259
            None, output, 'base')
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
260
        client_medium._accept_bytes(b'abc')
261
        self.assertEqual(b'abc', output.getvalue())
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
262
4797.85.17 by John Arbash Meinel
Re-enable one of the subprocess tests.
263
    def test_simple_pipes__accept_bytes_subprocess_closed(self):
264
        # It is unfortunate that we have to use Popen for this. However,
265
        # os.pipe() does not behave the same as subprocess.Popen().
266
        # On Windows, if you use os.pipe() and close the write side,
267
        # read.read() hangs. On Linux, read.read() returns the empty string.
268
        p = subprocess.Popen([sys.executable, '-c',
7143.15.2 by Jelmer Vernooij
Run autopep8.
269
                              'import sys\n'
270
                              'sys.stdout.write(sys.stdin.read(4))\n'
271
                              'sys.stdout.close()\n'],
272
                             stdout=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0)
4797.85.17 by John Arbash Meinel
Re-enable one of the subprocess tests.
273
        client_medium = medium.SmartSimplePipesClientMedium(
274
            p.stdout, p.stdin, 'base')
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
275
        client_medium._accept_bytes(b'abc\n')
276
        self.assertEqual(b'abc', client_medium._read_bytes(3))
4797.85.17 by John Arbash Meinel
Re-enable one of the subprocess tests.
277
        p.wait()
278
        # While writing to the underlying pipe,
279
        #   Windows py2.6.6 we get IOError(EINVAL)
280
        #   Lucid py2.6.5, we get IOError(EPIPE)
281
        # In both cases, it should be wrapped to ConnectionReset
282
        self.assertRaises(errors.ConnectionReset,
6855.4.9 by Jelmer Vernooij
More bees.
283
                          client_medium._accept_bytes, b'more')
4797.85.11 by John Arbash Meinel
Maybe we can just use a regular pipe for testing, rather than spawning a subprocess.
284
285
    def test_simple_pipes__accept_bytes_pipe_closed(self):
286
        child_read, client_write = create_file_pipes()
4797.85.9 by John Arbash Meinel
Start writing a test of how subprocess handles writing to a closed connection.
287
        client_medium = medium.SmartSimplePipesClientMedium(
4797.85.11 by John Arbash Meinel
Maybe we can just use a regular pipe for testing, rather than spawning a subprocess.
288
            None, client_write, 'base')
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
289
        client_medium._accept_bytes(b'abc\n')
290
        self.assertEqual(b'abc\n', child_read.read(4))
4797.85.10 by John Arbash Meinel
Wrap the call to .write() to raise ConnectionReset on failure.
291
        # While writing to the underlying pipe,
292
        #   Windows py2.6.6 we get IOError(EINVAL)
293
        #   Lucid py2.6.5, we get IOError(EPIPE)
294
        # In both cases, it should be wrapped to ConnectionReset
4797.85.11 by John Arbash Meinel
Maybe we can just use a regular pipe for testing, rather than spawning a subprocess.
295
        child_read.close()
4797.85.10 by John Arbash Meinel
Wrap the call to .write() to raise ConnectionReset on failure.
296
        self.assertRaises(errors.ConnectionReset,
6855.4.9 by Jelmer Vernooij
More bees.
297
                          client_medium._accept_bytes, b'more')
4797.85.9 by John Arbash Meinel
Start writing a test of how subprocess handles writing to a closed connection.
298
4797.85.12 by John Arbash Meinel
Try to test _flush.
299
    def test_simple_pipes__flush_pipe_closed(self):
300
        child_read, client_write = create_file_pipes()
301
        client_medium = medium.SmartSimplePipesClientMedium(
302
            None, client_write, 'base')
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
303
        client_medium._accept_bytes(b'abc\n')
4797.85.12 by John Arbash Meinel
Try to test _flush.
304
        child_read.close()
305
        # Even though the pipe is closed, flush on the write side seems to be a
306
        # no-op, rather than a failure.
307
        client_medium._flush()
308
309
    def test_simple_pipes__flush_subprocess_closed(self):
310
        p = subprocess.Popen([sys.executable, '-c',
7143.15.2 by Jelmer Vernooij
Run autopep8.
311
                              'import sys\n'
312
                              'sys.stdout.write(sys.stdin.read(4))\n'
313
                              'sys.stdout.close()\n'],
314
                             stdout=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0)
4797.85.14 by John Arbash Meinel
Test how _read_bytes works.
315
        client_medium = medium.SmartSimplePipesClientMedium(
316
            p.stdout, p.stdin, 'base')
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
317
        client_medium._accept_bytes(b'abc\n')
4797.85.14 by John Arbash Meinel
Test how _read_bytes works.
318
        p.wait()
319
        # Even though the child process is dead, flush seems to be a no-op.
320
        client_medium._flush()
321
4797.85.15 by John Arbash Meinel
Do the same test using simple pipes
322
    def test_simple_pipes__read_bytes_pipe_closed(self):
323
        child_read, client_write = create_file_pipes()
324
        client_medium = medium.SmartSimplePipesClientMedium(
325
            child_read, client_write, 'base')
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
326
        client_medium._accept_bytes(b'abc\n')
4797.85.15 by John Arbash Meinel
Do the same test using simple pipes
327
        client_write.close()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
328
        self.assertEqual(b'abc\n', client_medium._read_bytes(4))
329
        self.assertEqual(b'', client_medium._read_bytes(4))
4797.85.15 by John Arbash Meinel
Do the same test using simple pipes
330
4797.85.14 by John Arbash Meinel
Test how _read_bytes works.
331
    def test_simple_pipes__read_bytes_subprocess_closed(self):
332
        p = subprocess.Popen([sys.executable, '-c',
7143.15.2 by Jelmer Vernooij
Run autopep8.
333
                              'import sys\n'
334
                              'if sys.platform == "win32":\n'
335
                              '    import msvcrt, os\n'
336
                              '    msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)\n'
337
                              '    msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)\n'
338
                              'sys.stdout.write(sys.stdin.read(4))\n'
339
                              'sys.stdout.close()\n'],
340
                             stdout=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0)
4797.85.12 by John Arbash Meinel
Try to test _flush.
341
        client_medium = medium.SmartSimplePipesClientMedium(
342
            p.stdout, p.stdin, 'base')
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
343
        client_medium._accept_bytes(b'abc\n')
4797.85.12 by John Arbash Meinel
Try to test _flush.
344
        p.wait()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
345
        self.assertEqual(b'abc\n', client_medium._read_bytes(4))
346
        self.assertEqual(b'', client_medium._read_bytes(4))
4797.85.12 by John Arbash Meinel
Try to test _flush.
347
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
348
    def test_simple_pipes_client_disconnect_does_nothing(self):
349
        # calling disconnect does nothing.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
350
        input = BytesIO()
351
        output = BytesIO()
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.
352
        client_medium = medium.SmartSimplePipesClientMedium(
353
            input, output, 'base')
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
354
        # send some bytes to ensure disconnecting after activity still does not
355
        # close.
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
356
        client_medium._accept_bytes(b'abc')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
357
        client_medium.disconnect()
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
358
        self.assertFalse(input.closed)
359
        self.assertFalse(output.closed)
360
361
    def test_simple_pipes_client_accept_bytes_after_disconnect(self):
362
        # calling disconnect on the client does not alter the pipe that
363
        # accept_bytes writes to.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
364
        input = BytesIO()
365
        output = BytesIO()
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.
366
        client_medium = medium.SmartSimplePipesClientMedium(
367
            input, output, 'base')
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
368
        client_medium._accept_bytes(b'abc')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
369
        client_medium.disconnect()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
370
        client_medium._accept_bytes(b'abc')
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
371
        self.assertFalse(input.closed)
372
        self.assertFalse(output.closed)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
373
        self.assertEqual(b'abcabc', output.getvalue())
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
374
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
375
    def test_simple_pipes_client_ignores_disconnect_when_not_connected(self):
376
        # Doing a disconnect on a new (and thus unconnected) SimplePipes medium
377
        # does nothing.
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.
378
        client_medium = medium.SmartSimplePipesClientMedium(None, None, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
379
        client_medium.disconnect()
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
380
381
    def test_simple_pipes_client_can_always_read(self):
382
        # SmartSimplePipesClientMedium is never disconnected, so read_bytes
383
        # always tries to read from the underlying pipe.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
384
        input = BytesIO(b'abcdef')
7143.15.2 by Jelmer Vernooij
Run autopep8.
385
        client_medium = medium.SmartSimplePipesClientMedium(
386
            input, None, 'base')
6855.4.9 by Jelmer Vernooij
More bees.
387
        self.assertEqual(b'abc', client_medium.read_bytes(3))
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
388
        client_medium.disconnect()
6855.4.9 by Jelmer Vernooij
More bees.
389
        self.assertEqual(b'def', client_medium.read_bytes(3))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
390
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
391
    def test_simple_pipes_client_supports__flush(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
392
        # invoking _flush on a SimplePipesClient should flush the output
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
393
        # pipe. We test this by creating an output pipe that records
394
        # flush calls made to it.
7143.15.2 by Jelmer Vernooij
Run autopep8.
395
        from io import BytesIO  # get regular BytesIO
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
396
        input = BytesIO()
397
        output = BytesIO()
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
398
        flush_calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
399
2018.2.26 by Andrew Bennetts
Changes prompted by j-a-meinel's review.
400
        def logging_flush(): flush_calls.append('flush')
401
        output.flush = logging_flush
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.
402
        client_medium = medium.SmartSimplePipesClientMedium(
403
            input, output, 'base')
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
404
        # this call is here to ensure we only flush once, not on every
405
        # _accept_bytes call.
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
406
        client_medium._accept_bytes(b'abc')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
407
        client_medium._flush()
408
        client_medium.disconnect()
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
409
        self.assertEqual(['flush'], flush_calls)
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
410
411
    def test_construct_smart_ssh_client_medium(self):
412
        # the SSH client medium takes:
413
        # host, port, username, password, vendor
414
        # Constructing one should just save these and do nothing.
415
        # we test this by creating a empty bound socket and constructing
416
        # a medium.
417
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
418
        sock.bind(('127.0.0.1', 0))
2018.2.26 by Andrew Bennetts
Changes prompted by j-a-meinel's review.
419
        unopened_port = sock.getsockname()[1]
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
420
        # having vendor be invalid means that if it tries to connect via the
421
        # vendor it will blow up.
5284.5.1 by Andrew Bennetts
Use socketpairs (rather than pipes) for SSH subprocesses where possible, and formalise some internal APIs a little more.
422
        ssh_params = medium.SSHParams('127.0.0.1', unopened_port, None, None)
423
        client_medium = medium.SmartSSHClientMedium(
424
            'base', ssh_params, "not a vendor")
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
425
        sock.close()
426
427
    def test_ssh_client_connects_on_first_use(self):
428
        # The only thing that initiates a connection from the medium is giving
429
        # it bytes.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
430
        output = BytesIO()
431
        vendor = BytesIOSSHVendor(BytesIO(), output)
5284.5.1 by Andrew Bennetts
Use socketpairs (rather than pipes) for SSH subprocesses where possible, and formalise some internal APIs a little more.
432
        ssh_params = medium.SSHParams(
433
            'a hostname', 'a port', 'a username', 'a password', 'bzr')
434
        client_medium = medium.SmartSSHClientMedium('base', ssh_params, vendor)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
435
        client_medium._accept_bytes(b'abc')
436
        self.assertEqual(b'abc', output.getvalue())
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
437
        self.assertEqual([('connect_ssh', 'a username', 'a password',
7143.15.2 by Jelmer Vernooij
Run autopep8.
438
                           'a hostname', 'a port',
439
                           ['bzr', 'serve', '--inet', '--directory=/', '--allow-writes'])],
440
                         vendor.calls)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
441
1551.18.17 by Aaron Bentley
Introduce bzr_remote_path configuration variable
442
    def test_ssh_client_changes_command_when_bzr_remote_path_passed(self):
443
        # The only thing that initiates a connection from the medium is giving
444
        # it bytes.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
445
        output = BytesIO()
446
        vendor = BytesIOSSHVendor(BytesIO(), output)
5284.5.1 by Andrew Bennetts
Use socketpairs (rather than pipes) for SSH subprocesses where possible, and formalise some internal APIs a little more.
447
        ssh_params = medium.SSHParams(
448
            'a hostname', 'a port', 'a username', 'a password',
449
            bzr_remote_path='fugly')
450
        client_medium = medium.SmartSSHClientMedium('base', ssh_params, vendor)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
451
        client_medium._accept_bytes(b'abc')
452
        self.assertEqual(b'abc', output.getvalue())
1551.18.17 by Aaron Bentley
Introduce bzr_remote_path configuration variable
453
        self.assertEqual([('connect_ssh', 'a username', 'a password',
7143.15.2 by Jelmer Vernooij
Run autopep8.
454
                           'a hostname', 'a port',
455
                           ['fugly', 'serve', '--inet', '--directory=/', '--allow-writes'])],
456
                         vendor.calls)
1551.18.17 by Aaron Bentley
Introduce bzr_remote_path configuration variable
457
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
458
    def test_ssh_client_disconnect_does_so(self):
459
        # calling disconnect should disconnect both the read_from and write_to
460
        # file-like object it from the ssh connection.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
461
        input = BytesIO()
462
        output = BytesIO()
463
        vendor = BytesIOSSHVendor(input, output)
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.
464
        client_medium = medium.SmartSSHClientMedium(
5284.5.1 by Andrew Bennetts
Use socketpairs (rather than pipes) for SSH subprocesses where possible, and formalise some internal APIs a little more.
465
            'base', medium.SSHParams('a hostname'), vendor)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
466
        client_medium._accept_bytes(b'abc')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
467
        client_medium.disconnect()
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
468
        self.assertTrue(input.closed)
469
        self.assertTrue(output.closed)
470
        self.assertEqual([
471
            ('connect_ssh', None, None, 'a hostname', None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
472
             ['bzr', 'serve', '--inet', '--directory=/', '--allow-writes']),
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
473
            ('close', ),
474
            ],
475
            vendor.calls)
476
477
    def test_ssh_client_disconnect_allows_reconnection(self):
478
        # calling disconnect on the client terminates the connection, but should
479
        # not prevent additional connections occuring.
480
        # we test this by initiating a second connection after doing a
481
        # disconnect.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
482
        input = BytesIO()
483
        output = BytesIO()
484
        vendor = BytesIOSSHVendor(input, output)
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.
485
        client_medium = medium.SmartSSHClientMedium(
5284.5.1 by Andrew Bennetts
Use socketpairs (rather than pipes) for SSH subprocesses where possible, and formalise some internal APIs a little more.
486
            'base', medium.SSHParams('a hostname'), vendor)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
487
        client_medium._accept_bytes(b'abc')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
488
        client_medium.disconnect()
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
489
        # the disconnect has closed output, so we need a new output for the
490
        # new connection to write to.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
491
        input2 = BytesIO()
492
        output2 = BytesIO()
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
493
        vendor.read_from = input2
494
        vendor.write_to = output2
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
495
        client_medium._accept_bytes(b'abc')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
496
        client_medium.disconnect()
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
497
        self.assertTrue(input.closed)
498
        self.assertTrue(output.closed)
499
        self.assertTrue(input2.closed)
500
        self.assertTrue(output2.closed)
501
        self.assertEqual([
502
            ('connect_ssh', None, None, 'a hostname', None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
503
             ['bzr', 'serve', '--inet', '--directory=/', '--allow-writes']),
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
504
            ('close', ),
505
            ('connect_ssh', None, None, 'a hostname', None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
506
             ['bzr', 'serve', '--inet', '--directory=/', '--allow-writes']),
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
507
            ('close', ),
508
            ],
509
            vendor.calls)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
510
6242.1.1 by Jelmer Vernooij
Cope with username being None in SmartSSHMedium.__repr__.
511
    def test_ssh_client_repr(self):
512
        client_medium = medium.SmartSSHClientMedium(
513
            'base', medium.SSHParams("example.com", "4242", "username"))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
514
        self.assertEqual(
6242.1.1 by Jelmer Vernooij
Cope with username being None in SmartSSHMedium.__repr__.
515
            "SmartSSHClientMedium(bzr+ssh://username@example.com:4242/)",
516
            repr(client_medium))
517
518
    def test_ssh_client_repr_no_port(self):
519
        client_medium = medium.SmartSSHClientMedium(
520
            'base', medium.SSHParams("example.com", None, "username"))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
521
        self.assertEqual(
6242.1.1 by Jelmer Vernooij
Cope with username being None in SmartSSHMedium.__repr__.
522
            "SmartSSHClientMedium(bzr+ssh://username@example.com/)",
523
            repr(client_medium))
524
525
    def test_ssh_client_repr_no_username(self):
526
        client_medium = medium.SmartSSHClientMedium(
527
            'base', medium.SSHParams("example.com", None, None))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
528
        self.assertEqual(
6242.1.1 by Jelmer Vernooij
Cope with username being None in SmartSSHMedium.__repr__.
529
            "SmartSSHClientMedium(bzr+ssh://example.com/)",
530
            repr(client_medium))
531
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
532
    def test_ssh_client_ignores_disconnect_when_not_connected(self):
533
        # Doing a disconnect on a new (and thus unconnected) SSH medium
2018.2.26 by Andrew Bennetts
Changes prompted by j-a-meinel's review.
534
        # does not fail.  It's ok to disconnect an unconnected medium.
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.
535
        client_medium = medium.SmartSSHClientMedium(
5284.5.1 by Andrew Bennetts
Use socketpairs (rather than pipes) for SSH subprocesses where possible, and formalise some internal APIs a little more.
536
            'base', medium.SSHParams(None))
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
537
        client_medium.disconnect()
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
538
539
    def test_ssh_client_raises_on_read_when_not_connected(self):
540
        # Doing a read on a new (and thus unconnected) SSH medium raises
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
541
        # MediumNotConnected.
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.
542
        client_medium = medium.SmartSSHClientMedium(
5284.5.1 by Andrew Bennetts
Use socketpairs (rather than pipes) for SSH subprocesses where possible, and formalise some internal APIs a little more.
543
            'base', medium.SSHParams(None))
1551.18.17 by Aaron Bentley
Introduce bzr_remote_path configuration variable
544
        self.assertRaises(errors.MediumNotConnected, client_medium.read_bytes,
545
                          0)
546
        self.assertRaises(errors.MediumNotConnected, client_medium.read_bytes,
547
                          1)
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
548
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
549
    def test_ssh_client_supports__flush(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
550
        # invoking _flush on a SSHClientMedium should flush the output
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
551
        # pipe. We test this by creating an output pipe that records
552
        # flush calls made to it.
7143.15.2 by Jelmer Vernooij
Run autopep8.
553
        from io import BytesIO  # get regular BytesIO
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
554
        input = BytesIO()
555
        output = BytesIO()
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
556
        flush_calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
557
2018.2.26 by Andrew Bennetts
Changes prompted by j-a-meinel's review.
558
        def logging_flush(): flush_calls.append('flush')
559
        output.flush = logging_flush
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
560
        vendor = BytesIOSSHVendor(input, output)
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.
561
        client_medium = medium.SmartSSHClientMedium(
5284.5.1 by Andrew Bennetts
Use socketpairs (rather than pipes) for SSH subprocesses where possible, and formalise some internal APIs a little more.
562
            'base', medium.SSHParams('a hostname'), vendor=vendor)
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
563
        # this call is here to ensure we only flush once, not on every
564
        # _accept_bytes call.
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
565
        client_medium._accept_bytes(b'abc')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
566
        client_medium._flush()
567
        client_medium.disconnect()
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
568
        self.assertEqual(['flush'], flush_calls)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
569
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
570
    def test_construct_smart_tcp_client_medium(self):
571
        # the TCP client medium takes a host and a port.  Constructing it won't
572
        # connect to anything.
573
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
574
        sock.bind(('127.0.0.1', 0))
2018.2.26 by Andrew Bennetts
Changes prompted by j-a-meinel's review.
575
        unopened_port = sock.getsockname()[1]
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.
576
        client_medium = medium.SmartTCPClientMedium(
577
            '127.0.0.1', unopened_port, 'base')
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
578
        sock.close()
579
580
    def test_tcp_client_connects_on_first_use(self):
581
        # The only thing that initiates a connection from the medium is giving
582
        # it bytes.
583
        sock, medium = self.make_loopsocket_and_medium()
584
        bytes = []
585
        t = self.receive_bytes_on_server(sock, bytes)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
586
        medium.accept_bytes(b'abc')
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
587
        t.join()
588
        sock.close()
6973.7.8 by Jelmer Vernooij
Fix more tests.
589
        self.assertEqual([b'abc'], bytes)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
590
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
591
    def test_tcp_client_disconnect_does_so(self):
592
        # calling disconnect on the client terminates the connection.
593
        # we test this by forcing a short read during a socket.MSG_WAITALL
2018.2.26 by Andrew Bennetts
Changes prompted by j-a-meinel's review.
594
        # call: write 2 bytes, try to read 3, and then the client disconnects.
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
595
        sock, medium = self.make_loopsocket_and_medium()
596
        bytes = []
597
        t = self.receive_bytes_on_server(sock, bytes)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
598
        medium.accept_bytes(b'ab')
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
599
        medium.disconnect()
600
        t.join()
601
        sock.close()
6973.7.8 by Jelmer Vernooij
Fix more tests.
602
        self.assertEqual([b'ab'], bytes)
2018.2.26 by Andrew Bennetts
Changes prompted by j-a-meinel's review.
603
        # now disconnect again: this should not do anything, if disconnection
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
604
        # really did disconnect.
605
        medium.disconnect()
3236.3.1 by Andrew Bennetts
Fix a bug in SmartServerSocketStreamMedium._get_line, and add some asserts to catch this sort of mistake sooner.
606
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
607
    def test_tcp_client_ignores_disconnect_when_not_connected(self):
608
        # Doing a disconnect on a new (and thus unconnected) TCP medium
2018.2.26 by Andrew Bennetts
Changes prompted by j-a-meinel's review.
609
        # does not fail.  It's ok to disconnect an unconnected medium.
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.
610
        client_medium = medium.SmartTCPClientMedium(None, None, None)
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
611
        client_medium.disconnect()
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
612
613
    def test_tcp_client_raises_on_read_when_not_connected(self):
614
        # Doing a read on a new (and thus unconnected) TCP medium raises
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
615
        # MediumNotConnected.
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.
616
        client_medium = medium.SmartTCPClientMedium(None, None, None)
7143.15.2 by Jelmer Vernooij
Run autopep8.
617
        self.assertRaises(errors.MediumNotConnected,
618
                          client_medium.read_bytes, 0)
619
        self.assertRaises(errors.MediumNotConnected,
620
                          client_medium.read_bytes, 1)
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
621
622
    def test_tcp_client_supports__flush(self):
623
        # invoking _flush on a TCPClientMedium should do something useful.
624
        # RBC 20060922 not sure how to test/tell in this case.
625
        sock, medium = self.make_loopsocket_and_medium()
626
        bytes = []
627
        t = self.receive_bytes_on_server(sock, bytes)
628
        # try with nothing buffered
629
        medium._flush()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
630
        medium._accept_bytes(b'ab')
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
631
        # and with something sent.
632
        medium._flush()
633
        medium.disconnect()
634
        t.join()
635
        sock.close()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
636
        self.assertEqual([b'ab'], bytes)
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
637
        # now disconnect again : this should not do anything, if disconnection
638
        # really did disconnect.
639
        medium.disconnect()
640
3180.1.2 by Andrew Bennetts
Add a test, and also add InvalidHostnameFeature.
641
    def test_tcp_client_host_unknown_connection_error(self):
642
        self.requireFeature(InvalidHostnameFeature)
643
        client_medium = medium.SmartTCPClientMedium(
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.
644
            'non_existent.invalid', 4155, 'base')
3180.1.2 by Andrew Bennetts
Add a test, and also add InvalidHostnameFeature.
645
        self.assertRaises(
646
            errors.ConnectionError, client_medium._ensure_connection)
647
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
648
649
class TestSmartClientStreamMediumRequest(tests.TestCase):
650
    """Tests the for SmartClientStreamMediumRequest.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
651
652
    SmartClientStreamMediumRequest is a helper for the three stream based
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
653
    mediums: TCP, SSH, SimplePipes, so we only test it once, and then test that
654
    those three mediums implement the interface it expects.
655
    """
656
657
    def test_accept_bytes_after_finished_writing_errors(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
658
        # calling accept_bytes after calling finished_writing raises
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
659
        # WritingCompleted to prevent bad assumptions on stream environments
660
        # breaking the needs of message-based environments.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
661
        output = BytesIO()
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.
662
        client_medium = medium.SmartSimplePipesClientMedium(
663
            None, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
664
        request = medium.SmartClientStreamMediumRequest(client_medium)
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
665
        request.finished_writing()
666
        self.assertRaises(errors.WritingCompleted, request.accept_bytes, None)
667
668
    def test_accept_bytes(self):
669
        # accept bytes should invoke _accept_bytes on the stream medium.
670
        # we test this by using the SimplePipes medium - the most trivial one
671
        # and checking that the pipes get the data.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
672
        input = BytesIO()
673
        output = BytesIO()
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.
674
        client_medium = medium.SmartSimplePipesClientMedium(
675
            input, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
676
        request = medium.SmartClientStreamMediumRequest(client_medium)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
677
        request.accept_bytes(b'123')
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
678
        request.finished_writing()
679
        request.finished_reading()
6973.7.8 by Jelmer Vernooij
Fix more tests.
680
        self.assertEqual(b'', input.getvalue())
681
        self.assertEqual(b'123', output.getvalue())
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
682
683
    def test_construct_sets_stream_request(self):
684
        # constructing a SmartClientStreamMediumRequest on a StreamMedium sets
685
        # the current request to the new SmartClientStreamMediumRequest
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
686
        output = BytesIO()
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.
687
        client_medium = medium.SmartSimplePipesClientMedium(
688
            None, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
689
        request = medium.SmartClientStreamMediumRequest(client_medium)
690
        self.assertIs(client_medium._current_request, request)
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
691
692
    def test_construct_while_another_request_active_throws(self):
693
        # constructing a SmartClientStreamMediumRequest on a StreamMedium with
694
        # a non-None _current_request raises TooManyConcurrentRequests.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
695
        output = BytesIO()
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.
696
        client_medium = medium.SmartSimplePipesClientMedium(
697
            None, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
698
        client_medium._current_request = "a"
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
699
        self.assertRaises(errors.TooManyConcurrentRequests,
7143.15.2 by Jelmer Vernooij
Run autopep8.
700
                          medium.SmartClientStreamMediumRequest, client_medium)
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
701
702
    def test_finished_read_clears_current_request(self):
703
        # calling finished_reading clears the current request from the requests
704
        # medium
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
705
        output = BytesIO()
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.
706
        client_medium = medium.SmartSimplePipesClientMedium(
707
            None, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
708
        request = medium.SmartClientStreamMediumRequest(client_medium)
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
709
        request.finished_writing()
710
        request.finished_reading()
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
711
        self.assertEqual(None, client_medium._current_request)
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
712
713
    def test_finished_read_before_finished_write_errors(self):
714
        # calling finished_reading before calling finished_writing triggers a
715
        # WritingNotComplete error.
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.
716
        client_medium = medium.SmartSimplePipesClientMedium(
717
            None, None, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
718
        request = medium.SmartClientStreamMediumRequest(client_medium)
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
719
        self.assertRaises(errors.WritingNotComplete, request.finished_reading)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
720
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
721
    def test_read_bytes(self):
722
        # read bytes should invoke _read_bytes on the stream medium.
723
        # we test this by using the SimplePipes medium - the most trivial one
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
724
        # and checking that the data is supplied. Its possible that a
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
725
        # faulty implementation could poke at the pipe variables them selves,
726
        # but we trust that this will be caught as it will break the integration
727
        # smoke tests.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
728
        input = BytesIO(b'321')
729
        output = BytesIO()
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.
730
        client_medium = medium.SmartSimplePipesClientMedium(
731
            input, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
732
        request = medium.SmartClientStreamMediumRequest(client_medium)
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
733
        request.finished_writing()
6855.4.9 by Jelmer Vernooij
More bees.
734
        self.assertEqual(b'321', request.read_bytes(3))
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
735
        request.finished_reading()
6973.7.8 by Jelmer Vernooij
Fix more tests.
736
        self.assertEqual(b'', input.read())
737
        self.assertEqual(b'', output.getvalue())
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
738
739
    def test_read_bytes_before_finished_write_errors(self):
740
        # calling read_bytes before calling finished_writing triggers a
741
        # WritingNotComplete error because the Smart protocol is designed to be
742
        # compatible with strict message based protocols like HTTP where the
743
        # request cannot be submitted until the writing has completed.
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.
744
        client_medium = medium.SmartSimplePipesClientMedium(None, None, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
745
        request = medium.SmartClientStreamMediumRequest(client_medium)
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
746
        self.assertRaises(errors.WritingNotComplete, request.read_bytes, None)
747
748
    def test_read_bytes_after_finished_reading_errors(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
749
        # calling read_bytes after calling finished_reading raises
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
750
        # ReadingCompleted to prevent bad assumptions on stream environments
751
        # breaking the needs of message-based environments.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
752
        output = BytesIO()
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.
753
        client_medium = medium.SmartSimplePipesClientMedium(
754
            None, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
755
        request = medium.SmartClientStreamMediumRequest(client_medium)
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
756
        request.finished_writing()
757
        request.finished_reading()
758
        self.assertRaises(errors.ReadingCompleted, request.read_bytes, None)
759
4797.85.22 by John Arbash Meinel
Pull out portable_socket_pair.
760
    def test_reset(self):
761
        server_sock, client_sock = portable_socket_pair()
762
        # TODO: Use SmartClientAlreadyConnectedSocketMedium for the versions of
763
        #       bzr where it exists.
764
        client_medium = medium.SmartTCPClientMedium(None, None, None)
765
        client_medium._socket = client_sock
766
        client_medium._connected = True
767
        req = client_medium.get_request()
768
        self.assertRaises(errors.TooManyConcurrentRequests,
7143.15.2 by Jelmer Vernooij
Run autopep8.
769
                          client_medium.get_request)
4797.85.22 by John Arbash Meinel
Pull out portable_socket_pair.
770
        client_medium.reset()
771
        # The stream should be reset, marked as disconnected, though ready for
772
        # us to make a new request
773
        self.assertFalse(client_medium._connected)
774
        self.assertIs(None, client_medium._socket)
775
        try:
776
            self.assertEqual('', client_sock.recv(1))
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
777
        except socket.error as e:
4797.85.22 by John Arbash Meinel
Pull out portable_socket_pair.
778
            if e.errno not in (errno.EBADF,):
779
                raise
780
        req = client_medium.get_request()
781
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
782
5010.2.9 by Vincent Ladeuil
Fix test_smart_transport.py imports.
783
class RemoteTransportTests(test_smart.TestCaseWithSmartMedium):
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
784
785
    def test_plausible_url(self):
6614.1.1 by Vincent Ladeuil
Fix assert_ being deprecated by using assertTrue.
786
        self.assertTrue(self.get_url().startswith('bzr://'))
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
787
788
    def test_probe_transport(self):
789
        t = self.get_transport()
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)
790
        self.assertIsInstance(t, remote.RemoteTransport)
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
791
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
792
    def test_get_medium_from_transport(self):
793
        """Remote transport has a medium always, which it can return."""
794
        t = self.get_transport()
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
795
        client_medium = t.get_smart_medium()
796
        self.assertIsInstance(client_medium, medium.SmartClientMedium)
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
797
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
798
2018.2.18 by Andrew Bennetts
Just close the pipe/socket if the medium catches an error, and add tests for medium exception handling.
799
class ErrorRaisingProtocol(object):
800
801
    def __init__(self, exception):
802
        self.exception = exception
803
804
    def next_read_size(self):
805
        raise self.exception
806
807
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
808
class SampleRequest(object):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
809
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
810
    def __init__(self, expected_bytes):
6973.7.8 by Jelmer Vernooij
Fix more tests.
811
        self.accepted_bytes = b''
2018.2.15 by Andrew Bennetts
Remove SmartServerRequestProtocolOne.finished_reading attribute, replace with next_read_size method.
812
        self._finished_reading = False
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
813
        self.expected_bytes = expected_bytes
6973.7.8 by Jelmer Vernooij
Fix more tests.
814
        self.unused_data = b''
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
815
816
    def accept_bytes(self, bytes):
817
        self.accepted_bytes += bytes
818
        if self.accepted_bytes.startswith(self.expected_bytes):
2018.2.15 by Andrew Bennetts
Remove SmartServerRequestProtocolOne.finished_reading attribute, replace with next_read_size method.
819
            self._finished_reading = True
3245.4.21 by Andrew Bennetts
Remove 'excess_buffer' attribute and another crufty comment.
820
            self.unused_data = self.accepted_bytes[len(self.expected_bytes):]
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
821
2018.2.15 by Andrew Bennetts
Remove SmartServerRequestProtocolOne.finished_reading attribute, replace with next_read_size method.
822
    def next_read_size(self):
823
        if self._finished_reading:
824
            return 0
825
        else:
826
            return 1
827
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
828
829
class TestSmartServerStreamMedium(tests.TestCase):
830
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)
831
    def setUp(self):
832
        super(TestSmartServerStreamMedium, self).setUp()
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
833
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
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)
834
6133.4.26 by John Arbash Meinel
get rid of the default timeout parameters.
835
    def create_pipe_medium(self, to_server, from_server, transport,
836
                           timeout=4.0):
6133.4.27 by John Arbash Meinel
Clean up the code a bit by using a create_pipe_context helper.
837
        """Create a new SmartServerPipeStreamMedium."""
6133.4.26 by John Arbash Meinel
get rid of the default timeout parameters.
838
        return medium.SmartServerPipeStreamMedium(to_server, from_server,
7143.15.2 by Jelmer Vernooij
Run autopep8.
839
                                                  transport, timeout=timeout)
6133.4.26 by John Arbash Meinel
get rid of the default timeout parameters.
840
6133.4.27 by John Arbash Meinel
Clean up the code a bit by using a create_pipe_context helper.
841
    def create_pipe_context(self, to_server_bytes, transport):
842
        """Create a SmartServerSocketStreamMedium.
843
844
        This differes from create_pipe_medium, in that we initialize the
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
845
        request that is sent to the server, and return the BytesIO class that
6133.4.27 by John Arbash Meinel
Clean up the code a bit by using a create_pipe_context helper.
846
        will hold the response.
847
        """
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
848
        to_server = BytesIO(to_server_bytes)
849
        from_server = BytesIO()
6133.4.27 by John Arbash Meinel
Clean up the code a bit by using a create_pipe_context helper.
850
        m = self.create_pipe_medium(to_server, from_server, transport)
851
        return m, from_server
852
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
853
    def create_socket_medium(self, server_sock, transport, timeout=4.0):
6133.4.28 by John Arbash Meinel
Write a similar helper for ServerStreamSocketMedium.
854
        """Initialize a new medium.SmartServerSocketStreamMedium."""
6133.4.26 by John Arbash Meinel
get rid of the default timeout parameters.
855
        return medium.SmartServerSocketStreamMedium(server_sock, transport,
7143.15.2 by Jelmer Vernooij
Run autopep8.
856
                                                    timeout=timeout)
6133.4.26 by John Arbash Meinel
get rid of the default timeout parameters.
857
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
858
    def create_socket_context(self, transport, timeout=4.0):
6133.4.28 by John Arbash Meinel
Write a similar helper for ServerStreamSocketMedium.
859
        """Create a new SmartServerSocketStreamMedium with default context.
860
861
        This will call portable_socket_pair and pass the server side to
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
862
        create_socket_medium along with transport.
6133.4.28 by John Arbash Meinel
Write a similar helper for ServerStreamSocketMedium.
863
        It then returns the client_sock and the server.
864
        """
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
865
        server_sock, client_sock = portable_socket_pair()
866
        server = self.create_socket_medium(server_sock, transport,
6133.4.28 by John Arbash Meinel
Write a similar helper for ServerStreamSocketMedium.
867
                                           timeout=timeout)
868
        return server, client_sock
869
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
870
    def test_smart_query_version(self):
871
        """Feed a canned query version to a server"""
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
872
        # wire-to-wire, using the whole stack
2018.2.27 by Andrew Bennetts
Merge from bzr.dev
873
        transport = local.LocalTransport(urlutils.local_path_to_url('/'))
6973.7.8 by Jelmer Vernooij
Fix more tests.
874
        server, from_server = self.create_pipe_context(b'hello\n', transport)
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
875
        smart_protocol = protocol.SmartServerRequestProtocolOne(transport,
7143.15.2 by Jelmer Vernooij
Run autopep8.
876
                                                                from_server.write)
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
877
        server._serve_one_request(smart_protocol)
6973.7.8 by Jelmer Vernooij
Fix more tests.
878
        self.assertEqual(b'ok\0012\n',
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
879
                         from_server.getvalue())
880
2018.2.31 by Andrew Bennetts
Fix dispatching of smart server requests involving unicode paths.
881
    def test_response_to_canned_get(self):
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
882
        transport = memory.MemoryTransport('memory:///')
6973.7.8 by Jelmer Vernooij
Fix more tests.
883
        transport.put_bytes('testfile', b'contents\nof\nfile\n')
884
        server, from_server = self.create_pipe_context(b'get\001./testfile\n',
7143.15.2 by Jelmer Vernooij
Run autopep8.
885
                                                       transport)
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
886
        smart_protocol = protocol.SmartServerRequestProtocolOne(transport,
7143.15.2 by Jelmer Vernooij
Run autopep8.
887
                                                                from_server.write)
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
888
        server._serve_one_request(smart_protocol)
6973.7.8 by Jelmer Vernooij
Fix more tests.
889
        self.assertEqual(b'ok\n'
890
                         b'17\n'
891
                         b'contents\nof\nfile\n'
892
                         b'done\n',
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
893
                         from_server.getvalue())
894
2018.2.31 by Andrew Bennetts
Fix dispatching of smart server requests involving unicode paths.
895
    def test_response_to_canned_get_of_utf8(self):
896
        # wire-to-wire, using the whole stack, with a UTF-8 filename.
897
        transport = memory.MemoryTransport('memory:///')
898
        utf8_filename = u'testfile\N{INTERROBANG}'.encode('utf-8')
4760.2.4 by Andrew Bennetts
Update test_response_to_canned_get_of_utf8 to reflect reality.
899
        # VFS requests use filenames, not raw UTF-8.
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
900
        hpss_path = urlutils.quote_from_bytes(utf8_filename)
7045.4.30 by Jelmer Vernooij
Fix some more tests.
901
        transport.put_bytes(hpss_path, b'contents\nof\nfile\n')
6133.4.27 by John Arbash Meinel
Clean up the code a bit by using a create_pipe_context helper.
902
        server, from_server = self.create_pipe_context(
7143.15.2 by Jelmer Vernooij
Run autopep8.
903
            b'get\001' + hpss_path.encode('ascii') + b'\n', transport)
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
904
        smart_protocol = protocol.SmartServerRequestProtocolOne(transport,
7143.15.2 by Jelmer Vernooij
Run autopep8.
905
                                                                from_server.write)
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
906
        server._serve_one_request(smart_protocol)
6973.7.8 by Jelmer Vernooij
Fix more tests.
907
        self.assertEqual(b'ok\n'
908
                         b'17\n'
909
                         b'contents\nof\nfile\n'
910
                         b'done\n',
2018.2.31 by Andrew Bennetts
Fix dispatching of smart server requests involving unicode paths.
911
                         from_server.getvalue())
912
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
913
    def test_pipe_like_stream_with_bulk_data(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
914
        sample_request_bytes = b'command\n9\nbulk datadone\n'
6133.4.27 by John Arbash Meinel
Clean up the code a bit by using a create_pipe_context helper.
915
        server, from_server = self.create_pipe_context(
916
            sample_request_bytes, None)
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
917
        sample_protocol = SampleRequest(expected_bytes=sample_request_bytes)
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
918
        server._serve_one_request(sample_protocol)
6973.7.8 by Jelmer Vernooij
Fix more tests.
919
        self.assertEqual(b'', from_server.getvalue())
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
920
        self.assertEqual(sample_request_bytes, sample_protocol.accepted_bytes)
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
921
        self.assertFalse(server.finished)
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
922
923
    def test_socket_stream_with_bulk_data(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
924
        sample_request_bytes = b'command\n9\nbulk datadone\n'
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
925
        server, client_sock = self.create_socket_context(None)
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
926
        sample_protocol = SampleRequest(expected_bytes=sample_request_bytes)
927
        client_sock.sendall(sample_request_bytes)
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
928
        server._serve_one_request(sample_protocol)
6133.5.2 by John Arbash Meinel
Rename _close to _disconnect_client. This makes it more obvious.
929
        server._disconnect_client()
6973.7.8 by Jelmer Vernooij
Fix more tests.
930
        self.assertEqual(b'', client_sock.recv(1))
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
931
        self.assertEqual(sample_request_bytes, sample_protocol.accepted_bytes)
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
932
        self.assertFalse(server.finished)
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
933
934
    def test_pipe_like_stream_shutdown_detection(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
935
        server, _ = self.create_pipe_context(b'', None)
936
        server._serve_one_request(SampleRequest(b'x'))
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
937
        self.assertTrue(server.finished)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
938
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
939
    def test_socket_stream_shutdown_detection(self):
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
940
        server, client_sock = self.create_socket_context(None)
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
941
        client_sock.close()
6973.7.8 by Jelmer Vernooij
Fix more tests.
942
        server._serve_one_request(SampleRequest(b'x'))
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
943
        self.assertTrue(server.finished)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
944
3236.3.1 by Andrew Bennetts
Fix a bug in SmartServerSocketStreamMedium._get_line, and add some asserts to catch this sort of mistake sooner.
945
    def test_socket_stream_incomplete_request(self):
946
        """The medium should still construct the right protocol version even if
947
        the initial read only reads part of the request.
948
949
        Specifically, it should correctly read the protocol version line even
950
        if the partial read doesn't end in a newline.  An older, naive
951
        implementation of _get_line in the server used to have a bug in that
952
        case.
953
        """
6973.7.8 by Jelmer Vernooij
Fix more tests.
954
        incomplete_request_bytes = protocol.REQUEST_VERSION_TWO + b'hel'
955
        rest_of_request_bytes = b'lo\n'
3236.3.1 by Andrew Bennetts
Fix a bug in SmartServerSocketStreamMedium._get_line, and add some asserts to catch this sort of mistake sooner.
956
        expected_response = (
6973.7.8 by Jelmer Vernooij
Fix more tests.
957
            protocol.RESPONSE_VERSION_TWO + b'success\nok\x012\n')
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
958
        server, client_sock = self.create_socket_context(None)
3236.3.1 by Andrew Bennetts
Fix a bug in SmartServerSocketStreamMedium._get_line, and add some asserts to catch this sort of mistake sooner.
959
        client_sock.sendall(incomplete_request_bytes)
960
        server_protocol = server._build_protocol()
961
        client_sock.sendall(rest_of_request_bytes)
962
        server._serve_one_request(server_protocol)
6133.5.2 by John Arbash Meinel
Rename _close to _disconnect_client. This makes it more obvious.
963
        server._disconnect_client()
5011.3.11 by Andrew Bennetts
Consolidate changes, try to minimise unnecessary changes and tidy up those that kept.
964
        self.assertEqual(expected_response, osutils.recv_all(client_sock, 50),
3236.3.1 by Andrew Bennetts
Fix a bug in SmartServerSocketStreamMedium._get_line, and add some asserts to catch this sort of mistake sooner.
965
                         "Not a version 2 response to 'hello' request.")
6973.7.8 by Jelmer Vernooij
Fix more tests.
966
        self.assertEqual(b'', client_sock.recv(1))
3236.3.1 by Andrew Bennetts
Fix a bug in SmartServerSocketStreamMedium._get_line, and add some asserts to catch this sort of mistake sooner.
967
3236.3.2 by Andrew Bennetts
Fix SmartServerPipeStreamMedium._get_line too.
968
    def test_pipe_stream_incomplete_request(self):
969
        """The medium should still construct the right protocol version even if
970
        the initial read only reads part of the request.
971
972
        Specifically, it should correctly read the protocol version line even
973
        if the partial read doesn't end in a newline.  An older, naive
974
        implementation of _get_line in the server used to have a bug in that
975
        case.
976
        """
6973.7.8 by Jelmer Vernooij
Fix more tests.
977
        incomplete_request_bytes = protocol.REQUEST_VERSION_TWO + b'hel'
978
        rest_of_request_bytes = b'lo\n'
3236.3.2 by Andrew Bennetts
Fix SmartServerPipeStreamMedium._get_line too.
979
        expected_response = (
6973.7.8 by Jelmer Vernooij
Fix more tests.
980
            protocol.RESPONSE_VERSION_TWO + b'success\nok\x012\n')
3236.3.2 by Andrew Bennetts
Fix SmartServerPipeStreamMedium._get_line too.
981
        # Make a pair of pipes, to and from the server
982
        to_server, to_server_w = os.pipe()
983
        from_server_r, from_server = os.pipe()
6973.7.8 by Jelmer Vernooij
Fix more tests.
984
        to_server = os.fdopen(to_server, 'rb', 0)
985
        to_server_w = os.fdopen(to_server_w, 'wb', 0)
986
        from_server_r = os.fdopen(from_server_r, 'rb', 0)
987
        from_server = os.fdopen(from_server, 'wb', 0)
6133.4.27 by John Arbash Meinel
Clean up the code a bit by using a create_pipe_context helper.
988
        server = self.create_pipe_medium(to_server, from_server, None)
3236.3.2 by Andrew Bennetts
Fix SmartServerPipeStreamMedium._get_line too.
989
        # Like test_socket_stream_incomplete_request, write an incomplete
990
        # request (that does not end in '\n') and build a protocol from it.
991
        to_server_w.write(incomplete_request_bytes)
992
        server_protocol = server._build_protocol()
993
        # Send the rest of the request, and finish serving it.
994
        to_server_w.write(rest_of_request_bytes)
995
        server._serve_one_request(server_protocol)
996
        to_server_w.close()
997
        from_server.close()
998
        self.assertEqual(expected_response, from_server_r.read(),
999
                         "Not a version 2 response to 'hello' request.")
6973.7.8 by Jelmer Vernooij
Fix more tests.
1000
        self.assertEqual(b'', from_server_r.read(1))
3236.3.2 by Andrew Bennetts
Fix SmartServerPipeStreamMedium._get_line too.
1001
        from_server_r.close()
1002
        to_server.close()
1003
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
1004
    def test_pipe_like_stream_with_two_requests(self):
1005
        # If two requests are read in one go, then two calls to
1006
        # _serve_one_request should still process both of them as if they had
4031.3.1 by Frank Aspell
Fixing various typos
1007
        # been received separately.
6973.7.8 by Jelmer Vernooij
Fix more tests.
1008
        sample_request_bytes = b'command\n'
6133.4.27 by John Arbash Meinel
Clean up the code a bit by using a create_pipe_context helper.
1009
        server, from_server = self.create_pipe_context(
1010
            sample_request_bytes * 2, None)
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
1011
        first_protocol = SampleRequest(expected_bytes=sample_request_bytes)
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
1012
        server._serve_one_request(first_protocol)
2018.2.15 by Andrew Bennetts
Remove SmartServerRequestProtocolOne.finished_reading attribute, replace with next_read_size method.
1013
        self.assertEqual(0, first_protocol.next_read_size())
6973.7.8 by Jelmer Vernooij
Fix more tests.
1014
        self.assertEqual(b'', from_server.getvalue())
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
1015
        self.assertFalse(server.finished)
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
1016
        # Make a new protocol, call _serve_one_request with it to collect the
1017
        # second request.
1018
        second_protocol = SampleRequest(expected_bytes=sample_request_bytes)
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
1019
        server._serve_one_request(second_protocol)
6973.7.8 by Jelmer Vernooij
Fix more tests.
1020
        self.assertEqual(b'', from_server.getvalue())
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
1021
        self.assertEqual(sample_request_bytes, second_protocol.accepted_bytes)
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
1022
        self.assertFalse(server.finished)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1023
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
1024
    def test_socket_stream_with_two_requests(self):
1025
        # If two requests are read in one go, then two calls to
1026
        # _serve_one_request should still process both of them as if they had
4031.3.1 by Frank Aspell
Fixing various typos
1027
        # been received separately.
6973.7.8 by Jelmer Vernooij
Fix more tests.
1028
        sample_request_bytes = b'command\n'
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
1029
        server, client_sock = self.create_socket_context(None)
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
1030
        first_protocol = SampleRequest(expected_bytes=sample_request_bytes)
1031
        # Put two whole requests on the wire.
1032
        client_sock.sendall(sample_request_bytes * 2)
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
1033
        server._serve_one_request(first_protocol)
2018.2.15 by Andrew Bennetts
Remove SmartServerRequestProtocolOne.finished_reading attribute, replace with next_read_size method.
1034
        self.assertEqual(0, first_protocol.next_read_size())
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
1035
        self.assertFalse(server.finished)
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
1036
        # Make a new protocol, call _serve_one_request with it to collect the
1037
        # second request.
1038
        second_protocol = SampleRequest(expected_bytes=sample_request_bytes)
1039
        stream_still_open = server._serve_one_request(second_protocol)
1040
        self.assertEqual(sample_request_bytes, second_protocol.accepted_bytes)
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
1041
        self.assertFalse(server.finished)
6133.5.2 by John Arbash Meinel
Rename _close to _disconnect_client. This makes it more obvious.
1042
        server._disconnect_client()
6973.7.8 by Jelmer Vernooij
Fix more tests.
1043
        self.assertEqual(b'', client_sock.recv(1))
2018.2.18 by Andrew Bennetts
Just close the pipe/socket if the medium catches an error, and add tests for medium exception handling.
1044
1045
    def test_pipe_like_stream_error_handling(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1046
        # Use plain python BytesIO so we can monkey-patch the close method to
2018.2.18 by Andrew Bennetts
Just close the pipe/socket if the medium catches an error, and add tests for medium exception handling.
1047
        # not discard the contents.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1048
        from io import BytesIO
1049
        to_server = BytesIO(b'')
1050
        from_server = BytesIO()
2018.2.18 by Andrew Bennetts
Just close the pipe/socket if the medium catches an error, and add tests for medium exception handling.
1051
        self.closed = False
7143.15.2 by Jelmer Vernooij
Run autopep8.
1052
2018.2.18 by Andrew Bennetts
Just close the pipe/socket if the medium catches an error, and add tests for medium exception handling.
1053
        def close():
1054
            self.closed = True
1055
        from_server.close = close
6133.4.26 by John Arbash Meinel
get rid of the default timeout parameters.
1056
        server = self.create_pipe_medium(
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
1057
            to_server, from_server, None)
2018.2.18 by Andrew Bennetts
Just close the pipe/socket if the medium catches an error, and add tests for medium exception handling.
1058
        fake_protocol = ErrorRaisingProtocol(Exception('boom'))
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
1059
        server._serve_one_request(fake_protocol)
6973.7.8 by Jelmer Vernooij
Fix more tests.
1060
        self.assertEqual(b'', from_server.getvalue())
2018.2.18 by Andrew Bennetts
Just close the pipe/socket if the medium catches an error, and add tests for medium exception handling.
1061
        self.assertTrue(self.closed)
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
1062
        self.assertTrue(server.finished)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1063
2018.2.18 by Andrew Bennetts
Just close the pipe/socket if the medium catches an error, and add tests for medium exception handling.
1064
    def test_socket_stream_error_handling(self):
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
1065
        server, client_sock = self.create_socket_context(None)
2018.2.18 by Andrew Bennetts
Just close the pipe/socket if the medium catches an error, and add tests for medium exception handling.
1066
        fake_protocol = ErrorRaisingProtocol(Exception('boom'))
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
1067
        server._serve_one_request(fake_protocol)
2018.2.23 by Andrew Bennetts
Clean up SmartServerStreamMedium implementations, including removing unnecessary flushes.
1068
        # recv should not block, because the other end of the socket has been
1069
        # closed.
6973.7.8 by Jelmer Vernooij
Fix more tests.
1070
        self.assertEqual(b'', client_sock.recv(1))
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
1071
        self.assertTrue(server.finished)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1072
2018.2.18 by Andrew Bennetts
Just close the pipe/socket if the medium catches an error, and add tests for medium exception handling.
1073
    def test_pipe_like_stream_keyboard_interrupt_handling(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
1074
        server, from_server = self.create_pipe_context(b'', None)
2018.2.18 by Andrew Bennetts
Just close the pipe/socket if the medium catches an error, and add tests for medium exception handling.
1075
        fake_protocol = ErrorRaisingProtocol(KeyboardInterrupt('boom'))
1076
        self.assertRaises(
1077
            KeyboardInterrupt, server._serve_one_request, fake_protocol)
6973.7.8 by Jelmer Vernooij
Fix more tests.
1078
        self.assertEqual(b'', from_server.getvalue())
2018.2.18 by Andrew Bennetts
Just close the pipe/socket if the medium catches an error, and add tests for medium exception handling.
1079
1080
    def test_socket_stream_keyboard_interrupt_handling(self):
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
1081
        server, client_sock = self.create_socket_context(None)
2018.2.18 by Andrew Bennetts
Just close the pipe/socket if the medium catches an error, and add tests for medium exception handling.
1082
        fake_protocol = ErrorRaisingProtocol(KeyboardInterrupt('boom'))
1083
        self.assertRaises(
1084
            KeyboardInterrupt, server._serve_one_request, fake_protocol)
6133.5.2 by John Arbash Meinel
Rename _close to _disconnect_client. This makes it more obvious.
1085
        server._disconnect_client()
6973.7.8 by Jelmer Vernooij
Fix more tests.
1086
        self.assertEqual(b'', client_sock.recv(1))
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
1087
1088
    def build_protocol_pipe_like(self, bytes):
6133.4.27 by John Arbash Meinel
Clean up the code a bit by using a create_pipe_context helper.
1089
        server, _ = self.create_pipe_context(bytes, None)
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
1090
        return server._build_protocol()
1091
1092
    def build_protocol_socket(self, bytes):
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
1093
        server, client_sock = self.create_socket_context(None)
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
1094
        client_sock.sendall(bytes)
1095
        client_sock.close()
1096
        return server._build_protocol()
1097
1098
    def assertProtocolOne(self, server_protocol):
1099
        # Use assertIs because assertIsInstance will wrongly pass
1100
        # SmartServerRequestProtocolTwo (because it subclasses
1101
        # SmartServerRequestProtocolOne).
1102
        self.assertIs(
1103
            type(server_protocol), protocol.SmartServerRequestProtocolOne)
1104
1105
    def assertProtocolTwo(self, server_protocol):
1106
        self.assertIsInstance(
1107
            server_protocol, protocol.SmartServerRequestProtocolTwo)
1108
1109
    def test_pipe_like_build_protocol_empty_bytes(self):
1110
        # Any empty request (i.e. no bytes) is detected as protocol version one.
6973.7.8 by Jelmer Vernooij
Fix more tests.
1111
        server_protocol = self.build_protocol_pipe_like(b'')
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
1112
        self.assertProtocolOne(server_protocol)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1113
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
1114
    def test_socket_like_build_protocol_empty_bytes(self):
1115
        # Any empty request (i.e. no bytes) is detected as protocol version one.
6973.7.8 by Jelmer Vernooij
Fix more tests.
1116
        server_protocol = self.build_protocol_socket(b'')
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
1117
        self.assertProtocolOne(server_protocol)
1118
1119
    def test_pipe_like_build_protocol_non_two(self):
2432.2.7 by Andrew Bennetts
Use less confusing version strings, and define REQUEST_VERSION_TWO/RESPONSE_VERSION_TWO constants for them.
1120
        # A request that doesn't start with "bzr request 2\n" is version one.
6973.7.8 by Jelmer Vernooij
Fix more tests.
1121
        server_protocol = self.build_protocol_pipe_like(b'abc\n')
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
1122
        self.assertProtocolOne(server_protocol)
1123
1124
    def test_socket_build_protocol_non_two(self):
2432.2.7 by Andrew Bennetts
Use less confusing version strings, and define REQUEST_VERSION_TWO/RESPONSE_VERSION_TWO constants for them.
1125
        # A request that doesn't start with "bzr request 2\n" is version one.
6973.7.8 by Jelmer Vernooij
Fix more tests.
1126
        server_protocol = self.build_protocol_socket(b'abc\n')
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
1127
        self.assertProtocolOne(server_protocol)
1128
1129
    def test_pipe_like_build_protocol_two(self):
2432.2.7 by Andrew Bennetts
Use less confusing version strings, and define REQUEST_VERSION_TWO/RESPONSE_VERSION_TWO constants for them.
1130
        # A request that starts with "bzr request 2\n" is version two.
6973.7.8 by Jelmer Vernooij
Fix more tests.
1131
        server_protocol = self.build_protocol_pipe_like(b'bzr request 2\n')
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
1132
        self.assertProtocolTwo(server_protocol)
1133
1134
    def test_socket_build_protocol_two(self):
2432.2.7 by Andrew Bennetts
Use less confusing version strings, and define REQUEST_VERSION_TWO/RESPONSE_VERSION_TWO constants for them.
1135
        # A request that starts with "bzr request 2\n" is version two.
6973.7.8 by Jelmer Vernooij
Fix more tests.
1136
        server_protocol = self.build_protocol_socket(b'bzr request 2\n')
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
1137
        self.assertProtocolTwo(server_protocol)
3245.4.41 by Andrew Bennetts
Add TestGetProtocolFactoryForBytes.
1138
6133.4.43 by John Arbash Meinel
Initial implementation of SIGHUP for bzr serve. bug #795025.
1139
    def test__build_protocol_returns_if_stopping(self):
1140
        # _build_protocol should notice that we are stopping, and return
1141
        # without waiting for bytes from the client.
6133.4.49 by John Arbash Meinel
merge-up drop-idle
1142
        server, client_sock = self.create_socket_context(None)
6133.4.44 by John Arbash Meinel
Move the code into bzrlib.smart.signals.
1143
        server._stop_gracefully()
6133.4.43 by John Arbash Meinel
Initial implementation of SIGHUP for bzr serve. bug #795025.
1144
        self.assertIs(None, server._build_protocol())
1145
6133.4.16 by John Arbash Meinel
Add some tests to make sure the timeout parameter gets propagated upwards correctly.
1146
    def test_socket_set_timeout(self):
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
1147
        server, _ = self.create_socket_context(None, timeout=1.23)
6133.4.16 by John Arbash Meinel
Add some tests to make sure the timeout parameter gets propagated upwards correctly.
1148
        self.assertEqual(1.23, server._client_timeout)
1149
1150
    def test_pipe_set_timeout(self):
6133.4.26 by John Arbash Meinel
get rid of the default timeout parameters.
1151
        server = self.create_pipe_medium(None, None, None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1152
                                         timeout=1.23)
6133.4.16 by John Arbash Meinel
Add some tests to make sure the timeout parameter gets propagated upwards correctly.
1153
        self.assertEqual(1.23, server._client_timeout)
1154
6133.4.1 by John Arbash Meinel
Add a _wait_for_bytes_with_timeout helper function.
1155
    def test_socket_wait_for_bytes_with_timeout_with_data(self):
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
1156
        server, client_sock = self.create_socket_context(None)
6973.7.8 by Jelmer Vernooij
Fix more tests.
1157
        client_sock.sendall(b'data\n')
6133.4.1 by John Arbash Meinel
Add a _wait_for_bytes_with_timeout helper function.
1158
        # This should not block or consume any actual content
6133.4.2 by John Arbash Meinel
Implement waiting for Pipe mediums, including handling ones
1159
        self.assertFalse(server._wait_for_bytes_with_timeout(0.1))
6133.4.1 by John Arbash Meinel
Add a _wait_for_bytes_with_timeout helper function.
1160
        data = server.read_bytes(5)
6855.4.9 by Jelmer Vernooij
More bees.
1161
        self.assertEqual(b'data\n', data)
6133.4.1 by John Arbash Meinel
Add a _wait_for_bytes_with_timeout helper function.
1162
1163
    def test_socket_wait_for_bytes_with_timeout_no_data(self):
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
1164
        server, client_sock = self.create_socket_context(None)
6133.4.1 by John Arbash Meinel
Add a _wait_for_bytes_with_timeout helper function.
1165
        # This should timeout quickly, reporting that there wasn't any data
6133.4.42 by John Arbash Meinel
Change the code to just raise ConnectionTimeout.
1166
        self.assertRaises(errors.ConnectionTimeout,
1167
                          server._wait_for_bytes_with_timeout, 0.01)
6133.4.1 by John Arbash Meinel
Add a _wait_for_bytes_with_timeout helper function.
1168
        client_sock.close()
1169
        data = server.read_bytes(1)
6855.4.9 by Jelmer Vernooij
More bees.
1170
        self.assertEqual(b'', data)
6133.4.1 by John Arbash Meinel
Add a _wait_for_bytes_with_timeout helper function.
1171
6133.4.6 by John Arbash Meinel
Some testing shows that if the client closes its socket, the server immediately returns.
1172
    def test_socket_wait_for_bytes_with_timeout_closed(self):
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
1173
        server, client_sock = self.create_socket_context(None)
6133.4.6 by John Arbash Meinel
Some testing shows that if the client closes its socket, the server immediately returns.
1174
        # With the socket closed, this should return right away.
1175
        # It seems select.select() returns that you *can* read on the socket,
1176
        # even though it closed. Presumably as a way to tell it is closed?
1177
        # Testing shows that without sock.close() this times-out failing the
1178
        # test, but with it, it returns False immediately.
1179
        client_sock.close()
1180
        self.assertFalse(server._wait_for_bytes_with_timeout(10))
1181
        data = server.read_bytes(1)
6855.4.9 by Jelmer Vernooij
More bees.
1182
        self.assertEqual(b'', data)
6133.4.6 by John Arbash Meinel
Some testing shows that if the client closes its socket, the server immediately returns.
1183
6133.4.43 by John Arbash Meinel
Initial implementation of SIGHUP for bzr serve. bug #795025.
1184
    def test_socket_wait_for_bytes_with_shutdown(self):
6133.4.49 by John Arbash Meinel
merge-up drop-idle
1185
        server, client_sock = self.create_socket_context(None)
6133.4.43 by John Arbash Meinel
Initial implementation of SIGHUP for bzr serve. bug #795025.
1186
        t = time.time()
1187
        # Override the _timer functionality, so that time never increments,
1188
        # this way, we can be sure we stopped because of the flag, and not
1189
        # because of a timeout, etc.
1190
        server._timer = lambda: t
1191
        server._client_poll_timeout = 0.1
6133.4.44 by John Arbash Meinel
Move the code into bzrlib.smart.signals.
1192
        server._stop_gracefully()
6133.4.43 by John Arbash Meinel
Initial implementation of SIGHUP for bzr serve. bug #795025.
1193
        server._wait_for_bytes_with_timeout(1.0)
1194
6133.4.11 by John Arbash Meinel
It turns out that if we don't explicitly close the socket, it hangs around somewhere.
1195
    def test_socket_serve_timeout_closes_socket(self):
6133.5.1 by John Arbash Meinel
Change the name from 'create_stream_context' to 'create_socket_context'.
1196
        server, client_sock = self.create_socket_context(None, timeout=0.1)
6133.4.11 by John Arbash Meinel
It turns out that if we don't explicitly close the socket, it hangs around somewhere.
1197
        # This should timeout quickly, and then close the connection so that
1198
        # client_sock recv doesn't block.
6133.4.13 by John Arbash Meinel
I updated the code so that ConnectionTimeout isn't raised out of serve,
1199
        server.serve()
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1200
        self.assertEqual(b'', client_sock.recv(1))
6133.4.11 by John Arbash Meinel
It turns out that if we don't explicitly close the socket, it hangs around somewhere.
1201
6133.4.2 by John Arbash Meinel
Implement waiting for Pipe mediums, including handling ones
1202
    def test_pipe_wait_for_bytes_with_timeout_with_data(self):
1203
        # We intentionally use a real pipe here, so that we can 'select' on it.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1204
        # You can't select() on a BytesIO
6133.4.2 by John Arbash Meinel
Implement waiting for Pipe mediums, including handling ones
1205
        (r_server, w_client) = os.pipe()
6133.4.3 by John Arbash Meinel
use some 'with' statements for better cleanups.
1206
        self.addCleanup(os.close, w_client)
1207
        with os.fdopen(r_server, 'rb') as rf_server:
6133.4.26 by John Arbash Meinel
get rid of the default timeout parameters.
1208
            server = self.create_pipe_medium(
6133.4.3 by John Arbash Meinel
use some 'with' statements for better cleanups.
1209
                rf_server, None, None)
6855.4.9 by Jelmer Vernooij
More bees.
1210
            os.write(w_client, b'data\n')
6133.4.3 by John Arbash Meinel
use some 'with' statements for better cleanups.
1211
            # This should not block or consume any actual content
6133.4.42 by John Arbash Meinel
Change the code to just raise ConnectionTimeout.
1212
            server._wait_for_bytes_with_timeout(0.1)
6133.4.3 by John Arbash Meinel
use some 'with' statements for better cleanups.
1213
            data = server.read_bytes(5)
6855.4.9 by Jelmer Vernooij
More bees.
1214
            self.assertEqual(b'data\n', data)
6133.4.2 by John Arbash Meinel
Implement waiting for Pipe mediums, including handling ones
1215
1216
    def test_pipe_wait_for_bytes_with_timeout_no_data(self):
1217
        # We intentionally use a real pipe here, so that we can 'select' on it.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1218
        # You can't select() on a BytesIO
6133.4.2 by John Arbash Meinel
Implement waiting for Pipe mediums, including handling ones
1219
        (r_server, w_client) = os.pipe()
6133.4.3 by John Arbash Meinel
use some 'with' statements for better cleanups.
1220
        # We can't add an os.close cleanup here, because we need to control
1221
        # when the file handle gets closed ourselves.
1222
        with os.fdopen(r_server, 'rb') as rf_server:
6133.4.26 by John Arbash Meinel
get rid of the default timeout parameters.
1223
            server = self.create_pipe_medium(
6133.4.3 by John Arbash Meinel
use some 'with' statements for better cleanups.
1224
                rf_server, None, None)
6133.4.10 by John Arbash Meinel
Handle the win32 not-a-socket errors. I think this is ~ready. At least for feedback.
1225
            if sys.platform == 'win32':
1226
                # Windows cannot select() on a pipe, so we just always return
6133.4.42 by John Arbash Meinel
Change the code to just raise ConnectionTimeout.
1227
                server._wait_for_bytes_with_timeout(0.01)
6133.4.10 by John Arbash Meinel
Handle the win32 not-a-socket errors. I think this is ~ready. At least for feedback.
1228
            else:
6133.4.42 by John Arbash Meinel
Change the code to just raise ConnectionTimeout.
1229
                self.assertRaises(errors.ConnectionTimeout,
1230
                                  server._wait_for_bytes_with_timeout, 0.01)
6133.4.3 by John Arbash Meinel
use some 'with' statements for better cleanups.
1231
            os.close(w_client)
1232
            data = server.read_bytes(5)
6855.4.9 by Jelmer Vernooij
More bees.
1233
            self.assertEqual(b'', data)
6133.4.2 by John Arbash Meinel
Implement waiting for Pipe mediums, including handling ones
1234
1235
    def test_pipe_wait_for_bytes_no_fileno(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
1236
        server, _ = self.create_pipe_context(b'', None)
6133.4.2 by John Arbash Meinel
Implement waiting for Pipe mediums, including handling ones
1237
        # Our file doesn't support polling, so we should always just return
1238
        # 'you have data to consume.
6133.4.42 by John Arbash Meinel
Change the code to just raise ConnectionTimeout.
1239
        server._wait_for_bytes_with_timeout(0.01)
6133.4.2 by John Arbash Meinel
Implement waiting for Pipe mediums, including handling ones
1240
3245.4.41 by Andrew Bennetts
Add TestGetProtocolFactoryForBytes.
1241
1242
class TestGetProtocolFactoryForBytes(tests.TestCase):
1243
    """_get_protocol_factory_for_bytes identifies the protocol factory a server
1244
    should use to decode a given request.  Any bytes not part of the version
1245
    marker string (and thus part of the actual request) are returned alongside
1246
    the protocol factory.
1247
    """
1248
1249
    def test_version_three(self):
1250
        result = medium._get_protocol_factory_for_bytes(
6855.3.1 by Jelmer Vernooij
Several more fixes.
1251
            b'bzr message 3 (bzr 1.6)\nextra bytes')
3245.4.41 by Andrew Bennetts
Add TestGetProtocolFactoryForBytes.
1252
        protocol_factory, remainder = result
1253
        self.assertEqual(
1254
            protocol.build_server_protocol_three, protocol_factory)
6855.3.1 by Jelmer Vernooij
Several more fixes.
1255
        self.assertEqual(b'extra bytes', remainder)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1256
3245.4.41 by Andrew Bennetts
Add TestGetProtocolFactoryForBytes.
1257
    def test_version_two(self):
1258
        result = medium._get_protocol_factory_for_bytes(
6855.3.1 by Jelmer Vernooij
Several more fixes.
1259
            b'bzr request 2\nextra bytes')
3245.4.41 by Andrew Bennetts
Add TestGetProtocolFactoryForBytes.
1260
        protocol_factory, remainder = result
1261
        self.assertEqual(
1262
            protocol.SmartServerRequestProtocolTwo, protocol_factory)
6855.3.1 by Jelmer Vernooij
Several more fixes.
1263
        self.assertEqual(b'extra bytes', remainder)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1264
3245.4.41 by Andrew Bennetts
Add TestGetProtocolFactoryForBytes.
1265
    def test_version_one(self):
1266
        """Version one requests have no version markers."""
6855.3.1 by Jelmer Vernooij
Several more fixes.
1267
        result = medium._get_protocol_factory_for_bytes(b'anything\n')
3245.4.41 by Andrew Bennetts
Add TestGetProtocolFactoryForBytes.
1268
        protocol_factory, remainder = result
1269
        self.assertEqual(
1270
            protocol.SmartServerRequestProtocolOne, protocol_factory)
6855.3.1 by Jelmer Vernooij
Several more fixes.
1271
        self.assertEqual(b'anything\n', remainder)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1272
2018.2.20 by Andrew Bennetts
Tidy up _serve_one_request.
1273
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
1274
class TestSmartTCPServer(tests.TestCase):
1275
6133.4.53 by John Arbash Meinel
Refactor the code a bit. Now we can ensure that the active loop
1276
    def make_server(self):
1277
        """Create a SmartTCPServer that we can exercise.
1278
1279
        Note: we don't use SmartTCPServer_for_testing because the testing
1280
        version overrides lots of functionality like 'serve', and we want to
1281
        test the raw service.
1282
1283
        This will start the server in another thread, and wait for it to
1284
        indicate it has finished starting up.
1285
1286
        :return: (server, server_thread)
1287
        """
1288
        t = _mod_transport.get_transport_from_url('memory:///')
1289
        server = _mod_server.SmartTCPServer(t, client_timeout=4.0)
1290
        server._ACCEPT_TIMEOUT = 0.1
1291
        # We don't use 'localhost' because that might be an IPv6 address.
1292
        server.start_server('127.0.0.1', 0)
1293
        server_thread = threading.Thread(target=server.serve,
1294
                                         args=(self.id(),))
1295
        server_thread.start()
1296
        # Ensure this gets called at some point
1297
        self.addCleanup(server._stop_gracefully)
1298
        server._started.wait()
1299
        return server, server_thread
1300
1301
    def ensure_client_disconnected(self, client_sock):
1302
        """Ensure that a socket is closed, discarding all errors."""
1303
        try:
1304
            client_sock.close()
1305
        except Exception:
1306
            pass
1307
1308
    def connect_to_server(self, server):
1309
        """Create a client socket that can talk to the server."""
1310
        client_sock = socket.socket()
1311
        server_info = server._server_socket.getsockname()
1312
        client_sock.connect(server_info)
1313
        self.addCleanup(self.ensure_client_disconnected, client_sock)
1314
        return client_sock
1315
1316
    def connect_to_server_and_hangup(self, server):
1317
        """Connect to the server, and then hang up.
1318
        That way it doesn't sit waiting for 'accept()' to timeout.
1319
        """
6133.4.57 by John Arbash Meinel
If someone does manage to connect while we are shutting down, close the connection.
1320
        # If the server has already signaled that the socket is closed, we
1321
        # don't need to try to connect to it. Not being set, though, the server
1322
        # might still close the socket while we try to connect to it. So we
1323
        # still have to catch the exception.
1324
        if server._stopped.isSet():
1325
            return
1326
        try:
1327
            client_sock = self.connect_to_server(server)
1328
            client_sock.close()
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
1329
        except socket.error as e:
6133.4.57 by John Arbash Meinel
If someone does manage to connect while we are shutting down, close the connection.
1330
            # If the server has hung up already, that is fine.
1331
            pass
6133.4.53 by John Arbash Meinel
Refactor the code a bit. Now we can ensure that the active loop
1332
1333
    def say_hello(self, client_sock):
1334
        """Send the 'hello' smart RPC, and expect the response."""
6973.7.8 by Jelmer Vernooij
Fix more tests.
1335
        client_sock.send(b'hello\n')
1336
        self.assertEqual(b'ok\x012\n', client_sock.recv(5))
6133.4.53 by John Arbash Meinel
Refactor the code a bit. Now we can ensure that the active loop
1337
1338
    def shutdown_server_cleanly(self, server, server_thread):
1339
        server._stop_gracefully()
6133.4.57 by John Arbash Meinel
If someone does manage to connect while we are shutting down, close the connection.
1340
        self.connect_to_server_and_hangup(server)
6133.4.53 by John Arbash Meinel
Refactor the code a bit. Now we can ensure that the active loop
1341
        server._stopped.wait()
6133.4.55 by John Arbash Meinel
Now we've implemented the basic structure.
1342
        server._fully_stopped.wait()
6133.4.53 by John Arbash Meinel
Refactor the code a bit. Now we can ensure that the active loop
1343
        server_thread.join()
1344
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1345
    def test_get_error_unexpected(self):
1346
        """Error reported by server with no specific representation"""
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
1347
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1348
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1349
        class FlakyTransport(object):
2376.3.3 by Robert Collins
Fix all smart_transport tests.
1350
            base = 'a_url'
7143.15.2 by Jelmer Vernooij
Run autopep8.
1351
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
1352
            def external_url(self):
1353
                return self.base
7143.15.2 by Jelmer Vernooij
Run autopep8.
1354
5247.3.47 by Vincent Ladeuil
Use SmartTCPServer_for_testing for TestSmartTCPServer.test_get_error_unexpected.
1355
            def get(self, path):
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1356
                raise Exception("some random exception from inside server")
5247.3.47 by Vincent Ladeuil
Use SmartTCPServer_for_testing for TestSmartTCPServer.test_get_error_unexpected.
1357
1358
        class FlakyServer(test_server.SmartTCPServer_for_testing):
1359
            def get_backing_transport(self, backing_transport_server):
1360
                return FlakyTransport()
1361
1362
        smart_server = FlakyServer()
1363
        smart_server.start_server()
1364
        self.addCleanup(smart_server.stop_server)
1365
        t = remote.RemoteTCPTransport(smart_server.get_url())
1366
        self.addCleanup(t.disconnect)
1367
        err = self.assertRaises(errors.UnknownErrorFromSmartServer,
1368
                                t.get, 'something')
1369
        self.assertContainsRe(str(err), 'some random exception')
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1370
6133.4.19 by John Arbash Meinel
Make SmartTCPServer take a client_timeout parameter, which it passes down to the Medium.
1371
    def test_propagates_timeout(self):
1372
        server = _mod_server.SmartTCPServer(None, client_timeout=1.23)
6133.4.62 by John Arbash Meinel
Add a nicer repr for shutting down.
1373
        server_sock, client_sock = portable_socket_pair()
1374
        handler = server._make_handler(server_sock)
6133.4.19 by John Arbash Meinel
Make SmartTCPServer take a client_timeout parameter, which it passes down to the Medium.
1375
        self.assertEqual(1.23, handler._client_timeout)
1376
6133.4.50 by John Arbash Meinel
Track the active connections, add a polling function to notice when they are stopped.
1377
    def test_serve_conn_tracks_connections(self):
1378
        server = _mod_server.SmartTCPServer(None, client_timeout=4.0)
1379
        server_sock, client_sock = portable_socket_pair()
1380
        server.serve_conn(server_sock, '-%s' % (self.id(),))
1381
        self.assertEqual(1, len(server._active_connections))
1382
        # We still want to talk on the connection. Polling should indicate it
1383
        # is still active.
1384
        server._poll_active_connections()
1385
        self.assertEqual(1, len(server._active_connections))
1386
        # Closing the socket will end the active thread, and polling will
1387
        # notice and remove it from the active set.
1388
        client_sock.close()
1389
        server._poll_active_connections(0.1)
1390
        self.assertEqual(0, len(server._active_connections))
1391
6133.4.52 by John Arbash Meinel
Implement basic testing that the smart server tracks client connections,
1392
    def test_serve_closes_out_finished_connections(self):
6133.4.53 by John Arbash Meinel
Refactor the code a bit. Now we can ensure that the active loop
1393
        server, server_thread = self.make_server()
1394
        # The server is started, connect to it.
1395
        client_sock = self.connect_to_server(server)
1396
        # We send and receive on the connection, so that we know the
1397
        # server-side has seen the connect, and started handling the
1398
        # results.
1399
        self.say_hello(client_sock)
1400
        self.assertEqual(1, len(server._active_connections))
1401
        # Grab a handle to the thread that is processing our request
6133.4.55 by John Arbash Meinel
Now we've implemented the basic structure.
1402
        _, server_side_thread = server._active_connections[0]
6133.4.53 by John Arbash Meinel
Refactor the code a bit. Now we can ensure that the active loop
1403
        # Close the connection, ask the server to stop, and wait for the
1404
        # server to stop, as well as the thread that was servicing the
1405
        # client request.
1406
        client_sock.close()
1407
        # Wait for the server-side request thread to notice we are closed.
1408
        server_side_thread.join()
1409
        # Stop the server, it should notice the connection has finished.
1410
        self.shutdown_server_cleanly(server, server_thread)
1411
        # The server should have noticed that all clients are gone before
1412
        # exiting.
6133.4.52 by John Arbash Meinel
Implement basic testing that the smart server tracks client connections,
1413
        self.assertEqual(0, len(server._active_connections))
1414
6133.4.53 by John Arbash Meinel
Refactor the code a bit. Now we can ensure that the active loop
1415
    def test_serve_reaps_finished_connections(self):
1416
        server, server_thread = self.make_server()
1417
        client_sock1 = self.connect_to_server(server)
1418
        # We send and receive on the connection, so that we know the
1419
        # server-side has seen the connect, and started handling the
1420
        # results.
1421
        self.say_hello(client_sock1)
6133.4.56 by John Arbash Meinel
Change the ordering a bit.
1422
        server_handler1, server_side_thread1 = server._active_connections[0]
6133.4.53 by John Arbash Meinel
Refactor the code a bit. Now we can ensure that the active loop
1423
        client_sock1.close()
1424
        server_side_thread1.join()
6133.4.54 by John Arbash Meinel
Teach the SmartTCPServer to wait gracefully for the client threads to exit.
1425
        # By waiting until the first connection is fully done, the server
1426
        # should notice after another connection that the first has finished.
6133.4.53 by John Arbash Meinel
Refactor the code a bit. Now we can ensure that the active loop
1427
        client_sock2 = self.connect_to_server(server)
1428
        self.say_hello(client_sock2)
6133.4.56 by John Arbash Meinel
Change the ordering a bit.
1429
        server_handler2, server_side_thread2 = server._active_connections[-1]
1430
        # There is a race condition. We know that client_sock2 has been
1431
        # registered, but not that _poll_active_connections has been called. We
1432
        # know that it will be called before the server will accept a new
1433
        # connection, however. So connect one more time, and assert that we
1434
        # either have 1 or 2 active connections (never 3), and that the 'first'
1435
        # connection is not connection 1
1436
        client_sock3 = self.connect_to_server(server)
1437
        self.say_hello(client_sock3)
1438
        # Copy the list, so we don't have it mutating behind our back
1439
        conns = list(server._active_connections)
1440
        self.assertEqual(2, len(conns))
1441
        self.assertNotEqual((server_handler1, server_side_thread1), conns[0])
1442
        self.assertEqual((server_handler2, server_side_thread2), conns[0])
6133.4.53 by John Arbash Meinel
Refactor the code a bit. Now we can ensure that the active loop
1443
        client_sock2.close()
6133.4.56 by John Arbash Meinel
Change the ordering a bit.
1444
        client_sock3.close()
6133.4.53 by John Arbash Meinel
Refactor the code a bit. Now we can ensure that the active loop
1445
        self.shutdown_server_cleanly(server, server_thread)
1446
6133.4.54 by John Arbash Meinel
Teach the SmartTCPServer to wait gracefully for the client threads to exit.
1447
    def test_graceful_shutdown_waits_for_clients_to_stop(self):
1448
        server, server_thread = self.make_server()
6133.4.58 by John Arbash Meinel
Fix the race condition.
1449
        # We need something big enough that it won't fit in a single recv. So
1450
        # the server thread gets blocked writing content to the client until we
1451
        # finish reading on the client.
1452
        server.backing_transport.put_bytes('bigfile',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1453
                                           b'a' * 1024 * 1024)
6133.4.54 by John Arbash Meinel
Teach the SmartTCPServer to wait gracefully for the client threads to exit.
1454
        client_sock = self.connect_to_server(server)
1455
        self.say_hello(client_sock)
6133.4.55 by John Arbash Meinel
Now we've implemented the basic structure.
1456
        _, server_side_thread = server._active_connections[0]
6133.4.58 by John Arbash Meinel
Fix the race condition.
1457
        # Start the RPC, but don't finish reading the response
1458
        client_medium = medium.SmartClientAlreadyConnectedSocketMedium(
1459
            'base', client_sock)
1460
        client_client = client._SmartClient(client_medium)
6973.7.8 by Jelmer Vernooij
Fix more tests.
1461
        resp, response_handler = client_client.call_expecting_body(b'get',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1462
                                                                   b'bigfile')
6973.7.8 by Jelmer Vernooij
Fix more tests.
1463
        self.assertEqual((b'ok',), resp)
6133.4.54 by John Arbash Meinel
Teach the SmartTCPServer to wait gracefully for the client threads to exit.
1464
        # Ask the server to stop gracefully, and wait for it.
1465
        server._stop_gracefully()
1466
        self.connect_to_server_and_hangup(server)
1467
        server._stopped.wait()
1468
        # It should not be accepting another connection.
1469
        self.assertRaises(socket.error, self.connect_to_server, server)
6133.4.58 by John Arbash Meinel
Fix the race condition.
1470
        response_handler.read_body_bytes()
6133.4.54 by John Arbash Meinel
Teach the SmartTCPServer to wait gracefully for the client threads to exit.
1471
        client_sock.close()
1472
        server_side_thread.join()
1473
        server_thread.join()
1474
        self.assertTrue(server._fully_stopped.isSet())
1475
        log = self.get_log()
6133.4.55 by John Arbash Meinel
Now we've implemented the basic structure.
1476
        self.assertThat(log, DocTestMatches("""\
1477
    INFO  Requested to stop gracefully
6133.4.62 by John Arbash Meinel
Add a nicer repr for shutting down.
1478
... Stopping SmartServerSocketStreamMedium(client=('127.0.0.1', ...
7143.15.2 by Jelmer Vernooij
Run autopep8.
1479
""", flags=doctest.ELLIPSIS | doctest.REPORT_UDIFF))
6133.4.55 by John Arbash Meinel
Now we've implemented the basic structure.
1480
1481
    def test_stop_gracefully_tells_handlers_to_stop(self):
1482
        server, server_thread = self.make_server()
1483
        client_sock = self.connect_to_server(server)
1484
        self.say_hello(client_sock)
1485
        server_handler, server_side_thread = server._active_connections[0]
1486
        self.assertFalse(server_handler.finished)
1487
        server._stop_gracefully()
1488
        self.assertTrue(server_handler.finished)
1489
        client_sock.close()
1490
        self.connect_to_server_and_hangup(server)
1491
        server_thread.join()
6133.4.54 by John Arbash Meinel
Teach the SmartTCPServer to wait gracefully for the client threads to exit.
1492
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1493
1494
class SmartTCPTests(tests.TestCase):
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1495
    """Tests for connection/end to end behaviour using the TCP server.
1496
5247.3.48 by Vincent Ladeuil
Fixed as per lifeless suggestion.
1497
    All of these tests are run with a server running in another thread serving
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1498
    a MemoryTransport, and a connection to it already open.
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1499
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
1500
    the server is obtained by calling self.start_server(readonly=False).
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1501
    """
1502
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
1503
    def start_server(self, readonly=False, backing_transport=None):
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1504
        """Setup the server.
1505
1506
        :param readonly: Create a readonly server.
1507
        """
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.
1508
        # NB: Tests using this fall into two categories: tests of the server,
1509
        # tests wanting a server. The latter should be updated to use
1510
        # self.vfs_transport_factory etc.
5247.3.48 by Vincent Ladeuil
Fixed as per lifeless suggestion.
1511
        if backing_transport is None:
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
1512
            mem_server = memory.MemoryServer()
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
1513
            mem_server.start_server()
4934.3.1 by Martin Pool
Rename Server.tearDown to .stop_server
1514
            self.addCleanup(mem_server.stop_server)
4634.47.10 by Andrew Bennetts
Merge bzr.dev; fix test isolation glitch.
1515
            self.permit_url(mem_server.get_url())
6138.1.1 by John Arbash Meinel
Change the import lines.
1516
            self.backing_transport = _mod_transport.get_transport_from_url(
5010.2.9 by Vincent Ladeuil
Fix test_smart_transport.py imports.
1517
                mem_server.get_url())
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
1518
        else:
1519
            self.backing_transport = backing_transport
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1520
        if readonly:
1521
            self.real_backing_transport = self.backing_transport
6138.1.1 by John Arbash Meinel
Change the import lines.
1522
            self.backing_transport = _mod_transport.get_transport_from_url(
5010.2.9 by Vincent Ladeuil
Fix test_smart_transport.py imports.
1523
                "readonly+" + self.backing_transport.abspath('.'))
6133.4.26 by John Arbash Meinel
get rid of the default timeout parameters.
1524
        self.server = _mod_server.SmartTCPServer(self.backing_transport,
1525
                                                 client_timeout=4.0)
5247.3.48 by Vincent Ladeuil
Fixed as per lifeless suggestion.
1526
        self.server.start_server('127.0.0.1', 0)
3245.4.28 by Andrew Bennetts
Remove another XXX, and include test ID in smart server thread names.
1527
        self.server.start_background_thread('-' + self.id())
2413.2.1 by Andrew Bennetts
Rename Smart.*Transport classes to RemoteTransport, RemoteTCPTransport, etc.
1528
        self.transport = remote.RemoteTCPTransport(self.server.get_url())
5247.2.9 by Vincent Ladeuil
The smart server leaks one thread (daemonic) for each connection.
1529
        self.addCleanup(self.stop_server)
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.
1530
        self.permit_url(self.server.get_url())
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1531
5247.2.9 by Vincent Ladeuil
The smart server leaks one thread (daemonic) for each connection.
1532
    def stop_server(self):
1533
        """Disconnect the client and stop the server.
1534
1535
        This must be re-entrant as some tests will call it explicitly in
1536
        addition to the normal cleanup.
1537
        """
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1538
        if getattr(self, 'transport', None):
1539
            self.transport.disconnect()
2370.4.1 by Robert Collins
New SmartServer hooks facility. There are two initial hooks documented
1540
            del self.transport
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1541
        if getattr(self, 'server', None):
1542
            self.server.stop_background_thread()
2370.4.1 by Robert Collins
New SmartServer hooks facility. There are two initial hooks documented
1543
            del self.server
1544
1545
1546
class TestServerSocketUsage(SmartTCPTests):
1547
5247.2.9 by Vincent Ladeuil
The smart server leaks one thread (daemonic) for each connection.
1548
    def test_server_start_stop(self):
1549
        """It should be safe to stop the server with no requests."""
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
1550
        self.start_server()
5247.3.48 by Vincent Ladeuil
Fixed as per lifeless suggestion.
1551
        t = remote.RemoteTCPTransport(self.server.get_url())
5247.2.9 by Vincent Ladeuil
The smart server leaks one thread (daemonic) for each connection.
1552
        self.stop_server()
5247.3.48 by Vincent Ladeuil
Fixed as per lifeless suggestion.
1553
        self.assertRaises(errors.ConnectionError, t.has, '.')
2376.3.8 by Robert Collins
Overhaul the SmartTCPServer connect-thread logic to synchronise on startup and shutdown and notify the server if it is in accept.
1554
1555
    def test_server_closes_listening_sock_on_shutdown_after_request(self):
2370.4.2 by Robert Collins
Review feedback.
1556
        """The server should close its listening socket when it's stopped."""
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
1557
        self.start_server()
5247.2.9 by Vincent Ladeuil
The smart server leaks one thread (daemonic) for each connection.
1558
        server_url = self.server.get_url()
2370.4.1 by Robert Collins
New SmartServer hooks facility. There are two initial hooks documented
1559
        self.transport.has('.')
5247.2.9 by Vincent Ladeuil
The smart server leaks one thread (daemonic) for each connection.
1560
        self.stop_server()
2370.4.1 by Robert Collins
New SmartServer hooks facility. There are two initial hooks documented
1561
        # if the listening socket has closed, we should get a BADFD error
1562
        # when connecting, rather than a hang.
5247.2.34 by Vincent Ladeuil
Merge sftp-leaks into catch-them-all resolving conflicts
1563
        t = remote.RemoteTCPTransport(server_url)
5247.3.48 by Vincent Ladeuil
Fixed as per lifeless suggestion.
1564
        self.assertRaises(errors.ConnectionError, t.has, '.')
2370.4.1 by Robert Collins
New SmartServer hooks facility. There are two initial hooks documented
1565
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1566
1567
class WritableEndToEndTests(SmartTCPTests):
1568
    """Client to server tests that require a writable transport."""
1569
1570
    def setUp(self):
1571
        super(WritableEndToEndTests, self).setUp()
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
1572
        self.start_server()
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1573
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1574
    def test_start_tcp_server(self):
1575
        url = self.server.get_url()
1576
        self.assertContainsRe(url, r'^bzr://127\.0\.0\.1:[0-9]{2,}/')
1577
1578
    def test_smart_transport_has(self):
1579
        """Checking for file existence over smart."""
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
1580
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
6973.7.8 by Jelmer Vernooij
Fix more tests.
1581
        self.backing_transport.put_bytes("foo", b"contents of foo\n")
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1582
        self.assertTrue(self.transport.has("foo"))
1583
        self.assertFalse(self.transport.has("non-foo"))
1584
1585
    def test_smart_transport_get(self):
1586
        """Read back a file over smart."""
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
1587
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
6973.7.8 by Jelmer Vernooij
Fix more tests.
1588
        self.backing_transport.put_bytes("foo", b"contents\nof\nfoo\n")
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1589
        fp = self.transport.get("foo")
6973.7.8 by Jelmer Vernooij
Fix more tests.
1590
        self.assertEqual(b'contents\nof\nfoo\n', fp.read())
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1591
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1592
    def test_get_error_enoent(self):
1593
        """Error reported from server getting nonexistent file."""
1752.2.81 by Andrew Bennetts
Merge cleaned up underlying dependencies for remote bzrdir.
1594
        # The path in a raised NoSuchFile exception should be the precise path
1595
        # asked for by the client. This gives meaningful and unsurprising errors
1596
        # for users.
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
1597
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
3779.3.2 by Andrew Bennetts
Unify error translation done in bzrlib.remote and bzrlib.transport.remote.
1598
        err = self.assertRaises(
1599
            errors.NoSuchFile, self.transport.get, 'not%20a%20file')
4294.2.9 by Robert Collins
Fixup tests broken by cleaning up the layering.
1600
        self.assertSubset([err.path], ['not%20a%20file', './not%20a%20file'])
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1601
1602
    def test_simple_clone_conn(self):
1603
        """Test that cloning reuses the same connection."""
1604
        # we create a real connection not a loopback one, but it will use the
1605
        # same server and pipes
1752.2.74 by Andrew Bennetts
Make SmartTransport.clone return the right class, and move connection sharing into clone from __init__.
1606
        conn2 = self.transport.clone('.')
2485.8.54 by Vincent Ladeuil
Refactor medium uses by making a distinction betweem shared and real medium.
1607
        self.assertIs(self.transport.get_smart_medium(),
1608
                      conn2.get_smart_medium())
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1609
1910.19.12 by Andrew Bennetts
Activate a disabled test, rename another test to be consistent with what it's testing. (Andrew Bennetts, Robert Collins)
1610
    def test__remote_path(self):
6973.5.12 by Jelmer Vernooij
Merge trunk.
1611
        self.assertEqual(b'/foo/bar',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1612
                         self.transport._remote_path('foo/bar'))
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1613
1614
    def test_clone_changes_base(self):
1615
        """Cloning transport produces one with a new base location"""
1616
        conn2 = self.transport.clone('subdir')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1617
        self.assertEqual(self.transport.base + 'subdir/',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1618
                         conn2.base)
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1619
1620
    def test_open_dir(self):
1621
        """Test changing directory"""
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
1622
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1623
        transport = self.transport
1624
        self.backing_transport.mkdir('toffee')
1625
        self.backing_transport.mkdir('toffee/apple')
6973.7.8 by Jelmer Vernooij
Fix more tests.
1626
        self.assertEqual(b'/toffee', transport._remote_path('toffee'))
1910.19.13 by Andrew Bennetts
Address various review comments.
1627
        toffee_trans = transport.clone('toffee')
1628
        # Check that each transport has only the contents of its directory
1629
        # directly visible. If state was being held in the wrong object, it's
1630
        # conceivable that cloning a transport would alter the state of the
1631
        # cloned-from transport.
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1632
        self.assertTrue(transport.has('toffee'))
1910.19.13 by Andrew Bennetts
Address various review comments.
1633
        self.assertFalse(toffee_trans.has('toffee'))
1634
        self.assertFalse(transport.has('apple'))
1635
        self.assertTrue(toffee_trans.has('apple'))
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1636
1637
    def test_open_bzrdir(self):
1638
        """Open an existing bzrdir over smart transport"""
1639
        transport = self.transport
1640
        t = self.backing_transport
1641
        bzrdir.BzrDirFormat.get_default_format().initialize_on_transport(t)
6472.2.3 by Jelmer Vernooij
More control dir.
1642
        result_dir = controldir.ControlDir.open_containing_from_transport(
1643
            transport)
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1644
1645
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1646
class ReadOnlyEndToEndTests(SmartTCPTests):
1647
    """Tests from the client to the server using a readonly backing transport."""
1648
1649
    def test_mkdir_error_readonly(self):
1650
        """TransportNotPossible should be preserved from the backing transport."""
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
1651
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
1652
        self.start_server(readonly=True)
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1653
        self.assertRaises(errors.TransportNotPossible, self.transport.mkdir,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1654
                          'foo')
2370.4.1 by Robert Collins
New SmartServer hooks facility. There are two initial hooks documented
1655
6606.3.1 by Vincent Ladeuil
Add rename() and open_write_stream() as explicitly not supported via the ReadonlyTransportDecorator to give better feedback when a decorated transport is misused
1656
    def test_rename_error_readonly(self):
1657
        """TransportNotPossible should be preserved from the backing transport."""
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
1658
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
6606.3.1 by Vincent Ladeuil
Add rename() and open_write_stream() as explicitly not supported via the ReadonlyTransportDecorator to give better feedback when a decorated transport is misused
1659
        self.start_server(readonly=True)
1660
        self.assertRaises(errors.TransportNotPossible, self.transport.rename,
1661
                          'foo', 'bar')
1662
1663
    def test_open_write_stream_error_readonly(self):
1664
        """TransportNotPossible should be preserved from the backing transport."""
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
1665
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
6606.3.1 by Vincent Ladeuil
Add rename() and open_write_stream() as explicitly not supported via the ReadonlyTransportDecorator to give better feedback when a decorated transport is misused
1666
        self.start_server(readonly=True)
1667
        self.assertRaises(
1668
            errors.TransportNotPossible, self.transport.open_write_stream,
1669
            'foo')
1670
2370.4.1 by Robert Collins
New SmartServer hooks facility. There are two initial hooks documented
1671
1672
class TestServerHooks(SmartTCPTests):
1673
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
1674
    def capture_server_call(self, backing_urls, public_url):
2370.4.1 by Robert Collins
New SmartServer hooks facility. There are two initial hooks documented
1675
        """Record a server_started|stopped hook firing."""
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
1676
        self.hook_calls.append((backing_urls, public_url))
1677
1678
    def test_server_started_hook_memory(self):
1679
        """The server_started hook fires when the server is started."""
1680
        self.hook_calls = []
6138.1.1 by John Arbash Meinel
Change the import lines.
1681
        _mod_server.SmartTCPServer.hooks.install_named_hook('server_started',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1682
                                                            self.capture_server_call, None)
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
1683
        self.start_server()
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
1684
        # at this point, the server will be starting a thread up.
1685
        # there is no indicator at the moment, so bodge it by doing a request.
1686
        self.transport.has('.')
1687
        # The default test server uses MemoryTransport and that has no external
1688
        # url:
1689
        self.assertEqual([([self.backing_transport.base], self.transport.base)],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1690
                         self.hook_calls)
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
1691
1692
    def test_server_started_hook_file(self):
1693
        """The server_started hook fires when the server is started."""
1694
        self.hook_calls = []
6138.1.1 by John Arbash Meinel
Change the import lines.
1695
        _mod_server.SmartTCPServer.hooks.install_named_hook('server_started',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1696
                                                            self.capture_server_call, None)
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
1697
        self.start_server(
6138.1.1 by John Arbash Meinel
Change the import lines.
1698
            backing_transport=_mod_transport.get_transport_from_path("."))
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
1699
        # at this point, the server will be starting a thread up.
1700
        # there is no indicator at the moment, so bodge it by doing a request.
1701
        self.transport.has('.')
1702
        # The default test server uses MemoryTransport and that has no external
1703
        # url:
1704
        self.assertEqual([([
1705
            self.backing_transport.base, self.backing_transport.external_url()],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1706
            self.transport.base)],
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
1707
            self.hook_calls)
1708
1709
    def test_server_stopped_hook_simple_memory(self):
1710
        """The server_stopped hook fires when the server is stopped."""
1711
        self.hook_calls = []
6138.1.1 by John Arbash Meinel
Change the import lines.
1712
        _mod_server.SmartTCPServer.hooks.install_named_hook('server_stopped',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1713
                                                            self.capture_server_call, None)
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
1714
        self.start_server()
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
1715
        result = [([self.backing_transport.base], self.transport.base)]
1716
        # check the stopping message isn't emitted up front.
1717
        self.assertEqual([], self.hook_calls)
1718
        # nor after a single message
1719
        self.transport.has('.')
1720
        self.assertEqual([], self.hook_calls)
1721
        # clean up the server
5247.2.9 by Vincent Ladeuil
The smart server leaks one thread (daemonic) for each connection.
1722
        self.stop_server()
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
1723
        # now it should have fired.
1724
        self.assertEqual(result, self.hook_calls)
1725
1726
    def test_server_stopped_hook_simple_file(self):
1727
        """The server_stopped hook fires when the server is stopped."""
1728
        self.hook_calls = []
6138.1.1 by John Arbash Meinel
Change the import lines.
1729
        _mod_server.SmartTCPServer.hooks.install_named_hook('server_stopped',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1730
                                                            self.capture_server_call, None)
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
1731
        self.start_server(
6138.1.1 by John Arbash Meinel
Change the import lines.
1732
            backing_transport=_mod_transport.get_transport_from_path("."))
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
1733
        result = [(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1734
            [self.backing_transport.base, self.backing_transport.external_url()], self.transport.base)]
2376.3.8 by Robert Collins
Overhaul the SmartTCPServer connect-thread logic to synchronise on startup and shutdown and notify the server if it is in accept.
1735
        # check the stopping message isn't emitted up front.
1736
        self.assertEqual([], self.hook_calls)
1737
        # nor after a single message
2370.4.1 by Robert Collins
New SmartServer hooks facility. There are two initial hooks documented
1738
        self.transport.has('.')
1739
        self.assertEqual([], self.hook_calls)
1740
        # clean up the server
5247.2.9 by Vincent Ladeuil
The smart server leaks one thread (daemonic) for each connection.
1741
        self.stop_server()
2376.3.8 by Robert Collins
Overhaul the SmartTCPServer connect-thread logic to synchronise on startup and shutdown and notify the server if it is in accept.
1742
        # now it should have fired.
2370.4.1 by Robert Collins
New SmartServer hooks facility. There are two initial hooks documented
1743
        self.assertEqual(result, self.hook_calls)
1744
1745
# TODO: test that when the server suffers an exception that it calls the
1746
# server-stopped hook.
1747
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1748
2018.5.17 by Andrew Bennetts
Paramaterise the commands handled by SmartServerRequestHandler.
1749
class SmartServerCommandTests(tests.TestCaseWithTransport):
1750
    """Tests that call directly into the command objects, bypassing the network
1751
    and the request dispatching.
2432.2.1 by Andrew Bennetts
Add Smart{Client,Server}RequestProtocolTwo, that prefix args tuples with a version marker.
1752
1753
    Note: these tests are rudimentary versions of the command object tests in
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
1754
    test_smart.py.
2018.5.17 by Andrew Bennetts
Paramaterise the commands handled by SmartServerRequestHandler.
1755
    """
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1756
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1757
    def test_hello(self):
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1758
        cmd = _mod_request.HelloRequest(None, '/')
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)
1759
        response = cmd.execute()
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
1760
        self.assertEqual((b'ok', b'2'), response.args)
2018.5.17 by Andrew Bennetts
Paramaterise the commands handled by SmartServerRequestHandler.
1761
        self.assertEqual(None, response.body)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1762
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1763
    def test_get_bundle(self):
7358.12.1 by Jelmer Vernooij
Move bundle code to breezy.bzr.
1764
        from breezy.bzr.bundle import serializer
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1765
        wt = self.make_branch_and_tree('.')
6855.4.1 by Jelmer Vernooij
Yet more bees.
1766
        self.build_tree_contents([('hello', b'hello world')])
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1767
        wt.add('hello')
1910.19.13 by Andrew Bennetts
Address various review comments.
1768
        rev_id = wt.commit('add hello')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1769
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1770
        cmd = _mod_request.GetBundleRequest(self.get_transport(), '/')
6973.7.8 by Jelmer Vernooij
Fix more tests.
1771
        response = cmd.execute(b'.', rev_id)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1772
        bundle = serializer.read_bundle(BytesIO(response.body))
2018.5.17 by Andrew Bennetts
Paramaterise the commands handled by SmartServerRequestHandler.
1773
        self.assertEqual((), response.args)
1774
1775
1776
class SmartServerRequestHandlerTests(tests.TestCaseWithTransport):
1777
    """Test that call directly into the handler logic, bypassing the network."""
1778
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)
1779
    def setUp(self):
1780
        super(SmartServerRequestHandlerTests, self).setUp()
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
1781
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
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)
1782
2018.5.17 by Andrew Bennetts
Paramaterise the commands handled by SmartServerRequestHandler.
1783
    def build_handler(self, transport):
1784
        """Returns a handler for the commands in protocol version one."""
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1785
        return _mod_request.SmartServerRequestHandler(
1786
            transport, _mod_request.request_handlers, '/')
2018.5.17 by Andrew Bennetts
Paramaterise the commands handled by SmartServerRequestHandler.
1787
1788
    def test_construct_request_handler(self):
1789
        """Constructing a request handler should be easy and set defaults."""
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1790
        handler = _mod_request.SmartServerRequestHandler(None, commands=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1791
                                                         root_client_path='/')
2018.5.17 by Andrew Bennetts
Paramaterise the commands handled by SmartServerRequestHandler.
1792
        self.assertFalse(handler.finished_reading)
1793
1794
    def test_hello(self):
1795
        handler = self.build_handler(None)
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
1796
        handler.args_received((b'hello',))
1797
        self.assertEqual((b'ok', b'2'), handler.response.args)
2018.5.17 by Andrew Bennetts
Paramaterise the commands handled by SmartServerRequestHandler.
1798
        self.assertEqual(None, handler.response.body)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1799
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)
1800
    def test_disable_vfs_handler_classes_via_environment(self):
2018.5.140 by Andrew Bennetts
Merge from bzr.dev
1801
        # VFS handler classes will raise an error from "execute" if
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
1802
        # BRZ_NO_SMART_VFS is set.
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
1803
        handler = vfs.HasRequest(None, '/')
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)
1804
        # set environment variable after construction to make sure it's
1805
        # examined.
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
1806
        self.overrideEnv('BRZ_NO_SMART_VFS', '')
6734.1.4 by Jelmer Vernooij
Move DisabledMethod.
1807
        self.assertRaises(_mod_request.DisabledMethod, handler.execute)
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)
1808
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1809
    def test_readonly_exception_becomes_transport_not_possible(self):
1810
        """The response for a read-only error is ('ReadOnlyError')."""
2018.5.17 by Andrew Bennetts
Paramaterise the commands handled by SmartServerRequestHandler.
1811
        handler = self.build_handler(self.get_readonly_transport())
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1812
        # send a mkdir for foo, with no explicit mode - should fail.
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
1813
        handler.args_received((b'mkdir', b'foo', b''))
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1814
        # and the failure should be an explicit ReadOnlyError
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
1815
        self.assertEqual((b"ReadOnlyError", ), handler.response.args)
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1816
        # XXX: TODO: test that other TransportNotPossible errors are
1817
        # presented as TransportNotPossible - not possible to do that
1818
        # until I figure out how to trigger that relatively cleanly via
1819
        # the api. RBC 20060918
1820
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
1821
    def test_hello_has_finished_body_on_dispatch(self):
1822
        """The 'hello' command should set finished_reading."""
2018.5.17 by Andrew Bennetts
Paramaterise the commands handled by SmartServerRequestHandler.
1823
        handler = self.build_handler(None)
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
1824
        handler.args_received((b'hello',))
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
1825
        self.assertTrue(handler.finished_reading)
1826
        self.assertNotEqual(None, handler.response)
1827
1828
    def test_put_bytes_non_atomic(self):
1829
        """'put_...' should set finished_reading after reading the bytes."""
2018.5.17 by Andrew Bennetts
Paramaterise the commands handled by SmartServerRequestHandler.
1830
        handler = self.build_handler(self.get_transport())
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
1831
        handler.args_received((b'put_non_atomic', b'a-file', b'', b'F', b''))
1832
        self.assertFalse(handler.finished_reading)
1833
        handler.accept_body(b'1234')
1834
        self.assertFalse(handler.finished_reading)
1835
        handler.accept_body(b'5678')
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
1836
        handler.end_of_body()
1837
        self.assertTrue(handler.finished_reading)
6973.7.8 by Jelmer Vernooij
Fix more tests.
1838
        self.assertEqual((b'ok', ), handler.response.args)
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
1839
        self.assertEqual(None, handler.response.body)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1840
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
1841
    def test_readv_accept_body(self):
1842
        """'readv' should set finished_reading after reading offsets."""
1843
        self.build_tree(['a-file'])
2018.5.17 by Andrew Bennetts
Paramaterise the commands handled by SmartServerRequestHandler.
1844
        handler = self.build_handler(self.get_readonly_transport())
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
1845
        handler.args_received((b'readv', b'a-file'))
1846
        self.assertFalse(handler.finished_reading)
1847
        handler.accept_body(b'2,')
1848
        self.assertFalse(handler.finished_reading)
1849
        handler.accept_body(b'3')
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
1850
        handler.end_of_body()
1851
        self.assertTrue(handler.finished_reading)
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
1852
        self.assertEqual((b'readv', ), handler.response.args)
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
1853
        # co - nte - nt of a-file is the file contents we are extracting from.
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
1854
        self.assertEqual(b'nte', handler.response.body)
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
1855
1856
    def test_readv_short_read_response_contents(self):
1857
        """'readv' when a short read occurs sets the response appropriately."""
1858
        self.build_tree(['a-file'])
2018.5.17 by Andrew Bennetts
Paramaterise the commands handled by SmartServerRequestHandler.
1859
        handler = self.build_handler(self.get_readonly_transport())
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
1860
        handler.args_received((b'readv', b'a-file'))
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
1861
        # read beyond the end of the file.
6973.7.8 by Jelmer Vernooij
Fix more tests.
1862
        handler.accept_body(b'100,1')
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
1863
        handler.end_of_body()
1864
        self.assertTrue(handler.finished_reading)
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
1865
        self.assertEqual((b'ShortReadvError', b'./a-file', b'100', b'1', b'0'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1866
                         handler.response.args)
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
1867
        self.assertEqual(None, handler.response.body)
1868
1752.2.73 by Andrew Bennetts
Define (and register as bzr+ssh://) SmartSSHTransport, factor out an SSHSubprocess from SFTPSubprocess, and make SmartTransport connect lazily rather than in the constructor.
1869
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)
1870
class RemoteTransportRegistration(tests.TestCase):
1752.2.73 by Andrew Bennetts
Define (and register as bzr+ssh://) SmartSSHTransport, factor out an SSHSubprocess from SFTPSubprocess, and make SmartTransport connect lazily rather than in the constructor.
1871
1872
    def test_registration(self):
6138.1.1 by John Arbash Meinel
Change the import lines.
1873
        t = _mod_transport.get_transport_from_url('bzr+ssh://example.com/path')
2413.2.1 by Andrew Bennetts
Rename Smart.*Transport classes to RemoteTransport, RemoteTCPTransport, etc.
1874
        self.assertIsInstance(t, remote.RemoteSSHTransport)
6055.2.1 by Jelmer Vernooij
Add UnparsedUrl.
1875
        self.assertEqual('example.com', t._parsed_url.host)
1752.2.73 by Andrew Bennetts
Define (and register as bzr+ssh://) SmartSSHTransport, factor out an SSHSubprocess from SFTPSubprocess, and make SmartTransport connect lazily rather than in the constructor.
1876
2814.2.2 by Martin Pool
merge bzr+https patch from johnf and add a basic test
1877
    def test_bzr_https(self):
1878
        # https://bugs.launchpad.net/bzr/+bug/128456
7143.15.2 by Jelmer Vernooij
Run autopep8.
1879
        t = _mod_transport.get_transport_from_url(
1880
            'bzr+https://example.com/path')
2814.2.2 by Martin Pool
merge bzr+https patch from johnf and add a basic test
1881
        self.assertIsInstance(t, remote.RemoteHTTPTransport)
1882
        self.assertStartsWith(
1883
            t._http_transport.base,
1884
            'https://')
1885
1752.2.73 by Andrew Bennetts
Define (and register as bzr+ssh://) SmartSSHTransport, factor out an SSHSubprocess from SFTPSubprocess, and make SmartTransport connect lazily rather than in the constructor.
1886
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)
1887
class TestRemoteTransport(tests.TestCase):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1888
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
1889
    def test_use_connection_factory(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)
1890
        # We want to be able to pass a client as a parameter to RemoteTransport.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1891
        input = BytesIO(b'ok\n3\nbardone\n')
1892
        output = BytesIO()
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.
1893
        client_medium = medium.SmartSimplePipesClientMedium(
1894
            input, output, 'base')
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)
1895
        transport = remote.RemoteTransport(
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
1896
            'bzr://localhost/', medium=client_medium)
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
1897
        # Disable version detection.
3245.4.47 by Andrew Bennetts
Don't automatically send 'hello' requests from RemoteBzrDirFormat.probe_transport unless we have to (i.e. the transport is HTTP).
1898
        client_medium._protocol_version = 1
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
1899
1900
        # We want to make sure the client is used when the first remote
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
1901
        # method is called.  No data should have been sent, or read.
1902
        self.assertEqual(0, input.tell())
6973.7.8 by Jelmer Vernooij
Fix more tests.
1903
        self.assertEqual(b'', output.getvalue())
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
1904
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
1905
        # Now call a method that should result in one request: as the
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
1906
        # transport makes its own protocol instances, we check on the wire.
1907
        # XXX: TODO: give the transport a protocol factory, which can make
1908
        # an instrumented protocol for us.
6973.7.8 by Jelmer Vernooij
Fix more tests.
1909
        self.assertEqual(b'bar', transport.get_bytes('foo'))
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
1910
        # only the needed data should have been sent/received.
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
1911
        self.assertEqual(13, input.tell())
6973.7.8 by Jelmer Vernooij
Fix more tests.
1912
        self.assertEqual(b'get\x01/foo\n', output.getvalue())
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
1913
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1914
    def test__translate_error_readonly(self):
1915
        """Sending a ReadOnlyError to _translate_error raises TransportNotPossible."""
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.
1916
        client_medium = medium.SmartSimplePipesClientMedium(None, None, 'base')
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)
1917
        transport = remote.RemoteTransport(
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
1918
            'bzr://localhost/', medium=client_medium)
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
1919
        err = errors.ErrorFromSmartServer((b"ReadOnlyError", ))
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1920
        self.assertRaises(errors.TransportNotPossible,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1921
                          transport._translate_error, err)
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
1922
1910.19.22 by Robert Collins
Rearrange the readv patch to put the serialise offsets method into the correct class, and document the structure of the classes somewhat better to hint to people writing patches where code should go. Also alter the test so that the client and server components are tested in one place preventing possible encoding skew from occuring.
1923
2432.2.5 by Andrew Bennetts
Reduce duplication in test_smart_transport.
1924
class TestSmartProtocol(tests.TestCase):
1925
    """Base class for smart protocol tests.
1910.19.22 by Robert Collins
Rearrange the readv patch to put the serialise offsets method into the correct class, and document the structure of the classes somewhat better to hint to people writing patches where code should go. Also alter the test so that the client and server components are tested in one place preventing possible encoding skew from occuring.
1926
1927
    Each test case gets a smart_server and smart_client created during setUp().
1928
1929
    It is planned that the client can be called with self.call_client() giving
1930
    it an expected server response, which will be fed into it when it tries to
1931
    read. Likewise, self.call_server will call a servers method with a canned
1932
    serialised client request. Output done by the client or server for these
1933
    calls will be captured to self.to_server and self.to_client. Each element
1934
    in the list is a write call from the client or server respectively.
2432.2.5 by Andrew Bennetts
Reduce duplication in test_smart_transport.
1935
1936
    Subclasses can override client_protocol_class and server_protocol_class.
1910.19.22 by Robert Collins
Rearrange the readv patch to put the serialise offsets method into the correct class, and document the structure of the classes somewhat better to hint to people writing patches where code should go. Also alter the test so that the client and server components are tested in one place preventing possible encoding skew from occuring.
1937
    """
1938
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
1939
    request_encoder = None
1940
    response_decoder = None
1941
    server_protocol_class = None
2432.2.5 by Andrew Bennetts
Reduce duplication in test_smart_transport.
1942
    client_protocol_class = None
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
1943
1944
    def make_client_protocol_and_output(self, input_bytes=None):
3245.4.26 by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers.
1945
        """
1946
        :returns: a Request
1947
        """
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
1948
        # This is very similar to
6670.4.16 by Jelmer Vernooij
Move smart to breezy.bzr.
1949
        # breezy.bzr.smart.client._SmartClient._build_client_protocol
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
1950
        # XXX: make this use _SmartClient!
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
1951
        if input_bytes is None:
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1952
            input = BytesIO()
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
1953
        else:
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1954
            input = BytesIO(input_bytes)
1955
        output = BytesIO()
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.
1956
        client_medium = medium.SmartSimplePipesClientMedium(
1957
            input, output, 'base')
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
1958
        request = client_medium.get_request()
1959
        if self.client_protocol_class is not None:
1960
            client_protocol = self.client_protocol_class(request)
1961
            return client_protocol, client_protocol, output
1962
        else:
3245.4.55 by Andrew Bennetts
Test improvements suggested by John's review.
1963
            self.assertNotEqual(None, self.request_encoder)
1964
            self.assertNotEqual(None, self.response_decoder)
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
1965
            requester = self.request_encoder(request)
1966
            response_handler = message.ConventionalResponseHandler()
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
1967
            response_protocol = self.response_decoder(
1968
                response_handler, expect_version_marker=True)
3245.4.26 by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers.
1969
            response_handler.setProtoAndMediumRequest(
1970
                response_protocol, request)
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
1971
            return requester, response_handler, output
1972
1973
    def make_client_protocol(self, input_bytes=None):
1974
        result = self.make_client_protocol_and_output(input_bytes=input_bytes)
1975
        requester, response_handler, output = result
1976
        return requester, response_handler
1910.19.22 by Robert Collins
Rearrange the readv patch to put the serialise offsets method into the correct class, and document the structure of the classes somewhat better to hint to people writing patches where code should go. Also alter the test so that the client and server components are tested in one place preventing possible encoding skew from occuring.
1977
3245.1.11 by Andrew Bennetts
Add make_server_protocol helper to TestSmartProtocol.
1978
    def make_server_protocol(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1979
        out_stream = BytesIO()
3245.4.34 by Andrew Bennetts
Remove another insignificant change vs. bzr.dev.
1980
        smart_protocol = self.server_protocol_class(None, out_stream.write)
3245.1.11 by Andrew Bennetts
Add make_server_protocol helper to TestSmartProtocol.
1981
        return smart_protocol, out_stream
1982
1910.19.22 by Robert Collins
Rearrange the readv patch to put the serialise offsets method into the correct class, and document the structure of the classes somewhat better to hint to people writing patches where code should go. Also alter the test so that the client and server components are tested in one place preventing possible encoding skew from occuring.
1983
    def setUp(self):
2432.2.5 by Andrew Bennetts
Reduce duplication in test_smart_transport.
1984
        super(TestSmartProtocol, self).setUp()
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
1985
        self.response_marker = getattr(
1986
            self.client_protocol_class, 'response_marker', None)
1987
        self.request_marker = getattr(
1988
            self.client_protocol_class, 'request_marker', None)
1910.19.22 by Robert Collins
Rearrange the readv patch to put the serialise offsets method into the correct class, and document the structure of the classes somewhat better to hint to people writing patches where code should go. Also alter the test so that the client and server components are tested in one place preventing possible encoding skew from occuring.
1989
1990
    def assertOffsetSerialisation(self, expected_offsets, expected_serialised,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1991
                                  requester):
1910.19.22 by Robert Collins
Rearrange the readv patch to put the serialise offsets method into the correct class, and document the structure of the classes somewhat better to hint to people writing patches where code should go. Also alter the test so that the client and server components are tested in one place preventing possible encoding skew from occuring.
1992
        """Check that smart (de)serialises offsets as expected.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1993
1910.19.22 by Robert Collins
Rearrange the readv patch to put the serialise offsets method into the correct class, and document the structure of the classes somewhat better to hint to people writing patches where code should go. Also alter the test so that the client and server components are tested in one place preventing possible encoding skew from occuring.
1994
        We check both serialisation and deserialisation at the same time
1995
        to ensure that the round tripping cannot skew: both directions should
1996
        be as expected.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1997
1910.19.22 by Robert Collins
Rearrange the readv patch to put the serialise offsets method into the correct class, and document the structure of the classes somewhat better to hint to people writing patches where code should go. Also alter the test so that the client and server components are tested in one place preventing possible encoding skew from occuring.
1998
        :param expected_offsets: a readv offset list.
1999
        :param expected_seralised: an expected serial form of the offsets.
2000
        """
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
2001
        # XXX: '_deserialise_offsets' should be a method of the
2002
        # SmartServerRequestProtocol in future.
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
2003
        readv_cmd = vfs.ReadvRequest(None, '/')
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
2004
        offsets = readv_cmd._deserialise_offsets(expected_serialised)
1910.19.22 by Robert Collins
Rearrange the readv patch to put the serialise offsets method into the correct class, and document the structure of the classes somewhat better to hint to people writing patches where code should go. Also alter the test so that the client and server components are tested in one place preventing possible encoding skew from occuring.
2005
        self.assertEqual(expected_offsets, offsets)
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
2006
        serialised = requester._serialise_offsets(offsets)
1910.19.22 by Robert Collins
Rearrange the readv patch to put the serialise offsets method into the correct class, and document the structure of the classes somewhat better to hint to people writing patches where code should go. Also alter the test so that the client and server components are tested in one place preventing possible encoding skew from occuring.
2007
        self.assertEqual(expected_serialised, serialised)
2008
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
2009
    def build_protocol_waiting_for_body(self):
3245.1.11 by Andrew Bennetts
Add make_server_protocol helper to TestSmartProtocol.
2010
        smart_protocol, out_stream = self.make_server_protocol()
3245.4.59 by Andrew Bennetts
Various tweaks in response to Martin's review.
2011
        smart_protocol._has_dispatched = True
3245.1.14 by Andrew Bennetts
Merge from bzr.dev
2012
        smart_protocol.request = _mod_request.SmartServerRequestHandler(
2013
            None, _mod_request.request_handlers, '/')
5340.15.1 by John Arbash Meinel
supersede exc-info branch
2014
        # GZ 2010-08-10: Cycle with closure affects 4 tests
7143.15.2 by Jelmer Vernooij
Run autopep8.
2015
3923.5.2 by Andrew Bennetts
Completely delegate handling of request body chunks to the command object. The default implementation accumulates, like the existing behaviour.
2016
        class FakeCommand(_mod_request.SmartServerRequest):
2017
            def do_body(self_cmd, body_bytes):
2018.5.7 by Andrew Bennetts
Simplify dispatch_command.
2018
                self.end_received = True
6973.7.8 by Jelmer Vernooij
Fix more tests.
2019
                self.assertEqual(b'abcdefg', body_bytes)
2020
                return _mod_request.SuccessfulSmartServerResponse((b'ok', ))
3923.5.2 by Andrew Bennetts
Completely delegate handling of request body chunks to the command object. The default implementation accumulates, like the existing behaviour.
2021
        smart_protocol.request._command = FakeCommand(None)
2400.1.4 by Andrew Bennetts
Tidy up accidental changes.
2022
        # Call accept_bytes to make sure that internal state like _body_decoder
2023
        # is initialised.  This test should probably be given a clearer
2024
        # interface to work with that will not cause this inconsistency.
2025
        #   -- Andrew Bennetts, 2006-09-28
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2026
        smart_protocol.accept_bytes(b'')
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2027
        return smart_protocol
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
2028
2432.2.5 by Andrew Bennetts
Reduce duplication in test_smart_transport.
2029
    def assertServerToClientEncoding(self, expected_bytes, expected_tuple,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2030
                                     input_tuples):
2432.2.5 by Andrew Bennetts
Reduce duplication in test_smart_transport.
2031
        """Assert that each input_tuple serialises as expected_bytes, and the
2032
        bytes deserialise as expected_tuple.
2033
        """
2034
        # check the encoding of the server for all input_tuples matches
2035
        # expected bytes
2036
        for input_tuple in input_tuples:
3245.1.11 by Andrew Bennetts
Add make_server_protocol helper to TestSmartProtocol.
2037
            server_protocol, server_output = self.make_server_protocol()
2432.4.4 by Robert Collins
Merge hpss-protocol2.
2038
            server_protocol._send_response(
2039
                _mod_request.SuccessfulSmartServerResponse(input_tuple))
2432.2.5 by Andrew Bennetts
Reduce duplication in test_smart_transport.
2040
            self.assertEqual(expected_bytes, server_output.getvalue())
2041
        # check the decoding of the client smart_protocol from expected_bytes:
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
2042
        requester, response_handler = self.make_client_protocol(expected_bytes)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2043
        requester.call(b'foo')
7143.15.2 by Jelmer Vernooij
Run autopep8.
2044
        self.assertEqual(
2045
            expected_tuple, response_handler.read_response_tuple())
2432.2.5 by Andrew Bennetts
Reduce duplication in test_smart_transport.
2046
2047
2621.3.1 by Andrew Bennetts
Log errors from the smart server in the trace file, to make debugging test failures (and live failures!) easier.
2048
class CommonSmartProtocolTestMixin(object):
2049
3195.2.1 by Andrew Bennetts
Improve test coverage, and fix a bug revealed by the improved coverage.
2050
    def test_connection_closed_reporting(self):
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
2051
        requester, response_handler = self.make_client_protocol()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2052
        requester.call(b'hello')
3245.1.10 by Andrew Bennetts
Remove trailing whitespace.
2053
        ex = self.assertRaises(errors.ConnectionReset,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2054
                               response_handler.read_response_tuple)
3195.2.1 by Andrew Bennetts
Improve test coverage, and fix a bug revealed by the improved coverage.
2055
        self.assertEqual("Connection closed: "
7143.15.2 by Jelmer Vernooij
Run autopep8.
2056
                         "Unexpected end of message. Please check connectivity "
2057
                         "and permissions, and report a bug if problems persist. ",
2058
                         str(ex))
3195.2.1 by Andrew Bennetts
Improve test coverage, and fix a bug revealed by the improved coverage.
2059
3245.1.8 by Andrew Bennetts
Remove TestSmartProtocol.setUp entirely.
2060
    def test_server_offset_serialisation(self):
2061
        """The Smart protocol serialises offsets as a comma and \n string.
2062
2063
        We check a number of boundary cases are as expected: empty, one offset,
2064
        one with the order of reads not increasing (an out of order read), and
2065
        one that should coalesce.
2066
        """
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
2067
        requester, response_handler = self.make_client_protocol()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2068
        self.assertOffsetSerialisation([], b'', requester)
2069
        self.assertOffsetSerialisation([(1, 2)], b'1,2', requester)
2070
        self.assertOffsetSerialisation([(10, 40), (0, 5)], b'10,40\n0,5',
7143.15.2 by Jelmer Vernooij
Run autopep8.
2071
                                       requester)
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
2072
        self.assertOffsetSerialisation([(1, 2), (3, 4), (100, 200)],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2073
                                       b'1,2\n3,4\n100,200', requester)
3245.1.8 by Andrew Bennetts
Remove TestSmartProtocol.setUp entirely.
2074
2621.3.1 by Andrew Bennetts
Log errors from the smart server in the trace file, to make debugging test failures (and live failures!) easier.
2075
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2076
class TestVersionOneFeaturesInProtocolOne(
7143.15.2 by Jelmer Vernooij
Run autopep8.
2077
        TestSmartProtocol, CommonSmartProtocolTestMixin):
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2078
    """Tests for version one smart protocol features as implemeted by version
2079
    one."""
2432.2.5 by Andrew Bennetts
Reduce duplication in test_smart_transport.
2080
2081
    client_protocol_class = protocol.SmartClientRequestProtocolOne
2082
    server_protocol_class = protocol.SmartServerRequestProtocolOne
2083
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2084
    def test_construct_version_one_server_protocol(self):
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2085
        smart_protocol = protocol.SmartServerRequestProtocolOne(None, None)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2086
        self.assertEqual(b'', smart_protocol.unused_data)
2087
        self.assertEqual(b'', smart_protocol.in_buffer)
3245.4.59 by Andrew Bennetts
Various tweaks in response to Martin's review.
2088
        self.assertFalse(smart_protocol._has_dispatched)
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2089
        self.assertEqual(1, smart_protocol.next_read_size())
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2090
2091
    def test_construct_version_one_client_protocol(self):
2092
        # we can construct a client protocol from a client medium request
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2093
        output = BytesIO()
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.
2094
        client_medium = medium.SmartSimplePipesClientMedium(
2095
            None, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
2096
        request = client_medium.get_request()
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2097
        client_protocol = protocol.SmartClientRequestProtocolOne(request)
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
2098
2018.3.2 by Andrew Bennetts
Ensure that a request's next_read_size() is 0 once an error response is sent.
2099
    def test_accept_bytes_of_bad_request_to_protocol(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2100
        out_stream = BytesIO()
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2101
        smart_protocol = protocol.SmartServerRequestProtocolOne(
2102
            None, out_stream.write)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2103
        smart_protocol.accept_bytes(b'abc')
2104
        self.assertEqual(b'abc', smart_protocol.in_buffer)
2105
        smart_protocol.accept_bytes(b'\n')
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2106
        self.assertEqual(
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2107
            b"error\x01Generic bzr smart protocol error: bad request 'abc'\n",
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2108
            out_stream.getvalue())
3245.4.59 by Andrew Bennetts
Various tweaks in response to Martin's review.
2109
        self.assertTrue(smart_protocol._has_dispatched)
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2110
        self.assertEqual(0, smart_protocol.next_read_size())
2018.2.26 by Andrew Bennetts
Changes prompted by j-a-meinel's review.
2111
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
2112
    def test_accept_body_bytes_to_protocol(self):
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
2113
        protocol = self.build_protocol_waiting_for_body()
2018.2.15 by Andrew Bennetts
Remove SmartServerRequestProtocolOne.finished_reading attribute, replace with next_read_size method.
2114
        self.assertEqual(6, protocol.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2115
        protocol.accept_bytes(b'7\nabc')
2018.2.15 by Andrew Bennetts
Remove SmartServerRequestProtocolOne.finished_reading attribute, replace with next_read_size method.
2116
        self.assertEqual(9, protocol.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2117
        protocol.accept_bytes(b'defgd')
2118
        protocol.accept_bytes(b'one\n')
2018.2.15 by Andrew Bennetts
Remove SmartServerRequestProtocolOne.finished_reading attribute, replace with next_read_size method.
2119
        self.assertEqual(0, protocol.next_read_size())
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
2120
        self.assertTrue(self.end_received)
2121
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
2122
    def test_accept_request_and_body_all_at_once(self):
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
2123
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
2124
        mem_transport = memory.MemoryTransport()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2125
        mem_transport.put_bytes('foo', b'abcdefghij')
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2126
        out_stream = BytesIO()
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2127
        smart_protocol = protocol.SmartServerRequestProtocolOne(mem_transport,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2128
                                                                out_stream.write)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2129
        smart_protocol.accept_bytes(b'readv\x01foo\n3\n3,3done\n')
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2130
        self.assertEqual(0, smart_protocol.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2131
        self.assertEqual(b'readv\n3\ndefdone\n', out_stream.getvalue())
2132
        self.assertEqual(b'', smart_protocol.unused_data)
2133
        self.assertEqual(b'', smart_protocol.in_buffer)
2018.2.14 by Andrew Bennetts
Seperate SmartServer{Pipe,Socket}StreamMedium out of SmartServerStreamMedium. Use recv to make the socket server medium better.
2134
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
2135
    def test_accept_excess_bytes_are_preserved(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2136
        out_stream = BytesIO()
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2137
        smart_protocol = protocol.SmartServerRequestProtocolOne(
2138
            None, out_stream.write)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2139
        smart_protocol.accept_bytes(b'hello\nhello\n')
2140
        self.assertEqual(b"ok\x012\n", out_stream.getvalue())
2141
        self.assertEqual(b"hello\n", smart_protocol.unused_data)
2142
        self.assertEqual(b"", smart_protocol.in_buffer)
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
2143
2144
    def test_accept_excess_bytes_after_body(self):
2145
        protocol = self.build_protocol_waiting_for_body()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2146
        protocol.accept_bytes(b'7\nabcdefgdone\nX')
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
2147
        self.assertTrue(self.end_received)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2148
        self.assertEqual(b"X", protocol.unused_data)
2149
        self.assertEqual(b"", protocol.in_buffer)
2150
        protocol.accept_bytes(b'Y')
2151
        self.assertEqual(b"XY", protocol.unused_data)
2152
        self.assertEqual(b"", protocol.in_buffer)
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
2153
2154
    def test_accept_excess_bytes_after_dispatch(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2155
        out_stream = BytesIO()
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2156
        smart_protocol = protocol.SmartServerRequestProtocolOne(
2157
            None, out_stream.write)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2158
        smart_protocol.accept_bytes(b'hello\n')
2159
        self.assertEqual(b"ok\x012\n", out_stream.getvalue())
2160
        smart_protocol.accept_bytes(b'hel')
2161
        self.assertEqual(b"hel", smart_protocol.unused_data)
2162
        smart_protocol.accept_bytes(b'lo\n')
2163
        self.assertEqual(b"hello\n", smart_protocol.unused_data)
2164
        self.assertEqual(b"", smart_protocol.in_buffer)
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
2165
2018.3.2 by Andrew Bennetts
Ensure that a request's next_read_size() is 0 once an error response is sent.
2166
    def test__send_response_sets_finished_reading(self):
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2167
        smart_protocol = protocol.SmartServerRequestProtocolOne(
2168
            None, lambda x: None)
2169
        self.assertEqual(1, smart_protocol.next_read_size())
2432.4.3 by Robert Collins
Refactor the HPSS Response code to take SmartServerResponse rather than args and body.
2170
        smart_protocol._send_response(
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2171
            _mod_request.SuccessfulSmartServerResponse((b'x',)))
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2172
        self.assertEqual(0, smart_protocol.next_read_size())
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
2173
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
2174
    def test__send_response_errors_with_base_response(self):
2175
        """Ensure that only the Successful/Failed subclasses are used."""
2176
        smart_protocol = protocol.SmartServerRequestProtocolOne(
2177
            None, lambda x: None)
2178
        self.assertRaises(AttributeError, smart_protocol._send_response,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2179
                          _mod_request.SmartServerResponse((b'x',)))
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
2180
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
2181
    def test_query_version(self):
2182
        """query_version on a SmartClientProtocolOne should return a number.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2183
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2184
        The protocol provides the query_version because the domain level clients
2185
        may all need to be able to probe for capabilities.
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
2186
        """
2187
        # What we really want to test here is that SmartClientProtocolOne calls
2188
        # accept_bytes(tuple_based_encoding_of_hello) and reads and parses the
4031.3.1 by Frank Aspell
Fixing various typos
2189
        # response of tuple-encoded (ok, 1).  Also, separately we should test
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2190
        # the error if the response is a non-understood version.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2191
        input = BytesIO(b'ok\x012\n')
2192
        output = BytesIO()
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.
2193
        client_medium = medium.SmartSimplePipesClientMedium(
2194
            input, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
2195
        request = client_medium.get_request()
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2196
        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
3245.4.59 by Andrew Bennetts
Various tweaks in response to Martin's review.
2197
        self.assertEqual(2, smart_protocol.query_version())
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2198
2199
    def test_client_call_empty_response(self):
2200
        # protocol.call() can get back an empty tuple as a response. This occurs
2201
        # when the parsed line is an empty line, and results in a tuple with
2202
        # one element - an empty string.
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2203
        self.assertServerToClientEncoding(b'\n', (b'', ), [(), (b'', )])
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2204
2205
    def test_client_call_three_element_response(self):
2206
        # protocol.call() can get back tuples of other lengths. A three element
2207
        # tuple should be unpacked as three strings.
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2208
        self.assertServerToClientEncoding(b'a\x01b\x0134\n', (b'a', b'b', b'34'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
2209
                                          [(b'a', b'b', b'34')])
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2210
2211
    def test_client_call_with_body_bytes_uploads(self):
2018.5.131 by Andrew Bennetts
Be strict about unicode passed to transport.put_{bytes,file} and SmartClient.call_with_body_bytes, fixing part of TestLockableFiles_RemoteLockDir.test_read_write.
2212
        # protocol.call_with_body_bytes should length-prefix the bytes onto the
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2213
        # wire.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2214
        expected_bytes = b"foo\n7\nabcdefgdone\n"
2215
        input = BytesIO(b"\n")
2216
        output = BytesIO()
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.
2217
        client_medium = medium.SmartSimplePipesClientMedium(
2218
            input, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
2219
        request = client_medium.get_request()
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2220
        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2221
        smart_protocol.call_with_body_bytes((b'foo', ), b"abcdefg")
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2222
        self.assertEqual(expected_bytes, output.getvalue())
2223
2224
    def test_client_call_with_body_readv_array(self):
2225
        # protocol.call_with_upload should encode the readv array and then
2226
        # length-prefix the bytes onto the wire.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2227
        expected_bytes = b"foo\n7\n1,2\n5,6done\n"
2228
        input = BytesIO(b"\n")
2229
        output = BytesIO()
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.
2230
        client_medium = medium.SmartSimplePipesClientMedium(
2231
            input, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
2232
        request = client_medium.get_request()
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2233
        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2234
        smart_protocol.call_with_body_readv_array((b'foo', ), [(1, 2), (5, 6)])
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2235
        self.assertEqual(expected_bytes, output.getvalue())
2236
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.
2237
    def _test_client_read_response_tuple_raises_UnknownSmartMethod(self,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2238
                                                                   server_bytes):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2239
        input = BytesIO(server_bytes)
2240
        output = BytesIO()
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.
2241
        client_medium = medium.SmartSimplePipesClientMedium(
2242
            input, output, 'base')
3297.3.1 by Andrew Bennetts
Raise UnknownSmartMethod automatically from read_response_tuple.
2243
        request = client_medium.get_request()
2244
        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2245
        smart_protocol.call(b'foo')
3297.3.1 by Andrew Bennetts
Raise UnknownSmartMethod automatically from read_response_tuple.
2246
        self.assertRaises(
2247
            errors.UnknownSmartMethod, smart_protocol.read_response_tuple)
2248
        # The request has been finished.  There is no body to read, and
2249
        # attempts to read one will fail.
2250
        self.assertRaises(
2251
            errors.ReadingCompleted, smart_protocol.read_body_bytes)
2252
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.
2253
    def test_client_read_response_tuple_raises_UnknownSmartMethod(self):
2254
        """read_response_tuple raises UnknownSmartMethod if the response says
2255
        the server did not recognise the request.
2256
        """
2257
        server_bytes = (
6973.7.8 by Jelmer Vernooij
Fix more tests.
2258
            b"error\x01Generic bzr smart protocol error: bad request 'foo'\n")
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.
2259
        self._test_client_read_response_tuple_raises_UnknownSmartMethod(
2260
            server_bytes)
2261
2262
    def test_client_read_response_tuple_raises_UnknownSmartMethod_0_11(self):
2263
        """read_response_tuple also raises UnknownSmartMethod if the response
2264
        from a bzr 0.11 says the server did not recognise the request.
2265
2266
        (bzr 0.11 sends a slightly different error message to later versions.)
2267
        """
2268
        server_bytes = (
6973.7.8 by Jelmer Vernooij
Fix more tests.
2269
            b"error\x01Generic bzr smart protocol error: bad request u'foo'\n")
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.
2270
        self._test_client_read_response_tuple_raises_UnknownSmartMethod(
2271
            server_bytes)
2272
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2273
    def test_client_read_body_bytes_all(self):
2274
        # read_body_bytes should decode the body bytes from the wire into
2275
        # a response.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2276
        expected_bytes = b"1234567"
2277
        server_bytes = b"ok\n7\n1234567done\n"
2278
        input = BytesIO(server_bytes)
2279
        output = BytesIO()
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.
2280
        client_medium = medium.SmartSimplePipesClientMedium(
2281
            input, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
2282
        request = client_medium.get_request()
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2283
        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2284
        smart_protocol.call(b'foo')
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2285
        smart_protocol.read_response_tuple(True)
2286
        self.assertEqual(expected_bytes, smart_protocol.read_body_bytes())
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2287
2288
    def test_client_read_body_bytes_incremental(self):
2289
        # test reading a few bytes at a time from the body
2290
        # XXX: possibly we should test dribbling the bytes into the stringio
2018.2.15 by Andrew Bennetts
Remove SmartServerRequestProtocolOne.finished_reading attribute, replace with next_read_size method.
2291
        # to make the state machine work harder: however, as we use the
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2292
        # LengthPrefixedBodyDecoder that is already well tested - we can skip
2293
        # that.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2294
        expected_bytes = b"1234567"
2295
        server_bytes = b"ok\n7\n1234567done\n"
2296
        input = BytesIO(server_bytes)
2297
        output = BytesIO()
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.
2298
        client_medium = medium.SmartSimplePipesClientMedium(
2299
            input, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
2300
        request = client_medium.get_request()
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2301
        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2302
        smart_protocol.call(b'foo')
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2303
        smart_protocol.read_response_tuple(True)
7143.15.2 by Jelmer Vernooij
Run autopep8.
2304
        self.assertEqual(expected_bytes[0:2],
2305
                         smart_protocol.read_body_bytes(2))
2306
        self.assertEqual(expected_bytes[2:4],
2307
                         smart_protocol.read_body_bytes(2))
2308
        self.assertEqual(expected_bytes[4:6],
2309
                         smart_protocol.read_body_bytes(2))
6973.7.8 by Jelmer Vernooij
Fix more tests.
2310
        self.assertEqual(expected_bytes[6:7], smart_protocol.read_body_bytes())
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2311
2312
    def test_client_cancel_read_body_does_not_eat_body_bytes(self):
2313
        # cancelling the expected body needs to finish the request, but not
2314
        # read any more bytes.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2315
        expected_bytes = b"1234567"
2316
        server_bytes = b"ok\n7\n1234567done\n"
2317
        input = BytesIO(server_bytes)
2318
        output = BytesIO()
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.
2319
        client_medium = medium.SmartSimplePipesClientMedium(
2320
            input, output, 'base')
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
2321
        request = client_medium.get_request()
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2322
        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2323
        smart_protocol.call(b'foo')
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2324
        smart_protocol.read_response_tuple(True)
2325
        smart_protocol.cancel_read_body()
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
2326
        self.assertEqual(3, input.tell())
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
2327
        self.assertRaises(
2328
            errors.ReadingCompleted, smart_protocol.read_body_bytes)
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
2329
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2330
    def test_client_read_body_bytes_interrupted_connection(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2331
        server_bytes = b"ok\n999\nincomplete body"
2332
        input = BytesIO(server_bytes)
2333
        output = BytesIO()
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2334
        client_medium = medium.SmartSimplePipesClientMedium(
2335
            input, output, 'base')
2336
        request = client_medium.get_request()
2337
        smart_protocol = self.client_protocol_class(request)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2338
        smart_protocol.call(b'foo')
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2339
        smart_protocol.read_response_tuple(True)
2340
        self.assertRaises(
2341
            errors.ConnectionReset, smart_protocol.read_body_bytes)
2342
2018.2.15 by Andrew Bennetts
Remove SmartServerRequestProtocolOne.finished_reading attribute, replace with next_read_size method.
2343
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2344
class TestVersionOneFeaturesInProtocolTwo(
7143.15.2 by Jelmer Vernooij
Run autopep8.
2345
        TestSmartProtocol, CommonSmartProtocolTestMixin):
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2346
    """Tests for version one smart protocol features as implemeted by version
2347
    two.
2432.2.1 by Andrew Bennetts
Add Smart{Client,Server}RequestProtocolTwo, that prefix args tuples with a version marker.
2348
    """
2349
2432.2.5 by Andrew Bennetts
Reduce duplication in test_smart_transport.
2350
    client_protocol_class = protocol.SmartClientRequestProtocolTwo
2351
    server_protocol_class = protocol.SmartServerRequestProtocolTwo
2432.2.1 by Andrew Bennetts
Add Smart{Client,Server}RequestProtocolTwo, that prefix args tuples with a version marker.
2352
2353
    def test_construct_version_two_server_protocol(self):
2354
        smart_protocol = protocol.SmartServerRequestProtocolTwo(None, None)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2355
        self.assertEqual(b'', smart_protocol.unused_data)
2356
        self.assertEqual(b'', smart_protocol.in_buffer)
3245.4.59 by Andrew Bennetts
Various tweaks in response to Martin's review.
2357
        self.assertFalse(smart_protocol._has_dispatched)
2432.2.1 by Andrew Bennetts
Add Smart{Client,Server}RequestProtocolTwo, that prefix args tuples with a version marker.
2358
        self.assertEqual(1, smart_protocol.next_read_size())
2359
2360
    def test_construct_version_two_client_protocol(self):
2361
        # we can construct a client protocol from a client medium request
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2362
        output = BytesIO()
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.
2363
        client_medium = medium.SmartSimplePipesClientMedium(
2364
            None, output, 'base')
2432.2.1 by Andrew Bennetts
Add Smart{Client,Server}RequestProtocolTwo, that prefix args tuples with a version marker.
2365
        request = client_medium.get_request()
2366
        client_protocol = protocol.SmartClientRequestProtocolTwo(request)
2367
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2368
    def test_accept_bytes_of_bad_request_to_protocol(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2369
        out_stream = BytesIO()
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2370
        smart_protocol = self.server_protocol_class(None, out_stream.write)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2371
        smart_protocol.accept_bytes(b'abc')
2372
        self.assertEqual(b'abc', smart_protocol.in_buffer)
2373
        smart_protocol.accept_bytes(b'\n')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2374
        self.assertEqual(
7143.15.2 by Jelmer Vernooij
Run autopep8.
2375
            self.response_marker
2376
            + b"failed\nerror\x01Generic bzr smart protocol error: bad request 'abc'\n",
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2377
            out_stream.getvalue())
3245.4.59 by Andrew Bennetts
Various tweaks in response to Martin's review.
2378
        self.assertTrue(smart_protocol._has_dispatched)
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2379
        self.assertEqual(0, smart_protocol.next_read_size())
2380
2381
    def test_accept_body_bytes_to_protocol(self):
2382
        protocol = self.build_protocol_waiting_for_body()
2383
        self.assertEqual(6, protocol.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2384
        protocol.accept_bytes(b'7\nabc')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2385
        self.assertEqual(9, protocol.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2386
        protocol.accept_bytes(b'defgd')
2387
        protocol.accept_bytes(b'one\n')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2388
        self.assertEqual(0, protocol.next_read_size())
2389
        self.assertTrue(self.end_received)
2390
2391
    def test_accept_request_and_body_all_at_once(self):
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
2392
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2393
        mem_transport = memory.MemoryTransport()
6973.7.8 by Jelmer Vernooij
Fix more tests.
2394
        mem_transport.put_bytes('foo', b'abcdefghij')
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2395
        out_stream = BytesIO()
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2396
        smart_protocol = self.server_protocol_class(
2397
            mem_transport, out_stream.write)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2398
        smart_protocol.accept_bytes(b'readv\x01foo\n3\n3,3done\n')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2399
        self.assertEqual(0, smart_protocol.next_read_size())
7143.15.2 by Jelmer Vernooij
Run autopep8.
2400
        self.assertEqual(self.response_marker
2401
                         + b'success\nreadv\n3\ndefdone\n',
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2402
                         out_stream.getvalue())
6973.7.8 by Jelmer Vernooij
Fix more tests.
2403
        self.assertEqual(b'', smart_protocol.unused_data)
2404
        self.assertEqual(b'', smart_protocol.in_buffer)
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2405
2406
    def test_accept_excess_bytes_are_preserved(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2407
        out_stream = BytesIO()
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2408
        smart_protocol = self.server_protocol_class(None, out_stream.write)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2409
        smart_protocol.accept_bytes(b'hello\nhello\n')
2410
        self.assertEqual(self.response_marker + b"success\nok\x012\n",
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2411
                         out_stream.getvalue())
6973.7.8 by Jelmer Vernooij
Fix more tests.
2412
        self.assertEqual(b"hello\n", smart_protocol.unused_data)
2413
        self.assertEqual(b"", smart_protocol.in_buffer)
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2414
2415
    def test_accept_excess_bytes_after_body(self):
2416
        # The excess bytes look like the start of another request.
2417
        server_protocol = self.build_protocol_waiting_for_body()
7143.15.2 by Jelmer Vernooij
Run autopep8.
2418
        server_protocol.accept_bytes(
2419
            b'7\nabcdefgdone\n' + self.response_marker)
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2420
        self.assertTrue(self.end_received)
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2421
        self.assertEqual(self.response_marker,
3245.4.21 by Andrew Bennetts
Remove 'excess_buffer' attribute and another crufty comment.
2422
                         server_protocol.unused_data)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2423
        self.assertEqual(b"", server_protocol.in_buffer)
2424
        server_protocol.accept_bytes(b'Y')
2425
        self.assertEqual(self.response_marker + b"Y",
3245.4.21 by Andrew Bennetts
Remove 'excess_buffer' attribute and another crufty comment.
2426
                         server_protocol.unused_data)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2427
        self.assertEqual(b"", server_protocol.in_buffer)
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2428
2429
    def test_accept_excess_bytes_after_dispatch(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2430
        out_stream = BytesIO()
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2431
        smart_protocol = self.server_protocol_class(None, out_stream.write)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2432
        smart_protocol.accept_bytes(b'hello\n')
2433
        self.assertEqual(self.response_marker + b"success\nok\x012\n",
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2434
                         out_stream.getvalue())
6973.7.8 by Jelmer Vernooij
Fix more tests.
2435
        smart_protocol.accept_bytes(self.request_marker + b'hel')
2436
        self.assertEqual(self.request_marker + b"hel",
2437
                         smart_protocol.unused_data)
2438
        smart_protocol.accept_bytes(b'lo\n')
2439
        self.assertEqual(self.request_marker + b"hello\n",
2440
                         smart_protocol.unused_data)
2441
        self.assertEqual(b"", smart_protocol.in_buffer)
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2442
2443
    def test__send_response_sets_finished_reading(self):
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2444
        smart_protocol = self.server_protocol_class(None, lambda x: None)
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2445
        self.assertEqual(1, smart_protocol.next_read_size())
2446
        smart_protocol._send_response(
6973.7.8 by Jelmer Vernooij
Fix more tests.
2447
            _mod_request.SuccessfulSmartServerResponse((b'x',)))
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2448
        self.assertEqual(0, smart_protocol.next_read_size())
2449
2450
    def test__send_response_errors_with_base_response(self):
2451
        """Ensure that only the Successful/Failed subclasses are used."""
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2452
        smart_protocol = self.server_protocol_class(None, lambda x: None)
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2453
        self.assertRaises(AttributeError, smart_protocol._send_response,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2454
                          _mod_request.SmartServerResponse((b'x',)))
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2455
2456
    def test_query_version(self):
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2457
        """query_version on a SmartClientProtocolTwo should return a number.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2458
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2459
        The protocol provides the query_version because the domain level clients
2460
        may all need to be able to probe for capabilities.
2461
        """
2462
        # What we really want to test here is that SmartClientProtocolTwo calls
2463
        # accept_bytes(tuple_based_encoding_of_hello) and reads and parses the
4031.3.1 by Frank Aspell
Fixing various typos
2464
        # response of tuple-encoded (ok, 1).  Also, separately we should test
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2465
        # the error if the response is a non-understood version.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2466
        input = BytesIO(self.response_marker + b'success\nok\x012\n')
2467
        output = BytesIO()
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.
2468
        client_medium = medium.SmartSimplePipesClientMedium(
2469
            input, output, 'base')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2470
        request = client_medium.get_request()
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2471
        smart_protocol = self.client_protocol_class(request)
3245.4.59 by Andrew Bennetts
Various tweaks in response to Martin's review.
2472
        self.assertEqual(2, smart_protocol.query_version())
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2473
2474
    def test_client_call_empty_response(self):
2475
        # protocol.call() can get back an empty tuple as a response. This occurs
2476
        # when the parsed line is an empty line, and results in a tuple with
2477
        # one element - an empty string.
2478
        self.assertServerToClientEncoding(
6973.7.8 by Jelmer Vernooij
Fix more tests.
2479
            self.response_marker + b'success\n\n', (b'', ), [(), (b'', )])
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2480
2481
    def test_client_call_three_element_response(self):
2482
        # protocol.call() can get back tuples of other lengths. A three element
2483
        # tuple should be unpacked as three strings.
2484
        self.assertServerToClientEncoding(
6973.7.8 by Jelmer Vernooij
Fix more tests.
2485
            self.response_marker + b'success\na\x01b\x0134\n',
2486
            (b'a', b'b', b'34'),
2487
            [(b'a', b'b', b'34')])
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2488
2489
    def test_client_call_with_body_bytes_uploads(self):
2490
        # protocol.call_with_body_bytes should length-prefix the bytes onto the
2491
        # wire.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2492
        expected_bytes = self.request_marker + b"foo\n7\nabcdefgdone\n"
2493
        input = BytesIO(b"\n")
2494
        output = BytesIO()
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.
2495
        client_medium = medium.SmartSimplePipesClientMedium(
2496
            input, output, 'base')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2497
        request = client_medium.get_request()
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2498
        smart_protocol = self.client_protocol_class(request)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2499
        smart_protocol.call_with_body_bytes((b'foo', ), b"abcdefg")
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2500
        self.assertEqual(expected_bytes, output.getvalue())
2501
2502
    def test_client_call_with_body_readv_array(self):
2503
        # protocol.call_with_upload should encode the readv array and then
2504
        # length-prefix the bytes onto the wire.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2505
        expected_bytes = self.request_marker + b"foo\n7\n1,2\n5,6done\n"
2506
        input = BytesIO(b"\n")
2507
        output = BytesIO()
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.
2508
        client_medium = medium.SmartSimplePipesClientMedium(
2509
            input, output, 'base')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2510
        request = client_medium.get_request()
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2511
        smart_protocol = self.client_protocol_class(request)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2512
        smart_protocol.call_with_body_readv_array((b'foo', ), [(1, 2), (5, 6)])
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2513
        self.assertEqual(expected_bytes, output.getvalue())
2514
2515
    def test_client_read_body_bytes_all(self):
2516
        # read_body_bytes should decode the body bytes from the wire into
2517
        # a response.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2518
        expected_bytes = b"1234567"
7143.15.2 by Jelmer Vernooij
Run autopep8.
2519
        server_bytes = (self.response_marker
2520
                        + b"success\nok\n7\n1234567done\n")
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2521
        input = BytesIO(server_bytes)
2522
        output = BytesIO()
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.
2523
        client_medium = medium.SmartSimplePipesClientMedium(
2524
            input, output, 'base')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2525
        request = client_medium.get_request()
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2526
        smart_protocol = self.client_protocol_class(request)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2527
        smart_protocol.call(b'foo')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2528
        smart_protocol.read_response_tuple(True)
2529
        self.assertEqual(expected_bytes, smart_protocol.read_body_bytes())
2530
2531
    def test_client_read_body_bytes_incremental(self):
2532
        # test reading a few bytes at a time from the body
2533
        # XXX: possibly we should test dribbling the bytes into the stringio
2534
        # to make the state machine work harder: however, as we use the
2535
        # LengthPrefixedBodyDecoder that is already well tested - we can skip
2536
        # that.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2537
        expected_bytes = b"1234567"
2538
        server_bytes = self.response_marker + b"success\nok\n7\n1234567done\n"
2539
        input = BytesIO(server_bytes)
2540
        output = BytesIO()
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.
2541
        client_medium = medium.SmartSimplePipesClientMedium(
2542
            input, output, 'base')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2543
        request = client_medium.get_request()
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2544
        smart_protocol = self.client_protocol_class(request)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2545
        smart_protocol.call(b'foo')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2546
        smart_protocol.read_response_tuple(True)
7143.15.2 by Jelmer Vernooij
Run autopep8.
2547
        self.assertEqual(expected_bytes[0:2],
2548
                         smart_protocol.read_body_bytes(2))
2549
        self.assertEqual(expected_bytes[2:4],
2550
                         smart_protocol.read_body_bytes(2))
2551
        self.assertEqual(expected_bytes[4:6],
2552
                         smart_protocol.read_body_bytes(2))
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
2553
        self.assertEqual(expected_bytes[6:7], smart_protocol.read_body_bytes())
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2554
2555
    def test_client_cancel_read_body_does_not_eat_body_bytes(self):
2556
        # cancelling the expected body needs to finish the request, but not
2557
        # read any more bytes.
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2558
        server_bytes = self.response_marker + b"success\nok\n7\n1234567done\n"
2559
        input = BytesIO(server_bytes)
2560
        output = BytesIO()
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.
2561
        client_medium = medium.SmartSimplePipesClientMedium(
2562
            input, output, 'base')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2563
        request = client_medium.get_request()
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2564
        smart_protocol = self.client_protocol_class(request)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2565
        smart_protocol.call(b'foo')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2566
        smart_protocol.read_response_tuple(True)
2567
        smart_protocol.cancel_read_body()
6973.7.8 by Jelmer Vernooij
Fix more tests.
2568
        self.assertEqual(len(self.response_marker + b'success\nok\n'),
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2569
                         input.tell())
2570
        self.assertRaises(
2571
            errors.ReadingCompleted, smart_protocol.read_body_bytes)
2572
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2573
    def test_client_read_body_bytes_interrupted_connection(self):
7143.15.2 by Jelmer Vernooij
Run autopep8.
2574
        server_bytes = (self.response_marker
2575
                        + b"success\nok\n999\nincomplete body")
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2576
        input = BytesIO(server_bytes)
2577
        output = BytesIO()
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2578
        client_medium = medium.SmartSimplePipesClientMedium(
2579
            input, output, 'base')
2580
        request = client_medium.get_request()
2581
        smart_protocol = self.client_protocol_class(request)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2582
        smart_protocol.call(b'foo')
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2583
        smart_protocol.read_response_tuple(True)
2584
        self.assertRaises(
2585
            errors.ConnectionReset, smart_protocol.read_body_bytes)
2586
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2587
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2588
class TestSmartProtocolTwoSpecificsMixin(object):
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2589
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
2590
    def assertBodyStreamSerialisation(self, expected_serialisation,
2591
                                      body_stream):
2592
        """Assert that body_stream is serialised as expected_serialisation."""
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2593
        out_stream = BytesIO()
2748.4.10 by Andrew Bennetts
Fix chunking serialisation to be current with the latest changes to the protocol, and improve the tests to make it harder to have them desynchronised.
2594
        protocol._send_stream(body_stream, out_stream.write)
2748.4.4 by Andrew Bennetts
Extract a _send_chunks function to make testing easier.
2595
        self.assertEqual(expected_serialisation, out_stream.getvalue())
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
2596
2748.4.10 by Andrew Bennetts
Fix chunking serialisation to be current with the latest changes to the protocol, and improve the tests to make it harder to have them desynchronised.
2597
    def assertBodyStreamRoundTrips(self, body_stream):
2598
        """Assert that body_stream is the same after being serialised and
2599
        deserialised.
2600
        """
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2601
        out_stream = BytesIO()
2748.4.10 by Andrew Bennetts
Fix chunking serialisation to be current with the latest changes to the protocol, and improve the tests to make it harder to have them desynchronised.
2602
        protocol._send_stream(body_stream, out_stream.write)
2603
        decoder = protocol.ChunkedBodyDecoder()
2604
        decoder.accept_bytes(out_stream.getvalue())
2605
        decoded_stream = list(iter(decoder.read_next_chunk, None))
2606
        self.assertEqual(body_stream, decoded_stream)
2607
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
2608
    def test_body_stream_serialisation_empty(self):
2609
        """A body_stream with no bytes can be serialised."""
6973.7.8 by Jelmer Vernooij
Fix more tests.
2610
        self.assertBodyStreamSerialisation(b'chunked\nEND\n', [])
2748.4.10 by Andrew Bennetts
Fix chunking serialisation to be current with the latest changes to the protocol, and improve the tests to make it harder to have them desynchronised.
2611
        self.assertBodyStreamRoundTrips([])
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
2612
2613
    def test_body_stream_serialisation(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
2614
        stream = [b'chunk one', b'chunk two', b'chunk three']
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
2615
        self.assertBodyStreamSerialisation(
7143.15.2 by Jelmer Vernooij
Run autopep8.
2616
            b'chunked\n' + b'9\nchunk one' + b'9\nchunk two' + b'b\nchunk three'
2617
            + b'END\n',
2748.4.10 by Andrew Bennetts
Fix chunking serialisation to be current with the latest changes to the protocol, and improve the tests to make it harder to have them desynchronised.
2618
            stream)
2619
        self.assertBodyStreamRoundTrips(stream)
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
2620
2621
    def test_body_stream_with_empty_element_serialisation(self):
2748.4.7 by Andrew Bennetts
Change the end-of-body marker to something clearer than a zero-length chunk.
2622
        """A body stream can include ''.
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
2623
2748.4.7 by Andrew Bennetts
Change the end-of-body marker to something clearer than a zero-length chunk.
2624
        The empty string can be transmitted like any other string.
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
2625
        """
6973.7.8 by Jelmer Vernooij
Fix more tests.
2626
        stream = [b'', b'chunk']
2748.4.7 by Andrew Bennetts
Change the end-of-body marker to something clearer than a zero-length chunk.
2627
        self.assertBodyStreamSerialisation(
6973.7.8 by Jelmer Vernooij
Fix more tests.
2628
            b'chunked\n' + b'0\n' + b'5\nchunk' + b'END\n', stream)
2748.4.10 by Andrew Bennetts
Fix chunking serialisation to be current with the latest changes to the protocol, and improve the tests to make it harder to have them desynchronised.
2629
        self.assertBodyStreamRoundTrips(stream)
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
2630
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
2631
    def test_body_stream_error_serialistion(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
2632
        stream = [b'first chunk',
2692.1.2 by Andrew Bennetts
Merge from bzr.dev.
2633
                  _mod_request.FailedSmartServerResponse(
6973.7.8 by Jelmer Vernooij
Fix more tests.
2634
                      (b'FailureName', b'failure arg'))]
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
2635
        expected_bytes = (
7143.15.2 by Jelmer Vernooij
Run autopep8.
2636
            b'chunked\n' + b'b\nfirst chunk'
2637
            + b'ERR\n' + b'b\nFailureName' + b'b\nfailure arg'
2638
            + b'END\n')
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
2639
        self.assertBodyStreamSerialisation(expected_bytes, stream)
2748.4.10 by Andrew Bennetts
Fix chunking serialisation to be current with the latest changes to the protocol, and improve the tests to make it harder to have them desynchronised.
2640
        self.assertBodyStreamRoundTrips(stream)
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
2641
2432.4.6 by Robert Collins
Include success/failure feedback in SmartProtocolTwo responses to allow robust handling in the future.
2642
    def test__send_response_includes_failure_marker(self):
2643
        """FailedSmartServerResponse have 'failed\n' after the version."""
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2644
        out_stream = BytesIO()
2432.4.6 by Robert Collins
Include success/failure feedback in SmartProtocolTwo responses to allow robust handling in the future.
2645
        smart_protocol = protocol.SmartServerRequestProtocolTwo(
2646
            None, out_stream.write)
2647
        smart_protocol._send_response(
6973.7.8 by Jelmer Vernooij
Fix more tests.
2648
            _mod_request.FailedSmartServerResponse((b'x',)))
2649
        self.assertEqual(protocol.RESPONSE_VERSION_TWO + b'failed\nx\n',
2432.3.6 by Andrew Bennetts
Fix a couple of test failures introduced by the previous merge.
2650
                         out_stream.getvalue())
2432.4.6 by Robert Collins
Include success/failure feedback in SmartProtocolTwo responses to allow robust handling in the future.
2651
2652
    def test__send_response_includes_success_marker(self):
2653
        """SuccessfulSmartServerResponse have 'success\n' after the version."""
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2654
        out_stream = BytesIO()
2432.4.6 by Robert Collins
Include success/failure feedback in SmartProtocolTwo responses to allow robust handling in the future.
2655
        smart_protocol = protocol.SmartServerRequestProtocolTwo(
2656
            None, out_stream.write)
2657
        smart_protocol._send_response(
6973.7.8 by Jelmer Vernooij
Fix more tests.
2658
            _mod_request.SuccessfulSmartServerResponse((b'x',)))
2659
        self.assertEqual(protocol.RESPONSE_VERSION_TWO + b'success\nx\n',
2432.3.6 by Andrew Bennetts
Fix a couple of test failures introduced by the previous merge.
2660
                         out_stream.getvalue())
2432.4.6 by Robert Collins
Include success/failure feedback in SmartProtocolTwo responses to allow robust handling in the future.
2661
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2662
    def test__send_response_with_body_stream_sets_finished_reading(self):
2663
        smart_protocol = protocol.SmartServerRequestProtocolTwo(
2664
            None, lambda x: None)
2665
        self.assertEqual(1, smart_protocol.next_read_size())
2666
        smart_protocol._send_response(
6973.7.8 by Jelmer Vernooij
Fix more tests.
2667
            _mod_request.SuccessfulSmartServerResponse((b'x',), body_stream=[]))
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2668
        self.assertEqual(0, smart_protocol.next_read_size())
2432.2.1 by Andrew Bennetts
Add Smart{Client,Server}RequestProtocolTwo, that prefix args tuples with a version marker.
2669
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
2670
    def test_streamed_body_bytes(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
2671
        body_header = b'chunked\n'
2672
        two_body_chunks = b"4\n1234" + b"3\n567"
2673
        body_terminator = b"END\n"
7143.15.2 by Jelmer Vernooij
Run autopep8.
2674
        server_bytes = (protocol.RESPONSE_VERSION_TWO
2675
                        + b"success\nok\n" + body_header + two_body_chunks
2676
                        + body_terminator)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2677
        input = BytesIO(server_bytes)
2678
        output = BytesIO()
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.
2679
        client_medium = medium.SmartSimplePipesClientMedium(
2680
            input, output, 'base')
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
2681
        request = client_medium.get_request()
2682
        smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2683
        smart_protocol.call(b'foo')
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
2684
        smart_protocol.read_response_tuple(True)
2685
        stream = smart_protocol.read_streamed_body()
6973.7.8 by Jelmer Vernooij
Fix more tests.
2686
        self.assertEqual([b'1234', b'567'], list(stream))
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
2687
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
2688
    def test_read_streamed_body_error(self):
2689
        """When a stream is interrupted by an error..."""
6973.7.8 by Jelmer Vernooij
Fix more tests.
2690
        body_header = b'chunked\n'
2691
        a_body_chunk = b'4\naaaa'
2692
        err_signal = b'ERR\n'
2693
        err_chunks = b'a\nerror arg1' + b'4\narg2'
2694
        finish = b'END\n'
2748.4.16 by Andrew Bennetts
Tweaks suggested by review.
2695
        body = body_header + a_body_chunk + err_signal + err_chunks + finish
7143.15.2 by Jelmer Vernooij
Run autopep8.
2696
        server_bytes = (protocol.RESPONSE_VERSION_TWO
2697
                        + b"success\nok\n" + body)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2698
        input = BytesIO(server_bytes)
2699
        output = BytesIO()
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.
2700
        client_medium = medium.SmartSimplePipesClientMedium(
2701
            input, output, 'base')
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
2702
        smart_request = client_medium.get_request()
2703
        smart_protocol = protocol.SmartClientRequestProtocolTwo(smart_request)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2704
        smart_protocol.call(b'foo')
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
2705
        smart_protocol.read_response_tuple(True)
2706
        expected_chunks = [
6973.7.8 by Jelmer Vernooij
Fix more tests.
2707
            b'aaaa',
2708
            _mod_request.FailedSmartServerResponse((b'error arg1', b'arg2'))]
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
2709
        stream = smart_protocol.read_streamed_body()
2710
        self.assertEqual(expected_chunks, list(stream))
2711
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2712
    def test_streamed_body_bytes_interrupted_connection(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
2713
        body_header = b'chunked\n'
2714
        incomplete_body_chunk = b"9999\nincomplete chunk"
7143.15.2 by Jelmer Vernooij
Run autopep8.
2715
        server_bytes = (protocol.RESPONSE_VERSION_TWO
2716
                        + b"success\nok\n" + body_header + incomplete_body_chunk)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2717
        input = BytesIO(server_bytes)
2718
        output = BytesIO()
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2719
        client_medium = medium.SmartSimplePipesClientMedium(
2720
            input, output, 'base')
2721
        request = client_medium.get_request()
2722
        smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2723
        smart_protocol.call(b'foo')
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2724
        smart_protocol.read_response_tuple(True)
2725
        stream = smart_protocol.read_streamed_body()
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
2726
        self.assertRaises(errors.ConnectionReset, next, stream)
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2727
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2728
    def test_client_read_response_tuple_sets_response_status(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
2729
        server_bytes = protocol.RESPONSE_VERSION_TWO + b"success\nok\n"
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2730
        input = BytesIO(server_bytes)
2731
        output = BytesIO()
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.
2732
        client_medium = medium.SmartSimplePipesClientMedium(
2733
            input, output, 'base')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2734
        request = client_medium.get_request()
2735
        smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2736
        smart_protocol.call(b'foo')
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2737
        smart_protocol.read_response_tuple(False)
2738
        self.assertEqual(True, smart_protocol.response_status)
2739
3245.4.55 by Andrew Bennetts
Test improvements suggested by John's review.
2740
    def test_client_read_response_tuple_raises_UnknownSmartMethod(self):
2741
        """read_response_tuple raises UnknownSmartMethod if the response says
2742
        the server did not recognise the request.
2743
        """
2744
        server_bytes = (
7143.15.2 by Jelmer Vernooij
Run autopep8.
2745
            protocol.RESPONSE_VERSION_TWO
2746
            + b"failed\n"
2747
            + b"error\x01Generic bzr smart protocol error: bad request 'foo'\n")
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2748
        input = BytesIO(server_bytes)
2749
        output = BytesIO()
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.
2750
        client_medium = medium.SmartSimplePipesClientMedium(
2751
            input, output, 'base')
3245.4.55 by Andrew Bennetts
Test improvements suggested by John's review.
2752
        request = client_medium.get_request()
2753
        smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2754
        smart_protocol.call(b'foo')
3245.4.55 by Andrew Bennetts
Test improvements suggested by John's review.
2755
        self.assertRaises(
2756
            errors.UnknownSmartMethod, smart_protocol.read_response_tuple)
2757
        # The request has been finished.  There is no body to read, and
2758
        # attempts to read one will fail.
2759
        self.assertRaises(
2760
            errors.ReadingCompleted, smart_protocol.read_body_bytes)
2761
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2762
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2763
class TestSmartProtocolTwoSpecifics(
2764
        TestSmartProtocol, TestSmartProtocolTwoSpecificsMixin):
2765
    """Tests for aspects of smart protocol version two that are unique to
2766
    version two.
2767
2768
    Thus tests involving body streams and success/failure markers belong here.
2769
    """
2770
2771
    client_protocol_class = protocol.SmartClientRequestProtocolTwo
2772
    server_protocol_class = protocol.SmartServerRequestProtocolTwo
2773
2774
2775
class TestVersionOneFeaturesInProtocolThree(
7143.15.2 by Jelmer Vernooij
Run autopep8.
2776
        TestSmartProtocol, CommonSmartProtocolTestMixin):
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2777
    """Tests for version one smart protocol features as implemented by version
2778
    three.
2779
    """
2780
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
2781
    request_encoder = protocol.ProtocolThreeRequester
2782
    response_decoder = protocol.ProtocolThreeDecoder
3245.4.4 by Andrew Bennetts
Fix a KnownFailure.
2783
    # build_server_protocol_three is a function, so we can't set it as a class
2784
    # attribute directly, because then Python will assume it is actually a
3245.4.10 by Andrew Bennetts
Use a less ugly hack for TestVersionOneFeaturesInProtocolThree.server_protocol_class.
2785
    # method.  So we make server_protocol_class be a static method, rather than
2786
    # simply doing:
3245.4.4 by Andrew Bennetts
Fix a KnownFailure.
2787
    # "server_protocol_class = protocol.build_server_protocol_three".
3245.4.10 by Andrew Bennetts
Use a less ugly hack for TestVersionOneFeaturesInProtocolThree.server_protocol_class.
2788
    server_protocol_class = staticmethod(protocol.build_server_protocol_three)
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2789
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
2790
    def setUp(self):
2791
        super(TestVersionOneFeaturesInProtocolThree, self).setUp()
2792
        self.response_marker = protocol.MESSAGE_VERSION_THREE
2793
        self.request_marker = protocol.MESSAGE_VERSION_THREE
2794
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2795
    def test_construct_version_three_server_protocol(self):
3245.4.7 by Andrew Bennetts
Rename _ProtocolThreeBase to ProtocolThreeDecoder, remove SmartServerRequestProtocolThree.
2796
        smart_protocol = protocol.ProtocolThreeDecoder(None)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2797
        self.assertEqual(b'', smart_protocol.unused_data)
3649.5.5 by John Arbash Meinel
Fix the test suite.
2798
        self.assertEqual([], smart_protocol._in_buffer_list)
2799
        self.assertEqual(0, smart_protocol._in_buffer_len)
3245.4.59 by Andrew Bennetts
Various tweaks in response to Martin's review.
2800
        self.assertFalse(smart_protocol._has_dispatched)
3195.3.19 by Andrew Bennetts
Remove a stray pdb, fix a test.
2801
        # The protocol starts by expecting four bytes, a length prefix for the
2802
        # headers.
2803
        self.assertEqual(4, smart_protocol.next_read_size())
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2804
2805
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2806
class LoggingMessageHandler(object):
2807
2808
    def __init__(self):
2809
        self.event_log = []
2810
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
2811
    def _log(self, *args):
2812
        self.event_log.append(args)
2813
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2814
    def headers_received(self, headers):
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
2815
        self._log('headers', headers)
2816
2817
    def protocol_error(self, exception):
2818
        self._log('protocol_error', exception)
2819
2820
    def byte_part_received(self, byte):
2821
        self._log('byte', byte)
2822
2823
    def bytes_part_received(self, bytes):
2824
        self._log('bytes', bytes)
2825
2826
    def structure_part_received(self, structure):
2827
        self._log('structure', structure)
2828
2829
    def end_received(self):
2830
        self._log('end')
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2831
2832
2833
class TestProtocolThree(TestSmartProtocol):
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2834
    """Tests for v3 of the server-side protocol."""
2835
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
2836
    request_encoder = protocol.ProtocolThreeRequester
2837
    response_decoder = protocol.ProtocolThreeDecoder
3245.4.7 by Andrew Bennetts
Rename _ProtocolThreeBase to ProtocolThreeDecoder, remove SmartServerRequestProtocolThree.
2838
    server_protocol_class = protocol.ProtocolThreeDecoder
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2839
2840
    def test_trivial_request(self):
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2841
        """Smoke test for the simplest possible v3 request: empty headers, no
2842
        message parts.
3195.3.1 by Andrew Bennetts
Add TestProtocolTestCoverage.
2843
        """
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2844
        output = BytesIO()
6973.7.8 by Jelmer Vernooij
Fix more tests.
2845
        headers = b'\0\0\0\x02de'  # length-prefixed, bencoded empty dict
2846
        end = b'e'
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2847
        request_bytes = headers + end
2848
        smart_protocol = self.server_protocol_class(LoggingMessageHandler())
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2849
        smart_protocol.accept_bytes(request_bytes)
2850
        self.assertEqual(0, smart_protocol.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
2851
        self.assertEqual(b'', smart_protocol.unused_data)
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2852
4515.1.1 by Andrew Bennetts
Fix bug in HPSS v3 decoder when receiving multiple lots of excess bytes.
2853
    def test_repeated_excess(self):
2854
        """Repeated calls to accept_bytes after the message end has been parsed
2855
        accumlates the bytes in the unused_data attribute.
2856
        """
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2857
        output = BytesIO()
6973.7.8 by Jelmer Vernooij
Fix more tests.
2858
        headers = b'\0\0\0\x02de'  # length-prefixed, bencoded empty dict
2859
        end = b'e'
4515.1.1 by Andrew Bennetts
Fix bug in HPSS v3 decoder when receiving multiple lots of excess bytes.
2860
        request_bytes = headers + end
2861
        smart_protocol = self.server_protocol_class(LoggingMessageHandler())
2862
        smart_protocol.accept_bytes(request_bytes)
6973.7.8 by Jelmer Vernooij
Fix more tests.
2863
        self.assertEqual(b'', smart_protocol.unused_data)
2864
        smart_protocol.accept_bytes(b'aaa')
2865
        self.assertEqual(b'aaa', smart_protocol.unused_data)
2866
        smart_protocol.accept_bytes(b'bbb')
2867
        self.assertEqual(b'aaabbb', smart_protocol.unused_data)
4515.1.1 by Andrew Bennetts
Fix bug in HPSS v3 decoder when receiving multiple lots of excess bytes.
2868
        self.assertEqual(0, smart_protocol.next_read_size())
2869
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2870
    def make_protocol_expecting_message_part(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
2871
        headers = b'\0\0\0\x02de'  # length-prefixed, bencoded empty dict
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2872
        message_handler = LoggingMessageHandler()
2873
        smart_protocol = self.server_protocol_class(message_handler)
2874
        smart_protocol.accept_bytes(headers)
2875
        # Clear the event log
2876
        del message_handler.event_log[:]
2877
        return smart_protocol, message_handler.event_log
2878
2879
    def test_decode_one_byte(self):
2880
        """The protocol can decode a 'one byte' message part."""
2881
        smart_protocol, event_log = self.make_protocol_expecting_message_part()
6973.7.8 by Jelmer Vernooij
Fix more tests.
2882
        smart_protocol.accept_bytes(b'ox')
2883
        self.assertEqual([('byte', b'x')], event_log)
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2884
2885
    def test_decode_bytes(self):
2886
        """The protocol can decode a 'bytes' message part."""
2887
        smart_protocol, event_log = self.make_protocol_expecting_message_part()
2888
        smart_protocol.accept_bytes(
7143.15.2 by Jelmer Vernooij
Run autopep8.
2889
            b'b'  # message part kind
2890
            b'\0\0\0\x07'  # length prefix
2891
            b'payload'  # payload
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2892
            )
6973.7.8 by Jelmer Vernooij
Fix more tests.
2893
        self.assertEqual([('bytes', b'payload')], event_log)
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2894
2895
    def test_decode_structure(self):
2896
        """The protocol can decode a 'structure' message part."""
2897
        smart_protocol, event_log = self.make_protocol_expecting_message_part()
2898
        smart_protocol.accept_bytes(
7143.15.2 by Jelmer Vernooij
Run autopep8.
2899
            b's'  # message part kind
2900
            b'\0\0\0\x07'  # length prefix
2901
            b'l3:ARGe'  # ['ARG']
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2902
            )
6973.7.8 by Jelmer Vernooij
Fix more tests.
2903
        self.assertEqual([('structure', (b'ARG',))], event_log)
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2904
2905
    def test_decode_multiple_bytes(self):
2906
        """The protocol can decode a multiple 'bytes' message parts."""
2907
        smart_protocol, event_log = self.make_protocol_expecting_message_part()
2908
        smart_protocol.accept_bytes(
7143.15.2 by Jelmer Vernooij
Run autopep8.
2909
            b'b'  # message part kind
2910
            b'\0\0\0\x05'  # length prefix
2911
            b'first'  # payload
2912
            b'b'  # message part kind
6973.7.8 by Jelmer Vernooij
Fix more tests.
2913
            b'\0\0\0\x06'
2914
            b'second'
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2915
            )
2916
        self.assertEqual(
6973.7.8 by Jelmer Vernooij
Fix more tests.
2917
            [('bytes', b'first'), ('bytes', b'second')], event_log)
3195.3.16 by Andrew Bennetts
Update tests for revised v3 spec.
2918
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
2919
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
2920
class TestConventionalResponseHandlerBodyStream(tests.TestCase):
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
2921
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2922
    def make_response_handler(self, response_bytes):
6670.4.16 by Jelmer Vernooij
Move smart to breezy.bzr.
2923
        from breezy.bzr.smart.message import ConventionalResponseHandler
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
2924
        response_handler = ConventionalResponseHandler()
3245.4.7 by Andrew Bennetts
Rename _ProtocolThreeBase to ProtocolThreeDecoder, remove SmartServerRequestProtocolThree.
2925
        protocol_decoder = protocol.ProtocolThreeDecoder(response_handler)
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
2926
        # put decoder in desired state (waiting for message parts)
2927
        protocol_decoder.state_accept = protocol_decoder._state_accept_expecting_message_part
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2928
        output = BytesIO()
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
2929
        client_medium = medium.SmartSimplePipesClientMedium(
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2930
            BytesIO(response_bytes), output, 'base')
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
2931
        medium_request = client_medium.get_request()
2932
        medium_request.finished_writing()
3245.4.26 by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers.
2933
        response_handler.setProtoAndMediumRequest(
2934
            protocol_decoder, medium_request)
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2935
        return response_handler
2936
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
2937
    def test_interrupted_by_error(self):
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2938
        response_handler = self.make_response_handler(interrupted_body_stream)
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
2939
        stream = response_handler.read_streamed_body()
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
2940
        self.assertEqual(b'aaa', next(stream))
2941
        self.assertEqual(b'bbb', next(stream))
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
2942
        exc = self.assertRaises(errors.ErrorFromSmartServer, next, stream)
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
2943
        self.assertEqual((b'error', b'Exception', b'Boom!'), exc.error_tuple)
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
2944
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
2945
    def test_interrupted_by_connection_lost(self):
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2946
        interrupted_body_stream = (
7143.15.2 by Jelmer Vernooij
Run autopep8.
2947
            b'oS'  # successful response
2948
            b's\0\0\0\x02le'  # empty args
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
2949
            b'b\0\0\xff\xffincomplete chunk')
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2950
        response_handler = self.make_response_handler(interrupted_body_stream)
2951
        stream = response_handler.read_streamed_body()
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
2952
        self.assertRaises(errors.ConnectionReset, next, stream)
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2953
2954
    def test_read_body_bytes_interrupted_by_connection_lost(self):
2955
        interrupted_body_stream = (
7143.15.2 by Jelmer Vernooij
Run autopep8.
2956
            b'oS'  # successful response
2957
            b's\0\0\0\x02le'  # empty args
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
2958
            b'b\0\0\xff\xffincomplete chunk')
3464.4.1 by Andrew Bennetts
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.
2959
        response_handler = self.make_response_handler(interrupted_body_stream)
2960
        self.assertRaises(
2961
            errors.ConnectionReset, response_handler.read_body_bytes)
2962
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
2963
    def test_multiple_bytes_parts(self):
2964
        multiple_bytes_parts = (
7143.15.2 by Jelmer Vernooij
Run autopep8.
2965
            b'oS'  # successful response
2966
            b's\0\0\0\x02le'  # empty args
2967
            b'b\0\0\0\x0bSome bytes\n'  # some bytes
2968
            b'b\0\0\0\x0aMore bytes'  # more bytes
2969
            b'e'  # message end
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
2970
            )
2971
        response_handler = self.make_response_handler(multiple_bytes_parts)
2972
        self.assertEqual(
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
2973
            b'Some bytes\nMore bytes', response_handler.read_body_bytes())
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
2974
        response_handler = self.make_response_handler(multiple_bytes_parts)
2975
        self.assertEqual(
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
2976
            [b'Some bytes\n', b'More bytes'],
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
2977
            list(response_handler.read_streamed_body()))
2978
2979
3923.5.6 by Andrew Bennetts
Fix a style nit.
2980
class FakeResponder(object):
2981
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
2982
    response_sent = False
3923.5.6 by Andrew Bennetts
Fix a style nit.
2983
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
2984
    def send_error(self, exc):
2985
        raise exc
3923.5.6 by Andrew Bennetts
Fix a style nit.
2986
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
2987
    def send_response(self, response):
2988
        pass
2989
2990
2991
class TestConventionalRequestHandlerBodyStream(tests.TestCase):
2992
    """Tests for ConventionalRequestHandler's handling of request bodies."""
2993
2994
    def make_request_handler(self, request_bytes):
2995
        """Make a ConventionalRequestHandler for the given bytes using test
2996
        doubles for the request_handler and the responder.
2997
        """
6670.4.16 by Jelmer Vernooij
Move smart to breezy.bzr.
2998
        from breezy.bzr.smart.message import ConventionalRequestHandler
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
2999
        request_handler = InstrumentedRequestHandler()
7143.15.2 by Jelmer Vernooij
Run autopep8.
3000
        request_handler.response = _mod_request.SuccessfulSmartServerResponse(
3001
            (b'arg', b'arg'))
3923.5.6 by Andrew Bennetts
Fix a style nit.
3002
        responder = FakeResponder()
7143.15.2 by Jelmer Vernooij
Run autopep8.
3003
        message_handler = ConventionalRequestHandler(
3004
            request_handler, responder)
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
3005
        protocol_decoder = protocol.ProtocolThreeDecoder(message_handler)
3006
        # put decoder in desired state (waiting for message parts)
3007
        protocol_decoder.state_accept = protocol_decoder._state_accept_expecting_message_part
3008
        protocol_decoder.accept_bytes(request_bytes)
3009
        return request_handler
3010
3011
    def test_multiple_bytes_parts(self):
3012
        """Each bytes part triggers a call to the request_handler's
3013
        accept_body method.
3014
        """
3015
        multiple_bytes_parts = (
7143.15.2 by Jelmer Vernooij
Run autopep8.
3016
            b's\0\0\0\x07l3:fooe'  # args
3017
            b'b\0\0\0\x0bSome bytes\n'  # some bytes
3018
            b'b\0\0\0\x0aMore bytes'  # more bytes
3019
            b'e'  # message end
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
3020
            )
3021
        request_handler = self.make_request_handler(multiple_bytes_parts)
3022
        accept_body_calls = [
3023
            call_info[1] for call_info in request_handler.calls
3024
            if call_info[0] == 'accept_body']
3025
        self.assertEqual(
6973.7.8 by Jelmer Vernooij
Fix more tests.
3026
            [b'Some bytes\n', b'More bytes'], accept_body_calls)
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
3027
3923.5.4 by Andrew Bennetts
Allow a request's body part(s) to be followed by an error.
3028
    def test_error_flag_after_body(self):
3029
        body_then_error = (
7143.15.2 by Jelmer Vernooij
Run autopep8.
3030
            b's\0\0\0\x07l3:fooe'  # request args
3031
            b'b\0\0\0\x0bSome bytes\n'  # some bytes
3032
            b'b\0\0\0\x0aMore bytes'  # more bytes
3033
            b'oE'  # error flag
3034
            b's\0\0\0\x07l3:bare'  # error args
3035
            b'e'  # message end
3923.5.4 by Andrew Bennetts
Allow a request's body part(s) to be followed by an error.
3036
            )
3037
        request_handler = self.make_request_handler(body_then_error)
3038
        self.assertEqual(
6973.7.8 by Jelmer Vernooij
Fix more tests.
3039
            [('post_body_error_received', (b'bar',)), ('end_received',)],
3923.5.4 by Andrew Bennetts
Allow a request's body part(s) to be followed by an error.
3040
            request_handler.calls[-2:])
3041
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
3042
3245.4.49 by Andrew Bennetts
Distinguish between errors in decoding a message into message parts from errors in handling decoded message parts, and use that to make sure that entire requests are read even when they result in exceptions.
3043
class TestMessageHandlerErrors(tests.TestCase):
3044
    """Tests for v3 that unrecognised (but well-formed) requests/responses are
3045
    still fully read off the wire, so that subsequent requests/responses on the
3046
    same medium can be decoded.
3047
    """
3048
3049
    def test_non_conventional_request(self):
3050
        """ConventionalRequestHandler (the default message handler on the
3051
        server side) will reject an unconventional message, but still consume
3052
        all the bytes of that message and signal when it has done so.
3053
3054
        This is what allows a server to continue to accept requests after the
3055
        client sends a completely unrecognised request.
3056
        """
3057
        # Define an invalid request (but one that is a well-formed message).
3058
        # This particular invalid request not only lacks the mandatory
3059
        # verb+args tuple, it has a single-byte part, which is forbidden.  In
3060
        # fact it has that part twice, to trigger multiple errors.
3061
        invalid_request = (
7143.15.2 by Jelmer Vernooij
Run autopep8.
3062
            protocol.MESSAGE_VERSION_THREE  # protocol version marker
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
3063
            + b'\0\0\0\x02de'  # empty headers
7143.15.13 by Jelmer Vernooij
Fix more syntax errors.
3064
            + b'oX' +  # a single byte part: 'X'.  ConventionalRequestHandler will
7143.15.2 by Jelmer Vernooij
Run autopep8.
3065
            # error at this part.
7143.16.21 by Jelmer Vernooij
Fix regressions.
3066
            b'oX' +  # and again.
7143.15.13 by Jelmer Vernooij
Fix more syntax errors.
3067
            b'e'  # end of message
3245.4.49 by Andrew Bennetts
Distinguish between errors in decoding a message into message parts from errors in handling decoded message parts, and use that to make sure that entire requests are read even when they result in exceptions.
3068
            )
3069
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
3070
        to_server = BytesIO(invalid_request)
3071
        from_server = BytesIO()
3245.4.49 by Andrew Bennetts
Distinguish between errors in decoding a message into message parts from errors in handling decoded message parts, and use that to make sure that entire requests are read even when they result in exceptions.
3072
        transport = memory.MemoryTransport('memory:///')
3073
        server = medium.SmartServerPipeStreamMedium(
6133.4.26 by John Arbash Meinel
get rid of the default timeout parameters.
3074
            to_server, from_server, transport, timeout=4.0)
3245.4.49 by Andrew Bennetts
Distinguish between errors in decoding a message into message parts from errors in handling decoded message parts, and use that to make sure that entire requests are read even when they result in exceptions.
3075
        proto = server._build_protocol()
3076
        message_handler = proto.message_handler
3077
        server._serve_one_request(proto)
3078
        # All the bytes have been read from the medium...
6973.7.8 by Jelmer Vernooij
Fix more tests.
3079
        self.assertEqual(b'', to_server.read())
3245.4.49 by Andrew Bennetts
Distinguish between errors in decoding a message into message parts from errors in handling decoded message parts, and use that to make sure that entire requests are read even when they result in exceptions.
3080
        # ...and the protocol decoder has consumed all the bytes, and has
3081
        # finished reading.
6973.7.8 by Jelmer Vernooij
Fix more tests.
3082
        self.assertEqual(b'', proto.unused_data)
3245.4.49 by Andrew Bennetts
Distinguish between errors in decoding a message into message parts from errors in handling decoded message parts, and use that to make sure that entire requests are read even when they result in exceptions.
3083
        self.assertEqual(0, proto.next_read_size())
3084
3085
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
3086
class InstrumentedRequestHandler(object):
3087
    """Test Double of SmartServerRequestHandler."""
3088
3089
    def __init__(self):
3090
        self.calls = []
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
3091
        self.finished_reading = False
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
3092
3093
    def no_body_received(self):
3094
        self.calls.append(('no_body_received',))
3095
3195.3.4 by Andrew Bennetts
Make the general request handler dispatch version 3 events to the specific request handler (i.e. to the SmartServerRequest instance).
3096
    def end_received(self):
3097
        self.calls.append(('end_received',))
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
3098
        self.finished_reading = True
3099
4634.6.30 by Andrew Bennetts
Remove SmartServerRequest.dispatch_command, fix SmartServerRequest.args_received.
3100
    def args_received(self, args):
3101
        self.calls.append(('args_received', args))
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
3102
3103
    def accept_body(self, bytes):
3104
        self.calls.append(('accept_body', bytes))
3105
3106
    def end_of_body(self):
3107
        self.calls.append(('end_of_body',))
3108
        self.finished_reading = True
3195.3.4 by Andrew Bennetts
Make the general request handler dispatch version 3 events to the specific request handler (i.e. to the SmartServerRequest instance).
3109
3923.5.4 by Andrew Bennetts
Allow a request's body part(s) to be followed by an error.
3110
    def post_body_error_received(self, error_args):
3111
        self.calls.append(('post_body_error_received', error_args))
3112
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
3113
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3114
class StubRequest(object):
3115
3116
    def finished_reading(self):
3117
        pass
3118
3119
3245.4.22 by Andrew Bennetts
Uncomment TestClientDecodingProtocolThree.test_trivial_response_decoding.
3120
class TestClientDecodingProtocolThree(TestSmartProtocol):
3121
    """Tests for v3 of the client-side protocol decoding."""
3122
3245.4.55 by Andrew Bennetts
Test improvements suggested by John's review.
3123
    def make_logging_response_decoder(self):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3124
        """Make v3 response decoder using a test response handler."""
3125
        response_handler = LoggingMessageHandler()
3126
        decoder = protocol.ProtocolThreeDecoder(response_handler)
3127
        return decoder, response_handler
3128
3129
    def make_conventional_response_decoder(self):
3245.4.23 by Andrew Bennetts
Improve test_trivial_response_decoding slightly.
3130
        """Make v3 response decoder using a conventional response handler."""
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3131
        response_handler = message.ConventionalResponseHandler()
3245.4.23 by Andrew Bennetts
Improve test_trivial_response_decoding slightly.
3132
        decoder = protocol.ProtocolThreeDecoder(response_handler)
3245.4.26 by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers.
3133
        response_handler.setProtoAndMediumRequest(decoder, StubRequest())
3245.4.23 by Andrew Bennetts
Improve test_trivial_response_decoding slightly.
3134
        return decoder, response_handler
3135
3245.4.22 by Andrew Bennetts
Uncomment TestClientDecodingProtocolThree.test_trivial_response_decoding.
3136
    def test_trivial_response_decoding(self):
3137
        """Smoke test for the simplest possible v3 response: empty headers,
3245.4.23 by Andrew Bennetts
Improve test_trivial_response_decoding slightly.
3138
        status byte, empty args, no body.
3245.4.22 by Andrew Bennetts
Uncomment TestClientDecodingProtocolThree.test_trivial_response_decoding.
3139
        """
6973.7.8 by Jelmer Vernooij
Fix more tests.
3140
        headers = b'\0\0\0\x02de'  # length-prefixed, bencoded empty dict
7143.15.2 by Jelmer Vernooij
Run autopep8.
3141
        response_status = b'oS'  # success
3142
        args = b's\0\0\0\x02le'  # length-prefixed, bencoded empty list
3143
        end = b'e'  # end marker
3245.4.23 by Andrew Bennetts
Improve test_trivial_response_decoding slightly.
3144
        message_bytes = headers + response_status + args + end
3245.4.55 by Andrew Bennetts
Test improvements suggested by John's review.
3145
        decoder, response_handler = self.make_logging_response_decoder()
3245.4.23 by Andrew Bennetts
Improve test_trivial_response_decoding slightly.
3146
        decoder.accept_bytes(message_bytes)
3147
        # The protocol decoder has finished, and consumed all bytes
3245.4.22 by Andrew Bennetts
Uncomment TestClientDecodingProtocolThree.test_trivial_response_decoding.
3148
        self.assertEqual(0, decoder.next_read_size())
6973.7.8 by Jelmer Vernooij
Fix more tests.
3149
        self.assertEqual(b'', decoder.unused_data)
3245.4.23 by Andrew Bennetts
Improve test_trivial_response_decoding slightly.
3150
        # The message handler has been invoked with all the parts of the
3151
        # trivial response: empty headers, status byte, no args, end.
3152
        self.assertEqual(
6973.7.8 by Jelmer Vernooij
Fix more tests.
3153
            [('headers', {}), ('byte', b'S'), ('structure', ()), ('end',)],
3245.4.23 by Andrew Bennetts
Improve test_trivial_response_decoding slightly.
3154
            response_handler.event_log)
3195.3.5 by Andrew Bennetts
Start writing the client-side protocol logic for HPSS v3.
3155
3245.4.55 by Andrew Bennetts
Test improvements suggested by John's review.
3156
    def test_incomplete_message(self):
3157
        """A decoder will keep signalling that it needs more bytes via
3158
        next_read_size() != 0 until it has seen a complete message, regardless
3159
        which state it is in.
3160
        """
3161
        # Define a simple response that uses all possible message parts.
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3162
        headers = b'\0\0\0\x02de'  # length-prefixed, bencoded empty dict
7143.15.2 by Jelmer Vernooij
Run autopep8.
3163
        response_status = b'oS'  # success
3164
        args = b's\0\0\0\x02le'  # length-prefixed, bencoded empty list
3165
        body = b'b\0\0\0\x04BODY'  # a body: 'BODY'
3166
        end = b'e'  # end marker
3245.4.55 by Andrew Bennetts
Test improvements suggested by John's review.
3167
        simple_response = headers + response_status + args + body + end
3168
        # Feed the request to the decoder one byte at a time.
3169
        decoder, response_handler = self.make_logging_response_decoder()
6973.7.8 by Jelmer Vernooij
Fix more tests.
3170
        for byte in bytearray(simple_response):
3245.4.55 by Andrew Bennetts
Test improvements suggested by John's review.
3171
            self.assertNotEqual(0, decoder.next_read_size())
6973.7.8 by Jelmer Vernooij
Fix more tests.
3172
            decoder.accept_bytes(int2byte(byte))
3245.4.55 by Andrew Bennetts
Test improvements suggested by John's review.
3173
        # Now the response is complete
3174
        self.assertEqual(0, decoder.next_read_size())
3175
3176
    def test_read_response_tuple_raises_UnknownSmartMethod(self):
3177
        """read_response_tuple raises UnknownSmartMethod if the server replied
3178
        with 'UnknownMethod'.
3179
        """
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3180
        headers = b'\0\0\0\x02de'  # length-prefixed, bencoded empty dict
7143.15.2 by Jelmer Vernooij
Run autopep8.
3181
        response_status = b'oE'  # error flag
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3182
        # args: (b'UnknownMethod', 'method-name')
3183
        args = b's\0\0\0\x20l13:UnknownMethod11:method-namee'
7143.15.2 by Jelmer Vernooij
Run autopep8.
3184
        end = b'e'  # end marker
3245.4.35 by Andrew Bennetts
Remove some commented out cruft, test (and fix) handling of an 'UnknownMethod' response.
3185
        message_bytes = headers + response_status + args + end
3186
        decoder, response_handler = self.make_conventional_response_decoder()
3187
        decoder.accept_bytes(message_bytes)
3188
        error = self.assertRaises(
3189
            errors.UnknownSmartMethod, response_handler.read_response_tuple)
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3190
        self.assertEqual(b'method-name', error.verb)
3245.4.35 by Andrew Bennetts
Remove some commented out cruft, test (and fix) handling of an 'UnknownMethod' response.
3191
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3192
    def test_read_response_tuple_error(self):
3193
        """If the response has an error, it is raised as an exception."""
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3194
        headers = b'\0\0\0\x02de'  # length-prefixed, bencoded empty dict
7143.15.2 by Jelmer Vernooij
Run autopep8.
3195
        response_status = b'oE'  # error
3196
        args = b's\0\0\0\x1al9:first arg10:second arge'  # two args
3197
        end = b'e'  # end marker
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3198
        message_bytes = headers + response_status + args + end
3199
        decoder, response_handler = self.make_conventional_response_decoder()
3200
        decoder.accept_bytes(message_bytes)
3201
        error = self.assertRaises(
3202
            errors.ErrorFromSmartServer, response_handler.read_response_tuple)
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3203
        self.assertEqual((b'first arg', b'second arg'), error.error_tuple)
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
3204
3195.3.2 by Andrew Bennetts
Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests.
3205
3195.3.14 by Andrew Bennetts
Add some tests for how the client encodes requests.
3206
class TestClientEncodingProtocolThree(TestSmartProtocol):
3207
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
3208
    request_encoder = protocol.ProtocolThreeRequester
3209
    response_decoder = protocol.ProtocolThreeDecoder
3245.4.7 by Andrew Bennetts
Rename _ProtocolThreeBase to ProtocolThreeDecoder, remove SmartServerRequestProtocolThree.
3210
    server_protocol_class = protocol.ProtocolThreeDecoder
3195.3.14 by Andrew Bennetts
Add some tests for how the client encodes requests.
3211
3212
    def make_client_encoder_and_output(self):
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
3213
        result = self.make_client_protocol_and_output()
3214
        requester, response_handler, output = result
3215
        return requester, output
3195.3.14 by Andrew Bennetts
Add some tests for how the client encodes requests.
3216
3217
    def test_call_smoke_test(self):
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
3218
        """A smoke test for ProtocolThreeRequester.call.
3195.3.14 by Andrew Bennetts
Add some tests for how the client encodes requests.
3219
3220
        This test checks that a particular simple invocation of call emits the
3221
        correct bytes for that invocation.
3222
        """
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
3223
        requester, output = self.make_client_encoder_and_output()
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3224
        requester.set_headers({b'header name': b'header value'})
3225
        requester.call(b'one arg')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3226
        self.assertEqual(
7143.15.2 by Jelmer Vernooij
Run autopep8.
3227
            b'bzr message 3 (bzr 1.6)\n'  # protocol version
3228
            b'\x00\x00\x00\x1fd11:header name12:header valuee'  # headers
3229
            b's\x00\x00\x00\x0bl7:one arge'  # args
3230
            b'e',  # end
3195.3.14 by Andrew Bennetts
Add some tests for how the client encodes requests.
3231
            output.getvalue())
3232
3233
    def test_call_with_body_bytes_smoke_test(self):
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
3234
        """A smoke test for ProtocolThreeRequester.call_with_body_bytes.
3195.3.14 by Andrew Bennetts
Add some tests for how the client encodes requests.
3235
3236
        This test checks that a particular simple invocation of
3237
        call_with_body_bytes emits the correct bytes for that invocation.
3238
        """
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
3239
        requester, output = self.make_client_encoder_and_output()
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3240
        requester.set_headers({b'header name': b'header value'})
3241
        requester.call_with_body_bytes((b'one arg',), b'body bytes')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3242
        self.assertEqual(
7143.15.2 by Jelmer Vernooij
Run autopep8.
3243
            b'bzr message 3 (bzr 1.6)\n'  # protocol version
3244
            b'\x00\x00\x00\x1fd11:header name12:header valuee'  # headers
3245
            b's\x00\x00\x00\x0bl7:one arge'  # args
3246
            b'b'  # there is a prefixed body
3247
            b'\x00\x00\x00\nbody bytes'  # the prefixed body
3248
            b'e',  # end
3195.3.14 by Andrew Bennetts
Add some tests for how the client encodes requests.
3249
            output.getvalue())
3250
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3251
    def test_call_writes_just_once(self):
3252
        """A bodyless request is written to the medium all at once."""
3253
        medium_request = StubMediumRequest()
3254
        encoder = protocol.ProtocolThreeRequester(medium_request)
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3255
        encoder.call(b'arg1', b'arg2', b'arg3')
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3256
        self.assertEqual(
3257
            ['accept_bytes', 'finished_writing'], medium_request.calls)
3258
3259
    def test_call_with_body_bytes_writes_just_once(self):
3260
        """A request with body bytes is written to the medium all at once."""
3261
        medium_request = StubMediumRequest()
3262
        encoder = protocol.ProtocolThreeRequester(medium_request)
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3263
        encoder.call_with_body_bytes((b'arg', b'arg'), b'body bytes')
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3264
        self.assertEqual(
3265
            ['accept_bytes', 'finished_writing'], medium_request.calls)
3266
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
3267
    def test_call_with_body_stream_smoke_test(self):
3268
        """A smoke test for ProtocolThreeRequester.call_with_body_stream.
3269
3270
        This test checks that a particular simple invocation of
3271
        call_with_body_stream emits the correct bytes for that invocation.
3272
        """
3273
        requester, output = self.make_client_encoder_and_output()
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3274
        requester.set_headers({b'header name': b'header value'})
3275
        stream = [b'chunk 1', b'chunk two']
3276
        requester.call_with_body_stream((b'one arg',), stream)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3277
        self.assertEqual(
7143.15.2 by Jelmer Vernooij
Run autopep8.
3278
            b'bzr message 3 (bzr 1.6)\n'  # protocol version
3279
            b'\x00\x00\x00\x1fd11:header name12:header valuee'  # headers
3280
            b's\x00\x00\x00\x0bl7:one arge'  # args
3281
            b'b\x00\x00\x00\x07chunk 1'  # a prefixed body chunk
3282
            b'b\x00\x00\x00\x09chunk two'  # a prefixed body chunk
3283
            b'e',  # end
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
3284
            output.getvalue())
3285
3286
    def test_call_with_body_stream_empty_stream(self):
3287
        """call_with_body_stream with an empty stream."""
3288
        requester, output = self.make_client_encoder_and_output()
3289
        requester.set_headers({})
3290
        stream = []
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3291
        requester.call_with_body_stream((b'one arg',), stream)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3292
        self.assertEqual(
7143.15.2 by Jelmer Vernooij
Run autopep8.
3293
            b'bzr message 3 (bzr 1.6)\n'  # protocol version
3294
            b'\x00\x00\x00\x02de'  # headers
3295
            b's\x00\x00\x00\x0bl7:one arge'  # args
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
3296
            # no body chunks
7143.15.2 by Jelmer Vernooij
Run autopep8.
3297
            b'e',  # end
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
3298
            output.getvalue())
3299
3923.5.5 by Andrew Bennetts
Cleanly abort the request if an error occurs while iterating a body stream.
3300
    def test_call_with_body_stream_error(self):
3301
        """call_with_body_stream will abort the streamed body with an
3302
        error if the stream raises an error during iteration.
4032.1.1 by John Arbash Meinel
Merge the removal of all trailing whitespace, and resolve conflicts.
3303
3923.5.5 by Andrew Bennetts
Cleanly abort the request if an error occurs while iterating a body stream.
3304
        The resulting request will still be a complete message.
3305
        """
3306
        requester, output = self.make_client_encoder_and_output()
3307
        requester.set_headers({})
7143.15.2 by Jelmer Vernooij
Run autopep8.
3308
3923.5.5 by Andrew Bennetts
Cleanly abort the request if an error occurs while iterating a body stream.
3309
        def stream_that_fails():
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3310
            yield b'aaa'
3311
            yield b'bbb'
3923.5.5 by Andrew Bennetts
Cleanly abort the request if an error occurs while iterating a body stream.
3312
            raise Exception('Boom!')
4022.1.8 by Robert Collins
Fix test_call_with_body_stream_error which was broken by a debugging change to still pass tests.
3313
        self.assertRaises(Exception, requester.call_with_body_stream,
7143.15.2 by Jelmer Vernooij
Run autopep8.
3314
                          (b'one arg',), stream_that_fails())
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3315
        self.assertEqual(
7143.15.2 by Jelmer Vernooij
Run autopep8.
3316
            b'bzr message 3 (bzr 1.6)\n'  # protocol version
3317
            b'\x00\x00\x00\x02de'  # headers
3318
            b's\x00\x00\x00\x0bl7:one arge'  # args
3319
            b'b\x00\x00\x00\x03aaa'  # body
3320
            b'b\x00\x00\x00\x03bbb'  # more body
3321
            b'oE'  # error flag
3322
            b's\x00\x00\x00\x09l5:errore'  # error args: ('error',)
3323
            b'e',  # end
3923.5.5 by Andrew Bennetts
Cleanly abort the request if an error occurs while iterating a body stream.
3324
            output.getvalue())
3325
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3326
    def test_records_start_of_body_stream(self):
3327
        requester, output = self.make_client_encoder_and_output()
3328
        requester.set_headers({})
3329
        in_stream = [False]
7143.15.2 by Jelmer Vernooij
Run autopep8.
3330
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3331
        def stream_checker():
3332
            self.assertTrue(requester.body_stream_started)
3333
            in_stream[0] = True
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3334
            yield b'content'
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3335
        flush_called = []
3336
        orig_flush = requester.flush
7143.15.2 by Jelmer Vernooij
Run autopep8.
3337
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3338
        def tracked_flush():
3339
            flush_called.append(in_stream[0])
3340
            if in_stream[0]:
3341
                self.assertTrue(requester.body_stream_started)
3342
            else:
3343
                self.assertFalse(requester.body_stream_started)
3344
            return orig_flush()
3345
        requester.flush = tracked_flush
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3346
        requester.call_with_body_stream((b'one arg',), stream_checker())
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3347
        self.assertEqual(
7143.15.2 by Jelmer Vernooij
Run autopep8.
3348
            b'bzr message 3 (bzr 1.6)\n'  # protocol version
3349
            b'\x00\x00\x00\x02de'  # headers
3350
            b's\x00\x00\x00\x0bl7:one arge'  # args
3351
            b'b\x00\x00\x00\x07content'  # body
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3352
            b'e', output.getvalue())
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3353
        self.assertEqual([False, True, True], flush_called)
3354
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3355
3356
class StubMediumRequest(object):
3357
    """A stub medium request that tracks the number of times accept_bytes is
3358
    called.
3359
    """
3441.3.3 by Andrew Bennetts
Fix PEP 8 nit.
3360
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3361
    def __init__(self):
3362
        self.calls = []
3461.2.1 by Andrew Bennetts
Avoid unnecessary reconnections to old servers when the first HPSS is an error in the right protocol version.
3363
        self._medium = 'dummy medium'
3441.3.3 by Andrew Bennetts
Fix PEP 8 nit.
3364
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3365
    def accept_bytes(self, bytes):
3366
        self.calls.append('accept_bytes')
3441.3.3 by Andrew Bennetts
Fix PEP 8 nit.
3367
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3368
    def finished_writing(self):
3369
        self.calls.append('finished_writing')
3370
3195.3.14 by Andrew Bennetts
Add some tests for how the client encodes requests.
3371
4064.1.2 by Andrew Bennetts
Refactor server-side error translation, improve tests.
3372
interrupted_body_stream = (
7143.15.2 by Jelmer Vernooij
Run autopep8.
3373
    b'oS'  # status flag (success)
3374
    b's\x00\x00\x00\x08l4:argse'  # args struct ('args,')
3375
    b'b\x00\x00\x00\x03aaa'  # body part ('aaa')
3376
    b'b\x00\x00\x00\x03bbb'  # body part ('bbb')
3377
    b'oE'  # status flag (error)
5677.2.7 by Martin
Store exception name after initial 'error' slot as suggested in review
3378
    # err struct ('error', 'Exception', 'Boom!')
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3379
    b's\x00\x00\x00\x1bl5:error9:Exception5:Boom!e'
7143.15.2 by Jelmer Vernooij
Run autopep8.
3380
    b'e'  # EOM
4064.1.2 by Andrew Bennetts
Refactor server-side error translation, improve tests.
3381
    )
3382
3383
3245.4.37 by Andrew Bennetts
Add test for sending ProtocolThreeResponder.send_error(UnknownSmartMethod(...)).
3384
class TestResponseEncodingProtocolThree(tests.TestCase):
3385
3386
    def make_response_encoder(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
3387
        out_stream = BytesIO()
3245.4.37 by Andrew Bennetts
Add test for sending ProtocolThreeResponder.send_error(UnknownSmartMethod(...)).
3388
        response_encoder = protocol.ProtocolThreeResponder(out_stream.write)
3389
        return response_encoder, out_stream
3390
3391
    def test_send_error_unknown_method(self):
3392
        encoder, out_stream = self.make_response_encoder()
3393
        encoder.send_error(errors.UnknownSmartMethod('method name'))
3394
        # Use assertEndsWith so that we don't compare the header, which varies
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
3395
        # by breezy.__version__.
3245.4.37 by Andrew Bennetts
Add test for sending ProtocolThreeResponder.send_error(UnknownSmartMethod(...)).
3396
        self.assertEndsWith(
3397
            out_stream.getvalue(),
3398
            # error status
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3399
            b'oE' +
3245.4.37 by Andrew Bennetts
Add test for sending ProtocolThreeResponder.send_error(UnknownSmartMethod(...)).
3400
            # tuple: 'UnknownMethod', 'method name'
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3401
            b's\x00\x00\x00\x20l13:UnknownMethod11:method namee'
3245.4.37 by Andrew Bennetts
Add test for sending ProtocolThreeResponder.send_error(UnknownSmartMethod(...)).
3402
            # end of message
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3403
            b'e')
3245.4.37 by Andrew Bennetts
Add test for sending ProtocolThreeResponder.send_error(UnknownSmartMethod(...)).
3404
4064.1.1 by Andrew Bennetts
Add TestResponseEncodingProtocolThree.test_send_broken_body_stream, and make it pass.
3405
    def test_send_broken_body_stream(self):
3406
        encoder, out_stream = self.make_response_encoder()
3407
        encoder._headers = {}
7143.15.2 by Jelmer Vernooij
Run autopep8.
3408
4064.1.1 by Andrew Bennetts
Add TestResponseEncodingProtocolThree.test_send_broken_body_stream, and make it pass.
3409
        def stream_that_fails():
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3410
            yield b'aaa'
3411
            yield b'bbb'
4064.1.1 by Andrew Bennetts
Add TestResponseEncodingProtocolThree.test_send_broken_body_stream, and make it pass.
3412
            raise Exception('Boom!')
3413
        response = _mod_request.SuccessfulSmartServerResponse(
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3414
            (b'args',), body_stream=stream_that_fails())
4064.1.1 by Andrew Bennetts
Add TestResponseEncodingProtocolThree.test_send_broken_body_stream, and make it pass.
3415
        encoder.send_response(response)
4064.1.2 by Andrew Bennetts
Refactor server-side error translation, improve tests.
3416
        expected_response = (
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3417
            b'bzr message 3 (bzr 1.6)\n'  # protocol marker
7143.15.13 by Jelmer Vernooij
Fix more syntax errors.
3418
            b'\x00\x00\x00\x02de'  # headers dict (empty)
3419
            + interrupted_body_stream)
4064.1.2 by Andrew Bennetts
Refactor server-side error translation, improve tests.
3420
        self.assertEqual(expected_response, out_stream.getvalue())
4064.1.1 by Andrew Bennetts
Add TestResponseEncodingProtocolThree.test_send_broken_body_stream, and make it pass.
3421
3245.4.37 by Andrew Bennetts
Add test for sending ProtocolThreeResponder.send_error(UnknownSmartMethod(...)).
3422
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3423
class TestResponseEncoderBufferingProtocolThree(tests.TestCase):
3424
    """Tests for buffering of responses.
3425
3426
    We want to avoid doing many small writes when one would do, to avoid
3427
    unnecessary network overhead.
3428
    """
3429
3430
    def setUp(self):
6552.1.3 by Vincent Ladeuil
Use super() instead of calling <base>.setup(self), as the original fix illustrated a too-easy-to-fall-into trap.
3431
        super(TestResponseEncoderBufferingProtocolThree, self).setUp()
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3432
        self.writes = []
3433
        self.responder = protocol.ProtocolThreeResponder(self.writes.append)
3434
3435
    def assertWriteCount(self, expected_count):
5283.5.2 by Martin Pool
Update tests for buffering of hpss output
3436
        # self.writes can be quite large; don't show the whole thing
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3437
        self.assertEqual(
3438
            expected_count, len(self.writes),
5283.5.2 by Martin Pool
Update tests for buffering of hpss output
3439
            "Too many writes: %d, expected %d" % (len(self.writes), expected_count))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3440
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3441
    def test_send_error_writes_just_once(self):
3442
        """An error response is written to the medium all at once."""
3443
        self.responder.send_error(Exception('An exception string.'))
3444
        self.assertWriteCount(1)
3445
3446
    def test_send_response_writes_just_once(self):
3447
        """A normal response with no body is written to the medium all at once.
3448
        """
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3449
        response = _mod_request.SuccessfulSmartServerResponse((b'arg', b'arg'))
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3450
        self.responder.send_response(response)
3451
        self.assertWriteCount(1)
3452
3453
    def test_send_response_with_body_writes_just_once(self):
3454
        """A normal response with a monolithic body is written to the medium
3455
        all at once.
3456
        """
3457
        response = _mod_request.SuccessfulSmartServerResponse(
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3458
            (b'arg', b'arg'), body=b'body bytes')
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3459
        self.responder.send_response(response)
3460
        self.assertWriteCount(1)
3461
4078.1.2 by Andrew Bennetts
Adjust write buffering tests for improved buffering.
3462
    def test_send_response_with_body_stream_buffers_writes(self):
3463
        """A normal response with a stream body writes to the medium once."""
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3464
        # Construct a response with stream with 2 chunks in it.
3465
        response = _mod_request.SuccessfulSmartServerResponse(
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3466
            (b'arg', b'arg'), body_stream=[b'chunk1', b'chunk2'])
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3467
        self.responder.send_response(response)
5283.5.2 by Martin Pool
Update tests for buffering of hpss output
3468
        # Per the discussion in bug 590638 we flush once after the header and
3469
        # then once after each chunk
3470
        self.assertWriteCount(3)
3441.3.1 by Andrew Bennetts
Buffer encoding of v3 messages to minimise write/send calls. Doubles the speed of pushing over TCP with 500ms latency loopback.
3471
3472
2018.5.131 by Andrew Bennetts
Be strict about unicode passed to transport.put_{bytes,file} and SmartClient.call_with_body_bytes, fixing part of TestLockableFiles_RemoteLockDir.test_read_write.
3473
class TestSmartClientUnicode(tests.TestCase):
2414.1.4 by Andrew Bennetts
Rename SmartClient to _SmartClient.
3474
    """_SmartClient tests for unicode arguments.
2018.5.131 by Andrew Bennetts
Be strict about unicode passed to transport.put_{bytes,file} and SmartClient.call_with_body_bytes, fixing part of TestLockableFiles_RemoteLockDir.test_read_write.
3475
3476
    Unicode arguments to call_with_body_bytes are not correct (remote method
3477
    names, arguments, and bodies must all be expressed as byte strings), but
2414.1.4 by Andrew Bennetts
Rename SmartClient to _SmartClient.
3478
    _SmartClient should gracefully reject them, rather than getting into a
3479
    broken state that prevents future correct calls from working.  That is, it
3480
    should be possible to issue more requests on the medium afterwards, rather
3481
    than allowing one bad call to call_with_body_bytes to cause later calls to
2018.5.131 by Andrew Bennetts
Be strict about unicode passed to transport.put_{bytes,file} and SmartClient.call_with_body_bytes, fixing part of TestLockableFiles_RemoteLockDir.test_read_write.
3482
    mysteriously fail with TooManyConcurrentRequests.
3483
    """
3484
3485
    def assertCallDoesNotBreakMedium(self, method, args, body):
3486
        """Call a medium with the given method, args and body, then assert that
3487
        the medium is left in a sane state, i.e. is capable of allowing further
3488
        requests.
3489
        """
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
3490
        input = BytesIO(b"\n")
3491
        output = BytesIO()
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.
3492
        client_medium = medium.SmartSimplePipesClientMedium(
3493
            input, output, 'ignored base')
3431.3.2 by Andrew Bennetts
Remove 'base' from _SmartClient entirely, now that the medium has it.
3494
        smart_client = client._SmartClient(client_medium)
2018.5.131 by Andrew Bennetts
Be strict about unicode passed to transport.put_{bytes,file} and SmartClient.call_with_body_bytes, fixing part of TestLockableFiles_RemoteLockDir.test_read_write.
3495
        self.assertRaises(TypeError,
7143.15.2 by Jelmer Vernooij
Run autopep8.
3496
                          smart_client.call_with_body_bytes, method, args, body)
6973.7.8 by Jelmer Vernooij
Fix more tests.
3497
        self.assertEqual(b"", output.getvalue())
2018.5.131 by Andrew Bennetts
Be strict about unicode passed to transport.put_{bytes,file} and SmartClient.call_with_body_bytes, fixing part of TestLockableFiles_RemoteLockDir.test_read_write.
3498
        self.assertEqual(None, client_medium._current_request)
3499
3500
    def test_call_with_body_bytes_unicode_method(self):
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3501
        self.assertCallDoesNotBreakMedium(u'method', (b'args',), b'body')
2018.5.131 by Andrew Bennetts
Be strict about unicode passed to transport.put_{bytes,file} and SmartClient.call_with_body_bytes, fixing part of TestLockableFiles_RemoteLockDir.test_read_write.
3502
3503
    def test_call_with_body_bytes_unicode_args(self):
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3504
        self.assertCallDoesNotBreakMedium(b'method', (u'args',), b'body')
7143.15.2 by Jelmer Vernooij
Run autopep8.
3505
        self.assertCallDoesNotBreakMedium(
3506
            b'method', (b'arg1', u'arg2'), b'body')
2018.5.131 by Andrew Bennetts
Be strict about unicode passed to transport.put_{bytes,file} and SmartClient.call_with_body_bytes, fixing part of TestLockableFiles_RemoteLockDir.test_read_write.
3507
3508
    def test_call_with_body_bytes_unicode_body(self):
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3509
        self.assertCallDoesNotBreakMedium(b'method', (b'args',), u'body')
2018.5.131 by Andrew Bennetts
Be strict about unicode passed to transport.put_{bytes,file} and SmartClient.call_with_body_bytes, fixing part of TestLockableFiles_RemoteLockDir.test_read_write.
3510
3511
3453.4.4 by Andrew Bennetts
Small optimisation: don't bother trying RPCs from >= 1.6 if the server doesn't support protocol v3.
3512
class MockMedium(medium.SmartClientMedium):
3245.4.45 by Andrew Bennetts
Improve documentation of MockMedium.
3513
    """A mock medium that can be used to test _SmartClient.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3514
3245.4.45 by Andrew Bennetts
Improve documentation of MockMedium.
3515
    It can be given a series of requests to expect (and responses it should
3516
    return for them).  It can also be told when the client is expected to
3517
    disconnect a medium.  Expectations must be satisfied in the order they are
3518
    given, or else an AssertionError will be raised.
3519
3520
    Typical use looks like::
3521
3522
        medium = MockMedium()
3523
        medium.expect_request(...)
3524
        medium.expect_request(...)
3525
        medium.expect_request(...)
3526
    """
3527
3528
    def __init__(self):
3453.4.4 by Andrew Bennetts
Small optimisation: don't bother trying RPCs from >= 1.6 if the server doesn't support protocol v3.
3529
        super(MockMedium, self).__init__('dummy base')
3245.4.45 by Andrew Bennetts
Improve documentation of MockMedium.
3530
        self._mock_request = _MockMediumRequest(self)
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3531
        self._expected_events = []
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3532
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3533
    def expect_request(self, request_bytes, response_bytes,
3534
                       allow_partial_read=False):
3245.4.45 by Andrew Bennetts
Improve documentation of MockMedium.
3535
        """Expect 'request_bytes' to be sent, and reply with 'response_bytes'.
3536
3537
        No assumption is made about how many times accept_bytes should be
3538
        called to send the request.  Similarly, no assumption is made about how
3539
        many times read_bytes/read_line are called by protocol code to read a
3540
        response.  e.g.::
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3541
6973.7.8 by Jelmer Vernooij
Fix more tests.
3542
            request.accept_bytes(b'ab')
3543
            request.accept_bytes(b'cd')
3245.4.45 by Andrew Bennetts
Improve documentation of MockMedium.
3544
            request.finished_writing()
3545
3546
        and::
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3547
6973.7.8 by Jelmer Vernooij
Fix more tests.
3548
            request.accept_bytes(b'abcd')
3245.4.45 by Andrew Bennetts
Improve documentation of MockMedium.
3549
            request.finished_writing()
3550
3551
        Will both satisfy ``medium.expect_request('abcd', ...)``.  Thus tests
3552
        using this should not break due to irrelevant changes in protocol
3553
        implementations.
3554
3555
        :param allow_partial_read: if True, no assertion is raised if a
3556
            response is not fully read.  Setting this is useful when the client
3557
            is expected to disconnect without needing to read the complete
3558
            response.  Default is False.
3559
        """
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3560
        self._expected_events.append(('send request', request_bytes))
3561
        if allow_partial_read:
3562
            self._expected_events.append(
3563
                ('read response (partial)', response_bytes))
3564
        else:
3565
            self._expected_events.append(('read response', response_bytes))
3566
3567
    def expect_disconnect(self):
3245.4.45 by Andrew Bennetts
Improve documentation of MockMedium.
3568
        """Expect the client to call ``medium.disconnect()``."""
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3569
        self._expected_events.append('disconnect')
3570
3245.4.45 by Andrew Bennetts
Improve documentation of MockMedium.
3571
    def _assertEvent(self, observed_event):
3572
        """Raise AssertionError unless observed_event matches the next expected
3573
        event.
3574
3575
        :seealso: expect_request
3576
        :seealso: expect_disconnect
3577
        """
3245.4.44 by Andrew Bennetts
Remove auto-detection of protocol v1; it's complex and there's a high risk of false positives. Also remove unused mock object.
3578
        try:
3579
            expected_event = self._expected_events.pop(0)
3580
        except IndexError:
3581
            raise AssertionError(
3582
                'Mock medium observed event %r, but no more events expected'
3583
                % (observed_event,))
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3584
        if expected_event[0] == 'read response (partial)':
3585
            if observed_event[0] != 'read response':
3586
                raise AssertionError(
3587
                    'Mock medium observed event %r, but expected event %r'
3588
                    % (observed_event, expected_event))
3589
        elif observed_event != expected_event:
3590
            raise AssertionError(
3591
                'Mock medium observed event %r, but expected event %r'
3592
                % (observed_event, expected_event))
3593
        if self._expected_events:
3594
            next_event = self._expected_events[0]
3595
            if next_event[0].startswith('read response'):
3596
                self._mock_request._response = next_event[1]
3597
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
3598
    def get_request(self):
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3599
        return self._mock_request
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
3600
3601
    def disconnect(self):
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3602
        if self._mock_request._read_bytes:
7143.15.2 by Jelmer Vernooij
Run autopep8.
3603
            self._assertEvent(
3604
                ('read response', self._mock_request._read_bytes))
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3605
            self._mock_request._read_bytes = b''
3245.4.45 by Andrew Bennetts
Improve documentation of MockMedium.
3606
        self._assertEvent('disconnect')
3607
3608
3609
class _MockMediumRequest(object):
3610
    """A mock ClientMediumRequest used by MockMedium."""
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
3611
3612
    def __init__(self, mock_medium):
3613
        self._medium = mock_medium
6973.7.8 by Jelmer Vernooij
Fix more tests.
3614
        self._written_bytes = b''
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3615
        self._read_bytes = b''
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3616
        self._response = None
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
3617
3618
    def accept_bytes(self, bytes):
3619
        self._written_bytes += bytes
3620
3621
    def finished_writing(self):
3245.4.45 by Andrew Bennetts
Improve documentation of MockMedium.
3622
        self._medium._assertEvent(('send request', self._written_bytes))
6973.7.8 by Jelmer Vernooij
Fix more tests.
3623
        self._written_bytes = b''
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
3624
3625
    def finished_reading(self):
3245.4.45 by Andrew Bennetts
Improve documentation of MockMedium.
3626
        self._medium._assertEvent(('read response', self._read_bytes))
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3627
        self._read_bytes = b''
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
3628
3629
    def read_bytes(self, size):
3630
        resp = self._response
3631
        bytes, resp = resp[:size], resp[size:]
3632
        self._response = resp
3633
        self._read_bytes += bytes
3634
        return bytes
3635
3636
    def read_line(self):
3637
        resp = self._response
3638
        try:
6973.7.8 by Jelmer Vernooij
Fix more tests.
3639
            line, resp = resp.split(b'\n', 1)
3640
            line += b'\n'
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
3641
        except ValueError:
6973.7.8 by Jelmer Vernooij
Fix more tests.
3642
            line, resp = resp, b''
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
3643
        self._response = resp
3644
        self._read_bytes += line
3645
        return line
3646
3647
3648
class Test_SmartClientVersionDetection(tests.TestCase):
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3649
    """Tests for _SmartClient's automatic protocol version detection.
3650
3651
    On the first remote call, _SmartClient will keep retrying the request with
3652
    different protocol versions until it finds one that works.
3653
    """
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
3654
3655
    def test_version_three_server(self):
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3656
        """With a protocol 3 server, only one request is needed."""
3657
        medium = MockMedium()
3431.3.2 by Andrew Bennetts
Remove 'base' from _SmartClient entirely, now that the medium has it.
3658
        smart_client = client._SmartClient(medium, headers={})
6973.7.8 by Jelmer Vernooij
Fix more tests.
3659
        message_start = protocol.MESSAGE_VERSION_THREE + b'\x00\x00\x00\x02de'
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3660
        medium.expect_request(
7143.15.2 by Jelmer Vernooij
Run autopep8.
3661
            message_start
3662
            + b's\x00\x00\x00\x1el11:method-name5:arg 15:arg 2ee',
6973.7.8 by Jelmer Vernooij
Fix more tests.
3663
            message_start + b's\0\0\0\x13l14:response valueee')
3664
        result = smart_client.call(b'method-name', b'arg 1', b'arg 2')
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3665
        # The call succeeded without raising any exceptions from the mock
3666
        # medium, and the smart_client returns the response from the server.
6973.7.8 by Jelmer Vernooij
Fix more tests.
3667
        self.assertEqual((b'response value',), result)
3245.4.44 by Andrew Bennetts
Remove auto-detection of protocol v1; it's complex and there's a high risk of false positives. Also remove unused mock object.
3668
        self.assertEqual([], medium._expected_events)
3453.4.4 by Andrew Bennetts
Small optimisation: don't bother trying RPCs from >= 1.6 if the server doesn't support protocol v3.
3669
        # Also, the v3 works then the server should be assumed to support RPCs
3670
        # introduced in 1.6.
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
3671
        self.assertFalse(medium._is_remote_before((1, 6)))
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
3672
3673
    def test_version_two_server(self):
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3674
        """If the server only speaks protocol 2, the client will first try
3675
        version 3, then fallback to protocol 2.
3676
3677
        Further, _SmartClient caches the detection, so future requests will all
3678
        use protocol 2 immediately.
3679
        """
3680
        medium = MockMedium()
3431.3.2 by Andrew Bennetts
Remove 'base' from _SmartClient entirely, now that the medium has it.
3681
        smart_client = client._SmartClient(medium, headers={})
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3682
        # First the client should send a v3 request, but the server will reply
3683
        # with a v2 error.
3684
        medium.expect_request(
7143.15.2 by Jelmer Vernooij
Run autopep8.
3685
            b'bzr message 3 (bzr 1.6)\n\x00\x00\x00\x02de'
3686
            + b's\x00\x00\x00\x1el11:method-name5:arg 15:arg 2ee',
6973.7.8 by Jelmer Vernooij
Fix more tests.
3687
            b'bzr response 2\nfailed\n\n')
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3688
        # So then the client should disconnect to reset the connection, because
3689
        # the client needs to assume the server cannot read any further
3690
        # requests off the original connection.
3691
        medium.expect_disconnect()
3692
        # The client should then retry the original request in v2
3693
        medium.expect_request(
6973.7.8 by Jelmer Vernooij
Fix more tests.
3694
            b'bzr request 2\nmethod-name\x01arg 1\x01arg 2\n',
3695
            b'bzr response 2\nsuccess\nresponse value\n')
3696
        result = smart_client.call(b'method-name', b'arg 1', b'arg 2')
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3697
        # The smart_client object will return the result of the successful
3698
        # query.
6973.7.8 by Jelmer Vernooij
Fix more tests.
3699
        self.assertEqual((b'response value',), result)
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3700
3701
        # Now try another request, and this time the client will just use
3702
        # protocol 2.  (i.e. the autodetection won't be repeated)
3703
        medium.expect_request(
6973.7.8 by Jelmer Vernooij
Fix more tests.
3704
            b'bzr request 2\nanother-method\n',
3705
            b'bzr response 2\nsuccess\nanother response\n')
3706
        result = smart_client.call(b'another-method')
3707
        self.assertEqual((b'another response',), result)
3245.4.44 by Andrew Bennetts
Remove auto-detection of protocol v1; it's complex and there's a high risk of false positives. Also remove unused mock object.
3708
        self.assertEqual([], medium._expected_events)
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3709
3453.4.4 by Andrew Bennetts
Small optimisation: don't bother trying RPCs from >= 1.6 if the server doesn't support protocol v3.
3710
        # Also, because v3 is not supported, the client medium should assume
3711
        # that RPCs introduced in 1.6 aren't supported either.
3453.4.10 by Andrew Bennetts
Change _is_remote_at_least to _is_remote_before.
3712
        self.assertTrue(medium._is_remote_before((1, 6)))
3453.4.4 by Andrew Bennetts
Small optimisation: don't bother trying RPCs from >= 1.6 if the server doesn't support protocol v3.
3713
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3714
    def test_unknown_version(self):
3245.4.44 by Andrew Bennetts
Remove auto-detection of protocol v1; it's complex and there's a high risk of false positives. Also remove unused mock object.
3715
        """If the server does not use any known (or at least supported)
3716
        protocol version, a SmartProtocolError is raised.
3245.4.43 by Andrew Bennetts
Improve tests for automatic detection of protocol version.
3717
        """
3718
        medium = MockMedium()
3431.3.2 by Andrew Bennetts
Remove 'base' from _SmartClient entirely, now that the medium has it.
3719
        smart_client = client._SmartClient(medium, headers={})
6973.7.8 by Jelmer Vernooij
Fix more tests.
3720
        unknown_protocol_bytes = b'Unknown protocol!'
3245.4.44 by Andrew Bennetts
Remove auto-detection of protocol v1; it's complex and there's a high risk of false positives. Also remove unused mock object.
3721
        # The client will try v3 and v2 before eventually giving up.
3722
        medium.expect_request(
7143.15.2 by Jelmer Vernooij
Run autopep8.
3723
            b'bzr message 3 (bzr 1.6)\n\x00\x00\x00\x02de'
3724
            + b's\x00\x00\x00\x1el11:method-name5:arg 15:arg 2ee',
3245.4.44 by Andrew Bennetts
Remove auto-detection of protocol v1; it's complex and there's a high risk of false positives. Also remove unused mock object.
3725
            unknown_protocol_bytes)
3726
        medium.expect_disconnect()
3727
        medium.expect_request(
6973.7.8 by Jelmer Vernooij
Fix more tests.
3728
            b'bzr request 2\nmethod-name\x01arg 1\x01arg 2\n',
3245.4.44 by Andrew Bennetts
Remove auto-detection of protocol v1; it's complex and there's a high risk of false positives. Also remove unused mock object.
3729
            unknown_protocol_bytes)
3730
        medium.expect_disconnect()
3731
        self.assertRaises(
3732
            errors.SmartProtocolError,
6973.7.8 by Jelmer Vernooij
Fix more tests.
3733
            smart_client.call, b'method-name', b'arg 1', b'arg 2')
3245.4.44 by Andrew Bennetts
Remove auto-detection of protocol v1; it's complex and there's a high risk of false positives. Also remove unused mock object.
3734
        self.assertEqual([], medium._expected_events)
3461.2.1 by Andrew Bennetts
Avoid unnecessary reconnections to old servers when the first HPSS is an error in the right protocol version.
3735
3736
    def test_first_response_is_error(self):
3737
        """If the server replies with an error, then the version detection
3738
        should be complete.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3739
3461.2.1 by Andrew Bennetts
Avoid unnecessary reconnections to old servers when the first HPSS is an error in the right protocol version.
3740
        This test is very similar to test_version_two_server, but catches a bug
3741
        we had in the case where the first reply was an error response.
3742
        """
3743
        medium = MockMedium()
3744
        smart_client = client._SmartClient(medium, headers={})
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
3745
        message_start = protocol.MESSAGE_VERSION_THREE + b'\x00\x00\x00\x02de'
3461.2.1 by Andrew Bennetts
Avoid unnecessary reconnections to old servers when the first HPSS is an error in the right protocol version.
3746
        # Issue a request that gets an error reply in a non-default protocol
3747
        # version.
3748
        medium.expect_request(
7143.15.2 by Jelmer Vernooij
Run autopep8.
3749
            message_start
3750
            + b's\x00\x00\x00\x10l11:method-nameee',
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
3751
            b'bzr response 2\nfailed\n\n')
3461.2.1 by Andrew Bennetts
Avoid unnecessary reconnections to old servers when the first HPSS is an error in the right protocol version.
3752
        medium.expect_disconnect()
3753
        medium.expect_request(
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
3754
            b'bzr request 2\nmethod-name\n',
3755
            b'bzr response 2\nfailed\nFooBarError\n')
3461.2.1 by Andrew Bennetts
Avoid unnecessary reconnections to old servers when the first HPSS is an error in the right protocol version.
3756
        err = self.assertRaises(
3757
            errors.ErrorFromSmartServer,
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
3758
            smart_client.call, b'method-name')
3759
        self.assertEqual((b'FooBarError',), err.error_tuple)
3461.2.1 by Andrew Bennetts
Avoid unnecessary reconnections to old servers when the first HPSS is an error in the right protocol version.
3760
        # Now the medium should have remembered the protocol version, so
3761
        # subsequent requests will use the remembered version immediately.
3762
        medium.expect_request(
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
3763
            b'bzr request 2\nmethod-name\n',
3764
            b'bzr response 2\nsuccess\nresponse value\n')
3765
        result = smart_client.call(b'method-name')
3766
        self.assertEqual((b'response value',), result)
3461.2.1 by Andrew Bennetts
Avoid unnecessary reconnections to old servers when the first HPSS is an error in the right protocol version.
3767
        self.assertEqual([], medium._expected_events)
3768
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
3769
3770
class Test_SmartClient(tests.TestCase):
3771
3772
    def test_call_default_headers(self):
3773
        """ProtocolThreeRequester.call by default sends a 'Software
3774
        version' header.
3775
        """
3431.3.4 by Andrew Bennetts
Revert now unnecessary test change from bzr.dev.
3776
        smart_client = client._SmartClient('dummy medium')
3245.4.55 by Andrew Bennetts
Test improvements suggested by John's review.
3777
        self.assertEqual(
7143.15.2 by Jelmer Vernooij
Run autopep8.
3778
            breezy.__version__.encode('utf-8'),
3779
            smart_client._headers[b'Software version'])
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
3780
        # XXX: need a test that smart_client._headers is passed to the request
3781
        # encoder.
3782
4797.85.28 by John Arbash Meinel
Move all of the send logic into the _SmartClientRequest class.
3783
3784
class Test_SmartClientRequest(tests.TestCase):
3785
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
3786
    def make_client_with_failing_medium(self, fail_at_write=True, response=b''):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
3787
        response_io = BytesIO(response)
3788
        output = BytesIO()
3789
        vendor = FirstRejectedBytesIOSSHVendor(response_io, output,
7143.15.2 by Jelmer Vernooij
Run autopep8.
3790
                                               fail_at_write=fail_at_write)
5050.78.5 by John Arbash Meinel
Merge the 2.1-client-read-reconnect-819604 (bug #819604) to bzr-2.2
3791
        ssh_params = medium.SSHParams('a host', 'a port', 'a user', 'a pass')
3792
        client_medium = medium.SmartSSHClientMedium('base', ssh_params, vendor)
4797.91.2 by John Arbash Meinel
Don't pass headers, so we can more accurately assert the results.
3793
        smart_client = client._SmartClient(client_medium, headers={})
4797.91.1 by John Arbash Meinel
Small refactor, add a test helper to make it easier to set up testing.
3794
        return output, vendor, smart_client
3795
4797.85.34 by John Arbash Meinel
Start implementing retry during read.
3796
    def make_response(self, args, body=None, body_stream=None):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
3797
        response_io = BytesIO()
4797.85.34 by John Arbash Meinel
Start implementing retry during read.
3798
        response = _mod_request.SuccessfulSmartServerResponse(args, body=body,
7143.15.2 by Jelmer Vernooij
Run autopep8.
3799
                                                              body_stream=body_stream)
4797.85.34 by John Arbash Meinel
Start implementing retry during read.
3800
        responder = protocol.ProtocolThreeResponder(response_io.write)
3801
        responder.send_response(response)
3802
        return response_io.getvalue()
3803
3804
    def test__call_doesnt_retry_append(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
3805
        response = self.make_response(('appended', b'8'))
4797.85.34 by John Arbash Meinel
Start implementing retry during read.
3806
        output, vendor, smart_client = self.make_client_with_failing_medium(
3807
            fail_at_write=False, response=response)
6973.7.8 by Jelmer Vernooij
Fix more tests.
3808
        smart_request = client._SmartClientRequest(smart_client, b'append',
7143.15.2 by Jelmer Vernooij
Run autopep8.
3809
                                                   (b'foo', b''), body=b'content\n')
4797.85.34 by John Arbash Meinel
Start implementing retry during read.
3810
        self.assertRaises(errors.ConnectionReset, smart_request._call, 3)
3811
3812
    def test__call_retries_get_bytes(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
3813
        response = self.make_response((b'ok',), b'content\n')
4797.85.34 by John Arbash Meinel
Start implementing retry during read.
3814
        output, vendor, smart_client = self.make_client_with_failing_medium(
3815
            fail_at_write=False, response=response)
6973.7.8 by Jelmer Vernooij
Fix more tests.
3816
        smart_request = client._SmartClientRequest(smart_client, b'get',
7143.15.2 by Jelmer Vernooij
Run autopep8.
3817
                                                   (b'foo',))
4797.85.34 by John Arbash Meinel
Start implementing retry during read.
3818
        response, response_handler = smart_request._call(3)
6973.7.8 by Jelmer Vernooij
Fix more tests.
3819
        self.assertEqual((b'ok',), response)
3820
        self.assertEqual(b'content\n', response_handler.read_body_bytes())
4797.85.34 by John Arbash Meinel
Start implementing retry during read.
3821
4797.85.37 by John Arbash Meinel
We should refuse to retry on read for -Dnoretry as well.
3822
    def test__call_noretry_get_bytes(self):
3823
        debug.debug_flags.add('noretry')
6973.7.8 by Jelmer Vernooij
Fix more tests.
3824
        response = self.make_response((b'ok',), b'content\n')
4797.85.37 by John Arbash Meinel
We should refuse to retry on read for -Dnoretry as well.
3825
        output, vendor, smart_client = self.make_client_with_failing_medium(
3826
            fail_at_write=False, response=response)
6973.7.8 by Jelmer Vernooij
Fix more tests.
3827
        smart_request = client._SmartClientRequest(smart_client, b'get',
7143.15.2 by Jelmer Vernooij
Run autopep8.
3828
                                                   (b'foo',))
4797.85.37 by John Arbash Meinel
We should refuse to retry on read for -Dnoretry as well.
3829
        self.assertRaises(errors.ConnectionReset, smart_request._call, 3)
3830
4797.85.28 by John Arbash Meinel
Move all of the send logic into the _SmartClientRequest class.
3831
    def test__send_no_retry_pipes(self):
4797.85.23 by John Arbash Meinel
Start direct testing of the reconnection attempts.
3832
        client_read, server_write = create_file_pipes()
3833
        server_read, client_write = create_file_pipes()
3834
        client_medium = medium.SmartSimplePipesClientMedium(client_read,
7143.15.2 by Jelmer Vernooij
Run autopep8.
3835
                                                            client_write, base='/')
4797.85.23 by John Arbash Meinel
Start direct testing of the reconnection attempts.
3836
        smart_client = client._SmartClient(client_medium)
4797.85.28 by John Arbash Meinel
Move all of the send logic into the _SmartClientRequest class.
3837
        smart_request = client._SmartClientRequest(smart_client,
7143.15.2 by Jelmer Vernooij
Run autopep8.
3838
                                                   b'hello', ())
4797.85.23 by John Arbash Meinel
Start direct testing of the reconnection attempts.
3839
        # Close the server side
3840
        server_read.close()
4797.85.28 by John Arbash Meinel
Move all of the send logic into the _SmartClientRequest class.
3841
        encoder, response_handler = smart_request._construct_protocol(3)
4797.85.23 by John Arbash Meinel
Start direct testing of the reconnection attempts.
3842
        self.assertRaises(errors.ConnectionReset,
7143.15.2 by Jelmer Vernooij
Run autopep8.
3843
                          smart_request._send_no_retry, encoder)
4797.85.23 by John Arbash Meinel
Start direct testing of the reconnection attempts.
3844
4797.85.28 by John Arbash Meinel
Move all of the send logic into the _SmartClientRequest class.
3845
    def test__send_read_response_sockets(self):
4797.85.23 by John Arbash Meinel
Start direct testing of the reconnection attempts.
3846
        listen_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
3847
        listen_sock.bind(('127.0.0.1', 0))
3848
        listen_sock.listen(1)
3849
        host, port = listen_sock.getsockname()
3850
        client_medium = medium.SmartTCPClientMedium(host, port, '/')
3851
        client_medium._ensure_connection()
3852
        smart_client = client._SmartClient(client_medium)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
3853
        smart_request = client._SmartClientRequest(smart_client, b'hello', ())
4797.85.23 by John Arbash Meinel
Start direct testing of the reconnection attempts.
3854
        # Accept the connection, but don't actually talk to the client.
3855
        server_sock, _ = listen_sock.accept()
3856
        server_sock.close()
3857
        # Sockets buffer and don't really notice that the server has closed the
3858
        # connection until we try to read again.
4797.85.28 by John Arbash Meinel
Move all of the send logic into the _SmartClientRequest class.
3859
        handler = smart_request._send(3)
4797.85.23 by John Arbash Meinel
Start direct testing of the reconnection attempts.
3860
        self.assertRaises(errors.ConnectionReset,
7143.15.2 by Jelmer Vernooij
Run autopep8.
3861
                          handler.read_response_tuple, expect_body=False)
4797.85.23 by John Arbash Meinel
Start direct testing of the reconnection attempts.
3862
4797.85.28 by John Arbash Meinel
Move all of the send logic into the _SmartClientRequest class.
3863
    def test__send_retries_on_write(self):
4797.91.1 by John Arbash Meinel
Small refactor, add a test helper to make it easier to set up testing.
3864
        output, vendor, smart_client = self.make_client_with_failing_medium()
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
3865
        smart_request = client._SmartClientRequest(smart_client, b'hello', ())
4797.85.28 by John Arbash Meinel
Move all of the send logic into the _SmartClientRequest class.
3866
        handler = smart_request._send(3)
7143.15.2 by Jelmer Vernooij
Run autopep8.
3867
        self.assertEqual(b'bzr message 3 (bzr 1.6)\n'  # protocol
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
3868
                         b'\x00\x00\x00\x02de'   # empty headers
3869
                         b's\x00\x00\x00\tl5:helloee',
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3870
                         output.getvalue())
4797.85.24 by John Arbash Meinel
Show that we try to retry the request if the first attempt fails.
3871
        self.assertEqual(
3872
            [('connect_ssh', 'a user', 'a pass', 'a host', 'a port',
3873
              ['bzr', 'serve', '--inet', '--directory=/', '--allow-writes']),
3874
             ('close',),
3875
             ('connect_ssh', 'a user', 'a pass', 'a host', 'a port',
3876
              ['bzr', 'serve', '--inet', '--directory=/', '--allow-writes']),
7143.15.2 by Jelmer Vernooij
Run autopep8.
3877
             ],
4797.85.24 by John Arbash Meinel
Show that we try to retry the request if the first attempt fails.
3878
            vendor.calls)
3879
4797.85.28 by John Arbash Meinel
Move all of the send logic into the _SmartClientRequest class.
3880
    def test__send_doesnt_retry_read_failure(self):
4797.91.1 by John Arbash Meinel
Small refactor, add a test helper to make it easier to set up testing.
3881
        output, vendor, smart_client = self.make_client_with_failing_medium(
3882
            fail_at_write=False)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
3883
        smart_request = client._SmartClientRequest(smart_client, b'hello', ())
4797.85.28 by John Arbash Meinel
Move all of the send logic into the _SmartClientRequest class.
3884
        handler = smart_request._send(3)
7143.15.2 by Jelmer Vernooij
Run autopep8.
3885
        self.assertEqual(b'bzr message 3 (bzr 1.6)\n'  # protocol
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
3886
                         b'\x00\x00\x00\x02de'   # empty headers
3887
                         b's\x00\x00\x00\tl5:helloee',
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3888
                         output.getvalue())
4797.85.25 by John Arbash Meinel
_send_request can't handle retrying during a read failure
3889
        self.assertEqual(
3890
            [('connect_ssh', 'a user', 'a pass', 'a host', 'a port',
3891
              ['bzr', 'serve', '--inet', '--directory=/', '--allow-writes']),
7143.15.2 by Jelmer Vernooij
Run autopep8.
3892
             ],
4797.85.25 by John Arbash Meinel
_send_request can't handle retrying during a read failure
3893
            vendor.calls)
3894
        self.assertRaises(errors.ConnectionReset, handler.read_response_tuple)
4797.85.23 by John Arbash Meinel
Start direct testing of the reconnection attempts.
3895
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3896
    def test__send_request_retries_body_stream_if_not_started(self):
4797.91.1 by John Arbash Meinel
Small refactor, add a test helper to make it easier to set up testing.
3897
        output, vendor, smart_client = self.make_client_with_failing_medium()
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
3898
        smart_request = client._SmartClientRequest(smart_client, b'hello', (),
7143.15.2 by Jelmer Vernooij
Run autopep8.
3899
                                                   body_stream=[b'a', b'b'])
4797.93.2 by John Arbash Meinel
Merge the refactored SmartClientRequest code, and update to match it.
3900
        response_handler = smart_request._send(3)
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3901
        # We connect, get disconnected, and notice before consuming the stream,
3902
        # so we try again one time and succeed.
3903
        self.assertEqual(
3904
            [('connect_ssh', 'a user', 'a pass', 'a host', 'a port',
3905
              ['bzr', 'serve', '--inet', '--directory=/', '--allow-writes']),
3906
             ('close',),
3907
             ('connect_ssh', 'a user', 'a pass', 'a host', 'a port',
3908
              ['bzr', 'serve', '--inet', '--directory=/', '--allow-writes']),
7143.15.2 by Jelmer Vernooij
Run autopep8.
3909
             ],
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3910
            vendor.calls)
7143.15.2 by Jelmer Vernooij
Run autopep8.
3911
        self.assertEqual(b'bzr message 3 (bzr 1.6)\n'  # protocol
6973.7.8 by Jelmer Vernooij
Fix more tests.
3912
                         b'\x00\x00\x00\x02de'   # empty headers
3913
                         b's\x00\x00\x00\tl5:helloe'
3914
                         b'b\x00\x00\x00\x01a'
3915
                         b'b\x00\x00\x00\x01b'
3916
                         b'e',
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3917
                         output.getvalue())
3918
3919
    def test__send_request_stops_if_body_started(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
3920
        # We intentionally use the python BytesIO so that we can subclass it.
3921
        from io import BytesIO
3922
        response = BytesIO()
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3923
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
3924
        class FailAfterFirstWrite(BytesIO):
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3925
            """Allow one 'write' call to pass, fail the rest"""
7143.15.2 by Jelmer Vernooij
Run autopep8.
3926
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3927
            def __init__(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
3928
                BytesIO.__init__(self)
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3929
                self._first = True
3930
3931
            def write(self, s):
3932
                if self._first:
3933
                    self._first = False
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
3934
                    return BytesIO.write(self, s)
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3935
                raise IOError(errno.EINVAL, 'invalid file handle')
3936
        output = FailAfterFirstWrite()
3937
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
3938
        vendor = FirstRejectedBytesIOSSHVendor(response, output,
7143.15.2 by Jelmer Vernooij
Run autopep8.
3939
                                               fail_at_write=False)
5050.78.6 by John Arbash Meinel
Merge in the stream retry code, and update for the slightly newer apis.
3940
        ssh_params = medium.SSHParams('a host', 'a port', 'a user', 'a pass')
3941
        client_medium = medium.SmartSSHClientMedium('base', ssh_params, vendor)
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3942
        smart_client = client._SmartClient(client_medium, headers={})
6973.7.8 by Jelmer Vernooij
Fix more tests.
3943
        smart_request = client._SmartClientRequest(smart_client, b'hello', (),
7143.15.2 by Jelmer Vernooij
Run autopep8.
3944
                                                   body_stream=[b'a', b'b'])
4797.85.28 by John Arbash Meinel
Move all of the send logic into the _SmartClientRequest class.
3945
        self.assertRaises(errors.ConnectionReset, smart_request._send, 3)
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3946
        # We connect, and manage to get to the point that we start consuming
3947
        # the body stream. The next write fails, so we just stop.
4797.85.26 by John Arbash Meinel
If we get ConnectionReset and we are aborting the call reset the request.
3948
        self.assertEqual(
3949
            [('connect_ssh', 'a user', 'a pass', 'a host', 'a port',
3950
              ['bzr', 'serve', '--inet', '--directory=/', '--allow-writes']),
3951
             ('close',),
7143.15.2 by Jelmer Vernooij
Run autopep8.
3952
             ],
4797.85.26 by John Arbash Meinel
If we get ConnectionReset and we are aborting the call reset the request.
3953
            vendor.calls)
7143.15.2 by Jelmer Vernooij
Run autopep8.
3954
        self.assertEqual(b'bzr message 3 (bzr 1.6)\n'  # protocol
6973.7.8 by Jelmer Vernooij
Fix more tests.
3955
                         b'\x00\x00\x00\x02de'   # empty headers
3956
                         b's\x00\x00\x00\tl5:helloe',
4797.93.1 by John Arbash Meinel
Implement retrying a request as long as we haven't started consuming the body stream.
3957
                         output.getvalue())
4797.85.26 by John Arbash Meinel
If we get ConnectionReset and we are aborting the call reset the request.
3958
4797.91.5 by John Arbash Meinel
Add -Dnoretry as a way to disable all retrying code.
3959
    def test__send_disabled_retry(self):
3960
        debug.debug_flags.add('noretry')
3961
        output, vendor, smart_client = self.make_client_with_failing_medium()
6973.7.8 by Jelmer Vernooij
Fix more tests.
3962
        smart_request = client._SmartClientRequest(smart_client, b'hello', ())
4797.91.5 by John Arbash Meinel
Add -Dnoretry as a way to disable all retrying code.
3963
        self.assertRaises(errors.ConnectionReset, smart_request._send, 3)
3964
        self.assertEqual(
3965
            [('connect_ssh', 'a user', 'a pass', 'a host', 'a port',
3966
              ['bzr', 'serve', '--inet', '--directory=/', '--allow-writes']),
3967
             ('close',),
7143.15.2 by Jelmer Vernooij
Run autopep8.
3968
             ],
4797.91.5 by John Arbash Meinel
Add -Dnoretry as a way to disable all retrying code.
3969
            vendor.calls)
3970
3245.4.42 by Andrew Bennetts
Make _SmartClient automatically detect and use the highest protocol version compatible with the server.
3971
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
3972
class LengthPrefixedBodyDecoder(tests.TestCase):
3973
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
3974
    # XXX: TODO: make accept_reading_trailer invoke translate_response or
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
3975
    # something similar to the ProtocolBase method.
3976
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
3977
    def test_construct(self):
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
3978
        decoder = protocol.LengthPrefixedBodyDecoder()
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
3979
        self.assertFalse(decoder.finished_reading)
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
3980
        self.assertEqual(6, decoder.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
3981
        self.assertEqual(b'', decoder.read_pending_data())
3982
        self.assertEqual(b'', decoder.unused_data)
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
3983
3984
    def test_accept_bytes(self):
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
3985
        decoder = protocol.LengthPrefixedBodyDecoder()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
3986
        decoder.accept_bytes(b'')
3987
        self.assertFalse(decoder.finished_reading)
3988
        self.assertEqual(6, decoder.next_read_size())
3989
        self.assertEqual(b'', decoder.read_pending_data())
3990
        self.assertEqual(b'', decoder.unused_data)
3991
        decoder.accept_bytes(b'7')
3992
        self.assertFalse(decoder.finished_reading)
3993
        self.assertEqual(6, decoder.next_read_size())
3994
        self.assertEqual(b'', decoder.read_pending_data())
3995
        self.assertEqual(b'', decoder.unused_data)
3996
        decoder.accept_bytes(b'\na')
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
3997
        self.assertFalse(decoder.finished_reading)
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
3998
        self.assertEqual(11, decoder.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
3999
        self.assertEqual(b'a', decoder.read_pending_data())
4000
        self.assertEqual(b'', decoder.unused_data)
4001
        decoder.accept_bytes(b'bcdefgd')
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
4002
        self.assertFalse(decoder.finished_reading)
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
4003
        self.assertEqual(4, decoder.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4004
        self.assertEqual(b'bcdefg', decoder.read_pending_data())
4005
        self.assertEqual(b'', decoder.unused_data)
4006
        decoder.accept_bytes(b'one')
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
4007
        self.assertFalse(decoder.finished_reading)
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
4008
        self.assertEqual(1, decoder.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4009
        self.assertEqual(b'', decoder.read_pending_data())
4010
        self.assertEqual(b'', decoder.unused_data)
4011
        decoder.accept_bytes(b'\nblarg')
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
4012
        self.assertTrue(decoder.finished_reading)
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
4013
        self.assertEqual(1, decoder.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4014
        self.assertEqual(b'', decoder.read_pending_data())
4015
        self.assertEqual(b'blarg', decoder.unused_data)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
4016
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
4017
    def test_accept_bytes_all_at_once_with_excess(self):
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
4018
        decoder = protocol.LengthPrefixedBodyDecoder()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4019
        decoder.accept_bytes(b'1\nadone\nunused')
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
4020
        self.assertTrue(decoder.finished_reading)
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
4021
        self.assertEqual(1, decoder.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4022
        self.assertEqual(b'a', decoder.read_pending_data())
4023
        self.assertEqual(b'unused', decoder.unused_data)
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
4024
4025
    def test_accept_bytes_exact_end_of_body(self):
2018.5.3 by Andrew Bennetts
Split up more smart server code, this time into bzrlib/transport/smart/protocol.py
4026
        decoder = protocol.LengthPrefixedBodyDecoder()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4027
        decoder.accept_bytes(b'1\na')
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
4028
        self.assertFalse(decoder.finished_reading)
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
4029
        self.assertEqual(5, decoder.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4030
        self.assertEqual(b'a', decoder.read_pending_data())
4031
        self.assertEqual(b'', decoder.unused_data)
4032
        decoder.accept_bytes(b'done\n')
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
4033
        self.assertTrue(decoder.finished_reading)
2018.2.10 by Andrew Bennetts
Tidy up TODOs, further testing and fixes for SmartServerRequestProtocolOne, and remove a read_bytes(1) call.
4034
        self.assertEqual(1, decoder.next_read_size())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4035
        self.assertEqual(b'', decoder.read_pending_data())
4036
        self.assertEqual(b'', decoder.unused_data)
2018.2.2 by Andrew Bennetts
Implement HTTP smart server.
4037
4038
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4039
class TestChunkedBodyDecoder(tests.TestCase):
2748.4.16 by Andrew Bennetts
Tweaks suggested by review.
4040
    """Tests for ChunkedBodyDecoder.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
4041
2748.4.16 by Andrew Bennetts
Tweaks suggested by review.
4042
    This is the body decoder used for protocol version two.
4043
    """
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4044
4045
    def test_construct(self):
4046
        decoder = protocol.ChunkedBodyDecoder()
4047
        self.assertFalse(decoder.finished_reading)
2748.4.16 by Andrew Bennetts
Tweaks suggested by review.
4048
        self.assertEqual(8, decoder.next_read_size())
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
4049
        self.assertEqual(None, decoder.read_next_chunk())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4050
        self.assertEqual(b'', decoder.unused_data)
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4051
4052
    def test_empty_content(self):
2748.4.16 by Andrew Bennetts
Tweaks suggested by review.
4053
        """'chunked\nEND\n' is the complete encoding of a zero-length body.
4054
        """
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4055
        decoder = protocol.ChunkedBodyDecoder()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4056
        decoder.accept_bytes(b'chunked\n')
4057
        decoder.accept_bytes(b'END\n')
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4058
        self.assertTrue(decoder.finished_reading)
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
4059
        self.assertEqual(None, decoder.read_next_chunk())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4060
        self.assertEqual(b'', decoder.unused_data)
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4061
4062
    def test_one_chunk(self):
4063
        """A body in a single chunk is decoded correctly."""
4064
        decoder = protocol.ChunkedBodyDecoder()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4065
        decoder.accept_bytes(b'chunked\n')
4066
        chunk_length = b'f\n'
4067
        chunk_content = b'123456789abcdef'
4068
        finish = b'END\n'
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4069
        decoder.accept_bytes(chunk_length + chunk_content + finish)
4070
        self.assertTrue(decoder.finished_reading)
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
4071
        self.assertEqual(chunk_content, decoder.read_next_chunk())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4072
        self.assertEqual(b'', decoder.unused_data)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
4073
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4074
    def test_incomplete_chunk(self):
4075
        """When there are less bytes in the chunk than declared by the length,
4076
        then we haven't finished reading yet.
4077
        """
4078
        decoder = protocol.ChunkedBodyDecoder()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4079
        decoder.accept_bytes(b'chunked\n')
4080
        chunk_length = b'8\n'
4081
        three_bytes = b'123'
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4082
        decoder.accept_bytes(chunk_length + three_bytes)
4083
        self.assertFalse(decoder.finished_reading)
4084
        self.assertEqual(
2748.4.7 by Andrew Bennetts
Change the end-of-body marker to something clearer than a zero-length chunk.
4085
            5 + 4, decoder.next_read_size(),
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4086
            "The next_read_size hint should be the number of missing bytes in "
2748.4.7 by Andrew Bennetts
Change the end-of-body marker to something clearer than a zero-length chunk.
4087
            "this chunk plus 4 (the length of the end-of-body marker: "
4088
            "'END\\n')")
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
4089
        self.assertEqual(None, decoder.read_next_chunk())
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4090
4091
    def test_incomplete_length(self):
4092
        """A chunk length hasn't been read until a newline byte has been read.
4093
        """
4094
        decoder = protocol.ChunkedBodyDecoder()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4095
        decoder.accept_bytes(b'chunked\n')
4096
        decoder.accept_bytes(b'9')
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4097
        self.assertEqual(
4098
            1, decoder.next_read_size(),
4099
            "The next_read_size hint should be 1, because we don't know the "
4100
            "length yet.")
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4101
        decoder.accept_bytes(b'\n')
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4102
        self.assertEqual(
2748.4.7 by Andrew Bennetts
Change the end-of-body marker to something clearer than a zero-length chunk.
4103
            9 + 4, decoder.next_read_size(),
4104
            "The next_read_size hint should be the length of the chunk plus 4 "
4105
            "(the length of the end-of-body marker: 'END\\n')")
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4106
        self.assertFalse(decoder.finished_reading)
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
4107
        self.assertEqual(None, decoder.read_next_chunk())
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4108
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
4109
    def test_two_chunks(self):
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4110
        """Content from multiple chunks is concatenated."""
4111
        decoder = protocol.ChunkedBodyDecoder()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4112
        decoder.accept_bytes(b'chunked\n')
4113
        chunk_one = b'3\naaa'
4114
        chunk_two = b'5\nbbbbb'
4115
        finish = b'END\n'
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4116
        decoder.accept_bytes(chunk_one + chunk_two + finish)
4117
        self.assertTrue(decoder.finished_reading)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4118
        self.assertEqual(b'aaa', decoder.read_next_chunk())
4119
        self.assertEqual(b'bbbbb', decoder.read_next_chunk())
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
4120
        self.assertEqual(None, decoder.read_next_chunk())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4121
        self.assertEqual(b'', decoder.unused_data)
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4122
4123
    def test_excess_bytes(self):
4124
        """Bytes after the chunked body are reported as unused bytes."""
4125
        decoder = protocol.ChunkedBodyDecoder()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4126
        decoder.accept_bytes(b'chunked\n')
4127
        chunked_body = b"5\naaaaaEND\n"
4128
        excess_bytes = b"excess bytes"
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4129
        decoder.accept_bytes(chunked_body + excess_bytes)
4130
        self.assertTrue(decoder.finished_reading)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4131
        self.assertEqual(b'aaaaa', decoder.read_next_chunk())
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4132
        self.assertEqual(excess_bytes, decoder.unused_data)
4133
        self.assertEqual(
4134
            1, decoder.next_read_size(),
4135
            "next_read_size hint should be 1 when finished_reading.")
4136
4137
    def test_multidigit_length(self):
4138
        """Lengths in the chunk prefixes can have multiple digits."""
4139
        decoder = protocol.ChunkedBodyDecoder()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4140
        decoder.accept_bytes(b'chunked\n')
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4141
        length = 0x123
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4142
        chunk_prefix = hex(length).encode('ascii') + b'\n'
4143
        chunk_bytes = b'z' * length
4144
        finish = b'END\n'
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4145
        decoder.accept_bytes(chunk_prefix + chunk_bytes + finish)
4146
        self.assertTrue(decoder.finished_reading)
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
4147
        self.assertEqual(chunk_bytes, decoder.read_next_chunk())
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4148
4149
    def test_byte_at_a_time(self):
4150
        """A complete body fed to the decoder one byte at a time should not
4151
        confuse the decoder.  That is, it should give the same result as if the
4152
        bytes had been received in one batch.
4153
4154
        This test is the same as test_one_chunk apart from the way accept_bytes
4155
        is called.
4156
        """
4157
        decoder = protocol.ChunkedBodyDecoder()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4158
        decoder.accept_bytes(b'chunked\n')
4159
        chunk_length = b'f\n'
4160
        chunk_content = b'123456789abcdef'
4161
        finish = b'END\n'
4162
        combined = chunk_length + chunk_content + finish
4163
        for i in range(len(combined)):
7143.15.2 by Jelmer Vernooij
Run autopep8.
4164
            decoder.accept_bytes(combined[i:i + 1])
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4165
        self.assertTrue(decoder.finished_reading)
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
4166
        self.assertEqual(chunk_content, decoder.read_next_chunk())
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4167
        self.assertEqual(b'', decoder.unused_data)
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4168
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
4169
    def test_read_pending_data_resets(self):
4170
        """read_pending_data does not return the same bytes twice."""
4171
        decoder = protocol.ChunkedBodyDecoder()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4172
        decoder.accept_bytes(b'chunked\n')
4173
        chunk_one = b'3\naaa'
4174
        chunk_two = b'3\nbbb'
4175
        finish = b'END\n'
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
4176
        decoder.accept_bytes(chunk_one)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4177
        self.assertEqual(b'aaa', decoder.read_next_chunk())
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
4178
        decoder.accept_bytes(chunk_two)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4179
        self.assertEqual(b'bbb', decoder.read_next_chunk())
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
4180
        self.assertEqual(None, decoder.read_next_chunk())
4181
4182
    def test_decode_error(self):
4183
        decoder = protocol.ChunkedBodyDecoder()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4184
        decoder.accept_bytes(b'chunked\n')
4185
        chunk_one = b'b\nfirst chunk'
4186
        error_signal = b'ERR\n'
4187
        error_chunks = b'5\npart1' + b'5\npart2'
4188
        finish = b'END\n'
2748.4.6 by Andrew Bennetts
Use chunks for stream errors, rather than the response tuple format.
4189
        decoder.accept_bytes(chunk_one + error_signal + error_chunks + finish)
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
4190
        self.assertTrue(decoder.finished_reading)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4191
        self.assertEqual(b'first chunk', decoder.read_next_chunk())
2692.1.2 by Andrew Bennetts
Merge from bzr.dev.
4192
        expected_failure = _mod_request.FailedSmartServerResponse(
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4193
            (b'part1', b'part2'))
2748.4.5 by Andrew Bennetts
Allow an error to interrupt (and terminate) a streamed response body.
4194
        self.assertEqual(expected_failure, decoder.read_next_chunk())
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
4195
2748.4.16 by Andrew Bennetts
Tweaks suggested by review.
4196
    def test_bad_header(self):
4197
        """accept_bytes raises a SmartProtocolError if a chunked body does not
4198
        start with the right header.
4199
        """
4200
        decoder = protocol.ChunkedBodyDecoder()
4201
        self.assertRaises(
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4202
            errors.SmartProtocolError, decoder.accept_bytes, b'bad header\n')
2748.4.16 by Andrew Bennetts
Tweaks suggested by review.
4203
2748.4.1 by Andrew Bennetts
Implement a ChunkedBodyDecoder.
4204
2432.4.1 by Robert Collins
Add SuccessfulSmartServerResponse.
4205
class TestSuccessfulSmartServerResponse(tests.TestCase):
4206
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
4207
    def test_construct_no_body(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
4208
        response = _mod_request.SuccessfulSmartServerResponse((b'foo', b'bar'))
4209
        self.assertEqual((b'foo', b'bar'), response.args)
2432.4.1 by Robert Collins
Add SuccessfulSmartServerResponse.
4210
        self.assertEqual(None, response.body)
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
4211
4212
    def test_construct_with_body(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
4213
        response = _mod_request.SuccessfulSmartServerResponse((b'foo', b'bar'),
4214
                                                              b'bytes')
4215
        self.assertEqual((b'foo', b'bar'), response.args)
4216
        self.assertEqual(b'bytes', response.body)
2781.2.1 by Andrew Bennetts
Fix SmartServerResponse.__repr__.
4217
        # repr(response) doesn't trigger exceptions.
4218
        repr(response)
2432.4.1 by Robert Collins
Add SuccessfulSmartServerResponse.
4219
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
4220
    def test_construct_with_body_stream(self):
6973.7.8 by Jelmer Vernooij
Fix more tests.
4221
        bytes_iterable = [b'abc']
2692.1.2 by Andrew Bennetts
Merge from bzr.dev.
4222
        response = _mod_request.SuccessfulSmartServerResponse(
6973.7.8 by Jelmer Vernooij
Fix more tests.
4223
            (b'foo', b'bar'), body_stream=bytes_iterable)
4224
        self.assertEqual((b'foo', b'bar'), response.args)
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
4225
        self.assertEqual(bytes_iterable, response.body_stream)
4226
4227
    def test_construct_rejects_body_and_body_stream(self):
4228
        """'body' and 'body_stream' are mutually exclusive."""
4229
        self.assertRaises(
4230
            errors.BzrError,
6973.7.8 by Jelmer Vernooij
Fix more tests.
4231
            _mod_request.SuccessfulSmartServerResponse, (), b'body', [b'stream'])
2748.4.2 by Andrew Bennetts
Add protocol (version two) support for streaming bodies (using chunking) in responses.
4232
2432.4.1 by Robert Collins
Add SuccessfulSmartServerResponse.
4233
    def test_is_successful(self):
4234
        """is_successful should return True for SuccessfulSmartServerResponse."""
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
4235
        response = _mod_request.SuccessfulSmartServerResponse((b'error',))
2432.4.1 by Robert Collins
Add SuccessfulSmartServerResponse.
4236
        self.assertEqual(True, response.is_successful())
4237
4238
2432.4.2 by Robert Collins
Add FailedSmartServerResponse.
4239
class TestFailedSmartServerResponse(tests.TestCase):
4240
4241
    def test_construct(self):
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
4242
        response = _mod_request.FailedSmartServerResponse((b'foo', b'bar'))
4243
        self.assertEqual((b'foo', b'bar'), response.args)
2432.4.2 by Robert Collins
Add FailedSmartServerResponse.
4244
        self.assertEqual(None, response.body)
7143.15.2 by Jelmer Vernooij
Run autopep8.
4245
        response = _mod_request.FailedSmartServerResponse(
4246
            (b'foo', b'bar'), b'bytes')
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
4247
        self.assertEqual((b'foo', b'bar'), response.args)
4248
        self.assertEqual(b'bytes', response.body)
2781.2.1 by Andrew Bennetts
Fix SmartServerResponse.__repr__.
4249
        # repr(response) doesn't trigger exceptions.
4250
        repr(response)
2432.4.2 by Robert Collins
Add FailedSmartServerResponse.
4251
4252
    def test_is_successful(self):
4253
        """is_successful should return False for FailedSmartServerResponse."""
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
4254
        response = _mod_request.FailedSmartServerResponse((b'error',))
2432.4.2 by Robert Collins
Add FailedSmartServerResponse.
4255
        self.assertEqual(False, response.is_successful())
4256
2432.4.1 by Robert Collins
Add SuccessfulSmartServerResponse.
4257
2018.2.6 by Andrew Bennetts
HTTP client starting to work (pycurl for the moment).
4258
class FakeHTTPMedium(object):
4259
    def __init__(self):
4260
        self.written_request = None
4261
        self._current_request = None
7143.15.2 by Jelmer Vernooij
Run autopep8.
4262
2018.2.8 by Andrew Bennetts
Make HttpTransportBase.get_smart_client return self again.
4263
    def send_http_smart_request(self, bytes):
2018.2.6 by Andrew Bennetts
HTTP client starting to work (pycurl for the moment).
4264
        self.written_request = bytes
4265
        return None
4266
4267
3111.1.25 by Vincent Ladeuil
Fix the smart server failing test and use it against protocol combinations.
4268
class HTTPTunnellingSmokeTest(tests.TestCase):
4269
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)
4270
    def setUp(self):
4271
        super(HTTPTunnellingSmokeTest, self).setUp()
4272
        # We use the VFS layer as part of HTTP tunnelling tests.
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
4273
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
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)
4274
2018.2.6 by Andrew Bennetts
HTTP client starting to work (pycurl for the moment).
4275
    def test_smart_http_medium_request_accept_bytes(self):
4276
        medium = FakeHTTPMedium()
5010.2.9 by Vincent Ladeuil
Fix test_smart_transport.py imports.
4277
        request = http.SmartClientHTTPMediumRequest(medium)
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4278
        request.accept_bytes(b'abc')
4279
        request.accept_bytes(b'def')
2018.2.6 by Andrew Bennetts
HTTP client starting to work (pycurl for the moment).
4280
        self.assertEqual(None, medium.written_request)
4281
        request.finished_writing()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
4282
        self.assertEqual(b'abcdef', medium.written_request)
2018.2.6 by Andrew Bennetts
HTTP client starting to work (pycurl for the moment).
4283
2018.5.26 by Andrew Bennetts
Extract a simple SmartClient class from RemoteTransport, and a hack to avoid VFS operations when probing for a bzrdir over a smart transport.
4284
2208.4.4 by Andrew Bennetts
Merge bzr.dev.
4285
class RemoteHTTPTransportTestCase(tests.TestCase):
2208.4.2 by Andrew Bennetts
Always POST to the same .bzr/smart URL for a given branch, even when accessing files in subdirectories.
4286
2208.4.3 by Andrew Bennetts
Let SmartHTTPTransport.clone('..') continue to POST to the cloned URL (unlike clone('child')).
4287
    def test_remote_path_after_clone_child(self):
2208.4.2 by Andrew Bennetts
Always POST to the same .bzr/smart URL for a given branch, even when accessing files in subdirectories.
4288
        # If a user enters "bzr+http://host/foo", we want to sent all smart
2208.4.3 by Andrew Bennetts
Let SmartHTTPTransport.clone('..') continue to POST to the cloned URL (unlike clone('child')).
4289
        # requests for child URLs of that to the original URL.  i.e., we want to
4290
        # POST to "bzr+http://host/foo/.bzr/smart" and never something like
4291
        # "bzr+http://host/foo/.bzr/branch/.bzr/smart".  So, a cloned
3878.4.6 by Vincent Ladeuil
Fix bug #270863 by preserving 'bzr+http[s]' decorator.
4292
        # RemoteHTTPTransport remembers the initial URL, and adjusts the
4293
        # relpaths it sends in smart requests accordingly.
2208.4.4 by Andrew Bennetts
Merge bzr.dev.
4294
        base_transport = remote.RemoteHTTPTransport('bzr+http://host/path')
2208.4.2 by Andrew Bennetts
Always POST to the same .bzr/smart URL for a given branch, even when accessing files in subdirectories.
4295
        new_transport = base_transport.clone('child_dir')
2208.4.3 by Andrew Bennetts
Let SmartHTTPTransport.clone('..') continue to POST to the cloned URL (unlike clone('child')).
4296
        self.assertEqual(base_transport._http_transport,
4297
                         new_transport._http_transport)
2208.4.2 by Andrew Bennetts
Always POST to the same .bzr/smart URL for a given branch, even when accessing files in subdirectories.
4298
        self.assertEqual('child_dir/foo', new_transport._remote_path('foo'))
3431.3.8 by Andrew Bennetts
Add two tests that fail without the fixes in this branch.
4299
        self.assertEqual(
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
4300
            b'child_dir/',
3431.3.8 by Andrew Bennetts
Add two tests that fail without the fixes in this branch.
4301
            new_transport._client.remote_path_from_transport(new_transport))
2208.4.3 by Andrew Bennetts
Let SmartHTTPTransport.clone('..') continue to POST to the cloned URL (unlike clone('child')).
4302
2466.3.1 by Andrew Bennetts
Normalise URLs in RemoteHTTPTransport before doing URL calculations to fix bad results.
4303
    def test_remote_path_unnormal_base(self):
4304
        # If the transport's base isn't normalised, the _remote_path should
4305
        # still be calculated correctly.
4306
        base_transport = remote.RemoteHTTPTransport('bzr+http://host/%7Ea/b')
4307
        self.assertEqual('c', base_transport._remote_path('c'))
4308
4309
    def test_clone_unnormal_base(self):
4310
        # If the transport's base isn't normalised, cloned transports should
4311
        # still work correctly.
4312
        base_transport = remote.RemoteHTTPTransport('bzr+http://host/%7Ea/b')
4313
        new_transport = base_transport.clone('c')
6061.1.9 by Martin Packman
Unbreak test_clone_unnormal_base by not asserting url keeps tilde escaped
4314
        self.assertEqual(base_transport.base + 'c/', new_transport.base)
3431.3.8 by Andrew Bennetts
Add two tests that fail without the fixes in this branch.
4315
        self.assertEqual(
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
4316
            b'c/',
3431.3.8 by Andrew Bennetts
Add two tests that fail without the fixes in this branch.
4317
            new_transport._client.remote_path_from_transport(new_transport))
2466.3.1 by Andrew Bennetts
Normalise URLs in RemoteHTTPTransport before doing URL calculations to fix bad results.
4318
3878.4.6 by Vincent Ladeuil
Fix bug #270863 by preserving 'bzr+http[s]' decorator.
4319
    def test__redirect_to(self):
4320
        t = remote.RemoteHTTPTransport('bzr+http://www.example.com/foo')
4321
        r = t._redirected_to('http://www.example.com/foo',
4322
                             'http://www.example.com/bar')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4323
        self.assertEqual(type(r), type(t))
3878.4.6 by Vincent Ladeuil
Fix bug #270863 by preserving 'bzr+http[s]' decorator.
4324
4325
    def test__redirect_sibling_protocol(self):
4326
        t = remote.RemoteHTTPTransport('bzr+http://www.example.com/foo')
4327
        r = t._redirected_to('http://www.example.com/foo',
4328
                             'https://www.example.com/bar')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4329
        self.assertEqual(type(r), type(t))
3878.4.6 by Vincent Ladeuil
Fix bug #270863 by preserving 'bzr+http[s]' decorator.
4330
        self.assertStartsWith(r.base, 'bzr+https')
4331
4332
    def test__redirect_to_with_user(self):
4333
        t = remote.RemoteHTTPTransport('bzr+http://joe@www.example.com/foo')
4334
        r = t._redirected_to('http://www.example.com/foo',
4335
                             'http://www.example.com/bar')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4336
        self.assertEqual(type(r), type(t))
4337
        self.assertEqual('joe', t._parsed_url.user)
4338
        self.assertEqual(t._parsed_url.user, r._parsed_url.user)
3878.4.6 by Vincent Ladeuil
Fix bug #270863 by preserving 'bzr+http[s]' decorator.
4339
4340
    def test_redirected_to_same_host_different_protocol(self):
4341
        t = remote.RemoteHTTPTransport('bzr+http://joe@www.example.com/foo')
4342
        r = t._redirected_to('http://www.example.com/foo',
6939.3.1 by Jelmer Vernooij
Remove ftp.
4343
                             'bzr://www.example.com/foo')
6614.1.2 by Vincent Ladeuil
Fix assertNotEquals being deprecated by using assertNotEqual.
4344
        self.assertNotEqual(type(r), type(t))