Skip to content

Commit 9a0214b

Browse files
committed
test: add --log option to display tests execution
When enabled (--log=1), shows test start, completion, and execution time.
1 parent 0362f17 commit 9a0214b

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

src/unit_test.c

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ static int parse_jobs_count(const char* key, const char* value, struct tf_framew
2626
static int parse_iterations(const char* key, const char* value, struct tf_framework* tf);
2727
static int parse_seed(const char* key, const char* value, struct tf_framework* tf);
2828
static 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 */
3132
typedef 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 */
150159
static 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 */
258270
static 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

src/unit_test.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct tf_test_module {
6161

6262
typedef int (*setup_ctx_fn)(void);
6363
typedef int (*teardown_fn)(void);
64+
typedef void (*run_test_fn)(const struct tf_test_entry*);
6465

6566
/* Reference to a test in the registry. Group index and test index */
6667
typedef struct {
@@ -87,6 +88,8 @@ struct tf_args {
8788
int list_tests;
8889
/* Target tests indexes */
8990
struct Targets targets;
91+
/* Enable test execution logging */
92+
int logging;
9093
};
9194

9295
/* --------------------------------------------------------- */
@@ -105,6 +108,8 @@ struct tf_framework {
105108
/* Specific context setup and teardown functions */
106109
setup_ctx_fn fn_setup;
107110
teardown_fn fn_teardown;
111+
/* Test runner function (can be customized) */
112+
run_test_fn fn_run_test;
108113
};
109114

110115
/*

0 commit comments

Comments
 (0)