From 743c99fee8de7db57253daa15602bb4af6f85eda Mon Sep 17 00:00:00 2001 From: Jeremy Stanley Date: Sat, 17 Apr 2021 16:07:33 +0000 Subject: [PATCH] Retry client connections in selftest Replace a hard-coded delay after process start with a dynamic client connection retry, which attempts to connect up to five times with the first being immediate while subsequent connections observe an exponential backoff over a three-second period before giving up. This improves both speed and stability of test runs. Also combine the ConnectionResetError and EOFError conditions which could be raised later once the socket is in use, as the end result of either is effectively the same. --- mudpy/tests/selftest.py | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/mudpy/tests/selftest.py b/mudpy/tests/selftest.py index bb6f28a..c0bfc3c 100644 --- a/mudpy/tests/selftest.py +++ b/mudpy/tests/selftest.py @@ -477,7 +477,6 @@ def start_service(config): service = subprocess.Popen(("mudpy", config), stdout=subprocess.PIPE, stderr=subprocess.PIPE) - time.sleep(1) return service @@ -551,6 +550,31 @@ def check_debug(): return False +def connect_client(luser, service): + # Try multiple times to connect, with an exponential backoff + for retry in range(5): + try: + # Skipping the retry=0 case gives an immediate first attempt + if retry: + time.sleep((2 ** retry) / 10) + luser.open("::1", 4000) + # Attempt to poll the connection, closing if unusable + try: + luser.fill_rawq() + except ConnectionResetError: + luser.close() + continue + # Short-circuit if we get this far, connection is safe to use + return luser + except ConnectionRefusedError: + continue + else: + # Connection retries have been exhausted, so give up + tlog("\nERROR: Client could not connect.\n") + stop_service(service) + sys.exit(1) + + def main(): captures = ["", "", ""] lusers = [telnetlib.Telnet(), telnetlib.Telnet(), telnetlib.Telnet()] @@ -564,7 +588,7 @@ def main(): tlog("\nERROR: Service did not start.\n") sys.exit(1) for luser in lusers: - luser.open("::1", 4000) + connect_client(luser, service) luser.set_option_negotiation_callback(option_callback) selected_dialogue = dict(dialogue) if check_debug(): @@ -583,11 +607,7 @@ def main(): index, match, received = lusers[conversant].expect( [re.compile(question.encode("utf-8"), flags=re.DOTALL)], 5) captures[conversant] += received.decode("utf-8") - except ConnectionResetError: - tlog("\nERROR: Unable to connect to server.") - success = False - break - except EOFError: + except (ConnectionResetError, EOFError): tlog("\nERROR: luser%s premature disconnection expecting:\n\n" "%s\n\n" "Check the end of capture_%s.log for received data." -- 2.11.0