builtin-test.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. * builtin-test.c
  3. *
  4. * Builtin regression testing command: ever growing number of sanity tests
  5. */
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include "builtin.h"
  9. #include "hist.h"
  10. #include "intlist.h"
  11. #include "tests.h"
  12. #include "debug.h"
  13. #include "color.h"
  14. #include "parse-options.h"
  15. #include "symbol.h"
  16. struct test __weak arch_tests[] = {
  17. {
  18. .func = NULL,
  19. },
  20. };
  21. static struct test generic_tests[] = {
  22. {
  23. .desc = "vmlinux symtab matches kallsyms",
  24. .func = test__vmlinux_matches_kallsyms,
  25. },
  26. {
  27. .desc = "detect openat syscall event",
  28. .func = test__openat_syscall_event,
  29. },
  30. {
  31. .desc = "detect openat syscall event on all cpus",
  32. .func = test__openat_syscall_event_on_all_cpus,
  33. },
  34. {
  35. .desc = "read samples using the mmap interface",
  36. .func = test__basic_mmap,
  37. },
  38. {
  39. .desc = "parse events tests",
  40. .func = test__parse_events,
  41. },
  42. {
  43. .desc = "Validate PERF_RECORD_* events & perf_sample fields",
  44. .func = test__PERF_RECORD,
  45. },
  46. {
  47. .desc = "Test perf pmu format parsing",
  48. .func = test__pmu,
  49. },
  50. {
  51. .desc = "Test dso data read",
  52. .func = test__dso_data,
  53. },
  54. {
  55. .desc = "Test dso data cache",
  56. .func = test__dso_data_cache,
  57. },
  58. {
  59. .desc = "Test dso data reopen",
  60. .func = test__dso_data_reopen,
  61. },
  62. {
  63. .desc = "roundtrip evsel->name check",
  64. .func = test__perf_evsel__roundtrip_name_test,
  65. },
  66. {
  67. .desc = "Check parsing of sched tracepoints fields",
  68. .func = test__perf_evsel__tp_sched_test,
  69. },
  70. {
  71. .desc = "Generate and check syscalls:sys_enter_openat event fields",
  72. .func = test__syscall_openat_tp_fields,
  73. },
  74. {
  75. .desc = "struct perf_event_attr setup",
  76. .func = test__attr,
  77. },
  78. {
  79. .desc = "Test matching and linking multiple hists",
  80. .func = test__hists_link,
  81. },
  82. {
  83. .desc = "Try 'import perf' in python, checking link problems",
  84. .func = test__python_use,
  85. },
  86. {
  87. .desc = "Test breakpoint overflow signal handler",
  88. .func = test__bp_signal,
  89. },
  90. {
  91. .desc = "Test breakpoint overflow sampling",
  92. .func = test__bp_signal_overflow,
  93. },
  94. {
  95. .desc = "Test number of exit event of a simple workload",
  96. .func = test__task_exit,
  97. },
  98. {
  99. .desc = "Test software clock events have valid period values",
  100. .func = test__sw_clock_freq,
  101. },
  102. {
  103. .desc = "Test object code reading",
  104. .func = test__code_reading,
  105. },
  106. {
  107. .desc = "Test sample parsing",
  108. .func = test__sample_parsing,
  109. },
  110. {
  111. .desc = "Test using a dummy software event to keep tracking",
  112. .func = test__keep_tracking,
  113. },
  114. {
  115. .desc = "Test parsing with no sample_id_all bit set",
  116. .func = test__parse_no_sample_id_all,
  117. },
  118. {
  119. .desc = "Test filtering hist entries",
  120. .func = test__hists_filter,
  121. },
  122. {
  123. .desc = "Test mmap thread lookup",
  124. .func = test__mmap_thread_lookup,
  125. },
  126. {
  127. .desc = "Test thread mg sharing",
  128. .func = test__thread_mg_share,
  129. },
  130. {
  131. .desc = "Test output sorting of hist entries",
  132. .func = test__hists_output,
  133. },
  134. {
  135. .desc = "Test cumulation of child hist entries",
  136. .func = test__hists_cumulate,
  137. },
  138. {
  139. .desc = "Test tracking with sched_switch",
  140. .func = test__switch_tracking,
  141. },
  142. {
  143. .desc = "Filter fds with revents mask in a fdarray",
  144. .func = test__fdarray__filter,
  145. },
  146. {
  147. .desc = "Add fd to a fdarray, making it autogrow",
  148. .func = test__fdarray__add,
  149. },
  150. {
  151. .desc = "Test kmod_path__parse function",
  152. .func = test__kmod_path__parse,
  153. },
  154. {
  155. .desc = "Test thread map",
  156. .func = test__thread_map,
  157. },
  158. {
  159. .desc = "Test LLVM searching and compiling",
  160. .func = test__llvm,
  161. },
  162. {
  163. .desc = "Test topology in session",
  164. .func = test_session_topology,
  165. },
  166. {
  167. .desc = "Test BPF filter",
  168. .func = test__bpf,
  169. },
  170. {
  171. .func = NULL,
  172. },
  173. };
  174. static struct test *tests[] = {
  175. generic_tests,
  176. arch_tests,
  177. };
  178. static bool perf_test__matches(struct test *test, int curr, int argc, const char *argv[])
  179. {
  180. int i;
  181. if (argc == 0)
  182. return true;
  183. for (i = 0; i < argc; ++i) {
  184. char *end;
  185. long nr = strtoul(argv[i], &end, 10);
  186. if (*end == '\0') {
  187. if (nr == curr + 1)
  188. return true;
  189. continue;
  190. }
  191. if (strcasestr(test->desc, argv[i]))
  192. return true;
  193. }
  194. return false;
  195. }
  196. static int run_test(struct test *test)
  197. {
  198. int status, err = -1, child = fork();
  199. char sbuf[STRERR_BUFSIZE];
  200. if (child < 0) {
  201. pr_err("failed to fork test: %s\n",
  202. strerror_r(errno, sbuf, sizeof(sbuf)));
  203. return -1;
  204. }
  205. if (!child) {
  206. pr_debug("test child forked, pid %d\n", getpid());
  207. err = test->func();
  208. exit(err);
  209. }
  210. wait(&status);
  211. if (WIFEXITED(status)) {
  212. err = (signed char)WEXITSTATUS(status);
  213. pr_debug("test child finished with %d\n", err);
  214. } else if (WIFSIGNALED(status)) {
  215. err = -1;
  216. pr_debug("test child interrupted\n");
  217. }
  218. return err;
  219. }
  220. #define for_each_test(j, t) \
  221. for (j = 0; j < ARRAY_SIZE(tests); j++) \
  222. for (t = &tests[j][0]; t->func; t++)
  223. static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
  224. {
  225. struct test *t;
  226. unsigned int j;
  227. int i = 0;
  228. int width = 0;
  229. for_each_test(j, t) {
  230. int len = strlen(t->desc);
  231. if (width < len)
  232. width = len;
  233. }
  234. for_each_test(j, t) {
  235. int curr = i++, err;
  236. if (!perf_test__matches(t, curr, argc, argv))
  237. continue;
  238. pr_info("%2d: %-*s:", i, width, t->desc);
  239. if (intlist__find(skiplist, i)) {
  240. color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n");
  241. continue;
  242. }
  243. pr_debug("\n--- start ---\n");
  244. err = run_test(t);
  245. pr_debug("---- end ----\n%s:", t->desc);
  246. switch (err) {
  247. case TEST_OK:
  248. pr_info(" Ok\n");
  249. break;
  250. case TEST_SKIP:
  251. color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n");
  252. break;
  253. case TEST_FAIL:
  254. default:
  255. color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n");
  256. break;
  257. }
  258. }
  259. return 0;
  260. }
  261. static int perf_test__list(int argc, const char **argv)
  262. {
  263. unsigned int j;
  264. struct test *t;
  265. int i = 0;
  266. for_each_test(j, t) {
  267. if (argc > 1 && !strstr(t->desc, argv[1]))
  268. continue;
  269. pr_info("%2d: %s\n", ++i, t->desc);
  270. }
  271. return 0;
  272. }
  273. int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
  274. {
  275. const char *test_usage[] = {
  276. "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
  277. NULL,
  278. };
  279. const char *skip = NULL;
  280. const struct option test_options[] = {
  281. OPT_STRING('s', "skip", &skip, "tests", "tests to skip"),
  282. OPT_INCR('v', "verbose", &verbose,
  283. "be more verbose (show symbol address, etc)"),
  284. OPT_END()
  285. };
  286. const char * const test_subcommands[] = { "list", NULL };
  287. struct intlist *skiplist = NULL;
  288. int ret = hists__init();
  289. if (ret < 0)
  290. return ret;
  291. argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0);
  292. if (argc >= 1 && !strcmp(argv[0], "list"))
  293. return perf_test__list(argc, argv);
  294. symbol_conf.priv_size = sizeof(int);
  295. symbol_conf.sort_by_name = true;
  296. symbol_conf.try_vmlinux_path = true;
  297. if (symbol__init(NULL) < 0)
  298. return -1;
  299. if (skip != NULL)
  300. skiplist = intlist__new(skip);
  301. return __cmd_test(argc, argv, skiplist);
  302. }