From d70bb131333c1f6983e0885cf8bf2aee659abc61 Mon Sep 17 00:00:00 2001
From: Henry LE BERRE <hberre3@gatech.edu>
Date: Tue, 14 Nov 2023 20:15:00 -0800
Subject: [PATCH] #229: Elapsed time in test suite

---
 toolchain/mfc/test/case.py |  7 +++++--
 toolchain/mfc/test/test.py | 21 +++++++++++++--------
 2 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/toolchain/mfc/test/case.py b/toolchain/mfc/test/case.py
index 6c0af864ba..6cb7bb5665 100644
--- a/toolchain/mfc/test/case.py
+++ b/toolchain/mfc/test/case.py
@@ -2,6 +2,7 @@
 
 from ..      import case, common
 from ..state import ARG
+from ..build import MFCTarget, get_target
 
 Tend = 0.25
 Nt   = 50
@@ -99,7 +100,7 @@ def __init__(self, trace: str, mods: dict, ppn: int = None) -> None:
         self.ppn   = ppn if ppn is not None else 1
         super().__init__({**BASE_CFG.copy(), **mods})
 
-    def run(self, targets: typing.List[str], gpus: typing.Set[int]) -> subprocess.CompletedProcess:
+    def run(self, targets: typing.List[typing.Union[str, MFCTarget]], gpus: typing.Set[int]) -> subprocess.CompletedProcess:
         if gpus is not None and len(gpus) != 0:
             gpus_select = f"--gpus {' '.join([str(_) for _ in gpus])}"
         else:
@@ -113,9 +114,11 @@ def run(self, targets: typing.List[str], gpus: typing.Set[int]) -> subprocess.Co
         
         mfc_script = ".\mfc.bat" if os.name == 'nt' else "./mfc.sh"
         
+        target_names = [ get_target(t).name for t in targets ]
+
         command: str = f'''\
             {mfc_script} run {filepath} {tasks} {binary_option} \
-            {case_optimization} {jobs} -t {' '.join(targets)} \
+            {case_optimization} {jobs} -t {' '.join(target_names)} \
             {gpus_select} 2>&1\
             '''
 
diff --git a/toolchain/mfc/test/test.py b/toolchain/mfc/test/test.py
index 64116f1d02..902d7c691e 100644
--- a/toolchain/mfc/test/test.py
+++ b/toolchain/mfc/test/test.py
@@ -1,4 +1,4 @@
-import os, math, typing, shutil
+import os, math, typing, shutil, time
 
 from random    import sample
 from ..printer import cons
@@ -8,7 +8,7 @@
 from .cases    import generate_cases
 from ..        import sched
 from ..common  import MFCException, does_command_exist, format_list_to_string, get_program_output
-from ..build   import build_targets, HDF5
+from ..build   import build_targets, HDF5, PRE_PROCESS, SIMULATION, POST_PROCESS
 
 from ..packer import tol as packtol
 from ..packer import packer
@@ -91,7 +91,7 @@ def test():
 
         return
 
-    codes = ["pre_process", "simulation"] + (["post_process"] if ARG('test_all') else [])
+    codes = [PRE_PROCESS, SIMULATION] + ([POST_PROCESS] if ARG('test_all') else [])
     if not ARG("case_optimization"):
         build_targets(codes)
 
@@ -100,12 +100,12 @@ def test():
     if len(ARG("only")) > 0:
         range_str = "Only " + format_list_to_string(ARG("only"), "bold magenta", "Nothing to run")
     
-    cons.print(f"[bold]Test {format_list_to_string(codes, 'magenta')}[/bold] | {range_str} ({len(CASES)} test{'s' if len(CASES) != 1 else ''})")
+    cons.print(f"[bold]Test {format_list_to_string([ x.name for x in codes ], 'magenta')}[/bold] | {range_str} ({len(CASES)} test{'s' if len(CASES) != 1 else ''})")
     cons.indent()
 
     # Run CASES with multiple threads (if available)
     cons.print()
-    cons.print(f" tests/[bold magenta]UUID[/bold magenta]    Summary")
+    cons.print(f" tests/[bold magenta]UUID[/bold magenta]     (s)      Summary")
     cons.print()
     
     # Select the correct number of threads to use to launch test CASES
@@ -132,6 +132,8 @@ def test():
 
 
 def _handle_case(test: TestCase, devices: typing.Set[int]):
+    start_time = time.time()
+
     if test.params.get("qbmm", 'F') == 'T':
         tol = 1e-10
     elif test.params.get("bubbles", 'F') == 'T':
@@ -144,7 +146,7 @@ def _handle_case(test: TestCase, devices: typing.Set[int]):
     test.delete_output()
     test.create_directory()
 
-    cmd = test.run(["pre_process", "simulation"], gpus=devices)
+    cmd = test.run([PRE_PROCESS, SIMULATION], gpus=devices)
 
     out_filepath = os.path.join(test.get_dirpath(), "out_pre_sim.txt")
 
@@ -184,7 +186,7 @@ def _handle_case(test: TestCase, devices: typing.Set[int]):
 
     if ARG("test_all"):
         test.delete_output()
-        cmd = test.run(["pre_process", "simulation", "post_process"], gpus=devices)
+        cmd = test.run([PRE_PROCESS, SIMULATION, POST_PROCESS], gpus=devices)
         out_filepath = os.path.join(test.get_dirpath(), "out_post.txt")
         common.file_write(out_filepath, cmd.stdout)
 
@@ -214,7 +216,10 @@ def _handle_case(test: TestCase, devices: typing.Set[int]):
 
     test.delete_output()
 
-    cons.print(f"  [bold magenta]{test.get_uuid()}[/bold magenta]    {test.trace}")
+    end_time = time.time()
+    duration = end_time - start_time
+
+    cons.print(f"  [bold magenta]{test.get_uuid()}[/bold magenta]    {duration:6.2f}    {test.trace}")
 
 
 def handle_case(test: TestCase, devices: typing.Set[int]):