builtin-test.c 14 KB

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