Skip to content

Commit 906b45a

Browse files
committed
test: add -log option to display tests execution
When enabled (-log=1), shows test start, completion, and execution time.
1 parent 0af8519 commit 906b45a

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

src/unit_test.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ static int parse_arg(const char* key, const char* value, struct TestFramework* t
5353
if (strcmp(key, "t") == 0 || strcmp(key, "target") == 0) {
5454
return parse_target(value, tf);
5555
}
56+
/* Logging */
57+
if (strcmp(key, "log") == 0) {
58+
tf->args.logging = value && strcmp(value, "1") == 0;
59+
return 0;
60+
}
5661

5762
/* Unknown key: report just so typos don’t silently pass. */
5863
printf("Unknown argument '-%s=%s'\n", key, value);
@@ -79,6 +84,7 @@ static void help(void) {
7984
printf(" -seed=<hex> Set a specific RNG seed (default: random)\n");
8085
printf(" -target=<test name>, -t=<name> Run a specific test (can be provided multiple times)\n");
8186
printf(" -target=<module name>, -t=<module> Run all tests within a specific module (can be provided multiple times)\n");
87+
printf(" -log=<0|1> Enable or disable test execution logging (default: 0 = disabled)\n");
8288
printf("\n");
8389
printf("Notes:\n");
8490
printf(" - All arguments must be provided in the form '-key=value'.\n");
@@ -181,18 +187,21 @@ static int read_args(int argc, char** argv, int start, struct TestFramework* tf)
181187
return 0;
182188
}
183189

184-
static void run_test(const struct TestEntry* t) {
190+
static void run_test_log(const struct TestEntry* t) {
191+
int64_t start_time = gettime_i64();
185192
printf("Running %s..\n", t->name);
186193
t->func();
187-
printf("%s PASSED\n", t->name);
194+
printf("Test %s PASSED (%.3f sec)\n", t->name, (double)(gettime_i64() - start_time) / 1000000);
188195
}
189196

197+
static void run_test(const struct TestEntry* t) { t->func(); }
198+
190199
/* Process tests in sequential order */
191200
static int run_sequential(struct TestFramework* tf) {
192201
int it;
193202
for (it = 0; it < tf->args.targets.size; it++) {
194203
TestRef* index = &tf->args.targets.slots[it];
195-
run_test(&tf->registry_modules[index->group].data[index->idx]);
204+
tf->fn_run_test(&tf->registry_modules[index->group].data[index->idx]);
196205
}
197206
return EXIT_SUCCESS;
198207
}
@@ -230,7 +239,7 @@ static int run_concurrent(struct TestFramework* tf) {
230239
TestRef tref;
231240
close(pipes[it][1]); /* Close write end */
232241
while (read(pipes[it][0], &tref, sizeof(tref)) == sizeof(tref)) {
233-
run_test(&tf->registry_modules[tref.group].data[tref.idx]);
242+
tf->fn_run_test(&tf->registry_modules[tref.group].data[tref.idx]);
234243
}
235244
_exit(EXIT_SUCCESS); /* finish child process */
236245
} else {
@@ -277,6 +286,7 @@ static int tf_init(struct TestFramework* tf, int argc, char** argv)
277286
tf->args.num_processes = 0;
278287
tf->args.custom_seed = NULL;
279288
tf->args.targets.size = 0;
289+
tf->args.logging = 0;
280290

281291
/* Disable buffering for stdout to improve reliability of getting
282292
* diagnostic information. Happens right at the start of main because
@@ -322,6 +332,7 @@ static int tf_init(struct TestFramework* tf, int argc, char** argv)
322332
}
323333
}
324334

335+
tf->fn_run_test = tf->args.logging ? run_test_log : run_test;
325336
return EXIT_SUCCESS;
326337
}
327338

@@ -334,6 +345,12 @@ static int tf_run(struct TestFramework* tf) {
334345
int it;
335346
/* Initial test time */
336347
int64_t start_time = gettime_i64(); /* maybe move this after the slots set */
348+
/* Verify 'tf_init' has been called */
349+
if (!tf->fn_run_test) {
350+
fprintf(stderr, "Error: No test runner set. You must call 'tf_init' first to initialize the framework "
351+
"or manually assign 'fn_run_test' before calling 'tf_run'.\n");
352+
return EXIT_FAILURE;
353+
}
337354

338355
/* Populate targets with all tests if none were explicitly specified */
339356
run_all = 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 (it = 0; tf->registry_no_rng && it < tf->registry_no_rng->size; it++) {
361380
if (run_all) { /* future: support filtering */
362-
run_test(&tf->registry_no_rng->data[it]);
381+
tf->fn_run_test(&tf->registry_no_rng->data[it]);
363382
}
364383
}
365384

src/unit_test.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ struct TestModule {
6262

6363
typedef int (*setup_ctx_fn)(void);
6464
typedef int (*teardown_fn)(void);
65+
typedef void (*run_test_fn)(const struct TestEntry*);
6566

6667
/* Reference to a test in the registry. Group index and test index */
6768
typedef struct {
@@ -84,6 +85,8 @@ struct Args {
8485
const char* custom_seed;
8586
/* Target tests indexes */
8687
struct Targets targets;
88+
/* Enable test execution logging */
89+
int logging;
8790
};
8891

8992
struct TestFramework {
@@ -98,6 +101,8 @@ struct TestFramework {
98101
/* Specific context setup and teardown functions */
99102
setup_ctx_fn fn_setup;
100103
teardown_fn fn_teardown;
104+
/* Test runner function (can be customized) */
105+
run_test_fn fn_run_test;
101106
};
102107

103108
/* --------------------------------------------------------- */

0 commit comments

Comments
 (0)