@@ -66,6 +66,11 @@ static int parse_arg(const char* key, const char* value, struct TestFramework* t
6666    if  (strcmp (key , "t" ) ==  0  ||  strcmp (key , "target" ) ==  0 ) {
6767        return  parse_target (value , tf );
6868    }
69+     /* Logging */ 
70+     if  (strcmp (key , "log" ) ==  0 ) {
71+         tf -> args .logging  =  value  &&  strcmp (value , "1" ) ==  0 ;
72+         return  0 ;
73+     }
6974
7075    /* Unknown key: report just so typos don’t silently pass. */ 
7176    printf ("Unknown argument '-%s=%s'\n" , key , value );
@@ -83,6 +88,7 @@ static void help(void) {
8388    printf ("    -seed=<hex>                         Set a specific RNG seed (default: random)\n" );
8489    printf ("    -target=<test name>, -t=<name>      Run a specific test (can be provided multiple times)\n" );
8590    printf ("    -target=<module name>, -t=<module>  Run all tests within a specific module (can be provided multiple times)\n" );
91+     printf ("    -log=<0|1>                          Enable or disable test execution logging (default: 0 = disabled)\n" );
8692    printf ("\n" );
8793    printf ("Notes:\n" );
8894    printf ("    - All arguments must be provided in the form '-key=value'.\n" );
@@ -192,18 +198,21 @@ static int read_args(int argc, char** argv, int start, struct TestFramework* tf)
192198    return  0 ;
193199}
194200
195- static  void  run_test (const  struct  TestEntry *  t ) {
201+ static  void  run_test_log (const  struct  TestEntry *  t ) {
202+     int64_t  start_time  =  gettime_i64 ();
196203    printf ("Running %s..\n" , t -> name );
197204    t -> func ();
198-     printf ("%s PASSED\n" , t -> name );
205+     printf ("Test  %s PASSED (%.3f sec) \n" , t -> name , ( double )( gettime_i64 ()  -   start_time ) /  1000000 );
199206}
200207
208+ static  void  run_test (const  struct  TestEntry *  t ) { t -> func (); }
209+ 
201210/* Process tests in sequential order */ 
202211static  int  run_sequential (struct  TestFramework *  tf ) {
203212    int  it ;
204213    for  (it  =  0 ; it  <  tf -> args .targets .size ; it ++ ) {
205214        TestRef *  index  =  & tf -> args .targets .slots [it ];
206-         run_test (& tf -> registry_modules [index -> group ].data [index -> idx ]);
215+         tf -> fn_run_test (& tf -> registry_modules [index -> group ].data [index -> idx ]);
207216    }
208217    return  EXIT_SUCCESS ;
209218}
@@ -241,7 +250,7 @@ static int run_concurrent(struct TestFramework* tf) {
241250            TestRef  tref ;
242251            close (pipes [it ][1 ]); /* Close write end */ 
243252            while  (read (pipes [it ][0 ], & tref , sizeof (tref )) ==  sizeof (tref )) {
244-                 run_test (& tf -> registry_modules [tref .group ].data [tref .idx ]);
253+                 tf -> fn_run_test (& tf -> registry_modules [tref .group ].data [tref .idx ]);
245254            }
246255            _exit (EXIT_SUCCESS ); /* finish child process */ 
247256        } else  {
@@ -283,6 +292,7 @@ static int tf_init(struct TestFramework* tf, int argc, char** argv)
283292    tf -> args .num_processes  =  0 ;
284293    tf -> args .custom_seed  =  NULL ;
285294    tf -> args .targets .size  =  0 ;
295+     tf -> args .logging  =  0 ;
286296
287297    /* Disable buffering for stdout to improve reliability of getting 
288298     * diagnostic information. Happens right at the start of main because 
@@ -325,6 +335,7 @@ static int tf_init(struct TestFramework* tf, int argc, char** argv)
325335        }
326336    }
327337
338+     tf -> fn_run_test  =  tf -> args .logging  ? run_test_log  : run_test ;
328339    return  EXIT_SUCCESS ;
329340}
330341
@@ -335,6 +346,12 @@ static int tf_run(struct TestFramework* tf) {
335346    struct  TestEntry *  t ;
336347    /* Initial test time */ 
337348    int64_t  start_time  =  gettime_i64 (); /* maybe move this after the slots set */ 
349+     /* Verify 'tf_init' has been called */ 
350+     if  (!tf -> fn_run_test ) {
351+         fprintf (stderr , "Error: No test runner set. You must call 'tf_init' first to initialize the framework " 
352+                         "or manually assign 'fn_run_test' before calling 'tf_run'.\n" );
353+         return  EXIT_FAILURE ;
354+     }
338355
339356    /* Populate targets with all tests if none were explicitly specified */ 
340357    if  (tf -> args .targets .size  ==  0 ) {
@@ -354,12 +371,14 @@ static int tf_run(struct TestFramework* tf) {
354371        tf -> args .targets .size  =  slot ;
355372    }
356373
374+     if  (!tf -> args .logging ) printf ("Tests running silently. Use '-log=1' to enable detailed logging\n" );
375+ 
357376    /* Run test RNG tests (must run before we really initialize the test RNG) */ 
358377    /* Note: currently, these tests are executed sequentially because there */ 
359378    /* is really only one test. */ 
360379    for  (t  =  tf -> registry_no_ctx ; t -> name ; t ++ ) {
361380        if  (tf -> args .targets .size  ==  0 ) { /* future: support filtering */ 
362-             run_test (t );
381+             tf -> fn_run_test (t );
363382        }
364383    }
365384
0 commit comments