xref: /openbmc/linux/tools/perf/tests/pfm.c (revision a9d85efb)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Test support for libpfm4 event encodings.
4  *
5  * Copyright 2020 Google LLC.
6  */
7 #include "tests.h"
8 #include "util/debug.h"
9 #include "util/evlist.h"
10 #include "util/pfm.h"
11 
12 #include <linux/kernel.h>
13 
14 #ifdef HAVE_LIBPFM
15 static int test__pfm_events(void);
16 static int test__pfm_group(void);
17 #endif
18 
19 static const struct {
20 	int (*func)(void);
21 	const char *desc;
22 } pfm_testcase_table[] = {
23 #ifdef HAVE_LIBPFM
24 	{
25 		.func = test__pfm_events,
26 		.desc = "test of individual --pfm-events",
27 	},
28 	{
29 		.func = test__pfm_group,
30 		.desc = "test groups of --pfm-events",
31 	},
32 #endif
33 };
34 
35 #ifdef HAVE_LIBPFM
36 static int count_pfm_events(struct perf_evlist *evlist)
37 {
38 	struct perf_evsel *evsel;
39 	int count = 0;
40 
41 	perf_evlist__for_each_entry(evlist, evsel) {
42 		count++;
43 	}
44 	return count;
45 }
46 
47 static int test__pfm_events(void)
48 {
49 	struct evlist *evlist;
50 	struct option opt;
51 	size_t i;
52 	const struct {
53 		const char *events;
54 		int nr_events;
55 	} table[] = {
56 		{
57 			.events = "",
58 			.nr_events = 0,
59 		},
60 		{
61 			.events = "instructions",
62 			.nr_events = 1,
63 		},
64 		{
65 			.events = "instructions,cycles",
66 			.nr_events = 2,
67 		},
68 		{
69 			.events = "stereolab",
70 			.nr_events = 0,
71 		},
72 		{
73 			.events = "instructions,instructions",
74 			.nr_events = 2,
75 		},
76 		{
77 			.events = "stereolab,instructions",
78 			.nr_events = 0,
79 		},
80 		{
81 			.events = "instructions,stereolab",
82 			.nr_events = 1,
83 		},
84 	};
85 
86 	for (i = 0; i < ARRAY_SIZE(table); i++) {
87 		evlist = evlist__new();
88 		if (evlist == NULL)
89 			return -ENOMEM;
90 
91 		opt.value = evlist;
92 		parse_libpfm_events_option(&opt,
93 					table[i].events,
94 					0);
95 		TEST_ASSERT_EQUAL(table[i].events,
96 				count_pfm_events(&evlist->core),
97 				table[i].nr_events);
98 		TEST_ASSERT_EQUAL(table[i].events,
99 				evlist->core.nr_groups,
100 				0);
101 
102 		evlist__delete(evlist);
103 	}
104 	return 0;
105 }
106 
107 static int test__pfm_group(void)
108 {
109 	struct evlist *evlist;
110 	struct option opt;
111 	size_t i;
112 	const struct {
113 		const char *events;
114 		int nr_events;
115 		int nr_groups;
116 	} table[] = {
117 		{
118 			.events = "{},",
119 			.nr_events = 0,
120 			.nr_groups = 0,
121 		},
122 		{
123 			.events = "{instructions}",
124 			.nr_events = 1,
125 			.nr_groups = 1,
126 		},
127 		{
128 			.events = "{instructions},{}",
129 			.nr_events = 1,
130 			.nr_groups = 1,
131 		},
132 		{
133 			.events = "{},{instructions}",
134 			.nr_events = 1,
135 			.nr_groups = 1,
136 		},
137 		{
138 			.events = "{instructions},{instructions}",
139 			.nr_events = 2,
140 			.nr_groups = 2,
141 		},
142 		{
143 			.events = "{instructions,cycles},{instructions,cycles}",
144 			.nr_events = 4,
145 			.nr_groups = 2,
146 		},
147 		{
148 			.events = "{stereolab}",
149 			.nr_events = 0,
150 			.nr_groups = 0,
151 		},
152 		{
153 			.events =
154 			"{instructions,cycles},{instructions,stereolab}",
155 			.nr_events = 3,
156 			.nr_groups = 1,
157 		},
158 		{
159 			.events = "instructions}",
160 			.nr_events = 1,
161 			.nr_groups = 0,
162 		},
163 		{
164 			.events = "{{instructions}}",
165 			.nr_events = 0,
166 			.nr_groups = 0,
167 		},
168 	};
169 
170 	for (i = 0; i < ARRAY_SIZE(table); i++) {
171 		evlist = evlist__new();
172 		if (evlist == NULL)
173 			return -ENOMEM;
174 
175 		opt.value = evlist;
176 		parse_libpfm_events_option(&opt,
177 					table[i].events,
178 					0);
179 		TEST_ASSERT_EQUAL(table[i].events,
180 				count_pfm_events(&evlist->core),
181 				table[i].nr_events);
182 		TEST_ASSERT_EQUAL(table[i].events,
183 				evlist->core.nr_groups,
184 				table[i].nr_groups);
185 
186 		evlist__delete(evlist);
187 	}
188 	return 0;
189 }
190 #endif
191 
192 const char *test__pfm_subtest_get_desc(int i)
193 {
194 	if (i < 0 || i >= (int)ARRAY_SIZE(pfm_testcase_table))
195 		return NULL;
196 	return pfm_testcase_table[i].desc;
197 }
198 
199 int test__pfm_subtest_get_nr(void)
200 {
201 	return (int)ARRAY_SIZE(pfm_testcase_table);
202 }
203 
204 int test__pfm(struct test *test __maybe_unused, int i __maybe_unused)
205 {
206 #ifdef HAVE_LIBPFM
207 	if (i < 0 || i >= (int)ARRAY_SIZE(pfm_testcase_table))
208 		return TEST_FAIL;
209 	return pfm_testcase_table[i].func();
210 #else
211 	return TEST_SKIP;
212 #endif
213 }
214