Make selftest dialogue mutable
[mudpy.git] / mudpy / tests / selftest.py
index 86ffe22..d5b8ac4 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2004-2019 mudpy authors. Permission to use, copy,
+# Copyright (c) 2004-2020 mudpy authors. Permission to use, copy,
 # modify, and distribute this software is granted under terms
 # provided in the LICENSE file distributed with this software.
 
 # modify, and distribute this software is granted under terms
 # provided in the LICENSE file distributed with this software.
 
@@ -11,6 +11,13 @@ import sys
 import telnetlib
 import time
 
 import telnetlib
 import time
 
+# TODO(fungi) Clean this up once Python 3.5 is no longer supported
+if sys.version < "3.6":
+    import collections
+    odict = collections.OrderedDict
+else:
+    odict = dict
+
 pidfile = "var/mudpy.pid"
 
 test_account0_setup = (
 pidfile = "var/mudpy.pid"
 
 test_account0_setup = (
@@ -143,9 +150,48 @@ test_actor_disappears = (
     (0, r"You suddenly wonder where .* went\.", ""),
 )
 
     (0, r"You suddenly wonder where .* went\.", ""),
 )
 
-test_account1_teardown = (
+test_abort_avatar_deletion = (
     (1, r"What would you like to do\?", "d"),
     (1, r"Whom would you like to delete\?", ""),
     (1, r"What would you like to do\?", "d"),
     (1, r"Whom would you like to delete\?", ""),
+    (1, r"delete an unwanted avatar.*What would you like to do\?", ""),
+)
+
+test_avatar_creation_limit = (
+    (1, r"What would you like to do\?", "c"),
+    (1, "Pick a birth gender for your new avatar:", "m"),
+    (1, "Choose a name for him:", "3"),
+    (1, r"What would you like to do\?", "c"),
+    (1, "Pick a birth gender for your new avatar:", "m"),
+    (1, "Choose a name for him:", "4"),
+    (1, r"What would you like to do\?", "c"),
+    (1, "Pick a birth gender for your new avatar:", "m"),
+    (1, "Choose a name for him:", "7"),
+    (1, r"What would you like to do\?", "c"),
+    (1, "Pick a birth gender for your new avatar:", "m"),
+    (1, "Choose a name for him:", "5"),
+    (1, r"What would you like to do\?", "c"),
+    (1, "Pick a birth gender for your new avatar:", "m"),
+    (1, "Choose a name for him:", "2"),
+    (1, r"What would you like to do\?", "c"),
+    (1, "Pick a birth gender for your new avatar:", "m"),
+    (1, "Choose a name for him:", "6"),
+    (1, r"What would you like to do\?", "c"),
+    (1, r"That is not a valid choice\.\.\.", ""),
+)
+
+test_avatar_deletion = (
+    (1, r"What would you like to do\?", "d"),
+    (1, r"Whom would you like to delete\?", "1"),
+    (1, r"create a new avatar.*What would you like to do\?", ""),
+)
+
+test_abort_account_deletion = (
+    (1, r"What would you like to do\?", "p"),
+    (1, r"permanently delete your account\?", ""),
+    (1, r"What would you like to do\?", ""),
+)
+
+test_account_deletion = (
     (1, r"What would you like to do\?", "p"),
     (1, r"permanently delete your account\?", "y"),
     (1, r"Disconnecting\.\.\.", ""),
     (1, r"What would you like to do\?", "p"),
     (1, r"permanently delete your account\?", "y"),
     (1, r"Disconnecting\.\.\.", ""),
@@ -297,7 +343,7 @@ test_show_result = (
     (2, r"\r\n838102050\r\n.*> ", "show result 1/0"),
     (2, r"Your expression raised an exception.*division by zero.*> ",
      "show result mudpy"),
     (2, r"\r\n838102050\r\n.*> ", "show result 1/0"),
     (2, r"Your expression raised an exception.*division by zero.*> ",
      "show result mudpy"),
-    (2, r"<module 'mudpy' from .*> ", "show result re"),
+    (2, r"<module 'mudpy' from.*> ", "show result re"),
     (2, r"Your expression raised an exception.*name 're' is not defined.*> ",
      "show result universe"),
     (2, r"<mudpy\.misc\.Universe object at 0x.*> ", "show result actor"),
     (2, r"Your expression raised an exception.*name 're' is not defined.*> ",
      "show result universe"),
     (2, r"<mudpy\.misc\.Universe object at 0x.*> ", "show result actor"),
@@ -308,14 +354,14 @@ test_show_result = (
 test_show_log = (
     (2, "> ", "show log"),
     (2, r"There are [0-9]+ log lines in memory and [0-9]+ at or above level "
 test_show_log = (
     (2, "> ", "show log"),
     (2, r"There are [0-9]+ log lines in memory and [0-9]+ at or above level "
-        r"[0-9]+\. The matching lines\r\nfrom [0-9]+ to [0-9]+ are:", ""),
+        r"[0-9]+\. The matching.*from [0-9]+ to [0-9]+ are:", ""),
 )
 
 test_custom_loglevel = (
     (2, "> ", "set account.admin loglevel 2"),
     (2, "You have successfully .*> ", "show log"),
     (2, r"There are [0-9]+ log lines in memory and [0-9]+ at or above level "
 )
 
 test_custom_loglevel = (
     (2, "> ", "set account.admin loglevel 2"),
     (2, "You have successfully .*> ", "show log"),
     (2, r"There are [0-9]+ log lines in memory and [0-9]+ at or above level "
-        r"[0-9]+\. The matching lines\r\nfrom [0-9]+ to [0-9]+ are:", ""),
+        r"[0-9]+\. The matching.*from [0-9]+ to [0-9]+ are:", ""),
 )
 
 test_invalid_loglevel = (
 )
 
 test_invalid_loglevel = (
@@ -330,20 +376,16 @@ test_log_no_errors = (
 
 final_cleanup = (
     (0, "> ", "quit"),
 
 final_cleanup = (
     (0, "> ", "quit"),
-    (0, r"What would you like to do\?", "d"),
-    (0, r"Whom would you like to delete\?", ""),
     (0, r"What would you like to do\?", "p"),
     (0, r"permanently delete your account\?", "y"),
     (0, r"Disconnecting\.\.\.", ""),
     (2, "> ", "quit"),
     (0, r"What would you like to do\?", "p"),
     (0, r"permanently delete your account\?", "y"),
     (0, r"Disconnecting\.\.\.", ""),
     (2, "> ", "quit"),
-    (2, r"What would you like to do\?", "d"),
-    (2, r"Whom would you like to delete\?", ""),
     (2, r"What would you like to do\?", "p"),
     (2, r"permanently delete your account\?", "y"),
     (2, r"Disconnecting\.\.\.", ""),
 )
 
     (2, r"What would you like to do\?", "p"),
     (2, r"permanently delete your account\?", "y"),
     (2, r"Disconnecting\.\.\.", ""),
 )
 
-dialogue = (
+dialogue = odict((
     (test_account0_setup, "first account setup"),
     (test_account1_setup, "second account setup"),
     (test_actor_appears, "actor spontaneous appearance"),
     (test_account0_setup, "first account setup"),
     (test_account1_setup, "second account setup"),
     (test_actor_appears, "actor spontaneous appearance"),
@@ -357,7 +399,11 @@ dialogue = (
     (test_escape_macros, "replacement macros are escaped"),
     (test_movement, "movement"),
     (test_actor_disappears, "actor spontaneous disappearance"),
     (test_escape_macros, "replacement macros are escaped"),
     (test_movement, "movement"),
     (test_actor_disappears, "actor spontaneous disappearance"),
-    (test_account1_teardown, "second account teardown"),
+    (test_abort_avatar_deletion, "abort avatar deletion"),
+    (test_avatar_creation_limit, "avatar creation limit"),
+    (test_avatar_deletion, "avatar deletion"),
+    (test_abort_account_deletion, "abort account deletion"),
+    (test_account_deletion, "account deletion"),
     (test_admin_setup, "admin account setup"),
     (test_preferences, "set and show preferences"),
     (test_crlf_eol, "send crlf from the client as eol"),
     (test_admin_setup, "admin account setup"),
     (test_preferences, "set and show preferences"),
     (test_crlf_eol, "send crlf from the client as eol"),
@@ -384,14 +430,14 @@ dialogue = (
     (test_invalid_loglevel, "invalid loglevel"),
     (test_log_no_errors, "no errors logged"),
     (final_cleanup, "delete remaining accounts"),
     (test_invalid_loglevel, "invalid loglevel"),
     (test_log_no_errors, "no errors logged"),
     (final_cleanup, "delete remaining accounts"),
-)
+))
 
 
 def start_service(config):
     # Clean up any previously run daemon which didn't terminate
     if os.path.exists(pidfile):
 
 
 def start_service(config):
     # Clean up any previously run daemon which didn't terminate
     if os.path.exists(pidfile):
-        pidfd = open(pidfile)
-        pid = int(pidfd.read())
+        with open(pidfile) as pidfd:
+            pid = int(pidfd.read())
         try:
             # Stop the running service
             os.kill(pid, 15)
         try:
             # Stop the running service
             os.kill(pid, 15)
@@ -434,8 +480,8 @@ def stop_service(service):
 
     # This cleans up a daemonized and disassociated service
     if os.path.exists(pidfile):
 
     # This cleans up a daemonized and disassociated service
     if os.path.exists(pidfile):
-        pidfd = open(pidfile)
-        pid = int(pidfd.read())
+        with open(pidfile) as pidfd:
+            pid = int(pidfd.read())
         try:
             # Stop the running service
             os.kill(pid, 15)
         try:
             # Stop the running service
             os.kill(pid, 15)
@@ -451,11 +497,11 @@ def stop_service(service):
     # Log the contents of stdout and stderr, if any
     stdout, stderr = service.communicate()
     tlog("\nRecording stdout as capture_stdout.log.")
     # Log the contents of stdout and stderr, if any
     stdout, stderr = service.communicate()
     tlog("\nRecording stdout as capture_stdout.log.")
-    serviceout = open("capture_stdout.log", "w")
-    serviceout.write(stdout.decode("utf-8"))
+    with open("capture_stdout.log", "w") as serviceout:
+        serviceout.write(stdout.decode("utf-8"))
     tlog("\nRecording stderr as capture_stderr.log.")
     tlog("\nRecording stderr as capture_stderr.log.")
-    serviceerr = open("capture_stderr.log", "w")
-    serviceerr.write(stderr.decode("utf-8"))
+    with open("capture_stderr.log", "w") as serviceerr:
+        serviceerr.write(stderr.decode("utf-8"))
 
     return(success)
 
 
     return(success)
 
@@ -489,10 +535,14 @@ def main():
     if len(sys.argv) > 1:
         # Start the service if a config file was provided on the command line
         service = start_service(sys.argv[1])
     if len(sys.argv) > 1:
         # Start the service if a config file was provided on the command line
         service = start_service(sys.argv[1])
+        if not service:
+            tlog("\nERROR: Service did not start.\n")
+            sys.exit(1)
     for luser in lusers:
         luser.open("::1", 4000)
         luser.set_option_negotiation_callback(option_callback)
     for luser in lusers:
         luser.open("::1", 4000)
         luser.set_option_negotiation_callback(option_callback)
-    for test, description in dialogue:
+    selected_dialogue = odict(dialogue)
+    for test, description in selected_dialogue.items():
         tlog("\nTesting %s..." % description)
         test_start = time.time()
         for conversant, question, answer in test:
         tlog("\nTesting %s..." % description)
         test_start = time.time()
         for conversant, question, answer in test: