#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, }
 };