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