1 // SPDX-License-Identifier: GPL-2.0
2 #include "evlist.h"
3 #include "evsel.h"
4 #include "parse-events.h"
5 #include "tests.h"
6 #include "debug.h"
7 #include "pmu.h"
8 #include <errno.h>
9 #include <linux/kernel.h>
10 
11 static int perf_evsel__roundtrip_cache_name_test(void)
12 {
13 	char name[128];
14 	int type, op, err = 0, ret = 0, i, idx;
15 	struct evsel *evsel;
16 	struct evlist *evlist = evlist__new();
17 
18         if (evlist == NULL)
19                 return -ENOMEM;
20 
21 	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
22 		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
23 			/* skip invalid cache type */
24 			if (!evsel__is_cache_op_valid(type, op))
25 				continue;
26 
27 			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
28 				__evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name));
29 				err = parse_events(evlist, name, NULL);
30 				if (err)
31 					ret = err;
32 			}
33 		}
34 	}
35 
36 	idx = 0;
37 	evsel = evlist__first(evlist);
38 
39 	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
40 		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
41 			/* skip invalid cache type */
42 			if (!evsel__is_cache_op_valid(type, op))
43 				continue;
44 
45 			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
46 				__evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name));
47 				if (evsel->idx != idx)
48 					continue;
49 
50 				++idx;
51 
52 				if (strcmp(evsel__name(evsel), name)) {
53 					pr_debug("%s != %s\n", evsel__name(evsel), name);
54 					ret = -1;
55 				}
56 
57 				evsel = evsel__next(evsel);
58 			}
59 		}
60 	}
61 
62 	evlist__delete(evlist);
63 	return ret;
64 }
65 
66 static int __perf_evsel__name_array_test(const char *names[], int nr_names,
67 					 int distance)
68 {
69 	int i, err;
70 	struct evsel *evsel;
71 	struct evlist *evlist = evlist__new();
72 
73         if (evlist == NULL)
74                 return -ENOMEM;
75 
76 	for (i = 0; i < nr_names; ++i) {
77 		err = parse_events(evlist, names[i], NULL);
78 		if (err) {
79 			pr_debug("failed to parse event '%s', err %d\n",
80 				 names[i], err);
81 			goto out_delete_evlist;
82 		}
83 	}
84 
85 	err = 0;
86 	evlist__for_each_entry(evlist, evsel) {
87 		if (strcmp(evsel__name(evsel), names[evsel->idx / distance])) {
88 			--err;
89 			pr_debug("%s != %s\n", evsel__name(evsel), names[evsel->idx / distance]);
90 		}
91 	}
92 
93 out_delete_evlist:
94 	evlist__delete(evlist);
95 	return err;
96 }
97 
98 #define perf_evsel__name_array_test(names, distance) \
99 	__perf_evsel__name_array_test(names, ARRAY_SIZE(names), distance)
100 
101 int test__perf_evsel__roundtrip_name_test(struct test *test __maybe_unused, int subtest __maybe_unused)
102 {
103 	int err = 0, ret = 0;
104 
105 	if (perf_pmu__has_hybrid())
106 		return perf_evsel__name_array_test(evsel__hw_names, 2);
107 
108 	err = perf_evsel__name_array_test(evsel__hw_names, 1);
109 	if (err)
110 		ret = err;
111 
112 	err = __perf_evsel__name_array_test(evsel__sw_names, PERF_COUNT_SW_DUMMY + 1, 1);
113 	if (err)
114 		ret = err;
115 
116 	err = perf_evsel__roundtrip_cache_name_test();
117 	if (err)
118 		ret = err;
119 
120 	return ret;
121 }
122