projects/linux·blob master · refs

1815 lines · 43.8 KiB

1// SPDX-License-Identifier: GPL-2.0
2/*
3 * builtin-test.c
4 *
5 * Builtin regression testing command: ever growing number of sanity tests
6 */
7#include <ctype.h>
8#include <fcntl.h>
9#include <errno.h>
10#ifdef HAVE_BACKTRACE_SUPPORT
11#include <execinfo.h>
12#endif
13#include <setjmp.h>
14#include <stdlib.h>
15#include <string.h>
16
17#include <dirent.h>
18#include <linux/kernel.h>
19#include <linux/string.h>
20#include <linux/zalloc.h>
21#include <poll.h>
22#include <sys/ioctl.h>
23#include <sys/stat.h>
24#include <sys/time.h>
25#include <sys/types.h>
26#include <sys/wait.h>
27#include <unistd.h>
28
29#include <subcmd/exec-cmd.h>
30#include <subcmd/parse-options.h>
31#include <subcmd/run-command.h>
32
33#include "builtin.h"
34#include "color.h"
35#include "config.h"
36#include "debug.h"
37#include "hist.h"
38#include "intlist.h"
39#include "string2.h"
40#include "symbol.h"
41#include "tests-scripts.h"
42#include "tests.h"
43#include "util/rlimit.h"
44#include "util/strbuf.h"
45#include "util/term.h"
46
47static const char *junit_filename;
48static struct strbuf junit_xml_buf = STRBUF_INIT;
49
50/*
51 * Command line option to not fork the test running in the same process and
52 * making them easier to debug.
53 */
54static bool dont_fork;
55/* Fork the tests in parallel and wait for their completion. */
56static bool sequential;
57/* Number of times each test is run. */
58static unsigned int runs_per_test = 1;
59/* Number of lines to include in failure snippet. */
60static unsigned int failure_snippet_lines = 10;
61const char *dso_to_test;
62const char *test_objdump_path = "objdump";
63static const char *workload_control;
64
65/*
66 * List of architecture specific tests. Not a weak symbol as the array length is
67 * dependent on the initialization, as such GCC with LTO complains of
68 * conflicting definitions with a weak symbol.
69 */
70#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__)
71extern struct test_suite *arch_tests[];
72#else
73static struct test_suite *arch_tests[] = {
74 NULL,
75};
76#endif
77
78static struct test_suite *generic_tests[] = {
79 &suite__vmlinux_matches_kallsyms,
80 &suite__openat_syscall_event,
81 &suite__openat_syscall_event_on_all_cpus,
82 &suite__basic_mmap,
83 &suite__mem,
84 &suite__parse_events,
85 &suite__uncore_event_sorting,
86 &suite__expr,
87 &suite__PERF_RECORD,
88 &suite__pmu,
89 &suite__pmu_events,
90 &suite__hwmon_pmu,
91 &suite__tool_pmu,
92 &suite__dso_data,
93 &suite__perf_evsel__roundtrip_name_test,
94#ifdef HAVE_LIBTRACEEVENT
95 &suite__perf_evsel__tp_sched_test,
96 &suite__syscall_openat_tp_fields,
97#endif
98 &suite__hists_link,
99 &suite__bp_signal,
100 &suite__bp_signal_overflow,
101 &suite__bp_accounting,
102 &suite__wp,
103 &suite__task_exit,
104 &suite__sw_clock_freq,
105 &suite__code_reading,
106 &suite__sample_parsing,
107 &suite__keep_tracking,
108 &suite__parse_no_sample_id_all,
109 &suite__hists_filter,
110 &suite__mmap_thread_lookup,
111 &suite__thread_maps_share,
112 &suite__hists_output,
113 &suite__hists_cumulate,
114#ifdef HAVE_LIBTRACEEVENT
115 &suite__switch_tracking,
116#endif
117 &suite__fdarray__filter,
118 &suite__fdarray__add,
119 &suite__kmod_path__parse,
120 &suite__thread_map,
121 &suite__session_topology,
122 &suite__thread_map_synthesize,
123 &suite__thread_map_remove,
124 &suite__cpu_map,
125 &suite__synthesize_stat_config,
126 &suite__synthesize_stat,
127 &suite__synthesize_stat_round,
128 &suite__event_update,
129 &suite__event_times,
130 &suite__backward_ring_buffer,
131 &suite__sdt_event,
132 &suite__is_printable_array,
133 &suite__bitmap_print,
134 &suite__perf_hooks,
135 &suite__unit_number__scnprint,
136 &suite__mem2node,
137 &suite__time_utils,
138 &suite__jit_write_elf,
139 &suite__pfm,
140 &suite__api_io,
141 &suite__maps,
142 &suite__demangle_java,
143 &suite__demangle_ocaml,
144 &suite__demangle_rust,
145 &suite__parse_metric,
146 &suite__pe_file_parsing,
147 &suite__expand_cgroup_events,
148 &suite__perf_time_to_tsc,
149 &suite__dlfilter,
150 &suite__sigtrap,
151 &suite__event_groups,
152 &suite__symbols,
153 &suite__util,
154 &suite__subcmd_help,
155 &suite__kallsyms_split,
156 NULL,
157};
158
159static struct test_workload *workloads[] = {
160 &workload__noploop,
161 &workload__thloop,
162 &workload__named_threads,
163 &workload__leafloop,
164 &workload__sqrtloop,
165 &workload__brstack,
166 &workload__datasym,
167 &workload__landlock,
168 &workload__traploop,
169 &workload__inlineloop,
170 &workload__jitdump,
171 &workload__context_switch_loop,
172 &workload__deterministic,
173 &workload__callchain,
174
175#ifdef HAVE_RUST_SUPPORT
176 &workload__code_with_type,
177#endif
178};
179
180struct workload_control {
181 int ctl_fd;
182 int ack_fd;
183};
184
185#define workloads__for_each(workload) \
186 for (unsigned i = 0; i < ARRAY_SIZE(workloads) && ({ workload = workloads[i]; 1; }); i++)
187
188#define test_suite__for_each_test_case(suite, idx) \
189 for (idx = 0; (suite)->test_cases && (suite)->test_cases[idx].name != NULL; idx++)
190
191static void close_parent_fds(void)
192{
193 DIR *dir = opendir("/proc/self/fd");
194 struct dirent *ent;
195
196 while ((ent = readdir(dir))) {
197 char *end;
198 long fd;
199
200 if (ent->d_type != DT_LNK)
201 continue;
202
203 if (!isdigit(ent->d_name[0]))
204 continue;
205
206 fd = strtol(ent->d_name, &end, 10);
207 if (*end)
208 continue;
209
210 if (fd <= 3 || fd == dirfd(dir))
211 continue;
212
213 close(fd);
214 }
215 closedir(dir);
216}
217
218static void check_leaks(void)
219{
220 DIR *dir = opendir("/proc/self/fd");
221 struct dirent *ent;
222 int leaks = 0;
223
224 while ((ent = readdir(dir))) {
225 char path[PATH_MAX];
226 char *end;
227 long fd;
228 ssize_t len;
229
230 if (ent->d_type != DT_LNK)
231 continue;
232
233 if (!isdigit(ent->d_name[0]))
234 continue;
235
236 fd = strtol(ent->d_name, &end, 10);
237 if (*end)
238 continue;
239
240 if (fd <= 3 || fd == dirfd(dir))
241 continue;
242
243 leaks++;
244 len = readlinkat(dirfd(dir), ent->d_name, path, sizeof(path));
245 if (len > 0 && (size_t)len < sizeof(path))
246 path[len] = '\0';
247 else
248 strncpy(path, ent->d_name, sizeof(path));
249 pr_err("Leak of file descriptor %s that opened: '%s'\n", ent->d_name, path);
250 }
251 closedir(dir);
252 if (leaks)
253 abort();
254}
255
256static int test_suite__num_test_cases(const struct test_suite *t)
257{
258 int num;
259
260 test_suite__for_each_test_case(t, num);
261
262 return num;
263}
264
265static const char *skip_reason(const struct test_suite *t, int test_case)
266{
267 if (!t->test_cases)
268 return NULL;
269
270 return t->test_cases[test_case >= 0 ? test_case : 0].skip_reason;
271}
272
273static const char *test_description(const struct test_suite *t, int test_case)
274{
275 if (t->test_cases && test_case >= 0)
276 return t->test_cases[test_case].desc;
277
278 return t->desc;
279}
280
281static test_fnptr test_function(const struct test_suite *t, int test_case)
282{
283 if (test_case <= 0)
284 return t->test_cases[0].run_case;
285
286 return t->test_cases[test_case].run_case;
287}
288
289static bool test_exclusive(const struct test_suite *t, int test_case)
290{
291 if (test_case <= 0)
292 return t->test_cases[0].exclusive;
293
294 return t->test_cases[test_case].exclusive;
295}
296
297static bool perf_test__matches(const char *desc, int suite_num, int argc, const char *argv[])
298{
299 int i;
300
301 if (argc == 0)
302 return true;
303
304 for (i = 0; i < argc; ++i) {
305 char *end;
306 long nr = strtoul(argv[i], &end, 10);
307
308 if (*end == '\0') {
309 if (nr == suite_num + 1)
310 return true;
311 continue;
312 }
313
314 if (strcasestr(desc, argv[i]))
315 return true;
316 }
317
318 return false;
319}
320
321struct child_test {
322 struct child_process process;
323 struct test_suite *test;
324 int suite_num;
325 int test_case_num;
326 struct strbuf err_output;
327 int result;
328 bool done;
329 struct timespec start_time;
330 struct timespec end_time;
331};
332
333static jmp_buf run_test_jmp_buf;
334
335static void child_test_sig_handler(int sig)
336{
337#ifdef HAVE_BACKTRACE_SUPPORT
338 void *stackdump[32];
339 size_t stackdump_size;
340#endif
341
342 fprintf(stderr, "\n---- unexpected signal (%d) ----\n", sig);
343#ifdef HAVE_BACKTRACE_SUPPORT
344 stackdump_size = backtrace(stackdump, ARRAY_SIZE(stackdump));
345 __dump_stack(stderr, stackdump, stackdump_size);
346#endif
347 siglongjmp(run_test_jmp_buf, sig);
348}
349
350static int run_test_child(struct child_process *process)
351{
352 const int signals[] = {
353 SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGINT, SIGPIPE, SIGQUIT, SIGSEGV, SIGTERM,
354 };
355 struct child_test *child = container_of(process, struct child_test, process);
356 int err;
357
358 close_parent_fds();
359
360 err = sigsetjmp(run_test_jmp_buf, 1);
361 if (err) {
362 /* Received signal. */
363 err = err > 0 ? -err : -1;
364 goto err_out;
365 }
366
367 for (size_t i = 0; i < ARRAY_SIZE(signals); i++)
368 signal(signals[i], child_test_sig_handler);
369
370 pr_debug("---- start ----\n");
371 pr_debug("test child forked, pid %d\n", getpid());
372 err = test_function(child->test, child->test_case_num)(child->test, child->test_case_num);
373 pr_debug("---- end(%d) ----\n", err);
374
375 check_leaks();
376err_out:
377 fflush(NULL);
378 for (size_t i = 0; i < ARRAY_SIZE(signals); i++)
379 signal(signals[i], SIG_DFL);
380 return -err;
381}
382
383#define TEST_RUNNING -3
384
385static struct pollfd *global_pfds;
386static size_t *global_pfd_indices;
387static unsigned int summary_tests_passed;
388static unsigned int summary_subtests_passed;
389static unsigned int summary_tests_skipped;
390static unsigned int summary_tests_failed;
391static struct strbuf summary_failed_tests_buf = STRBUF_INIT;
392
393static int strbuf_addstr_safe(struct strbuf *sb, const char *s);
394static int __printf(2, 3) strbuf_addf_safe(struct strbuf *sb, const char *fmt, ...);
395
396static char *xml_escape(const char *str)
397{
398 struct strbuf buf = STRBUF_INIT;
399 const char *p;
400 char *res;
401
402 if (!str)
403 return strdup("");
404
405 for (p = str; *p; p++) {
406 if (*p == '&')
407 strbuf_addstr(&buf, "&amp;");
408 else if (*p == '<')
409 strbuf_addstr(&buf, "&lt;");
410 else if (*p == '>')
411 strbuf_addstr(&buf, "&gt;");
412 else if (*p == '"')
413 strbuf_addstr(&buf, "&quot;");
414 else if ((unsigned char)*p >= 32 || *p == '\n' || *p == '\t')
415 strbuf_addch(&buf, *p);
416 }
417 res = strbuf_detach(&buf, NULL);
418 return res ? res : strdup("");
419}
420
421static int get_term_width(void)
422{
423 struct winsize ws;
424 int cols = 80;
425 int term_width;
426
427 /*
428 * If output is redirected to a file or piped, we don't need to wrap
429 * or truncate at all. Use a massive virtually infinite terminal width
430 * so descriptions are printed in full.
431 */
432 if (!isatty(fileno(debug_file())))
433 return 10000;
434
435 get_term_dimensions(&ws);
436 if (ws.ws_col > 0)
437 cols = ws.ws_col;
438
439 /*
440 * Limit description width to fit on a single line. We subtract 35
441 * columns of headroom to allocate space for:
442 * - The suite index prefix: e.g. " 10.100:" (8 characters) plus 1 space separator.
443 * - The trailing colon (1 character) and space before status (1 character).
444 * - The longest status results: e.g. "Skip (some metrics failed)" (26 characters)
445 * or "Running (XX active)" (20 characters).
446 *
447 * A minimum description width of 10 is enforced to ensure names are
448 * legible even on very narrow consoles.
449 */
450 term_width = cols - 35;
451 if (term_width < 10)
452 term_width = 10;
453
454 return term_width;
455}
456
457static int get_max_desc_width(int width)
458{
459 int term_width = get_term_width();
460
461 return width > term_width ? term_width : width;
462}
463
464static int print_test_result(struct test_suite *t, int curr_suite, int curr_test_case,
465 int result, int width, int running,
466 const char *err_output, double elapsed)
467{
468 int pad_width = get_max_desc_width(width);
469 int term_width = get_term_width();
470
471 if (test_suite__num_test_cases(t) > 1) {
472 char prefix[32];
473 int len = snprintf(prefix, sizeof(prefix), "%3d.%1d:",
474 curr_suite + 1, curr_test_case + 1);
475 int pad = len >= 4 ? pad_width + 4 - len : pad_width;
476 int trunc = len >= 4 ? term_width + 4 - len : term_width;
477
478 pr_info("%s %-*.*s:", prefix, pad, trunc,
479 test_description(t, curr_test_case));
480 } else {
481 pr_info("%3d: %-*.*s:", curr_suite + 1, pad_width, term_width,
482 test_description(t, curr_test_case));
483 }
484
485 switch (result) {
486 case TEST_RUNNING:
487 color_fprintf(debug_file(), PERF_COLOR_YELLOW, " Running (%d active)\n", running);
488 break;
489 case TEST_OK:
490 if (test_suite__num_test_cases(t) > 1)
491 summary_subtests_passed++;
492 else
493 summary_tests_passed++;
494 pr_info(" Ok\n");
495 break;
496 case TEST_SKIP: {
497 const char *reason = skip_reason(t, curr_test_case);
498
499 summary_tests_skipped++;
500 if (reason)
501 color_fprintf(debug_file(), PERF_COLOR_YELLOW, " Skip (%s)\n", reason);
502 else
503 color_fprintf(debug_file(), PERF_COLOR_YELLOW, " Skip\n");
504 }
505 break;
506 case TEST_FAIL:
507 default:
508 summary_tests_failed++;
509 if (test_suite__num_test_cases(t) > 1)
510 strbuf_addf_safe(&summary_failed_tests_buf, " %3d.%1d: %s\n",
511 curr_suite + 1, curr_test_case + 1,
512 test_description(t, curr_test_case));
513 else
514 strbuf_addf_safe(&summary_failed_tests_buf, " %3d: %s\n",
515 curr_suite + 1,
516 test_description(t, curr_test_case));
517 color_fprintf(debug_file(), PERF_COLOR_RED, " FAILED!\n");
518 break;
519 }
520
521 if (junit_filename && result != TEST_RUNNING) {
522 const char *classname = t->desc;
523 const char *testname = test_description(t, curr_test_case);
524 char *escaped_err = xml_escape(err_output);
525 char *escaped_class = xml_escape(classname);
526 char *escaped_test = xml_escape(testname);
527
528 strbuf_addf(&junit_xml_buf,
529 " <testcase classname=\"%s\" name=\"%s\" time=\"%.2f\">\n",
530 escaped_class, escaped_test, elapsed);
531 if (result != TEST_OK && result != TEST_SKIP) {
532 strbuf_addf(&junit_xml_buf,
533 " <failure message=\"FAILED\">\n%s\n </failure>\n",
534 escaped_err);
535 } else if (result == TEST_SKIP) {
536 const char *reason = skip_reason(t, curr_test_case);
537 char *escaped_reason = xml_escape(reason ? reason : "Skip");
538
539 if (err_output && *err_output) {
540 strbuf_addf(&junit_xml_buf,
541 " <skipped message=\"%s\">\n%s\n </skipped>\n",
542 escaped_reason, escaped_err);
543 } else {
544 strbuf_addf(&junit_xml_buf, " <skipped message=\"%s\"/>\n",
545 escaped_reason);
546 }
547 free(escaped_reason);
548 }
549 strbuf_addstr(&junit_xml_buf, " </testcase>\n");
550 free(escaped_err);
551 free(escaped_class);
552 free(escaped_test);
553 }
554
555 return 0;
556}
557
558static const char * const fail_keywords[] = {
559 "error", "fail", "segv", "abort",
560 "signal", "fatal", "panic", "corrupt", NULL
561};
562
563static const char *find_next_keyword(const char *str, size_t max_len, size_t *kw_len)
564{
565 const char *best = NULL;
566 size_t best_len = 0;
567 int k;
568
569 for (k = 0; fail_keywords[k]; k++) {
570 const char *s = str;
571 size_t len = strlen(fail_keywords[k]);
572
573 while ((size_t)(s - str) + len <= max_len) {
574 size_t i;
575
576 if (best && s >= best)
577 break;
578
579 for (i = 0; i < len; i++) {
580 if (tolower(s[i]) != fail_keywords[k][i])
581 break;
582 }
583 if (i == len) {
584 if (!best || s < best) {
585 best = s;
586 best_len = len;
587 }
588 break;
589 }
590 s++;
591 }
592 }
593 if (best) {
594 *kw_len = best_len;
595 return best;
596 }
597 return NULL;
598}
599
600static void print_line_highlighted(FILE *fp, const char *line, size_t len)
601{
602 const char *s = line;
603
604 while (len > 0) {
605 size_t kw_len = 0;
606 const char *match = find_next_keyword(s, len, &kw_len);
607
608 if (!match) {
609 fwrite(s, 1, len, fp);
610 break;
611 }
612 if (match > s)
613 fwrite(s, 1, match - s, fp);
614 if (perf_use_color_default)
615 fprintf(fp, "%s", PERF_COLOR_RED);
616 fwrite(match, 1, kw_len, fp);
617 if (perf_use_color_default)
618 fprintf(fp, "%s", PERF_COLOR_RESET);
619
620 len -= (match + kw_len) - s;
621 s = match + kw_len;
622 }
623}
624
625
626static void print_test_failure_snippet(FILE *fp, const char *buf)
627{
628 size_t num_lines = 0;
629 size_t max_lines = 128;
630 const char **lines = calloc(max_lines, sizeof(const char *));
631 size_t *line_lens = calloc(max_lines, sizeof(size_t));
632 const char *s = buf;
633 size_t i;
634 unsigned int picked_count = 0;
635 bool *pick;
636 int last_printed = -1;
637
638 if (!lines || !line_lens) {
639 free(lines); free(line_lens);
640 fprintf(fp, "%s", buf);
641 return;
642 }
643
644 while (*s) {
645 const char *eol = strchr(s, '\n');
646 size_t len;
647
648 if (eol)
649 len = eol - s + 1;
650 else
651 len = strlen(s);
652
653 if (num_lines == max_lines) {
654 const char **new_lines;
655 size_t *new_lens;
656
657 max_lines *= 2;
658 new_lines = realloc(lines, max_lines * sizeof(const char *));
659 if (!new_lines) {
660 free(lines); free(line_lens);
661 fprintf(fp, "%s", buf);
662 return;
663 }
664 lines = new_lines;
665
666 new_lens = realloc(line_lens, max_lines * sizeof(size_t));
667 if (!new_lens) {
668 free(lines); free(line_lens);
669 fprintf(fp, "%s", buf);
670 return;
671 }
672 line_lens = new_lens;
673 }
674 lines[num_lines] = s;
675 line_lens[num_lines] = len;
676 num_lines++;
677 s += len;
678 }
679
680 if (num_lines <= failure_snippet_lines) {
681 for (i = 0; i < num_lines; i++)
682 print_line_highlighted(fp, lines[i], line_lens[i]);
683 free(lines); free(line_lens);
684 return;
685 }
686
687 pick = calloc(num_lines, sizeof(bool));
688 if (!pick) {
689 for (i = 0; i < num_lines; i++)
690 print_line_highlighted(fp, lines[i], line_lens[i]);
691 free(lines); free(line_lens);
692 return;
693 }
694
695 /* Pass 0: Always pick the very first line */
696 if (num_lines > 0 && picked_count < failure_snippet_lines) {
697 pick[0] = true;
698 picked_count++;
699 }
700
701 /* Pass 1: Pick lines with failure keywords from start (Highest Priority) */
702 for (i = 0; i < num_lines && picked_count < failure_snippet_lines; i++) {
703 size_t dummy;
704
705 if (find_next_keyword(lines[i], line_lens[i], &dummy)) {
706 if (!pick[i]) {
707 pick[i] = true;
708 picked_count++;
709 }
710 /* Prioritize getting the immediate next line for context */
711 if (i + 1 < num_lines && !pick[i + 1] &&
712 picked_count < failure_snippet_lines) {
713 pick[i + 1] = true;
714 picked_count++;
715 }
716 }
717 }
718
719 /* Pass 2: Fill remaining quota from the end backwards */
720 i = num_lines;
721 while (i > 0 && picked_count < failure_snippet_lines) {
722 i--;
723 if (!pick[i]) {
724 pick[i] = true;
725 picked_count++;
726 }
727 }
728
729 for (i = 0; i < num_lines; i++) {
730 if (!pick[i])
731 continue;
732 if (last_printed != -1 && (int)i > last_printed + 1) {
733 if (perf_use_color_default)
734 fprintf(fp, "%s...%s\n", PERF_COLOR_BLUE, PERF_COLOR_RESET);
735 else
736 fprintf(fp, "...\n");
737 }
738 print_line_highlighted(fp, lines[i], line_lens[i]);
739 last_printed = i;
740 }
741
742 free(pick);
743 free(lines);
744 free(line_lens);
745}
746
747static void finish_test(struct child_test **child_tests, int running_test, int child_test_num,
748 int width)
749{
750 struct child_test *child_test = child_tests[running_test];
751 struct test_suite *t;
752 int curr_suite, curr_test_case, err;
753 bool err_done = false;
754 struct strbuf err_output = STRBUF_INIT;
755 int last_running = -1;
756 int ret;
757 struct timespec end_time;
758 double elapsed;
759 width = get_max_desc_width(width);
760
761 if (child_test == NULL) {
762 /* Test wasn't started. */
763 return;
764 }
765 t = child_test->test;
766 curr_suite = child_test->suite_num;
767 curr_test_case = child_test->test_case_num;
768 err = child_test->process.err;
769 /*
770 * For test suites with subtests, display the suite name ahead of the
771 * sub test names.
772 */
773 if (test_suite__num_test_cases(t) > 1 && curr_test_case == 0)
774 pr_info("%3d: %-*.*s:\n", curr_suite + 1, width, width,
775 test_description(t, -1));
776
777 /*
778 * Busy loop reading from the child's stdout/stderr that are set to be
779 * non-blocking until EOF.
780 */
781 if (err >= 0)
782 fcntl(err, F_SETFL, O_NONBLOCK);
783 if (verbose > 1) {
784 if (test_suite__num_test_cases(t) > 1)
785 pr_info("%3d.%1d: %s:\n", curr_suite + 1, curr_test_case + 1,
786 test_description(t, curr_test_case));
787 else
788 pr_info("%3d: %s:\n", curr_suite + 1, test_description(t, -1));
789 }
790 while (!err_done) {
791 struct pollfd pfds[1] = {
792 { .fd = err,
793 .events = POLLIN | POLLERR | POLLHUP | POLLNVAL,
794 },
795 };
796 if (perf_use_color_default) {
797 int running = 0;
798
799 for (int y = running_test; y < child_test_num; y++) {
800 if (child_tests[y] == NULL)
801 continue;
802 if (check_if_command_finished(&child_tests[y]->process) == 0)
803 running++;
804 }
805 if (running != last_running) {
806 if (last_running != -1) {
807 /*
808 * Erase "Running (.. active)" line
809 * printed before poll/sleep.
810 */
811 fprintf(debug_file(), PERF_COLOR_DELETE_LINE);
812 }
813 print_test_result(t, curr_suite, curr_test_case, TEST_RUNNING,
814 width, running, NULL, 0.0);
815 last_running = running;
816 }
817 }
818
819 err_done = true;
820 if (err <= 0) {
821 /* No child stderr to poll, sleep for 10ms for child to complete. */
822 usleep(10 * 1000);
823 } else {
824 /* Poll to avoid excessive spinning, timeout set for 100ms. */
825 poll(pfds, ARRAY_SIZE(pfds), /*timeout=*/100);
826 if (pfds[0].revents) {
827 char buf[512];
828 ssize_t len;
829
830 len = read(err, buf, sizeof(buf) - 1);
831
832 if (len > 0) {
833 err_done = false;
834 buf[len] = '\0';
835 strbuf_addstr_safe(&err_output, buf);
836 }
837 }
838 }
839 if (err_done)
840 err_done = check_if_command_finished(&child_test->process);
841 }
842 /* Drain any remaining data from the pipe. */
843 if (err >= 0) {
844 char buf[512];
845 ssize_t len;
846
847 while ((len = read(err, buf, sizeof(buf) - 1)) > 0) {
848 buf[len] = '\0';
849 strbuf_addstr_safe(&err_output, buf);
850 }
851 }
852 if (perf_use_color_default && last_running != -1) {
853 /* Erase "Running (.. active)" line printed before poll/sleep. */
854 fprintf(debug_file(), PERF_COLOR_DELETE_LINE);
855 }
856 /* Clean up child process. */
857 ret = finish_command(&child_test->process);
858 child_test->process.pid = 0;
859 if (child_test->err_output.len > 0) {
860 struct strbuf merged = STRBUF_INIT;
861
862 if (child_test->err_output.buf)
863 strbuf_addstr_safe(&merged, child_test->err_output.buf);
864 if (err_output.buf)
865 strbuf_addstr_safe(&merged, err_output.buf);
866 strbuf_release(&err_output);
867 err_output = merged;
868 }
869 if (verbose > 1)
870 fprintf(stderr, "%s", err_output.buf);
871 else if (verbose == 1 && ret == TEST_FAIL)
872 print_test_failure_snippet(stderr, err_output.buf);
873
874 clock_gettime(CLOCK_MONOTONIC, &end_time);
875 elapsed = (end_time.tv_sec - child_test->start_time.tv_sec) +
876 (end_time.tv_nsec - child_test->start_time.tv_nsec) / 1000000000.0;
877
878 print_test_result(t, curr_suite, curr_test_case, ret, width, /*running=*/0,
879 err_output.buf, elapsed);
880 strbuf_release(&err_output);
881 strbuf_release(&child_test->err_output);
882 if (err > 0)
883 close(err);
884 zfree(&child_tests[running_test]);
885}
886
887static int strbuf_addstr_safe(struct strbuf *sb, const char *s)
888{
889 sigset_t set, oldset;
890 int ret;
891
892 sigemptyset(&set);
893 sigaddset(&set, SIGINT);
894 sigaddset(&set, SIGTERM);
895 pthread_sigmask(SIG_BLOCK, &set, &oldset);
896 ret = strbuf_addstr(sb, s);
897 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
898 return ret;
899}
900
901static int __printf(2, 3) strbuf_addf_safe(struct strbuf *sb, const char *fmt, ...)
902{
903 char buf[1024];
904 va_list ap;
905 int len;
906 sigset_t set, oldset;
907 int ret;
908
909 sigemptyset(&set);
910 sigaddset(&set, SIGINT);
911 sigaddset(&set, SIGTERM);
912 sigprocmask(SIG_BLOCK, &set, &oldset);
913
914 va_start(ap, fmt);
915 len = vsnprintf(buf, sizeof(buf), fmt, ap);
916 va_end(ap);
917
918 if (len < 0) {
919 sigprocmask(SIG_SETMASK, &oldset, NULL);
920 return len;
921 }
922 if ((size_t)len >= sizeof(buf)) {
923 char *dynamic_buf = malloc(len + 1);
924
925 if (!dynamic_buf) {
926 sigprocmask(SIG_SETMASK, &oldset, NULL);
927 return -ENOMEM;
928 }
929 va_start(ap, fmt);
930 vsnprintf(dynamic_buf, len + 1, fmt, ap);
931 va_end(ap);
932 ret = strbuf_addstr(sb, dynamic_buf);
933 free(dynamic_buf);
934 } else {
935 ret = strbuf_addstr(sb, buf);
936 }
937
938 sigprocmask(SIG_SETMASK, &oldset, NULL);
939 return ret;
940}
941
942static void drain_child_process_err(struct child_test *child)
943{
944 char buf[512];
945 ssize_t len;
946
947 while ((len = read(child->process.err, buf, sizeof(buf) - 1)) > 0) {
948 buf[len] = '\0';
949 strbuf_addstr_safe(&child->err_output, buf);
950 }
951}
952
953static void handle_child_pipe_activity(struct child_test *child, short revents)
954{
955 if (!revents)
956 return;
957
958 drain_child_process_err(child);
959 /*
960 * If the child closed its end of the pipe (EOF) or encountered
961 * an error, close the file descriptor immediately and set it
962 * to -1. This removes it from the pfds array for subsequent
963 * iterations, preventing a tight CPU busy-loop while waiting
964 * for the process itself to exit.
965 */
966 if (revents & (POLLHUP | POLLERR | POLLNVAL)) {
967 close(child->process.err);
968 child->process.err = -1;
969 }
970}
971
972static int finish_tests_parallel(struct child_test **child_tests, size_t num_tests, int width)
973{
974 size_t next_to_print = 0;
975 struct pollfd *pfds;
976 size_t *pfd_indices;
977 size_t num_pfds = 0;
978 int last_running = -1;
979 size_t i;
980 int last_suite_printed = -1;
981 sigset_t set, oldset;
982
983 width = get_max_desc_width(width);
984
985 sigemptyset(&set);
986 sigaddset(&set, SIGINT);
987 sigaddset(&set, SIGTERM);
988
989 pthread_sigmask(SIG_BLOCK, &set, &oldset);
990 global_pfds = calloc(num_tests, sizeof(*pfds));
991 global_pfd_indices = calloc(num_tests, sizeof(*pfd_indices));
992 pfds = global_pfds;
993 pfd_indices = global_pfd_indices;
994 if (!pfds || !pfd_indices) {
995 free(pfds);
996 free(pfd_indices);
997 global_pfds = NULL;
998 global_pfd_indices = NULL;
999 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1000 return -ENOMEM;
1001 }
1002 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1003
1004 for (i = 0; i < num_tests; i++) {
1005 struct child_test *child = child_tests[i];
1006
1007 if (!child)
1008 continue;
1009 strbuf_init(&child->err_output, 0);
1010 if (child->process.err >= 0)
1011 fcntl(child->process.err, F_SETFL, O_NONBLOCK);
1012 }
1013
1014 while (next_to_print < num_tests) {
1015 size_t running_count = 0;
1016 size_t p;
1017
1018 while (next_to_print < num_tests &&
1019 (!child_tests[next_to_print] || child_tests[next_to_print]->done))
1020 next_to_print++;
1021
1022 if (next_to_print >= num_tests)
1023 break;
1024
1025 num_pfds = 0;
1026
1027 for (i = next_to_print; i < num_tests; i++) {
1028 struct child_test *child = child_tests[i];
1029
1030 if (!child || child->done)
1031 continue;
1032
1033 if (!check_if_command_finished(&child->process))
1034 running_count++;
1035
1036 if (child->process.err >= 0) {
1037 pfds[num_pfds].fd = child->process.err;
1038 pfds[num_pfds].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
1039 pfd_indices[num_pfds] = i;
1040 num_pfds++;
1041 }
1042 }
1043
1044 if (perf_use_color_default && running_count != (size_t)last_running) {
1045 struct child_test *next_child = child_tests[next_to_print];
1046
1047 if (last_running != -1)
1048 fprintf(debug_file(), PERF_COLOR_DELETE_LINE);
1049
1050 if (next_child) {
1051 if (test_suite__num_test_cases(next_child->test) > 1 &&
1052 last_suite_printed != next_child->suite_num) {
1053 pr_info("%3d: %-*.*s:\n",
1054 next_child->suite_num + 1,
1055 width, width,
1056 test_description(
1057 next_child->test, -1));
1058 last_suite_printed = next_child->suite_num;
1059 }
1060 print_test_result(next_child->test, next_child->suite_num,
1061 next_child->test_case_num, TEST_RUNNING, width,
1062 running_count, NULL, 0.0);
1063 }
1064 last_running = running_count;
1065 }
1066
1067 if (num_pfds == 0) {
1068 if (running_count > 0)
1069 usleep(10 * 1000);
1070 } else {
1071 int pret = poll(pfds, num_pfds, 100);
1072
1073 if (pret > 0) {
1074 for (p = 0; p < num_pfds; p++) {
1075 size_t idx = pfd_indices[p];
1076
1077 handle_child_pipe_activity(child_tests[idx],
1078 pfds[p].revents);
1079 }
1080 }
1081 }
1082
1083 for (i = next_to_print; i < num_tests; i++) {
1084 struct child_test *child = child_tests[i];
1085
1086 if (!child || child->done)
1087 continue;
1088
1089 if (check_if_command_finished(&child->process)) {
1090 if (child->process.err >= 0) {
1091 drain_child_process_err(child);
1092 close(child->process.err);
1093 child->process.err = -1;
1094 }
1095 child->result = finish_command(&child->process);
1096 child->process.pid = 0;
1097 clock_gettime(CLOCK_MONOTONIC, &child->end_time);
1098 child->done = true;
1099 }
1100 }
1101
1102 while (next_to_print < num_tests) {
1103 struct child_test *child = child_tests[next_to_print];
1104 double elapsed;
1105
1106 if (!child) {
1107 next_to_print++;
1108 continue;
1109 }
1110 if (!child->done)
1111 break;
1112
1113 if (perf_use_color_default && last_running != -1) {
1114 fprintf(debug_file(), PERF_COLOR_DELETE_LINE);
1115 last_running = -1;
1116 }
1117
1118 if (test_suite__num_test_cases(child->test) > 1 &&
1119 last_suite_printed != child->suite_num) {
1120 pr_info("%3d: %-*.*s:\n", child->suite_num + 1,
1121 width, width,
1122 test_description(child->test, -1));
1123 last_suite_printed = child->suite_num;
1124 }
1125
1126 if (verbose > 1) {
1127 if (test_suite__num_test_cases(child->test) > 1) {
1128 pr_info("%3d.%1d: %s:\n", child->suite_num + 1,
1129 child->test_case_num + 1,
1130 test_description(child->test,
1131 child->test_case_num));
1132 } else {
1133 pr_info("%3d: %s:\n", child->suite_num + 1,
1134 test_description(child->test, -1));
1135 }
1136 }
1137
1138 if (verbose > 1)
1139 fprintf(stderr, "%s", child->err_output.buf);
1140 else if (verbose == 1 && child->result == TEST_FAIL)
1141 print_test_failure_snippet(stderr, child->err_output.buf);
1142
1143 elapsed = (child->end_time.tv_sec - child->start_time.tv_sec) +
1144 (child->end_time.tv_nsec -
1145 child->start_time.tv_nsec) / 1000000000.0;
1146
1147 print_test_result(child->test, child->suite_num, child->test_case_num,
1148 child->result, width, 0, child->err_output.buf, elapsed);
1149 pthread_sigmask(SIG_BLOCK, &set, &oldset);
1150 strbuf_release(&child->err_output);
1151 child_tests[next_to_print] = NULL;
1152 zfree(&child);
1153 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1154 next_to_print++;
1155 }
1156 }
1157
1158 pthread_sigmask(SIG_BLOCK, &set, &oldset);
1159 free(global_pfds);
1160 free(global_pfd_indices);
1161 global_pfds = NULL;
1162 global_pfd_indices = NULL;
1163 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1164 return 0;
1165}
1166
1167static int start_test(struct test_suite *test, int curr_suite, int curr_test_case,
1168 struct child_test **child, int width, int pass)
1169{
1170 int err;
1171
1172 *child = NULL;
1173 if (dont_fork) {
1174 if (pass == 1) {
1175 struct timespec start_time, end_time;
1176 double elapsed;
1177
1178 clock_gettime(CLOCK_MONOTONIC, &start_time);
1179 pr_debug("--- start ---\n");
1180 err = test_function(test, curr_test_case)(test, curr_test_case);
1181 pr_debug("---- end ----\n");
1182 clock_gettime(CLOCK_MONOTONIC, &end_time);
1183 elapsed = (end_time.tv_sec - start_time.tv_sec) +
1184 (end_time.tv_nsec - start_time.tv_nsec) / 1000000000.0;
1185 print_test_result(test, curr_suite, curr_test_case, err, width,
1186 /*running=*/0, NULL, elapsed);
1187 }
1188 return 0;
1189 }
1190 if (pass == 1 && !sequential && test_exclusive(test, curr_test_case)) {
1191 /* When parallel, skip exclusive tests on the first pass. */
1192 return 0;
1193 }
1194 if (pass != 1 && (sequential || !test_exclusive(test, curr_test_case))) {
1195 /* Sequential and non-exclusive tests were run on the first pass. */
1196 return 0;
1197 }
1198 *child = zalloc(sizeof(**child));
1199 if (!*child)
1200 return -ENOMEM;
1201
1202 (*child)->test = test;
1203 (*child)->suite_num = curr_suite;
1204 (*child)->test_case_num = curr_test_case;
1205 (*child)->process.pid = -1;
1206 (*child)->process.no_stdin = 1;
1207 (*child)->process.in = -1;
1208 (*child)->process.out = -1;
1209 (*child)->process.err = -1;
1210 if (verbose <= 0) {
1211 (*child)->process.no_stdout = 1;
1212 (*child)->process.no_stderr = 1;
1213 } else {
1214 (*child)->process.stdout_to_stderr = 1;
1215 }
1216 (*child)->process.no_exec_cmd = run_test_child;
1217 if (sequential || pass == 2) {
1218 err = start_command(&(*child)->process);
1219 if (err)
1220 return err;
1221 finish_test(child, /*running_test=*/0, /*child_test_num=*/1, width);
1222 return 0;
1223 }
1224 return start_command(&(*child)->process);
1225}
1226
1227/* State outside of __cmd_test for the sake of the signal handler. */
1228
1229static size_t num_tests;
1230static struct child_test **child_tests;
1231static jmp_buf cmd_test_jmp_buf;
1232
1233static void cmd_test_sig_handler(int sig)
1234{
1235 siglongjmp(cmd_test_jmp_buf, sig);
1236}
1237
1238static void print_tests_summary(void)
1239{
1240 pr_info("\n=== Test Summary ===\n");
1241 pr_info("Passed main tests : %u\n", summary_tests_passed);
1242 pr_info("Passed subtests : %u\n", summary_subtests_passed);
1243 pr_info("Skipped tests : %u\n", summary_tests_skipped);
1244 if (summary_tests_failed > 0) {
1245 color_fprintf(debug_file(), PERF_COLOR_RED, "Failed tests : %u\n",
1246 summary_tests_failed);
1247 pr_info("List of failed tests:\n");
1248 pr_info("%s", summary_failed_tests_buf.buf);
1249 } else {
1250 color_fprintf(debug_file(), PERF_COLOR_GREEN, "Failed tests : 0\n");
1251 }
1252
1253 if (junit_filename) {
1254 int fd;
1255 FILE *fp;
1256
1257 fd = open(junit_filename, O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW, 0644);
1258 if (fd >= 0) {
1259 fp = fdopen(fd, "w");
1260 if (fp) {
1261 unsigned int total = summary_tests_passed +
1262 summary_subtests_passed +
1263 summary_tests_skipped +
1264 summary_tests_failed;
1265 fprintf(fp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
1266 fprintf(fp, "<testsuites>\n");
1267 fprintf(fp,
1268 " <testsuite name=\"perf-tests\" tests=\"%u\" failures=\"%u\" skipped=\"%u\">\n",
1269 total, summary_tests_failed,
1270 summary_tests_skipped);
1271 fprintf(fp, "%s", junit_xml_buf.buf);
1272 fprintf(fp, " </testsuite>\n");
1273 fprintf(fp, "</testsuites>\n");
1274 fclose(fp);
1275 pr_info("Wrote junit XML output to %s\n", junit_filename);
1276 } else {
1277 close(fd);
1278 pr_err("Failed to associate stream with fd for %s: %s\n",
1279 junit_filename, strerror(errno));
1280 }
1281 } else {
1282 pr_err("Failed to open %s for writing junit XML output: %s\n",
1283 junit_filename, strerror(errno));
1284 }
1285 }
1286 strbuf_release(&junit_xml_buf);
1287 strbuf_release(&summary_failed_tests_buf);
1288}
1289
1290static int __cmd_test(struct test_suite **suites, int argc, const char *argv[],
1291 struct intlist *skiplist)
1292{
1293 static int width = 0;
1294 int err = 0;
1295
1296 for (struct test_suite **t = suites; *t; t++) {
1297 int i, len = strlen(test_description(*t, -1));
1298
1299 if (width < len)
1300 width = len;
1301
1302 test_suite__for_each_test_case(*t, i) {
1303 len = strlen(test_description(*t, i));
1304 if (width < len)
1305 width = len;
1306 num_tests += runs_per_test;
1307 }
1308 }
1309 child_tests = calloc(num_tests, sizeof(*child_tests));
1310 if (!child_tests)
1311 return -ENOMEM;
1312
1313 err = sigsetjmp(cmd_test_jmp_buf, 1);
1314 if (err) {
1315 pr_err("\nSignal (%d) while running tests.\nTerminating tests with the same signal\n",
1316 err);
1317 for (size_t x = 0; x < num_tests; x++) {
1318 struct child_test *child_test = child_tests[x];
1319
1320 if (!child_test || child_test->process.pid <= 0)
1321 continue;
1322
1323 pr_debug3("Killing %d pid %d\n",
1324 child_test->suite_num + 1,
1325 child_test->process.pid);
1326 kill(child_test->process.pid, err);
1327 }
1328 goto err_out;
1329 }
1330 signal(SIGINT, cmd_test_sig_handler);
1331 signal(SIGTERM, cmd_test_sig_handler);
1332
1333 /*
1334 * In parallel mode pass 1 runs non-exclusive tests in parallel, pass 2
1335 * runs the exclusive tests sequentially. In other modes all tests are
1336 * run in pass 1.
1337 */
1338 for (int pass = 1; pass <= 2; pass++) {
1339 int child_test_num = 0;
1340 int curr_suite = 0;
1341
1342 for (struct test_suite **t = suites; *t; t++, curr_suite++) {
1343 int curr_test_case;
1344 bool suite_matched = false;
1345
1346 if (!perf_test__matches(test_description(*t, -1), curr_suite, argc, argv)) {
1347 /*
1348 * Test suite shouldn't be run based on
1349 * description. See if any test case should.
1350 */
1351 bool skip = true;
1352
1353 test_suite__for_each_test_case(*t, curr_test_case) {
1354 if (perf_test__matches(test_description(*t, curr_test_case),
1355 curr_suite, argc, argv)) {
1356 skip = false;
1357 break;
1358 }
1359 }
1360 if (skip)
1361 continue;
1362 } else {
1363 suite_matched = true;
1364 }
1365
1366 if (intlist__find(skiplist, curr_suite + 1)) {
1367 if (pass == 1) {
1368 int pad_width = get_max_desc_width(width);
1369 int term_width = get_term_width();
1370
1371 pr_info("%3d: %-*.*s:", curr_suite + 1,
1372 pad_width, term_width,
1373 test_description(*t, -1));
1374 color_fprintf(debug_file(), PERF_COLOR_YELLOW,
1375 " Skip (user override)\n");
1376 summary_tests_skipped++;
1377 if (junit_filename) {
1378 char *escaped_class =
1379 xml_escape((const char *)
1380 test_description(*t, -1));
1381 char *escaped_test = xml_escape("override");
1382 char *escaped_reason =
1383 xml_escape("user override");
1384
1385 strbuf_addf(&junit_xml_buf,
1386 " <testcase classname=\"%s\" name=\"%s\" time=\"0.000\">\n",
1387 escaped_class, escaped_test);
1388 strbuf_addf(&junit_xml_buf,
1389 " <skipped message=\"%s\"/>\n",
1390 escaped_reason);
1391 strbuf_addstr(&junit_xml_buf, " </testcase>\n");
1392 free(escaped_reason);
1393 free(escaped_test);
1394 free(escaped_class);
1395 }
1396 }
1397 continue;
1398 }
1399
1400 for (unsigned int run = 0; run < runs_per_test; run++) {
1401 test_suite__for_each_test_case(*t, curr_test_case) {
1402 if (!suite_matched &&
1403 !perf_test__matches(test_description(*t, curr_test_case),
1404 curr_suite, argc, argv))
1405 continue;
1406 err = start_test(*t, curr_suite, curr_test_case,
1407 &child_tests[child_test_num++],
1408 width, pass);
1409 if (err)
1410 goto err_out;
1411 }
1412 }
1413 }
1414 if (!sequential) {
1415 /* Parallel mode starts tests but doesn't finish them. Do that now. */
1416 err = finish_tests_parallel(child_tests, num_tests, width);
1417 if (err)
1418 goto err_out;
1419 }
1420 }
1421err_out:
1422 signal(SIGINT, SIG_DFL);
1423 signal(SIGTERM, SIG_DFL);
1424 if (err) {
1425 pr_err("Internal test harness failure. Completing any started tests:\n:");
1426 for (size_t x = 0; x < num_tests; x++)
1427 finish_test(child_tests, x, num_tests, width);
1428 }
1429 print_tests_summary();
1430 free(global_pfds);
1431 free(global_pfd_indices);
1432 global_pfds = NULL;
1433 global_pfd_indices = NULL;
1434 free(child_tests);
1435 return err;
1436}
1437
1438static int perf_test__list(FILE *fp, struct test_suite **suites, int argc, const char **argv)
1439{
1440 int curr_suite = 0;
1441
1442 for (struct test_suite **t = suites; *t; t++, curr_suite++) {
1443 int curr_test_case;
1444
1445 if (!perf_test__matches(test_description(*t, -1), curr_suite, argc, argv))
1446 continue;
1447
1448 fprintf(fp, "%3d: %s\n", curr_suite + 1, test_description(*t, -1));
1449
1450 if (test_suite__num_test_cases(*t) <= 1)
1451 continue;
1452
1453 test_suite__for_each_test_case(*t, curr_test_case) {
1454 fprintf(fp, "%3d.%1d: %s\n", curr_suite + 1, curr_test_case + 1,
1455 test_description(*t, curr_test_case));
1456 }
1457 }
1458 return 0;
1459}
1460
1461static int workloads__fprintf_list(FILE *fp)
1462{
1463 struct test_workload *twl;
1464 int printed = 0;
1465
1466 workloads__for_each(twl)
1467 printed += fprintf(fp, "%s\n", twl->name);
1468
1469 return printed;
1470}
1471
1472static int perf_control_open_fifo(struct workload_control *ctl, const char *str)
1473{
1474 char *s, *p;
1475 int ret;
1476
1477 if (strncmp(str, "fifo:", 5))
1478 return -EINVAL;
1479
1480 str += 5;
1481 if (!*str || *str == ',')
1482 return -EINVAL;
1483
1484 s = strdup(str);
1485 if (!s)
1486 return -ENOMEM;
1487
1488 p = strchr(s, ',');
1489 if (p)
1490 *p = '\0';
1491
1492 ctl->ctl_fd = open(s, O_WRONLY | O_CLOEXEC);
1493 if (ctl->ctl_fd < 0) {
1494 ret = -errno;
1495 pr_err("Failed to open workload control FIFO '%s': %m\n", s);
1496 free(s);
1497 return ret;
1498 }
1499
1500 if (p && *++p) {
1501 ctl->ack_fd = open(p, O_RDONLY | O_CLOEXEC);
1502 if (ctl->ack_fd < 0) {
1503 ret = -errno;
1504 pr_err("Failed to open workload control ack FIFO '%s': %m\n", p);
1505 close(ctl->ctl_fd);
1506 ctl->ctl_fd = -1;
1507 free(s);
1508 return ret;
1509 }
1510 }
1511
1512 free(s);
1513 return 0;
1514}
1515
1516static int perf_control_open(struct workload_control *ctl)
1517{
1518 int ret;
1519
1520 if (!workload_control)
1521 return 0;
1522
1523 ret = perf_control_open_fifo(ctl, workload_control);
1524
1525 if (ret == -EINVAL) {
1526 pr_err("Unsupported workload control spec '%s', expected fifo:ctl-fifo[,ack-fifo]\n",
1527 workload_control);
1528 }
1529
1530 return ret;
1531}
1532
1533static void perf_control_close(struct workload_control *ctl)
1534{
1535 if (ctl->ctl_fd >= 0) {
1536 close(ctl->ctl_fd);
1537 ctl->ctl_fd = -1;
1538 }
1539 if (ctl->ack_fd >= 0) {
1540 close(ctl->ack_fd);
1541 ctl->ack_fd = -1;
1542 }
1543}
1544
1545static int perf_control_write_cmd(int fd, const char *cmd)
1546{
1547 size_t len = strlen(cmd);
1548 ssize_t ret;
1549
1550 while (len) {
1551 ret = write(fd, cmd, len);
1552 if (ret < 0) {
1553 if (errno == EINTR)
1554 continue;
1555 pr_err("Failed to write perf control command: %m\n");
1556 return -1;
1557 }
1558
1559 if (!ret) {
1560 pr_err("Failed to write perf control command: short write\n");
1561 return -1;
1562 }
1563
1564 cmd += ret;
1565 len -= ret;
1566 }
1567
1568 return 0;
1569}
1570
1571static int perf_control_read_ack(int fd)
1572{
1573 char buf[16];
1574 ssize_t ret;
1575
1576 do {
1577 ret = read(fd, buf, sizeof(buf) - 1);
1578 } while (ret < 0 && errno == EINTR);
1579
1580 if (ret < 0) {
1581 pr_err("Failed to read perf control ack: %m\n");
1582 return -1;
1583 }
1584
1585 if (!ret) {
1586 pr_err("Unexpected EOF while reading perf control ack\n");
1587 return -1;
1588 }
1589
1590 buf[ret] = '\0';
1591 for (ssize_t i = 0; i < ret; i++) {
1592 if (buf[i] == '\n' || buf[i] == '\0') {
1593 buf[i] = '\0';
1594 break;
1595 }
1596 }
1597
1598 if (strcmp(buf, "ack")) {
1599 pr_err("Unexpected perf control ack: %s\n", buf);
1600 return -1;
1601 }
1602
1603 return 0;
1604}
1605
1606static int perf_control_send(struct workload_control *ctl, const char *cmd)
1607{
1608 if (ctl->ctl_fd < 0)
1609 return 0;
1610
1611 if (perf_control_write_cmd(ctl->ctl_fd, cmd))
1612 return -1;
1613
1614 if (ctl->ack_fd >= 0 && perf_control_read_ack(ctl->ack_fd))
1615 return -1;
1616
1617 return 0;
1618}
1619
1620static int run_workload(const char *work, int argc, const char **argv)
1621{
1622 struct test_workload *twl;
1623
1624 workloads__for_each(twl) {
1625 struct workload_control ctl = {
1626 .ctl_fd = -1,
1627 .ack_fd = -1,
1628 };
1629 int control_ret, ret;
1630
1631 if (strcmp(twl->name, work))
1632 continue;
1633
1634 ret = perf_control_open(&ctl);
1635 if (ret)
1636 return ret;
1637
1638 if (perf_control_send(&ctl, "enable\n")) {
1639 perf_control_close(&ctl);
1640 return -1;
1641 }
1642
1643 ret = twl->func(argc, argv);
1644
1645 control_ret = perf_control_send(&ctl, "disable\n");
1646 perf_control_close(&ctl);
1647 if (control_ret)
1648 return -1;
1649
1650 return ret;
1651 }
1652
1653 pr_info("No workload found: %s\n", work);
1654 return -1;
1655}
1656
1657static int perf_test__config(const char *var, const char *value,
1658 void *data __maybe_unused)
1659{
1660 if (!strcmp(var, "annotate.objdump"))
1661 test_objdump_path = value;
1662
1663 return 0;
1664}
1665
1666static struct test_suite **build_suites(void)
1667{
1668 /*
1669 * TODO: suites is static to avoid needing to clean up the scripts tests
1670 * for leak sanitizer.
1671 */
1672 static struct test_suite **suites[] = {
1673 generic_tests,
1674 arch_tests,
1675 NULL,
1676 };
1677 struct test_suite **result;
1678 struct test_suite *t;
1679 size_t n = 0, num_suites = 0;
1680
1681 if (suites[2] == NULL)
1682 suites[2] = create_script_test_suites();
1683
1684#define for_each_suite(suite) \
1685 for (size_t i = 0, j = 0; i < ARRAY_SIZE(suites); i++, j = 0) \
1686 while ((suite = suites[i][j++]) != NULL)
1687
1688 for_each_suite(t) {
1689 if (t->setup) {
1690 int ret = t->setup(t);
1691
1692 if (ret < 0) {
1693 errno = -ret;
1694 return NULL;
1695 }
1696 }
1697 num_suites++;
1698 }
1699
1700 result = calloc(num_suites + 1, sizeof(struct test_suite *));
1701 if (!result)
1702 return NULL;
1703
1704 for (int pass = 1; pass <= 2; pass++) {
1705 for_each_suite(t) {
1706 bool exclusive = false;
1707 int curr_test_case;
1708
1709 test_suite__for_each_test_case(t, curr_test_case) {
1710 if (test_exclusive(t, curr_test_case)) {
1711 exclusive = true;
1712 break;
1713 }
1714 }
1715 if ((!exclusive && pass == 1) || (exclusive && pass == 2))
1716 result[n++] = t;
1717 }
1718 }
1719 return result;
1720#undef for_each_suite
1721}
1722
1723int cmd_test(int argc, const char **argv)
1724{
1725 const char *test_usage[] = {
1726 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
1727 NULL,
1728 };
1729 const char *skip = NULL;
1730 const char *workload = NULL;
1731 bool list_workloads = false;
1732 const struct option test_options[] = {
1733 OPT_STRING('s', "skip", &skip, "tests", "tests to skip"),
1734 OPT_INCR('v', "verbose", &verbose,
1735 "be more verbose (show symbol address, etc)"),
1736 OPT_BOOLEAN('F', "dont-fork", &dont_fork,
1737 "Do not fork for testcase"),
1738 OPT_BOOLEAN('S', "sequential", &sequential,
1739 "Run the tests one after another rather than in parallel"),
1740 OPT_UINTEGER('r', "runs-per-test", &runs_per_test,
1741 "Run each test the given number of times, default 1"),
1742 OPT_STRING('w', "workload", &workload, "work", "workload to run for testing, use '--list-workloads' to list the available ones."),
1743 OPT_STRING(0, "record-ctl", &workload_control, "fifo:ctl-fifo[,ack-fifo]",
1744 "Write enable to the fifo just before running the workload and disable after, with optional ack from ack-fifo"),
1745 OPT_BOOLEAN(0, "list-workloads", &list_workloads, "List the available builtin workloads to use with -w/--workload"),
1746 OPT_STRING(0, "dso", &dso_to_test, "dso", "dso to test"),
1747 OPT_STRING(0, "objdump", &test_objdump_path, "path",
1748 "objdump binary to use for disassembly and annotations"),
1749 OPT_UINTEGER(0, "failure-snippet-lines", &failure_snippet_lines,
1750 "Number of lines to include in failure snippet, default 10"),
1751 OPT_STRING_OPTARG('j', "junit", &junit_filename, "file",
1752 "Generate junit XML output, default test.xml", "test.xml"),
1753 OPT_END()
1754 };
1755 const char * const test_subcommands[] = { "list", NULL };
1756 struct intlist *skiplist = NULL;
1757 int ret = hists__init();
1758 struct test_suite **suites;
1759
1760 if (ret < 0)
1761 return ret;
1762
1763 perf_config(perf_test__config, NULL);
1764
1765 /* Unbuffered output */
1766 setvbuf(stdout, NULL, _IONBF, 0);
1767
1768 argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0);
1769 if (argc >= 1 && !strcmp(argv[0], "list")) {
1770 suites = build_suites();
1771 if (!suites)
1772 return errno ? -errno : -ENOMEM;
1773 ret = perf_test__list(stdout, suites, argc - 1, argv + 1);
1774 free(suites);
1775 return ret;
1776 }
1777
1778 if (workload)
1779 return run_workload(workload, argc, argv);
1780
1781 if (list_workloads) {
1782 workloads__fprintf_list(stdout);
1783 return 0;
1784 }
1785
1786 if (dont_fork)
1787 sequential = true;
1788
1789 symbol_conf.priv_size = sizeof(int);
1790 symbol_conf.try_vmlinux_path = true;
1791
1792
1793 if (symbol__init(NULL) < 0)
1794 return -1;
1795
1796 if (skip != NULL)
1797 skiplist = intlist__new(skip);
1798 /*
1799 * Tests that create BPF maps, for instance, need more than the 64K
1800 * default:
1801 */
1802 rlimit__bump_memlock();
1803
1804 suites = build_suites();
1805 if (!suites) {
1806 int err = errno;
1807
1808 intlist__delete(skiplist);
1809 return err ? -err : -ENOMEM;
1810 }
1811 ret = __cmd_test(suites, argc, argv, skiplist);
1812 free(suites);
1813 intlist__delete(skiplist);
1814 return ret;
1815}