xref: /linux/tools/perf/tests/builtin-test.c (revision 33f44bfd3c04e3559633c24b797044e849144fea)
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 	NULL,
111 };
112 
113 static struct test_suite **tests[] = {
114 	generic_tests,
115 	arch_tests,
116 };
117 
118 static bool perf_test__matches(const char *desc, int curr, int argc, const char *argv[])
119 {
120 	int i;
121 
122 	if (argc == 0)
123 		return true;
124 
125 	for (i = 0; i < argc; ++i) {
126 		char *end;
127 		long nr = strtoul(argv[i], &end, 10);
128 
129 		if (*end == '\0') {
130 			if (nr == curr + 1)
131 				return true;
132 			continue;
133 		}
134 
135 		if (strcasestr(desc, argv[i]))
136 			return true;
137 	}
138 
139 	return false;
140 }
141 
142 static int run_test(struct test_suite *test, int subtest)
143 {
144 	int status, err = -1, child = dont_fork ? 0 : fork();
145 	char sbuf[STRERR_BUFSIZE];
146 
147 	if (child < 0) {
148 		pr_err("failed to fork test: %s\n",
149 			str_error_r(errno, sbuf, sizeof(sbuf)));
150 		return -1;
151 	}
152 
153 	if (!child) {
154 		if (!dont_fork) {
155 			pr_debug("test child forked, pid %d\n", getpid());
156 
157 			if (verbose <= 0) {
158 				int nullfd = open("/dev/null", O_WRONLY);
159 
160 				if (nullfd >= 0) {
161 					close(STDERR_FILENO);
162 					close(STDOUT_FILENO);
163 
164 					dup2(nullfd, STDOUT_FILENO);
165 					dup2(STDOUT_FILENO, STDERR_FILENO);
166 					close(nullfd);
167 				}
168 			} else {
169 				signal(SIGSEGV, sighandler_dump_stack);
170 				signal(SIGFPE, sighandler_dump_stack);
171 			}
172 		}
173 
174 		err = test->func(test, subtest);
175 		if (!dont_fork)
176 			exit(err);
177 	}
178 
179 	if (!dont_fork) {
180 		wait(&status);
181 
182 		if (WIFEXITED(status)) {
183 			err = (signed char)WEXITSTATUS(status);
184 			pr_debug("test child finished with %d\n", err);
185 		} else if (WIFSIGNALED(status)) {
186 			err = -1;
187 			pr_debug("test child interrupted\n");
188 		}
189 	}
190 
191 	return err;
192 }
193 
194 #define for_each_test(j, k, t)			\
195 	for (j = 0; j < ARRAY_SIZE(tests); j++)	\
196 		for (k = 0, t = tests[j][k]; tests[j][k]; k++, t = tests[j][k])
197 
198 static int test_and_print(struct test_suite *t, bool force_skip, int subtest)
199 {
200 	int err;
201 
202 	if (!force_skip) {
203 		pr_debug("\n--- start ---\n");
204 		err = run_test(t, subtest);
205 		pr_debug("---- end ----\n");
206 	} else {
207 		pr_debug("\n--- force skipped ---\n");
208 		err = TEST_SKIP;
209 	}
210 
211 	if (!t->subtest.get_nr)
212 		pr_debug("%s:", t->desc);
213 	else
214 		pr_debug("%s subtest %d:", t->desc, subtest + 1);
215 
216 	switch (err) {
217 	case TEST_OK:
218 		pr_info(" Ok\n");
219 		break;
220 	case TEST_SKIP: {
221 		const char *skip_reason = NULL;
222 		if (t->subtest.skip_reason)
223 			skip_reason = t->subtest.skip_reason(subtest);
224 		if (skip_reason)
225 			color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (%s)\n", skip_reason);
226 		else
227 			color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n");
228 	}
229 		break;
230 	case TEST_FAIL:
231 	default:
232 		color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n");
233 		break;
234 	}
235 
236 	return err;
237 }
238 
239 static const char *shell_test__description(char *description, size_t size,
240 					   const char *path, const char *name)
241 {
242 	FILE *fp;
243 	char filename[PATH_MAX];
244 
245 	path__join(filename, sizeof(filename), path, name);
246 	fp = fopen(filename, "r");
247 	if (!fp)
248 		return NULL;
249 
250 	/* Skip shebang */
251 	while (fgetc(fp) != '\n');
252 
253 	description = fgets(description, size, fp);
254 	fclose(fp);
255 
256 	return description ? strim(description + 1) : NULL;
257 }
258 
259 #define for_each_shell_test(entlist, nr, base, ent)	                \
260 	for (int __i = 0; __i < nr && (ent = entlist[__i]); __i++)	\
261 		if (!is_directory(base, ent) && ent->d_name[0] != '.')
262 
263 static const char *shell_tests__dir(char *path, size_t size)
264 {
265 	const char *devel_dirs[] = { "./tools/perf/tests", "./tests", };
266         char *exec_path;
267 	unsigned int i;
268 
269 	for (i = 0; i < ARRAY_SIZE(devel_dirs); ++i) {
270 		struct stat st;
271 		if (!lstat(devel_dirs[i], &st)) {
272 			scnprintf(path, size, "%s/shell", devel_dirs[i]);
273 			if (!lstat(devel_dirs[i], &st))
274 				return path;
275 		}
276 	}
277 
278         /* Then installed path. */
279         exec_path = get_argv_exec_path();
280         scnprintf(path, size, "%s/tests/shell", exec_path);
281 	free(exec_path);
282 	return path;
283 }
284 
285 static int shell_tests__max_desc_width(void)
286 {
287 	struct dirent **entlist;
288 	struct dirent *ent;
289 	int n_dirs, e;
290 	char path_dir[PATH_MAX];
291 	const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
292 	int width = 0;
293 
294 	if (path == NULL)
295 		return -1;
296 
297 	n_dirs = scandir(path, &entlist, NULL, alphasort);
298 	if (n_dirs == -1)
299 		return -1;
300 
301 	for_each_shell_test(entlist, n_dirs, path, ent) {
302 		char bf[256];
303 		const char *desc = shell_test__description(bf, sizeof(bf), path, ent->d_name);
304 
305 		if (desc) {
306 			int len = strlen(desc);
307 
308 			if (width < len)
309 				width = len;
310 		}
311 	}
312 
313 	for (e = 0; e < n_dirs; e++)
314 		zfree(&entlist[e]);
315 	free(entlist);
316 	return width;
317 }
318 
319 struct shell_test {
320 	const char *dir;
321 	const char *file;
322 };
323 
324 static int shell_test__run(struct test_suite *test, int subdir __maybe_unused)
325 {
326 	int err;
327 	char script[PATH_MAX];
328 	struct shell_test *st = test->priv;
329 
330 	path__join(script, sizeof(script) - 3, st->dir, st->file);
331 
332 	if (verbose)
333 		strncat(script, " -v", sizeof(script) - strlen(script) - 1);
334 
335 	err = system(script);
336 	if (!err)
337 		return TEST_OK;
338 
339 	return WEXITSTATUS(err) == 2 ? TEST_SKIP : TEST_FAIL;
340 }
341 
342 static int run_shell_tests(int argc, const char *argv[], int i, int width,
343 				struct intlist *skiplist)
344 {
345 	struct dirent **entlist;
346 	struct dirent *ent;
347 	int n_dirs, e;
348 	char path_dir[PATH_MAX];
349 	struct shell_test st = {
350 		.dir = shell_tests__dir(path_dir, sizeof(path_dir)),
351 	};
352 
353 	if (st.dir == NULL)
354 		return -1;
355 
356 	n_dirs = scandir(st.dir, &entlist, NULL, alphasort);
357 	if (n_dirs == -1) {
358 		pr_err("failed to open shell test directory: %s\n",
359 			st.dir);
360 		return -1;
361 	}
362 
363 	for_each_shell_test(entlist, n_dirs, st.dir, ent) {
364 		int curr = i++;
365 		char desc[256];
366 		struct test_suite test = {
367 			.desc = shell_test__description(desc, sizeof(desc), st.dir, ent->d_name),
368 			.func = shell_test__run,
369 			.priv = &st,
370 		};
371 
372 		if (!perf_test__matches(test.desc, curr, argc, argv))
373 			continue;
374 
375 		st.file = ent->d_name;
376 		pr_info("%2d: %-*s:", i, width, test.desc);
377 
378 		if (intlist__find(skiplist, i)) {
379 			color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n");
380 			continue;
381 		}
382 
383 		test_and_print(&test, false, -1);
384 	}
385 
386 	for (e = 0; e < n_dirs; e++)
387 		zfree(&entlist[e]);
388 	free(entlist);
389 	return 0;
390 }
391 
392 static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
393 {
394 	struct test_suite *t;
395 	unsigned int j, k;
396 	int i = 0;
397 	int width = shell_tests__max_desc_width();
398 
399 	for_each_test(j, k, t) {
400 		int len = strlen(t->desc);
401 
402 		if (width < len)
403 			width = len;
404 	}
405 
406 	for_each_test(j, k, t) {
407 		int curr = i++, err;
408 		int subi;
409 
410 		if (!perf_test__matches(t->desc, curr, argc, argv)) {
411 			bool skip = true;
412 			int subn;
413 
414 			if (!t->subtest.get_nr)
415 				continue;
416 
417 			subn = t->subtest.get_nr();
418 
419 			for (subi = 0; subi < subn; subi++) {
420 				if (perf_test__matches(t->subtest.get_desc(subi), curr, argc, argv))
421 					skip = false;
422 			}
423 
424 			if (skip)
425 				continue;
426 		}
427 
428 		if (t->is_supported && !t->is_supported()) {
429 			pr_debug("%2d: %-*s: Disabled\n", i, width, t->desc);
430 			continue;
431 		}
432 
433 		pr_info("%2d: %-*s:", i, width, t->desc);
434 
435 		if (intlist__find(skiplist, i)) {
436 			color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n");
437 			continue;
438 		}
439 
440 		if (!t->subtest.get_nr) {
441 			test_and_print(t, false, -1);
442 		} else {
443 			int subn = t->subtest.get_nr();
444 			/*
445 			 * minus 2 to align with normal testcases.
446 			 * For subtest we print additional '.x' in number.
447 			 * for example:
448 			 *
449 			 * 35: Test LLVM searching and compiling                        :
450 			 * 35.1: Basic BPF llvm compiling test                          : Ok
451 			 */
452 			int subw = width > 2 ? width - 2 : width;
453 			bool skip = false;
454 
455 			if (subn <= 0) {
456 				color_fprintf(stderr, PERF_COLOR_YELLOW,
457 					      " Skip (not compiled in)\n");
458 				continue;
459 			}
460 			pr_info("\n");
461 
462 			for (subi = 0; subi < subn; subi++) {
463 				int len = strlen(t->subtest.get_desc(subi));
464 
465 				if (subw < len)
466 					subw = len;
467 			}
468 
469 			for (subi = 0; subi < subn; subi++) {
470 				if (!perf_test__matches(t->subtest.get_desc(subi), curr, argc, argv))
471 					continue;
472 
473 				pr_info("%2d.%1d: %-*s:", i, subi + 1, subw,
474 					t->subtest.get_desc(subi));
475 				err = test_and_print(t, skip, subi);
476 				if (err != TEST_OK && t->subtest.skip_if_fail)
477 					skip = true;
478 			}
479 		}
480 	}
481 
482 	return run_shell_tests(argc, argv, i, width, skiplist);
483 }
484 
485 static int perf_test__list_shell(int argc, const char **argv, int i)
486 {
487 	struct dirent **entlist;
488 	struct dirent *ent;
489 	int n_dirs, e;
490 	char path_dir[PATH_MAX];
491 	const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
492 
493 	if (path == NULL)
494 		return -1;
495 
496 	n_dirs = scandir(path, &entlist, NULL, alphasort);
497 	if (n_dirs == -1)
498 		return -1;
499 
500 	for_each_shell_test(entlist, n_dirs, path, ent) {
501 		int curr = i++;
502 		char bf[256];
503 		struct test_suite t = {
504 			.desc = shell_test__description(bf, sizeof(bf), path, ent->d_name),
505 		};
506 
507 		if (!perf_test__matches(t.desc, curr, argc, argv))
508 			continue;
509 
510 		pr_info("%2d: %s\n", i, t.desc);
511 
512 	}
513 
514 	for (e = 0; e < n_dirs; e++)
515 		zfree(&entlist[e]);
516 	free(entlist);
517 	return 0;
518 }
519 
520 static int perf_test__list(int argc, const char **argv)
521 {
522 	unsigned int j, k;
523 	struct test_suite *t;
524 	int i = 0;
525 
526 	for_each_test(j, k, t) {
527 		int curr = i++;
528 
529 		if (!perf_test__matches(t->desc, curr, argc, argv) ||
530 		    (t->is_supported && !t->is_supported()))
531 			continue;
532 
533 		pr_info("%2d: %s\n", i, t->desc);
534 
535 		if (t->subtest.get_nr) {
536 			int subn = t->subtest.get_nr();
537 			int subi;
538 
539 			for (subi = 0; subi < subn; subi++)
540 				pr_info("%2d:%1d: %s\n", i, subi + 1,
541 					t->subtest.get_desc(subi));
542 		}
543 	}
544 
545 	perf_test__list_shell(argc, argv, i);
546 
547 	return 0;
548 }
549 
550 int cmd_test(int argc, const char **argv)
551 {
552 	const char *test_usage[] = {
553 	"perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
554 	NULL,
555 	};
556 	const char *skip = NULL;
557 	const struct option test_options[] = {
558 	OPT_STRING('s', "skip", &skip, "tests", "tests to skip"),
559 	OPT_INCR('v', "verbose", &verbose,
560 		    "be more verbose (show symbol address, etc)"),
561 	OPT_BOOLEAN('F', "dont-fork", &dont_fork,
562 		    "Do not fork for testcase"),
563 	OPT_END()
564 	};
565 	const char * const test_subcommands[] = { "list", NULL };
566 	struct intlist *skiplist = NULL;
567         int ret = hists__init();
568 
569         if (ret < 0)
570                 return ret;
571 
572 	argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0);
573 	if (argc >= 1 && !strcmp(argv[0], "list"))
574 		return perf_test__list(argc - 1, argv + 1);
575 
576 	symbol_conf.priv_size = sizeof(int);
577 	symbol_conf.sort_by_name = true;
578 	symbol_conf.try_vmlinux_path = true;
579 
580 	if (symbol__init(NULL) < 0)
581 		return -1;
582 
583 	if (skip != NULL)
584 		skiplist = intlist__new(skip);
585 	/*
586 	 * Tests that create BPF maps, for instance, need more than the 64K
587 	 * default:
588 	 */
589 	rlimit__bump_memlock();
590 
591 	return __cmd_test(argc, argv, skiplist);
592 }
593