Kaydet (Commit) caa59c15 authored tarafından Victor Stinner's avatar Victor Stinner Kaydeden (comit) GitHub

[3.6] bpo-30106: Fix test_asyncore.test_quick_connect() (#1336)

* Fix/optimize test_asyncore.test_quick_connect() (#1188)

Don't use addCleanup() in test_quick_connect() because it keeps the
Thread object alive and so @reap_threads fails on its timeout of 1
second. "./python -m test -v test_asyncore -m test_quick_connect"
now takes 185 ms, instead of 11 seconds.

Other minor changes:

* Use "with sock:" to close the socket instead of
  try/finally: sock.close()
* Use self.skipTest() in test_quick_connect() to remove one
  indentation level and notice user that the test is specific to
  AF_INET and AF_INET6

* bpo-30106: Fix tearDown() of test_asyncore (#1194)

Call asyncore.close_all() with ignore_all=True in the tearDown()
method of the test_asyncore base test case. It should prevent keeping
alive sockets in asyncore.socket_map if close() fails with an
unexpected error.

Revert also an unwanted change of my previous commit: remove name
parameter of Thread in test_quick_connect().

* bpo-30106: Fix test_asyncore.test_quick_connect() (#1234)

test_quick_connect() runs a thread up to 50 seconds, whereas the
socket is connected in 0.2 second and then the thread is expected to
end in less than 3 second. On Linux, the thread ends quickly because
select() seems to always return quickly. On FreeBSD, sometimes
select() fails with timeout and so the thread runs much longer than
expected.

Fix the thread timeout to fix a race condition in the test.
üst c9ca57ee
...@@ -502,7 +502,7 @@ class BaseClient(BaseTestHandler): ...@@ -502,7 +502,7 @@ class BaseClient(BaseTestHandler):
class BaseTestAPI: class BaseTestAPI:
def tearDown(self): def tearDown(self):
asyncore.close_all() asyncore.close_all(ignore_all=True)
def loop_waiting_for_flag(self, instance, timeout=5): def loop_waiting_for_flag(self, instance, timeout=5):
timeout = float(timeout) / 100 timeout = float(timeout) / 100
...@@ -755,7 +755,8 @@ class BaseTestAPI: ...@@ -755,7 +755,8 @@ class BaseTestAPI:
def test_set_reuse_addr(self): def test_set_reuse_addr(self):
if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX: if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX:
self.skipTest("Not applicable to AF_UNIX sockets.") self.skipTest("Not applicable to AF_UNIX sockets.")
sock = socket.socket(self.family)
with socket.socket(self.family) as sock:
try: try:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
except OSError: except OSError:
...@@ -771,34 +772,33 @@ class BaseTestAPI: ...@@ -771,34 +772,33 @@ class BaseTestAPI:
s.set_reuse_addr() s.set_reuse_addr()
self.assertTrue(s.socket.getsockopt(socket.SOL_SOCKET, self.assertTrue(s.socket.getsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR)) socket.SO_REUSEADDR))
finally:
sock.close()
@unittest.skipUnless(threading, 'Threading required for this test.') @unittest.skipUnless(threading, 'Threading required for this test.')
@support.reap_threads @support.reap_threads
def test_quick_connect(self): def test_quick_connect(self):
# see: http://bugs.python.org/issue10340 # see: http://bugs.python.org/issue10340
if self.family in (socket.AF_INET, getattr(socket, "AF_INET6", object())): if self.family not in (socket.AF_INET, getattr(socket, "AF_INET6", object())):
self.skipTest("test specific to AF_INET and AF_INET6")
server = BaseServer(self.family, self.addr) server = BaseServer(self.family, self.addr)
# run the thread 500 ms: the socket should be connected in 200 ms
t = threading.Thread(target=lambda: asyncore.loop(timeout=0.1, t = threading.Thread(target=lambda: asyncore.loop(timeout=0.1,
count=500)) count=5))
t.start() t.start()
def cleanup(): try:
t.join(timeout=TIMEOUT) with socket.socket(self.family, socket.SOCK_STREAM) as s:
if t.is_alive():
self.fail("join() timed out")
self.addCleanup(cleanup)
s = socket.socket(self.family, socket.SOCK_STREAM)
s.settimeout(.2) s.settimeout(.2)
s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
struct.pack('ii', 1, 0)) struct.pack('ii', 1, 0))
try: try:
s.connect(server.address) s.connect(server.address)
except OSError: except OSError:
pass pass
finally: finally:
s.close() t.join(timeout=TIMEOUT)
if t.is_alive():
self.fail("join() timed out")
class TestAPI_UseIPv4Sockets(BaseTestAPI): class TestAPI_UseIPv4Sockets(BaseTestAPI):
family = socket.AF_INET family = socket.AF_INET
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment