def test_total_applies_connect(self):
        host, port = TARPIT_HOST, 80

        timeout = Timeout(total=None, connect=SHORT_TIMEOUT)
        pool = HTTPConnectionPool(host, port, timeout=timeout)
        self.addCleanup(pool.close)
        conn = pool._get_conn()
        self.addCleanup(conn.close)
        self.assertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET',
                          '/')

        timeout = Timeout(connect=3, read=5, total=SHORT_TIMEOUT)
        pool = HTTPConnectionPool(host, port, timeout=timeout)
        self.addCleanup(pool.close)
        conn = pool._get_conn()
        self.addCleanup(conn.close)
        self.assertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET',
                          '/')
    def test_connect_timeout(self):
        url = '/'
        host, port = TARPIT_HOST, 80
        timeout = Timeout(connect=SHORT_TIMEOUT)

        # Pool-global timeout
        pool = HTTPConnectionPool(host, port, timeout=timeout)
        self.addCleanup(pool.close)
        conn = pool._get_conn()
        self.assertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET',
                          url)

        # Retries
        retries = Retry(connect=0)
        self.assertRaises(MaxRetryError,
                          pool.request,
                          'GET',
                          url,
                          retries=retries)

        # Request-specific connection timeouts
        big_timeout = Timeout(read=LONG_TIMEOUT, connect=LONG_TIMEOUT)
        pool = HTTPConnectionPool(host,
                                  port,
                                  timeout=big_timeout,
                                  retries=False)
        self.addCleanup(pool.close)
        conn = pool._get_conn()
        self.assertRaises(ConnectTimeoutError,
                          pool._make_request,
                          conn,
                          'GET',
                          url,
                          timeout=timeout)

        pool._put_conn(conn)
        self.assertRaises(ConnectTimeoutError,
                          pool.request,
                          'GET',
                          url,
                          timeout=timeout)
 def test_nagle(self):
     """ Test that connections have TCP_NODELAY turned on """
     # This test needs to be here in order to be run. socket.create_connection actually tries
     # to connect to the host provided so we need a dummyserver to be running.
     pool = HTTPConnectionPool(self.host, self.port)
     self.addCleanup(pool.close)
     conn = pool._get_conn()
     self.addCleanup(conn.close)
     pool._make_request(conn, 'GET', '/')
     tcp_nodelay_setting = conn._sock.getsockopt(socket.IPPROTO_TCP,
                                                 socket.TCP_NODELAY)
     self.assertTrue(tcp_nodelay_setting)
    def test_conn_closed(self):
        block_event = Event()
        self.start_basic_handler(block_send=block_event, num=1)

        pool = HTTPConnectionPool(self.host,
                                  self.port,
                                  timeout=SHORT_TIMEOUT,
                                  retries=False)
        self.addCleanup(pool.close)
        conn = pool._get_conn()
        pool._put_conn(conn)
        try:
            pool.urlopen('GET', '/')
            self.fail("The request should fail with a timeout error.")
        except ReadTimeoutError:
            if conn._sock:
                self.assertRaises(socket.error, conn.sock.recv, 1024)
        finally:
            pool._put_conn(conn)

        block_event.set()
    def test_timeout(self):
        # Requests should time out when expected
        block_event = Event()
        ready_event = self.start_basic_handler(block_send=block_event, num=6)

        # Pool-global timeout
        timeout = Timeout(read=SHORT_TIMEOUT)
        pool = HTTPConnectionPool(self.host,
                                  self.port,
                                  timeout=timeout,
                                  retries=False)
        self.addCleanup(pool.close)

        wait_for_socket(ready_event)
        conn = pool._get_conn()
        self.assertRaises(ReadTimeoutError, pool._make_request, conn, 'GET',
                          '/')
        pool._put_conn(conn)
        block_event.set()  # Release request

        wait_for_socket(ready_event)
        block_event.clear()
        self.assertRaises(ReadTimeoutError, pool.request, 'GET', '/')
        block_event.set()  # Release request

        # Request-specific timeouts should raise errors
        pool = HTTPConnectionPool(self.host,
                                  self.port,
                                  timeout=LONG_TIMEOUT,
                                  retries=False)
        self.addCleanup(pool.close)

        conn = pool._get_conn()
        wait_for_socket(ready_event)
        now = time.time()
        self.assertRaises(ReadTimeoutError,
                          pool._make_request,
                          conn,
                          'GET',
                          '/',
                          timeout=timeout)
        delta = time.time() - now
        block_event.set()  # Release request

        message = "timeout was pool-level LONG_TIMEOUT rather than request-level SHORT_TIMEOUT"
        self.assertTrue(delta < LONG_TIMEOUT, message)
        pool._put_conn(conn)

        wait_for_socket(ready_event)
        now = time.time()
        self.assertRaises(ReadTimeoutError,
                          pool.request,
                          'GET',
                          '/',
                          timeout=timeout)
        delta = time.time() - now

        message = "timeout was pool-level LONG_TIMEOUT rather than request-level SHORT_TIMEOUT"
        self.assertTrue(delta < LONG_TIMEOUT, message)
        block_event.set()  # Release request

        # Timeout int/float passed directly to request and _make_request should
        # raise a request timeout
        wait_for_socket(ready_event)
        self.assertRaises(ReadTimeoutError,
                          pool.request,
                          'GET',
                          '/',
                          timeout=SHORT_TIMEOUT)
        block_event.set()  # Release request

        wait_for_socket(ready_event)
        conn = pool._new_conn()
        # FIXME: This assert flakes sometimes. Not sure why.
        self.assertRaises(ReadTimeoutError,
                          pool._make_request,
                          conn,
                          'GET',
                          '/',
                          timeout=SHORT_TIMEOUT)
        block_event.set()  # Release request