test: Add a flag to emit per-test result lines
The ut command shows test output but does not provide a machine-readable indication of whether each individual test passed or failed. External tools must rely on heuristics like scanning for failure patterns in the output. Add a -E flag that emits an explicit result line after each test: Result: PASS: test_name: file.c Result: FAIL: test_name: file.c This allows tools to reliably determine per-test pass/fail status without fragile pattern matching. The flag is optional to maintain backward compatibility with existing scripts. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com>
This commit is contained in:
@@ -11,7 +11,7 @@ Synopsis
|
||||
|
||||
::
|
||||
|
||||
ut [-fmr<runs>] [-R] [-I<n>:<one_test>] [<suite> | all [<test>]] [<args>...]
|
||||
ut [-Efmr<runs>] [-R] [-I<n>:<one_test>] [<suite> | all [<test>]] [<args>...]
|
||||
ut [-s] info
|
||||
|
||||
Description
|
||||
@@ -26,6 +26,11 @@ suite
|
||||
test
|
||||
Speciifes a particular test to run, within a suite, or all suites
|
||||
|
||||
-E
|
||||
Emit a result line after each test, in the format
|
||||
`Result: PASS|FAIL|SKIP: <test_name>: <file>`. This is useful for
|
||||
automated parsing of test results.
|
||||
|
||||
-f, -m
|
||||
Force running of manual tests. Manual tests have the `_norun` suffix and
|
||||
are normally skipped because they require external setup (e.g., creating
|
||||
|
||||
@@ -97,6 +97,7 @@ struct ut_arg {
|
||||
* @arg_count: Number of parsed arguments
|
||||
* @arg_error: Set if ut_str/int/bool() detects a type mismatch
|
||||
* @keep_record: Preserve console recording when ut_fail() is called
|
||||
* @emit_result: Emit result line after each test completes
|
||||
* @priv: Private data for tests to use as needed
|
||||
*/
|
||||
struct unit_test_state {
|
||||
@@ -128,6 +129,7 @@ struct unit_test_state {
|
||||
int arg_count;
|
||||
bool arg_error;
|
||||
bool keep_record;
|
||||
bool emit_result;
|
||||
char priv[UT_PRIV_SIZE];
|
||||
};
|
||||
|
||||
|
||||
@@ -255,6 +255,7 @@ static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||
bool show_suites = false;
|
||||
bool force_run = false;
|
||||
bool keep_record = false;
|
||||
bool emit_result = false;
|
||||
int runs_per_text = 1;
|
||||
struct suite *ste;
|
||||
char *name;
|
||||
@@ -269,6 +270,9 @@ static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||
|
||||
for (str++; *str; str++) {
|
||||
switch (*str) {
|
||||
case 'E':
|
||||
emit_result = true;
|
||||
break;
|
||||
case 'r':
|
||||
runs_per_text = dectoul(str + 1, NULL);
|
||||
goto next_arg;
|
||||
@@ -299,6 +303,7 @@ next_arg:
|
||||
|
||||
ut_init_state(&uts);
|
||||
uts.keep_record = keep_record;
|
||||
uts.emit_result = emit_result;
|
||||
name = argv[0];
|
||||
select_name = cmd_arg1(argc, argv);
|
||||
|
||||
@@ -344,7 +349,8 @@ next_arg:
|
||||
}
|
||||
|
||||
U_BOOT_LONGHELP(ut,
|
||||
"[-fmrs] [-R] [-I<n>:<one_test>] <suite> [<test> [<args>...]] - run unit tests\n"
|
||||
"[-Efmrs] [-R] [-I<n>:<one_test>] <suite> [<test> [<args>...]] - run unit tests\n"
|
||||
" -E Emit result line after each test\n"
|
||||
" -r<runs> Number of times to run each test\n"
|
||||
" -f/-m Force 'manual' tests to run as well\n"
|
||||
" -I Test to run after <n> other tests have run\n"
|
||||
|
||||
@@ -624,6 +624,7 @@ static int ut_run_test(struct unit_test_state *uts, struct unit_test *test,
|
||||
{
|
||||
const char *fname = strrchr(test->file, '/') + 1;
|
||||
const char *note = "";
|
||||
int old_fail_count;
|
||||
int ret;
|
||||
|
||||
if ((test->flags & UTF_DM) && !uts->of_live)
|
||||
@@ -639,6 +640,7 @@ static int ut_run_test(struct unit_test_state *uts, struct unit_test *test,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
old_fail_count = uts->cur.fail_count;
|
||||
uts->arg_error = false;
|
||||
ret = test->func(uts);
|
||||
if (ret == -EAGAIN)
|
||||
@@ -650,6 +652,13 @@ static int ut_run_test(struct unit_test_state *uts, struct unit_test *test,
|
||||
|
||||
ut_set_state(NULL);
|
||||
|
||||
if (uts->emit_result) {
|
||||
bool passed = uts->cur.fail_count == old_fail_count;
|
||||
|
||||
printf("Result: %s: %s: %s%s\n", passed ? "PASS" : "FAIL",
|
||||
test_name, fname, note);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user