]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - tools/perf/tests/builtin-test.c
perf tests: Move test__rdpmc into separate object
[mirror_ubuntu-artful-kernel.git] / tools / perf / tests / builtin-test.c
CommitLineData
1c6a800c
ACM
1/*
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"
9a8e85ad 9#include "util/color.h"
1c6a800c 10#include "util/debug.h"
ebf294bf 11#include "util/debugfs.h"
de5fa3a8 12#include "util/evlist.h"
69d2591a 13#include "util/machine.h"
1c6a800c 14#include "util/parse-options.h"
de5fa3a8 15#include "util/parse-events.h"
1c6a800c 16#include "util/symbol.h"
fd78260b 17#include "util/thread_map.h"
cd82a32e 18#include "util/pmu.h"
6a6cd11d 19#include "event-parse.h"
13b62567 20#include "../../include/linux/hw_breakpoint.h"
1c6a800c 21
08aa0d1f
PZ
22#include <sys/mman.h>
23
0252208e 24#include "util/cpumap.h"
d854861c
ACM
25#include "util/evsel.h"
26#include <sys/types.h>
27
0a4e1ae6
JO
28#include "tests.h"
29
0252208e
ACM
30#include <sched.h>
31
0252208e 32
cd82a32e
JO
33static int test__perf_pmu(void)
34{
35 return perf_pmu__test();
36}
37
49f20d72
ACM
38static int perf_evsel__roundtrip_cache_name_test(void)
39{
40 char name[128];
41 int type, op, err = 0, ret = 0, i, idx;
42 struct perf_evsel *evsel;
43 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
44
45 if (evlist == NULL)
46 return -ENOMEM;
47
48 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
49 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
50 /* skip invalid cache type */
51 if (!perf_evsel__is_cache_op_valid(type, op))
52 continue;
53
54 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
55 __perf_evsel__hw_cache_type_op_res_name(type, op, i,
56 name, sizeof(name));
57 err = parse_events(evlist, name, 0);
58 if (err)
59 ret = err;
60 }
61 }
62 }
63
64 idx = 0;
65 evsel = perf_evlist__first(evlist);
66
67 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
68 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
69 /* skip invalid cache type */
70 if (!perf_evsel__is_cache_op_valid(type, op))
71 continue;
72
73 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
74 __perf_evsel__hw_cache_type_op_res_name(type, op, i,
75 name, sizeof(name));
76 if (evsel->idx != idx)
77 continue;
78
79 ++idx;
80
81 if (strcmp(perf_evsel__name(evsel), name)) {
82 pr_debug("%s != %s\n", perf_evsel__name(evsel), name);
83 ret = -1;
84 }
85
86 evsel = perf_evsel__next(evsel);
87 }
88 }
89 }
90
91 perf_evlist__delete(evlist);
92 return ret;
93}
94
8ad7013b
ACM
95static int __perf_evsel__name_array_test(const char *names[], int nr_names)
96{
97 int i, err;
98 struct perf_evsel *evsel;
99 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
100
101 if (evlist == NULL)
102 return -ENOMEM;
103
104 for (i = 0; i < nr_names; ++i) {
105 err = parse_events(evlist, names[i], 0);
106 if (err) {
107 pr_debug("failed to parse event '%s', err %d\n",
108 names[i], err);
109 goto out_delete_evlist;
110 }
111 }
112
113 err = 0;
114 list_for_each_entry(evsel, &evlist->entries, node) {
115 if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) {
116 --err;
117 pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]);
118 }
119 }
120
121out_delete_evlist:
122 perf_evlist__delete(evlist);
123 return err;
124}
125
126#define perf_evsel__name_array_test(names) \
127 __perf_evsel__name_array_test(names, ARRAY_SIZE(names))
128
129static int perf_evsel__roundtrip_name_test(void)
130{
131 int err = 0, ret = 0;
132
133 err = perf_evsel__name_array_test(perf_evsel__hw_names);
134 if (err)
135 ret = err;
136
137 err = perf_evsel__name_array_test(perf_evsel__sw_names);
138 if (err)
139 ret = err;
140
49f20d72
ACM
141 err = perf_evsel__roundtrip_cache_name_test();
142 if (err)
143 ret = err;
144
8ad7013b
ACM
145 return ret;
146}
147
6a6cd11d
ACM
148static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
149 int size, bool should_be_signed)
150{
151 struct format_field *field = perf_evsel__field(evsel, name);
152 int is_signed;
153 int ret = 0;
154
155 if (field == NULL) {
156 pr_debug("%s: \"%s\" field not found!\n", evsel->name, name);
157 return -1;
158 }
159
160 is_signed = !!(field->flags | FIELD_IS_SIGNED);
161 if (should_be_signed && !is_signed) {
162 pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
163 evsel->name, name, is_signed, should_be_signed);
164 ret = -1;
165 }
166
167 if (field->size != size) {
168 pr_debug("%s: \"%s\" size (%d) should be %d!\n",
169 evsel->name, name, field->size, size);
170 ret = -1;
171 }
172
af9da88f 173 return ret;
6a6cd11d
ACM
174}
175
176static int perf_evsel__tp_sched_test(void)
177{
178 struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0);
179 int ret = 0;
180
181 if (evsel == NULL) {
182 pr_debug("perf_evsel__new\n");
183 return -1;
184 }
185
186 if (perf_evsel__test_field(evsel, "prev_comm", 16, true))
187 ret = -1;
188
189 if (perf_evsel__test_field(evsel, "prev_pid", 4, true))
190 ret = -1;
191
192 if (perf_evsel__test_field(evsel, "prev_prio", 4, true))
193 ret = -1;
194
195 if (perf_evsel__test_field(evsel, "prev_state", 8, true))
196 ret = -1;
197
198 if (perf_evsel__test_field(evsel, "next_comm", 16, true))
199 ret = -1;
200
201 if (perf_evsel__test_field(evsel, "next_pid", 4, true))
202 ret = -1;
203
204 if (perf_evsel__test_field(evsel, "next_prio", 4, true))
205 ret = -1;
206
207 perf_evsel__delete(evsel);
208
209 evsel = perf_evsel__newtp("sched", "sched_wakeup", 0);
210
211 if (perf_evsel__test_field(evsel, "comm", 16, true))
212 ret = -1;
213
214 if (perf_evsel__test_field(evsel, "pid", 4, true))
215 ret = -1;
216
217 if (perf_evsel__test_field(evsel, "prio", 4, true))
218 ret = -1;
219
220 if (perf_evsel__test_field(evsel, "success", 4, true))
221 ret = -1;
222
223 if (perf_evsel__test_field(evsel, "target_cpu", 4, true))
224 ret = -1;
225
af9da88f 226 return ret;
6a6cd11d
ACM
227}
228
eb2f2703
ACM
229static int test__syscall_open_tp_fields(void)
230{
231 struct perf_record_opts opts = {
232 .target = {
233 .uid = UINT_MAX,
234 .uses_mmap = true,
235 },
236 .no_delay = true,
237 .freq = 1,
238 .mmap_pages = 256,
239 .raw_samples = true,
240 };
241 const char *filename = "/etc/passwd";
242 int flags = O_RDONLY | O_DIRECTORY;
243 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
244 struct perf_evsel *evsel;
245 int err = -1, i, nr_events = 0, nr_polls = 0;
246
247 if (evlist == NULL) {
248 pr_debug("%s: perf_evlist__new\n", __func__);
249 goto out;
250 }
251
252 evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
253 if (evsel == NULL) {
254 pr_debug("%s: perf_evsel__newtp\n", __func__);
255 goto out_delete_evlist;
256 }
257
258 perf_evlist__add(evlist, evsel);
259
260 err = perf_evlist__create_maps(evlist, &opts.target);
261 if (err < 0) {
262 pr_debug("%s: perf_evlist__create_maps\n", __func__);
263 goto out_delete_evlist;
264 }
265
266 perf_evsel__config(evsel, &opts, evsel);
267
268 evlist->threads->map[0] = getpid();
269
270 err = perf_evlist__open(evlist);
271 if (err < 0) {
272 pr_debug("perf_evlist__open: %s\n", strerror(errno));
273 goto out_delete_evlist;
274 }
275
276 err = perf_evlist__mmap(evlist, UINT_MAX, false);
277 if (err < 0) {
278 pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
279 goto out_delete_evlist;
280 }
281
282 perf_evlist__enable(evlist);
283
284 /*
945aea22
JO
285 * Generate the event:
286 */
eb2f2703
ACM
287 open(filename, flags);
288
289 while (1) {
290 int before = nr_events;
291
292 for (i = 0; i < evlist->nr_mmaps; i++) {
293 union perf_event *event;
294
295 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
296 const u32 type = event->header.type;
297 int tp_flags;
298 struct perf_sample sample;
299
300 ++nr_events;
301
302 if (type != PERF_RECORD_SAMPLE)
303 continue;
304
305 err = perf_evsel__parse_sample(evsel, event, &sample);
306 if (err) {
307 pr_err("Can't parse sample, err = %d\n", err);
308 goto out_munmap;
309 }
310
311 tp_flags = perf_evsel__intval(evsel, &sample, "flags");
312
313 if (flags != tp_flags) {
314 pr_debug("%s: Expected flags=%#x, got %#x\n",
315 __func__, flags, tp_flags);
316 goto out_munmap;
317 }
318
319 goto out_ok;
320 }
321 }
322
323 if (nr_events == before)
324 poll(evlist->pollfd, evlist->nr_fds, 10);
325
326 if (++nr_polls > 5) {
327 pr_debug("%s: no events!\n", __func__);
328 goto out_munmap;
329 }
330 }
331out_ok:
332 err = 0;
333out_munmap:
334 perf_evlist__munmap(evlist);
335out_delete_evlist:
336 perf_evlist__delete(evlist);
337out:
338 return err;
339}
340
1c6a800c
ACM
341static struct test {
342 const char *desc;
343 int (*func)(void);
344} tests[] = {
345 {
346 .desc = "vmlinux symtab matches kallsyms",
347 .func = test__vmlinux_matches_kallsyms,
348 },
d854861c
ACM
349 {
350 .desc = "detect open syscall event",
351 .func = test__open_syscall_event,
352 },
0252208e
ACM
353 {
354 .desc = "detect open syscall event on all cpus",
355 .func = test__open_syscall_event_on_all_cpus,
356 },
de5fa3a8
ACM
357 {
358 .desc = "read samples using the mmap interface",
359 .func = test__basic_mmap,
360 },
13b62567
JO
361 {
362 .desc = "parse events tests",
f50246e2 363 .func = parse_events__test,
13b62567 364 },
08aa0d1f
PZ
365#if defined(__x86_64__) || defined(__i386__)
366 {
367 .desc = "x86 rdpmc test",
368 .func = test__rdpmc,
369 },
370#endif
3e7c439a
ACM
371 {
372 .desc = "Validate PERF_RECORD_* events & perf_sample fields",
373 .func = test__PERF_RECORD,
374 },
cd82a32e
JO
375 {
376 .desc = "Test perf pmu format parsing",
377 .func = test__perf_pmu,
378 },
f7add556
JO
379 {
380 .desc = "Test dso data interface",
381 .func = dso__test_data,
382 },
8ad7013b
ACM
383 {
384 .desc = "roundtrip evsel->name check",
385 .func = perf_evsel__roundtrip_name_test,
386 },
6a6cd11d
ACM
387 {
388 .desc = "Check parsing of sched tracepoints fields",
389 .func = perf_evsel__tp_sched_test,
390 },
eb2f2703
ACM
391 {
392 .desc = "Generate and check syscalls:sys_enter_open event fields",
393 .func = test__syscall_open_tp_fields,
394 },
d898b241
JO
395 {
396 .desc = "struct perf_event_attr setup",
397 .func = test_attr__run,
398 },
1c6a800c
ACM
399 {
400 .func = NULL,
401 },
402};
403
e60770a0 404static bool perf_test__matches(int curr, int argc, const char *argv[])
1c6a800c 405{
e60770a0
ACM
406 int i;
407
408 if (argc == 0)
409 return true;
410
411 for (i = 0; i < argc; ++i) {
412 char *end;
413 long nr = strtoul(argv[i], &end, 10);
414
415 if (*end == '\0') {
416 if (nr == curr + 1)
417 return true;
418 continue;
419 }
1c6a800c 420
e60770a0
ACM
421 if (strstr(tests[curr].desc, argv[i]))
422 return true;
423 }
424
425 return false;
426}
427
428static int __cmd_test(int argc, const char *argv[])
429{
430 int i = 0;
9a8e85ad 431 int width = 0;
1c6a800c 432
9a8e85ad
ACM
433 while (tests[i].func) {
434 int len = strlen(tests[i].desc);
435
436 if (width < len)
437 width = len;
438 ++i;
439 }
945aea22 440
9a8e85ad 441 i = 0;
1c6a800c 442 while (tests[i].func) {
e60770a0
ACM
443 int curr = i++, err;
444
445 if (!perf_test__matches(curr, argc, argv))
446 continue;
447
9a8e85ad 448 pr_info("%2d: %-*s:", i, width, tests[curr].desc);
1c6a800c 449 pr_debug("\n--- start ---\n");
e60770a0
ACM
450 err = tests[curr].func();
451 pr_debug("---- end ----\n%s:", tests[curr].desc);
9a8e85ad
ACM
452 if (err)
453 color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n");
454 else
455 pr_info(" Ok\n");
1c6a800c
ACM
456 }
457
458 return 0;
459}
460
e60770a0
ACM
461static int perf_test__list(int argc, const char **argv)
462{
463 int i = 0;
464
465 while (tests[i].func) {
466 int curr = i++;
467
468 if (argc > 1 && !strstr(tests[curr].desc, argv[1]))
469 continue;
470
471 pr_info("%2d: %s\n", i, tests[curr].desc);
472 }
473
474 return 0;
475}
1c6a800c 476
1d037ca1 477int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
e60770a0
ACM
478{
479 const char * const test_usage[] = {
480 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
481 NULL,
482 };
483 const struct option test_options[] = {
c30ab8aa 484 OPT_INCR('v', "verbose", &verbose,
1c6a800c
ACM
485 "be more verbose (show symbol address, etc)"),
486 OPT_END()
e60770a0 487 };
1c6a800c 488
1c6a800c 489 argc = parse_options(argc, argv, test_options, test_usage, 0);
e60770a0
ACM
490 if (argc >= 1 && !strcmp(argv[0], "list"))
491 return perf_test__list(argc, argv);
1c6a800c
ACM
492
493 symbol_conf.priv_size = sizeof(int);
494 symbol_conf.sort_by_name = true;
495 symbol_conf.try_vmlinux_path = true;
496
497 if (symbol__init() < 0)
498 return -1;
499
e60770a0 500 return __cmd_test(argc, argv);
1c6a800c 501}