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