/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1
# Copyright (C) 2006-2010, 2012, 2013, 2016 Canonical Ltd
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
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
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
16
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
17
"""Tests from HTTP response parsing.
18
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
19
The handle_response method read the response body of a GET request an returns
20
the corresponding RangeFile.
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
21
22
There are four different kinds of RangeFile:
23
- a whole file whose size is unknown, seen as a simple byte stream,
24
- a whole file whose size is known, we can't read past its end,
25
- a single range file, a part of a file with a start and a size,
26
- a multiple range file, several consecutive parts with known start offset
27
  and size.
28
29
Some properties are common to all kinds:
30
- seek can only be forward (its really a socket underneath),
31
- read can't cross ranges,
32
- successive ranges are taken into account transparently,
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
33
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
34
- the expected pattern of use is either seek(offset)+read(size) or a single
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
35
  read with no size specified. For multiple range files, multiple read() will
36
  return the corresponding ranges, trying to read further will raise
37
  InvalidHttpResponse.
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
38
"""
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
39
6791.2.3 by Jelmer Vernooij
Fix more imports.
40
try:
41
    import http.client as http_client
7295.1.1 by Matthew Fuller
Fix with py2.7 + future
42
except ImportError:  # python < 3 without future
43
    import httplib as http_client
44
45
try:
7067.8.2 by Jelmer Vernooij
Fix some http response tests.
46
    parse_headers = http_client.parse_headers
7295.1.1 by Matthew Fuller
Fix with py2.7 + future
47
except AttributeError:  # python 2
7067.8.2 by Jelmer Vernooij
Fix some http response tests.
48
    parse_headers = http_client.HTTPMessage
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
49
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
50
from .. import (
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
51
    errors,
52
    tests,
53
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
54
from ..sixish import (
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
55
    BytesIO,
56
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
57
from ..transport.http import (
3104.3.4 by Vincent Ladeuil
Add test.
58
    response,
59
    _urllib2_wrappers,
60
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
61
from .file_utils import (
3408.6.1 by Eric Holmberg
Fix for Bug #215426 in which bzr can cause a MemoryError in socket.recv while
62
    FakeReadFile,
63
    )
3104.3.4 by Vincent Ladeuil
Add test.
64
65
66
class ReadSocket(object):
67
    """A socket-like object that can be given a predefined content."""
68
69
    def __init__(self, data):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
70
        self.readfile = BytesIO(data)
3104.3.4 by Vincent Ladeuil
Add test.
71
72
    def makefile(self, mode='r', bufsize=None):
73
        return self.readfile
74
3408.6.1 by Eric Holmberg
Fix for Bug #215426 in which bzr can cause a MemoryError in socket.recv while
75
3104.3.4 by Vincent Ladeuil
Add test.
76
class FakeHTTPConnection(_urllib2_wrappers.HTTPConnection):
77
78
    def __init__(self, sock):
79
        _urllib2_wrappers.HTTPConnection.__init__(self, 'localhost')
80
        # Set the socket to bypass the connection
81
        self.sock = sock
82
83
    def send(self, str):
84
        """Ignores the writes on the socket."""
85
        pass
86
87
6575.1.2 by Vincent Ladeuil
TDD backwards, works here ;)
88
class TestResponseFileIter(tests.TestCase):
89
90
    def test_iter_empty(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
91
        f = response.ResponseFile('empty', BytesIO())
6575.1.3 by Vincent Ladeuil
Simpler.
92
        self.assertEqual([], list(f))
6575.1.2 by Vincent Ladeuil
TDD backwards, works here ;)
93
94
    def test_iter_many(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
95
        f = response.ResponseFile('many', BytesIO(b'0\n1\nboo!\n'))
6973.11.6 by Jelmer Vernooij
Fix more http tests.
96
        self.assertEqual([b'0\n', b'1\n', b'boo!\n'], list(f))
6575.1.2 by Vincent Ladeuil
TDD backwards, works here ;)
97
98
3104.3.4 by Vincent Ladeuil
Add test.
99
class TestHTTPConnection(tests.TestCase):
100
101
    def test_cleanup_pipe(self):
6973.11.6 by Jelmer Vernooij
Fix more http tests.
102
        sock = ReadSocket(b"""HTTP/1.1 200 OK\r
3104.3.4 by Vincent Ladeuil
Add test.
103
Content-Type: text/plain; charset=UTF-8\r
104
Content-Length: 18
105
\r
106
0123456789
107
garbage""")
108
        conn = FakeHTTPConnection(sock)
109
        # Simulate the request sending so that the connection will be able to
110
        # read the response.
111
        conn.putrequest('GET', 'http://localhost/fictious')
112
        conn.endheaders()
113
        # Now, get the response
114
        resp = conn.getresponse()
115
        # Read part of the response
6973.11.6 by Jelmer Vernooij
Fix more http tests.
116
        self.assertEqual(b'0123456789\n', resp.read(11))
3104.3.4 by Vincent Ladeuil
Add test.
117
        # Override the thresold to force the warning emission
7143.15.2 by Jelmer Vernooij
Run autopep8.
118
        conn._range_warning_thresold = 6  # There are 7 bytes pending
3104.3.4 by Vincent Ladeuil
Add test.
119
        conn.cleanup_pipe()
4794.1.15 by Robert Collins
Review feedback.
120
        self.assertContainsRe(self.get_log(), 'Got a 200 response when asking')
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
121
122
123
class TestRangeFileMixin(object):
124
    """Tests for accessing the first range in a RangeFile."""
125
126
    # A simple string used to represent a file part (also called a range), in
127
    # which offsets are easy to calculate for test writers. It's used as a
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
128
    # building block with slight variations but basically 'a' is the first char
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
129
    # of the range and 'z' is the last.
6973.11.6 by Jelmer Vernooij
Fix more http tests.
130
    alpha = b'abcdefghijklmnopqrstuvwxyz'
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
131
132
    def test_can_read_at_first_access(self):
133
        """Test that the just created file can be read."""
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
134
        self.assertEqual(self.alpha, self._file.read())
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
135
136
    def test_seek_read(self):
137
        """Test seek/read inside the range."""
138
        f = self._file
139
        start = self.first_range_start
140
        # Before any use, tell() should be at the range start
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
141
        self.assertEqual(start, f.tell())
7143.15.2 by Jelmer Vernooij
Run autopep8.
142
        cur = start  # For an overall offset assertion
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
143
        f.seek(start + 3)
144
        cur += 3
6973.11.6 by Jelmer Vernooij
Fix more http tests.
145
        self.assertEqual(b'def', f.read(3))
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
146
        cur += len('def')
147
        f.seek(4, 1)
148
        cur += 4
6973.11.6 by Jelmer Vernooij
Fix more http tests.
149
        self.assertEqual(b'klmn', f.read(4))
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
150
        cur += len('klmn')
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
151
        # read(0) in the middle of a range
6973.11.6 by Jelmer Vernooij
Fix more http tests.
152
        self.assertEqual(b'', f.read(0))
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
153
        # seek in place
154
        here = f.tell()
155
        f.seek(0, 1)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
156
        self.assertEqual(here, f.tell())
157
        self.assertEqual(cur, f.tell())
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
158
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
159
    def test_read_zero(self):
160
        f = self._file
6973.11.6 by Jelmer Vernooij
Fix more http tests.
161
        self.assertEqual(b'', f.read(0))
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
162
        f.seek(10, 1)
6973.11.6 by Jelmer Vernooij
Fix more http tests.
163
        self.assertEqual(b'', f.read(0))
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
164
165
    def test_seek_at_range_end(self):
166
        f = self._file
167
        f.seek(26, 1)
168
169
    def test_read_at_range_end(self):
170
        """Test read behaviour at range end."""
171
        f = self._file
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
172
        self.assertEqual(self.alpha, f.read())
6973.11.6 by Jelmer Vernooij
Fix more http tests.
173
        self.assertEqual(b'', f.read(0))
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
174
        self.assertRaises(errors.InvalidRange, f.read, 1)
175
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
176
    def test_unbounded_read_after_seek(self):
177
        f = self._file
178
        f.seek(24, 1)
179
        # Should not cross ranges
6973.11.6 by Jelmer Vernooij
Fix more http tests.
180
        self.assertEqual(b'yz', f.read())
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
181
182
    def test_seek_backwards(self):
183
        f = self._file
184
        start = self.first_range_start
185
        f.seek(start)
186
        f.read(12)
187
        self.assertRaises(errors.InvalidRange, f.seek, start + 5)
188
189
    def test_seek_outside_single_range(self):
190
        f = self._file
191
        if f._size == -1 or f._boundary is not None:
192
            raise tests.TestNotApplicable('Needs a fully defined range')
193
        # Will seek past the range and then errors out
194
        self.assertRaises(errors.InvalidRange,
195
                          f.seek, self.first_range_start + 27)
196
197
    def test_read_past_end_of_range(self):
198
        f = self._file
199
        if f._size == -1:
200
            raise tests.TestNotApplicable("Can't check an unknown size")
201
        start = self.first_range_start
202
        f.seek(start + 20)
203
        self.assertRaises(errors.InvalidRange, f.read, 10)
204
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
205
    def test_seek_from_end(self):
7143.15.2 by Jelmer Vernooij
Run autopep8.
206
        """Test seeking from the end of the file.
207
208
        The semantic is unclear in case of multiple ranges. Seeking from end
209
        exists only for the http transports, cannot be used if the file size is
210
        unknown and is not used in breezy itself. This test must be (and is)
211
        overridden by daughter classes.
212
213
        Reading from end makes sense only when a range has been requested from
214
        the end of the file (see HttpTransportBase._get() when using the
215
        'tail_amount' parameter). The HTTP response can only be a whole file or
216
        a single range.
217
        """
218
        f = self._file
219
        f.seek(-2, 2)
220
        self.assertEqual(b'yz', f.read())
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
221
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
222
223
class TestRangeFileSizeUnknown(tests.TestCase, TestRangeFileMixin):
224
    """Test a RangeFile for a whole file whose size is not known."""
225
226
    def setUp(self):
227
        super(TestRangeFileSizeUnknown, self).setUp()
228
        self._file = response.RangeFile('Whole_file_size_known',
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
229
                                        BytesIO(self.alpha))
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
230
        # We define no range, relying on RangeFile to provide default values
7143.15.2 by Jelmer Vernooij
Run autopep8.
231
        self.first_range_start = 0  # It's the whole file
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
232
233
    def test_seek_from_end(self):
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
234
        """See TestRangeFileMixin.test_seek_from_end.
235
236
        The end of the file can't be determined since the size is unknown.
237
        """
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
238
        self.assertRaises(errors.InvalidRange, self._file.seek, -1, 2)
239
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
240
    def test_read_at_range_end(self):
241
        """Test read behaviour at range end."""
242
        f = self._file
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
243
        self.assertEqual(self.alpha, f.read())
6973.11.6 by Jelmer Vernooij
Fix more http tests.
244
        self.assertEqual(b'', f.read(0))
245
        self.assertEqual(b'', f.read(1))
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
246
3537.1.1 by Vincent Ladeuil
Fix some more PEP8isms and delete useless import
247
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
248
class TestRangeFileSizeKnown(tests.TestCase, TestRangeFileMixin):
249
    """Test a RangeFile for a whole file whose size is known."""
250
251
    def setUp(self):
252
        super(TestRangeFileSizeKnown, self).setUp()
253
        self._file = response.RangeFile('Whole_file_size_known',
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
254
                                        BytesIO(self.alpha))
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
255
        self._file.set_range(0, len(self.alpha))
7143.15.2 by Jelmer Vernooij
Run autopep8.
256
        self.first_range_start = 0  # It's the whole file
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
257
258
259
class TestRangeFileSingleRange(tests.TestCase, TestRangeFileMixin):
260
    """Test a RangeFile for a single range."""
261
262
    def setUp(self):
263
        super(TestRangeFileSingleRange, self).setUp()
264
        self._file = response.RangeFile('Single_range_file',
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
265
                                        BytesIO(self.alpha))
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
266
        self.first_range_start = 15
267
        self._file.set_range(self.first_range_start, len(self.alpha))
268
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
269
    def test_read_before_range(self):
270
        # This can't occur under normal circumstances, we have to force it
271
        f = self._file
7143.15.2 by Jelmer Vernooij
Run autopep8.
272
        f._pos = 0  # Force an invalid pos
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
273
        self.assertRaises(errors.InvalidRange, f.read, 2)
274
3537.1.1 by Vincent Ladeuil
Fix some more PEP8isms and delete useless import
275
3146.3.2 by Vincent Ladeuil
Fix #179368 by keeping the current range hint on ShortReadvErrors.
276
class TestRangeFileMultipleRanges(tests.TestCase, TestRangeFileMixin):
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
277
    """Test a RangeFile for multiple ranges.
278
279
    The RangeFile used for the tests contains three ranges:
280
281
    - at offset 25: alpha
282
    - at offset 100: alpha
283
    - at offset 126: alpha.upper()
284
285
    The two last ranges are contiguous. This only rarely occurs (should not in
286
    fact) in real uses but may lead to hard to track bugs.
287
    """
3535.1.4 by adwi2
Changes as suggested by Mr Ladeuil.
288
289
    # The following is used to represent the boundary paramter defined
290
    # in HTTP response headers and the boundary lines that separate
291
    # multipart content.
292
6973.11.6 by Jelmer Vernooij
Fix more http tests.
293
    boundary = b"separation"
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
294
295
    def setUp(self):
3146.3.2 by Vincent Ladeuil
Fix #179368 by keeping the current range hint on ShortReadvErrors.
296
        super(TestRangeFileMultipleRanges, self).setUp()
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
297
3535.1.4 by adwi2
Changes as suggested by Mr Ladeuil.
298
        boundary = self.boundary
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
299
6973.11.6 by Jelmer Vernooij
Fix more http tests.
300
        content = b''
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
301
        self.first_range_start = 25
7143.15.2 by Jelmer Vernooij
Run autopep8.
302
        file_size = 200  # big enough to encompass all ranges
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
303
        for (start, part) in [(self.first_range_start, self.alpha),
304
                              # Two contiguous ranges
305
                              (100, self.alpha),
306
                              (126, self.alpha.upper())]:
307
            content += self._multipart_byterange(part, start, boundary,
308
                                                 file_size)
309
        # Final boundary
3535.1.4 by adwi2
Changes as suggested by Mr Ladeuil.
310
        content += self._boundary_line()
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
311
312
        self._file = response.RangeFile('Multiple_ranges_file',
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
313
                                        BytesIO(content))
3535.1.4 by adwi2
Changes as suggested by Mr Ladeuil.
314
        self.set_file_boundary()
315
316
    def _boundary_line(self):
317
        """Helper to build the formatted boundary line."""
6973.11.6 by Jelmer Vernooij
Fix more http tests.
318
        return b'--' + self.boundary + b'\r\n'
3535.1.4 by adwi2
Changes as suggested by Mr Ladeuil.
319
320
    def set_file_boundary(self):
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
321
        # Ranges are set by decoding the range headers, the RangeFile user is
322
        # supposed to call the following before using seek or read since it
323
        # requires knowing the *response* headers (in that case the boundary
324
        # which is part of the Content-Type header).
3535.1.4 by adwi2
Changes as suggested by Mr Ladeuil.
325
        self._file.set_boundary(self.boundary)
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
326
6973.11.6 by Jelmer Vernooij
Fix more http tests.
327
    def _multipart_byterange(self, data, offset, boundary, file_size=b'*'):
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
328
        """Encode a part of a file as a multipart/byterange MIME type.
329
330
        When a range request is issued, the HTTP response body can be
331
        decomposed in parts, each one representing a range (start, size) in a
332
        file.
333
334
        :param data: The payload.
335
        :param offset: where data starts in the file
336
        :param boundary: used to separate the parts
337
        :param file_size: the size of the file containing the range (default to
338
            '*' meaning unknown)
339
340
        :return: a string containing the data encoded as it will appear in the
341
            HTTP response body.
342
        """
3535.1.4 by adwi2
Changes as suggested by Mr Ladeuil.
343
        bline = self._boundary_line()
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
344
        # Each range begins with a boundary line
345
        range = bline
346
        # A range is described by a set of headers, but only 'Content-Range' is
347
        # required for our implementation (TestHandleResponse below will
348
        # exercise ranges with multiple or missing headers')
6973.11.6 by Jelmer Vernooij
Fix more http tests.
349
        if isinstance(file_size, int):
350
            file_size = b'%d' % file_size
351
        range += b'Content-Range: bytes %d-%d/%s\r\n' % (offset,
7143.15.2 by Jelmer Vernooij
Run autopep8.
352
                                                         offset +
353
                                                         len(data) - 1,
6973.11.6 by Jelmer Vernooij
Fix more http tests.
354
                                                         file_size)
355
        range += b'\r\n'
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
356
        # Finally the raw bytes
357
        range += data
358
        return range
359
360
    def test_read_all_ranges(self):
361
        f = self._file
7143.15.2 by Jelmer Vernooij
Run autopep8.
362
        self.assertEqual(self.alpha, f.read())  # Read first range
363
        f.seek(100)  # Trigger the second range recognition
364
        self.assertEqual(self.alpha, f.read())  # Read second range
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
365
        self.assertEqual(126, f.tell())
7143.15.2 by Jelmer Vernooij
Run autopep8.
366
        f.seek(126)  # Start of third range which is also the current pos !
6973.11.6 by Jelmer Vernooij
Fix more http tests.
367
        self.assertEqual(b'A', f.read(1))
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
368
        f.seek(10, 1)
6973.11.6 by Jelmer Vernooij
Fix more http tests.
369
        self.assertEqual(b'LMN', f.read(3))
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
370
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
371
    def test_seek_from_end(self):
372
        """See TestRangeFileMixin.test_seek_from_end."""
373
        # The actual implementation will seek from end for the first range only
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
374
        # and then fail. Since seeking from end is intended to be used for a
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
375
        # single range only anyway, this test just document the actual
376
        # behaviour.
377
        f = self._file
378
        f.seek(-2, 2)
6973.11.6 by Jelmer Vernooij
Fix more http tests.
379
        self.assertEqual(b'yz', f.read())
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
380
        self.assertRaises(errors.InvalidRange, f.seek, -2, 2)
381
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
382
    def test_seek_into_void(self):
383
        f = self._file
384
        start = self.first_range_start
385
        f.seek(start)
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
386
        # Seeking to a point between two ranges is possible (only once) but
387
        # reading there is forbidden
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
388
        f.seek(start + 40)
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
389
        # We crossed a range boundary, so now the file is positioned at the
390
        # start of the new range (i.e. trying to seek below 100 will error out)
391
        f.seek(100)
3059.2.7 by Vincent Ladeuil
Allow pycurl users to watch the blinkenlights and fix a bug when ranges are contiguous.
392
        f.seek(125)
393
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
394
    def test_seek_across_ranges(self):
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
395
        f = self._file
7143.15.2 by Jelmer Vernooij
Run autopep8.
396
        f.seek(126)  # skip the two first ranges
6973.11.6 by Jelmer Vernooij
Fix more http tests.
397
        self.assertEqual(b'AB', f.read(2))
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
398
3146.3.2 by Vincent Ladeuil
Fix #179368 by keeping the current range hint on ShortReadvErrors.
399
    def test_checked_read_dont_overflow_buffers(self):
400
        f = self._file
401
        # We force a very low value to exercise all code paths in _checked_read
402
        f._discarded_buf_size = 8
7143.15.2 by Jelmer Vernooij
Run autopep8.
403
        f.seek(126)  # skip the two first ranges
6973.11.6 by Jelmer Vernooij
Fix more http tests.
404
        self.assertEqual(b'AB', f.read(2))
3146.3.2 by Vincent Ladeuil
Fix #179368 by keeping the current range hint on ShortReadvErrors.
405
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
406
    def test_seek_twice_between_ranges(self):
407
        f = self._file
408
        start = self.first_range_start
7143.15.2 by Jelmer Vernooij
Run autopep8.
409
        f.seek(start + 40)  # Past the first range but before the second
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
410
        # Now the file is positioned at the second range start (100)
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
411
        self.assertRaises(errors.InvalidRange, f.seek, start + 41)
412
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
413
    def test_seek_at_range_end(self):
414
        """Test seek behavior at range end."""
415
        f = self._file
416
        f.seek(25 + 25)
417
        f.seek(100 + 25)
418
        f.seek(126 + 25)
419
420
    def test_read_at_range_end(self):
421
        f = self._file
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
422
        self.assertEqual(self.alpha, f.read())
423
        self.assertEqual(self.alpha, f.read())
424
        self.assertEqual(self.alpha.upper(), f.read())
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
425
        self.assertRaises(errors.InvalidHttpResponse, f.read, 1)
426
3537.1.1 by Vincent Ladeuil
Fix some more PEP8isms and delete useless import
427
3535.1.1 by Adrian Wilkins
Made the behaviour of the existing multi-range test more like the real thing by
428
class TestRangeFileMultipleRangesQuotedBoundaries(TestRangeFileMultipleRanges):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
429
    """Perform the same tests as TestRangeFileMultipleRanges, but uses
3535.1.1 by Adrian Wilkins
Made the behaviour of the existing multi-range test more like the real thing by
430
    an angle-bracket quoted boundary string like IIS 6.0 and 7.0
3535.1.4 by adwi2
Changes as suggested by Mr Ladeuil.
431
    (but not IIS 5, which breaks the RFC in a different way
432
    by using square brackets, not angle brackets)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
433
434
    This reveals a bug caused by
435
436
    - The bad implementation of RFC 822 unquoting in Python (angles are not
437
      quotes), coupled with
3535.1.4 by adwi2
Changes as suggested by Mr Ladeuil.
438
439
    - The bad implementation of RFC 2046 in IIS (angles are not permitted chars
440
      in boundary lines).
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
441
3535.1.1 by Adrian Wilkins
Made the behaviour of the existing multi-range test more like the real thing by
442
    """
3535.1.4 by adwi2
Changes as suggested by Mr Ladeuil.
443
    # The boundary as it appears in boundary lines
444
    # IIS 6 and 7 use this value
6973.11.6 by Jelmer Vernooij
Fix more http tests.
445
    _boundary_trimmed = b"q1w2e3r4t5y6u7i8o9p0zaxscdvfbgnhmjklkl"
446
    boundary = b'<' + _boundary_trimmed + b'>'
3535.1.4 by adwi2
Changes as suggested by Mr Ladeuil.
447
448
    def set_file_boundary(self):
449
        # Emulate broken rfc822.unquote() here by removing angles
450
        self._file.set_boundary(self._boundary_trimmed)
3537.1.1 by Vincent Ladeuil
Fix some more PEP8isms and delete useless import
451
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
452
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
453
class TestRangeFileVarious(tests.TestCase):
454
    """Tests RangeFile aspects not covered elsewhere."""
455
456
    def test_seek_whence(self):
457
        """Test the seek whence parameter values."""
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
458
        f = response.RangeFile('foo', BytesIO(b'abc'))
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
459
        f.set_range(0, 3)
460
        f.seek(0)
461
        f.seek(1, 1)
462
        f.seek(-1, 2)
463
        self.assertRaises(ValueError, f.seek, 0, 14)
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
464
465
    def test_range_syntax(self):
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
466
        """Test the Content-Range scanning."""
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
467
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
468
        f = response.RangeFile('foo', BytesIO())
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
469
470
        def ok(expected, header_value):
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
471
            f.set_range_from_header(header_value)
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
472
            # Slightly peek under the covers to get the size
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
473
            self.assertEqual(expected, (f.tell(), f._size))
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
474
475
        ok((1, 10), 'bytes 1-10/11')
476
        ok((1, 10), 'bytes 1-10/*')
477
        ok((12, 2), '\tbytes 12-13/*')
478
        ok((28, 1), '  bytes 28-28/*')
479
        ok((2123, 2120), 'bytes  2123-4242/12310')
7143.15.2 by Jelmer Vernooij
Run autopep8.
480
        ok((1, 10), 'bytes 1-10/ttt')  # We don't check total (ttt)
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
481
482
        def nok(header_value):
483
            self.assertRaises(errors.InvalidHttpRange,
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
484
                              f.set_range_from_header, header_value)
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
485
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
486
        nok('bytes 10-2/3')
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
487
        nok('chars 1-2/3')
488
        nok('bytes xx-yyy/zzz')
489
        nok('bytes xx-12/zzz')
490
        nok('bytes 11-yy/zzz')
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
491
        nok('bytes10-2/3')
1786.1.21 by John Arbash Meinel
(broken) Work on factoring out handle_response so we can test with fake headers.
492
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
493
1786.1.21 by John Arbash Meinel
(broken) Work on factoring out handle_response so we can test with fake headers.
494
# Taken from real request responses
6973.11.6 by Jelmer Vernooij
Fix more http tests.
495
_full_text_response = (200, b"""HTTP/1.1 200 OK\r
1786.1.21 by John Arbash Meinel
(broken) Work on factoring out handle_response so we can test with fake headers.
496
Date: Tue, 11 Jul 2006 04:32:56 GMT\r
497
Server: Apache/2.0.54 (Fedora)\r
498
Last-Modified: Sun, 23 Apr 2006 19:35:20 GMT\r
499
ETag: "56691-23-38e9ae00"\r
500
Accept-Ranges: bytes\r
501
Content-Length: 35\r
502
Connection: close\r
503
Content-Type: text/plain; charset=UTF-8\r
504
\r
6973.11.6 by Jelmer Vernooij
Fix more http tests.
505
""", b"""Bazaar-NG meta directory, format 1
1786.1.25 by John Arbash Meinel
Test that we can extract headers properly.
506
""")
507
508
6973.11.6 by Jelmer Vernooij
Fix more http tests.
509
_single_range_response = (206, b"""HTTP/1.1 206 Partial Content\r
1786.1.21 by John Arbash Meinel
(broken) Work on factoring out handle_response so we can test with fake headers.
510
Date: Tue, 11 Jul 2006 04:45:22 GMT\r
511
Server: Apache/2.0.54 (Fedora)\r
512
Last-Modified: Thu, 06 Jul 2006 20:22:05 GMT\r
513
ETag: "238a3c-16ec2-805c5540"\r
514
Accept-Ranges: bytes\r
515
Content-Length: 100\r
1786.1.26 by John Arbash Meinel
Update and test handle_response.
516
Content-Range: bytes 100-199/93890\r
1786.1.21 by John Arbash Meinel
(broken) Work on factoring out handle_response so we can test with fake headers.
517
Connection: close\r
518
Content-Type: text/plain; charset=UTF-8\r
519
\r
6973.11.6 by Jelmer Vernooij
Fix more http tests.
520
""", b"""mbp@sourcefrog.net-20050309040815-13242001617e4a06
1786.1.26 by John Arbash Meinel
Update and test handle_response.
521
mbp@sourcefrog.net-20050309040929-eee0eb3e6d1e762""")
522
523
6973.11.6 by Jelmer Vernooij
Fix more http tests.
524
_single_range_no_content_type = (206, b"""HTTP/1.1 206 Partial Content\r
2070.1.1 by John Arbash Meinel
Fix bug #62473 by not requiring content-type in range responses
525
Date: Tue, 11 Jul 2006 04:45:22 GMT\r
526
Server: Apache/2.0.54 (Fedora)\r
527
Last-Modified: Thu, 06 Jul 2006 20:22:05 GMT\r
528
ETag: "238a3c-16ec2-805c5540"\r
529
Accept-Ranges: bytes\r
530
Content-Length: 100\r
531
Content-Range: bytes 100-199/93890\r
532
Connection: close\r
533
\r
6973.11.6 by Jelmer Vernooij
Fix more http tests.
534
""", b"""mbp@sourcefrog.net-20050309040815-13242001617e4a06
2070.1.1 by John Arbash Meinel
Fix bug #62473 by not requiring content-type in range responses
535
mbp@sourcefrog.net-20050309040929-eee0eb3e6d1e762""")
536
537
6973.11.6 by Jelmer Vernooij
Fix more http tests.
538
_multipart_range_response = (206, b"""HTTP/1.1 206 Partial Content\r
1786.1.21 by John Arbash Meinel
(broken) Work on factoring out handle_response so we can test with fake headers.
539
Date: Tue, 11 Jul 2006 04:49:48 GMT\r
540
Server: Apache/2.0.54 (Fedora)\r
541
Last-Modified: Thu, 06 Jul 2006 20:22:05 GMT\r
542
ETag: "238a3c-16ec2-805c5540"\r
543
Accept-Ranges: bytes\r
544
Content-Length: 1534\r
545
Connection: close\r
546
Content-Type: multipart/byteranges; boundary=418470f848b63279b\r
547
\r
6973.11.6 by Jelmer Vernooij
Fix more http tests.
548
\r""", b"""--418470f848b63279b\r
1786.1.21 by John Arbash Meinel
(broken) Work on factoring out handle_response so we can test with fake headers.
549
Content-type: text/plain; charset=UTF-8\r
550
Content-range: bytes 0-254/93890\r
551
\r
552
mbp@sourcefrog.net-20050309040815-13242001617e4a06
553
mbp@sourcefrog.net-20050309040929-eee0eb3e6d1e7627
554
mbp@sourcefrog.net-20050309040957-6cad07f466bb0bb8
555
mbp@sourcefrog.net-20050309041501-c840e09071de3b67
556
mbp@sourcefrog.net-20050309044615-c24a3250be83220a
557
\r
558
--418470f848b63279b\r
559
Content-type: text/plain; charset=UTF-8\r
560
Content-range: bytes 1000-2049/93890\r
561
\r
562
40-fd4ec249b6b139ab
563
mbp@sourcefrog.net-20050311063625-07858525021f270b
564
mbp@sourcefrog.net-20050311231934-aa3776aff5200bb9
565
mbp@sourcefrog.net-20050311231953-73aeb3a131c3699a
566
mbp@sourcefrog.net-20050311232353-f5e33da490872c6a
567
mbp@sourcefrog.net-20050312071639-0a8f59a34a024ff0
568
mbp@sourcefrog.net-20050312073432-b2c16a55e0d6e9fb
569
mbp@sourcefrog.net-20050312073831-a47c3335ece1920f
570
mbp@sourcefrog.net-20050312085412-13373aa129ccbad3
571
mbp@sourcefrog.net-20050313052251-2bf004cb96b39933
572
mbp@sourcefrog.net-20050313052856-3edd84094687cb11
573
mbp@sourcefrog.net-20050313053233-e30a4f28aef48f9d
574
mbp@sourcefrog.net-20050313053853-7c64085594ff3072
575
mbp@sourcefrog.net-20050313054757-a86c3f5871069e22
576
mbp@sourcefrog.net-20050313061422-418f1f73b94879b9
577
mbp@sourcefrog.net-20050313120651-497bd231b19df600
578
mbp@sourcefrog.net-20050314024931-eae0170ef25a5d1a
579
mbp@sourcefrog.net-20050314025438-d52099f915fe65fc
580
mbp@sourcefrog.net-20050314025539-637a636692c055cf
581
mbp@sourcefrog.net-20050314025737-55eb441f430ab4ba
582
mbp@sourcefrog.net-20050314025901-d74aa93bb7ee8f62
583
mbp@source\r
1979.1.1 by John Arbash Meinel
Fix bug #57723, parse boundary="" correctly, since Squid uses it
584
--418470f848b63279b--\r
585
""")
586
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
587
6973.11.6 by Jelmer Vernooij
Fix more http tests.
588
_multipart_squid_range_response = (206, b"""HTTP/1.0 206 Partial Content\r
1979.1.1 by John Arbash Meinel
Fix bug #57723, parse boundary="" correctly, since Squid uses it
589
Date: Thu, 31 Aug 2006 21:16:22 GMT\r
590
Server: Apache/2.2.2 (Unix) DAV/2\r
591
Last-Modified: Thu, 31 Aug 2006 17:57:06 GMT\r
592
Accept-Ranges: bytes\r
593
Content-Type: multipart/byteranges; boundary="squid/2.5.STABLE12:C99323425AD4FE26F726261FA6C24196"\r
594
Content-Length: 598\r
595
X-Cache: MISS from localhost.localdomain\r
596
X-Cache-Lookup: HIT from localhost.localdomain:3128\r
597
Proxy-Connection: keep-alive\r
598
\r
599
""",
7143.15.2 by Jelmer Vernooij
Run autopep8.
600
                                   b"""\r
1979.1.1 by John Arbash Meinel
Fix bug #57723, parse boundary="" correctly, since Squid uses it
601
--squid/2.5.STABLE12:C99323425AD4FE26F726261FA6C24196\r
602
Content-Type: text/plain\r
603
Content-Range: bytes 0-99/18672\r
604
\r
605
# bzr knit index 8
606
607
scott@netsplit.com-20050708230047-47c7868f276b939f fulltext 0 863  :
608
scott@netsp\r
609
--squid/2.5.STABLE12:C99323425AD4FE26F726261FA6C24196\r
610
Content-Type: text/plain\r
611
Content-Range: bytes 300-499/18672\r
612
\r
613
com-20050708231537-2b124b835395399a :
614
scott@netsplit.com-20050820234126-551311dbb7435b51 line-delta 1803 479 .scott@netsplit.com-20050820232911-dc4322a084eadf7e :
615
scott@netsplit.com-20050821213706-c86\r
616
--squid/2.5.STABLE12:C99323425AD4FE26F726261FA6C24196--\r
1786.1.25 by John Arbash Meinel
Test that we can extract headers properly.
617
""")
618
619
1786.1.26 by John Arbash Meinel
Update and test handle_response.
620
# This is made up
6973.11.6 by Jelmer Vernooij
Fix more http tests.
621
_full_text_response_no_content_type = (200, b"""HTTP/1.1 200 OK\r
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
622
Date: Tue, 11 Jul 2006 04:32:56 GMT\r
623
Server: Apache/2.0.54 (Fedora)\r
624
Last-Modified: Sun, 23 Apr 2006 19:35:20 GMT\r
625
ETag: "56691-23-38e9ae00"\r
626
Accept-Ranges: bytes\r
627
Content-Length: 35\r
628
Connection: close\r
629
\r
6973.11.6 by Jelmer Vernooij
Fix more http tests.
630
""", b"""Bazaar-NG meta directory, format 1
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
631
""")
632
633
6973.11.6 by Jelmer Vernooij
Fix more http tests.
634
_full_text_response_no_content_length = (200, b"""HTTP/1.1 200 OK\r
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
635
Date: Tue, 11 Jul 2006 04:32:56 GMT\r
636
Server: Apache/2.0.54 (Fedora)\r
637
Last-Modified: Sun, 23 Apr 2006 19:35:20 GMT\r
638
ETag: "56691-23-38e9ae00"\r
639
Accept-Ranges: bytes\r
640
Connection: close\r
641
Content-Type: text/plain; charset=UTF-8\r
642
\r
6973.11.6 by Jelmer Vernooij
Fix more http tests.
643
""", b"""Bazaar-NG meta directory, format 1
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
644
""")
645
646
6973.11.6 by Jelmer Vernooij
Fix more http tests.
647
_single_range_no_content_range = (206, b"""HTTP/1.1 206 Partial Content\r
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
648
Date: Tue, 11 Jul 2006 04:45:22 GMT\r
649
Server: Apache/2.0.54 (Fedora)\r
650
Last-Modified: Thu, 06 Jul 2006 20:22:05 GMT\r
651
ETag: "238a3c-16ec2-805c5540"\r
652
Accept-Ranges: bytes\r
653
Content-Length: 100\r
654
Connection: close\r
655
\r
6973.11.6 by Jelmer Vernooij
Fix more http tests.
656
""", b"""mbp@sourcefrog.net-20050309040815-13242001617e4a06
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
657
mbp@sourcefrog.net-20050309040929-eee0eb3e6d1e762""")
658
659
6973.11.6 by Jelmer Vernooij
Fix more http tests.
660
_single_range_response_truncated = (206, b"""HTTP/1.1 206 Partial Content\r
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
661
Date: Tue, 11 Jul 2006 04:45:22 GMT\r
662
Server: Apache/2.0.54 (Fedora)\r
663
Last-Modified: Thu, 06 Jul 2006 20:22:05 GMT\r
664
ETag: "238a3c-16ec2-805c5540"\r
665
Accept-Ranges: bytes\r
666
Content-Length: 100\r
667
Content-Range: bytes 100-199/93890\r
668
Connection: close\r
669
Content-Type: text/plain; charset=UTF-8\r
670
\r
6973.11.6 by Jelmer Vernooij
Fix more http tests.
671
""", b"""mbp@sourcefrog.net-20050309040815-13242001617e4a06""")
672
673
674
_invalid_response = (444, b"""HTTP/1.1 444 Bad Response\r
1786.1.26 by John Arbash Meinel
Update and test handle_response.
675
Date: Tue, 11 Jul 2006 04:32:56 GMT\r
676
Connection: close\r
677
Content-Type: text/html; charset=iso-8859-1\r
678
\r
6973.11.6 by Jelmer Vernooij
Fix more http tests.
679
""", b"""<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
1786.1.26 by John Arbash Meinel
Update and test handle_response.
680
<html><head>
681
<title>404 Not Found</title>
682
</head><body>
683
<h1>Not Found</h1>
684
<p>I don't know what I'm doing</p>
685
<hr>
686
</body></html>
687
""")
688
689
6973.11.6 by Jelmer Vernooij
Fix more http tests.
690
_multipart_no_content_range = (206, b"""HTTP/1.0 206 Partial Content\r
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
691
Content-Type: multipart/byteranges; boundary=THIS_SEPARATES\r
692
Content-Length: 598\r
693
\r
694
""",
7143.15.2 by Jelmer Vernooij
Run autopep8.
695
                               b"""\r
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
696
--THIS_SEPARATES\r
697
Content-Type: text/plain\r
698
\r
699
# bzr knit index 8
700
--THIS_SEPARATES\r
701
""")
702
703
6973.11.6 by Jelmer Vernooij
Fix more http tests.
704
_multipart_no_boundary = (206, b"""HTTP/1.0 206 Partial Content\r
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
705
Content-Type: multipart/byteranges; boundary=THIS_SEPARATES\r
706
Content-Length: 598\r
707
\r
708
""",
7143.15.2 by Jelmer Vernooij
Run autopep8.
709
                          b"""\r
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
710
--THIS_SEPARATES\r
711
Content-Type: text/plain\r
712
Content-Range: bytes 0-18/18672\r
713
\r
714
# bzr knit index 8
715
716
The range ended at the line above, this text is garbage instead of a boundary
717
line
718
""")
719
720
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
721
class TestHandleResponse(tests.TestCase):
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
722
723
    def _build_HTTPMessage(self, raw_headers):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
724
        status_and_headers = BytesIO(raw_headers)
3059.2.11 by Vincent Ladeuil
Fix typos mentioned by spiv.
725
        # Get rid of the status line
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
726
        status_and_headers.readline()
7067.8.2 by Jelmer Vernooij
Fix some http response tests.
727
        msg = parse_headers(status_and_headers)
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
728
        return msg
729
1786.1.26 by John Arbash Meinel
Update and test handle_response.
730
    def get_response(self, a_response):
731
        """Process a supplied response, and return the result."""
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
732
        code, raw_headers, body = a_response
733
        msg = self._build_HTTPMessage(raw_headers)
734
        return response.handle_response('http://foo', code, msg,
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
735
                                        BytesIO(a_response[2]))
1786.1.26 by John Arbash Meinel
Update and test handle_response.
736
737
    def test_full_text(self):
738
        out = self.get_response(_full_text_response)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
739
        # It is a BytesIO from the original data
1786.1.26 by John Arbash Meinel
Update and test handle_response.
740
        self.assertEqual(_full_text_response[2], out.read())
741
742
    def test_single_range(self):
743
        out = self.get_response(_single_range_response)
744
745
        out.seek(100)
746
        self.assertEqual(_single_range_response[2], out.read(100))
747
2070.1.1 by John Arbash Meinel
Fix bug #62473 by not requiring content-type in range responses
748
    def test_single_range_no_content(self):
749
        out = self.get_response(_single_range_no_content_type)
750
751
        out.seek(100)
752
        self.assertEqual(_single_range_no_content_type[2], out.read(100))
753
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
754
    def test_single_range_truncated(self):
755
        out = self.get_response(_single_range_response_truncated)
756
        # Content-Range declares 100 but only 51 present
757
        self.assertRaises(errors.ShortReadvError, out.seek, out.tell() + 51)
758
1786.1.26 by John Arbash Meinel
Update and test handle_response.
759
    def test_multi_range(self):
760
        out = self.get_response(_multipart_range_response)
761
762
        # Just make sure we can read the right contents
763
        out.seek(0)
764
        out.read(255)
765
766
        out.seek(1000)
767
        out.read(1050)
768
1979.1.1 by John Arbash Meinel
Fix bug #57723, parse boundary="" correctly, since Squid uses it
769
    def test_multi_squid_range(self):
770
        out = self.get_response(_multipart_squid_range_response)
771
772
        # Just make sure we can read the right contents
773
        out.seek(0)
774
        out.read(100)
775
776
        out.seek(300)
777
        out.read(200)
778
1786.1.26 by John Arbash Meinel
Update and test handle_response.
779
    def test_invalid_response(self):
780
        self.assertRaises(errors.InvalidHttpResponse,
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
781
                          self.get_response, _invalid_response)
1786.1.26 by John Arbash Meinel
Update and test handle_response.
782
783
    def test_full_text_no_content_type(self):
784
        # We should not require Content-Type for a full response
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
785
        code, raw_headers, body = _full_text_response_no_content_type
786
        msg = self._build_HTTPMessage(raw_headers)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
787
        out = response.handle_response('http://foo', code, msg, BytesIO(body))
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
788
        self.assertEqual(body, out.read())
1786.1.26 by John Arbash Meinel
Update and test handle_response.
789
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
790
    def test_full_text_no_content_length(self):
791
        code, raw_headers, body = _full_text_response_no_content_length
792
        msg = self._build_HTTPMessage(raw_headers)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
793
        out = response.handle_response('http://foo', code, msg, BytesIO(body))
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
794
        self.assertEqual(body, out.read())
795
1786.1.26 by John Arbash Meinel
Update and test handle_response.
796
    def test_missing_content_range(self):
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
797
        code, raw_headers, body = _single_range_no_content_range
798
        msg = self._build_HTTPMessage(raw_headers)
1786.1.26 by John Arbash Meinel
Update and test handle_response.
799
        self.assertRaises(errors.InvalidHttpResponse,
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
800
                          response.handle_response,
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
801
                          'http://bogus', code, msg, BytesIO(body))
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
802
803
    def test_multipart_no_content_range(self):
804
        code, raw_headers, body = _multipart_no_content_range
805
        msg = self._build_HTTPMessage(raw_headers)
806
        self.assertRaises(errors.InvalidHttpResponse,
807
                          response.handle_response,
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
808
                          'http://bogus', code, msg, BytesIO(body))
3059.2.14 by Vincent Ladeuil
Complete coverage by adding tests for more invalid inputs. Fix a
809
810
    def test_multipart_no_boundary(self):
811
        out = self.get_response(_multipart_no_boundary)
812
        out.read()  # Read the whole range
813
        # Fail to find the boundary line
814
        self.assertRaises(errors.InvalidHttpResponse, out.seek, 1, 1)
3408.6.1 by Eric Holmberg
Fix for Bug #215426 in which bzr can cause a MemoryError in socket.recv while
815
816
817
class TestRangeFileSizeReadLimited(tests.TestCase):
818
    """Test RangeFile _max_read_size functionality which limits the size of
819
    read blocks to prevent MemoryError messages in socket.recv.
820
    """
821
822
    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.
823
        super(TestRangeFileSizeReadLimited, self).setUp()
3408.6.1 by Eric Holmberg
Fix for Bug #215426 in which bzr can cause a MemoryError in socket.recv while
824
        # create a test datablock larger than _max_read_size.
825
        chunk_size = response.RangeFile._max_read_size
6973.11.6 by Jelmer Vernooij
Fix more http tests.
826
        test_pattern = b'0123456789ABCDEF'
7143.15.2 by Jelmer Vernooij
Run autopep8.
827
        self.test_data = test_pattern * (3 * chunk_size // len(test_pattern))
3408.6.1 by Eric Holmberg
Fix for Bug #215426 in which bzr can cause a MemoryError in socket.recv while
828
        self.test_data_len = len(self.test_data)
829
830
    def test_max_read_size(self):
831
        """Read data in blocks and verify that the reads are not larger than
832
           the maximum read size.
833
        """
834
        # retrieve data in large blocks from response.RangeFile object
835
        mock_read_file = FakeReadFile(self.test_data)
836
        range_file = response.RangeFile('test_max_read_size', mock_read_file)
837
        response_data = range_file.read(self.test_data_len)
838
839
        # verify read size was equal to the maximum read size
840
        self.assertTrue(mock_read_file.get_max_read_size() > 0)
841
        self.assertEqual(mock_read_file.get_max_read_size(),
842
                         response.RangeFile._max_read_size)
843
        self.assertEqual(mock_read_file.get_read_count(), 3)
844
845
        # report error if the data wasn't equal (we only report the size due
846
        # to the length of the data)
847
        if response_data != self.test_data:
848
            message = "Data not equal.  Expected %d bytes, received %d."
849
            self.fail(message % (len(response_data), self.test_data_len))