From c5076f5e019b73ec2f6efea5a4bafed90423df8f Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 3 Jun 2016 11:47:07 +1200 Subject: [PATCH] Implement a service connection handler counter, use it in Pathod test suite Lots of failures, but that's a good thing. --- netlib/tcp.py | 35 ++++++++++++++++++++++++++++------- pathod/test.py | 15 +++++++++++++++ test/pathod/tutils.py | 1 + 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/netlib/tcp.py b/netlib/tcp.py index 914aa7014..bb0c93a98 100644 --- a/netlib/tcp.py +++ b/netlib/tcp.py @@ -833,6 +833,25 @@ class BaseHandler(_Connection): return b"" +class Counter: + def __init__(self): + self._count = 0 + self._lock = threading.Lock() + + @property + def count(self): + with self._lock: + return self._count + + def __enter__(self): + with self._lock: + self._count += 1 + + def __exit__(self, *args): + with self._lock: + self._count -= 1 + + class TCPServer(object): request_queue_size = 20 @@ -845,15 +864,17 @@ class TCPServer(object): self.socket.bind(self.address()) self.address = Address.wrap(self.socket.getsockname()) self.socket.listen(self.request_queue_size) + self.counter = Counter() def connection_thread(self, connection, client_address): - client_address = Address(client_address) - try: - self.handle_client_connection(connection, client_address) - except: - self.handle_error(connection, client_address) - finally: - close_socket(connection) + with self.counter: + client_address = Address(client_address) + try: + self.handle_client_connection(connection, client_address) + except: + self.handle_error(connection, client_address) + finally: + close_socket(connection) def serve_forever(self, poll_interval=0.1): self.__is_shut_down.clear() diff --git a/pathod/test.py b/pathod/test.py index 32b377311..b10e92298 100644 --- a/pathod/test.py +++ b/pathod/test.py @@ -7,6 +7,10 @@ from six.moves import queue from . import pathod +class TimeoutError(Exception): + pass + + class Daemon: IFACE = "127.0.0.1" @@ -40,6 +44,17 @@ class Daemon: def text_log(self): return self.logfp.getvalue() + def wait_for_silence(self, timeout=5): + start = time.time() + while 1: + if time.time() - start >= timeout: + raise TimeoutError( + "%s service threads still alive" % + self.thread.server.counter.count + ) + if self.thread.server.counter.count == 0: + return + def expect_log(self, n, timeout=5): l = [] start = time.time() diff --git a/test/pathod/tutils.py b/test/pathod/tutils.py index a99a2fd36..e674812ba 100644 --- a/test/pathod/tutils.py +++ b/test/pathod/tutils.py @@ -64,6 +64,7 @@ class DaemonTests(object): shutil.rmtree(cls.confdir) def teardown(self): + self.d.wait_for_silence() if not (self.noweb or self.noapi): self.d.clear_log()