expand-cgroup.c 5.6 KB

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