PageRenderTime 70ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 1ms

/tools/perf/tests/builtin-test.c

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