Linux Audio

Check our new training course

Loading...
v5.4
  1// SPDX-License-Identifier: GPL-2.0
 
 
  2#include "parse-events.h"
  3#include "pmu.h"
 
  4#include "tests.h"
 
 
 
 
 
  5#include <errno.h>
 
  6#include <stdio.h>
  7#include <linux/kernel.h>
  8#include <linux/limits.h>
 
 
  9
 10/* Simulated format definitions. */
 11static struct test_format {
 12	const char *name;
 13	const char *value;
 14} test_formats[] = {
 15	{ "krava01", "config:0-1,62-63\n", },
 16	{ "krava02", "config:10-17\n", },
 17	{ "krava03", "config:5\n", },
 18	{ "krava11", "config1:0,2,4,6,8,20-28\n", },
 19	{ "krava12", "config1:63\n", },
 20	{ "krava13", "config1:45-47\n", },
 21	{ "krava21", "config2:0-3,10-13,20-23,30-33,40-43,50-53,60-63\n", },
 22	{ "krava22", "config2:8,18,48,58\n", },
 23	{ "krava23", "config2:28-29,38\n", },
 24};
 25
 26/* Simulated users input. */
 27static struct parse_events_term test_terms[] = {
 28	{
 29		.config    = (char *) "krava01",
 30		.val.num   = 15,
 31		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
 32		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
 33	},
 34	{
 35		.config    = (char *) "krava02",
 36		.val.num   = 170,
 37		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
 38		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
 39	},
 40	{
 41		.config    = (char *) "krava03",
 42		.val.num   = 1,
 43		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
 44		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
 45	},
 46	{
 47		.config    = (char *) "krava11",
 48		.val.num   = 27,
 49		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
 50		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
 51	},
 52	{
 53		.config    = (char *) "krava12",
 54		.val.num   = 1,
 55		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
 56		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
 57	},
 58	{
 59		.config    = (char *) "krava13",
 60		.val.num   = 2,
 61		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
 62		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
 63	},
 64	{
 65		.config    = (char *) "krava21",
 66		.val.num   = 119,
 67		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
 68		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
 69	},
 70	{
 71		.config    = (char *) "krava22",
 72		.val.num   = 11,
 73		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
 74		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
 75	},
 76	{
 77		.config    = (char *) "krava23",
 78		.val.num   = 2,
 79		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
 80		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
 81	},
 82};
 83
 84/*
 85 * Prepare format directory data, exported by kernel
 86 * at /sys/bus/event_source/devices/<dev>/format.
 
 87 */
 88static char *test_format_dir_get(void)
 89{
 90	static char dir[PATH_MAX];
 91	unsigned int i;
 92
 93	snprintf(dir, PATH_MAX, "/tmp/perf-pmu-test-format-XXXXXX");
 94	if (!mkdtemp(dir))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 95		return NULL;
 
 
 
 
 
 
 96
 97	for (i = 0; i < ARRAY_SIZE(test_formats); i++) {
 98		static char name[PATH_MAX];
 99		struct test_format *format = &test_formats[i];
100		FILE *file;
 
 
 
 
 
 
 
 
 
 
 
 
 
101
102		scnprintf(name, PATH_MAX, "%s/%s", dir, format->name);
 
 
 
 
 
 
103
104		file = fopen(name, "w");
105		if (!file)
106			return NULL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
108		if (1 != fwrite(format->value, strlen(format->value), 1, file))
109			break;
 
 
 
 
 
 
 
 
 
 
110
111		fclose(file);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112	}
113
114	return dir;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115}
116
117/* Cleanup format directory. */
118static int test_format_dir_put(char *dir)
119{
120	char buf[PATH_MAX];
121	snprintf(buf, PATH_MAX, "rm -f %s/*\n", dir);
122	if (system(buf))
123		return -1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
125	snprintf(buf, PATH_MAX, "rmdir %s\n", dir);
126	return system(buf);
 
 
 
 
127}
128
129static struct list_head *test_terms_list(void)
130{
131	static LIST_HEAD(terms);
132	unsigned int i;
133
134	for (i = 0; i < ARRAY_SIZE(test_terms); i++)
135		list_add_tail(&test_terms[i].list, &terms);
136
137	return &terms;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138}
139
140int test__pmu(struct test *test __maybe_unused, int subtest __maybe_unused)
 
141{
142	char *format = test_format_dir_get();
143	LIST_HEAD(formats);
144	struct list_head *terms = test_terms_list();
145	int ret;
 
 
 
 
 
 
146
147	if (!format)
148		return -EINVAL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
150	do {
151		struct perf_event_attr attr;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
153		memset(&attr, 0, sizeof(attr));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
155		ret = perf_pmu__format_parse(format, &formats);
156		if (ret)
157			break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
159		ret = perf_pmu__config_terms(&formats, &attr, terms,
160					     false, NULL);
161		if (ret)
162			break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
164		ret = -EINVAL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
166		if (attr.config  != 0xc00000000002a823)
167			break;
168		if (attr.config1 != 0x8000400000000145)
169			break;
170		if (attr.config2 != 0x0400000020041d07)
171			break;
172
173		ret = 0;
174	} while (0);
 
 
 
 
 
 
 
175
176	test_format_dir_put(format);
177	return ret;
178}
 
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2#include "evlist.h"
  3#include "evsel.h"
  4#include "parse-events.h"
  5#include "pmu.h"
  6#include "pmus.h"
  7#include "tests.h"
  8#include "debug.h"
  9#include "fncache.h"
 10#include <api/fs/fs.h>
 11#include <ctype.h>
 12#include <dirent.h>
 13#include <errno.h>
 14#include <fcntl.h>
 15#include <stdio.h>
 16#include <stdlib.h>
 17#include <unistd.h>
 18#include <sys/stat.h>
 19#include <sys/types.h>
 20
 21/* Cleanup test PMU directory. */
 22static int test_pmu_put(const char *dir, struct perf_pmu *pmu)
 23{
 24	char buf[PATH_MAX + 20];
 25	int ret;
 
 
 
 
 
 
 
 
 
 
 26
 27	if (scnprintf(buf, sizeof(buf), "rm -fr %s", dir) < 0) {
 28		pr_err("Failure to set up buffer for \"%s\"\n", dir);
 29		return -EINVAL;
 30	}
 31	ret = system(buf);
 32	if (ret)
 33		pr_err("Failure to \"%s\"\n", buf);
 34
 35	list_del(&pmu->list);
 36	perf_pmu__delete(pmu);
 37	return ret;
 38}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 39
 40/*
 41 * Prepare test PMU directory data, normally exported by kernel at
 42 * /sys/bus/event_source/devices/<pmu>/. Give as input a buffer to hold the file
 43 * path, the result is PMU loaded using that directory.
 44 */
 45static struct perf_pmu *test_pmu_get(char *dir, size_t sz)
 46{
 47	/* Simulated format definitions. */
 48	const struct test_format {
 49		const char *name;
 50		const char *value;
 51	} test_formats[] = {
 52		{ "krava01", "config:0-1,62-63\n", },
 53		{ "krava02", "config:10-17\n", },
 54		{ "krava03", "config:5\n", },
 55		{ "krava11", "config1:0,2,4,6,8,20-28\n", },
 56		{ "krava12", "config1:63\n", },
 57		{ "krava13", "config1:45-47\n", },
 58		{ "krava21", "config2:0-3,10-13,20-23,30-33,40-43,50-53,60-63\n", },
 59		{ "krava22", "config2:8,18,48,58\n", },
 60		{ "krava23", "config2:28-29,38\n", },
 61	};
 62	const char *test_event = "krava01=15,krava02=170,krava03=1,krava11=27,krava12=1,"
 63		"krava13=2,krava21=119,krava22=11,krava23=2\n";
 64
 65	char name[PATH_MAX];
 66	int dirfd, file;
 67	struct perf_pmu *pmu = NULL;
 68	ssize_t len;
 69
 70	/* Create equivalent of sysfs mount point. */
 71	scnprintf(dir, sz, "/tmp/perf-pmu-test-XXXXXX");
 72	if (!mkdtemp(dir)) {
 73		pr_err("mkdtemp failed\n");
 74		dir[0] = '\0';
 75		return NULL;
 76	}
 77	dirfd = open(dir, O_DIRECTORY);
 78	if (dirfd < 0) {
 79		pr_err("Failed to open test directory \"%s\"\n", dir);
 80		goto err_out;
 81	}
 82
 83	/* Create the test PMU directory and give it a perf_event_attr type number. */
 84	if (mkdirat(dirfd, "perf-pmu-test", 0755) < 0) {
 85		pr_err("Failed to mkdir PMU directory\n");
 86		goto err_out;
 87	}
 88	file = openat(dirfd, "perf-pmu-test/type", O_WRONLY | O_CREAT, 0600);
 89	if (!file) {
 90		pr_err("Failed to open for writing file \"type\"\n");
 91		goto err_out;
 92	}
 93	len = strlen("9999");
 94	if (write(file, "9999\n", len) < len) {
 95		close(file);
 96		pr_err("Failed to write to 'type' file\n");
 97		goto err_out;
 98	}
 99	close(file);
100
101	/* Create format directory and files. */
102	if (mkdirat(dirfd, "perf-pmu-test/format", 0755) < 0) {
103		pr_err("Failed to mkdir PMU format directory\n)");
104		goto err_out;
105	}
106	for (size_t i = 0; i < ARRAY_SIZE(test_formats); i++) {
107		const struct test_format *format = &test_formats[i];
108
109		if (scnprintf(name, PATH_MAX, "perf-pmu-test/format/%s", format->name) < 0) {
110			pr_err("Failure to set up path for \"%s\"\n", format->name);
111			goto err_out;
112		}
113		file = openat(dirfd, name, O_WRONLY | O_CREAT, 0600);
114		if (!file) {
115			pr_err("Failed to open for writing file \"%s\"\n", name);
116			goto err_out;
117		}
118
119		if (write(file, format->value, strlen(format->value)) < 0) {
120			pr_err("Failed to write to file \"%s\"\n", name);
121			close(file);
122			goto err_out;
123		}
124		close(file);
125	}
126
127	/* Create test event. */
128	if (mkdirat(dirfd, "perf-pmu-test/events", 0755) < 0) {
129		pr_err("Failed to mkdir PMU events directory\n");
130		goto err_out;
131	}
132	file = openat(dirfd, "perf-pmu-test/events/test-event", O_WRONLY | O_CREAT, 0600);
133	if (!file) {
134		pr_err("Failed to open for writing file \"type\"\n");
135		goto err_out;
136	}
137	len = strlen(test_event);
138	if (write(file, test_event, len) < len) {
139		close(file);
140		pr_err("Failed to write to 'test-event' file\n");
141		goto err_out;
142	}
143	close(file);
144
145	/* Make the PMU reading the files created above. */
146	pmu = perf_pmus__add_test_pmu(dirfd, "perf-pmu-test");
147	if (!pmu)
148		pr_err("Test PMU creation failed\n");
149
150err_out:
151	if (!pmu)
152		test_pmu_put(dir, pmu);
153	if (dirfd >= 0)
154		close(dirfd);
155	return pmu;
156}
157
158static int test__pmu_format(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
159{
160	char dir[PATH_MAX];
161	struct perf_event_attr attr;
162	struct parse_events_terms terms;
163	int ret = TEST_FAIL;
164	struct perf_pmu *pmu = test_pmu_get(dir, sizeof(dir));
165
166	if (!pmu)
167		return TEST_FAIL;
168
169	parse_events_terms__init(&terms);
170	if (parse_events_terms(&terms,
171				"krava01=15,krava02=170,krava03=1,krava11=27,krava12=1,"
172				"krava13=2,krava21=119,krava22=11,krava23=2",
173				NULL)) {
174		pr_err("Term parsing failed\n");
175		goto err_out;
176	}
177
178	memset(&attr, 0, sizeof(attr));
179	ret = perf_pmu__config_terms(pmu, &attr, &terms, /*zero=*/false,
180				     /*apply_hardcoded=*/false, /*err=*/NULL);
181	if (ret) {
182		pr_err("perf_pmu__config_terms failed");
183		goto err_out;
184	}
185
186	if (attr.config  != 0xc00000000002a823) {
187		pr_err("Unexpected config value %llx\n", attr.config);
188		goto err_out;
189	}
190	if (attr.config1 != 0x8000400000000145) {
191		pr_err("Unexpected config1 value %llx\n", attr.config1);
192		goto err_out;
193	}
194	if (attr.config2 != 0x0400000020041d07) {
195		pr_err("Unexpected config2 value %llx\n", attr.config2);
196		goto err_out;
197	}
198
199	ret = TEST_OK;
200err_out:
201	parse_events_terms__exit(&terms);
202	test_pmu_put(dir, pmu);
203	return ret;
204}
205
206static int test__pmu_events(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
 
207{
208	char dir[PATH_MAX];
209	struct parse_events_error err;
210	struct evlist *evlist;
211	struct evsel *evsel;
212	struct perf_event_attr *attr;
213	int ret = TEST_FAIL;
214	struct perf_pmu *pmu = test_pmu_get(dir, sizeof(dir));
215	const char *event = "perf-pmu-test/test-event/";
216
217
218	if (!pmu)
219		return TEST_FAIL;
220
221	evlist = evlist__new();
222	if (evlist == NULL) {
223		pr_err("Failed allocation");
224		goto err_out;
225	}
226	parse_events_error__init(&err);
227	ret = parse_events(evlist, event, &err);
228	if (ret) {
229		pr_debug("failed to parse event '%s', err %d\n", event, ret);
230		parse_events_error__print(&err, event);
231		if (parse_events_error__contains(&err, "can't access trace events"))
232			ret = TEST_SKIP;
233		goto err_out;
234	}
235	evsel = evlist__first(evlist);
236	attr = &evsel->core.attr;
237	if (attr->config  != 0xc00000000002a823) {
238		pr_err("Unexpected config value %llx\n", attr->config);
239		goto err_out;
240	}
241	if (attr->config1 != 0x8000400000000145) {
242		pr_err("Unexpected config1 value %llx\n", attr->config1);
243		goto err_out;
244	}
245	if (attr->config2 != 0x0400000020041d07) {
246		pr_err("Unexpected config2 value %llx\n", attr->config2);
247		goto err_out;
248	}
249
250	ret = TEST_OK;
251err_out:
252	parse_events_error__exit(&err);
253	evlist__delete(evlist);
254	test_pmu_put(dir, pmu);
255	return ret;
256}
257
258static bool permitted_event_name(const char *name)
259{
260	bool has_lower = false, has_upper = false;
261	__u64 config;
262
263	for (size_t i = 0; i < strlen(name); i++) {
264		char c = name[i];
265
266		if (islower(c)) {
267			if (has_upper)
268				goto check_legacy;
269			has_lower = true;
270			continue;
271		}
272		if (isupper(c)) {
273			if (has_lower)
274				goto check_legacy;
275			has_upper = true;
276			continue;
277		}
278		if (!isdigit(c) && c != '.' && c != '_' && c != '-')
279			goto check_legacy;
280	}
281	return true;
282check_legacy:
283	/*
284	 * If the event name matches a legacy cache name the legacy encoding
285	 * will still be used. This isn't quite WAI as sysfs events should take
286	 * priority, but this case happens on PowerPC and matches the behavior
287	 * in older perf tools where legacy events were the priority. Be
288	 * permissive and assume later PMU drivers will use all lower or upper
289	 * case names.
290	 */
291	if (parse_events__decode_legacy_cache(name, /*extended_pmu_type=*/0, &config) == 0) {
292		pr_warning("sysfs event '%s' should be all lower/upper case, it will be matched using legacy encoding.",
293			   name);
294		return true;
295	}
296	return false;
297}
298
299static int test__pmu_event_names(struct test_suite *test __maybe_unused,
300				 int subtest __maybe_unused)
301{
302	char path[PATH_MAX];
303	DIR *pmu_dir, *event_dir;
304	struct dirent *pmu_dent, *event_dent;
305	const char *sysfs = sysfs__mountpoint();
306	int ret = TEST_OK;
307
308	if (!sysfs) {
309		pr_err("Sysfs not mounted\n");
310		return TEST_FAIL;
311	}
312
313	snprintf(path, sizeof(path), "%s/bus/event_source/devices/", sysfs);
314	pmu_dir = opendir(path);
315	if (!pmu_dir) {
316		pr_err("Error opening \"%s\"\n", path);
317		return TEST_FAIL;
318	}
319	while ((pmu_dent = readdir(pmu_dir))) {
320		if (!strcmp(pmu_dent->d_name, ".") ||
321		    !strcmp(pmu_dent->d_name, ".."))
322			continue;
323
324		snprintf(path, sizeof(path), "%s/bus/event_source/devices/%s/type",
325			 sysfs, pmu_dent->d_name);
326
327		/* Does it look like a PMU? */
328		if (!file_available(path))
329			continue;
330
331		/* Process events. */
332		snprintf(path, sizeof(path), "%s/bus/event_source/devices/%s/events",
333			 sysfs, pmu_dent->d_name);
334
335		event_dir = opendir(path);
336		if (!event_dir) {
337			pr_debug("Skipping as no event directory \"%s\"\n", path);
338			continue;
339		}
340		while ((event_dent = readdir(event_dir))) {
341			const char *event_name = event_dent->d_name;
342
343			if (!strcmp(event_name, ".") || !strcmp(event_name, ".."))
344				continue;
345
346			if (!permitted_event_name(event_name)) {
347				pr_err("Invalid sysfs event name: %s/%s\n",
348					pmu_dent->d_name, event_name);
349				ret = TEST_FAIL;
350			}
351		}
352		closedir(event_dir);
353	}
354	closedir(pmu_dir);
355	return ret;
356}
357
358static const char * const uncore_chas[] = {
359	"uncore_cha_0",
360	"uncore_cha_1",
361	"uncore_cha_2",
362	"uncore_cha_3",
363	"uncore_cha_4",
364	"uncore_cha_5",
365	"uncore_cha_6",
366	"uncore_cha_7",
367	"uncore_cha_8",
368	"uncore_cha_9",
369	"uncore_cha_10",
370	"uncore_cha_11",
371	"uncore_cha_12",
372	"uncore_cha_13",
373	"uncore_cha_14",
374	"uncore_cha_15",
375	"uncore_cha_16",
376	"uncore_cha_17",
377	"uncore_cha_18",
378	"uncore_cha_19",
379	"uncore_cha_20",
380	"uncore_cha_21",
381	"uncore_cha_22",
382	"uncore_cha_23",
383	"uncore_cha_24",
384	"uncore_cha_25",
385	"uncore_cha_26",
386	"uncore_cha_27",
387	"uncore_cha_28",
388	"uncore_cha_29",
389	"uncore_cha_30",
390	"uncore_cha_31",
391};
392
393static const char * const mrvl_ddrs[] = {
394	"mrvl_ddr_pmu_87e1b0000000",
395	"mrvl_ddr_pmu_87e1b1000000",
396	"mrvl_ddr_pmu_87e1b2000000",
397	"mrvl_ddr_pmu_87e1b3000000",
398	"mrvl_ddr_pmu_87e1b4000000",
399	"mrvl_ddr_pmu_87e1b5000000",
400	"mrvl_ddr_pmu_87e1b6000000",
401	"mrvl_ddr_pmu_87e1b7000000",
402	"mrvl_ddr_pmu_87e1b8000000",
403	"mrvl_ddr_pmu_87e1b9000000",
404	"mrvl_ddr_pmu_87e1ba000000",
405	"mrvl_ddr_pmu_87e1bb000000",
406	"mrvl_ddr_pmu_87e1bc000000",
407	"mrvl_ddr_pmu_87e1bd000000",
408	"mrvl_ddr_pmu_87e1be000000",
409	"mrvl_ddr_pmu_87e1bf000000",
410};
411
412static int test__name_len(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
413{
414	TEST_ASSERT_VAL("cpu", pmu_name_len_no_suffix("cpu") == strlen("cpu"));
415	TEST_ASSERT_VAL("i915", pmu_name_len_no_suffix("i915") == strlen("i915"));
416	TEST_ASSERT_VAL("cpum_cf", pmu_name_len_no_suffix("cpum_cf") == strlen("cpum_cf"));
417	for (size_t i = 0; i < ARRAY_SIZE(uncore_chas); i++) {
418		TEST_ASSERT_VAL("Strips uncore_cha suffix",
419				pmu_name_len_no_suffix(uncore_chas[i]) ==
420				strlen("uncore_cha"));
421	}
422	for (size_t i = 0; i < ARRAY_SIZE(mrvl_ddrs); i++) {
423		TEST_ASSERT_VAL("Strips mrvl_ddr_pmu suffix",
424				pmu_name_len_no_suffix(mrvl_ddrs[i]) ==
425				strlen("mrvl_ddr_pmu"));
426	}
427	return TEST_OK;
428}
429
430static int test__name_cmp(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
431{
432	TEST_ASSERT_EQUAL("cpu", pmu_name_cmp("cpu", "cpu"), 0);
433	TEST_ASSERT_EQUAL("i915", pmu_name_cmp("i915", "i915"), 0);
434	TEST_ASSERT_EQUAL("cpum_cf", pmu_name_cmp("cpum_cf", "cpum_cf"), 0);
435	TEST_ASSERT_VAL("i915", pmu_name_cmp("cpu", "i915") < 0);
436	TEST_ASSERT_VAL("i915", pmu_name_cmp("i915", "cpu") > 0);
437	TEST_ASSERT_VAL("cpum_cf", pmu_name_cmp("cpum_cf", "cpum_ce") > 0);
438	TEST_ASSERT_VAL("cpum_cf", pmu_name_cmp("cpum_cf", "cpum_d0") < 0);
439	for (size_t i = 1; i < ARRAY_SIZE(uncore_chas); i++) {
440		TEST_ASSERT_VAL("uncore_cha suffixes ordered lt",
441				pmu_name_cmp(uncore_chas[i-1], uncore_chas[i]) < 0);
442		TEST_ASSERT_VAL("uncore_cha suffixes ordered gt",
443				pmu_name_cmp(uncore_chas[i], uncore_chas[i-1]) > 0);
444	}
445	for (size_t i = 1; i < ARRAY_SIZE(mrvl_ddrs); i++) {
446		TEST_ASSERT_VAL("mrvl_ddr_pmu suffixes ordered lt",
447				pmu_name_cmp(mrvl_ddrs[i-1], mrvl_ddrs[i]) < 0);
448		TEST_ASSERT_VAL("mrvl_ddr_pmu suffixes ordered gt",
449				pmu_name_cmp(mrvl_ddrs[i], mrvl_ddrs[i-1]) > 0);
450	}
451	return TEST_OK;
452}
453
454/**
455 * Test perf_pmu__match() that's used to search for a PMU given a name passed
456 * on the command line. The name that's passed may also be a filename type glob
457 * match. If the name does not match, perf_pmu__match() attempts to match the
458 * alias of the PMU, if provided.
459 */
460static int test__pmu_match(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
461{
462	struct perf_pmu test_pmu = {
463		.name = "pmuname",
464	};
465
466	TEST_ASSERT_EQUAL("Exact match", perf_pmu__match(&test_pmu, "pmuname"),	     true);
467	TEST_ASSERT_EQUAL("Longer token", perf_pmu__match(&test_pmu, "longertoken"), false);
468	TEST_ASSERT_EQUAL("Shorter token", perf_pmu__match(&test_pmu, "pmu"),	     false);
469
470	test_pmu.name = "pmuname_10";
471	TEST_ASSERT_EQUAL("Diff suffix_", perf_pmu__match(&test_pmu, "pmuname_2"),  false);
472	TEST_ASSERT_EQUAL("Sub suffix_",  perf_pmu__match(&test_pmu, "pmuname_1"),  true);
473	TEST_ASSERT_EQUAL("Same suffix_", perf_pmu__match(&test_pmu, "pmuname_10"), true);
474	TEST_ASSERT_EQUAL("No suffix_",   perf_pmu__match(&test_pmu, "pmuname"),    true);
475	TEST_ASSERT_EQUAL("Underscore_",  perf_pmu__match(&test_pmu, "pmuname_"),   true);
476	TEST_ASSERT_EQUAL("Substring_",   perf_pmu__match(&test_pmu, "pmuna"),      false);
477
478	test_pmu.name = "pmuname_ab23";
479	TEST_ASSERT_EQUAL("Diff suffix hex_", perf_pmu__match(&test_pmu, "pmuname_2"),    false);
480	TEST_ASSERT_EQUAL("Sub suffix hex_",  perf_pmu__match(&test_pmu, "pmuname_ab"),   true);
481	TEST_ASSERT_EQUAL("Same suffix hex_", perf_pmu__match(&test_pmu, "pmuname_ab23"), true);
482	TEST_ASSERT_EQUAL("No suffix hex_",   perf_pmu__match(&test_pmu, "pmuname"),      true);
483	TEST_ASSERT_EQUAL("Underscore hex_",  perf_pmu__match(&test_pmu, "pmuname_"),     true);
484	TEST_ASSERT_EQUAL("Substring hex_",   perf_pmu__match(&test_pmu, "pmuna"),	 false);
485
486	test_pmu.name = "pmuname10";
487	TEST_ASSERT_EQUAL("Diff suffix", perf_pmu__match(&test_pmu, "pmuname2"),  false);
488	TEST_ASSERT_EQUAL("Sub suffix",  perf_pmu__match(&test_pmu, "pmuname1"),  true);
489	TEST_ASSERT_EQUAL("Same suffix", perf_pmu__match(&test_pmu, "pmuname10"), true);
490	TEST_ASSERT_EQUAL("No suffix",   perf_pmu__match(&test_pmu, "pmuname"),   true);
491	TEST_ASSERT_EQUAL("Underscore",  perf_pmu__match(&test_pmu, "pmuname_"),  false);
492	TEST_ASSERT_EQUAL("Substring",   perf_pmu__match(&test_pmu, "pmuna"),     false);
493
494	test_pmu.name = "pmunameab23";
495	TEST_ASSERT_EQUAL("Diff suffix hex", perf_pmu__match(&test_pmu, "pmuname2"),    false);
496	TEST_ASSERT_EQUAL("Sub suffix hex",  perf_pmu__match(&test_pmu, "pmunameab"),   true);
497	TEST_ASSERT_EQUAL("Same suffix hex", perf_pmu__match(&test_pmu, "pmunameab23"), true);
498	TEST_ASSERT_EQUAL("No suffix hex",   perf_pmu__match(&test_pmu, "pmuname"),     true);
499	TEST_ASSERT_EQUAL("Underscore hex",  perf_pmu__match(&test_pmu, "pmuname_"),    false);
500	TEST_ASSERT_EQUAL("Substring hex",   perf_pmu__match(&test_pmu, "pmuna"),	false);
501
502	/*
503	 * 2 hex chars or less are not considered suffixes so it shouldn't be
504	 * possible to wildcard by skipping the suffix. Therefore there are more
505	 * false results here than above.
506	 */
507	test_pmu.name = "pmuname_a3";
508	TEST_ASSERT_EQUAL("Diff suffix 2 hex_", perf_pmu__match(&test_pmu, "pmuname_2"),  false);
509	/*
510	 * This one should be false, but because pmuname_a3 ends in 3 which is
511	 * decimal, it's not possible to determine if it's a short hex suffix or
512	 * a normal decimal suffix following text. And we want to match on any
513	 * length of decimal suffix. Run the test anyway and expect the wrong
514	 * result. And slightly fuzzy matching shouldn't do too much harm.
515	 */
516	TEST_ASSERT_EQUAL("Sub suffix 2 hex_",  perf_pmu__match(&test_pmu, "pmuname_a"),  true);
517	TEST_ASSERT_EQUAL("Same suffix 2 hex_", perf_pmu__match(&test_pmu, "pmuname_a3"), true);
518	TEST_ASSERT_EQUAL("No suffix 2 hex_",   perf_pmu__match(&test_pmu, "pmuname"),    false);
519	TEST_ASSERT_EQUAL("Underscore 2 hex_",  perf_pmu__match(&test_pmu, "pmuname_"),   false);
520	TEST_ASSERT_EQUAL("Substring 2 hex_",   perf_pmu__match(&test_pmu, "pmuna"),	  false);
521
522	test_pmu.name = "pmuname_5";
523	TEST_ASSERT_EQUAL("Glob 1", perf_pmu__match(&test_pmu, "pmu*"),		   true);
524	TEST_ASSERT_EQUAL("Glob 2", perf_pmu__match(&test_pmu, "nomatch*"),	   false);
525	TEST_ASSERT_EQUAL("Seq 1",  perf_pmu__match(&test_pmu, "pmuname_[12345]"), true);
526	TEST_ASSERT_EQUAL("Seq 2",  perf_pmu__match(&test_pmu, "pmuname_[67890]"), false);
527	TEST_ASSERT_EQUAL("? 1",    perf_pmu__match(&test_pmu, "pmuname_?"),	   true);
528	TEST_ASSERT_EQUAL("? 2",    perf_pmu__match(&test_pmu, "pmuname_1?"),	   false);
529
530	return TEST_OK;
531}
 
 
 
 
532
533static struct test_case tests__pmu[] = {
534	TEST_CASE("Parsing with PMU format directory", pmu_format),
535	TEST_CASE("Parsing with PMU event", pmu_events),
536	TEST_CASE("PMU event names", pmu_event_names),
537	TEST_CASE("PMU name combining", name_len),
538	TEST_CASE("PMU name comparison", name_cmp),
539	TEST_CASE("PMU cmdline match", pmu_match),
540	{	.name = NULL, }
541};
542
543struct test_suite suite__pmu = {
544	.desc = "Sysfs PMU tests",
545	.test_cases = tests__pmu,
546};