xref: /linux/tools/perf/tests/builtin-test.c (revision b889fcf63cb62e7fdb7816565e28f44dbe4a76a5)
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 
13 static 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 
76 static 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 
100 static 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 
133 static 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 
149 int 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 }
174