Index: Lib/test/test_httplib.py =================================================================== --- Lib/test/test_httplib.py (revision 50809) +++ Lib/test/test_httplib.py (working copy) @@ -11,6 +11,9 @@ self.text = text self.fileclass = fileclass + def close(self): + self.text = self.data = None + def sendall(self, data): self.data = data @@ -70,6 +73,80 @@ conn.request('POST', '/', body, headers) self.assertEqual(conn._buffer.count[header.lower()], 1) +class ChunkingTests(TestCase): + good_response = ( + 'HTTP/1.1 200 OK\r\n' + 'Connection: close\r\n' + 'Transfer-Encoding: chunked\r\n' + '\r\n' + '0005\r\n' + 'abcd\n' + '\r\n' + '0004\r\n' + 'abc\n' + '\r\n' + '0\r\n' + '\r\n') + + # Bad chunking that I have actually seen in the wild: the "last + # chunk size" line ("0\r\n") is missing. httplib in Python 2.3.5 + # and 2.4.3 raises ValueError on this. + bad_response_1 = ( + 'HTTP/1.1 200 OK\r\n' + 'Connection: close\r\n' + 'Transfer-Encoding: chunked\r\n' + '\r\n' + '0005\r\n' + 'abcd\n' + '\r\n' + '0004\r\n' + 'abc\n' + '\r\n' + '\r\n') + + # Bad chunking that is entirely hypothetical: everything after the + # "\r\n" that terminates the last chunk is missing. With a real + # socket, httplib in Python 2.3.5 and 2.4.3 blocks forever on this + # (self.fp.readline() call at top of main loop in + # HTTPResponse._read_chunked() never returns). With a FakeSocket, + # that self.fp.readline() call returns '' and httplib raises + # ValueError. + bad_response_2 = ( + 'HTTP/1.1 200 OK\r\n' + 'Connection: close\r\n' + 'Transfer-Encoding: chunked\r\n' + '\r\n' + '0005\r\n' + 'abcd\n' + '\r\n' + '0004\r\n' + 'abc\n' + '\r\n') + + def _getresponse(self, response): + conn = httplib.HTTPConnection("bogus.domain") + conn.sock = FakeSocket(response) + conn.request('GET', '/') + response = conn.getresponse() + return response.read() + + def _test_good_chunking(self): + "correctly-chunked response" + self.assertEquals("abcd\nabc\n", + self._getresponse(self.good_response)) + + def _test_bad_chunking_1(self): + "incorrectly-chunked response: last chunk size missing" + self.assertRaises(httplib.HTTPException, + self._getresponse, self.bad_response_1) + + def test_bad_chunking_2(self): + "incorrectly-chunked response: everything after last chunk missing" + self.assertRaises(httplib.HTTPException, + self._getresponse, self.bad_response_2) + + + # Collect output to a buffer so that we don't have to cope with line-ending # issues across platforms. Specifically, the headers will have \r\n pairs # and some platforms will strip them from the output file. @@ -162,7 +239,8 @@ def test_main(verbose=None): - tests = [HeaderTests,] + #tests = [HeaderTests,] + tests = [ChunkingTests,] test_support.run_unittest(*tests) -test() +test_main()