Skip to content

Commit

Permalink
Add context to find_unused_port (urllib3#1837)
Browse files Browse the repository at this point in the history
  • Loading branch information
hodbn committed Apr 1, 2020
1 parent 39e580e commit a9508d8
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 16 deletions.
17 changes: 6 additions & 11 deletions test/port_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# library test suite.

import socket
from contextlib import contextmanager


# Don't use "localhost", since resolving it uses the DNS under recent
Expand All @@ -10,13 +11,14 @@
HOSTv6 = "::1"


@contextmanager
def find_unused_port(family=socket.AF_INET, socktype=socket.SOCK_STREAM):
"""Returns an unused port that should be suitable for binding. This is
achieved by creating a temporary socket with the same family and type as
the 'sock' parameter (default is AF_INET, SOCK_STREAM), and binding it to
the specified host address (defaults to 0.0.0.0) with the port set to 0,
eliciting an unused ephemeral port from the OS. The temporary socket is
then closed and deleted, and the ephemeral port is returned.
eliciting an unused ephemeral port from the OS. The ephemeral port is
yielded, and finally the temporary socket is closed and deleted.
Either this method or bind_port() should be used for any tests where a
server socket needs to be bound to a particular port for the duration of
Expand Down Expand Up @@ -56,19 +58,12 @@ def find_unused_port(family=socket.AF_INET, socktype=socket.SOCK_STREAM):
http://bugs.python.org/issue2550 for more info. The following site also
has a very thorough description about the implications of both REUSEADDR
and EXCLUSIVEADDRUSE on Windows:
http://msdn2.microsoft.com/en-us/library/ms740621(VS.85).aspx)
XXX: although this approach is a vast improvement on previous attempts to
elicit unused ports, it rests heavily on the assumption that the ephemeral
port returned to us by the OS won't immediately be dished back out to some
other process when we close and delete our temporary socket but before our
calling code has a chance to bind the returned port. We can deal with this
issue if/when we come across it."""
http://msdn2.microsoft.com/en-us/library/ms740621(VS.85).aspx)"""
tempsock = socket.socket(family, socktype)
port = bind_port(tempsock)
yield port
tempsock.close()
del tempsock
return port


def bind_port(sock, host=HOST):
Expand Down
10 changes: 5 additions & 5 deletions test/with_dummyserver/test_connectionpool.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,11 +349,11 @@ def test_defaults_are_applied(self):

def test_connection_error_retries(self):
""" ECONNREFUSED error should raise a connection error, with retries """
port = find_unused_port()
with HTTPConnectionPool(self.host, port) as pool:
with pytest.raises(MaxRetryError) as e:
pool.request("GET", "/", retries=Retry(connect=3))
assert type(e.value.reason) == NewConnectionError
with find_unused_port() as port:
with HTTPConnectionPool(self.host, port) as pool:
with pytest.raises(MaxRetryError) as e:
pool.request("GET", "/", retries=Retry(connect=3))
assert type(e.value.reason) == NewConnectionError

def test_timeout_success(self):
timeout = Timeout(connect=3, read=5, total=None)
Expand Down

0 comments on commit a9508d8

Please sign in to comment.