[PATCH v2 5/6] perf test pmu: Test all sysfs PMU event names are lowercase

Ian Rogers
2024-04-23T03:17:50Z

Being lowercase means event name probes can avoid scanning the
directory doing case insensitive comparisons, just the lowercase
version of the name can be checked for existence.

Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/tests/pmu.c | 75 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)

diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index f4e9a39534cb..c49e790248cd 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -5,12 +5,17 @@
#include "pmu.h"
#include "tests.h"
#include "debug.h"
+#include "fncache.h"
+#include <api/fs/fs.h>
+#include <ctype.h>
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
+#include <sys/types.h>

/* Fake PMUs created in temp directory. */
static LIST_HEAD(test_pmus);
@@ -241,9 +246,79 @@ static int test__pmu_events(struct test_suite *test __maybe_unused, int subtest
return ret;
}

+static bool permitted_event_name_char(char c)
+{
+ if (islower(c) || isdigit(c))
+ return true;
+
+ return c == '.' || c == '_' || c == '-';
+}
+
+static int test__pmu_event_names(struct test_suite *test __maybe_unused,
+ int subtest __maybe_unused)
+{
+ char path[PATH_MAX];
+ DIR *pmu_dir, *event_dir;
+ struct dirent *pmu_dent, *event_dent;
+ const char *sysfs = sysfs__mountpoint();
+ int ret = TEST_OK;
+
+ if (!sysfs) {
+ pr_err("Sysfs not mounted\n");
+ return TEST_FAIL;
+ }
+
+ snprintf(path, sizeof(path), "%s/bus/event_source/devices/", sysfs);
+ pmu_dir = opendir(path);
+ if (!pmu_dir) {
+ pr_err("Error opening \"%s\"\n", path);
+ return TEST_FAIL;
+ }
+ while ((pmu_dent = readdir(pmu_dir))) {
+ if (!strcmp(pmu_dent->d_name, ".") ||
+ !strcmp(pmu_dent->d_name, ".."))
+ continue;
+
+ snprintf(path, sizeof(path), "%s/bus/event_source/devices/%s/type",
+ sysfs, pmu_dent->d_name);
+
+ /* Does it look like a PMU? */
+ if (!file_available(path))
+ continue;
+
+ /* Process events. */
+ snprintf(path, sizeof(path), "%s/bus/event_source/devices/%s/events",
+ sysfs, pmu_dent->d_name);
+
+ event_dir = opendir(path);
+ if (!event_dir) {
+ pr_debug("No event directory \"%s\"\n", path);
+ continue;
+ }
+ while ((event_dent = readdir(event_dir))) {
+ const char *event_name = event_dent->d_name;
+
+ if (!strcmp(event_name, ".") || !strcmp(event_name, ".."))
+ continue;
+
+ for (size_t i = 0, n = strlen(event_name); i < n; i++) {
+ if (!permitted_event_name_char(event_name[i])) {
+ pr_err("Sysfs event names should be lower case \"%s/%s\"\n",
+ pmu_dent->d_name, event_name);
+ ret = TEST_FAIL;
+ }
+ }
+ }
+ closedir(event_dir);
+ }
+ closedir(pmu_dir);
+ return ret;
+}
+
static struct test_case tests__pmu[] = {
TEST_CASE("Parsing with PMU format directory", pmu_format),
TEST_CASE("Parsing with PMU event", pmu_events),
+ TEST_CASE("PMU event names", pmu_event_names),
{ .name = NULL, }
};

--
2.44.0.769.g3c40516874-goog