builtin-test.c 9.5 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 "hist.h"
10
#include "intlist.h"
11
#include "tests.h"
12 13
#include "debug.h"
#include "color.h"
14
#include <subcmd/parse-options.h>
15
#include "symbol.h"
16

J
Jiri Olsa 已提交
17 18
static bool dont_fork;

M
Matt Fleming 已提交
19 20 21 22 23 24 25
struct test __weak arch_tests[] = {
	{
		.func = NULL,
	},
};

static struct test generic_tests[] = {
26 27 28 29
	{
		.desc = "vmlinux symtab matches kallsyms",
		.func = test__vmlinux_matches_kallsyms,
	},
30
	{
31
		.desc = "Detect openat syscall event",
32
		.func = test__openat_syscall_event,
33
	},
34
	{
35
		.desc = "Detect openat syscall event on all cpus",
36
		.func = test__openat_syscall_event_on_all_cpus,
37
	},
38
	{
39
		.desc = "Read samples using the mmap interface",
40 41
		.func = test__basic_mmap,
	},
42
	{
43
		.desc = "Parse event definition strings",
44
		.func = test__parse_events,
45
	},
46
	{
47
		.desc = "PERF_RECORD_* events & perf_sample fields",
48 49
		.func = test__PERF_RECORD,
	},
50
	{
51
		.desc = "Parse perf pmu format",
52
		.func = test__pmu,
53
	},
54
	{
55
		.desc = "DSO data read",
56
		.func = test__dso_data,
57
	},
58
	{
59
		.desc = "DSO data cache",
60 61
		.func = test__dso_data_cache,
	},
62
	{
63
		.desc = "DSO data reopen",
64 65
		.func = test__dso_data_reopen,
	},
66
	{
67
		.desc = "Roundtrip evsel->name",
68
		.func = test__perf_evsel__roundtrip_name_test,
69
	},
70
	{
71
		.desc = "Parse sched tracepoints fields",
72
		.func = test__perf_evsel__tp_sched_test,
73
	},
74
	{
75
		.desc = "syscalls:sys_enter_openat event fields",
76
		.func = test__syscall_openat_tp_fields,
77
	},
78
	{
79
		.desc = "Setup struct perf_event_attr",
80
		.func = test__attr,
81
	},
82
	{
83
		.desc = "Match and link multiple hists",
84 85
		.func = test__hists_link,
	},
86
	{
87
		.desc = "'import perf' in python",
88 89
		.func = test__python_use,
	},
90
	{
91
		.desc = "Breakpoint overflow signal handler",
92 93
		.func = test__bp_signal,
	},
94
	{
95
		.desc = "Breakpoint overflow sampling",
96 97
		.func = test__bp_signal_overflow,
	},
98
	{
99
		.desc = "Number of exit events of a simple workload",
100 101
		.func = test__task_exit,
	},
102
	{
103
		.desc = "Software clock events period values",
104 105
		.func = test__sw_clock_freq,
	},
106
	{
107
		.desc = "Object code reading",
108 109
		.func = test__code_reading,
	},
110
	{
111
		.desc = "Sample parsing",
112 113
		.func = test__sample_parsing,
	},
114
	{
115
		.desc = "Use a dummy software event to keep tracking",
116 117
		.func = test__keep_tracking,
	},
118
	{
119
		.desc = "Parse with no sample_id_all bit set",
120 121
		.func = test__parse_no_sample_id_all,
	},
122
	{
123
		.desc = "Filter hist entries",
124 125
		.func = test__hists_filter,
	},
126
	{
127
		.desc = "Lookup mmap thread",
128 129
		.func = test__mmap_thread_lookup,
	},
130
	{
131
		.desc = "Share thread mg",
132 133
		.func = test__thread_mg_share,
	},
134
	{
135
		.desc = "Sort output of hist entries",
136 137
		.func = test__hists_output,
	},
138
	{
139
		.desc = "Cumulate child hist entries",
140 141
		.func = test__hists_cumulate,
	},
142
	{
143
		.desc = "Track with sched_switch",
144 145
		.func = test__switch_tracking,
	},
146
	{
147 148
		.desc = "Filter fds with revents mask in a fdarray",
		.func = test__fdarray__filter,
149
	},
150
	{
151 152
		.desc = "Add fd to a fdarray, making it autogrow",
		.func = test__fdarray__add,
153
	},
154
	{
155
		.desc = "kmod_path__parse",
156 157
		.func = test__kmod_path__parse,
	},
158
	{
159
		.desc = "Thread map",
160 161
		.func = test__thread_map,
	},
162
	{
163
		.desc = "LLVM search and compile",
164
		.func = test__llvm,
165 166 167 168 169
		.subtest = {
			.skip_if_fail	= true,
			.get_nr		= test__llvm_subtest_get_nr,
			.get_desc	= test__llvm_subtest_get_desc,
		},
170
	},
171
	{
172
		.desc = "Session topology",
173 174
		.func = test_session_topology,
	},
W
Wang Nan 已提交
175
	{
176
		.desc = "BPF filter",
W
Wang Nan 已提交
177
		.func = test__bpf,
178 179 180 181 182
		.subtest = {
			.skip_if_fail	= true,
			.get_nr		= test__bpf_subtest_get_nr,
			.get_desc	= test__bpf_subtest_get_desc,
		},
W
Wang Nan 已提交
183
	},
184
	{
185
		.desc = "Synthesize thread map",
186 187
		.func = test__thread_map_synthesize,
	},
188
	{
189
		.desc = "Synthesize cpu map",
190 191
		.func = test__cpu_map_synthesize,
	},
192
	{
193
		.desc = "Synthesize stat config",
194 195
		.func = test__synthesize_stat_config,
	},
196
	{
197
		.desc = "Synthesize stat",
198 199
		.func = test__synthesize_stat,
	},
200
	{
201
		.desc = "Synthesize stat round",
202 203
		.func = test__synthesize_stat_round,
	},
204
	{
205
		.desc = "Synthesize attr update",
206 207
		.func = test__event_update,
	},
208
	{
209
		.desc = "Event times",
210 211
		.func = test__event_times,
	},
212
	{
213
		.desc = "Read backward ring buffer",
214 215
		.func = test__backward_ring_buffer,
	},
216
	{
217
		.desc = "Print cpu map",
218 219
		.func = test__cpu_map_print,
	},
220
	{
221
		.desc = "Probe SDT events",
222 223
		.func = test__sdt_event,
	},
224
	{
225
		.desc = "is_printable_array",
226 227
		.func = test__is_printable_array,
	},
228
	{
229
		.desc = "Print bitmap",
230 231
		.func = test__bitmap_print,
	},
W
Wang Nan 已提交
232
	{
233
		.desc = "perf hooks",
W
Wang Nan 已提交
234 235
		.func = test__perf_hooks,
	},
236 237 238 239 240
	{
		.func = NULL,
	},
};

M
Matt Fleming 已提交
241 242 243 244 245
static struct test *tests[] = {
	generic_tests,
	arch_tests,
};

246
static bool perf_test__matches(struct test *test, int curr, int argc, const char *argv[])
247
{
248 249 250 251 252 253 254 255 256 257 258 259 260 261
	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;
		}
262

263
		if (strcasestr(test->desc, argv[i]))
264 265 266 267 268 269
			return true;
	}

	return false;
}

270
static int run_test(struct test *test, int subtest)
271
{
J
Jiri Olsa 已提交
272
	int status, err = -1, child = dont_fork ? 0 : fork();
273
	char sbuf[STRERR_BUFSIZE];
274 275

	if (child < 0) {
276
		pr_err("failed to fork test: %s\n",
277
			str_error_r(errno, sbuf, sizeof(sbuf)));
278 279 280 281
		return -1;
	}

	if (!child) {
J
Jiri Olsa 已提交
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
		if (!dont_fork) {
			pr_debug("test child forked, pid %d\n", getpid());

			if (!verbose) {
				int nullfd = open("/dev/null", O_WRONLY);

				if (nullfd >= 0) {
					close(STDERR_FILENO);
					close(STDOUT_FILENO);

					dup2(nullfd, STDOUT_FILENO);
					dup2(STDOUT_FILENO, STDERR_FILENO);
					close(nullfd);
				}
			} else {
				signal(SIGSEGV, sighandler_dump_stack);
				signal(SIGFPE, sighandler_dump_stack);
299 300 301
			}
		}

302
		err = test->func(subtest);
J
Jiri Olsa 已提交
303 304
		if (!dont_fork)
			exit(err);
305 306
	}

J
Jiri Olsa 已提交
307 308
	if (!dont_fork) {
		wait(&status);
309

J
Jiri Olsa 已提交
310 311 312 313 314 315 316
		if (WIFEXITED(status)) {
			err = (signed char)WEXITSTATUS(status);
			pr_debug("test child finished with %d\n", err);
		} else if (WIFSIGNALED(status)) {
			err = -1;
			pr_debug("test child interrupted\n");
		}
317 318 319 320 321
	}

	return err;
}

M
Matt Fleming 已提交
322 323 324
#define for_each_test(j, t)	 				\
	for (j = 0; j < ARRAY_SIZE(tests); j++)	\
		for (t = &tests[j][0]; t->func; t++)
325

326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
static int test_and_print(struct test *t, bool force_skip, int subtest)
{
	int err;

	if (!force_skip) {
		pr_debug("\n--- start ---\n");
		err = run_test(t, subtest);
		pr_debug("---- end ----\n");
	} else {
		pr_debug("\n--- force skipped ---\n");
		err = TEST_SKIP;
	}

	if (!t->subtest.get_nr)
		pr_debug("%s:", t->desc);
	else
		pr_debug("%s subtest %d:", t->desc, subtest);

	switch (err) {
	case TEST_OK:
		pr_info(" Ok\n");
		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;
	}

	return err;
}

360
static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
361
{
362
	struct test *t;
M
Matt Fleming 已提交
363
	unsigned int j;
364
	int i = 0;
365
	int width = 0;
366

M
Matt Fleming 已提交
367
	for_each_test(j, t) {
368
		int len = strlen(t->desc);
369 370 371 372

		if (width < len)
			width = len;
	}
373

M
Matt Fleming 已提交
374
	for_each_test(j, t) {
375 376
		int curr = i++, err;

377
		if (!perf_test__matches(t, curr, argc, argv))
378 379
			continue;

380
		pr_info("%2d: %-*s:", i, width, t->desc);
381 382 383 384 385 386

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

387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
		if (!t->subtest.get_nr) {
			test_and_print(t, false, -1);
		} else {
			int subn = t->subtest.get_nr();
			/*
			 * minus 2 to align with normal testcases.
			 * For subtest we print additional '.x' in number.
			 * for example:
			 *
			 * 35: Test LLVM searching and compiling                        :
			 * 35.1: Basic BPF llvm compiling test                          : Ok
			 */
			int subw = width > 2 ? width - 2 : width;
			bool skip = false;
			int subi;

			if (subn <= 0) {
				color_fprintf(stderr, PERF_COLOR_YELLOW,
					      " Skip (not compiled in)\n");
				continue;
			}
			pr_info("\n");

			for (subi = 0; subi < subn; subi++) {
				int len = strlen(t->subtest.get_desc(subi));

				if (subw < len)
					subw = len;
			}

			for (subi = 0; subi < subn; subi++) {
				pr_info("%2d.%1d: %-*s:", i, subi + 1, subw,
					t->subtest.get_desc(subi));
				err = test_and_print(t, skip, subi);
				if (err != TEST_OK && t->subtest.skip_if_fail)
					skip = true;
			}
424
		}
425 426 427 428 429
	}

	return 0;
}

430 431
static int perf_test__list(int argc, const char **argv)
{
M
Matt Fleming 已提交
432
	unsigned int j;
433
	struct test *t;
434 435
	int i = 0;

M
Matt Fleming 已提交
436
	for_each_test(j, t) {
437
		if (argc > 1 && !strstr(t->desc, argv[1]))
438 439
			continue;

440
		pr_info("%2d: %s\n", ++i, t->desc);
441 442 443 444
	}

	return 0;
}
445

446
int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
447
{
448
	const char *test_usage[] = {
449 450 451
	"perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
	NULL,
	};
452
	const char *skip = NULL;
453
	const struct option test_options[] = {
454
	OPT_STRING('s', "skip", &skip, "tests", "tests to skip"),
455
	OPT_INCR('v', "verbose", &verbose,
456
		    "be more verbose (show symbol address, etc)"),
J
Jiri Olsa 已提交
457 458
	OPT_BOOLEAN('F', "dont-fork", &dont_fork,
		    "Do not fork for testcase"),
459
	OPT_END()
460
	};
461
	const char * const test_subcommands[] = { "list", NULL };
462
	struct intlist *skiplist = NULL;
463 464 465 466
        int ret = hists__init();

        if (ret < 0)
                return ret;
467

468
	argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0);
469 470
	if (argc >= 1 && !strcmp(argv[0], "list"))
		return perf_test__list(argc, argv);
471 472 473 474 475

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

476
	if (symbol__init(NULL) < 0)
477 478
		return -1;

479 480 481 482
	if (skip != NULL)
		skiplist = intlist__new(skip);

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