expand-cgroup.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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", !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 (!evsel__name_is(evsel, 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 rblist metric_events;
  95. struct evlist *evlist = evlist__new_default();
  96. TEST_ASSERT_VAL("failed to get evlist", evlist);
  97. rblist__init(&metric_events);
  98. ret = test_expand_events(evlist, &metric_events);
  99. evlist__delete(evlist);
  100. return ret;
  101. }
  102. static int expand_group_events(void)
  103. {
  104. int ret;
  105. struct evlist *evlist;
  106. struct rblist metric_events;
  107. struct parse_events_error err;
  108. const char event_str[] = "{cycles,instructions}";
  109. symbol_conf.event_group = true;
  110. evlist = evlist__new();
  111. TEST_ASSERT_VAL("failed to get evlist", evlist);
  112. parse_events_error__init(&err);
  113. ret = parse_events(evlist, event_str, &err);
  114. if (ret < 0) {
  115. pr_debug("failed to parse event '%s', err %d\n", event_str, ret);
  116. parse_events_error__print(&err, event_str);
  117. goto out;
  118. }
  119. rblist__init(&metric_events);
  120. ret = test_expand_events(evlist, &metric_events);
  121. out:
  122. parse_events_error__exit(&err);
  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 (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. const struct pmu_metrics_table *pme_test;
  161. evlist = evlist__new();
  162. TEST_ASSERT_VAL("failed to get evlist", evlist);
  163. rblist__init(&metric_events);
  164. pme_test = find_core_metrics_table("testarch", "testcpu");
  165. ret = metricgroup__parse_groups_test(evlist, pme_test, metric_str, &metric_events);
  166. if (ret < 0) {
  167. pr_debug("failed to parse '%s' metric\n", metric_str);
  168. goto out;
  169. }
  170. ret = test_expand_events(evlist, &metric_events);
  171. out:
  172. metricgroup__rblist_exit(&metric_events);
  173. evlist__delete(evlist);
  174. return ret;
  175. }
  176. static int test__expand_cgroup_events(struct test_suite *test __maybe_unused,
  177. int subtest __maybe_unused)
  178. {
  179. int ret;
  180. ret = expand_default_events();
  181. TEST_ASSERT_EQUAL("failed to expand default events", ret, 0);
  182. ret = expand_group_events();
  183. TEST_ASSERT_EQUAL("failed to expand event group", ret, 0);
  184. ret = expand_libpfm_events();
  185. TEST_ASSERT_EQUAL("failed to expand event group", ret, 0);
  186. ret = expand_metric_events();
  187. TEST_ASSERT_EQUAL("failed to expand metric events", ret, 0);
  188. return ret;
  189. }
  190. DEFINE_SUITE("Event expansion for cgroups", expand_cgroup_events);