builtin-test.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  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 <sys/types.h>
  12. #include <dirent.h>
  13. #include <sys/wait.h>
  14. #include <sys/stat.h>
  15. #include "builtin.h"
  16. #include "hist.h"
  17. #include "intlist.h"
  18. #include "tests.h"
  19. #include "debug.h"
  20. #include "color.h"
  21. #include <subcmd/parse-options.h>
  22. #include "string2.h"
  23. #include "symbol.h"
  24. #include <linux/kernel.h>
  25. #include <subcmd/exec-cmd.h>
  26. static bool dont_fork;
  27. struct test __weak arch_tests[] = {
  28. {
  29. .func = NULL,
  30. },
  31. };
  32. static struct test generic_tests[] = {
  33. {
  34. .desc = "vmlinux symtab matches kallsyms",
  35. .func = test__vmlinux_matches_kallsyms,
  36. },
  37. {
  38. .desc = "Detect openat syscall event",
  39. .func = test__openat_syscall_event,
  40. },
  41. {
  42. .desc = "Detect openat syscall event on all cpus",
  43. .func = test__openat_syscall_event_on_all_cpus,
  44. },
  45. {
  46. .desc = "Read samples using the mmap interface",
  47. .func = test__basic_mmap,
  48. },
  49. {
  50. .desc = "Test data source output",
  51. .func = test__mem,
  52. },
  53. {
  54. .desc = "Parse event definition strings",
  55. .func = test__parse_events,
  56. },
  57. {
  58. .desc = "Simple expression parser",
  59. .func = test__expr,
  60. },
  61. {
  62. .desc = "PERF_RECORD_* events & perf_sample fields",
  63. .func = test__PERF_RECORD,
  64. },
  65. {
  66. .desc = "Parse perf pmu format",
  67. .func = test__pmu,
  68. },
  69. {
  70. .desc = "DSO data read",
  71. .func = test__dso_data,
  72. },
  73. {
  74. .desc = "DSO data cache",
  75. .func = test__dso_data_cache,
  76. },
  77. {
  78. .desc = "DSO data reopen",
  79. .func = test__dso_data_reopen,
  80. },
  81. {
  82. .desc = "Roundtrip evsel->name",
  83. .func = test__perf_evsel__roundtrip_name_test,
  84. },
  85. {
  86. .desc = "Parse sched tracepoints fields",
  87. .func = test__perf_evsel__tp_sched_test,
  88. },
  89. {
  90. .desc = "syscalls:sys_enter_openat event fields",
  91. .func = test__syscall_openat_tp_fields,
  92. },
  93. {
  94. .desc = "Setup struct perf_event_attr",
  95. .func = test__attr,
  96. },
  97. {
  98. .desc = "Match and link multiple hists",
  99. .func = test__hists_link,
  100. },
  101. {
  102. .desc = "'import perf' in python",
  103. .func = test__python_use,
  104. },
  105. {
  106. .desc = "Breakpoint overflow signal handler",
  107. .func = test__bp_signal,
  108. .is_supported = test__bp_signal_is_supported,
  109. },
  110. {
  111. .desc = "Breakpoint overflow sampling",
  112. .func = test__bp_signal_overflow,
  113. .is_supported = test__bp_signal_is_supported,
  114. },
  115. {
  116. .desc = "Breakpoint accounting",
  117. .func = test__bp_accounting,
  118. .is_supported = test__bp_signal_is_supported,
  119. },
  120. {
  121. .desc = "Watchpoint",
  122. .func = test__wp,
  123. .is_supported = test__wp_is_supported,
  124. .subtest = {
  125. .skip_if_fail = false,
  126. .get_nr = test__wp_subtest_get_nr,
  127. .get_desc = test__wp_subtest_get_desc,
  128. },
  129. },
  130. {
  131. .desc = "Number of exit events of a simple workload",
  132. .func = test__task_exit,
  133. },
  134. {
  135. .desc = "Software clock events period values",
  136. .func = test__sw_clock_freq,
  137. },
  138. {
  139. .desc = "Object code reading",
  140. .func = test__code_reading,
  141. },
  142. {
  143. .desc = "Sample parsing",
  144. .func = test__sample_parsing,
  145. },
  146. {
  147. .desc = "Use a dummy software event to keep tracking",
  148. .func = test__keep_tracking,
  149. },
  150. {
  151. .desc = "Parse with no sample_id_all bit set",
  152. .func = test__parse_no_sample_id_all,
  153. },
  154. {
  155. .desc = "Filter hist entries",
  156. .func = test__hists_filter,
  157. },
  158. {
  159. .desc = "Lookup mmap thread",
  160. .func = test__mmap_thread_lookup,
  161. },
  162. {
  163. .desc = "Share thread mg",
  164. .func = test__thread_mg_share,
  165. },
  166. {
  167. .desc = "Sort output of hist entries",
  168. .func = test__hists_output,
  169. },
  170. {
  171. .desc = "Cumulate child hist entries",
  172. .func = test__hists_cumulate,
  173. },
  174. {
  175. .desc = "Track with sched_switch",
  176. .func = test__switch_tracking,
  177. },
  178. {
  179. .desc = "Filter fds with revents mask in a fdarray",
  180. .func = test__fdarray__filter,
  181. },
  182. {
  183. .desc = "Add fd to a fdarray, making it autogrow",
  184. .func = test__fdarray__add,
  185. },
  186. {
  187. .desc = "kmod_path__parse",
  188. .func = test__kmod_path__parse,
  189. },
  190. {
  191. .desc = "Thread map",
  192. .func = test__thread_map,
  193. },
  194. {
  195. .desc = "LLVM search and compile",
  196. .func = test__llvm,
  197. .subtest = {
  198. .skip_if_fail = true,
  199. .get_nr = test__llvm_subtest_get_nr,
  200. .get_desc = test__llvm_subtest_get_desc,
  201. },
  202. },
  203. {
  204. .desc = "Session topology",
  205. .func = test__session_topology,
  206. },
  207. {
  208. .desc = "BPF filter",
  209. .func = test__bpf,
  210. .subtest = {
  211. .skip_if_fail = true,
  212. .get_nr = test__bpf_subtest_get_nr,
  213. .get_desc = test__bpf_subtest_get_desc,
  214. },
  215. },
  216. {
  217. .desc = "Synthesize thread map",
  218. .func = test__thread_map_synthesize,
  219. },
  220. {
  221. .desc = "Remove thread map",
  222. .func = test__thread_map_remove,
  223. },
  224. {
  225. .desc = "Synthesize cpu map",
  226. .func = test__cpu_map_synthesize,
  227. },
  228. {
  229. .desc = "Synthesize stat config",
  230. .func = test__synthesize_stat_config,
  231. },
  232. {
  233. .desc = "Synthesize stat",
  234. .func = test__synthesize_stat,
  235. },
  236. {
  237. .desc = "Synthesize stat round",
  238. .func = test__synthesize_stat_round,
  239. },
  240. {
  241. .desc = "Synthesize attr update",
  242. .func = test__event_update,
  243. },
  244. {
  245. .desc = "Event times",
  246. .func = test__event_times,
  247. },
  248. {
  249. .desc = "Read backward ring buffer",
  250. .func = test__backward_ring_buffer,
  251. },
  252. {
  253. .desc = "Print cpu map",
  254. .func = test__cpu_map_print,
  255. },
  256. {
  257. .desc = "Probe SDT events",
  258. .func = test__sdt_event,
  259. },
  260. {
  261. .desc = "is_printable_array",
  262. .func = test__is_printable_array,
  263. },
  264. {
  265. .desc = "Print bitmap",
  266. .func = test__bitmap_print,
  267. },
  268. {
  269. .desc = "perf hooks",
  270. .func = test__perf_hooks,
  271. },
  272. {
  273. .desc = "builtin clang support",
  274. .func = test__clang,
  275. .subtest = {
  276. .skip_if_fail = true,
  277. .get_nr = test__clang_subtest_get_nr,
  278. .get_desc = test__clang_subtest_get_desc,
  279. }
  280. },
  281. {
  282. .desc = "unit_number__scnprintf",
  283. .func = test__unit_number__scnprint,
  284. },
  285. {
  286. .desc = "mem2node",
  287. .func = test__mem2node,
  288. },
  289. {
  290. .func = NULL,
  291. },
  292. };
  293. static struct test *tests[] = {
  294. generic_tests,
  295. arch_tests,
  296. };
  297. static bool perf_test__matches(struct test *test, int curr, int argc, const char *argv[])
  298. {
  299. int i;
  300. if (argc == 0)
  301. return true;
  302. for (i = 0; i < argc; ++i) {
  303. char *end;
  304. long nr = strtoul(argv[i], &end, 10);
  305. if (*end == '\0') {
  306. if (nr == curr + 1)
  307. return true;
  308. continue;
  309. }
  310. if (strcasestr(test->desc, argv[i]))
  311. return true;
  312. }
  313. return false;
  314. }
  315. static int run_test(struct test *test, int subtest)
  316. {
  317. int status, err = -1, child = dont_fork ? 0 : fork();
  318. char sbuf[STRERR_BUFSIZE];
  319. if (child < 0) {
  320. pr_err("failed to fork test: %s\n",
  321. str_error_r(errno, sbuf, sizeof(sbuf)));
  322. return -1;
  323. }
  324. if (!child) {
  325. if (!dont_fork) {
  326. pr_debug("test child forked, pid %d\n", getpid());
  327. if (verbose <= 0) {
  328. int nullfd = open("/dev/null", O_WRONLY);
  329. if (nullfd >= 0) {
  330. close(STDERR_FILENO);
  331. close(STDOUT_FILENO);
  332. dup2(nullfd, STDOUT_FILENO);
  333. dup2(STDOUT_FILENO, STDERR_FILENO);
  334. close(nullfd);
  335. }
  336. } else {
  337. signal(SIGSEGV, sighandler_dump_stack);
  338. signal(SIGFPE, sighandler_dump_stack);
  339. }
  340. }
  341. err = test->func(test, subtest);
  342. if (!dont_fork)
  343. exit(err);
  344. }
  345. if (!dont_fork) {
  346. wait(&status);
  347. if (WIFEXITED(status)) {
  348. err = (signed char)WEXITSTATUS(status);
  349. pr_debug("test child finished with %d\n", err);
  350. } else if (WIFSIGNALED(status)) {
  351. err = -1;
  352. pr_debug("test child interrupted\n");
  353. }
  354. }
  355. return err;
  356. }
  357. #define for_each_test(j, t) \
  358. for (j = 0; j < ARRAY_SIZE(tests); j++) \
  359. for (t = &tests[j][0]; t->func; t++)
  360. static int test_and_print(struct test *t, bool force_skip, int subtest)
  361. {
  362. int err;
  363. if (!force_skip) {
  364. pr_debug("\n--- start ---\n");
  365. err = run_test(t, subtest);
  366. pr_debug("---- end ----\n");
  367. } else {
  368. pr_debug("\n--- force skipped ---\n");
  369. err = TEST_SKIP;
  370. }
  371. if (!t->subtest.get_nr)
  372. pr_debug("%s:", t->desc);
  373. else
  374. pr_debug("%s subtest %d:", t->desc, subtest + 1);
  375. switch (err) {
  376. case TEST_OK:
  377. pr_info(" Ok\n");
  378. break;
  379. case TEST_SKIP:
  380. color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n");
  381. break;
  382. case TEST_FAIL:
  383. default:
  384. color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n");
  385. break;
  386. }
  387. return err;
  388. }
  389. static const char *shell_test__description(char *description, size_t size,
  390. const char *path, const char *name)
  391. {
  392. FILE *fp;
  393. char filename[PATH_MAX];
  394. path__join(filename, sizeof(filename), path, name);
  395. fp = fopen(filename, "r");
  396. if (!fp)
  397. return NULL;
  398. description = fgets(description, size, fp);
  399. fclose(fp);
  400. return description ? trim(description + 1) : NULL;
  401. }
  402. #define for_each_shell_test(dir, base, ent) \
  403. while ((ent = readdir(dir)) != NULL) \
  404. if (!is_directory(base, ent) && ent->d_name[0] != '.')
  405. static const char *shell_tests__dir(char *path, size_t size)
  406. {
  407. const char *devel_dirs[] = { "./tools/perf/tests", "./tests", };
  408. char *exec_path;
  409. unsigned int i;
  410. for (i = 0; i < ARRAY_SIZE(devel_dirs); ++i) {
  411. struct stat st;
  412. if (!lstat(devel_dirs[i], &st)) {
  413. scnprintf(path, size, "%s/shell", devel_dirs[i]);
  414. if (!lstat(devel_dirs[i], &st))
  415. return path;
  416. }
  417. }
  418. /* Then installed path. */
  419. exec_path = get_argv_exec_path();
  420. scnprintf(path, size, "%s/tests/shell", exec_path);
  421. free(exec_path);
  422. return path;
  423. }
  424. static int shell_tests__max_desc_width(void)
  425. {
  426. DIR *dir;
  427. struct dirent *ent;
  428. char path_dir[PATH_MAX];
  429. const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
  430. int width = 0;
  431. if (path == NULL)
  432. return -1;
  433. dir = opendir(path);
  434. if (!dir)
  435. return -1;
  436. for_each_shell_test(dir, path, ent) {
  437. char bf[256];
  438. const char *desc = shell_test__description(bf, sizeof(bf), path, ent->d_name);
  439. if (desc) {
  440. int len = strlen(desc);
  441. if (width < len)
  442. width = len;
  443. }
  444. }
  445. closedir(dir);
  446. return width;
  447. }
  448. struct shell_test {
  449. const char *dir;
  450. const char *file;
  451. };
  452. static int shell_test__run(struct test *test, int subdir __maybe_unused)
  453. {
  454. int err;
  455. char script[PATH_MAX];
  456. struct shell_test *st = test->priv;
  457. path__join(script, sizeof(script), st->dir, st->file);
  458. err = system(script);
  459. if (!err)
  460. return TEST_OK;
  461. return WEXITSTATUS(err) == 2 ? TEST_SKIP : TEST_FAIL;
  462. }
  463. static int run_shell_tests(int argc, const char *argv[], int i, int width)
  464. {
  465. DIR *dir;
  466. struct dirent *ent;
  467. char path_dir[PATH_MAX];
  468. struct shell_test st = {
  469. .dir = shell_tests__dir(path_dir, sizeof(path_dir)),
  470. };
  471. if (st.dir == NULL)
  472. return -1;
  473. dir = opendir(st.dir);
  474. if (!dir)
  475. return -1;
  476. for_each_shell_test(dir, st.dir, ent) {
  477. int curr = i++;
  478. char desc[256];
  479. struct test test = {
  480. .desc = shell_test__description(desc, sizeof(desc), st.dir, ent->d_name),
  481. .func = shell_test__run,
  482. .priv = &st,
  483. };
  484. if (!perf_test__matches(&test, curr, argc, argv))
  485. continue;
  486. st.file = ent->d_name;
  487. pr_info("%2d: %-*s:", i, width, test.desc);
  488. test_and_print(&test, false, -1);
  489. }
  490. closedir(dir);
  491. return 0;
  492. }
  493. static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
  494. {
  495. struct test *t;
  496. unsigned int j;
  497. int i = 0;
  498. int width = shell_tests__max_desc_width();
  499. for_each_test(j, t) {
  500. int len = strlen(t->desc);
  501. if (width < len)
  502. width = len;
  503. }
  504. for_each_test(j, t) {
  505. int curr = i++, err;
  506. if (!perf_test__matches(t, curr, argc, argv))
  507. continue;
  508. if (t->is_supported && !t->is_supported()) {
  509. pr_debug("%2d: %-*s: Disabled\n", i, width, t->desc);
  510. continue;
  511. }
  512. pr_info("%2d: %-*s:", i, width, t->desc);
  513. if (intlist__find(skiplist, i)) {
  514. color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n");
  515. continue;
  516. }
  517. if (!t->subtest.get_nr) {
  518. test_and_print(t, false, -1);
  519. } else {
  520. int subn = t->subtest.get_nr();
  521. /*
  522. * minus 2 to align with normal testcases.
  523. * For subtest we print additional '.x' in number.
  524. * for example:
  525. *
  526. * 35: Test LLVM searching and compiling :
  527. * 35.1: Basic BPF llvm compiling test : Ok
  528. */
  529. int subw = width > 2 ? width - 2 : width;
  530. bool skip = false;
  531. int subi;
  532. if (subn <= 0) {
  533. color_fprintf(stderr, PERF_COLOR_YELLOW,
  534. " Skip (not compiled in)\n");
  535. continue;
  536. }
  537. pr_info("\n");
  538. for (subi = 0; subi < subn; subi++) {
  539. int len = strlen(t->subtest.get_desc(subi));
  540. if (subw < len)
  541. subw = len;
  542. }
  543. for (subi = 0; subi < subn; subi++) {
  544. pr_info("%2d.%1d: %-*s:", i, subi + 1, subw,
  545. t->subtest.get_desc(subi));
  546. err = test_and_print(t, skip, subi);
  547. if (err != TEST_OK && t->subtest.skip_if_fail)
  548. skip = true;
  549. }
  550. }
  551. }
  552. return run_shell_tests(argc, argv, i, width);
  553. }
  554. static int perf_test__list_shell(int argc, const char **argv, int i)
  555. {
  556. DIR *dir;
  557. struct dirent *ent;
  558. char path_dir[PATH_MAX];
  559. const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
  560. if (path == NULL)
  561. return -1;
  562. dir = opendir(path);
  563. if (!dir)
  564. return -1;
  565. for_each_shell_test(dir, path, ent) {
  566. int curr = i++;
  567. char bf[256];
  568. struct test t = {
  569. .desc = shell_test__description(bf, sizeof(bf), path, ent->d_name),
  570. };
  571. if (!perf_test__matches(&t, curr, argc, argv))
  572. continue;
  573. pr_info("%2d: %s\n", i, t.desc);
  574. }
  575. closedir(dir);
  576. return 0;
  577. }
  578. static int perf_test__list(int argc, const char **argv)
  579. {
  580. unsigned int j;
  581. struct test *t;
  582. int i = 0;
  583. for_each_test(j, t) {
  584. int curr = i++;
  585. if (!perf_test__matches(t, curr, argc, argv) ||
  586. (t->is_supported && !t->is_supported()))
  587. continue;
  588. pr_info("%2d: %s\n", i, t->desc);
  589. if (t->subtest.get_nr) {
  590. int subn = t->subtest.get_nr();
  591. int subi;
  592. for (subi = 0; subi < subn; subi++)
  593. pr_info("%2d:%1d: %s\n", i, subi + 1,
  594. t->subtest.get_desc(subi));
  595. }
  596. }
  597. perf_test__list_shell(argc, argv, i);
  598. return 0;
  599. }
  600. int cmd_test(int argc, const char **argv)
  601. {
  602. const char *test_usage[] = {
  603. "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
  604. NULL,
  605. };
  606. const char *skip = NULL;
  607. const struct option test_options[] = {
  608. OPT_STRING('s', "skip", &skip, "tests", "tests to skip"),
  609. OPT_INCR('v', "verbose", &verbose,
  610. "be more verbose (show symbol address, etc)"),
  611. OPT_BOOLEAN('F', "dont-fork", &dont_fork,
  612. "Do not fork for testcase"),
  613. OPT_END()
  614. };
  615. const char * const test_subcommands[] = { "list", NULL };
  616. struct intlist *skiplist = NULL;
  617. int ret = hists__init();
  618. if (ret < 0)
  619. return ret;
  620. argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0);
  621. if (argc >= 1 && !strcmp(argv[0], "list"))
  622. return perf_test__list(argc - 1, argv + 1);
  623. symbol_conf.priv_size = sizeof(int);
  624. symbol_conf.sort_by_name = true;
  625. symbol_conf.try_vmlinux_path = true;
  626. if (symbol__init(NULL) < 0)
  627. return -1;
  628. if (skip != NULL)
  629. skiplist = intlist__new(skip);
  630. return __cmd_test(argc, argv, skiplist);
  631. }