Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tests: Add tool PMU test

Ensure parsing with and without PMU creates events with the expected
config values. This ensures the tool.json doesn't get out of sync with
tool_pmu_event enum.

Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20241002032016.333748-11-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

authored by

Ian Rogers and committed by
Namhyung Kim
8c25df7a 609aa266

+114
+1
tools/perf/tests/Build
··· 67 67 perf-test-y += event_groups.o 68 68 perf-test-y += symbols.o 69 69 perf-test-y += util.o 70 + perf-test-y += tool_pmu.o 70 71 71 72 ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc)) 72 73 perf-test-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
+1
tools/perf/tests/builtin-test.c
··· 73 73 &suite__PERF_RECORD, 74 74 &suite__pmu, 75 75 &suite__pmu_events, 76 + &suite__tool_pmu, 76 77 &suite__dso_data, 77 78 &suite__perf_evsel__roundtrip_name_test, 78 79 #ifdef HAVE_LIBTRACEEVENT
+1
tools/perf/tests/tests.h
··· 83 83 DECLARE_SUITE(syscall_openat_tp_fields); 84 84 DECLARE_SUITE(pmu); 85 85 DECLARE_SUITE(pmu_events); 86 + DECLARE_SUITE(tool_pmu); 86 87 DECLARE_SUITE(attr); 87 88 DECLARE_SUITE(dso_data); 88 89 DECLARE_SUITE(dso_data_cache);
+111
tools/perf/tests/tool_pmu.c
··· 1 + // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 + #include "debug.h" 3 + #include "evlist.h" 4 + #include "parse-events.h" 5 + #include "tests.h" 6 + #include "tool_pmu.h" 7 + 8 + static int do_test(enum tool_pmu_event ev, bool with_pmu) 9 + { 10 + struct evlist *evlist = evlist__new(); 11 + struct evsel *evsel; 12 + struct parse_events_error err; 13 + int ret; 14 + char str[128]; 15 + bool found = false; 16 + 17 + if (!evlist) { 18 + pr_err("evlist allocation failed\n"); 19 + return TEST_FAIL; 20 + } 21 + 22 + if (with_pmu) 23 + snprintf(str, sizeof(str), "tool/%s/", tool_pmu__event_to_str(ev)); 24 + else 25 + strncpy(str, tool_pmu__event_to_str(ev), sizeof(str)); 26 + 27 + parse_events_error__init(&err); 28 + ret = parse_events(evlist, str, &err); 29 + if (ret) { 30 + evlist__delete(evlist); 31 + if (tool_pmu__skip_event(tool_pmu__event_to_str(ev))) { 32 + ret = TEST_OK; 33 + goto out; 34 + } 35 + 36 + pr_debug("FAILED %s:%d failed to parse event '%s', err %d\n", 37 + __FILE__, __LINE__, str, ret); 38 + parse_events_error__print(&err, str); 39 + ret = TEST_FAIL; 40 + goto out; 41 + } 42 + 43 + ret = TEST_OK; 44 + if (with_pmu ? (evlist->core.nr_entries != 1) : (evlist->core.nr_entries < 1)) { 45 + pr_debug("FAILED %s:%d Unexpected number of events for '%s' of %d\n", 46 + __FILE__, __LINE__, str, evlist->core.nr_entries); 47 + ret = TEST_FAIL; 48 + goto out; 49 + } 50 + 51 + evlist__for_each_entry(evlist, evsel) { 52 + if (perf_pmu__is_tool(evsel->pmu)) { 53 + if (evsel->core.attr.config != ev) { 54 + pr_debug("FAILED %s:%d Unexpected config for '%s', %lld != %d\n", 55 + __FILE__, __LINE__, str, evsel->core.attr.config, ev); 56 + ret = TEST_FAIL; 57 + goto out; 58 + } 59 + found = true; 60 + } 61 + } 62 + 63 + if (!found && !tool_pmu__skip_event(tool_pmu__event_to_str(ev))) { 64 + pr_debug("FAILED %s:%d Didn't find tool event '%s' in parsed evsels\n", 65 + __FILE__, __LINE__, str); 66 + ret = TEST_FAIL; 67 + } 68 + 69 + out: 70 + evlist__delete(evlist); 71 + return ret; 72 + } 73 + 74 + static int test__tool_pmu_without_pmu(struct test_suite *test __maybe_unused, 75 + int subtest __maybe_unused) 76 + { 77 + int i; 78 + 79 + tool_pmu__for_each_event(i) { 80 + int ret = do_test(i, /*with_pmu=*/false); 81 + 82 + if (ret != TEST_OK) 83 + return ret; 84 + } 85 + return TEST_OK; 86 + } 87 + 88 + static int test__tool_pmu_with_pmu(struct test_suite *test __maybe_unused, 89 + int subtest __maybe_unused) 90 + { 91 + int i; 92 + 93 + tool_pmu__for_each_event(i) { 94 + int ret = do_test(i, /*with_pmu=*/true); 95 + 96 + if (ret != TEST_OK) 97 + return ret; 98 + } 99 + return TEST_OK; 100 + } 101 + 102 + static struct test_case tests__tool_pmu[] = { 103 + TEST_CASE("Parsing without PMU name", tool_pmu_without_pmu), 104 + TEST_CASE("Parsing with PMU name", tool_pmu_with_pmu), 105 + { .name = NULL, } 106 + }; 107 + 108 + struct test_suite suite__tool_pmu = { 109 + .desc = "Tool PMU", 110 + .test_cases = tests__tool_pmu, 111 + };