def test_connect_timeout(self): url = '/sleep?seconds=0.005' timeout = Timeout(connect=0.001) # Pool-global timeout pool = HTTPConnectionPool(TARPIT_HOST, self.port, timeout=timeout) conn = pool._get_conn() yield From(self.aioAssertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET', url)) # Retries retries = Retry(connect=0) yield From(self.aioAssertRaises(MaxRetryError, pool.request, 'GET', url, retries=retries)) # Request-specific connection timeouts big_timeout = Timeout(read=0.2, connect=0.2) pool = HTTPConnectionPool(TARPIT_HOST, self.port, timeout=big_timeout, retries=False) conn = pool._get_conn() yield From(self.aioAssertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET', url, timeout=timeout)) pool._put_conn(conn) yield From(self.aioAssertRaises(ConnectTimeoutError, pool.request, 'GET', url, timeout=timeout))
def tst_enhanced_timeout(self): def new_pool(timeout, cert_reqs='CERT_REQUIRED'): https_pool = HTTPSConnectionPool(TARPIT_HOST, self.port, timeout=timeout, retries=False, cert_reqs=cert_reqs) return https_pool https_pool = new_pool(Timeout(connect=0.001)) conn = https_pool._new_conn() try: yield From(https_pool.request('GET', '/')) except ConnectTimeoutError as e: pass except Exception as e: pass except: pass else: self.fail('connect timeout error not raised') yield From(self.aioAssertRaises(ConnectTimeoutError, https_pool._make_request, conn, 'GET', '/')) https_pool = new_pool(Timeout(connect=5)) yield From(self.aioAssertRaises(ConnectTimeoutError, https_pool.request, 'GET', '/', timeout=Timeout(connect=0.001))) t = Timeout(total=None) https_pool = new_pool(t) conn = https_pool._new_conn() yield From(self.aioAssertRaises(ConnectTimeoutError, https_pool.request, 'GET', '/', timeout=Timeout(total=None, connect=0.001)))
def tst_https_timeout(self): timeout = Timeout(connect=0.001) https_pool = HTTPSConnectionPool(TARPIT_HOST, self.port, timeout=timeout, retries=False, cert_reqs='CERT_REQUIRED') timeout = Timeout(total=None, connect=0.001) https_pool = HTTPSConnectionPool(TARPIT_HOST, self.port, timeout=timeout, retries=False, cert_reqs='CERT_REQUIRED') yield From(self.aioAssertRaises(ConnectTimeoutError, https_pool.request, 'GET', '/')) timeout = Timeout(read=0.001) https_pool = HTTPSConnectionPool(self.host, self.port, timeout=timeout, retries=False, cert_reqs='CERT_REQUIRED') https_pool.ca_certs = DEFAULT_CA https_pool.assert_fingerprint = 'CC:45:6A:90:82:F7FF:C0:8218:8e:' \ '7A:F2:8A:D7:1E:07:33:67:DE' url = '/sleep?seconds=0.005' try: yield From(https_pool.request('GET', url)) except ReadTimeoutError as e: pass else: self.fail('ReadTimeoutError was not raised') timeout = Timeout(total=None) https_pool = HTTPSConnectionPool(self.host, self.port, timeout=timeout, cert_reqs='CERT_NONE') yield From(https_pool.request('GET', '/'))
def test_invalid_timeouts(self): try: Timeout(total=-1) self.fail("negative value should throw exception") except ValueError as e: self.assertTrue('less than' in str(e)) try: Timeout(connect=2, total=-1) self.fail("negative value should throw exception") except ValueError as e: self.assertTrue('less than' in str(e)) try: Timeout(read=-1) self.fail("negative value should throw exception") except ValueError as e: self.assertTrue('less than' in str(e)) # Booleans are allowed also by socket.settimeout and converted to the # equivalent float (1.0 for True, 0.0 for False) Timeout(connect=False, read=True) try: Timeout(read="foo") self.fail("string value should not be allowed") except ValueError as e: self.assertTrue('int or float' in str(e))
def test_timeout_success(self): timeout = Timeout(connect=3, read=5, total=None) pool = HTTPConnectionPool(self.host, self.port, timeout=timeout) yield From(pool.request('GET', '/')) # This should not raise a "Timeout already started" error yield From(pool.request('GET', '/')) pool = HTTPConnectionPool(self.host, self.port, timeout=timeout) # This should also not raise a "Timeout already started" error yield From(pool.request('GET', '/')) timeout = Timeout(total=None) pool = HTTPConnectionPool(self.host, self.port, timeout=timeout) yield From(pool.request('GET', '/'))
def test_delayed_body_read_timeout(self): timed_out = Event() def socket_handler(listener): sock = listener.accept()[0] buf = b'' body = 'Hi' while not buf.endswith(b'\r\n\r\n'): buf = sock.recv(65536) sock.send(('HTTP/1.1 200 OK\r\n' 'Content-Type: text/plain\r\n' 'Content-Length: %d\r\n' '\r\n' % len(body)).encode('utf-8')) timed_out.wait() sock.send(body.encode('utf-8')) sock.close() self._start_server(socket_handler) pool = HTTPConnectionPool(self.host, self.port) response = yield From( pool.urlopen('GET', '/', retries=0, preload_content=False, timeout=Timeout(connect=1, read=0.1))) try: self.aioAssertRaises(ReadTimeoutError, response.read) finally: timed_out.set()
def test_total_timeout(self): url = '/sleep?seconds=0.005' timeout = Timeout(connect=3, read=5, total=0.001) pool = HTTPConnectionPool(TARPIT_HOST, self.port, timeout=timeout) conn = pool._get_conn() yield From(self.aioAssertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET', url)) # This will get the socket to raise an EAGAIN on the read timeout = Timeout(connect=3, read=0) pool = HTTPConnectionPool(self.host, self.port, timeout=timeout) conn = pool._get_conn() yield From(self.aioAssertRaises(ReadTimeoutError, pool._make_request, conn, 'GET', url)) # The connect should succeed and this should hit the read timeout timeout = Timeout(connect=3, read=5, total=0.002) pool = HTTPConnectionPool(self.host, self.port, timeout=timeout) conn = pool._get_conn() yield From(self.aioAssertRaises(ReadTimeoutError, pool._make_request, conn, 'GET', url))
def test_timeout_reset(self): """ If the read timeout isn't set, socket timeout should reset """ url = '/sleep?seconds=0.005' timeout = Timeout(connect=0.001) pool = HTTPConnectionPool(self.host, self.port, timeout=timeout) conn = pool._get_conn() try: yield From(pool._make_request(conn, 'GET', url)) except ReadTimeoutError: self.fail("This request shouldn't trigger a read timeout.")
def test_tunnel(self): """ test the _tunnel behavior """ timeout = Timeout(total=None) https_pool = HTTPSConnectionPool(self.host, self.port, timeout=timeout, cert_reqs='CERT_NONE') conn = https_pool._new_conn() try: conn.set_tunnel(self.host, self.port) except AttributeError: # python 2.6 conn._set_tunnel(self.host, self.port) conn._tunnel = mock.Mock(return_value=iter([None, None, None])) yield From(https_pool._make_request(conn, 'GET', '/')) conn._tunnel.assert_called_once_with()
def test_tunnel(self): # note the actual httplib.py has no tests for this functionality timeout = Timeout(total=None) pool = HTTPConnectionPool(self.host, self.port, timeout=timeout) conn = pool._get_conn() try: conn.set_tunnel(self.host, self.port) except AttributeError: # python 2.6 conn._set_tunnel(self.host, self.port) conn._tunnel = mock.Mock(return_value=None) yield From(pool._make_request(conn, 'GET', '/')) conn._tunnel.assert_called_once_with() # test that it's not called when tunnel is not set timeout = Timeout(total=None) pool = HTTPConnectionPool(self.host, self.port, timeout=timeout) conn = pool._get_conn() conn._tunnel = mock.Mock(return_value=None) yield From(pool._make_request(conn, 'GET', '/')) self.assertEqual(conn._tunnel.called, False)
def test_timeout_elapsed(self, current_time): current_time.return_value = TIMEOUT_EPOCH timeout = Timeout(total=3) self.assertRaises(TimeoutStateError, timeout.get_connect_duration) timeout.start_connect() self.assertRaises(TimeoutStateError, timeout.start_connect) current_time.return_value = TIMEOUT_EPOCH + 2 self.assertEqual(timeout.get_connect_duration(), 2) current_time.return_value = TIMEOUT_EPOCH + 37 self.assertEqual(timeout.get_connect_duration(), 37)
def test_timeout(self): """ Requests should time out when expected """ url = '/sleep?seconds=0.002' timeout = Timeout(read=0.001) # Pool-global timeout pool = HTTPConnectionPool(self.host, self.port, timeout=timeout, retries=False) conn = pool._get_conn() yield From(self.aioAssertRaises(ReadTimeoutError, pool._make_request, conn, 'GET', url)) pool._put_conn(conn) time.sleep(0.02) # Wait for server to start receiving again. :( yield From(self.aioAssertRaises(ReadTimeoutError, pool.request, 'GET', url)) # Request-specific timeouts should raise errors pool = HTTPConnectionPool(self.host, self.port, timeout=0.1, retries=False) conn = pool._get_conn() yield From(self.aioAssertRaises(ReadTimeoutError, pool._make_request, conn, 'GET', url, timeout=timeout)) pool._put_conn(conn) time.sleep(0.02) # Wait for server to start receiving again. :( yield From(self.aioAssertRaises(ReadTimeoutError, pool.request, 'GET', url, timeout=timeout)) # Timeout int/float passed directly to request and _make_request should # raise a request timeout yield From(self.aioAssertRaises(ReadTimeoutError, pool.request, 'GET', url, timeout=0.001)) conn = pool._new_conn() yield From(self.aioAssertRaises(ReadTimeoutError, pool._make_request, conn, 'GET', url, timeout=0.001)) pool._put_conn(conn) # Timeout int/float passed directly to _make_request should not raise a # request timeout if it's a high value yield From(pool.request('GET', url, timeout=1))
def tst_timeout_errors_cause_retries(self): def socket_handler(listener): sock_timeout = listener.accept()[0] # Wait for a second request before closing the first socket. sock = listener.accept()[0] sock_timeout.close() # Second request. buf = b'' while not buf.endswith(b'\r\n\r\n'): buf += sock.recv(65536) # Now respond immediately. body = 'Response 2' sock.send(('HTTP/1.1 200 OK\r\n' 'Content-Type: text/plain\r\n' 'Content-Length: %d\r\n' '\r\n' '%s' % (len(body), body)).encode('utf-8')) sock.close() # In situations where the main thread throws an exception, the server # thread can hang on an accept() call. This ensures everything times # out within 1 second. This should be long enough for any socket # operations in the test suite to complete default_timeout = socket.getdefaulttimeout() socket.setdefaulttimeout(1) try: self._start_server(socket_handler) t = Timeout(connect=0.1, read=0.1) pool = HTTPConnectionPool(self.host, self.port, timeout=t) response = yield From(pool.request('GET', '/', retries=1)) self.assertEqual(response.status, 200) self.assertEqual((yield From(response.data), b'Response 2')) finally: socket.setdefaulttimeout(default_timeout)
def test_timeout(self, current_time): timeout = Timeout(total=3) # make 'no time' elapse timeout = self._make_time_pass(seconds=0, timeout=timeout, time_mock=current_time) self.assertEqual(timeout.read_timeout, 3) self.assertEqual(timeout.connect_timeout, 3) timeout = Timeout(total=3, connect=2) self.assertEqual(timeout.connect_timeout, 2) timeout = Timeout() self.assertEqual(timeout.connect_timeout, Timeout.DEFAULT_TIMEOUT) # Connect takes 5 seconds, leaving 5 seconds for read timeout = Timeout(total=10, read=7) timeout = self._make_time_pass(seconds=5, timeout=timeout, time_mock=current_time) self.assertEqual(timeout.read_timeout, 5) # Connect takes 2 seconds, read timeout still 7 seconds timeout = Timeout(total=10, read=7) timeout = self._make_time_pass(seconds=2, timeout=timeout, time_mock=current_time) self.assertEqual(timeout.read_timeout, 7) timeout = Timeout(total=10, read=7) self.assertEqual(timeout.read_timeout, 7) timeout = Timeout(total=None, read=None, connect=None) self.assertEqual(timeout.connect_timeout, None) self.assertEqual(timeout.read_timeout, None) self.assertEqual(timeout.total, None) timeout = Timeout(5) self.assertEqual(timeout.total, 5)
def test_ssl_read_timeout(self): timed_out = Event() def socket_handler(listener): sock = listener.accept()[0] ssl_sock = ssl.wrap_socket(sock, server_side=True, keyfile=DEFAULT_CERTS['keyfile'], certfile=DEFAULT_CERTS['certfile'], ca_certs=DEFAULT_CA) buf = b'' while not buf.endswith(b'\r\n\r\n'): buf += ssl_sock.recv(65536) # Send incomplete message (note Content-Length) ssl_sock.send(('HTTP/1.1 200 OK\r\n' 'Content-Type: text/plain\r\n' 'Content-Length: 10\r\n' '\r\n' 'Hi-').encode('utf-8')) timed_out.wait() sock.close() ssl_sock.close() self._start_server(socket_handler) pool = HTTPSConnectionPool(self.host, self.port) response = yield From( pool.urlopen('GET', '/', retries=0, preload_content=False, timeout=Timeout(connect=1, read=0.5))) try: self.aioAssertRaises(ReadTimeoutError, response.read) finally: timed_out.set()
def test_none_total_applies_connect(self): url = '/sleep?seconds=0.005' timeout = Timeout(total=None, connect=0.001) pool = HTTPConnectionPool(TARPIT_HOST, self.port, timeout=timeout) conn = pool._get_conn() yield From(self.aioAssertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET', url))
def test_timeout_str(self): timeout = Timeout(connect=1, read=2, total=3) self.assertEqual(str(timeout), "Timeout(connect=1, read=2, total=3)") timeout = Timeout(connect=1, read=None, total=3) self.assertEqual(str(timeout), "Timeout(connect=1, read=None, total=3)")