~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_http.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-01-03 18:09:01 UTC
  • mfrom: (3159.1.1 trunk)
  • Revision ID: pqm@pqm.ubuntu.com-20080103180901-w987y1ftqoh02qbm
(vila) Fix #179368 by keeping the current range hint on
        ShortReadvErrors

Show diffs side-by-side

added added

removed removed

Lines of Context:
904
904
 
905
905
    _req_handler_class = MultipleRangeWithoutContentLengthRequestHandler
906
906
 
 
907
 
 
908
class TruncatedMultipleRangeRequestHandler(
 
909
    http_server.TestingHTTPRequestHandler):
 
910
    """Reply to multiple range requests truncating the last ones.
 
911
 
 
912
    This server generates responses whose Content-Length describes all the
 
913
    ranges, but fail to include the last ones leading to client short reads.
 
914
    This has been observed randomly with lighttpd (bug #179368).
 
915
    """
 
916
 
 
917
    _truncated_ranges = 2
 
918
 
 
919
    def get_multiple_ranges(self, file, file_size, ranges):
 
920
        self.send_response(206)
 
921
        self.send_header('Accept-Ranges', 'bytes')
 
922
        boundary = 'tagada'
 
923
        self.send_header('Content-Type',
 
924
                         'multipart/byteranges; boundary=%s' % boundary)
 
925
        boundary_line = '--%s\r\n' % boundary
 
926
        # Calculate the Content-Length
 
927
        content_length = 0
 
928
        for (start, end) in ranges:
 
929
            content_length += len(boundary_line)
 
930
            content_length += self._header_line_length(
 
931
                'Content-type', 'application/octet-stream')
 
932
            content_length += self._header_line_length(
 
933
                'Content-Range', 'bytes %d-%d/%d' % (start, end, file_size))
 
934
            content_length += len('\r\n') # end headers
 
935
            content_length += end - start # + 1
 
936
        content_length += len(boundary_line)
 
937
        self.send_header('Content-length', content_length)
 
938
        self.end_headers()
 
939
 
 
940
        # Send the multipart body
 
941
        cur = 0
 
942
        for (start, end) in ranges:
 
943
            self.wfile.write(boundary_line)
 
944
            self.send_header('Content-type', 'application/octet-stream')
 
945
            self.send_header('Content-Range', 'bytes %d-%d/%d'
 
946
                             % (start, end, file_size))
 
947
            self.end_headers()
 
948
            if cur + self._truncated_ranges >= len(ranges):
 
949
                # Abruptly ends the response and close the connection
 
950
                self.close_connection = 1
 
951
                return
 
952
            self.send_range_content(file, start, end - start + 1)
 
953
            cur += 1
 
954
        # No final boundary
 
955
        self.wfile.write(boundary_line)
 
956
 
 
957
 
 
958
class TestTruncatedMultipleRangeServer(TestSpecificRequestHandler):
 
959
 
 
960
    _req_handler_class = TruncatedMultipleRangeRequestHandler
 
961
 
 
962
    def setUp(self):
 
963
        super(TestTruncatedMultipleRangeServer, self).setUp()
 
964
        self.build_tree_contents([('a', '0123456789')],)
 
965
 
 
966
    def test_readv_with_short_reads(self):
 
967
        server = self.get_readonly_server()
 
968
        t = self._transport(server.get_url())
 
969
        # Force separate ranges for each offset
 
970
        t._bytes_to_read_before_seek = 0
 
971
        ireadv = iter(t.readv('a', ((0, 1), (2, 1), (4, 2), (9, 1))))
 
972
        self.assertEqual((0, '0'), ireadv.next())
 
973
        self.assertEqual((2, '2'), ireadv.next())
 
974
        if not self._testing_pycurl():
 
975
            # Only one request have been issued so far (except for pycurl that
 
976
            # try to read the whole response at once)
 
977
            self.assertEqual(1, server.GET_request_nb)
 
978
        self.assertEqual((4, '45'), ireadv.next())
 
979
        self.assertEqual((9, '9'), ireadv.next())
 
980
        # Both implementations issue 3 requests but:
 
981
        # - urllib does two multiple (4 ranges, then 2 ranges) then a single
 
982
        #   range,
 
983
        # - pycurl does two multiple (4 ranges, 4 ranges) then a single range
 
984
        self.assertEqual(3, server.GET_request_nb)
 
985
        # Finally the client have tried a single range request and stays in
 
986
        # that mode
 
987
        self.assertEqual('single', t._range_hint)
 
988
 
907
989
class LimitedRangeRequestHandler(http_server.TestingHTTPRequestHandler):
908
990
    """Errors out when range specifiers exceed the limit"""
909
991