Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/*
2 * builtin-test.c
3 *
4 * Builtin regression testing command: ever growing number of sanity tests
5 */
6#include "builtin.h"
7#include "tests.h"
8#include "debug.h"
9#include "color.h"
10#include "parse-options.h"
11#include "symbol.h"
12
13static struct test {
14 const char *desc;
15 int (*func)(void);
16} tests[] = {
17 {
18 .desc = "vmlinux symtab matches kallsyms",
19 .func = test__vmlinux_matches_kallsyms,
20 },
21 {
22 .desc = "detect open syscall event",
23 .func = test__open_syscall_event,
24 },
25 {
26 .desc = "detect open syscall event on all cpus",
27 .func = test__open_syscall_event_on_all_cpus,
28 },
29 {
30 .desc = "read samples using the mmap interface",
31 .func = test__basic_mmap,
32 },
33 {
34 .desc = "parse events tests",
35 .func = test__parse_events,
36 },
37#if defined(__x86_64__) || defined(__i386__)
38 {
39 .desc = "x86 rdpmc test",
40 .func = test__rdpmc,
41 },
42#endif
43 {
44 .desc = "Validate PERF_RECORD_* events & perf_sample fields",
45 .func = test__PERF_RECORD,
46 },
47 {
48 .desc = "Test perf pmu format parsing",
49 .func = test__pmu,
50 },
51 {
52 .desc = "Test dso data interface",
53 .func = test__dso_data,
54 },
55 {
56 .desc = "roundtrip evsel->name check",
57 .func = test__perf_evsel__roundtrip_name_test,
58 },
59 {
60 .desc = "Check parsing of sched tracepoints fields",
61 .func = test__perf_evsel__tp_sched_test,
62 },
63 {
64 .desc = "Generate and check syscalls:sys_enter_open event fields",
65 .func = test__syscall_open_tp_fields,
66 },
67 {
68 .desc = "struct perf_event_attr setup",
69 .func = test__attr,
70 },
71 {
72 .func = NULL,
73 },
74};
75
76static bool perf_test__matches(int curr, int argc, const char *argv[])
77{
78 int i;
79
80 if (argc == 0)
81 return true;
82
83 for (i = 0; i < argc; ++i) {
84 char *end;
85 long nr = strtoul(argv[i], &end, 10);
86
87 if (*end == '\0') {
88 if (nr == curr + 1)
89 return true;
90 continue;
91 }
92
93 if (strstr(tests[curr].desc, argv[i]))
94 return true;
95 }
96
97 return false;
98}
99
100static int __cmd_test(int argc, const char *argv[])
101{
102 int i = 0;
103 int width = 0;
104
105 while (tests[i].func) {
106 int len = strlen(tests[i].desc);
107
108 if (width < len)
109 width = len;
110 ++i;
111 }
112
113 i = 0;
114 while (tests[i].func) {
115 int curr = i++, err;
116
117 if (!perf_test__matches(curr, argc, argv))
118 continue;
119
120 pr_info("%2d: %-*s:", i, width, tests[curr].desc);
121 pr_debug("\n--- start ---\n");
122 err = tests[curr].func();
123 pr_debug("---- end ----\n%s:", tests[curr].desc);
124 if (err)
125 color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n");
126 else
127 pr_info(" Ok\n");
128 }
129
130 return 0;
131}
132
133static int perf_test__list(int argc, const char **argv)
134{
135 int i = 0;
136
137 while (tests[i].func) {
138 int curr = i++;
139
140 if (argc > 1 && !strstr(tests[curr].desc, argv[1]))
141 continue;
142
143 pr_info("%2d: %s\n", i, tests[curr].desc);
144 }
145
146 return 0;
147}
148
149int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
150{
151 const char * const test_usage[] = {
152 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
153 NULL,
154 };
155 const struct option test_options[] = {
156 OPT_INCR('v', "verbose", &verbose,
157 "be more verbose (show symbol address, etc)"),
158 OPT_END()
159 };
160
161 argc = parse_options(argc, argv, test_options, test_usage, 0);
162 if (argc >= 1 && !strcmp(argv[0], "list"))
163 return perf_test__list(argc, argv);
164
165 symbol_conf.priv_size = sizeof(int);
166 symbol_conf.sort_by_name = true;
167 symbol_conf.try_vmlinux_path = true;
168
169 if (symbol__init() < 0)
170 return -1;
171
172 return __cmd_test(argc, argv);
173}