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