perf tests: Add test for PMU aliases
authorJin Yao <yao.jin@linux.intel.com>
Thu, 2 Sep 2021 06:59:55 +0000 (14:59 +0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 3 Sep 2021 11:38:49 +0000 (08:38 -0300)
A perf uncore PMU may have two PMU names, a real name and an alias.

Add one test case to verify that the real and alias names have the same
effect.

Iterate sysfs to get one event which has an alias and create an evlist
by adding two evsels. Evsel1 is created by event and evsel2 is created
by alias.

Test asserts:

  evsel1->core.attr.type == evsel2->core.attr.type
  evsel1->core.attr.config == evsel2->core.attr.config

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jin Yao <yao.jin@intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.garry@huawei.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Riccardo Mancini <rickyman7@gmail.com>
Link: http://lore.kernel.org/lkml/20210902065955.1299-3-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/tests/parse-events.c

index 8d48667..fd3556c 100644 (file)
@@ -9,6 +9,7 @@
 #include "pmu-hybrid.h"
 #include <dirent.h>
 #include <errno.h>
+#include "fncache.h"
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -2194,9 +2195,91 @@ static int test_pmu_events(void)
        return ret;
 }
 
+static bool test_alias(char **event, char **alias)
+{
+       char path[PATH_MAX];
+       DIR *dir;
+       struct dirent *dent;
+       const char *sysfs = sysfs__mountpoint();
+       char buf[128];
+       FILE *file;
+
+       if (!sysfs)
+               return false;
+
+       snprintf(path, PATH_MAX, "%s/bus/event_source/devices/", sysfs);
+       dir = opendir(path);
+       if (!dir)
+               return false;
+
+       while ((dent = readdir(dir))) {
+               if (!strcmp(dent->d_name, ".") ||
+                   !strcmp(dent->d_name, ".."))
+                       continue;
+
+               snprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s/alias",
+                        sysfs, dent->d_name);
+
+               if (!file_available(path))
+                       continue;
+
+               file = fopen(path, "r");
+               if (!file)
+                       continue;
+
+               if (!fgets(buf, sizeof(buf), file)) {
+                       fclose(file);
+                       continue;
+               }
+
+               /* Remove the last '\n' */
+               buf[strlen(buf) - 1] = 0;
+
+               fclose(file);
+               *event = strdup(dent->d_name);
+               *alias = strdup(buf);
+               closedir(dir);
+
+               if (*event == NULL || *alias == NULL) {
+                       free(*event);
+                       free(*alias);
+                       return false;
+               }
+
+               return true;
+       }
+
+       closedir(dir);
+       return false;
+}
+
+static int test__checkevent_pmu_events_alias(struct evlist *evlist)
+{
+       struct evsel *evsel1 = evlist__first(evlist);
+       struct evsel *evsel2 = evlist__last(evlist);
+
+       TEST_ASSERT_VAL("wrong type", evsel1->core.attr.type == evsel2->core.attr.type);
+       TEST_ASSERT_VAL("wrong config", evsel1->core.attr.config == evsel2->core.attr.config);
+       return 0;
+}
+
+static int test_pmu_events_alias(char *event, char *alias)
+{
+       struct evlist_test e = { .id = 0, };
+       char name[2 * NAME_MAX + 20];
+
+       snprintf(name, sizeof(name), "%s/event=1/,%s/event=1/",
+                event, alias);
+
+       e.name  = name;
+       e.check = test__checkevent_pmu_events_alias;
+       return test_event(&e);
+}
+
 int test__parse_events(struct test *test __maybe_unused, int subtest __maybe_unused)
 {
        int ret1, ret2 = 0;
+       char *event, *alias;
 
 #define TEST_EVENTS(tests)                             \
 do {                                                   \
@@ -2221,6 +2304,15 @@ do {                                                     \
                        return ret;
        }
 
+       if (test_alias(&event, &alias)) {
+               int ret = test_pmu_events_alias(event, alias);
+
+               free(event);
+               free(alias);
+               if (ret)
+                       return ret;
+       }
+
        ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms));
        if (!ret2)
                ret2 = ret1;