diff -r 8ee02ec9b634 Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py Sat Jan 09 23:56:40 2016 -0800 +++ b/Lib/test/test_httplib.py Sun Jan 10 19:13:39 2016 +0000 @@ -74,6 +74,9 @@ def setsockopt(self, level, optname, value): pass + def fileno(self): + return 0 + class EPipeSocket(FakeSocket): def __init__(self, text, pipe_trigger): @@ -978,6 +981,118 @@ p = self.resp.peek(0) self.assertLessEqual(0, len(p)) +class RealSocketBasedTests(TestCase): + def setUp(self): + self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.server_port = support.bind_port(self.server_socket) + self.server_socket.listen() + + self.test_size = self.server_socket.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF) + + def tearDown(self): + self.server_socket.shutdown(socket.SHUT_RDWR) + self.server_socket.close() + + + def test_response_after_headers(self): + import time + import multiprocessing + + response_received = multiprocessing.Value('b', 0) + #response_received = multiprocessing.Semaphore(-1) + + def make_request(): + with open(support.TESTFN, "w") as f: + f.write("body" * self.test_size) # test file must be bigger than SO_SNDBUF + with open(support.TESTFN, "rb") as f: + conn = client.HTTPConnection(support.HOST, self.server_port) + req = conn.request( + method='PUT', + url='/foobar', + body=f) + resp = conn.getresponse() + conn.close() + response_received.value = 1 + #response_received.release() + + requester = multiprocessing.Process(target=make_request) + + try: + requester.start() + (conn, address) = self.server_socket.accept() + + conn.send(b"HTTP/1.1 413 Request Entity Too Large\r\n" + b"Content-Length: 0\r\n" + b"Server: HTTP lib tests\r\n" + b"\r\n" + ) + #self.assertTrue(response_received.acquire(timeout=1), + # "Response not received, though already sent by server") + time.sleep(0.1) # wait for other process to call make_request + self.assertEqual(response_received.value, 1, + "Response not received, though already sent by server") + finally: + conn.shutdown(socket.SHUT_RDWR) + conn.close() + requester.terminate() + + @unittest.skipIf(not hasattr(client, 'HTTPSConnection'), + 'http.client.HTTPSConnection not defined') + @support.reap_threads + def test_ssl_renegotiation(self): + import ssl + import threading + #sslcontext = ssl._create_unverified_context() + sslcontext = ssl.create_default_context() + sslcontext.check_hostname = False + sslcontext.verify_mode = ssl.CERT_NONE + sslcontext.set_ciphers("ALL") + TEST_BODY = "body" * self.test_size + lock = threading.Lock() + + def make_request(): + with open(support.TESTFN, "w") as f: + f.write(TEST_BODY) # test file must be bigger than SO_SNDBUF + with open(support.TESTFN, "rb") as f: + with lock: + conn = client.HTTPSConnection(support.HOST, + self.server_port, context=sslcontext) + req = conn.request( + method='PUT', + url='/foobar', + body=f) + response = conn.getresponse() + conn.close() + + requester = threading.Thread(target=make_request) + requester.start() + (conn, address) = self.server_socket.accept() + conn = sslcontext.wrap_socket(conn, server_side=True) + fp = conn.makefile("rwb") + #import pdb; pdb.set_trace() + while True: + data = fp.readline() + if data == b'\r\n': + break + first_part = int(len(TEST_BODY) / 2) + conn.settimeout(0.1) + conn.send(b"H") + conn.recv(first_part) + conn.send(b"TTP/1.1 200\r\n" + b"Header: ") + try: + conn.recv(len(TEST_BODY) - first_part) + except socket.timeout: + self.fail("Request data loss possibile due to renegotiation, waits, etc.") + conn.send(b"Value\r\n\r\n") + + # wait till everything is sent + with lock: + conn.shutdown(socket.SHUT_RDWR) + conn.close() + + + class ExtendedReadTestChunked(ExtendedReadTest): """ Test peek(), read1(), readline() in chunked mode @@ -1605,7 +1720,8 @@ PersistenceTest, HTTPSTest, RequestBodyTest, SourceAddressTest, HTTPResponseTest, ExtendedReadTest, - ExtendedReadTestChunked, TunnelTests) + ExtendedReadTestChunked, TunnelTests, + RealSocketBasedTests) if __name__ == '__main__': test_main()