@@ -26,6 +26,7 @@ static int parse_jobs_count(const char* key, const char* value, struct tf_framew
2626static  int  parse_iterations (const  char *  key , const  char *  value , struct  tf_framework *  tf );
2727static  int  parse_seed (const  char *  key , const  char *  value , struct  tf_framework *  tf );
2828static  int  parse_target (const  char *  key , const  char *  value , struct  tf_framework *  tf );
29+ static  int  parse_logging (const  char *  key , const  char *  value , struct  tf_framework *  tf );
2930
3031/* Mapping table: key -> handler */ 
3132typedef  int  (* ArgHandler )(const  char *  key , const  char *  value , struct  tf_framework *  tf );
@@ -46,6 +47,7 @@ static struct ArgMap arg_map[] = {
4647    { "j" , parse_jobs_count  }, { "jobs" , parse_jobs_count  },
4748    { "i" , parse_iterations  }, { "iterations" , parse_iterations  },
4849    { "seed" , parse_seed  },
50+     { "log" , parse_logging  },
4951    { NULL , NULL  } /* sentinel */ 
5052};
5153
@@ -87,6 +89,7 @@ static void help(void) {
8789    printf ("    --seed=<hex>                         Set a specific RNG seed (default: random)\n" );
8890    printf ("    --target=<test name>, -t=<name>      Run a specific test (can be provided multiple times)\n" );
8991    printf ("    --target=<module name>, -t=<module>  Run all tests within a specific module (can be provided multiple times)\n" );
92+     printf ("    --log=<0|1>                          Enable or disable test execution logging (default: 0 = disabled)\n" );
9093    printf ("\n" );
9194    printf ("Notes:\n" );
9295    printf ("    - All arguments must be provided in the form '--key=value', '-key=value' or '-k=value'.\n" );
@@ -146,6 +149,12 @@ static int parse_seed(const char* key, const char* value, struct tf_framework* t
146149    return  0 ;
147150}
148151
152+ static  int  parse_logging (const  char *  key , const  char *  value , struct  tf_framework *  tf ) {
153+     UNUSED (key );
154+     tf -> args .logging  =  value  &&  strcmp (value , "1" ) ==  0 ;
155+     return  0 ;
156+ }
157+ 
149158/* Strip up to two leading dashes */ 
150159static  const  char *  normalize_key (const  char *  arg , const  char * *  err_msg ) {
151160    const  char *  key ;
@@ -248,18 +257,21 @@ static int read_args(int argc, char** argv, int start, struct tf_framework* tf)
248257    return  0 ;
249258}
250259
251- static  void  run_test (const  struct  tf_test_entry *  t ) {
260+ static  void  run_test_log (const  struct  tf_test_entry *  t ) {
261+     int64_t  start_time  =  gettime_i64 ();
252262    printf ("Running %s..\n" , t -> name );
253263    t -> func ();
254-     printf ("%s PASSED\n" , t -> name );
264+     printf ("Test  %s PASSED (%.3f sec) \n" , t -> name , ( double )( gettime_i64 ()  -   start_time ) /  1000000 );
255265}
256266
267+ static  void  run_test (const  struct  tf_test_entry *  t ) { t -> func (); }
268+ 
257269/* Process tests in sequential order */ 
258270static  int  run_sequential (struct  tf_framework *  tf ) {
259271    int  it ;
260272    for  (it  =  0 ; it  <  tf -> args .targets .size ; it ++ ) {
261273        const  TestRef *  index  =  & tf -> args .targets .slots [it ];
262-         run_test (& tf -> registry_modules [index -> group ].data [index -> idx ]);
274+         tf -> fn_run_test (& tf -> registry_modules [index -> group ].data [index -> idx ]);
263275    }
264276    return  EXIT_SUCCESS ;
265277}
@@ -297,7 +309,7 @@ static int run_concurrent(struct tf_framework* tf) {
297309            TestRef  tref ;
298310            close (pipes [it ][1 ]); /* Close write end */ 
299311            while  (read (pipes [it ][0 ], & tref , sizeof (tref )) ==  sizeof (tref )) {
300-                 run_test (& tf -> registry_modules [tref .group ].data [tref .idx ]);
312+                 tf -> fn_run_test (& tf -> registry_modules [tref .group ].data [tref .idx ]);
301313            }
302314            _exit (EXIT_SUCCESS ); /* finish child process */ 
303315        } else  {
@@ -346,6 +358,7 @@ static int tf_init(struct tf_framework* tf, int argc, char** argv)
346358    tf -> args .help  =  0 ;
347359    tf -> args .targets .size  =  0 ;
348360    tf -> args .list_tests  =  0 ;
361+     tf -> args .logging  =  0 ;
349362
350363    /* Disable buffering for stdout to improve reliability of getting 
351364     * diagnostic information. Happens right at the start of main because 
@@ -389,6 +402,7 @@ static int tf_init(struct tf_framework* tf, int argc, char** argv)
389402        }
390403    }
391404
405+     tf -> fn_run_test  =  tf -> args .logging  ? run_test_log  : run_test ;
392406    return  EXIT_SUCCESS ;
393407}
394408
@@ -401,6 +415,12 @@ static int tf_run(struct tf_framework* tf) {
401415    int  it ;
402416    /* Initial test time */ 
403417    int64_t  start_time  =  gettime_i64 ();
418+     /* Verify 'tf_init' has been called */ 
419+     if  (!tf -> fn_run_test ) {
420+         fprintf (stderr , "Error: No test runner set. You must call 'tf_init' first to initialize the framework " 
421+                         "or manually assign 'fn_run_test' before calling 'tf_run'.\n" );
422+         return  EXIT_FAILURE ;
423+     }
404424
405425    /* Populate targets with all tests if none were explicitly specified */ 
406426    run_all  =  tf -> args .targets .size  ==  0 ;
@@ -419,6 +439,8 @@ static int tf_run(struct tf_framework* tf) {
419439        }
420440    }
421441
442+     if  (!tf -> args .logging ) printf ("Tests running silently. Use '-log=1' to enable detailed logging\n" );
443+ 
422444    /* Log configuration */ 
423445    print_args (& tf -> args );
424446
@@ -427,7 +449,7 @@ static int tf_run(struct tf_framework* tf) {
427449    /* is really only one test. */ 
428450    for  (it  =  0 ; tf -> registry_no_rng  &&  it  <  tf -> registry_no_rng -> size ; it ++ ) {
429451        if  (run_all ) { /* future: support filtering */ 
430-             run_test (& tf -> registry_no_rng -> data [it ]);
452+             tf -> fn_run_test (& tf -> registry_no_rng -> data [it ]);
431453        }
432454    }
433455
0 commit comments