/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5557.1.15 by John Arbash Meinel
Merge bzr.dev 5597 to resolve NEWS, aka bzr-2.3.txt
1
# Copyright (C) 2006-2009, 2011 Canonical Ltd
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
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
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
16
17
"""Tests for WSGI application"""
18
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
19
from .. import tests
20
from ..sixish import (
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
21
    BytesIO,
22
    )
6670.4.16 by Jelmer Vernooij
Move smart to breezy.bzr.
23
from ..bzr.smart import medium, protocol
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
24
from ..transport.http import wsgi
25
from ..transport import chroot, memory
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
26
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
27
4760.1.2 by Andrew Bennetts
Add test that WSGI glue allows request handlers to access paths above that request's. backing transport, so long as it is within the WSGI app's backing transport.
28
class WSGITestMixin(object):
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
29
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
30
    def build_environ(self, updates=None):
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
31
        """Builds an environ dict with all fields required by PEP 333.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
32
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
33
        :param updates: a dict to that will be incorporated into the returned
34
            dict using dict.update(updates).
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
35
        """
36
        environ = {
37
            # Required CGI variables
38
            'REQUEST_METHOD': 'GET',
39
            'SCRIPT_NAME': '/script/name/',
40
            'PATH_INFO': 'path/info',
41
            'SERVER_NAME': 'test',
42
            'SERVER_PORT': '9999',
43
            'SERVER_PROTOCOL': 'HTTP/1.0',
44
45
            # Required WSGI variables
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
46
            'wsgi.version': (1, 0),
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
47
            'wsgi.url_scheme': 'http',
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
48
            'wsgi.input': BytesIO(b''),
49
            'wsgi.errors': BytesIO(),
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
50
            'wsgi.multithread': False,
51
            'wsgi.multiprocess': False,
52
            'wsgi.run_once': True,
53
        }
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
54
        if updates is not None:
55
            environ.update(updates)
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
56
        return environ
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
57
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
58
    def read_response(self, iterable):
7045.2.6 by Jelmer Vernooij
Fix some wsgi tests.
59
        response = b''
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
60
        for string in iterable:
61
            response += string
62
        return response
63
64
    def start_response(self, status, headers):
65
        self.status = status
66
        self.headers = headers
67
4760.1.2 by Andrew Bennetts
Add test that WSGI glue allows request handlers to access paths above that request's. backing transport, so long as it is within the WSGI app's backing transport.
68
6404.2.1 by Vincent Ladeuil
Cleanup a test that requires a log file in some cases
69
class TestWSGI(tests.TestCaseInTempDir, WSGITestMixin):
4760.1.2 by Andrew Bennetts
Add test that WSGI glue allows request handlers to access paths above that request's. backing transport, so long as it is within the WSGI app's backing transport.
70
71
    def setUp(self):
6552.1.1 by Vincent Ladeuil
Hmpf, one more case where using super() is safer. This TestWSGI.setUp() were by-passing its base class setUp().
72
        super(TestWSGI, self).setUp()
4760.1.2 by Andrew Bennetts
Add test that WSGI glue allows request handlers to access paths above that request's. backing transport, so long as it is within the WSGI app's backing transport.
73
        self.status = None
74
        self.headers = None
75
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
76
    def test_construct(self):
2018.4.11 by Andrew Bennetts
Use ChrootTransportDecorator so that the WSGI server won't let you access the entire filesystem.
77
        app = wsgi.SmartWSGIApp(FakeTransport())
78
        self.assertIsInstance(
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
79
            app.backing_transport, chroot.ChrootTransport)
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
80
81
    def test_http_get_rejected(self):
82
        # GET requests are rejected.
2018.4.11 by Andrew Bennetts
Use ChrootTransportDecorator so that the WSGI server won't let you access the entire filesystem.
83
        app = wsgi.SmartWSGIApp(FakeTransport())
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
84
        environ = self.build_environ({'REQUEST_METHOD': 'GET'})
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
85
        iterable = app(environ, self.start_response)
86
        self.read_response(iterable)
87
        self.assertEqual('405 Method not allowed', self.status)
88
        self.assertTrue(('Allow', 'POST') in self.headers)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
89
2692.1.14 by Andrew Bennetts
All WSGI tests passing, and manual testing works too.
90
    def _fake_make_request(self, transport, write_func, bytes, rcp):
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
91
        request = FakeRequest(transport, write_func)
92
        request.accept_bytes(bytes)
93
        self.request = request
94
        return request
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
95
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
96
    def test_smart_wsgi_app_uses_given_relpath(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
97
        # The SmartWSGIApp should use the "breezy.relpath" field from the
2379.2.1 by Robert Collins
Rewritten chroot transport that prevents accidental chroot escapes when
98
        # WSGI environ to clone from its backing transport to get a specific
99
        # transport for this request.
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
100
        transport = FakeTransport()
101
        wsgi_app = wsgi.SmartWSGIApp(transport)
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
102
        wsgi_app.backing_transport = transport
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
103
        wsgi_app.make_request = self._fake_make_request
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
104
        fake_input = BytesIO(b'fake request')
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
105
        environ = self.build_environ({
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
106
            'REQUEST_METHOD': 'POST',
107
            'CONTENT_LENGTH': len(fake_input.getvalue()),
108
            'wsgi.input': fake_input,
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
109
            'breezy.relpath': 'foo/bar',
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
110
        })
111
        iterable = wsgi_app(environ, self.start_response)
112
        response = self.read_response(iterable)
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
113
        self.assertEqual([('clone', 'foo/bar/')], transport.calls)
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
114
115
    def test_smart_wsgi_app_request_and_response(self):
116
        # SmartWSGIApp reads the smart request from the 'wsgi.input' file-like
117
        # object in the environ dict, and returns the response via the iterable
118
        # returned to the WSGI handler.
119
        transport = memory.MemoryTransport()
7045.1.1 by Jelmer Vernooij
Fix another 300 tests.
120
        transport.put_bytes('foo', b'some bytes')
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
121
        wsgi_app = wsgi.SmartWSGIApp(transport)
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
122
        wsgi_app.make_request = self._fake_make_request
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
123
        fake_input = BytesIO(b'fake request')
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
124
        environ = self.build_environ({
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
125
            'REQUEST_METHOD': 'POST',
126
            'CONTENT_LENGTH': len(fake_input.getvalue()),
127
            'wsgi.input': fake_input,
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
128
            'breezy.relpath': 'foo',
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
129
        })
130
        iterable = wsgi_app(environ, self.start_response)
131
        response = self.read_response(iterable)
132
        self.assertEqual('200 OK', self.status)
7045.1.13 by Jelmer Vernooij
Fix a few more tests.
133
        self.assertEqual(b'got bytes: fake request', response)
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
134
135
    def test_relpath_setter(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
136
        # wsgi.RelpathSetter is WSGI "middleware" to set the 'breezy.relpath'
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
137
        # variable.
138
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
139
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
140
        def fake_app(environ, start_response):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
141
            calls.append(environ['breezy.relpath'])
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
142
        wrapped_app = wsgi.RelpathSetter(
143
            fake_app, prefix='/abc/', path_var='FOO')
144
        wrapped_app({'FOO': '/abc/xyz/.bzr/smart'}, None)
145
        self.assertEqual(['xyz'], calls)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
146
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
147
    def test_relpath_setter_bad_path_prefix(self):
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
148
        # wsgi.RelpathSetter will reject paths with that don't match the prefix
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
149
        # with a 404.  This is probably a sign of misconfiguration; a server
150
        # shouldn't ever be invoking our WSGI application with bad paths.
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
151
        def fake_app(environ, start_response):
152
            self.fail('The app should never be called when the path is wrong')
153
        wrapped_app = wsgi.RelpathSetter(
154
            fake_app, prefix='/abc/', path_var='FOO')
155
        iterable = wrapped_app(
156
            {'FOO': 'AAA/abc/xyz/.bzr/smart'}, self.start_response)
157
        self.read_response(iterable)
158
        self.assertTrue(self.status.startswith('404'))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
159
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
160
    def test_relpath_setter_bad_path_suffix(self):
161
        # Similar to test_relpath_setter_bad_path_prefix: wsgi.RelpathSetter
162
        # will reject paths with that don't match the suffix '.bzr/smart' with a
163
        # 404 as well.  Again, this shouldn't be seen by our WSGI application if
164
        # the server is configured correctly.
165
        def fake_app(environ, start_response):
166
            self.fail('The app should never be called when the path is wrong')
167
        wrapped_app = wsgi.RelpathSetter(
168
            fake_app, prefix='/abc/', path_var='FOO')
169
        iterable = wrapped_app(
170
            {'FOO': '/abc/xyz/.bzr/AAA'}, self.start_response)
171
        self.read_response(iterable)
172
        self.assertTrue(self.status.startswith('404'))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
173
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
174
    def test_make_app(self):
175
        # The make_app helper constructs a SmartWSGIApp wrapped in a
176
        # RelpathSetter.
177
        app = wsgi.make_app(
178
            root='a root',
179
            prefix='a prefix',
180
            path_var='a path_var')
181
        self.assertIsInstance(app, wsgi.RelpathSetter)
182
        self.assertIsInstance(app.app, wsgi.SmartWSGIApp)
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
183
        self.assertStartsWith(app.app.backing_transport.base, 'chroot-')
184
        backing_transport = app.app.backing_transport
185
        chroot_backing_transport = backing_transport.server.backing_transport
186
        self.assertEndsWith(chroot_backing_transport.base, 'a%20root/')
2692.1.14 by Andrew Bennetts
All WSGI tests passing, and manual testing works too.
187
        self.assertEqual(app.app.root_client_path, 'a prefix')
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
188
        self.assertEqual(app.path_var, 'a path_var')
189
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
190
    def test_incomplete_request(self):
191
        transport = FakeTransport()
192
        wsgi_app = wsgi.SmartWSGIApp(transport)
7143.15.2 by Jelmer Vernooij
Run autopep8.
193
2692.1.14 by Andrew Bennetts
All WSGI tests passing, and manual testing works too.
194
        def make_request(transport, write_func, bytes, root_client_path):
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
195
            request = IncompleteRequest(transport, write_func)
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
196
            request.accept_bytes(bytes)
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
197
            self.request = request
198
            return request
199
        wsgi_app.make_request = make_request
200
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
201
        fake_input = BytesIO(b'incomplete request')
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
202
        environ = self.build_environ({
203
            'REQUEST_METHOD': 'POST',
204
            'CONTENT_LENGTH': len(fake_input.getvalue()),
205
            'wsgi.input': fake_input,
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
206
            'breezy.relpath': 'foo/bar',
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
207
        })
208
        iterable = wsgi_app(environ, self.start_response)
209
        response = self.read_response(iterable)
210
        self.assertEqual('200 OK', self.status)
7045.1.13 by Jelmer Vernooij
Fix a few more tests.
211
        self.assertEqual(b'error\x01incomplete request\n', response)
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
212
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
213
    def test_protocol_version_detection_one(self):
2432.2.7 by Andrew Bennetts
Use less confusing version strings, and define REQUEST_VERSION_TWO/RESPONSE_VERSION_TWO constants for them.
214
        # SmartWSGIApp detects requests that don't start with
215
        # REQUEST_VERSION_TWO as version one.
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
216
        transport = memory.MemoryTransport()
217
        wsgi_app = wsgi.SmartWSGIApp(transport)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
218
        fake_input = BytesIO(b'hello\n')
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
219
        environ = self.build_environ({
220
            'REQUEST_METHOD': 'POST',
221
            'CONTENT_LENGTH': len(fake_input.getvalue()),
222
            'wsgi.input': fake_input,
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
223
            'breezy.relpath': 'foo',
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
224
        })
225
        iterable = wsgi_app(environ, self.start_response)
226
        response = self.read_response(iterable)
227
        self.assertEqual('200 OK', self.status)
228
        # Expect a version 1-encoded response.
7045.2.6 by Jelmer Vernooij
Fix some wsgi tests.
229
        self.assertEqual(b'ok\x012\n', response)
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
230
231
    def test_protocol_version_detection_two(self):
2432.2.7 by Andrew Bennetts
Use less confusing version strings, and define REQUEST_VERSION_TWO/RESPONSE_VERSION_TWO constants for them.
232
        # SmartWSGIApp detects requests that start with REQUEST_VERSION_TWO
233
        # as version two.
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
234
        transport = memory.MemoryTransport()
235
        wsgi_app = wsgi.SmartWSGIApp(transport)
7045.1.13 by Jelmer Vernooij
Fix a few more tests.
236
        fake_input = BytesIO(protocol.REQUEST_VERSION_TWO + b'hello\n')
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
237
        environ = self.build_environ({
238
            'REQUEST_METHOD': 'POST',
239
            'CONTENT_LENGTH': len(fake_input.getvalue()),
240
            'wsgi.input': fake_input,
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
241
            'breezy.relpath': 'foo',
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
242
        })
243
        iterable = wsgi_app(environ, self.start_response)
244
        response = self.read_response(iterable)
245
        self.assertEqual('200 OK', self.status)
246
        # Expect a version 2-encoded response.
2432.3.5 by Andrew Bennetts
Merge Robert's status prefix changes to protocol 2.
247
        self.assertEqual(
7045.1.13 by Jelmer Vernooij
Fix a few more tests.
248
            protocol.RESPONSE_VERSION_TWO + b'success\nok\x012\n', response)
2432.2.2 by Andrew Bennetts
Smart server mediums now detect which protocol version a request is and dispatch accordingly.
249
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
250
4760.1.2 by Andrew Bennetts
Add test that WSGI glue allows request handlers to access paths above that request's. backing transport, so long as it is within the WSGI app's backing transport.
251
class TestWSGIJail(tests.TestCaseWithMemoryTransport, WSGITestMixin):
252
253
    def make_hpss_wsgi_request(self, wsgi_relpath, *args):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
254
        write_buf = BytesIO()
4760.1.2 by Andrew Bennetts
Add test that WSGI glue allows request handlers to access paths above that request's. backing transport, so long as it is within the WSGI app's backing transport.
255
        request_medium = medium.SmartSimplePipesClientMedium(
256
            None, write_buf, 'fake:' + wsgi_relpath)
257
        request_encoder = protocol.ProtocolThreeRequester(
258
            request_medium.get_request())
259
        request_encoder.call(*args)
260
        write_buf.seek(0)
261
        environ = self.build_environ({
262
            'REQUEST_METHOD': 'POST',
263
            'CONTENT_LENGTH': len(write_buf.getvalue()),
264
            'wsgi.input': write_buf,
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
265
            'breezy.relpath': wsgi_relpath,
4760.1.2 by Andrew Bennetts
Add test that WSGI glue allows request handlers to access paths above that request's. backing transport, so long as it is within the WSGI app's backing transport.
266
        })
267
        return environ
268
269
    def test_jail_root(self):
270
        """The WSGI HPSS glue allows access to the whole WSGI backing
271
        transport, regardless of which HTTP path the request was delivered
272
        to.
273
        """
274
        # make a branch in a shared repo
275
        self.make_repository('repo', shared=True)
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
276
        branch = self.make_controldir('repo/branch').create_branch()
4760.1.2 by Andrew Bennetts
Add test that WSGI glue allows request handlers to access paths above that request's. backing transport, so long as it is within the WSGI app's backing transport.
277
        # serve the repo via bzr+http WSGI
278
        wsgi_app = wsgi.SmartWSGIApp(self.get_transport())
279
        # send a request to /repo/branch that will have to access /repo.
280
        environ = self.make_hpss_wsgi_request(
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
281
            '/repo/branch', b'BzrDir.open_branchV2', b'.')
4760.1.2 by Andrew Bennetts
Add test that WSGI glue allows request handlers to access paths above that request's. backing transport, so long as it is within the WSGI app's backing transport.
282
        iterable = wsgi_app(environ, self.start_response)
283
        response_bytes = self.read_response(iterable)
284
        self.assertEqual('200 OK', self.status)
285
        # expect a successful response, rather than a jail break error
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
286
        from breezy.tests.test_smart_transport import LoggingMessageHandler
4760.1.2 by Andrew Bennetts
Add test that WSGI glue allows request handlers to access paths above that request's. backing transport, so long as it is within the WSGI app's backing transport.
287
        message_handler = LoggingMessageHandler()
288
        decoder = protocol.ProtocolThreeDecoder(
289
            message_handler, expect_version_marker=True)
290
        decoder.accept_bytes(response_bytes)
291
        self.assertTrue(
7045.2.6 by Jelmer Vernooij
Fix some wsgi tests.
292
            ('structure', (b'branch', branch._format.network_name()))
4760.1.2 by Andrew Bennetts
Add test that WSGI glue allows request handlers to access paths above that request's. backing transport, so long as it is within the WSGI app's backing transport.
293
            in message_handler.event_log)
294
295
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
296
class FakeRequest(object):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
297
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
298
    def __init__(self, transport, write_func):
299
        self.transport = transport
300
        self.write_func = write_func
7045.1.1 by Jelmer Vernooij
Fix another 300 tests.
301
        self.accepted_bytes = b''
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
302
303
    def accept_bytes(self, bytes):
304
        self.accepted_bytes = bytes
7045.1.13 by Jelmer Vernooij
Fix a few more tests.
305
        self.write_func(b'got bytes: ' + bytes)
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
306
307
    def next_read_size(self):
308
        return 0
309
310
311
class FakeTransport(object):
312
313
    def __init__(self):
314
        self.calls = []
2018.4.11 by Andrew Bennetts
Use ChrootTransportDecorator so that the WSGI server won't let you access the entire filesystem.
315
        self.base = 'fake:///'
316
317
    def abspath(self, relpath):
318
        return 'fake:///' + relpath
2018.4.1 by Andrew Bennetts
Add WSGI smart server.
319
320
    def clone(self, relpath):
321
        self.calls.append(('clone', relpath))
322
        return self
323
2018.4.5 by Andrew Bennetts
Improvement thanks to John's review.
324
325
class IncompleteRequest(FakeRequest):
326
    """A request-like object that always expects to read more bytes."""
327
328
    def next_read_size(self):
329
        # this request always asks for more
330
        return 1