builtin-test.c 6.1 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 read",
56
		.func = test__dso_data,
57
	},
58 59 60 61
	{
		.desc = "Test dso data cache",
		.func = test__dso_data_cache,
	},
62 63 64 65
	{
		.desc = "Test dso data reopen",
		.func = test__dso_data_reopen,
	},
66 67
	{
		.desc = "roundtrip evsel->name check",
68
		.func = test__perf_evsel__roundtrip_name_test,
69
	},
70 71
	{
		.desc = "Check parsing of sched tracepoints fields",
72
		.func = test__perf_evsel__tp_sched_test,
73
	},
74 75 76 77
	{
		.desc = "Generate and check syscalls:sys_enter_open event fields",
		.func = test__syscall_open_tp_fields,
	},
78 79
	{
		.desc = "struct perf_event_attr setup",
80
		.func = test__attr,
81
	},
82
	{
A
Arnaldo Carvalho de Melo 已提交
83
		.desc = "Test matching and linking multiple hists",
84 85
		.func = test__hists_link,
	},
86 87 88 89
	{
		.desc = "Try 'use perf' in python, checking link problems",
		.func = test__python_use,
	},
90 91 92 93
	{
		.desc = "Test breakpoint overflow signal handler",
		.func = test__bp_signal,
	},
94 95 96 97
	{
		.desc = "Test breakpoint overflow sampling",
		.func = test__bp_signal_overflow,
	},
98 99 100 101
	{
		.desc = "Test number of exit event of a simple workload",
		.func = test__task_exit,
	},
102 103 104 105
	{
		.desc = "Test software clock events have valid period values",
		.func = test__sw_clock_freq,
	},
106 107 108 109 110 111
#if defined(__x86_64__) || defined(__i386__)
	{
		.desc = "Test converting perf time to TSC",
		.func = test__perf_time_to_tsc,
	},
#endif
112 113 114 115
	{
		.desc = "Test object code reading",
		.func = test__code_reading,
	},
116 117 118 119
	{
		.desc = "Test sample parsing",
		.func = test__sample_parsing,
	},
120 121 122 123
	{
		.desc = "Test using a dummy software event to keep tracking",
		.func = test__keep_tracking,
	},
124 125 126 127
	{
		.desc = "Test parsing with no sample_id_all bit set",
		.func = test__parse_no_sample_id_all,
	},
128
#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
129
#ifdef HAVE_DWARF_UNWIND_SUPPORT
130 131 132 133 134 135
	{
		.desc = "Test dwarf unwind",
		.func = test__dwarf_unwind,
	},
#endif
#endif
136 137 138 139
	{
		.desc = "Test filtering hist entries",
		.func = test__hists_filter,
	},
140 141 142 143
	{
		.desc = "Test mmap thread lookup",
		.func = test__mmap_thread_lookup,
	},
144 145 146 147
	{
		.desc = "Test thread mg sharing",
		.func = test__thread_mg_share,
	},
148 149 150 151
	{
		.desc = "Test output sorting of hist entries",
		.func = test__hists_output,
	},
152 153 154 155
	{
		.desc = "Test cumulation of child hist entries",
		.func = test__hists_cumulate,
	},
156 157 158 159 160
	{
		.func = NULL,
	},
};

161
static bool perf_test__matches(int curr, int argc, const char *argv[])
162
{
163 164 165 166 167 168 169 170 171 172 173 174 175 176
	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;
		}
177

178 179 180 181 182 183 184
		if (strstr(tests[curr].desc, argv[i]))
			return true;
	}

	return false;
}

185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
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;
}

213
static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
214 215
{
	int i = 0;
216
	int width = 0;
217

218 219 220 221 222 223 224
	while (tests[i].func) {
		int len = strlen(tests[i].desc);

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

226
	i = 0;
227
	while (tests[i].func) {
228 229 230 231 232
		int curr = i++, err;

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

233
		pr_info("%2d: %-*s:", i, width, tests[curr].desc);
234 235 236 237 238 239

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

240
		pr_debug("\n--- start ---\n");
241
		err = run_test(&tests[curr]);
242
		pr_debug("---- end ----\n%s:", tests[curr].desc);
243 244 245

		switch (err) {
		case TEST_OK:
246
			pr_info(" Ok\n");
247 248 249 250 251 252 253 254 255
			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;
		}
256 257 258 259 260
	}

	return 0;
}

261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
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;
}
276

277
int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
278 279 280 281 282
{
	const char * const test_usage[] = {
	"perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
	NULL,
	};
283
	const char *skip = NULL;
284
	const struct option test_options[] = {
285
	OPT_STRING('s', "skip", &skip, "tests", "tests to skip"),
286
	OPT_INCR('v', "verbose", &verbose,
287 288
		    "be more verbose (show symbol address, etc)"),
	OPT_END()
289
	};
290
	struct intlist *skiplist = NULL;
291 292

	argc = parse_options(argc, argv, test_options, test_usage, 0);
293 294
	if (argc >= 1 && !strcmp(argv[0], "list"))
		return perf_test__list(argc, argv);
295 296 297 298 299 300 301 302

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

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

303 304 305 306
	if (skip != NULL)
		skiplist = intlist__new(skip);

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