1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
5 #include "parse-events.h"
9 #include <linux/compiler.h>
10 #include <linux/kernel.h>
11 #include <linux/string.h>
13 static const struct test_event
{
19 "temp_test_hwmon_event1",
24 "temp_test_hwmon_event2",
30 /* Cleanup test PMU directory. */
31 static int test_pmu_put(const char *dir
, struct perf_pmu
*hwm
)
33 char buf
[PATH_MAX
+ 20];
36 if (scnprintf(buf
, sizeof(buf
), "rm -fr %s", dir
) < 0) {
37 pr_err("Failure to set up buffer for \"%s\"\n", dir
);
42 pr_err("Failure to \"%s\"\n", buf
);
45 perf_pmu__delete(hwm
);
50 * Prepare test PMU directory data, normally exported by kernel at
51 * /sys/class/hwmon/hwmon<number>/. Give as input a buffer to hold the file
52 * path, the result is PMU loaded using that directory.
54 static struct perf_pmu
*test_pmu_get(char *dir
, size_t sz
)
56 const char *test_hwmon_name_nl
= "A test hwmon PMU\n";
57 const char *test_hwmon_name
= "A test hwmon PMU";
58 /* Simulated hwmon items. */
59 const struct test_item
{
63 { "temp1_label", "test hwmon event1\n", },
64 { "temp1_input", "40000\n", },
65 { "temp2_label", "test hwmon event2\n", },
66 { "temp2_input", "50000\n", },
69 struct perf_pmu
*hwm
= NULL
;
72 /* Create equivalent of sysfs mount point. */
73 scnprintf(dir
, sz
, "/tmp/perf-hwmon-pmu-test-XXXXXX");
75 pr_err("mkdtemp failed\n");
79 dirfd
= open(dir
, O_DIRECTORY
);
81 pr_err("Failed to open test directory \"%s\"\n", dir
);
85 /* Create the test hwmon directory and give it a name. */
86 if (mkdirat(dirfd
, "hwmon1234", 0755) < 0) {
87 pr_err("Failed to mkdir hwmon directory\n");
90 file
= openat(dirfd
, "hwmon1234/name", O_WRONLY
| O_CREAT
, 0600);
92 pr_err("Failed to open for writing file \"name\"\n");
95 len
= strlen(test_hwmon_name_nl
);
96 if (write(file
, test_hwmon_name_nl
, len
) < len
) {
98 pr_err("Failed to write to 'name' file\n");
103 /* Create test hwmon files. */
104 for (size_t i
= 0; i
< ARRAY_SIZE(test_items
); i
++) {
105 const struct test_item
*item
= &test_items
[i
];
107 file
= openat(dirfd
, item
->name
, O_WRONLY
| O_CREAT
, 0600);
109 pr_err("Failed to open for writing file \"%s\"\n", item
->name
);
113 if (write(file
, item
->value
, strlen(item
->value
)) < 0) {
114 pr_err("Failed to write to file \"%s\"\n", item
->name
);
121 /* Make the PMU reading the files created above. */
122 hwm
= perf_pmus__add_test_hwmon_pmu(dirfd
, "hwmon1234", test_hwmon_name
);
124 pr_err("Test hwmon creation failed\n");
128 test_pmu_put(dir
, hwm
);
135 static int do_test(size_t i
, bool with_pmu
, bool with_alias
)
137 const char *test_event
= with_alias
? test_events
[i
].alias
: test_events
[i
].name
;
138 struct evlist
*evlist
= evlist__new();
140 struct parse_events_error err
;
146 pr_err("evlist allocation failed\n");
151 snprintf(str
, sizeof(str
), "hwmon_a_test_hwmon_pmu/%s/", test_event
);
153 strlcpy(str
, test_event
, sizeof(str
));
155 pr_debug("Testing '%s'\n", str
);
156 parse_events_error__init(&err
);
157 ret
= parse_events(evlist
, str
, &err
);
159 pr_debug("FAILED %s:%d failed to parse event '%s', err %d\n",
160 __FILE__
, __LINE__
, str
, ret
);
161 parse_events_error__print(&err
, str
);
167 if (with_pmu
? (evlist
->core
.nr_entries
!= 1) : (evlist
->core
.nr_entries
< 1)) {
168 pr_debug("FAILED %s:%d Unexpected number of events for '%s' of %d\n",
169 __FILE__
, __LINE__
, str
, evlist
->core
.nr_entries
);
174 evlist__for_each_entry(evlist
, evsel
) {
175 if (!evsel
->pmu
|| !evsel
->pmu
->name
||
176 strcmp(evsel
->pmu
->name
, "hwmon_a_test_hwmon_pmu"))
179 if (evsel
->core
.attr
.config
!= (u64
)test_events
[i
].config
) {
180 pr_debug("FAILED %s:%d Unexpected config for '%s', %lld != %ld\n",
181 __FILE__
, __LINE__
, str
,
182 evsel
->core
.attr
.config
,
183 test_events
[i
].config
);
191 pr_debug("FAILED %s:%d Didn't find hwmon event '%s' in parsed evsels\n",
192 __FILE__
, __LINE__
, str
);
197 parse_events_error__exit(&err
);
198 evlist__delete(evlist
);
202 static int test__hwmon_pmu(bool with_pmu
)
205 struct perf_pmu
*pmu
= test_pmu_get(dir
, sizeof(dir
));
211 for (size_t i
= 0; i
< ARRAY_SIZE(test_events
); i
++) {
212 ret
= do_test(i
, with_pmu
, /*with_alias=*/false);
217 ret
= do_test(i
, with_pmu
, /*with_alias=*/true);
222 test_pmu_put(dir
, pmu
);
226 static int test__hwmon_pmu_without_pmu(struct test_suite
*test __maybe_unused
,
227 int subtest __maybe_unused
)
229 return test__hwmon_pmu(/*with_pmu=*/false);
232 static int test__hwmon_pmu_with_pmu(struct test_suite
*test __maybe_unused
,
233 int subtest __maybe_unused
)
235 return test__hwmon_pmu(/*with_pmu=*/true);
238 static int test__parse_hwmon_filename(struct test_suite
*test __maybe_unused
,
239 int subtest __maybe_unused
)
241 const struct hwmon_parse_test
{
242 const char *filename
;
243 enum hwmon_type type
;
245 enum hwmon_item item
;
250 .filename
= "cpu0_accuracy",
251 .type
= HWMON_TYPE_CPU
,
253 .item
= HWMON_ITEM_ACCURACY
,
258 .filename
= "temp1_input",
259 .type
= HWMON_TYPE_TEMP
,
261 .item
= HWMON_ITEM_INPUT
,
266 .filename
= "fan2_vid",
267 .type
= HWMON_TYPE_FAN
,
269 .item
= HWMON_ITEM_VID
,
274 .filename
= "power3_crit_alarm",
275 .type
= HWMON_TYPE_POWER
,
277 .item
= HWMON_ITEM_CRIT
,
282 .filename
= "intrusion4_average_interval_min_alarm",
283 .type
= HWMON_TYPE_INTRUSION
,
285 .item
= HWMON_ITEM_AVERAGE_INTERVAL_MIN
,
290 .filename
= "badtype5_baditem",
291 .type
= HWMON_TYPE_NONE
,
293 .item
= HWMON_ITEM_NONE
,
298 .filename
= "humidity6_baditem",
299 .type
= HWMON_TYPE_NONE
,
301 .item
= HWMON_ITEM_NONE
,
307 for (size_t i
= 0; i
< ARRAY_SIZE(tests
); i
++) {
308 enum hwmon_type type
;
310 enum hwmon_item item
;
313 TEST_ASSERT_EQUAL("parse_hwmon_filename",
314 parse_hwmon_filename(
322 if (tests
[i
].parse_ok
) {
323 TEST_ASSERT_EQUAL("parse_hwmon_filename type", type
, tests
[i
].type
);
324 TEST_ASSERT_EQUAL("parse_hwmon_filename number", number
, tests
[i
].number
);
325 TEST_ASSERT_EQUAL("parse_hwmon_filename item", item
, tests
[i
].item
);
326 TEST_ASSERT_EQUAL("parse_hwmon_filename alarm", alarm
, tests
[i
].alarm
);
332 static struct test_case tests__hwmon_pmu
[] = {
333 TEST_CASE("Basic parsing test", parse_hwmon_filename
),
334 TEST_CASE("Parsing without PMU name", hwmon_pmu_without_pmu
),
335 TEST_CASE("Parsing with PMU name", hwmon_pmu_with_pmu
),
339 struct test_suite suite__hwmon_pmu
= {
341 .test_cases
= tests__hwmon_pmu
,