]> www.git.momoyon.org Git - commonlib.git/commitdiff
[test.py] Update
authorahmedsamyh <ahmedsamyh10@gmail.com>
Mon, 7 Apr 2025 17:19:28 +0000 (22:19 +0500)
committerahmedsamyh <ahmedsamyh10@gmail.com>
Mon, 7 Apr 2025 17:19:28 +0000 (22:19 +0500)
test.py

diff --git a/test.py b/test.py
index ca4588c3207a35f6c2a53db9f48d6f662cc42805..9cfceeb7b41c878c6e3cdf7fd830ba91504a3fd0 100644 (file)
--- a/test.py
+++ b/test.py
@@ -3,8 +3,72 @@ import os
 import subprocess
 import sys
 import shlex
+import coloredlogs, logging
 
-# TODO: Use Colored logging
+'''-COLORED PRINT------------'''
+import sys
+
+colors_table = {
+    'BLACK':   [ '30', '40' ],
+    'RED':     [ '31', '41' ],
+    'GREEN':   [ '32', '42' ],
+    'YELLOW':  [ '33', '43' ],
+    'BLUE':    [ '34', '44' ],
+    'MAGENTA': [ '35', '45' ],
+    'CYAN':    [ '36', '46' ],
+    'WHITE':   [ '37', '47' ],
+    'DEFAULT': [ '39', '49' ],
+    'RESET':   [ '00', '00' ],
+}
+
+def set_color(fg: str = 'DEFAULT', bg: str = 'DEFAULT', file=sys.stdout):
+    bg = bg.upper()
+    fg = fg.upper()
+    if bg not in colors_table:
+        raise ValueError(f'{bg} is not a valid color!, we only support 8 colors only!')
+    if fg not in colors_table:
+        raise ValueError(f'{fg} is not a valid color!, we only support 8 colors only!')
+    print(f"\033[{colors_table[fg][0]};{colors_table[bg][1]}m", file=file, end='')
+
+
+def cprint(fg: str, bg: str, msg: str, file=sys.stdout, *args, **kwargs):
+    set_color(fg, bg, file)
+    print(msg, file=file, **kwargs)
+    set_color(file=file)
+'''-------------------------'''
+
+CMD_LEVEL = 15
+logging.addLevelName(CMD_LEVEL, "CMD")
+
+class MyLogger(logging.Logger):
+    def cmd(self, msg, *args, **kwargs):
+        if self.isEnabledFor(CMD_LEVEL):
+            self._log(CMD_LEVEL, msg, args, **kwargs)
+
+
+logging.setLoggerClass(MyLogger)
+
+logger = logging.getLogger('test')
+logger.setLevel(logging.DEBUG)
+
+coloredlogs.install(
+    level='DEBUG', 
+    fmt='%(name)s [%(levelname)s]: %(message)s',
+    level_styles={
+        'cmd': {'color': 'cyan'},  # Color for CMD level
+        'debug': {'color': 'white'},
+        'info': {'color': 'green'},
+        'warning': {'color': 'yellow'},
+        'error': {'color': 'red'},
+        'critical': {'color': 'magenta'},
+    },
+    field_styles={
+        'name': {'color': 'cyan'},
+        'levelname': {'bold': True},
+    }
+)
+
+# TODO: Implement or Use a third-party diff-ing library
 
 ## Substitutable values; These values are substituted with the following values if found in BUILD_CMD or RUN_CMD
 
@@ -39,9 +103,21 @@ def get_cmd_substituted(cmd, tests, current_test):
 
 def check_crucial_envvar(var, var_name):
     if var == "NOT SET":
-        print(f"[ERROR] `{var_name}` environment variable not set! please provide a value and run again!", file=sys.stderr)
+        logger.error(f"`{var_name}` environment variable not set! please provide a value and run again!")
         exit(1)
 
+
+def expect_output(expected_name: str, expected: str, got: str):
+    print(f"Expected {expected_name}: ")
+    print(">>>")
+    cprint("green", "default", expected)
+    print(">>>")
+    print("But got: ")
+    print("<<<")
+    cprint("red", "default", got)
+    print("<<<")
+
+
 class Test:
     stdin = ''
     expected_stdout = ''
@@ -62,7 +138,7 @@ class Test:
                 with open(f, "w") as file:
                     pass
                     # NOTE: Why do we need to log this?
-                    # print(f"[INFO] Created empty {self.name}.{name}.expected")
+                    # logger.info("Created empty {self.name}.{name}.expected")
                 return ""
             else:
                 with open(f, "r") as file:
@@ -125,7 +201,7 @@ class Test:
             return input_array
 
 def usage(program: str):
-    print(f"Usage: {program} <subcmd> [flags]")
+    logger.info(f"Usage: {program} <subcmd> [flags]")
 
 # NOTE: We named this hhelp because help is a builtin python function
 def hhelp():
@@ -143,15 +219,11 @@ def hhelp():
         -x      - Stop on first error.
           ''')
 
-def vlog(verbose_output, msg):
-    if verbose_output:
-        print(msg)
-
 def main():
     program = sys.argv.pop(0)
 
     if len(sys.argv) <= 0:
-        print("[ERROR] Please provide at least one subcommand!", file=sys.stderr)
+        logger.error("Please provide at least one subcommand!")
         usage(program)
         hhelp()
         exit(1)
@@ -184,11 +256,11 @@ def main():
         elif flag == 'x':
             stop_on_error = True
         else:
-            print(f"[ERROR] Invalid flag '{flag}'", file=sys.stderr)
+            logger.error(f"Invalid flag '{flag}'")
             exit(1)
 
     if len(subcmds) <= 0:
-        print("[ERROR] Please provide at least one subcommand!", file=sys.stderr)
+        logger.error("Please provide at least one subcommand!")
         usage(program)
         hhelp()
         exit(1)
@@ -199,7 +271,7 @@ def main():
     check_crucial_envvar(SRC_SUFFIX, "SRC_SUFFIX")
 
     os.chdir(TESTS_DIR)
-    vlog(verbose_output, f"[INFO] Changed cwd to {os.getcwd()}")
+    if verbose_output: logger.info(f"Changed cwd to {os.getcwd()}")
 
     tests = {}
 
@@ -224,45 +296,47 @@ def main():
             exit(0)
         elif subcmd == "build":
             check_crucial_envvar(BUILD_CMD, "BUILD_CMD")
-            print(f'----- [BUILD] -----')
+            cprint('green', 'default', f'----- [BUILD] -----')
             for test_name in tests:
-                print(f'+ Building {test_name} [{current_test_id+1}/{total_tests_count}]...')
+                cprint('green', 'default', f'+ Building {test_name}.{SRC_SUFFIX} [{current_test_id+1}/{total_tests_count}]...')
                 current_test_id += 1
                 test = tests[test_name]
 
                 if test.build_expected_returncode == -1:
-                    print(f"[WARNING] Test doesn't have any expected build returncode!")
-                    print(f"[WARNING] Please record the expected build behaviour of the test using the 'record_build' subcommand!")
-                    print(f"[SKIPPING]...")
+                    logger.warning(f"Test doesn't have any expected build returncode!")
+                    logger.warning(f"Please record the expected build behaviour of the test using the 'record_build' subcommand!")
+                    cprint('yellow', 'default', f"[SKIPPING]...")
                     if stop_on_error: exit(1)
                     continue
 
                 cmd = shlex.split(get_cmd_substituted(BUILD_CMD, tests, test_name))
                 build_stdin_list = test.get_build_stdin_list()
                 if len(build_stdin_list) > 0: cmd.extend(build_stdin_list)
-                vlog(verbose_output, f"[CMD] {cmd}")
+                vlog(verbose_output, f"[CMD] {cmd}")
                 res = subprocess.run(cmd, capture_output = True, text = True)
                 if res.returncode != 0:
-                    print("[FAILED] ", end='')
+                    m = ''
                     if res.stderr:
-                        print(f"{res.stderr}")
-                    else:
-                        print('')
+                        m += f"{res.stderr}"
+                    logger.error("[FAILED] {m}")
+
                     if stop_on_error: exit(1)
                     else: continue
                 else:
+                    failed = False
                     if res.stdout != test.build_expected_stdout:
-                        print('[FAILED]', file=sys.stderr)
-                        print(f"build_Expected: >>>{test.build_expected_stdout}>>>")
-                        print(f"But Got: >>>{res.stdout}>>>")
+                        cprint('red', 'default', f'[FAILED]')
+                        expect_output("stdout", test.build_expected_stdout, res.stdout)
+                        failed = True
                         if stop_on_error: exit(1)
                     if res.stderr != test.build_expected_stderr:
-                        print('[FAILED]', file=sys.stderr)
-                        print(f"build_Expected: >>>{test.build_expected_stderr}>>>")
-                        print(f"But Got: >>>{res.stderr}>>>")
+                        cprint('red', 'default', f'[FAILED]')
+                        expect_output("stderr", test.build_expected_stderr, res.stderr)
+                        failed = True
                         if stop_on_error: exit(1)
-                    passing_tests_count += 1
-                    print("[PASS] ", end='')
+                    if not failed:
+                        passing_tests_count += 1
+                        cprint('green', 'default', "[PASS] ")
                     o = False
                     if verbose_output and res.stdout:
                         print(f"{res.stdout}")
@@ -275,34 +349,33 @@ def main():
                 print(f"Build {passing_tests_count}/{total_tests_count} tests")
         elif subcmd == "run":
             check_crucial_envvar(RUN_CMD, "RUN_CMD")
-            print(f'----- [RUN] -----')
+            cprint('green', 'default', f'----- [RUN] -----')
             for test_name in tests:
-                print(f'+ Running {test_name} [{current_test_id+1}/{total_tests_count}]...')
+                cprint('green', 'default', f'+ Running {test_name} [{current_test_id+1}/{total_tests_count}]...')
                 current_test_id += 1
                 test = tests[test_name]
 
                 res = None
                 try:
                     cmd = shlex.split(get_cmd_substituted(RUN_CMD, tests, test_name))
-                    vlog(verbose_output, f"[CMD] {cmd}")
+                    vlog(verbose_output, f"[CMD] {cmd}")
                     res = subprocess.run(cmd, capture_output = True, text = True)
                 except Exception as e:
-                    print(f"[ERROR] Failed to run ./{test_name}: {e}")
+                    logger.error("Failed to run ./{test_name}: {e}")
                     if stop_on_error: exit(1)
                     else: continue
 
                 if test.expected_returncode == -1:
-                    print(f"[WARNING] Test doesn't have any expected returncode!")
-                    print(f"[WARNING] Please record the expected behaviour of the test using the 'record' subcommand!")
+                    logger.warning(f"Test doesn't have any expected returncode!")
+                    logger.warning(f"Please record the expected behaviour of the test using the 'record' subcommand!")
 
                 if res.stdout != test.expected_stdout:
-                    print('[FAILED]', file=sys.stderr)
-                    print(f"Expected: >>>{test.expected_stdout}>>>")
-                    print(f"But Got: >>>{res.stdout}>>>")
+                    cprint('red', 'default', f'[FAILED]')
+                    expect_output("stdout", test.expected_stdout, res.stdout)
                     if stop_on_error: exit(1)
                     else: continue
                 passing_tests_count += 1
-                print('[PASS]')
+                cprint('green', 'default', '[PASS]')
 
             print(f"PASSED {passing_tests_count}/{total_tests_count}")
         elif subcmd == "record":
@@ -315,7 +388,7 @@ def main():
                 cmd = shlex.split(get_cmd_substituted(RUN_CMD, tests, test_name))
                 stdin_list = test.get_stdin_list()
                 if len(stdin_list) > 0: cmd.extend(stdin_list)
-                vlog(verbose_output, f"[CMD] {cmd}")
+                vlog(verbose_output, f"[CMD] {cmd}")
                 res = subprocess.run([f"./{test_name}"], capture_output = True, text = True)
 
                 print(f"stdout: {res.stdout}")
@@ -341,7 +414,7 @@ def main():
                 test = tests[test_name]
 
                 if len(test.build_stdin) > 0:
-                    print(f"[INFO] Test already has build_input '{test.build_stdin}'...")
+                    logger.info("Test already has build_input '{test.build_stdin}'...")
                     ans = input("Do you want to change the build_input? [y/N]")
                     if ans.lower() == 'y':
                         test.build_stdin = input("What is the input passed? ")
@@ -354,7 +427,7 @@ def main():
                 cmd = shlex.split(get_cmd_substituted(BUILD_CMD, tests, test_name))
                 build_stdin_list = test.get_build_stdin_list()
                 if len(build_stdin_list) > 0: cmd.extend(build_stdin_list)
-                vlog(verbose_output, f"[CMD] {cmd}")
+                vlog(verbose_output, f"[CMD] {cmd}")
                 res = subprocess.run(cmd, capture_output = True, text = True)
 
                 print(f"stdout: {res.stdout}")