@@ -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