builtin-test.c 6.0 KB
Newer Older
1 2 3 4 5
/*
 * builtin-test.c
 *
 * Builtin regression testing command: ever growing number of sanity tests
 */
6 7
#include <unistd.h>
#include <string.h>
8
#include "builtin.h"
9
#include "intlist.h"
10
#include "tests.h"
11 12 13 14
#include "debug.h"
#include "color.h"
#include "parse-options.h"
#include "symbol.h"
15

16 17 18 19 20 21 22 23
static struct test {
	const char *desc;
	int (*func)(void);
} tests[] = {
	{
		.desc = "vmlinux symtab matches kallsyms",
		.func = test__vmlinux_matches_kallsyms,
	},
24 25 26 27
	{
		.desc = "detect open syscall event",
		.func = test__open_syscall_event,
	},
28 29 30 31
	{
		.desc = "detect open syscall event on all cpus",
		.func = test__open_syscall_event_on_all_cpus,
	},
32 33 34 35
	{
		.desc = "read samples using the mmap interface",
		.func = test__basic_mmap,
	},
36 37
	{
		.desc = "parse events tests",
38
		.func = test__parse_events,
39
	},
40 41 42 43 44 45
#if defined(__x86_64__) || defined(__i386__)
	{
		.desc = "x86 rdpmc test",
		.func = test__rdpmc,
	},
#endif
46 47 48 49
	{
		.desc = "Validate PERF_RECORD_* events & perf_sample fields",
		.func = test__PERF_RECORD,
	},
50 51
	{
		.desc = "Test perf pmu format parsing",
52
		.func = test__pmu,
53
	},
54 55
	{
		.desc = "Test dso data interface",
56
		.func = test__dso_data,
57
	},
58 59
	{
		.desc = "roundtrip evsel->name check",
60
		.func = test__perf_evsel__roundtrip_name_test,
61
	},
62 63
	{
		.desc = "Check parsing of sched tracepoints fields",
64
		.func = test__perf_evsel__tp_sched_test,
65
	},
66 67 68 69
	{
		.desc = "Generate and check syscalls:sys_enter_open event fields",
		.func = test__syscall_open_tp_fields,
	},
70 71
	{
		.desc = "struct perf_event_attr setup",
72
		.func = test__attr,
73
	},
74
	{
A
Arnaldo Carvalho de Melo 已提交
75
		.desc = "Test matching and linking multiple hists",
76 77
		.func = test__hists_link,
	},
78 79 80 81
	{
		.desc = "Try 'use perf' in python, checking link problems",
		.func = test__python_use,
	},
82 83 84 85
	{
		.desc = "Test breakpoint overflow signal handler",
		.func = test__bp_signal,
	},
86 87 88 89
	{
		.desc = "Test breakpoint overflow sampling",
		.func = test__bp_signal_overflow,
	},
90 91 92 93
	{
		.desc = "Test number of exit event of a simple workload",
		.func = test__task_exit,
	},
94 95 96 97
	{
		.desc = "Test software clock events have valid period values",
		.func = test__sw_clock_freq,
	},
98 99 100 101 102 103
#if defined(__x86_64__) || defined(__i386__)
	{
		.desc = "Test converting perf time to TSC",
		.func = test__perf_time_to_tsc,
	},
#endif
104 105 106 107
	{
		.desc = "Test object code reading",
		.func = test__code_reading,
	},
108 109 110 111
	{
		.desc = "Test sample parsing",
		.func = test__sample_parsing,
	},
112 113 114 115
	{
		.desc = "Test using a dummy software event to keep tracking",
		.func = test__keep_tracking,
	},
116 117 118 119
	{
		.desc = "Test parsing with no sample_id_all bit set",
		.func = test__parse_no_sample_id_all,
	},
120
#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
121
#ifdef HAVE_DWARF_UNWIND_SUPPORT
122 123 124 125 126 127
	{
		.desc = "Test dwarf unwind",
		.func = test__dwarf_unwind,
	},
#endif
#endif
128 129 130 131
	{
		.desc = "Test filtering hist entries",
		.func = test__hists_filter,
	},
132 133 134 135
	{
		.desc = "Test mmap thread lookup",
		.func = test__mmap_thread_lookup,
	},
136 137 138 139
	{
		.desc = "Test thread mg sharing",
		.func = test__thread_mg_share,
	},
140 141 142 143
	{
		.desc = "Test output sorting of hist entries",
		.func = test__hists_output,
	},
144 145 146 147
	{
		.desc = "Test cumulation of child hist entries",
		.func = test__hists_cumulate,
	},
148 149 150 151 152
	{
		.func = NULL,
	},
};

153
static bool perf_test__matches(int curr, int argc, const char *argv[])
154
{
155 156 157 158 159 160 161 162 163 164 165 166 167 168
	int i;

	if (argc == 0)
		return true;

	for (i = 0; i < argc; ++i) {
		char *end;
		long nr = strtoul(argv[i], &end, 10);

		if (*end == '\0') {
			if (nr == curr + 1)
				return true;
			continue;
		}
169

170 171 172 173 174 175 176
		if (strstr(tests[curr].desc, argv[i]))
			return true;
	}

	return false;
}

177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
static int run_test(struct test *test)
{
	int status, err = -1, child = fork();

	if (child < 0) {
		pr_err("failed to fork test: %s\n", strerror(errno));
		return -1;
	}

	if (!child) {
		pr_debug("test child forked, pid %d\n", getpid());
		err = test->func();
		exit(err);
	}

	wait(&status);

	if (WIFEXITED(status)) {
		err = WEXITSTATUS(status);
		pr_debug("test child finished with %d\n", err);
	} else if (WIFSIGNALED(status)) {
		err = -1;
		pr_debug("test child interrupted\n");
	}

	return err;
}

205
static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
206 207
{
	int i = 0;
208
	int width = 0;
209

210 211 212 213 214 215 216
	while (tests[i].func) {
		int len = strlen(tests[i].desc);

		if (width < len)
			width = len;
		++i;
	}
217

218
	i = 0;
219
	while (tests[i].func) {
220 221 222 223 224
		int curr = i++, err;

		if (!perf_test__matches(curr, argc, argv))
			continue;

225
		pr_info("%2d: %-*s:", i, width, tests[curr].desc);
226 227 228 229 230 231

		if (intlist__find(skiplist, i)) {
			color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n");
			continue;
		}

232
		pr_debug("\n--- start ---\n");
233
		err = run_test(&tests[curr]);
234
		pr_debug("---- end ----\n%s:", tests[curr].desc);
235 236 237

		switch (err) {
		case TEST_OK:
238
			pr_info(" Ok\n");
239 240 241 242 243 244 245 246 247
			break;
		case TEST_SKIP:
			color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n");
			break;
		case TEST_FAIL:
		default:
			color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n");
			break;
		}
248 249 250 251 252
	}

	return 0;
}

253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
static int perf_test__list(int argc, const char **argv)
{
	int i = 0;

	while (tests[i].func) {
		int curr = i++;

		if (argc > 1 && !strstr(tests[curr].desc, argv[1]))
			continue;

		pr_info("%2d: %s\n", i, tests[curr].desc);
	}

	return 0;
}
268

269
int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
270 271 272 273 274
{
	const char * const test_usage[] = {
	"perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
	NULL,
	};
275
	const char *skip = NULL;
276
	const struct option test_options[] = {
277
	OPT_STRING('s', "skip", &skip, "tests", "tests to skip"),
278
	OPT_INCR('v', "verbose", &verbose,
279 280
		    "be more verbose (show symbol address, etc)"),
	OPT_END()
281
	};
282
	struct intlist *skiplist = NULL;
283 284

	argc = parse_options(argc, argv, test_options, test_usage, 0);
285 286
	if (argc >= 1 && !strcmp(argv[0], "list"))
		return perf_test__list(argc, argv);
287 288 289 290 291 292 293 294

	symbol_conf.priv_size = sizeof(int);
	symbol_conf.sort_by_name = true;
	symbol_conf.try_vmlinux_path = true;

	if (symbol__init() < 0)
		return -1;

295 296 297 298
	if (skip != NULL)
		skiplist = intlist__new(skip);

	return __cmd_test(argc, argv, skiplist);
299
}