pmu.c 19 KB

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