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