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 <fcntl.h> 8 #include <errno.h> 9 #include <unistd.h> 10 #include <string.h> 11 #include <stdlib.h> 12 #include <sys/types.h> 13 #include <dirent.h> 14 #include <sys/wait.h> 15 #include <sys/stat.h> 16 #include "builtin.h" 17 #include "hist.h" 18 #include "intlist.h" 19 #include "tests.h" 20 #include "debug.h" 21 #include "color.h" 22 #include <subcmd/parse-options.h> 23 #include "string2.h" 24 #include "symbol.h" 25 #include "util/rlimit.h" 26 #include <linux/kernel.h> 27 #include <linux/string.h> 28 #include <subcmd/exec-cmd.h> 29 #include <linux/zalloc.h> 30 31 static bool dont_fork; 32 33 struct test_suite *__weak arch_tests[] = { 34 NULL, 35 }; 36 37 static struct test_suite *generic_tests[] = { 38 &suite__vmlinux_matches_kallsyms, 39 &suite__openat_syscall_event, 40 &suite__openat_syscall_event_on_all_cpus, 41 &suite__basic_mmap, 42 &suite__mem, 43 &suite__parse_events, 44 &suite__expr, 45 &suite__PERF_RECORD, 46 &suite__pmu, 47 &suite__pmu_events, 48 &suite__dso_data, 49 &suite__dso_data_cache, 50 &suite__dso_data_reopen, 51 &suite__perf_evsel__roundtrip_name_test, 52 &suite__perf_evsel__tp_sched_test, 53 &suite__syscall_openat_tp_fields, 54 &suite__attr, 55 &suite__hists_link, 56 &suite__python_use, 57 &suite__bp_signal, 58 &suite__bp_signal_overflow, 59 &suite__bp_accounting, 60 &suite__wp, 61 &suite__task_exit, 62 &suite__sw_clock_freq, 63 &suite__code_reading, 64 &suite__sample_parsing, 65 &suite__keep_tracking, 66 &suite__parse_no_sample_id_all, 67 &suite__hists_filter, 68 &suite__mmap_thread_lookup, 69 &suite__thread_maps_share, 70 &suite__hists_output, 71 &suite__hists_cumulate, 72 &suite__switch_tracking, 73 &suite__fdarray__filter, 74 &suite__fdarray__add, 75 &suite__kmod_path__parse, 76 &suite__thread_map, 77 &suite__llvm, 78 &suite__session_topology, 79 &suite__bpf, 80 &suite__thread_map_synthesize, 81 &suite__thread_map_remove, 82 &suite__cpu_map_synthesize, 83 &suite__synthesize_stat_config, 84 &suite__synthesize_stat, 85 &suite__synthesize_stat_round, 86 &suite__event_update, 87 &suite__event_times, 88 &suite__backward_ring_buffer, 89 &suite__cpu_map_print, 90 &suite__cpu_map_merge, 91 &suite__sdt_event, 92 &suite__is_printable_array, 93 &suite__bitmap_print, 94 &suite__perf_hooks, 95 &suite__clang, 96 &suite__unit_number__scnprint, 97 &suite__mem2node, 98 &suite__time_utils, 99 &suite__jit_write_elf, 100 &suite__pfm, 101 &suite__api_io, 102 &suite__maps__merge_in, 103 &suite__demangle_java, 104 &suite__demangle_ocaml, 105 &suite__parse_metric, 106 &suite__pe_file_parsing, 107 &suite__expand_cgroup_events, 108 &suite__perf_time_to_tsc, 109 &suite__dlfilter, 110 NULL, 111 }; 112 113 static struct test_suite **tests[] = { 114 generic_tests, 115 arch_tests, 116 }; 117 118 static int num_subtests(const struct test_suite *t) 119 { 120 int num; 121 122 if (!t->test_cases) 123 return 0; 124 125 num = 0; 126 while (t->test_cases[num].name) 127 num++; 128 129 return num; 130 } 131 132 static bool has_subtests(const struct test_suite *t) 133 { 134 return num_subtests(t) > 1; 135 } 136 137 static const char *skip_reason(const struct test_suite *t, int subtest) 138 { 139 if (t->test_cases && subtest >= 0) 140 return t->test_cases[subtest].skip_reason; 141 142 return NULL; 143 } 144 145 static const char *test_description(const struct test_suite *t, int subtest) 146 { 147 if (t->test_cases && subtest >= 0) 148 return t->test_cases[subtest].desc; 149 150 return t->desc; 151 } 152 153 static test_fnptr test_function(const struct test_suite *t, int subtest) 154 { 155 if (subtest <= 0) 156 return t->test_cases[0].run_case; 157 158 return t->test_cases[subtest].run_case; 159 } 160 161 static bool perf_test__matches(const char *desc, int curr, int argc, const char *argv[]) 162 { 163 int i; 164 165 if (argc == 0) 166 return true; 167 168 for (i = 0; i < argc; ++i) { 169 char *end; 170 long nr = strtoul(argv[i], &end, 10); 171 172 if (*end == '\0') { 173 if (nr == curr + 1) 174 return true; 175 continue; 176 } 177 178 if (strcasestr(desc, argv[i])) 179 return true; 180 } 181 182 return false; 183 } 184 185 static int run_test(struct test_suite *test, int subtest) 186 { 187 int status, err = -1, child = dont_fork ? 0 : fork(); 188 char sbuf[STRERR_BUFSIZE]; 189 190 if (child < 0) { 191 pr_err("failed to fork test: %s\n", 192 str_error_r(errno, sbuf, sizeof(sbuf))); 193 return -1; 194 } 195 196 if (!child) { 197 if (!dont_fork) { 198 pr_debug("test child forked, pid %d\n", getpid()); 199 200 if (verbose <= 0) { 201 int nullfd = open("/dev/null", O_WRONLY); 202 203 if (nullfd >= 0) { 204 close(STDERR_FILENO); 205 close(STDOUT_FILENO); 206 207 dup2(nullfd, STDOUT_FILENO); 208 dup2(STDOUT_FILENO, STDERR_FILENO); 209 close(nullfd); 210 } 211 } else { 212 signal(SIGSEGV, sighandler_dump_stack); 213 signal(SIGFPE, sighandler_dump_stack); 214 } 215 } 216 217 err = test_function(test, subtest)(test, subtest); 218 if (!dont_fork) 219 exit(err); 220 } 221 222 if (!dont_fork) { 223 wait(&status); 224 225 if (WIFEXITED(status)) { 226 err = (signed char)WEXITSTATUS(status); 227 pr_debug("test child finished with %d\n", err); 228 } else if (WIFSIGNALED(status)) { 229 err = -1; 230 pr_debug("test child interrupted\n"); 231 } 232 } 233 234 return err; 235 } 236 237 #define for_each_test(j, k, t) \ 238 for (j = 0; j < ARRAY_SIZE(tests); j++) \ 239 for (k = 0, t = tests[j][k]; tests[j][k]; k++, t = tests[j][k]) 240 241 static int test_and_print(struct test_suite *t, int subtest) 242 { 243 int err; 244 245 pr_debug("\n--- start ---\n"); 246 err = run_test(t, subtest); 247 pr_debug("---- end ----\n"); 248 249 if (!has_subtests(t)) 250 pr_debug("%s:", t->desc); 251 else 252 pr_debug("%s subtest %d:", t->desc, subtest + 1); 253 254 switch (err) { 255 case TEST_OK: 256 pr_info(" Ok\n"); 257 break; 258 case TEST_SKIP: { 259 const char *reason = skip_reason(t, subtest); 260 261 if (reason) 262 color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (%s)\n", reason); 263 else 264 color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n"); 265 } 266 break; 267 case TEST_FAIL: 268 default: 269 color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n"); 270 break; 271 } 272 273 return err; 274 } 275 276 static const char *shell_test__description(char *description, size_t size, 277 const char *path, const char *name) 278 { 279 FILE *fp; 280 char filename[PATH_MAX]; 281 282 path__join(filename, sizeof(filename), path, name); 283 fp = fopen(filename, "r"); 284 if (!fp) 285 return NULL; 286 287 /* Skip shebang */ 288 while (fgetc(fp) != '\n'); 289 290 description = fgets(description, size, fp); 291 fclose(fp); 292 293 return description ? strim(description + 1) : NULL; 294 } 295 296 #define for_each_shell_test(entlist, nr, base, ent) \ 297 for (int __i = 0; __i < nr && (ent = entlist[__i]); __i++) \ 298 if (!is_directory(base, ent) && ent->d_name[0] != '.') 299 300 static const char *shell_tests__dir(char *path, size_t size) 301 { 302 const char *devel_dirs[] = { "./tools/perf/tests", "./tests", }; 303 char *exec_path; 304 unsigned int i; 305 306 for (i = 0; i < ARRAY_SIZE(devel_dirs); ++i) { 307 struct stat st; 308 if (!lstat(devel_dirs[i], &st)) { 309 scnprintf(path, size, "%s/shell", devel_dirs[i]); 310 if (!lstat(devel_dirs[i], &st)) 311 return path; 312 } 313 } 314 315 /* Then installed path. */ 316 exec_path = get_argv_exec_path(); 317 scnprintf(path, size, "%s/tests/shell", exec_path); 318 free(exec_path); 319 return path; 320 } 321 322 static int shell_tests__max_desc_width(void) 323 { 324 struct dirent **entlist; 325 struct dirent *ent; 326 int n_dirs, e; 327 char path_dir[PATH_MAX]; 328 const char *path = shell_tests__dir(path_dir, sizeof(path_dir)); 329 int width = 0; 330 331 if (path == NULL) 332 return -1; 333 334 n_dirs = scandir(path, &entlist, NULL, alphasort); 335 if (n_dirs == -1) 336 return -1; 337 338 for_each_shell_test(entlist, n_dirs, path, ent) { 339 char bf[256]; 340 const char *desc = shell_test__description(bf, sizeof(bf), path, ent->d_name); 341 342 if (desc) { 343 int len = strlen(desc); 344 345 if (width < len) 346 width = len; 347 } 348 } 349 350 for (e = 0; e < n_dirs; e++) 351 zfree(&entlist[e]); 352 free(entlist); 353 return width; 354 } 355 356 struct shell_test { 357 const char *dir; 358 const char *file; 359 }; 360 361 static int shell_test__run(struct test_suite *test, int subdir __maybe_unused) 362 { 363 int err; 364 char script[PATH_MAX]; 365 struct shell_test *st = test->priv; 366 367 path__join(script, sizeof(script) - 3, st->dir, st->file); 368 369 if (verbose) 370 strncat(script, " -v", sizeof(script) - strlen(script) - 1); 371 372 err = system(script); 373 if (!err) 374 return TEST_OK; 375 376 return WEXITSTATUS(err) == 2 ? TEST_SKIP : TEST_FAIL; 377 } 378 379 static int run_shell_tests(int argc, const char *argv[], int i, int width, 380 struct intlist *skiplist) 381 { 382 struct dirent **entlist; 383 struct dirent *ent; 384 int n_dirs, e; 385 char path_dir[PATH_MAX]; 386 struct shell_test st = { 387 .dir = shell_tests__dir(path_dir, sizeof(path_dir)), 388 }; 389 390 if (st.dir == NULL) 391 return -1; 392 393 n_dirs = scandir(st.dir, &entlist, NULL, alphasort); 394 if (n_dirs == -1) { 395 pr_err("failed to open shell test directory: %s\n", 396 st.dir); 397 return -1; 398 } 399 400 for_each_shell_test(entlist, n_dirs, st.dir, ent) { 401 int curr = i++; 402 char desc[256]; 403 struct test_case test_cases[] = { 404 { 405 .desc = shell_test__description(desc, 406 sizeof(desc), 407 st.dir, 408 ent->d_name), 409 .run_case = shell_test__run, 410 }, 411 { .name = NULL, } 412 }; 413 struct test_suite test_suite = { 414 .desc = test_cases[0].desc, 415 .test_cases = test_cases, 416 .priv = &st, 417 }; 418 419 if (!perf_test__matches(test_suite.desc, curr, argc, argv)) 420 continue; 421 422 st.file = ent->d_name; 423 pr_info("%2d: %-*s:", i, width, test_suite.desc); 424 425 if (intlist__find(skiplist, i)) { 426 color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n"); 427 continue; 428 } 429 430 test_and_print(&test_suite, 0); 431 } 432 433 for (e = 0; e < n_dirs; e++) 434 zfree(&entlist[e]); 435 free(entlist); 436 return 0; 437 } 438 439 static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) 440 { 441 struct test_suite *t; 442 unsigned int j, k; 443 int i = 0; 444 int width = shell_tests__max_desc_width(); 445 446 for_each_test(j, k, t) { 447 int len = strlen(test_description(t, -1)); 448 449 if (width < len) 450 width = len; 451 } 452 453 for_each_test(j, k, t) { 454 int curr = i++; 455 int subi; 456 457 if (!perf_test__matches(test_description(t, -1), curr, argc, argv)) { 458 bool skip = true; 459 int subn; 460 461 subn = num_subtests(t); 462 463 for (subi = 0; subi < subn; subi++) { 464 if (perf_test__matches(test_description(t, subi), 465 curr, argc, argv)) 466 skip = false; 467 } 468 469 if (skip) 470 continue; 471 } 472 473 pr_info("%2d: %-*s:", i, width, test_description(t, -1)); 474 475 if (intlist__find(skiplist, i)) { 476 color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n"); 477 continue; 478 } 479 480 if (!has_subtests(t)) { 481 test_and_print(t, -1); 482 } else { 483 int subn = num_subtests(t); 484 /* 485 * minus 2 to align with normal testcases. 486 * For subtest we print additional '.x' in number. 487 * for example: 488 * 489 * 35: Test LLVM searching and compiling : 490 * 35.1: Basic BPF llvm compiling test : Ok 491 */ 492 int subw = width > 2 ? width - 2 : width; 493 494 if (subn <= 0) { 495 color_fprintf(stderr, PERF_COLOR_YELLOW, 496 " Skip (not compiled in)\n"); 497 continue; 498 } 499 pr_info("\n"); 500 501 for (subi = 0; subi < subn; subi++) { 502 int len = strlen(test_description(t, subi)); 503 504 if (subw < len) 505 subw = len; 506 } 507 508 for (subi = 0; subi < subn; subi++) { 509 if (!perf_test__matches(test_description(t, subi), 510 curr, argc, argv)) 511 continue; 512 513 pr_info("%2d.%1d: %-*s:", i, subi + 1, subw, 514 test_description(t, subi)); 515 test_and_print(t, subi); 516 } 517 } 518 } 519 520 return run_shell_tests(argc, argv, i, width, skiplist); 521 } 522 523 static int perf_test__list_shell(int argc, const char **argv, int i) 524 { 525 struct dirent **entlist; 526 struct dirent *ent; 527 int n_dirs, e; 528 char path_dir[PATH_MAX]; 529 const char *path = shell_tests__dir(path_dir, sizeof(path_dir)); 530 531 if (path == NULL) 532 return -1; 533 534 n_dirs = scandir(path, &entlist, NULL, alphasort); 535 if (n_dirs == -1) 536 return -1; 537 538 for_each_shell_test(entlist, n_dirs, path, ent) { 539 int curr = i++; 540 char bf[256]; 541 struct test_suite t = { 542 .desc = shell_test__description(bf, sizeof(bf), path, ent->d_name), 543 }; 544 545 if (!perf_test__matches(t.desc, curr, argc, argv)) 546 continue; 547 548 pr_info("%2d: %s\n", i, t.desc); 549 550 } 551 552 for (e = 0; e < n_dirs; e++) 553 zfree(&entlist[e]); 554 free(entlist); 555 return 0; 556 } 557 558 static int perf_test__list(int argc, const char **argv) 559 { 560 unsigned int j, k; 561 struct test_suite *t; 562 int i = 0; 563 564 for_each_test(j, k, t) { 565 int curr = i++; 566 567 if (!perf_test__matches(test_description(t, -1), curr, argc, argv)) 568 continue; 569 570 pr_info("%2d: %s\n", i, test_description(t, -1)); 571 572 if (has_subtests(t)) { 573 int subn = num_subtests(t); 574 int subi; 575 576 for (subi = 0; subi < subn; subi++) 577 pr_info("%2d:%1d: %s\n", i, subi + 1, 578 test_description(t, subi)); 579 } 580 } 581 582 perf_test__list_shell(argc, argv, i); 583 584 return 0; 585 } 586 587 int cmd_test(int argc, const char **argv) 588 { 589 const char *test_usage[] = { 590 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]", 591 NULL, 592 }; 593 const char *skip = NULL; 594 const struct option test_options[] = { 595 OPT_STRING('s', "skip", &skip, "tests", "tests to skip"), 596 OPT_INCR('v', "verbose", &verbose, 597 "be more verbose (show symbol address, etc)"), 598 OPT_BOOLEAN('F', "dont-fork", &dont_fork, 599 "Do not fork for testcase"), 600 OPT_END() 601 }; 602 const char * const test_subcommands[] = { "list", NULL }; 603 struct intlist *skiplist = NULL; 604 int ret = hists__init(); 605 606 if (ret < 0) 607 return ret; 608 609 argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0); 610 if (argc >= 1 && !strcmp(argv[0], "list")) 611 return perf_test__list(argc - 1, argv + 1); 612 613 symbol_conf.priv_size = sizeof(int); 614 symbol_conf.sort_by_name = true; 615 symbol_conf.try_vmlinux_path = true; 616 617 if (symbol__init(NULL) < 0) 618 return -1; 619 620 if (skip != NULL) 621 skiplist = intlist__new(skip); 622 /* 623 * Tests that create BPF maps, for instance, need more than the 64K 624 * default: 625 */ 626 rlimit__bump_memlock(); 627 628 return __cmd_test(argc, argv, skiplist); 629 } 630