1*40b74c30SNamhyung Kim // SPDX-License-Identifier: GPL-2.0 2*40b74c30SNamhyung Kim #include "tests.h" 3*40b74c30SNamhyung Kim #include "debug.h" 4*40b74c30SNamhyung Kim #include "evlist.h" 5*40b74c30SNamhyung Kim #include "cgroup.h" 6*40b74c30SNamhyung Kim #include "rblist.h" 7*40b74c30SNamhyung Kim #include "metricgroup.h" 8*40b74c30SNamhyung Kim #include "parse-events.h" 9*40b74c30SNamhyung Kim #include "pmu-events/pmu-events.h" 10*40b74c30SNamhyung Kim #include "pfm.h" 11*40b74c30SNamhyung Kim #include <subcmd/parse-options.h> 12*40b74c30SNamhyung Kim #include <stdio.h> 13*40b74c30SNamhyung Kim #include <stdlib.h> 14*40b74c30SNamhyung Kim #include <string.h> 15*40b74c30SNamhyung Kim 16*40b74c30SNamhyung Kim static int test_expand_events(struct evlist *evlist, 17*40b74c30SNamhyung Kim struct rblist *metric_events) 18*40b74c30SNamhyung Kim { 19*40b74c30SNamhyung Kim int i, ret = TEST_FAIL; 20*40b74c30SNamhyung Kim int nr_events; 21*40b74c30SNamhyung Kim bool was_group_event; 22*40b74c30SNamhyung Kim int nr_members; /* for the first evsel only */ 23*40b74c30SNamhyung Kim const char cgrp_str[] = "A,B,C"; 24*40b74c30SNamhyung Kim const char *cgrp_name[] = { "A", "B", "C" }; 25*40b74c30SNamhyung Kim int nr_cgrps = ARRAY_SIZE(cgrp_name); 26*40b74c30SNamhyung Kim char **ev_name; 27*40b74c30SNamhyung Kim struct evsel *evsel; 28*40b74c30SNamhyung Kim 29*40b74c30SNamhyung Kim TEST_ASSERT_VAL("evlist is empty", !perf_evlist__empty(evlist)); 30*40b74c30SNamhyung Kim 31*40b74c30SNamhyung Kim nr_events = evlist->core.nr_entries; 32*40b74c30SNamhyung Kim ev_name = calloc(nr_events, sizeof(*ev_name)); 33*40b74c30SNamhyung Kim if (ev_name == NULL) { 34*40b74c30SNamhyung Kim pr_debug("memory allocation failure\n"); 35*40b74c30SNamhyung Kim return TEST_FAIL; 36*40b74c30SNamhyung Kim } 37*40b74c30SNamhyung Kim i = 0; 38*40b74c30SNamhyung Kim evlist__for_each_entry(evlist, evsel) { 39*40b74c30SNamhyung Kim ev_name[i] = strdup(evsel->name); 40*40b74c30SNamhyung Kim if (ev_name[i] == NULL) { 41*40b74c30SNamhyung Kim pr_debug("memory allocation failure\n"); 42*40b74c30SNamhyung Kim goto out; 43*40b74c30SNamhyung Kim } 44*40b74c30SNamhyung Kim i++; 45*40b74c30SNamhyung Kim } 46*40b74c30SNamhyung Kim /* remember grouping info */ 47*40b74c30SNamhyung Kim was_group_event = evsel__is_group_event(evlist__first(evlist)); 48*40b74c30SNamhyung Kim nr_members = evlist__first(evlist)->core.nr_members; 49*40b74c30SNamhyung Kim 50*40b74c30SNamhyung Kim ret = evlist__expand_cgroup(evlist, cgrp_str, metric_events, false); 51*40b74c30SNamhyung Kim if (ret < 0) { 52*40b74c30SNamhyung Kim pr_debug("failed to expand events for cgroups\n"); 53*40b74c30SNamhyung Kim goto out; 54*40b74c30SNamhyung Kim } 55*40b74c30SNamhyung Kim 56*40b74c30SNamhyung Kim ret = TEST_FAIL; 57*40b74c30SNamhyung Kim if (evlist->core.nr_entries != nr_events * nr_cgrps) { 58*40b74c30SNamhyung Kim pr_debug("event count doesn't match\n"); 59*40b74c30SNamhyung Kim goto out; 60*40b74c30SNamhyung Kim } 61*40b74c30SNamhyung Kim 62*40b74c30SNamhyung Kim i = 0; 63*40b74c30SNamhyung Kim evlist__for_each_entry(evlist, evsel) { 64*40b74c30SNamhyung Kim if (strcmp(evsel->name, ev_name[i % nr_events])) { 65*40b74c30SNamhyung Kim pr_debug("event name doesn't match:\n"); 66*40b74c30SNamhyung Kim pr_debug(" evsel[%d]: %s\n expected: %s\n", 67*40b74c30SNamhyung Kim i, evsel->name, ev_name[i % nr_events]); 68*40b74c30SNamhyung Kim goto out; 69*40b74c30SNamhyung Kim } 70*40b74c30SNamhyung Kim if (strcmp(evsel->cgrp->name, cgrp_name[i / nr_events])) { 71*40b74c30SNamhyung Kim pr_debug("cgroup name doesn't match:\n"); 72*40b74c30SNamhyung Kim pr_debug(" evsel[%d]: %s\n expected: %s\n", 73*40b74c30SNamhyung Kim i, evsel->cgrp->name, cgrp_name[i / nr_events]); 74*40b74c30SNamhyung Kim goto out; 75*40b74c30SNamhyung Kim } 76*40b74c30SNamhyung Kim 77*40b74c30SNamhyung Kim if ((i % nr_events) == 0) { 78*40b74c30SNamhyung Kim if (evsel__is_group_event(evsel) != was_group_event) { 79*40b74c30SNamhyung Kim pr_debug("event group doesn't match: got %s, expect %s\n", 80*40b74c30SNamhyung Kim evsel__is_group_event(evsel) ? "true" : "false", 81*40b74c30SNamhyung Kim was_group_event ? "true" : "false"); 82*40b74c30SNamhyung Kim goto out; 83*40b74c30SNamhyung Kim } 84*40b74c30SNamhyung Kim if (evsel->core.nr_members != nr_members) { 85*40b74c30SNamhyung Kim pr_debug("event group member doesn't match: %d vs %d\n", 86*40b74c30SNamhyung Kim evsel->core.nr_members, nr_members); 87*40b74c30SNamhyung Kim goto out; 88*40b74c30SNamhyung Kim } 89*40b74c30SNamhyung Kim } 90*40b74c30SNamhyung Kim i++; 91*40b74c30SNamhyung Kim } 92*40b74c30SNamhyung Kim ret = TEST_OK; 93*40b74c30SNamhyung Kim 94*40b74c30SNamhyung Kim out: for (i = 0; i < nr_events; i++) 95*40b74c30SNamhyung Kim free(ev_name[i]); 96*40b74c30SNamhyung Kim free(ev_name); 97*40b74c30SNamhyung Kim return ret; 98*40b74c30SNamhyung Kim } 99*40b74c30SNamhyung Kim 100*40b74c30SNamhyung Kim static int expand_default_events(void) 101*40b74c30SNamhyung Kim { 102*40b74c30SNamhyung Kim int ret; 103*40b74c30SNamhyung Kim struct evlist *evlist; 104*40b74c30SNamhyung Kim struct rblist metric_events; 105*40b74c30SNamhyung Kim 106*40b74c30SNamhyung Kim evlist = perf_evlist__new_default(); 107*40b74c30SNamhyung Kim TEST_ASSERT_VAL("failed to get evlist", evlist); 108*40b74c30SNamhyung Kim 109*40b74c30SNamhyung Kim rblist__init(&metric_events); 110*40b74c30SNamhyung Kim ret = test_expand_events(evlist, &metric_events); 111*40b74c30SNamhyung Kim evlist__delete(evlist); 112*40b74c30SNamhyung Kim return ret; 113*40b74c30SNamhyung Kim } 114*40b74c30SNamhyung Kim 115*40b74c30SNamhyung Kim static int expand_group_events(void) 116*40b74c30SNamhyung Kim { 117*40b74c30SNamhyung Kim int ret; 118*40b74c30SNamhyung Kim struct evlist *evlist; 119*40b74c30SNamhyung Kim struct rblist metric_events; 120*40b74c30SNamhyung Kim struct parse_events_error err; 121*40b74c30SNamhyung Kim const char event_str[] = "{cycles,instructions}"; 122*40b74c30SNamhyung Kim 123*40b74c30SNamhyung Kim symbol_conf.event_group = true; 124*40b74c30SNamhyung Kim 125*40b74c30SNamhyung Kim evlist = evlist__new(); 126*40b74c30SNamhyung Kim TEST_ASSERT_VAL("failed to get evlist", evlist); 127*40b74c30SNamhyung Kim 128*40b74c30SNamhyung Kim ret = parse_events(evlist, event_str, &err); 129*40b74c30SNamhyung Kim if (ret < 0) { 130*40b74c30SNamhyung Kim pr_debug("failed to parse event '%s', err %d, str '%s'\n", 131*40b74c30SNamhyung Kim event_str, ret, err.str); 132*40b74c30SNamhyung Kim parse_events_print_error(&err, event_str); 133*40b74c30SNamhyung Kim goto out; 134*40b74c30SNamhyung Kim } 135*40b74c30SNamhyung Kim 136*40b74c30SNamhyung Kim rblist__init(&metric_events); 137*40b74c30SNamhyung Kim ret = test_expand_events(evlist, &metric_events); 138*40b74c30SNamhyung Kim out: 139*40b74c30SNamhyung Kim evlist__delete(evlist); 140*40b74c30SNamhyung Kim return ret; 141*40b74c30SNamhyung Kim } 142*40b74c30SNamhyung Kim 143*40b74c30SNamhyung Kim static int expand_libpfm_events(void) 144*40b74c30SNamhyung Kim { 145*40b74c30SNamhyung Kim int ret; 146*40b74c30SNamhyung Kim struct evlist *evlist; 147*40b74c30SNamhyung Kim struct rblist metric_events; 148*40b74c30SNamhyung Kim const char event_str[] = "UNHALTED_CORE_CYCLES"; 149*40b74c30SNamhyung Kim struct option opt = { 150*40b74c30SNamhyung Kim .value = &evlist, 151*40b74c30SNamhyung Kim }; 152*40b74c30SNamhyung Kim 153*40b74c30SNamhyung Kim symbol_conf.event_group = true; 154*40b74c30SNamhyung Kim 155*40b74c30SNamhyung Kim evlist = evlist__new(); 156*40b74c30SNamhyung Kim TEST_ASSERT_VAL("failed to get evlist", evlist); 157*40b74c30SNamhyung Kim 158*40b74c30SNamhyung Kim ret = parse_libpfm_events_option(&opt, event_str, 0); 159*40b74c30SNamhyung Kim if (ret < 0) { 160*40b74c30SNamhyung Kim pr_debug("failed to parse libpfm event '%s', err %d\n", 161*40b74c30SNamhyung Kim event_str, ret); 162*40b74c30SNamhyung Kim goto out; 163*40b74c30SNamhyung Kim } 164*40b74c30SNamhyung Kim if (perf_evlist__empty(evlist)) { 165*40b74c30SNamhyung Kim pr_debug("libpfm was not enabled\n"); 166*40b74c30SNamhyung Kim goto out; 167*40b74c30SNamhyung Kim } 168*40b74c30SNamhyung Kim 169*40b74c30SNamhyung Kim rblist__init(&metric_events); 170*40b74c30SNamhyung Kim ret = test_expand_events(evlist, &metric_events); 171*40b74c30SNamhyung Kim out: 172*40b74c30SNamhyung Kim evlist__delete(evlist); 173*40b74c30SNamhyung Kim return ret; 174*40b74c30SNamhyung Kim } 175*40b74c30SNamhyung Kim 176*40b74c30SNamhyung Kim static int expand_metric_events(void) 177*40b74c30SNamhyung Kim { 178*40b74c30SNamhyung Kim int ret; 179*40b74c30SNamhyung Kim struct evlist *evlist; 180*40b74c30SNamhyung Kim struct rblist metric_events; 181*40b74c30SNamhyung Kim const char metric_str[] = "CPI"; 182*40b74c30SNamhyung Kim 183*40b74c30SNamhyung Kim struct pmu_event pme_test[] = { 184*40b74c30SNamhyung Kim { 185*40b74c30SNamhyung Kim .metric_expr = "instructions / cycles", 186*40b74c30SNamhyung Kim .metric_name = "IPC", 187*40b74c30SNamhyung Kim }, 188*40b74c30SNamhyung Kim { 189*40b74c30SNamhyung Kim .metric_expr = "1 / IPC", 190*40b74c30SNamhyung Kim .metric_name = "CPI", 191*40b74c30SNamhyung Kim }, 192*40b74c30SNamhyung Kim { 193*40b74c30SNamhyung Kim .metric_expr = NULL, 194*40b74c30SNamhyung Kim .metric_name = NULL, 195*40b74c30SNamhyung Kim }, 196*40b74c30SNamhyung Kim }; 197*40b74c30SNamhyung Kim struct pmu_events_map ev_map = { 198*40b74c30SNamhyung Kim .cpuid = "test", 199*40b74c30SNamhyung Kim .version = "1", 200*40b74c30SNamhyung Kim .type = "core", 201*40b74c30SNamhyung Kim .table = pme_test, 202*40b74c30SNamhyung Kim }; 203*40b74c30SNamhyung Kim 204*40b74c30SNamhyung Kim evlist = evlist__new(); 205*40b74c30SNamhyung Kim TEST_ASSERT_VAL("failed to get evlist", evlist); 206*40b74c30SNamhyung Kim 207*40b74c30SNamhyung Kim rblist__init(&metric_events); 208*40b74c30SNamhyung Kim ret = metricgroup__parse_groups_test(evlist, &ev_map, metric_str, 209*40b74c30SNamhyung Kim false, false, &metric_events); 210*40b74c30SNamhyung Kim if (ret < 0) { 211*40b74c30SNamhyung Kim pr_debug("failed to parse '%s' metric\n", metric_str); 212*40b74c30SNamhyung Kim goto out; 213*40b74c30SNamhyung Kim } 214*40b74c30SNamhyung Kim 215*40b74c30SNamhyung Kim ret = test_expand_events(evlist, &metric_events); 216*40b74c30SNamhyung Kim 217*40b74c30SNamhyung Kim out: 218*40b74c30SNamhyung Kim metricgroup__rblist_exit(&metric_events); 219*40b74c30SNamhyung Kim evlist__delete(evlist); 220*40b74c30SNamhyung Kim return ret; 221*40b74c30SNamhyung Kim } 222*40b74c30SNamhyung Kim 223*40b74c30SNamhyung Kim int test__expand_cgroup_events(struct test *test __maybe_unused, 224*40b74c30SNamhyung Kim int subtest __maybe_unused) 225*40b74c30SNamhyung Kim { 226*40b74c30SNamhyung Kim int ret; 227*40b74c30SNamhyung Kim 228*40b74c30SNamhyung Kim ret = expand_default_events(); 229*40b74c30SNamhyung Kim TEST_ASSERT_EQUAL("failed to expand default events", ret, 0); 230*40b74c30SNamhyung Kim 231*40b74c30SNamhyung Kim ret = expand_group_events(); 232*40b74c30SNamhyung Kim TEST_ASSERT_EQUAL("failed to expand event group", ret, 0); 233*40b74c30SNamhyung Kim 234*40b74c30SNamhyung Kim ret = expand_libpfm_events(); 235*40b74c30SNamhyung Kim TEST_ASSERT_EQUAL("failed to expand event group", ret, 0); 236*40b74c30SNamhyung Kim 237*40b74c30SNamhyung Kim ret = expand_metric_events(); 238*40b74c30SNamhyung Kim TEST_ASSERT_EQUAL("failed to expand metric events", ret, 0); 239*40b74c30SNamhyung Kim 240*40b74c30SNamhyung Kim return ret; 241*40b74c30SNamhyung Kim } 242