1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Test support for libpfm4 event encodings. 4 * 5 * Copyright 2020 Google LLC. 6 */ 7 #include "tests.h" 8 #include "util/debug.h" 9 #include "util/evlist.h" 10 #include "util/pfm.h" 11 12 #include <linux/kernel.h> 13 14 #ifdef HAVE_LIBPFM 15 static int test__pfm_events(void); 16 static int test__pfm_group(void); 17 #endif 18 19 static const struct { 20 int (*func)(void); 21 const char *desc; 22 } pfm_testcase_table[] = { 23 #ifdef HAVE_LIBPFM 24 { 25 .func = test__pfm_events, 26 .desc = "test of individual --pfm-events", 27 }, 28 { 29 .func = test__pfm_group, 30 .desc = "test groups of --pfm-events", 31 }, 32 #endif 33 }; 34 35 #ifdef HAVE_LIBPFM 36 static int count_pfm_events(struct perf_evlist *evlist) 37 { 38 struct perf_evsel *evsel; 39 int count = 0; 40 41 perf_evlist__for_each_entry(evlist, evsel) { 42 count++; 43 } 44 return count; 45 } 46 47 static int test__pfm_events(void) 48 { 49 struct evlist *evlist; 50 struct option opt; 51 size_t i; 52 const struct { 53 const char *events; 54 int nr_events; 55 } table[] = { 56 { 57 .events = "", 58 .nr_events = 0, 59 }, 60 { 61 .events = "instructions", 62 .nr_events = 1, 63 }, 64 { 65 .events = "instructions,cycles", 66 .nr_events = 2, 67 }, 68 { 69 .events = "stereolab", 70 .nr_events = 0, 71 }, 72 { 73 .events = "instructions,instructions", 74 .nr_events = 2, 75 }, 76 { 77 .events = "stereolab,instructions", 78 .nr_events = 0, 79 }, 80 { 81 .events = "instructions,stereolab", 82 .nr_events = 1, 83 }, 84 }; 85 86 for (i = 0; i < ARRAY_SIZE(table); i++) { 87 evlist = evlist__new(); 88 if (evlist == NULL) 89 return -ENOMEM; 90 91 opt.value = evlist; 92 parse_libpfm_events_option(&opt, 93 table[i].events, 94 0); 95 TEST_ASSERT_EQUAL(table[i].events, 96 count_pfm_events(&evlist->core), 97 table[i].nr_events); 98 TEST_ASSERT_EQUAL(table[i].events, 99 evlist->core.nr_groups, 100 0); 101 102 evlist__delete(evlist); 103 } 104 return 0; 105 } 106 107 static int test__pfm_group(void) 108 { 109 struct evlist *evlist; 110 struct option opt; 111 size_t i; 112 const struct { 113 const char *events; 114 int nr_events; 115 int nr_groups; 116 } table[] = { 117 { 118 .events = "{},", 119 .nr_events = 0, 120 .nr_groups = 0, 121 }, 122 { 123 .events = "{instructions}", 124 .nr_events = 1, 125 .nr_groups = 1, 126 }, 127 { 128 .events = "{instructions},{}", 129 .nr_events = 1, 130 .nr_groups = 1, 131 }, 132 { 133 .events = "{},{instructions}", 134 .nr_events = 1, 135 .nr_groups = 1, 136 }, 137 { 138 .events = "{instructions},{instructions}", 139 .nr_events = 2, 140 .nr_groups = 2, 141 }, 142 { 143 .events = "{instructions,cycles},{instructions,cycles}", 144 .nr_events = 4, 145 .nr_groups = 2, 146 }, 147 { 148 .events = "{stereolab}", 149 .nr_events = 0, 150 .nr_groups = 0, 151 }, 152 { 153 .events = 154 "{instructions,cycles},{instructions,stereolab}", 155 .nr_events = 3, 156 .nr_groups = 1, 157 }, 158 { 159 .events = "instructions}", 160 .nr_events = 1, 161 .nr_groups = 0, 162 }, 163 { 164 .events = "{{instructions}}", 165 .nr_events = 0, 166 .nr_groups = 0, 167 }, 168 }; 169 170 for (i = 0; i < ARRAY_SIZE(table); i++) { 171 evlist = evlist__new(); 172 if (evlist == NULL) 173 return -ENOMEM; 174 175 opt.value = evlist; 176 parse_libpfm_events_option(&opt, 177 table[i].events, 178 0); 179 TEST_ASSERT_EQUAL(table[i].events, 180 count_pfm_events(&evlist->core), 181 table[i].nr_events); 182 TEST_ASSERT_EQUAL(table[i].events, 183 evlist->core.nr_groups, 184 table[i].nr_groups); 185 186 evlist__delete(evlist); 187 } 188 return 0; 189 } 190 #endif 191 192 const char *test__pfm_subtest_get_desc(int i) 193 { 194 if (i < 0 || i >= (int)ARRAY_SIZE(pfm_testcase_table)) 195 return NULL; 196 return pfm_testcase_table[i].desc; 197 } 198 199 int test__pfm_subtest_get_nr(void) 200 { 201 return (int)ARRAY_SIZE(pfm_testcase_table); 202 } 203 204 int test__pfm(struct test *test __maybe_unused, int i __maybe_unused) 205 { 206 #ifdef HAVE_LIBPFM 207 if (i < 0 || i >= (int)ARRAY_SIZE(pfm_testcase_table)) 208 return TEST_FAIL; 209 return pfm_testcase_table[i].func(); 210 #else 211 return TEST_SKIP; 212 #endif 213 } 214