18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include "tests.h" 38c2ecf20Sopenharmony_ci#include "debug.h" 48c2ecf20Sopenharmony_ci#include "evlist.h" 58c2ecf20Sopenharmony_ci#include "cgroup.h" 68c2ecf20Sopenharmony_ci#include "rblist.h" 78c2ecf20Sopenharmony_ci#include "metricgroup.h" 88c2ecf20Sopenharmony_ci#include "parse-events.h" 98c2ecf20Sopenharmony_ci#include "pmu-events/pmu-events.h" 108c2ecf20Sopenharmony_ci#include "pfm.h" 118c2ecf20Sopenharmony_ci#include <subcmd/parse-options.h> 128c2ecf20Sopenharmony_ci#include <stdio.h> 138c2ecf20Sopenharmony_ci#include <stdlib.h> 148c2ecf20Sopenharmony_ci#include <string.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic int test_expand_events(struct evlist *evlist, 178c2ecf20Sopenharmony_ci struct rblist *metric_events) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci int i, ret = TEST_FAIL; 208c2ecf20Sopenharmony_ci int nr_events; 218c2ecf20Sopenharmony_ci bool was_group_event; 228c2ecf20Sopenharmony_ci int nr_members; /* for the first evsel only */ 238c2ecf20Sopenharmony_ci const char cgrp_str[] = "A,B,C"; 248c2ecf20Sopenharmony_ci const char *cgrp_name[] = { "A", "B", "C" }; 258c2ecf20Sopenharmony_ci int nr_cgrps = ARRAY_SIZE(cgrp_name); 268c2ecf20Sopenharmony_ci char **ev_name; 278c2ecf20Sopenharmony_ci struct evsel *evsel; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("evlist is empty", !perf_evlist__empty(evlist)); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci nr_events = evlist->core.nr_entries; 328c2ecf20Sopenharmony_ci ev_name = calloc(nr_events, sizeof(*ev_name)); 338c2ecf20Sopenharmony_ci if (ev_name == NULL) { 348c2ecf20Sopenharmony_ci pr_debug("memory allocation failure\n"); 358c2ecf20Sopenharmony_ci return TEST_FAIL; 368c2ecf20Sopenharmony_ci } 378c2ecf20Sopenharmony_ci i = 0; 388c2ecf20Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 398c2ecf20Sopenharmony_ci ev_name[i] = strdup(evsel->name); 408c2ecf20Sopenharmony_ci if (ev_name[i] == NULL) { 418c2ecf20Sopenharmony_ci pr_debug("memory allocation failure\n"); 428c2ecf20Sopenharmony_ci goto out; 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci i++; 458c2ecf20Sopenharmony_ci } 468c2ecf20Sopenharmony_ci /* remember grouping info */ 478c2ecf20Sopenharmony_ci was_group_event = evsel__is_group_event(evlist__first(evlist)); 488c2ecf20Sopenharmony_ci nr_members = evlist__first(evlist)->core.nr_members; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci ret = evlist__expand_cgroup(evlist, cgrp_str, metric_events, false); 518c2ecf20Sopenharmony_ci if (ret < 0) { 528c2ecf20Sopenharmony_ci pr_debug("failed to expand events for cgroups\n"); 538c2ecf20Sopenharmony_ci goto out; 548c2ecf20Sopenharmony_ci } 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci ret = TEST_FAIL; 578c2ecf20Sopenharmony_ci if (evlist->core.nr_entries != nr_events * nr_cgrps) { 588c2ecf20Sopenharmony_ci pr_debug("event count doesn't match\n"); 598c2ecf20Sopenharmony_ci goto out; 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci i = 0; 638c2ecf20Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 648c2ecf20Sopenharmony_ci if (strcmp(evsel->name, ev_name[i % nr_events])) { 658c2ecf20Sopenharmony_ci pr_debug("event name doesn't match:\n"); 668c2ecf20Sopenharmony_ci pr_debug(" evsel[%d]: %s\n expected: %s\n", 678c2ecf20Sopenharmony_ci i, evsel->name, ev_name[i % nr_events]); 688c2ecf20Sopenharmony_ci goto out; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci if (strcmp(evsel->cgrp->name, cgrp_name[i / nr_events])) { 718c2ecf20Sopenharmony_ci pr_debug("cgroup name doesn't match:\n"); 728c2ecf20Sopenharmony_ci pr_debug(" evsel[%d]: %s\n expected: %s\n", 738c2ecf20Sopenharmony_ci i, evsel->cgrp->name, cgrp_name[i / nr_events]); 748c2ecf20Sopenharmony_ci goto out; 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if ((i % nr_events) == 0) { 788c2ecf20Sopenharmony_ci if (evsel__is_group_event(evsel) != was_group_event) { 798c2ecf20Sopenharmony_ci pr_debug("event group doesn't match: got %s, expect %s\n", 808c2ecf20Sopenharmony_ci evsel__is_group_event(evsel) ? "true" : "false", 818c2ecf20Sopenharmony_ci was_group_event ? "true" : "false"); 828c2ecf20Sopenharmony_ci goto out; 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci if (evsel->core.nr_members != nr_members) { 858c2ecf20Sopenharmony_ci pr_debug("event group member doesn't match: %d vs %d\n", 868c2ecf20Sopenharmony_ci evsel->core.nr_members, nr_members); 878c2ecf20Sopenharmony_ci goto out; 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci i++; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci ret = TEST_OK; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ciout: for (i = 0; i < nr_events; i++) 958c2ecf20Sopenharmony_ci free(ev_name[i]); 968c2ecf20Sopenharmony_ci free(ev_name); 978c2ecf20Sopenharmony_ci return ret; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic int expand_default_events(void) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci int ret; 1038c2ecf20Sopenharmony_ci struct evlist *evlist; 1048c2ecf20Sopenharmony_ci struct rblist metric_events; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci evlist = perf_evlist__new_default(); 1078c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("failed to get evlist", evlist); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci rblist__init(&metric_events); 1108c2ecf20Sopenharmony_ci ret = test_expand_events(evlist, &metric_events); 1118c2ecf20Sopenharmony_ci evlist__delete(evlist); 1128c2ecf20Sopenharmony_ci return ret; 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic int expand_group_events(void) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci int ret; 1188c2ecf20Sopenharmony_ci struct evlist *evlist; 1198c2ecf20Sopenharmony_ci struct rblist metric_events; 1208c2ecf20Sopenharmony_ci struct parse_events_error err; 1218c2ecf20Sopenharmony_ci const char event_str[] = "{cycles,instructions}"; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci symbol_conf.event_group = true; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci evlist = evlist__new(); 1268c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("failed to get evlist", evlist); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci ret = parse_events(evlist, event_str, &err); 1298c2ecf20Sopenharmony_ci if (ret < 0) { 1308c2ecf20Sopenharmony_ci pr_debug("failed to parse event '%s', err %d, str '%s'\n", 1318c2ecf20Sopenharmony_ci event_str, ret, err.str); 1328c2ecf20Sopenharmony_ci parse_events_print_error(&err, event_str); 1338c2ecf20Sopenharmony_ci goto out; 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci rblist__init(&metric_events); 1378c2ecf20Sopenharmony_ci ret = test_expand_events(evlist, &metric_events); 1388c2ecf20Sopenharmony_ciout: 1398c2ecf20Sopenharmony_ci evlist__delete(evlist); 1408c2ecf20Sopenharmony_ci return ret; 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic int expand_libpfm_events(void) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci int ret; 1468c2ecf20Sopenharmony_ci struct evlist *evlist; 1478c2ecf20Sopenharmony_ci struct rblist metric_events; 1488c2ecf20Sopenharmony_ci const char event_str[] = "CYCLES"; 1498c2ecf20Sopenharmony_ci struct option opt = { 1508c2ecf20Sopenharmony_ci .value = &evlist, 1518c2ecf20Sopenharmony_ci }; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci symbol_conf.event_group = true; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci evlist = evlist__new(); 1568c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("failed to get evlist", evlist); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci ret = parse_libpfm_events_option(&opt, event_str, 0); 1598c2ecf20Sopenharmony_ci if (ret < 0) { 1608c2ecf20Sopenharmony_ci pr_debug("failed to parse libpfm event '%s', err %d\n", 1618c2ecf20Sopenharmony_ci event_str, ret); 1628c2ecf20Sopenharmony_ci goto out; 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci if (perf_evlist__empty(evlist)) { 1658c2ecf20Sopenharmony_ci pr_debug("libpfm was not enabled\n"); 1668c2ecf20Sopenharmony_ci goto out; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci rblist__init(&metric_events); 1708c2ecf20Sopenharmony_ci ret = test_expand_events(evlist, &metric_events); 1718c2ecf20Sopenharmony_ciout: 1728c2ecf20Sopenharmony_ci evlist__delete(evlist); 1738c2ecf20Sopenharmony_ci return ret; 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_cistatic int expand_metric_events(void) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci int ret; 1798c2ecf20Sopenharmony_ci struct evlist *evlist; 1808c2ecf20Sopenharmony_ci struct rblist metric_events; 1818c2ecf20Sopenharmony_ci const char metric_str[] = "CPI"; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci struct pmu_event pme_test[] = { 1848c2ecf20Sopenharmony_ci { 1858c2ecf20Sopenharmony_ci .metric_expr = "instructions / cycles", 1868c2ecf20Sopenharmony_ci .metric_name = "IPC", 1878c2ecf20Sopenharmony_ci }, 1888c2ecf20Sopenharmony_ci { 1898c2ecf20Sopenharmony_ci .metric_expr = "1 / IPC", 1908c2ecf20Sopenharmony_ci .metric_name = "CPI", 1918c2ecf20Sopenharmony_ci }, 1928c2ecf20Sopenharmony_ci { 1938c2ecf20Sopenharmony_ci .metric_expr = NULL, 1948c2ecf20Sopenharmony_ci .metric_name = NULL, 1958c2ecf20Sopenharmony_ci }, 1968c2ecf20Sopenharmony_ci }; 1978c2ecf20Sopenharmony_ci struct pmu_events_map ev_map = { 1988c2ecf20Sopenharmony_ci .cpuid = "test", 1998c2ecf20Sopenharmony_ci .version = "1", 2008c2ecf20Sopenharmony_ci .type = "core", 2018c2ecf20Sopenharmony_ci .table = pme_test, 2028c2ecf20Sopenharmony_ci }; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci evlist = evlist__new(); 2058c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("failed to get evlist", evlist); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci rblist__init(&metric_events); 2088c2ecf20Sopenharmony_ci ret = metricgroup__parse_groups_test(evlist, &ev_map, metric_str, 2098c2ecf20Sopenharmony_ci false, false, &metric_events); 2108c2ecf20Sopenharmony_ci if (ret < 0) { 2118c2ecf20Sopenharmony_ci pr_debug("failed to parse '%s' metric\n", metric_str); 2128c2ecf20Sopenharmony_ci goto out; 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci ret = test_expand_events(evlist, &metric_events); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ciout: 2188c2ecf20Sopenharmony_ci metricgroup__rblist_exit(&metric_events); 2198c2ecf20Sopenharmony_ci evlist__delete(evlist); 2208c2ecf20Sopenharmony_ci return ret; 2218c2ecf20Sopenharmony_ci} 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ciint test__expand_cgroup_events(struct test *test __maybe_unused, 2248c2ecf20Sopenharmony_ci int subtest __maybe_unused) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci int ret; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci ret = expand_default_events(); 2298c2ecf20Sopenharmony_ci TEST_ASSERT_EQUAL("failed to expand default events", ret, 0); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci ret = expand_group_events(); 2328c2ecf20Sopenharmony_ci TEST_ASSERT_EQUAL("failed to expand event group", ret, 0); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci ret = expand_libpfm_events(); 2358c2ecf20Sopenharmony_ci TEST_ASSERT_EQUAL("failed to expand event group", ret, 0); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci ret = expand_metric_events(); 2388c2ecf20Sopenharmony_ci TEST_ASSERT_EQUAL("failed to expand metric events", ret, 0); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci return ret; 2418c2ecf20Sopenharmony_ci} 242