~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_http.py

(mbp) cope with proxies that drop the connection during a multipart response
 (bug 198646) (Martin Pool)

Show diffs side-by-side

added added

removed removed

Lines of Context:
999
999
        self.assertEqual('single', t._range_hint)
1000
1000
 
1001
1001
 
 
1002
class TruncatedBeforeBoundaryRequestHandler(
 
1003
    http_server.TestingHTTPRequestHandler):
 
1004
    """Truncation before a boundary, like in bug 198646"""
 
1005
 
 
1006
    _truncated_ranges = 1
 
1007
 
 
1008
    def get_multiple_ranges(self, file, file_size, ranges):
 
1009
        self.send_response(206)
 
1010
        self.send_header('Accept-Ranges', 'bytes')
 
1011
        boundary = 'tagada'
 
1012
        self.send_header('Content-Type',
 
1013
                         'multipart/byteranges; boundary=%s' % boundary)
 
1014
        boundary_line = '--%s\r\n' % boundary
 
1015
        # Calculate the Content-Length
 
1016
        content_length = 0
 
1017
        for (start, end) in ranges:
 
1018
            content_length += len(boundary_line)
 
1019
            content_length += self._header_line_length(
 
1020
                'Content-type', 'application/octet-stream')
 
1021
            content_length += self._header_line_length(
 
1022
                'Content-Range', 'bytes %d-%d/%d' % (start, end, file_size))
 
1023
            content_length += len('\r\n') # end headers
 
1024
            content_length += end - start # + 1
 
1025
        content_length += len(boundary_line)
 
1026
        self.send_header('Content-length', content_length)
 
1027
        self.end_headers()
 
1028
 
 
1029
        # Send the multipart body
 
1030
        cur = 0
 
1031
        for (start, end) in ranges:
 
1032
            if cur + self._truncated_ranges >= len(ranges):
 
1033
                # Abruptly ends the response and close the connection
 
1034
                self.close_connection = 1
 
1035
                return
 
1036
            self.wfile.write(boundary_line)
 
1037
            self.send_header('Content-type', 'application/octet-stream')
 
1038
            self.send_header('Content-Range', 'bytes %d-%d/%d'
 
1039
                             % (start, end, file_size))
 
1040
            self.end_headers()
 
1041
            self.send_range_content(file, start, end - start + 1)
 
1042
            cur += 1
 
1043
        # Final boundary
 
1044
        self.wfile.write(boundary_line)
 
1045
 
 
1046
 
 
1047
class TestTruncatedBeforeBoundary(TestSpecificRequestHandler):
 
1048
    """Tests the case of bug 198646, disconnecting before a boundary."""
 
1049
 
 
1050
    _req_handler_class = TruncatedBeforeBoundaryRequestHandler
 
1051
 
 
1052
    def setUp(self):
 
1053
        super(TestTruncatedBeforeBoundary, self).setUp()
 
1054
        self.build_tree_contents([('a', '0123456789')],)
 
1055
 
 
1056
    def test_readv_with_short_reads(self):
 
1057
        server = self.get_readonly_server()
 
1058
        t = self.get_readonly_transport()
 
1059
        # Force separate ranges for each offset
 
1060
        t._bytes_to_read_before_seek = 0
 
1061
        ireadv = iter(t.readv('a', ((0, 1), (2, 1), (4, 2), (9, 1))))
 
1062
        self.assertEqual((0, '0'), ireadv.next())
 
1063
        self.assertEqual((2, '2'), ireadv.next())
 
1064
        self.assertEqual((4, '45'), ireadv.next())
 
1065
        self.assertEqual((9, '9'), ireadv.next())
 
1066
 
 
1067
 
1002
1068
class LimitedRangeRequestHandler(http_server.TestingHTTPRequestHandler):
1003
1069
    """Errors out when range specifiers exceed the limit"""
1004
1070