summaryrefslogtreecommitdiff
path: root/tools/perf/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/tests')
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/builtin-test-list.c207
-rw-r--r--tools/perf/tests/builtin-test-list.h12
-rw-r--r--tools/perf/tests/builtin-test.c152
-rw-r--r--tools/perf/tests/code-reading.c2
-rw-r--r--tools/perf/tests/event-times.c2
-rw-r--r--tools/perf/tests/evsel-roundtrip-name.c4
-rw-r--r--tools/perf/tests/expand-cgroup.c25
-rw-r--r--tools/perf/tests/hists_cumulate.c2
-rw-r--r--tools/perf/tests/hists_filter.c4
-rw-r--r--tools/perf/tests/hists_link.c4
-rw-r--r--tools/perf/tests/hists_output.c2
-rw-r--r--tools/perf/tests/keep-tracking.c4
-rw-r--r--tools/perf/tests/parse-metric.c77
-rw-r--r--tools/perf/tests/perf-time-to-tsc.c4
-rw-r--r--tools/perf/tests/pmu-events.c466
-rw-r--r--tools/perf/tests/shell/lib/perf_json_output_lint.py96
-rwxr-xr-xtools/perf/tests/shell/record_offcpu.sh57
-rwxr-xr-xtools/perf/tests/shell/stat+json_output.sh147
-rw-r--r--tools/perf/tests/switch-tracking.c24
20 files changed, 757 insertions, 535 deletions
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index af2b37ef7c70..2064a640facb 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
perf-y += builtin-test.o
+perf-y += builtin-test-list.o
perf-y += parse-events.o
perf-y += dso-data.o
perf-y += attr.o
diff --git a/tools/perf/tests/builtin-test-list.c b/tools/perf/tests/builtin-test-list.c
new file mode 100644
index 000000000000..a65b9e547d82
--- /dev/null
+++ b/tools/perf/tests/builtin-test-list.c
@@ -0,0 +1,207 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/zalloc.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <subcmd/exec-cmd.h>
+#include <subcmd/parse-options.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include "builtin.h"
+#include "builtin-test-list.h"
+#include "color.h"
+#include "debug.h"
+#include "hist.h"
+#include "intlist.h"
+#include "string2.h"
+#include "symbol.h"
+#include "tests.h"
+#include "util/rlimit.h"
+
+
+/*
+ * As this is a singleton built once for the run of the process, there is
+ * no value in trying to free it and just let it stay around until process
+ * exits when it's cleaned up.
+ */
+static size_t files_num = 0;
+static struct script_file *files = NULL;
+static int files_max_width = 0;
+
+static const char *shell_tests__dir(char *path, size_t size)
+{
+ const char *devel_dirs[] = { "./tools/perf/tests", "./tests", };
+ char *exec_path;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(devel_dirs); ++i) {
+ struct stat st;
+
+ if (!lstat(devel_dirs[i], &st)) {
+ scnprintf(path, size, "%s/shell", devel_dirs[i]);
+ if (!lstat(devel_dirs[i], &st))
+ return path;
+ }
+ }
+
+ /* Then installed path. */
+ exec_path = get_argv_exec_path();
+ scnprintf(path, size, "%s/tests/shell", exec_path);
+ free(exec_path);
+ return path;
+}
+
+static const char *shell_test__description(char *description, size_t size,
+ const char *path, const char *name)
+{
+ FILE *fp;
+ char filename[PATH_MAX];
+ int ch;
+
+ path__join(filename, sizeof(filename), path, name);
+ fp = fopen(filename, "r");
+ if (!fp)
+ return NULL;
+
+ /* Skip first line - should be #!/bin/sh Shebang */
+ do {
+ ch = fgetc(fp);
+ } while (ch != EOF && ch != '\n');
+
+ description = fgets(description, size, fp);
+ fclose(fp);
+
+ /* Assume first char on line is omment everything after that desc */
+ return description ? strim(description + 1) : NULL;
+}
+
+/* Is this full file path a shell script */
+static bool is_shell_script(const char *path)
+{
+ const char *ext;
+
+ ext = strrchr(path, '.');
+ if (!ext)
+ return false;
+ if (!strcmp(ext, ".sh")) { /* Has .sh extension */
+ if (access(path, R_OK | X_OK) == 0) /* Is executable */
+ return true;
+ }
+ return false;
+}
+
+/* Is this file in this dir a shell script (for test purposes) */
+static bool is_test_script(const char *path, const char *name)
+{
+ char filename[PATH_MAX];
+
+ path__join(filename, sizeof(filename), path, name);
+ if (!is_shell_script(filename)) return false;
+ return true;
+}
+
+/* Duplicate a string and fall over and die if we run out of memory */
+static char *strdup_check(const char *str)
+{
+ char *newstr;
+
+ newstr = strdup(str);
+ if (!newstr) {
+ pr_err("Out of memory while duplicating test script string\n");
+ abort();
+ }
+ return newstr;
+}
+
+static void append_script(const char *dir, const char *file, const char *desc)
+{
+ struct script_file *files_tmp;
+ size_t files_num_tmp;
+ int width;
+
+ files_num_tmp = files_num + 1;
+ if (files_num_tmp >= SIZE_MAX) {
+ pr_err("Too many script files\n");
+ abort();
+ }
+ /* Realloc is good enough, though we could realloc by chunks, not that
+ * anyone will ever measure performance here */
+ files_tmp = realloc(files,
+ (files_num_tmp + 1) * sizeof(struct script_file));
+ if (files_tmp == NULL) {
+ pr_err("Out of memory while building test list\n");
+ abort();
+ }
+ /* Add file to end and NULL terminate the struct array */
+ files = files_tmp;
+ files_num = files_num_tmp;
+ files[files_num - 1].dir = strdup_check(dir);
+ files[files_num - 1].file = strdup_check(file);
+ files[files_num - 1].desc = strdup_check(desc);
+ files[files_num].dir = NULL;
+ files[files_num].file = NULL;
+ files[files_num].desc = NULL;
+
+ width = strlen(desc); /* Track max width of desc */
+ if (width > files_max_width)
+ files_max_width = width;
+}
+
+static void append_scripts_in_dir(const char *path)
+{
+ struct dirent **entlist;
+ struct dirent *ent;
+ int n_dirs, i;
+ char filename[PATH_MAX];
+
+ /* List files, sorted by alpha */
+ n_dirs = scandir(path, &entlist, NULL, alphasort);
+ if (n_dirs == -1)
+ return;
+ for (i = 0; i < n_dirs && (ent = entlist[i]); i++) {
+ if (ent->d_name[0] == '.')
+ continue; /* Skip hidden files */
+ if (is_test_script(path, ent->d_name)) { /* It's a test */
+ char bf[256];
+ const char *desc = shell_test__description
+ (bf, sizeof(bf), path, ent->d_name);
+
+ if (desc) /* It has a desc line - valid script */
+ append_script(path, ent->d_name, desc);
+ } else if (is_directory(path, ent)) { /* Scan the subdir */
+ path__join(filename, sizeof(filename),
+ path, ent->d_name);
+ append_scripts_in_dir(filename);
+ }
+ }
+ for (i = 0; i < n_dirs; i++) /* Clean up */
+ zfree(&entlist[i]);
+ free(entlist);
+}
+
+const struct script_file *list_script_files(void)
+{
+ char path_dir[PATH_MAX];
+ const char *path;
+
+ if (files)
+ return files; /* Singleton - we already know our list */
+
+ path = shell_tests__dir(path_dir, sizeof(path_dir)); /* Walk dir */
+ append_scripts_in_dir(path);
+
+ return files;
+}
+
+int list_script_max_width(void)
+{
+ list_script_files(); /* Ensure we have scanned all scripts */
+ return files_max_width;
+}
diff --git a/tools/perf/tests/builtin-test-list.h b/tools/perf/tests/builtin-test-list.h
new file mode 100644
index 000000000000..eb81f3aa6683
--- /dev/null
+++ b/tools/perf/tests/builtin-test-list.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+struct script_file {
+ char *dir;
+ char *file;
+ char *desc;
+};
+
+/* List available script tests to run - singleton - never freed */
+const struct script_file *list_script_files(void);
+/* Get maximum width of description string */
+int list_script_max_width(void);
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 81cf241cd109..7122eae1d98d 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -28,6 +28,8 @@
#include <subcmd/exec-cmd.h>
#include <linux/zalloc.h>
+#include "builtin-test-list.h"
+
static bool dont_fork;
struct test_suite *__weak arch_tests[] = {
@@ -274,91 +276,6 @@ static int test_and_print(struct test_suite *t, int subtest)
return err;
}
-static const char *shell_test__description(char *description, size_t size,
- const char *path, const char *name)
-{
- FILE *fp;
- char filename[PATH_MAX];
- int ch;
-
- path__join(filename, sizeof(filename), path, name);
- fp = fopen(filename, "r");
- if (!fp)
- return NULL;
-
- /* Skip shebang */
- do {
- ch = fgetc(fp);
- } while (ch != EOF && ch != '\n');
-
- description = fgets(description, size, fp);
- fclose(fp);
-
- return description ? strim(description + 1) : NULL;
-}
-
-#define for_each_shell_test(entlist, nr, base, ent) \
- for (int __i = 0; __i < nr && (ent = entlist[__i]); __i++) \
- if (!is_directory(base, ent) && \
- is_executable_file(base, ent) && \
- ent->d_name[0] != '.')
-
-static const char *shell_tests__dir(char *path, size_t size)
-{
- const char *devel_dirs[] = { "./tools/perf/tests", "./tests", };
- char *exec_path;
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(devel_dirs); ++i) {
- struct stat st;
- if (!lstat(devel_dirs[i], &st)) {
- scnprintf(path, size, "%s/shell", devel_dirs[i]);
- if (!lstat(devel_dirs[i], &st))
- return path;
- }
- }
-
- /* Then installed path. */
- exec_path = get_argv_exec_path();
- scnprintf(path, size, "%s/tests/shell", exec_path);
- free(exec_path);
- return path;
-}
-
-static int shell_tests__max_desc_width(void)
-{
- struct dirent **entlist;
- struct dirent *ent;
- int n_dirs, e;
- char path_dir[PATH_MAX];
- const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
- int width = 0;
-
- if (path == NULL)
- return -1;
-
- n_dirs = scandir(path, &entlist, NULL, alphasort);
- if (n_dirs == -1)
- return -1;
-
- for_each_shell_test(entlist, n_dirs, path, ent) {
- char bf[256];
- const char *desc = shell_test__description(bf, sizeof(bf), path, ent->d_name);
-
- if (desc) {
- int len = strlen(desc);
-
- if (width < len)
- width = len;
- }
- }
-
- for (e = 0; e < n_dirs; e++)
- zfree(&entlist[e]);
- free(entlist);
- return width;
-}
-
struct shell_test {
const char *dir;
const char *file;
@@ -385,33 +302,17 @@ static int shell_test__run(struct test_suite *test, int subdir __maybe_unused)
static int run_shell_tests(int argc, const char *argv[], int i, int width,
struct intlist *skiplist)
{
- struct dirent **entlist;
- struct dirent *ent;
- int n_dirs, e;
- char path_dir[PATH_MAX];
- struct shell_test st = {
- .dir = shell_tests__dir(path_dir, sizeof(path_dir)),
- };
-
- if (st.dir == NULL)
- return -1;
+ struct shell_test st;
+ const struct script_file *files, *file;
- n_dirs = scandir(st.dir, &entlist, NULL, alphasort);
- if (n_dirs == -1) {
- pr_err("failed to open shell test directory: %s\n",
- st.dir);
- return -1;
- }
-
- for_each_shell_test(entlist, n_dirs, st.dir, ent) {
+ files = list_script_files();
+ if (!files)
+ return 0;
+ for (file = files; file->dir; file++) {
int curr = i++;
- char desc[256];
struct test_case test_cases[] = {
{
- .desc = shell_test__description(desc,
- sizeof(desc),
- st.dir,
- ent->d_name),
+ .desc = file->desc,
.run_case = shell_test__run,
},
{ .name = NULL, }
@@ -421,12 +322,13 @@ static int run_shell_tests(int argc, const char *argv[], int i, int width,
.test_cases = test_cases,
.priv = &st,
};
+ st.dir = file->dir;
if (test_suite.desc == NULL ||
!perf_test__matches(test_suite.desc, curr, argc, argv))
continue;
- st.file = ent->d_name;
+ st.file = file->file;
pr_info("%3d: %-*s:", i, width, test_suite.desc);
if (intlist__find(skiplist, i)) {
@@ -436,10 +338,6 @@ static int run_shell_tests(int argc, const char *argv[], int i, int width,
test_and_print(&test_suite, 0);
}
-
- for (e = 0; e < n_dirs; e++)
- zfree(&entlist[e]);
- free(entlist);
return 0;
}
@@ -448,7 +346,7 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
struct test_suite *t;
unsigned int j, k;
int i = 0;
- int width = shell_tests__max_desc_width();
+ int width = list_script_max_width();
for_each_test(j, k, t) {
int len = strlen(test_description(t, -1));
@@ -529,36 +427,22 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
static int perf_test__list_shell(int argc, const char **argv, int i)
{
- struct dirent **entlist;
- struct dirent *ent;
- int n_dirs, e;
- char path_dir[PATH_MAX];
- const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
-
- if (path == NULL)
- return -1;
+ const struct script_file *files, *file;
- n_dirs = scandir(path, &entlist, NULL, alphasort);
- if (n_dirs == -1)
- return -1;
-
- for_each_shell_test(entlist, n_dirs, path, ent) {
+ files = list_script_files();
+ if (!files)
+ return 0;
+ for (file = files; file->dir; file++) {
int curr = i++;
- char bf[256];
struct test_suite t = {
- .desc = shell_test__description(bf, sizeof(bf), path, ent->d_name),
+ .desc = file->desc
};
if (!perf_test__matches(t.desc, curr, argc, argv))
continue;
pr_info("%3d: %s\n", i, t.desc);
-
}
-
- for (e = 0; e < n_dirs; e++)
- zfree(&entlist[e]);
- free(entlist);
return 0;
}
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 5610767b407f..95feb6ef34a0 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -638,7 +638,7 @@ static int do_test_code_reading(bool try_kcore)
str = do_determine_event(excl_kernel);
pr_debug("Parsing event '%s'\n", str);
- ret = parse_events(evlist, str, NULL);
+ ret = parse_event(evlist, str);
if (ret < 0) {
pr_debug("parse_events failed\n");
goto out_put;
diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c
index 7606eb3df92f..e155f0e0e04d 100644
--- a/tools/perf/tests/event-times.c
+++ b/tools/perf/tests/event-times.c
@@ -174,7 +174,7 @@ static int test_times(int (attach)(struct evlist *),
goto out_err;
}
- err = parse_events(evlist, "cpu-clock:u", NULL);
+ err = parse_event(evlist, "cpu-clock:u");
if (err) {
pr_debug("failed to parse event cpu-clock:u\n");
goto out_err;
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c
index 9d3c64974f77..e94fed901992 100644
--- a/tools/perf/tests/evsel-roundtrip-name.c
+++ b/tools/perf/tests/evsel-roundtrip-name.c
@@ -27,7 +27,7 @@ static int perf_evsel__roundtrip_cache_name_test(void)
for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
__evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name));
- err = parse_events(evlist, name, NULL);
+ err = parse_event(evlist, name);
if (err)
ret = err;
}
@@ -75,7 +75,7 @@ static int __perf_evsel__name_array_test(const char *const names[], int nr_names
return -ENOMEM;
for (i = 0; i < nr_names; ++i) {
- err = parse_events(evlist, names[i], NULL);
+ err = parse_event(evlist, names[i]);
if (err) {
pr_debug("failed to parse event '%s', err %d\n",
names[i], err);
diff --git a/tools/perf/tests/expand-cgroup.c b/tools/perf/tests/expand-cgroup.c
index dfefe5b60eb2..51fb5f34c1dd 100644
--- a/tools/perf/tests/expand-cgroup.c
+++ b/tools/perf/tests/expand-cgroup.c
@@ -180,33 +180,14 @@ static int expand_metric_events(void)
struct evlist *evlist;
struct rblist metric_events;
const char metric_str[] = "CPI";
-
- struct pmu_event pme_test[] = {
- {
- .metric_expr = "instructions / cycles",
- .metric_name = "IPC",
- },
- {
- .metric_expr = "1 / IPC",
- .metric_name = "CPI",
- },
- {
- .metric_expr = NULL,
- .metric_name = NULL,
- },
- };
- const struct pmu_events_map ev_map = {
- .cpuid = "test",
- .version = "1",
- .type = "core",
- .table = pme_test,
- };
+ const struct pmu_events_table *pme_test;
evlist = evlist__new();
TEST_ASSERT_VAL("failed to get evlist", evlist);
rblist__init(&metric_events);
- ret = metricgroup__parse_groups_test(evlist, &ev_map, metric_str,
+ pme_test = find_core_events_table("testarch", "testcpu");
+ ret = metricgroup__parse_groups_test(evlist, pme_test, metric_str,
false, false, &metric_events);
if (ret < 0) {
pr_debug("failed to parse '%s' metric\n", metric_str);
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 17f4fcd6bdce..b42d37ff2399 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -706,7 +706,7 @@ static int test__hists_cumulate(struct test_suite *test __maybe_unused, int subt
TEST_ASSERT_VAL("No memory", evlist);
- err = parse_events(evlist, "cpu-clock", NULL);
+ err = parse_event(evlist, "cpu-clock");
if (err)
goto out;
err = TEST_FAIL;
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 08cbeb9e39ae..8e1ceeb9b7b6 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -111,10 +111,10 @@ static int test__hists_filter(struct test_suite *test __maybe_unused, int subtes
TEST_ASSERT_VAL("No memory", evlist);
- err = parse_events(evlist, "cpu-clock", NULL);
+ err = parse_event(evlist, "cpu-clock");
if (err)
goto out;
- err = parse_events(evlist, "task-clock", NULL);
+ err = parse_event(evlist, "task-clock");
if (err)
goto out;
err = TEST_FAIL;
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index c575e13a850d..14b2ff808b5e 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -276,10 +276,10 @@ static int test__hists_link(struct test_suite *test __maybe_unused, int subtest
if (evlist == NULL)
return -ENOMEM;
- err = parse_events(evlist, "cpu-clock", NULL);
+ err = parse_event(evlist, "cpu-clock");
if (err)
goto out;
- err = parse_events(evlist, "task-clock", NULL);
+ err = parse_event(evlist, "task-clock");
if (err)
goto out;
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index 0bde4a768c15..62b0093253e3 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -593,7 +593,7 @@ static int test__hists_output(struct test_suite *test __maybe_unused, int subtes
TEST_ASSERT_VAL("No memory", evlist);
- err = parse_events(evlist, "cpu-clock", NULL);
+ err = parse_event(evlist, "cpu-clock");
if (err)
goto out;
err = TEST_FAIL;
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index dd2067312452..8f4f9b632e1e 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -89,8 +89,8 @@ static int test__keep_tracking(struct test_suite *test __maybe_unused, int subte
perf_evlist__set_maps(&evlist->core, cpus, threads);
- CHECK__(parse_events(evlist, "dummy:u", NULL));
- CHECK__(parse_events(evlist, "cycles:u", NULL));
+ CHECK__(parse_event(evlist, "dummy:u"));
+ CHECK__(parse_event(evlist, "cycles:u"));
evlist__config(evlist, &opts, NULL);
diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c
index 07b6f4ec024f..68f5a2a03242 100644
--- a/tools/perf/tests/parse-metric.c
+++ b/tools/perf/tests/parse-metric.c
@@ -13,79 +13,6 @@
#include "stat.h"
#include "pmu.h"
-static struct pmu_event pme_test[] = {
-{
- .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread",
- .metric_name = "IPC",
- .metric_group = "group1",
-},
-{
- .metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * "
- "( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))",
- .metric_name = "Frontend_Bound_SMT",
-},
-{
- .metric_expr = "l1d\\-loads\\-misses / inst_retired.any",
- .metric_name = "dcache_miss_cpi",
-},
-{
- .metric_expr = "l1i\\-loads\\-misses / inst_retired.any",
- .metric_name = "icache_miss_cycles",
-},
-{
- .metric_expr = "(dcache_miss_cpi + icache_miss_cycles)",
- .metric_name = "cache_miss_cycles",
- .metric_group = "group1",
-},
-{
- .metric_expr = "l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit",
- .metric_name = "DCache_L2_All_Hits",
-},
-{
- .metric_expr = "max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + "
- "l2_rqsts.pf_miss + l2_rqsts.rfo_miss",
- .metric_name = "DCache_L2_All_Miss",
-},
-{
- .metric_expr = "dcache_l2_all_hits + dcache_l2_all_miss",
- .metric_name = "DCache_L2_All",
-},
-{
- .metric_expr = "d_ratio(dcache_l2_all_hits, dcache_l2_all)",
- .metric_name = "DCache_L2_Hits",
-},
-{
- .metric_expr = "d_ratio(dcache_l2_all_miss, dcache_l2_all)",
- .metric_name = "DCache_L2_Misses",
-},
-{
- .metric_expr = "ipc + m2",
- .metric_name = "M1",
-},
-{
- .metric_expr = "ipc + m1",
- .metric_name = "M2",
-},
-{
- .metric_expr = "1/m3",
- .metric_name = "M3",
-},
-{
- .metric_expr = "64 * l1d.replacement / 1000000000 / duration_time",
- .metric_name = "L1D_Cache_Fill_BW",
-},
-{
- .name = NULL,
-}
-};
-
-static const struct pmu_events_map map = {
- .cpuid = "test",
- .version = "1",
- .type = "core",
- .table = pme_test,
-};
-
struct value {
const char *event;
u64 val;
@@ -145,6 +72,7 @@ static int __compute_metric(const char *name, struct value *vals,
struct rblist metric_events = {
.nr_entries = 0,
};
+ const struct pmu_events_table *pme_test;
struct perf_cpu_map *cpus;
struct runtime_stat st;
struct evlist *evlist;
@@ -168,7 +96,8 @@ static int __compute_metric(const char *name, struct value *vals,
runtime_stat__init(&st);
/* Parse the metric into metric_events list. */
- err = metricgroup__parse_groups_test(evlist, &map, name,
+ pme_test = find_core_events_table("testarch", "testcpu");
+ err = metricgroup__parse_groups_test(evlist, pme_test, name,
false, false,
&metric_events);
if (err)
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c
index 7c7d20fc503a..c3aaa1ddff29 100644
--- a/tools/perf/tests/perf-time-to-tsc.c
+++ b/tools/perf/tests/perf-time-to-tsc.c
@@ -62,7 +62,7 @@ static int test__tsc_is_supported(struct test_suite *test __maybe_unused,
* This function implements a test that checks that the conversion of perf time
* to and from TSC is consistent with the order of events. If the test passes
* %0 is returned, otherwise %-1 is returned. If TSC conversion is not
- * supported then then the test passes but " (not supported)" is printed.
+ * supported then the test passes but " (not supported)" is printed.
*/
static int test__perf_time_to_tsc(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
@@ -100,7 +100,7 @@ static int test__perf_time_to_tsc(struct test_suite *test __maybe_unused, int su
perf_evlist__set_maps(&evlist->core, cpus, threads);
- CHECK__(parse_events(evlist, "cycles:u", NULL));
+ CHECK__(parse_event(evlist, "cycles:u"));
evlist__config(evlist, &opts, NULL);
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
index 263cbb67c861..097e05c796ab 100644
--- a/tools/perf/tests/pmu-events.c
+++ b/tools/perf/tests/pmu-events.c
@@ -9,10 +9,12 @@
#include <linux/zalloc.h>
#include "debug.h"
#include "../pmu-events/pmu-events.h"
+#include <perf/evlist.h>
#include "util/evlist.h"
#include "util/expr.h"
#include "util/parse-events.h"
#include "metricgroup.h"
+#include "stat.h"
struct perf_pmu_test_event {
/* used for matching against events from generated pmu-events.c */
@@ -272,32 +274,6 @@ static bool is_same(const char *reference, const char *test)
return !strcmp(reference, test);
}
-static const struct pmu_events_map *__test_pmu_get_events_map(void)
-{
- const struct pmu_events_map *map;
-
- for (map = &pmu_events_map[0]; map->cpuid; map++) {
- if (!strcmp(map->cpuid, "testcpu"))
- return map;
- }
-
- pr_err("could not find test events map\n");
-
- return NULL;
-}
-
-static const struct pmu_event *__test_pmu_get_sys_events_table(void)
-{
- const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
-
- for ( ; tables->name; tables++) {
- if (!strcmp("pme_test_soc_sys", tables->name))
- return tables->table;
- }
-
- return NULL;
-}
-
static int compare_pmu_events(const struct pmu_event *e1, const struct pmu_event *e2)
{
if (!is_same(e1->name, e2->name)) {
@@ -447,85 +423,104 @@ static int compare_alias_to_test_event(struct perf_pmu_alias *alias,
return 0;
}
-/* Verify generated events from pmu-events.c are as expected */
-static int test__pmu_event_table(struct test_suite *test __maybe_unused,
- int subtest __maybe_unused)
+static int test__pmu_event_table_core_callback(const struct pmu_event *pe,
+ const struct pmu_events_table *table __maybe_unused,
+ void *data)
{
- const struct pmu_event *sys_event_tables = __test_pmu_get_sys_events_table();
- const struct pmu_events_map *map = __test_pmu_get_events_map();
- const struct pmu_event *table;
- int map_events = 0, expected_events;
+ int *map_events = data;
+ struct perf_pmu_test_event const **test_event_table;
+ bool found = false;
- /* ignore 3x sentinels */
- expected_events = ARRAY_SIZE(core_events) +
- ARRAY_SIZE(uncore_events) +
- ARRAY_SIZE(sys_events) - 3;
+ if (!pe->name)
+ return 0;
- if (!map || !sys_event_tables)
- return -1;
+ if (pe->pmu)
+ test_event_table = &uncore_events[0];
+ else
+ test_event_table = &core_events[0];
- for (table = map->table; table->name; table++) {
- struct perf_pmu_test_event const **test_event_table;
- bool found = false;
+ for (; *test_event_table; test_event_table++) {
+ struct perf_pmu_test_event const *test_event = *test_event_table;
+ struct pmu_event const *event = &test_event->event;
- if (table->pmu)
- test_event_table = &uncore_events[0];
- else
- test_event_table = &core_events[0];
+ if (strcmp(pe->name, event->name))
+ continue;
+ found = true;
+ (*map_events)++;
- for (; *test_event_table; test_event_table++) {
- struct perf_pmu_test_event const *test_event = *test_event_table;
- struct pmu_event const *event = &test_event->event;
+ if (compare_pmu_events(pe, event))
+ return -1;
+
+ pr_debug("testing event table %s: pass\n", pe->name);
+ }
+ if (!found) {
+ pr_err("testing event table: could not find event %s\n", pe->name);
+ return -1;
+ }
+ return 0;
+}
- if (strcmp(table->name, event->name))
- continue;
- found = true;
- map_events++;
+static int test__pmu_event_table_sys_callback(const struct pmu_event *pe,
+ const struct pmu_events_table *table __maybe_unused,
+ void *data)
+{
+ int *map_events = data;
+ struct perf_pmu_test_event const **test_event_table;
+ bool found = false;
- if (compare_pmu_events(table, event))
- return -1;
+ test_event_table = &sys_events[0];
- pr_debug("testing event table %s: pass\n", table->name);
- }
+ for (; *test_event_table; test_event_table++) {
+ struct perf_pmu_test_event const *test_event = *test_event_table;
+ struct pmu_event const *event = &test_event->event;
- if (!found) {
- pr_err("testing event table: could not find event %s\n",
- table->name);
- return -1;
- }
- }
+ if (strcmp(pe->name, event->name))
+ continue;
+ found = true;
+ (*map_events)++;
- for (table = sys_event_tables; table->name; table++) {
- struct perf_pmu_test_event const **test_event_table;
- bool found = false;
+ if (compare_pmu_events(pe, event))
+ return TEST_FAIL;
- test_event_table = &sys_events[0];
+ pr_debug("testing sys event table %s: pass\n", pe->name);
+ }
+ if (!found) {
+ pr_debug("testing sys event table: could not find event %s\n", pe->name);
+ return TEST_FAIL;
+ }
+ return TEST_OK;
+}
- for (; *test_event_table; test_event_table++) {
- struct perf_pmu_test_event const *test_event = *test_event_table;
- struct pmu_event const *event = &test_event->event;
+/* Verify generated events from pmu-events.c are as expected */
+static int test__pmu_event_table(struct test_suite *test __maybe_unused,
+ int subtest __maybe_unused)
+{
+ const struct pmu_events_table *sys_event_table = find_sys_events_table("pme_test_soc_sys");
+ const struct pmu_events_table *table = find_core_events_table("testarch", "testcpu");
+ int map_events = 0, expected_events, err;
- if (strcmp(table->name, event->name))
- continue;
- found = true;
- map_events++;
+ /* ignore 3x sentinels */
+ expected_events = ARRAY_SIZE(core_events) +
+ ARRAY_SIZE(uncore_events) +
+ ARRAY_SIZE(sys_events) - 3;
- if (compare_pmu_events(table, event))
- return -1;
+ if (!table || !sys_event_table)