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