blob: 93f5e9176e68f0b308e72aae6292c5d0a4939835 [file] [log] [blame]
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -03001/*
2 * builtin-test.c
3 *
4 * Builtin regression testing command: ever growing number of sanity tests
5 */
6#include "builtin.h"
7
8#include "util/cache.h"
Arnaldo Carvalho de Melo9a8e85a2012-10-24 15:44:41 -02009#include "util/color.h"
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -030010#include "util/debug.h"
Arnaldo Carvalho de Meloebf294b2011-11-16 14:03:07 -020011#include "util/debugfs.h"
Arnaldo Carvalho de Melode5fa3a2011-01-15 10:42:46 -020012#include "util/evlist.h"
Arnaldo Carvalho de Melo69d25912012-11-09 11:32:52 -030013#include "util/machine.h"
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -030014#include "util/parse-options.h"
Arnaldo Carvalho de Melode5fa3a2011-01-15 10:42:46 -020015#include "util/parse-events.h"
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -030016#include "util/symbol.h"
Arnaldo Carvalho de Melofd782602011-01-18 15:15:24 -020017#include "util/thread_map.h"
Jiri Olsacd82a322012-03-15 20:09:17 +010018#include "util/pmu.h"
Arnaldo Carvalho de Melo6a6cd112012-09-18 11:56:28 -030019#include "event-parse.h"
Jiri Olsa13b62562011-07-14 11:25:33 +020020#include "../../include/linux/hw_breakpoint.h"
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -030021
Peter Zijlstra08aa0d12011-11-21 14:42:47 +010022#include <sys/mman.h>
23
Arnaldo Carvalho de Melo02522082011-01-04 11:55:27 -020024#include "util/cpumap.h"
Arnaldo Carvalho de Melod8548612011-01-04 00:16:20 -020025#include "util/evsel.h"
26#include <sys/types.h>
27
Jiri Olsa0a4e1ae2012-11-10 01:46:41 +010028#include "tests.h"
29
Arnaldo Carvalho de Melo02522082011-01-04 11:55:27 -020030#include <sched.h>
31
Arnaldo Carvalho de Melo02522082011-01-04 11:55:27 -020032
Jiri Olsacd82a322012-03-15 20:09:17 +010033static int test__perf_pmu(void)
34{
35 return perf_pmu__test();
36}
37
Arnaldo Carvalho de Melo6a6cd112012-09-18 11:56:28 -030038static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
39 int size, bool should_be_signed)
40{
41 struct format_field *field = perf_evsel__field(evsel, name);
42 int is_signed;
43 int ret = 0;
44
45 if (field == NULL) {
46 pr_debug("%s: \"%s\" field not found!\n", evsel->name, name);
47 return -1;
48 }
49
50 is_signed = !!(field->flags | FIELD_IS_SIGNED);
51 if (should_be_signed && !is_signed) {
52 pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
53 evsel->name, name, is_signed, should_be_signed);
54 ret = -1;
55 }
56
57 if (field->size != size) {
58 pr_debug("%s: \"%s\" size (%d) should be %d!\n",
59 evsel->name, name, field->size, size);
60 ret = -1;
61 }
62
Namhyung Kimaf9da882012-09-25 11:20:28 +090063 return ret;
Arnaldo Carvalho de Melo6a6cd112012-09-18 11:56:28 -030064}
65
66static int perf_evsel__tp_sched_test(void)
67{
68 struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0);
69 int ret = 0;
70
71 if (evsel == NULL) {
72 pr_debug("perf_evsel__new\n");
73 return -1;
74 }
75
76 if (perf_evsel__test_field(evsel, "prev_comm", 16, true))
77 ret = -1;
78
79 if (perf_evsel__test_field(evsel, "prev_pid", 4, true))
80 ret = -1;
81
82 if (perf_evsel__test_field(evsel, "prev_prio", 4, true))
83 ret = -1;
84
85 if (perf_evsel__test_field(evsel, "prev_state", 8, true))
86 ret = -1;
87
88 if (perf_evsel__test_field(evsel, "next_comm", 16, true))
89 ret = -1;
90
91 if (perf_evsel__test_field(evsel, "next_pid", 4, true))
92 ret = -1;
93
94 if (perf_evsel__test_field(evsel, "next_prio", 4, true))
95 ret = -1;
96
97 perf_evsel__delete(evsel);
98
99 evsel = perf_evsel__newtp("sched", "sched_wakeup", 0);
100
101 if (perf_evsel__test_field(evsel, "comm", 16, true))
102 ret = -1;
103
104 if (perf_evsel__test_field(evsel, "pid", 4, true))
105 ret = -1;
106
107 if (perf_evsel__test_field(evsel, "prio", 4, true))
108 ret = -1;
109
110 if (perf_evsel__test_field(evsel, "success", 4, true))
111 ret = -1;
112
113 if (perf_evsel__test_field(evsel, "target_cpu", 4, true))
114 ret = -1;
115
Namhyung Kimaf9da882012-09-25 11:20:28 +0900116 return ret;
Arnaldo Carvalho de Melo6a6cd112012-09-18 11:56:28 -0300117}
118
Arnaldo Carvalho de Meloeb2f2702012-09-26 13:23:10 -0300119static int test__syscall_open_tp_fields(void)
120{
121 struct perf_record_opts opts = {
122 .target = {
123 .uid = UINT_MAX,
124 .uses_mmap = true,
125 },
126 .no_delay = true,
127 .freq = 1,
128 .mmap_pages = 256,
129 .raw_samples = true,
130 };
131 const char *filename = "/etc/passwd";
132 int flags = O_RDONLY | O_DIRECTORY;
133 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
134 struct perf_evsel *evsel;
135 int err = -1, i, nr_events = 0, nr_polls = 0;
136
137 if (evlist == NULL) {
138 pr_debug("%s: perf_evlist__new\n", __func__);
139 goto out;
140 }
141
142 evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
143 if (evsel == NULL) {
144 pr_debug("%s: perf_evsel__newtp\n", __func__);
145 goto out_delete_evlist;
146 }
147
148 perf_evlist__add(evlist, evsel);
149
150 err = perf_evlist__create_maps(evlist, &opts.target);
151 if (err < 0) {
152 pr_debug("%s: perf_evlist__create_maps\n", __func__);
153 goto out_delete_evlist;
154 }
155
156 perf_evsel__config(evsel, &opts, evsel);
157
158 evlist->threads->map[0] = getpid();
159
160 err = perf_evlist__open(evlist);
161 if (err < 0) {
162 pr_debug("perf_evlist__open: %s\n", strerror(errno));
163 goto out_delete_evlist;
164 }
165
166 err = perf_evlist__mmap(evlist, UINT_MAX, false);
167 if (err < 0) {
168 pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
169 goto out_delete_evlist;
170 }
171
172 perf_evlist__enable(evlist);
173
174 /*
Jiri Olsa945aea22012-10-30 23:01:43 +0100175 * Generate the event:
176 */
Arnaldo Carvalho de Meloeb2f2702012-09-26 13:23:10 -0300177 open(filename, flags);
178
179 while (1) {
180 int before = nr_events;
181
182 for (i = 0; i < evlist->nr_mmaps; i++) {
183 union perf_event *event;
184
185 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
186 const u32 type = event->header.type;
187 int tp_flags;
188 struct perf_sample sample;
189
190 ++nr_events;
191
192 if (type != PERF_RECORD_SAMPLE)
193 continue;
194
195 err = perf_evsel__parse_sample(evsel, event, &sample);
196 if (err) {
197 pr_err("Can't parse sample, err = %d\n", err);
198 goto out_munmap;
199 }
200
201 tp_flags = perf_evsel__intval(evsel, &sample, "flags");
202
203 if (flags != tp_flags) {
204 pr_debug("%s: Expected flags=%#x, got %#x\n",
205 __func__, flags, tp_flags);
206 goto out_munmap;
207 }
208
209 goto out_ok;
210 }
211 }
212
213 if (nr_events == before)
214 poll(evlist->pollfd, evlist->nr_fds, 10);
215
216 if (++nr_polls > 5) {
217 pr_debug("%s: no events!\n", __func__);
218 goto out_munmap;
219 }
220 }
221out_ok:
222 err = 0;
223out_munmap:
224 perf_evlist__munmap(evlist);
225out_delete_evlist:
226 perf_evlist__delete(evlist);
227out:
228 return err;
229}
230
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -0300231static struct test {
232 const char *desc;
233 int (*func)(void);
234} tests[] = {
235 {
236 .desc = "vmlinux symtab matches kallsyms",
237 .func = test__vmlinux_matches_kallsyms,
238 },
239 {
Arnaldo Carvalho de Melod8548612011-01-04 00:16:20 -0200240 .desc = "detect open syscall event",
241 .func = test__open_syscall_event,
242 },
243 {
Arnaldo Carvalho de Melo02522082011-01-04 11:55:27 -0200244 .desc = "detect open syscall event on all cpus",
245 .func = test__open_syscall_event_on_all_cpus,
246 },
247 {
Arnaldo Carvalho de Melode5fa3a2011-01-15 10:42:46 -0200248 .desc = "read samples using the mmap interface",
249 .func = test__basic_mmap,
250 },
251 {
Jiri Olsa13b62562011-07-14 11:25:33 +0200252 .desc = "parse events tests",
Jiri Olsaf50246e2012-05-21 09:12:49 +0200253 .func = parse_events__test,
Jiri Olsa13b62562011-07-14 11:25:33 +0200254 },
Peter Zijlstra08aa0d12011-11-21 14:42:47 +0100255#if defined(__x86_64__) || defined(__i386__)
256 {
257 .desc = "x86 rdpmc test",
258 .func = test__rdpmc,
259 },
260#endif
Jiri Olsa13b62562011-07-14 11:25:33 +0200261 {
Arnaldo Carvalho de Melo3e7c4392011-12-02 11:13:50 -0200262 .desc = "Validate PERF_RECORD_* events & perf_sample fields",
263 .func = test__PERF_RECORD,
264 },
265 {
Jiri Olsacd82a322012-03-15 20:09:17 +0100266 .desc = "Test perf pmu format parsing",
267 .func = test__perf_pmu,
268 },
269 {
Jiri Olsaf7add552012-07-22 14:14:40 +0200270 .desc = "Test dso data interface",
271 .func = dso__test_data,
272 },
273 {
Arnaldo Carvalho de Melo8ad70132012-09-06 13:11:18 -0300274 .desc = "roundtrip evsel->name check",
Jiri Olsacfffae22012-11-10 01:46:47 +0100275 .func = test__perf_evsel__roundtrip_name_test,
Arnaldo Carvalho de Melo8ad70132012-09-06 13:11:18 -0300276 },
277 {
Arnaldo Carvalho de Melo6a6cd112012-09-18 11:56:28 -0300278 .desc = "Check parsing of sched tracepoints fields",
279 .func = perf_evsel__tp_sched_test,
280 },
281 {
Arnaldo Carvalho de Meloeb2f2702012-09-26 13:23:10 -0300282 .desc = "Generate and check syscalls:sys_enter_open event fields",
283 .func = test__syscall_open_tp_fields,
284 },
285 {
Jiri Olsad898b242012-10-30 23:02:05 +0100286 .desc = "struct perf_event_attr setup",
287 .func = test_attr__run,
288 },
289 {
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -0300290 .func = NULL,
291 },
292};
293
Arnaldo Carvalho de Meloe60770a2011-11-29 12:52:07 -0200294static bool perf_test__matches(int curr, int argc, const char *argv[])
295{
296 int i;
297
298 if (argc == 0)
299 return true;
300
301 for (i = 0; i < argc; ++i) {
302 char *end;
303 long nr = strtoul(argv[i], &end, 10);
304
305 if (*end == '\0') {
306 if (nr == curr + 1)
307 return true;
308 continue;
309 }
310
311 if (strstr(tests[curr].desc, argv[i]))
312 return true;
313 }
314
315 return false;
316}
317
318static int __cmd_test(int argc, const char *argv[])
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -0300319{
320 int i = 0;
Arnaldo Carvalho de Melo9a8e85a2012-10-24 15:44:41 -0200321 int width = 0;
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -0300322
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -0300323 while (tests[i].func) {
Arnaldo Carvalho de Melo9a8e85a2012-10-24 15:44:41 -0200324 int len = strlen(tests[i].desc);
325
326 if (width < len)
327 width = len;
328 ++i;
329 }
Jiri Olsa945aea22012-10-30 23:01:43 +0100330
Arnaldo Carvalho de Melo9a8e85a2012-10-24 15:44:41 -0200331 i = 0;
332 while (tests[i].func) {
Arnaldo Carvalho de Meloe60770a2011-11-29 12:52:07 -0200333 int curr = i++, err;
334
335 if (!perf_test__matches(curr, argc, argv))
336 continue;
337
Arnaldo Carvalho de Melo9a8e85a2012-10-24 15:44:41 -0200338 pr_info("%2d: %-*s:", i, width, tests[curr].desc);
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -0300339 pr_debug("\n--- start ---\n");
Arnaldo Carvalho de Meloe60770a2011-11-29 12:52:07 -0200340 err = tests[curr].func();
341 pr_debug("---- end ----\n%s:", tests[curr].desc);
Arnaldo Carvalho de Melo9a8e85a2012-10-24 15:44:41 -0200342 if (err)
343 color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n");
344 else
345 pr_info(" Ok\n");
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -0300346 }
347
348 return 0;
349}
350
Arnaldo Carvalho de Meloe60770a2011-11-29 12:52:07 -0200351static int perf_test__list(int argc, const char **argv)
352{
353 int i = 0;
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -0300354
Arnaldo Carvalho de Meloe60770a2011-11-29 12:52:07 -0200355 while (tests[i].func) {
356 int curr = i++;
357
358 if (argc > 1 && !strstr(tests[curr].desc, argv[1]))
359 continue;
360
361 pr_info("%2d: %s\n", i, tests[curr].desc);
362 }
363
364 return 0;
365}
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -0300366
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300367int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -0300368{
Arnaldo Carvalho de Meloe60770a2011-11-29 12:52:07 -0200369 const char * const test_usage[] = {
370 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
371 NULL,
372 };
373 const struct option test_options[] = {
Namhyung Kimc30ab8a2012-01-08 02:25:26 +0900374 OPT_INCR('v', "verbose", &verbose,
Arnaldo Carvalho de Meloe60770a2011-11-29 12:52:07 -0200375 "be more verbose (show symbol address, etc)"),
376 OPT_END()
377 };
378
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -0300379 argc = parse_options(argc, argv, test_options, test_usage, 0);
Arnaldo Carvalho de Meloe60770a2011-11-29 12:52:07 -0200380 if (argc >= 1 && !strcmp(argv[0], "list"))
381 return perf_test__list(argc, argv);
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -0300382
383 symbol_conf.priv_size = sizeof(int);
384 symbol_conf.sort_by_name = true;
385 symbol_conf.try_vmlinux_path = true;
386
387 if (symbol__init() < 0)
388 return -1;
389
Arnaldo Carvalho de Meloe60770a2011-11-29 12:52:07 -0200390 return __cmd_test(argc, argv);
Arnaldo Carvalho de Melo1c6a8002010-04-29 18:58:32 -0300391}