Retry client connections in selftest
[mudpy.git] / mudpy / tests / selftest.py
index bb6f28a..c0bfc3c 100644 (file)
@@ -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."