#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);
return ret;
}
+static bool permitted_event_name(const char *name)
+{
+ bool has_lower = false, has_upper = false;
+
+ for (size_t i = 0; i < strlen(name); i++) {
+ char c = name[i];
+
+ if (islower(c)) {
+ if (has_upper)
+ return false;
+ has_lower = true;
+ continue;
+ }
+ if (isupper(c)) {
+ if (has_lower)
+ return false;
+ has_upper = true;
+ continue;
+ }
+ if (!isdigit(c) && c != '.' && c != '_' && c != '-')
+ return false;
+ }
+ return true;
+}
+
+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("Skipping as 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;
+
+ if (!permitted_event_name(event_name)) {
+ pr_err("Invalid sysfs event name: %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, }
};