xref: /linux/tools/perf/tests/pfm.c (revision b77e0ce62d63a761ffb7f7245a215a49f5921c2f)
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->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 = 0,
135 			.nr_groups = 0,
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 
160 	for (i = 0; i < ARRAY_SIZE(table); i++) {
161 		evlist = evlist__new();
162 		if (evlist == NULL)
163 			return -ENOMEM;
164 
165 		opt.value = evlist;
166 		parse_libpfm_events_option(&opt,
167 					table[i].events,
168 					0);
169 		TEST_ASSERT_EQUAL(table[i].events,
170 				count_pfm_events(&evlist->core),
171 				table[i].nr_events);
172 		TEST_ASSERT_EQUAL(table[i].events,
173 				evlist->nr_groups,
174 				table[i].nr_groups);
175 
176 		evlist__delete(evlist);
177 	}
178 	return 0;
179 }
180 #endif
181 
182 const char *test__pfm_subtest_get_desc(int i)
183 {
184 	if (i < 0 || i >= (int)ARRAY_SIZE(pfm_testcase_table))
185 		return NULL;
186 	return pfm_testcase_table[i].desc;
187 }
188 
189 int test__pfm_subtest_get_nr(void)
190 {
191 	return (int)ARRAY_SIZE(pfm_testcase_table);
192 }
193 
194 int test__pfm(struct test *test __maybe_unused, int i __maybe_unused)
195 {
196 #ifdef HAVE_LIBPFM
197 	if (i < 0 || i >= (int)ARRAY_SIZE(pfm_testcase_table))
198 		return TEST_FAIL;
199 	return pfm_testcase_table[i].func();
200 #else
201 	return TEST_SKIP;
202 #endif
203 }
204