test: add --output-file to print test logs to a file

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1067>
This commit is contained in:
Peter Hutterer 2024-10-21 12:12:45 +10:00 committed by Marge Bot
parent 1f8a4df58c
commit 4a98e273a4
3 changed files with 57 additions and 33 deletions

View file

@ -87,6 +87,7 @@ struct litest_runner {
unsigned int timeout;
bool verbose;
bool exit_on_fail;
FILE *fp;
int terminating;
@ -664,23 +665,24 @@ litest_runner_log_test_result(struct litest_runner *runner, struct litest_runner
case LITEST_SYSTEM_ERROR: color = ANSI_BRIGHT_MAGENTA; break;
}
fprintf(stderr, " - name: \"%s\"\n", t->desc.name);
fprintf(runner->fp, " - name: \"%s\"\n", t->desc.name);
int min = t->desc.args.range.lower,
max = t->desc.args.range.upper;
if (range_is_valid(&t->desc.args.range))
fprintf(stderr, " rangeval: %d # %d..%d\n", t->desc.rangeval, min, max);
fprintf(runner->fp, " rangeval: %d # %d..%d\n", t->desc.rangeval, min, max);
fprintf(stderr,
fprintf(runner->fp,
" duration: %ld # (ms), total test run time: %02d:%02d\n",
t->times.end_millis - t->times.start_millis,
(ms2s(t->times.end_millis - runner->times.start_millis)) / 60,
(ms2s(t->times.end_millis - runner->times.start_millis)) % 60);
status = litest_runner_result_as_str(t->result);
fprintf(stderr, " status: %s%s%s\n",
isatty(STDERR_FILENO) ? color : "",
bool is_tty = isatty(fileno(runner->fp));
fprintf(runner->fp, " status: %s%s%s\n",
is_tty ? color : "",
&status[7], /* skip LITEST_ prefix */
isatty(STDERR_FILENO) ? ANSI_NORMAL : "");
is_tty ? ANSI_NORMAL : "");
switch (t->result) {
case LITEST_PASS:
@ -694,28 +696,28 @@ litest_runner_log_test_result(struct litest_runner *runner, struct litest_runner
}
if (t->sig_or_errno > 0)
fprintf(stderr, " signal: %d # SIG%s \n",
fprintf(runner->fp, " signal: %d # SIG%s \n",
t->sig_or_errno,
sigabbrev_np(t->sig_or_errno));
else if (t->sig_or_errno < 0)
fprintf(stderr, " errno: %d # %s\n",
fprintf(runner->fp, " errno: %d # %s\n",
-t->sig_or_errno,
strerror(-t->sig_or_errno));
if (!stringbuf_is_empty(&t->logs[FD_LOG])) {
fprintf(stderr, " log: |\n");
print_lines(stderr, t->logs[FD_LOG].data, " ");
fprintf(runner->fp, " log: |\n");
print_lines(runner->fp, t->logs[FD_LOG].data, " ");
}
if (!stringbuf_is_empty(&t->logs[FD_STDOUT])) {
fprintf(stderr, " stdout: |\n");
print_lines(stderr, t->logs[FD_STDOUT].data, " ");
fprintf(runner->fp, " stdout: |\n");
print_lines(runner->fp, t->logs[FD_STDOUT].data, " ");
}
if (!stringbuf_is_empty(&t->logs[FD_STDERR])) {
fprintf(stderr, " stderr: |\n");
print_lines(stderr, t->logs[FD_STDERR].data, " ");
fprintf(runner->fp, " stderr: |\n");
print_lines(runner->fp, t->logs[FD_STDERR].data, " ");
}
if (!stringbuf_is_empty(&t->logs[FD_VALGRIND])) {
fprintf(stderr, " valgrind: |\n");
print_lines(stderr, t->logs[FD_VALGRIND].data, " ");
fprintf(runner->fp, " valgrind: |\n");
print_lines(runner->fp, t->logs[FD_VALGRIND].data, " ");
}
}
@ -729,6 +731,7 @@ litest_runner_new(void)
list_init(&runner->tests_running);
runner->timeout = LITEST_RUNNER_DEFAULT_TIMEOUT;
runner->max_forks = get_nprocs() * 2;
runner->fp = stderr;
return runner;
}
@ -740,6 +743,14 @@ litest_runner_set_timeout(struct litest_runner *runner,
runner->timeout = timeout;
}
void
litest_runner_set_output_file(struct litest_runner *runner,
FILE *fp)
{
setlinebuf(fp);
runner->fp = fp;
}
void
litest_runner_set_num_parallel(struct litest_runner *runner,
size_t num_jobs)
@ -875,9 +886,9 @@ litest_runner_run_tests(struct litest_runner *runner)
runner->times.start = time(NULL);
ltime = localtime(&runner->times.start);
strftime(timestamp, sizeof(timestamp), "%FT%H:%M", ltime);
fprintf(stderr, "start: %ld # \"%s\"\n", runner->times.start, timestamp);
fprintf(stderr, "jobs: %zd\n", runner->max_forks);
fprintf(stderr, "tests:\n");
fprintf(runner->fp, "start: %ld # \"%s\"\n", runner->times.start, timestamp);
fprintf(runner->fp, "jobs: %zd\n", runner->max_forks);
fprintf(runner->fp, "tests:\n");
list_for_each_safe(t, &runner->tests, node) {
int r = litest_runner_run_test(runner, t);
if (r >= 0) {
@ -949,26 +960,26 @@ litest_runner_run_tests(struct litest_runner *runner)
runner->times.end = time(NULL);
ltime = localtime(&runner->times.end);
strftime(timestamp, sizeof(timestamp), "%FT%H:%M", ltime);
fprintf(stderr, "end: %ld # \"%s\"\n", runner->times.end, timestamp);
fprintf(stderr,
fprintf(runner->fp, "end: %ld # \"%s\"\n", runner->times.end, timestamp);
fprintf(runner->fp,
"duration: %ld # (s) %02ld:%02ld\n",
runner->times.end - runner->times.start,
(runner->times.end - runner->times.start) / 60,
(runner->times.end - runner->times.start) % 60);
fprintf(stderr, "summary:\n");
fprintf(stderr, " completed: %zd\n", ncomplete);
fprintf(stderr, " pass: %zd\n", npass);
fprintf(stderr, " na: %zd\n", nna);
fprintf(stderr, " fail: %zd\n", nfail);
fprintf(stderr, " skip: %zd\n", nskip);
fprintf(runner->fp, "summary:\n");
fprintf(runner->fp, " completed: %zd\n", ncomplete);
fprintf(runner->fp, " pass: %zd\n", npass);
fprintf(runner->fp, " na: %zd\n", nna);
fprintf(runner->fp, " fail: %zd\n", nfail);
fprintf(runner->fp, " skip: %zd\n", nskip);
if (nfail > 0) {
fprintf(stderr, " failed:\n");
fprintf(runner->fp, " failed:\n");
list_for_each(t, &runner->tests_complete, node) {
switch (t->result) {
case LITEST_FAIL:
case LITEST_SYSTEM_ERROR:
case LITEST_TIMEOUT:
fprintf(stderr, " - \"%s\"\n", t->desc.name);
fprintf(runner->fp, " - \"%s\"\n", t->desc.name);
break;
default:
break;
@ -981,9 +992,9 @@ litest_runner_run_tests(struct litest_runner *runner)
struct stringbuf *b = stringbuf_new();
collect_file(filename, b);
fprintf(stderr, "valgrind:\n");
print_lines(stderr, b->data, " ");
fprintf(stderr, "# Valgrind log is incomplete, see %s for full log\n", filename);
fprintf(runner->fp, "valgrind:\n");
print_lines(runner->fp, b->data, " ");
fprintf(runner->fp, "# Valgrind log is incomplete, see %s for full log\n", filename);
free(filename);
stringbuf_destroy(b);
}
@ -1006,7 +1017,7 @@ litest_runner_run_tests(struct litest_runner *runner)
}
}
/* Status is always prefixed with LITEST_ */
fprintf(stderr, " status: %s\n", &litest_runner_result_as_str(result)[7]);
fprintf(runner->fp, " status: %s\n", &litest_runner_result_as_str(result)[7]);
return result;
}

View file

@ -78,6 +78,7 @@ void litest_runner_set_num_parallel(struct litest_runner *runner, size_t num_job
void litest_runner_set_timeout(struct litest_runner *runner, unsigned int timeout);
void litest_runner_set_verbose(struct litest_runner *runner, bool verbose);
void litest_runner_set_exit_on_fail(struct litest_runner *runner, bool do_exit);
void litest_runner_set_output_file(struct litest_runner *runner, FILE *fp);
void litest_runner_add_test(struct litest_runner *runner,
const struct litest_runner_test_description *t);
enum litest_runner_result litest_runner_run_tests(struct litest_runner *runner);

View file

@ -83,6 +83,7 @@ static bool verbose = false;
static bool run_deviceless = false;
static bool use_system_rules_quirks = false;
static bool exit_first = false;
static FILE * outfile = NULL;
static const char *filter_test = NULL;
static const char *filter_device = NULL;
static const char *filter_group = NULL;
@ -943,6 +944,8 @@ litest_run_suite(struct list *suites, int njobs)
struct litest_runner *runner = litest_runner_new();
litest_runner_set_num_parallel(runner, jobs > 0 ? jobs : 0);
if (outfile)
litest_runner_set_output_file(runner, outfile);
litest_runner_set_verbose(runner, verbose);
litest_runner_set_timeout(runner, 30);
litest_runner_set_exit_on_fail(runner, exit_first);
@ -4520,6 +4523,7 @@ litest_parse_argv(int argc, char **argv)
OPT_FILTER_GROUP,
OPT_FILTER_RANGEVAL,
OPT_FILTER_DEVICELESS,
OPT_OUTPUT_FILE,
OPT_JOBS,
OPT_LIST,
OPT_VERBOSE,
@ -4530,6 +4534,7 @@ litest_parse_argv(int argc, char **argv)
{ "filter-group", 1, 0, OPT_FILTER_GROUP },
{ "filter-rangeval", 1, 0, OPT_FILTER_RANGEVAL },
{ "filter-deviceless", 0, 0, OPT_FILTER_DEVICELESS },
{ "output-file", 1, 0, OPT_OUTPUT_FILE },
{ "exitfirst", 0, 0, OPT_EXIT_FIRST },
{ "jobs", 1, 0, OPT_JOBS },
{ "list", 0, 0, OPT_LIST },
@ -4628,6 +4633,13 @@ litest_parse_argv(int argc, char **argv)
case OPT_FILTER_DEVICELESS:
run_deviceless = true;
break;
case OPT_OUTPUT_FILE:
outfile = fopen(optarg, "w+");
if (!outfile) {
fprintf(stderr, "Failed to open %s: %m\n", optarg);
exit(1);
}
break;
case 'x':
case OPT_EXIT_FIRST:
exit_first = true;