xref: /openbmc/linux/tools/perf/tests/builtin-test.c (revision d68f0365087395fe232e39ac9c8ee53627522c3c)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2945aea22SJiri Olsa /*
3945aea22SJiri Olsa  * builtin-test.c
4945aea22SJiri Olsa  *
5945aea22SJiri Olsa  * Builtin regression testing command: ever growing number of sanity tests
6945aea22SJiri Olsa  */
7c23c2a0fSArnaldo Carvalho de Melo #include <fcntl.h>
8a43783aeSArnaldo Carvalho de Melo #include <errno.h>
90d8a5faaSJiri Olsa #include <unistd.h>
100d8a5faaSJiri Olsa #include <string.h>
11f2a39fe8SArnaldo Carvalho de Melo #include <stdlib.h>
121209b273SArnaldo Carvalho de Melo #include <sys/types.h>
131209b273SArnaldo Carvalho de Melo #include <dirent.h>
144208735dSArnaldo Carvalho de Melo #include <sys/wait.h>
151209b273SArnaldo Carvalho de Melo #include <sys/stat.h>
16945aea22SJiri Olsa #include "builtin.h"
17a635fc51SArnaldo Carvalho de Melo #include "hist.h"
182ae82878SArnaldo Carvalho de Melo #include "intlist.h"
190a4e1ae6SJiri Olsa #include "tests.h"
20c81251e8SJiri Olsa #include "debug.h"
21c81251e8SJiri Olsa #include "color.h"
224b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
231209b273SArnaldo Carvalho de Melo #include "string2.h"
24c81251e8SJiri Olsa #include "symbol.h"
25d3280ce0SArnaldo Carvalho de Melo #include "util/rlimit.h"
26877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h>
273ca43b60SArnaldo Carvalho de Melo #include <linux/string.h>
281209b273SArnaldo Carvalho de Melo #include <subcmd/exec-cmd.h>
29eb7261f1SRiccardo Mancini #include <linux/zalloc.h>
30945aea22SJiri Olsa 
317fa9b8fbSJiri Olsa static bool dont_fork;
327fa9b8fbSJiri Olsa 
33df225205SIan Rogers struct test *__weak arch_tests[] = {
34df225205SIan Rogers 	NULL,
3531b6753fSMatt Fleming };
3631b6753fSMatt Fleming 
37df225205SIan Rogers static struct test *generic_tests[] = {
38*d68f0365SIan Rogers 	&suite__vmlinux_matches_kallsyms,
39*d68f0365SIan Rogers 	&suite__openat_syscall_event,
40*d68f0365SIan Rogers 	&suite__openat_syscall_event_on_all_cpus,
41*d68f0365SIan Rogers 	&suite__basic_mmap,
42*d68f0365SIan Rogers 	&suite__mem,
43*d68f0365SIan Rogers 	&suite__parse_events,
44*d68f0365SIan Rogers 	&suite__expr,
45*d68f0365SIan Rogers 	&suite__PERF_RECORD,
46*d68f0365SIan Rogers 	&suite__pmu,
47*d68f0365SIan Rogers 	&suite__pmu_events,
48*d68f0365SIan Rogers 	&suite__dso_data,
49*d68f0365SIan Rogers 	&suite__dso_data_cache,
50*d68f0365SIan Rogers 	&suite__dso_data_reopen,
51*d68f0365SIan Rogers 	&suite__perf_evsel__roundtrip_name_test,
52*d68f0365SIan Rogers 	&suite__perf_evsel__tp_sched_test,
53*d68f0365SIan Rogers 	&suite__syscall_openat_tp_fields,
54*d68f0365SIan Rogers 	&suite__attr,
55*d68f0365SIan Rogers 	&suite__hists_link,
56*d68f0365SIan Rogers 	&suite__python_use,
57*d68f0365SIan Rogers 	&suite__bp_signal,
58*d68f0365SIan Rogers 	&suite__bp_signal_overflow,
59*d68f0365SIan Rogers 	&suite__bp_accounting,
60*d68f0365SIan Rogers 	&suite__wp,
61*d68f0365SIan Rogers 	&suite__task_exit,
62*d68f0365SIan Rogers 	&suite__sw_clock_freq,
63*d68f0365SIan Rogers 	&suite__code_reading,
64*d68f0365SIan Rogers 	&suite__sample_parsing,
65*d68f0365SIan Rogers 	&suite__keep_tracking,
66*d68f0365SIan Rogers 	&suite__parse_no_sample_id_all,
67*d68f0365SIan Rogers 	&suite__hists_filter,
68*d68f0365SIan Rogers 	&suite__mmap_thread_lookup,
69*d68f0365SIan Rogers 	&suite__thread_maps_share,
70*d68f0365SIan Rogers 	&suite__hists_output,
71*d68f0365SIan Rogers 	&suite__hists_cumulate,
72*d68f0365SIan Rogers 	&suite__switch_tracking,
73*d68f0365SIan Rogers 	&suite__fdarray__filter,
74*d68f0365SIan Rogers 	&suite__fdarray__add,
75*d68f0365SIan Rogers 	&suite__kmod_path__parse,
76*d68f0365SIan Rogers 	&suite__thread_map,
77*d68f0365SIan Rogers 	&suite__llvm,
78*d68f0365SIan Rogers 	&suite__session_topology,
79*d68f0365SIan Rogers 	&suite__bpf,
80*d68f0365SIan Rogers 	&suite__thread_map_synthesize,
81*d68f0365SIan Rogers 	&suite__thread_map_remove,
82*d68f0365SIan Rogers 	&suite__cpu_map_synthesize,
83*d68f0365SIan Rogers 	&suite__synthesize_stat_config,
84*d68f0365SIan Rogers 	&suite__synthesize_stat,
85*d68f0365SIan Rogers 	&suite__synthesize_stat_round,
86*d68f0365SIan Rogers 	&suite__event_update,
87*d68f0365SIan Rogers 	&suite__event_times,
88*d68f0365SIan Rogers 	&suite__backward_ring_buffer,
89*d68f0365SIan Rogers 	&suite__cpu_map_print,
90*d68f0365SIan Rogers 	&suite__cpu_map_merge,
91*d68f0365SIan Rogers 	&suite__sdt_event,
92*d68f0365SIan Rogers 	&suite__is_printable_array,
93*d68f0365SIan Rogers 	&suite__bitmap_print,
94*d68f0365SIan Rogers 	&suite__perf_hooks,
95*d68f0365SIan Rogers 	&suite__clang,
96*d68f0365SIan Rogers 	&suite__unit_number__scnprint,
97*d68f0365SIan Rogers 	&suite__mem2node,
98*d68f0365SIan Rogers 	&suite__time_utils,
99*d68f0365SIan Rogers 	&suite__jit_write_elf,
100*d68f0365SIan Rogers 	&suite__pfm,
101*d68f0365SIan Rogers 	&suite__api_io,
102*d68f0365SIan Rogers 	&suite__maps__merge_in,
103*d68f0365SIan Rogers 	&suite__demangle_java,
104*d68f0365SIan Rogers 	&suite__demangle_ocaml,
105*d68f0365SIan Rogers 	&suite__parse_metric,
106*d68f0365SIan Rogers 	&suite__pe_file_parsing,
107*d68f0365SIan Rogers 	&suite__expand_cgroup_events,
108*d68f0365SIan Rogers 	&suite__perf_time_to_tsc,
109*d68f0365SIan Rogers 	&suite__dlfilter,
110df225205SIan Rogers 	NULL,
111945aea22SJiri Olsa };
112945aea22SJiri Olsa 
113df225205SIan Rogers static struct test **tests[] = {
11431b6753fSMatt Fleming 	generic_tests,
11531b6753fSMatt Fleming 	arch_tests,
11631b6753fSMatt Fleming };
11731b6753fSMatt Fleming 
118d685e6c1SJiri Olsa static bool perf_test__matches(const char *desc, int curr, int argc, const char *argv[])
119945aea22SJiri Olsa {
120945aea22SJiri Olsa 	int i;
121945aea22SJiri Olsa 
122945aea22SJiri Olsa 	if (argc == 0)
123945aea22SJiri Olsa 		return true;
124945aea22SJiri Olsa 
125945aea22SJiri Olsa 	for (i = 0; i < argc; ++i) {
126945aea22SJiri Olsa 		char *end;
127945aea22SJiri Olsa 		long nr = strtoul(argv[i], &end, 10);
128945aea22SJiri Olsa 
129945aea22SJiri Olsa 		if (*end == '\0') {
130945aea22SJiri Olsa 			if (nr == curr + 1)
131945aea22SJiri Olsa 				return true;
132945aea22SJiri Olsa 			continue;
133945aea22SJiri Olsa 		}
134945aea22SJiri Olsa 
135d685e6c1SJiri Olsa 		if (strcasestr(desc, argv[i]))
136945aea22SJiri Olsa 			return true;
137945aea22SJiri Olsa 	}
138945aea22SJiri Olsa 
139945aea22SJiri Olsa 	return false;
140945aea22SJiri Olsa }
141945aea22SJiri Olsa 
142721a1f53SArnaldo Carvalho de Melo static int run_test(struct test *test, int subtest)
1430d8a5faaSJiri Olsa {
1447fa9b8fbSJiri Olsa 	int status, err = -1, child = dont_fork ? 0 : fork();
145ba3dfff8SMasami Hiramatsu 	char sbuf[STRERR_BUFSIZE];
1460d8a5faaSJiri Olsa 
1470d8a5faaSJiri Olsa 	if (child < 0) {
148ba3dfff8SMasami Hiramatsu 		pr_err("failed to fork test: %s\n",
149c8b5f2c9SArnaldo Carvalho de Melo 			str_error_r(errno, sbuf, sizeof(sbuf)));
1500d8a5faaSJiri Olsa 		return -1;
1510d8a5faaSJiri Olsa 	}
1520d8a5faaSJiri Olsa 
1530d8a5faaSJiri Olsa 	if (!child) {
1547fa9b8fbSJiri Olsa 		if (!dont_fork) {
1550d8a5faaSJiri Olsa 			pr_debug("test child forked, pid %d\n", getpid());
1567fa9b8fbSJiri Olsa 
157bb963e16SNamhyung Kim 			if (verbose <= 0) {
1585bcf2fe0SWang Nan 				int nullfd = open("/dev/null", O_WRONLY);
1597fa9b8fbSJiri Olsa 
1605bcf2fe0SWang Nan 				if (nullfd >= 0) {
1615bcf2fe0SWang Nan 					close(STDERR_FILENO);
1625bcf2fe0SWang Nan 					close(STDOUT_FILENO);
1635bcf2fe0SWang Nan 
1645bcf2fe0SWang Nan 					dup2(nullfd, STDOUT_FILENO);
1655bcf2fe0SWang Nan 					dup2(STDOUT_FILENO, STDERR_FILENO);
1665bcf2fe0SWang Nan 					close(nullfd);
1675bcf2fe0SWang Nan 				}
168b6847d2cSArnaldo Carvalho de Melo 			} else {
169b6847d2cSArnaldo Carvalho de Melo 				signal(SIGSEGV, sighandler_dump_stack);
170b6847d2cSArnaldo Carvalho de Melo 				signal(SIGFPE, sighandler_dump_stack);
1715bcf2fe0SWang Nan 			}
1727fa9b8fbSJiri Olsa 		}
1735bcf2fe0SWang Nan 
17481f17c90SArnaldo Carvalho de Melo 		err = test->func(test, subtest);
1757fa9b8fbSJiri Olsa 		if (!dont_fork)
1760d8a5faaSJiri Olsa 			exit(err);
1770d8a5faaSJiri Olsa 	}
1780d8a5faaSJiri Olsa 
1797fa9b8fbSJiri Olsa 	if (!dont_fork) {
1800d8a5faaSJiri Olsa 		wait(&status);
1810d8a5faaSJiri Olsa 
1820d8a5faaSJiri Olsa 		if (WIFEXITED(status)) {
183189c466fSHe Kuang 			err = (signed char)WEXITSTATUS(status);
1840d8a5faaSJiri Olsa 			pr_debug("test child finished with %d\n", err);
1850d8a5faaSJiri Olsa 		} else if (WIFSIGNALED(status)) {
1860d8a5faaSJiri Olsa 			err = -1;
1870d8a5faaSJiri Olsa 			pr_debug("test child interrupted\n");
1880d8a5faaSJiri Olsa 		}
1897fa9b8fbSJiri Olsa 	}
1900d8a5faaSJiri Olsa 
1910d8a5faaSJiri Olsa 	return err;
1920d8a5faaSJiri Olsa }
1930d8a5faaSJiri Olsa 
194df225205SIan Rogers #define for_each_test(j, k, t)			\
19531b6753fSMatt Fleming 	for (j = 0; j < ARRAY_SIZE(tests); j++)	\
196df225205SIan Rogers 		for (k = 0, t = tests[j][k]; tests[j][k]; k++, t = tests[j][k])
197e8210cefSMatt Fleming 
198e8c6d500SWang Nan static int test_and_print(struct test *t, bool force_skip, int subtest)
199e8c6d500SWang Nan {
200e8c6d500SWang Nan 	int err;
201e8c6d500SWang Nan 
202e8c6d500SWang Nan 	if (!force_skip) {
203e8c6d500SWang Nan 		pr_debug("\n--- start ---\n");
204e8c6d500SWang Nan 		err = run_test(t, subtest);
205e8c6d500SWang Nan 		pr_debug("---- end ----\n");
206e8c6d500SWang Nan 	} else {
207e8c6d500SWang Nan 		pr_debug("\n--- force skipped ---\n");
208e8c6d500SWang Nan 		err = TEST_SKIP;
209e8c6d500SWang Nan 	}
210e8c6d500SWang Nan 
211e8c6d500SWang Nan 	if (!t->subtest.get_nr)
212e8c6d500SWang Nan 		pr_debug("%s:", t->desc);
213e8c6d500SWang Nan 	else
214aa90f9f9SSandipan Das 		pr_debug("%s subtest %d:", t->desc, subtest + 1);
215e8c6d500SWang Nan 
216e8c6d500SWang Nan 	switch (err) {
217e8c6d500SWang Nan 	case TEST_OK:
218e8c6d500SWang Nan 		pr_info(" Ok\n");
219e8c6d500SWang Nan 		break;
2203b536651SIan Rogers 	case TEST_SKIP: {
2213b536651SIan Rogers 		const char *skip_reason = NULL;
2223b536651SIan Rogers 		if (t->subtest.skip_reason)
2233b536651SIan Rogers 			skip_reason = t->subtest.skip_reason(subtest);
2243b536651SIan Rogers 		if (skip_reason)
2253b536651SIan Rogers 			color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (%s)\n", skip_reason);
2263b536651SIan Rogers 		else
227e8c6d500SWang Nan 			color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n");
2283b536651SIan Rogers 	}
229e8c6d500SWang Nan 		break;
230e8c6d500SWang Nan 	case TEST_FAIL:
231e8c6d500SWang Nan 	default:
232e8c6d500SWang Nan 		color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n");
233e8c6d500SWang Nan 		break;
234e8c6d500SWang Nan 	}
235e8c6d500SWang Nan 
236e8c6d500SWang Nan 	return err;
237e8c6d500SWang Nan }
238e8c6d500SWang Nan 
2391209b273SArnaldo Carvalho de Melo static const char *shell_test__description(char *description, size_t size,
2401209b273SArnaldo Carvalho de Melo 					   const char *path, const char *name)
2411209b273SArnaldo Carvalho de Melo {
2421209b273SArnaldo Carvalho de Melo 	FILE *fp;
2431209b273SArnaldo Carvalho de Melo 	char filename[PATH_MAX];
2441209b273SArnaldo Carvalho de Melo 
2451209b273SArnaldo Carvalho de Melo 	path__join(filename, sizeof(filename), path, name);
2461209b273SArnaldo Carvalho de Melo 	fp = fopen(filename, "r");
2471209b273SArnaldo Carvalho de Melo 	if (!fp)
2481209b273SArnaldo Carvalho de Melo 		return NULL;
2491209b273SArnaldo Carvalho de Melo 
2504eaf97e8SMichael Petlan 	/* Skip shebang */
2514eaf97e8SMichael Petlan 	while (fgetc(fp) != '\n');
2524eaf97e8SMichael Petlan 
2531209b273SArnaldo Carvalho de Melo 	description = fgets(description, size, fp);
2541209b273SArnaldo Carvalho de Melo 	fclose(fp);
2551209b273SArnaldo Carvalho de Melo 
2563ca43b60SArnaldo Carvalho de Melo 	return description ? strim(description + 1) : NULL;
2571209b273SArnaldo Carvalho de Melo }
2581209b273SArnaldo Carvalho de Melo 
259da963834SRiccardo Mancini #define for_each_shell_test(entlist, nr, base, ent)	                \
260da963834SRiccardo Mancini 	for (int __i = 0; __i < nr && (ent = entlist[__i]); __i++)	\
261db8fec58SKim Phillips 		if (!is_directory(base, ent) && ent->d_name[0] != '.')
2621209b273SArnaldo Carvalho de Melo 
2631209b273SArnaldo Carvalho de Melo static const char *shell_tests__dir(char *path, size_t size)
2641209b273SArnaldo Carvalho de Melo {
2651209b273SArnaldo Carvalho de Melo 	const char *devel_dirs[] = { "./tools/perf/tests", "./tests", };
2661209b273SArnaldo Carvalho de Melo         char *exec_path;
2671209b273SArnaldo Carvalho de Melo 	unsigned int i;
2681209b273SArnaldo Carvalho de Melo 
2691209b273SArnaldo Carvalho de Melo 	for (i = 0; i < ARRAY_SIZE(devel_dirs); ++i) {
2701209b273SArnaldo Carvalho de Melo 		struct stat st;
2711209b273SArnaldo Carvalho de Melo 		if (!lstat(devel_dirs[i], &st)) {
2721209b273SArnaldo Carvalho de Melo 			scnprintf(path, size, "%s/shell", devel_dirs[i]);
2731209b273SArnaldo Carvalho de Melo 			if (!lstat(devel_dirs[i], &st))
2741209b273SArnaldo Carvalho de Melo 				return path;
2751209b273SArnaldo Carvalho de Melo 		}
2761209b273SArnaldo Carvalho de Melo 	}
2771209b273SArnaldo Carvalho de Melo 
2781209b273SArnaldo Carvalho de Melo         /* Then installed path. */
2791209b273SArnaldo Carvalho de Melo         exec_path = get_argv_exec_path();
2801209b273SArnaldo Carvalho de Melo         scnprintf(path, size, "%s/tests/shell", exec_path);
2811209b273SArnaldo Carvalho de Melo 	free(exec_path);
2821209b273SArnaldo Carvalho de Melo 	return path;
2831209b273SArnaldo Carvalho de Melo }
2841209b273SArnaldo Carvalho de Melo 
2851209b273SArnaldo Carvalho de Melo static int shell_tests__max_desc_width(void)
2861209b273SArnaldo Carvalho de Melo {
287da963834SRiccardo Mancini 	struct dirent **entlist;
2881209b273SArnaldo Carvalho de Melo 	struct dirent *ent;
289eb7261f1SRiccardo Mancini 	int n_dirs, e;
2901209b273SArnaldo Carvalho de Melo 	char path_dir[PATH_MAX];
2911209b273SArnaldo Carvalho de Melo 	const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
2921209b273SArnaldo Carvalho de Melo 	int width = 0;
2931209b273SArnaldo Carvalho de Melo 
2941209b273SArnaldo Carvalho de Melo 	if (path == NULL)
2951209b273SArnaldo Carvalho de Melo 		return -1;
2961209b273SArnaldo Carvalho de Melo 
297da963834SRiccardo Mancini 	n_dirs = scandir(path, &entlist, NULL, alphasort);
298da963834SRiccardo Mancini 	if (n_dirs == -1)
2991209b273SArnaldo Carvalho de Melo 		return -1;
3001209b273SArnaldo Carvalho de Melo 
301da963834SRiccardo Mancini 	for_each_shell_test(entlist, n_dirs, path, ent) {
3021209b273SArnaldo Carvalho de Melo 		char bf[256];
3031209b273SArnaldo Carvalho de Melo 		const char *desc = shell_test__description(bf, sizeof(bf), path, ent->d_name);
3041209b273SArnaldo Carvalho de Melo 
3051209b273SArnaldo Carvalho de Melo 		if (desc) {
3061209b273SArnaldo Carvalho de Melo 			int len = strlen(desc);
3071209b273SArnaldo Carvalho de Melo 
3081209b273SArnaldo Carvalho de Melo 			if (width < len)
3091209b273SArnaldo Carvalho de Melo 				width = len;
3101209b273SArnaldo Carvalho de Melo 		}
3111209b273SArnaldo Carvalho de Melo 	}
3121209b273SArnaldo Carvalho de Melo 
313eb7261f1SRiccardo Mancini 	for (e = 0; e < n_dirs; e++)
314eb7261f1SRiccardo Mancini 		zfree(&entlist[e]);
315da963834SRiccardo Mancini 	free(entlist);
3161209b273SArnaldo Carvalho de Melo 	return width;
3171209b273SArnaldo Carvalho de Melo }
3181209b273SArnaldo Carvalho de Melo 
3191209b273SArnaldo Carvalho de Melo struct shell_test {
3201209b273SArnaldo Carvalho de Melo 	const char *dir;
3211209b273SArnaldo Carvalho de Melo 	const char *file;
3221209b273SArnaldo Carvalho de Melo };
3231209b273SArnaldo Carvalho de Melo 
3241209b273SArnaldo Carvalho de Melo static int shell_test__run(struct test *test, int subdir __maybe_unused)
3251209b273SArnaldo Carvalho de Melo {
3261209b273SArnaldo Carvalho de Melo 	int err;
3271209b273SArnaldo Carvalho de Melo 	char script[PATH_MAX];
3281209b273SArnaldo Carvalho de Melo 	struct shell_test *st = test->priv;
3291209b273SArnaldo Carvalho de Melo 
330e3c9cfd0SIan Rogers 	path__join(script, sizeof(script) - 3, st->dir, st->file);
331e3c9cfd0SIan Rogers 
332e3c9cfd0SIan Rogers 	if (verbose)
333e3c9cfd0SIan Rogers 		strncat(script, " -v", sizeof(script) - strlen(script) - 1);
3341209b273SArnaldo Carvalho de Melo 
3351209b273SArnaldo Carvalho de Melo 	err = system(script);
3361209b273SArnaldo Carvalho de Melo 	if (!err)
3371209b273SArnaldo Carvalho de Melo 		return TEST_OK;
3381209b273SArnaldo Carvalho de Melo 
3391209b273SArnaldo Carvalho de Melo 	return WEXITSTATUS(err) == 2 ? TEST_SKIP : TEST_FAIL;
3401209b273SArnaldo Carvalho de Melo }
3411209b273SArnaldo Carvalho de Melo 
342ebdf90a4SRiccardo Mancini static int run_shell_tests(int argc, const char *argv[], int i, int width,
343ebdf90a4SRiccardo Mancini 				struct intlist *skiplist)
3441209b273SArnaldo Carvalho de Melo {
345da963834SRiccardo Mancini 	struct dirent **entlist;
3461209b273SArnaldo Carvalho de Melo 	struct dirent *ent;
347eb7261f1SRiccardo Mancini 	int n_dirs, e;
3481209b273SArnaldo Carvalho de Melo 	char path_dir[PATH_MAX];
3491209b273SArnaldo Carvalho de Melo 	struct shell_test st = {
3501209b273SArnaldo Carvalho de Melo 		.dir = shell_tests__dir(path_dir, sizeof(path_dir)),
3511209b273SArnaldo Carvalho de Melo 	};
3521209b273SArnaldo Carvalho de Melo 
3531209b273SArnaldo Carvalho de Melo 	if (st.dir == NULL)
3541209b273SArnaldo Carvalho de Melo 		return -1;
3551209b273SArnaldo Carvalho de Melo 
356da963834SRiccardo Mancini 	n_dirs = scandir(st.dir, &entlist, NULL, alphasort);
357da963834SRiccardo Mancini 	if (n_dirs == -1) {
358b2bf6660SIan Rogers 		pr_err("failed to open shell test directory: %s\n",
359b2bf6660SIan Rogers 			st.dir);
3601209b273SArnaldo Carvalho de Melo 		return -1;
361b2bf6660SIan Rogers 	}
3621209b273SArnaldo Carvalho de Melo 
363da963834SRiccardo Mancini 	for_each_shell_test(entlist, n_dirs, st.dir, ent) {
3641209b273SArnaldo Carvalho de Melo 		int curr = i++;
3651209b273SArnaldo Carvalho de Melo 		char desc[256];
3661209b273SArnaldo Carvalho de Melo 		struct test test = {
3671209b273SArnaldo Carvalho de Melo 			.desc = shell_test__description(desc, sizeof(desc), st.dir, ent->d_name),
3681209b273SArnaldo Carvalho de Melo 			.func = shell_test__run,
3691209b273SArnaldo Carvalho de Melo 			.priv = &st,
3701209b273SArnaldo Carvalho de Melo 		};
3711209b273SArnaldo Carvalho de Melo 
372d685e6c1SJiri Olsa 		if (!perf_test__matches(test.desc, curr, argc, argv))
3731209b273SArnaldo Carvalho de Melo 			continue;
3741209b273SArnaldo Carvalho de Melo 
3751209b273SArnaldo Carvalho de Melo 		st.file = ent->d_name;
3761209b273SArnaldo Carvalho de Melo 		pr_info("%2d: %-*s:", i, width, test.desc);
377ebdf90a4SRiccardo Mancini 
378ebdf90a4SRiccardo Mancini 		if (intlist__find(skiplist, i)) {
379ebdf90a4SRiccardo Mancini 			color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n");
380ebdf90a4SRiccardo Mancini 			continue;
381ebdf90a4SRiccardo Mancini 		}
382ebdf90a4SRiccardo Mancini 
3831209b273SArnaldo Carvalho de Melo 		test_and_print(&test, false, -1);
3841209b273SArnaldo Carvalho de Melo 	}
3851209b273SArnaldo Carvalho de Melo 
386eb7261f1SRiccardo Mancini 	for (e = 0; e < n_dirs; e++)
387eb7261f1SRiccardo Mancini 		zfree(&entlist[e]);
388da963834SRiccardo Mancini 	free(entlist);
3891209b273SArnaldo Carvalho de Melo 	return 0;
3901209b273SArnaldo Carvalho de Melo }
3911209b273SArnaldo Carvalho de Melo 
3922ae82878SArnaldo Carvalho de Melo static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
393945aea22SJiri Olsa {
394e8210cefSMatt Fleming 	struct test *t;
395df225205SIan Rogers 	unsigned int j, k;
396945aea22SJiri Olsa 	int i = 0;
3971209b273SArnaldo Carvalho de Melo 	int width = shell_tests__max_desc_width();
398945aea22SJiri Olsa 
399df225205SIan Rogers 	for_each_test(j, k, t) {
400e8210cefSMatt Fleming 		int len = strlen(t->desc);
401945aea22SJiri Olsa 
402945aea22SJiri Olsa 		if (width < len)
403945aea22SJiri Olsa 			width = len;
404945aea22SJiri Olsa 	}
405945aea22SJiri Olsa 
406df225205SIan Rogers 	for_each_test(j, k, t) {
407945aea22SJiri Olsa 		int curr = i++, err;
408d685e6c1SJiri Olsa 		int subi;
409945aea22SJiri Olsa 
410d685e6c1SJiri Olsa 		if (!perf_test__matches(t->desc, curr, argc, argv)) {
411d685e6c1SJiri Olsa 			bool skip = true;
412d685e6c1SJiri Olsa 			int subn;
413d685e6c1SJiri Olsa 
414d685e6c1SJiri Olsa 			if (!t->subtest.get_nr)
415945aea22SJiri Olsa 				continue;
416945aea22SJiri Olsa 
417d685e6c1SJiri Olsa 			subn = t->subtest.get_nr();
418d685e6c1SJiri Olsa 
419d685e6c1SJiri Olsa 			for (subi = 0; subi < subn; subi++) {
420d685e6c1SJiri Olsa 				if (perf_test__matches(t->subtest.get_desc(subi), curr, argc, argv))
421d685e6c1SJiri Olsa 					skip = false;
422d685e6c1SJiri Olsa 			}
423d685e6c1SJiri Olsa 
424d685e6c1SJiri Olsa 			if (skip)
425d685e6c1SJiri Olsa 				continue;
426d685e6c1SJiri Olsa 		}
427d685e6c1SJiri Olsa 
428598762cfSJiri Olsa 		if (t->is_supported && !t->is_supported()) {
429598762cfSJiri Olsa 			pr_debug("%2d: %-*s: Disabled\n", i, width, t->desc);
430598762cfSJiri Olsa 			continue;
431598762cfSJiri Olsa 		}
432598762cfSJiri Olsa 
433e8210cefSMatt Fleming 		pr_info("%2d: %-*s:", i, width, t->desc);
4342ae82878SArnaldo Carvalho de Melo 
4352ae82878SArnaldo Carvalho de Melo 		if (intlist__find(skiplist, i)) {
4362ae82878SArnaldo Carvalho de Melo 			color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n");
4372ae82878SArnaldo Carvalho de Melo 			continue;
4382ae82878SArnaldo Carvalho de Melo 		}
4392ae82878SArnaldo Carvalho de Melo 
440e8c6d500SWang Nan 		if (!t->subtest.get_nr) {
441e8c6d500SWang Nan 			test_and_print(t, false, -1);
442e8c6d500SWang Nan 		} else {
443e8c6d500SWang Nan 			int subn = t->subtest.get_nr();
444e8c6d500SWang Nan 			/*
445e8c6d500SWang Nan 			 * minus 2 to align with normal testcases.
446e8c6d500SWang Nan 			 * For subtest we print additional '.x' in number.
447e8c6d500SWang Nan 			 * for example:
448e8c6d500SWang Nan 			 *
449e8c6d500SWang Nan 			 * 35: Test LLVM searching and compiling                        :
450e8c6d500SWang Nan 			 * 35.1: Basic BPF llvm compiling test                          : Ok
451e8c6d500SWang Nan 			 */
452e8c6d500SWang Nan 			int subw = width > 2 ? width - 2 : width;
453e8c6d500SWang Nan 			bool skip = false;
454f4c1ea5fSJiri Olsa 
455e8c6d500SWang Nan 			if (subn <= 0) {
456e8c6d500SWang Nan 				color_fprintf(stderr, PERF_COLOR_YELLOW,
457e8c6d500SWang Nan 					      " Skip (not compiled in)\n");
458e8c6d500SWang Nan 				continue;
459e8c6d500SWang Nan 			}
460e8c6d500SWang Nan 			pr_info("\n");
461e8c6d500SWang Nan 
462e8c6d500SWang Nan 			for (subi = 0; subi < subn; subi++) {
463e8c6d500SWang Nan 				int len = strlen(t->subtest.get_desc(subi));
464e8c6d500SWang Nan 
465e8c6d500SWang Nan 				if (subw < len)
466e8c6d500SWang Nan 					subw = len;
467e8c6d500SWang Nan 			}
468e8c6d500SWang Nan 
469e8c6d500SWang Nan 			for (subi = 0; subi < subn; subi++) {
470d685e6c1SJiri Olsa 				if (!perf_test__matches(t->subtest.get_desc(subi), curr, argc, argv))
471d685e6c1SJiri Olsa 					continue;
472d685e6c1SJiri Olsa 
473e8c6d500SWang Nan 				pr_info("%2d.%1d: %-*s:", i, subi + 1, subw,
474e8c6d500SWang Nan 					t->subtest.get_desc(subi));
475aa90f9f9SSandipan Das 				err = test_and_print(t, skip, subi);
476e8c6d500SWang Nan 				if (err != TEST_OK && t->subtest.skip_if_fail)
477e8c6d500SWang Nan 					skip = true;
478e8c6d500SWang Nan 			}
479f4c1ea5fSJiri Olsa 		}
480945aea22SJiri Olsa 	}
481945aea22SJiri Olsa 
482ebdf90a4SRiccardo Mancini 	return run_shell_tests(argc, argv, i, width, skiplist);
4831209b273SArnaldo Carvalho de Melo }
4841209b273SArnaldo Carvalho de Melo 
4851209b273SArnaldo Carvalho de Melo static int perf_test__list_shell(int argc, const char **argv, int i)
4861209b273SArnaldo Carvalho de Melo {
487da963834SRiccardo Mancini 	struct dirent **entlist;
4881209b273SArnaldo Carvalho de Melo 	struct dirent *ent;
489eb7261f1SRiccardo Mancini 	int n_dirs, e;
4901209b273SArnaldo Carvalho de Melo 	char path_dir[PATH_MAX];
4911209b273SArnaldo Carvalho de Melo 	const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
4921209b273SArnaldo Carvalho de Melo 
4931209b273SArnaldo Carvalho de Melo 	if (path == NULL)
4941209b273SArnaldo Carvalho de Melo 		return -1;
4951209b273SArnaldo Carvalho de Melo 
496da963834SRiccardo Mancini 	n_dirs = scandir(path, &entlist, NULL, alphasort);
497da963834SRiccardo Mancini 	if (n_dirs == -1)
4981209b273SArnaldo Carvalho de Melo 		return -1;
4991209b273SArnaldo Carvalho de Melo 
500da963834SRiccardo Mancini 	for_each_shell_test(entlist, n_dirs, path, ent) {
5016d02acc1SArnaldo Carvalho de Melo 		int curr = i++;
5021209b273SArnaldo Carvalho de Melo 		char bf[256];
5036d02acc1SArnaldo Carvalho de Melo 		struct test t = {
5046d02acc1SArnaldo Carvalho de Melo 			.desc = shell_test__description(bf, sizeof(bf), path, ent->d_name),
5056d02acc1SArnaldo Carvalho de Melo 		};
5061209b273SArnaldo Carvalho de Melo 
507d685e6c1SJiri Olsa 		if (!perf_test__matches(t.desc, curr, argc, argv))
5081209b273SArnaldo Carvalho de Melo 			continue;
5091209b273SArnaldo Carvalho de Melo 
5106d02acc1SArnaldo Carvalho de Melo 		pr_info("%2d: %s\n", i, t.desc);
511eb7261f1SRiccardo Mancini 
5121209b273SArnaldo Carvalho de Melo 	}
5131209b273SArnaldo Carvalho de Melo 
514eb7261f1SRiccardo Mancini 	for (e = 0; e < n_dirs; e++)
515eb7261f1SRiccardo Mancini 		zfree(&entlist[e]);
516da963834SRiccardo Mancini 	free(entlist);
517945aea22SJiri Olsa 	return 0;
518945aea22SJiri Olsa }
519945aea22SJiri Olsa 
520945aea22SJiri Olsa static int perf_test__list(int argc, const char **argv)
521945aea22SJiri Olsa {
522df225205SIan Rogers 	unsigned int j, k;
523e8210cefSMatt Fleming 	struct test *t;
524945aea22SJiri Olsa 	int i = 0;
525945aea22SJiri Olsa 
526df225205SIan Rogers 	for_each_test(j, k, t) {
5276d02acc1SArnaldo Carvalho de Melo 		int curr = i++;
52828765bf2SArnaldo Carvalho de Melo 
529d685e6c1SJiri Olsa 		if (!perf_test__matches(t->desc, curr, argc, argv) ||
5306d02acc1SArnaldo Carvalho de Melo 		    (t->is_supported && !t->is_supported()))
531945aea22SJiri Olsa 			continue;
532945aea22SJiri Olsa 
53328765bf2SArnaldo Carvalho de Melo 		pr_info("%2d: %s\n", i, t->desc);
534ea40b6d3SHendrik Brueckner 
535ea40b6d3SHendrik Brueckner 		if (t->subtest.get_nr) {
536ea40b6d3SHendrik Brueckner 			int subn = t->subtest.get_nr();
537ea40b6d3SHendrik Brueckner 			int subi;
538ea40b6d3SHendrik Brueckner 
539ea40b6d3SHendrik Brueckner 			for (subi = 0; subi < subn; subi++)
540ea40b6d3SHendrik Brueckner 				pr_info("%2d:%1d: %s\n", i, subi + 1,
541ea40b6d3SHendrik Brueckner 					t->subtest.get_desc(subi));
542ea40b6d3SHendrik Brueckner 		}
543945aea22SJiri Olsa 	}
544945aea22SJiri Olsa 
5451209b273SArnaldo Carvalho de Melo 	perf_test__list_shell(argc, argv, i);
5461209b273SArnaldo Carvalho de Melo 
547945aea22SJiri Olsa 	return 0;
548945aea22SJiri Olsa }
549945aea22SJiri Olsa 
550b0ad8ea6SArnaldo Carvalho de Melo int cmd_test(int argc, const char **argv)
551945aea22SJiri Olsa {
5521f9975f1SYunlong Song 	const char *test_usage[] = {
553945aea22SJiri Olsa 	"perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
554945aea22SJiri Olsa 	NULL,
555945aea22SJiri Olsa 	};
5562ae82878SArnaldo Carvalho de Melo 	const char *skip = NULL;
557945aea22SJiri Olsa 	const struct option test_options[] = {
5582ae82878SArnaldo Carvalho de Melo 	OPT_STRING('s', "skip", &skip, "tests", "tests to skip"),
559945aea22SJiri Olsa 	OPT_INCR('v', "verbose", &verbose,
560945aea22SJiri Olsa 		    "be more verbose (show symbol address, etc)"),
5617fa9b8fbSJiri Olsa 	OPT_BOOLEAN('F', "dont-fork", &dont_fork,
5627fa9b8fbSJiri Olsa 		    "Do not fork for testcase"),
563945aea22SJiri Olsa 	OPT_END()
564945aea22SJiri Olsa 	};
5651f9975f1SYunlong Song 	const char * const test_subcommands[] = { "list", NULL };
5662ae82878SArnaldo Carvalho de Melo 	struct intlist *skiplist = NULL;
567a635fc51SArnaldo Carvalho de Melo         int ret = hists__init();
568a635fc51SArnaldo Carvalho de Melo 
569a635fc51SArnaldo Carvalho de Melo         if (ret < 0)
570a635fc51SArnaldo Carvalho de Melo                 return ret;
571945aea22SJiri Olsa 
5721f9975f1SYunlong Song 	argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0);
573945aea22SJiri Olsa 	if (argc >= 1 && !strcmp(argv[0], "list"))
5746d02acc1SArnaldo Carvalho de Melo 		return perf_test__list(argc - 1, argv + 1);
575945aea22SJiri Olsa 
576945aea22SJiri Olsa 	symbol_conf.priv_size = sizeof(int);
577945aea22SJiri Olsa 	symbol_conf.sort_by_name = true;
578945aea22SJiri Olsa 	symbol_conf.try_vmlinux_path = true;
579945aea22SJiri Olsa 
5800a7e6d1bSNamhyung Kim 	if (symbol__init(NULL) < 0)
581945aea22SJiri Olsa 		return -1;
582945aea22SJiri Olsa 
5832ae82878SArnaldo Carvalho de Melo 	if (skip != NULL)
5842ae82878SArnaldo Carvalho de Melo 		skiplist = intlist__new(skip);
585d3280ce0SArnaldo Carvalho de Melo 	/*
586d3280ce0SArnaldo Carvalho de Melo 	 * Tests that create BPF maps, for instance, need more than the 64K
587d3280ce0SArnaldo Carvalho de Melo 	 * default:
588d3280ce0SArnaldo Carvalho de Melo 	 */
589d3280ce0SArnaldo Carvalho de Melo 	rlimit__bump_memlock();
5902ae82878SArnaldo Carvalho de Melo 
5912ae82878SArnaldo Carvalho de Melo 	return __cmd_test(argc, argv, skiplist);
592945aea22SJiri Olsa }
593