]>
Commit | Line | Data |
---|---|---|
f21d1815 NK |
1 | #include "perf.h" |
2 | #include "util/debug.h" | |
3 | #include "util/symbol.h" | |
4 | #include "util/sort.h" | |
5 | #include "util/evsel.h" | |
6 | #include "util/evlist.h" | |
7 | #include "util/machine.h" | |
8 | #include "util/thread.h" | |
9 | #include "util/parse-events.h" | |
10 | #include "tests/tests.h" | |
11 | #include "tests/hists_common.h" | |
12 | ||
13 | struct sample { | |
14 | u32 cpu; | |
15 | u32 pid; | |
16 | u64 ip; | |
17 | struct thread *thread; | |
18 | struct map *map; | |
19 | struct symbol *sym; | |
20 | }; | |
21 | ||
22 | /* For the numbers, see hists_common.c */ | |
23 | static struct sample fake_samples[] = { | |
24 | /* perf [kernel] schedule() */ | |
a1891aa4 | 25 | { .cpu = 0, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, }, |
f21d1815 | 26 | /* perf [perf] main() */ |
a1891aa4 | 27 | { .cpu = 1, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, }, |
f21d1815 | 28 | /* perf [perf] cmd_record() */ |
a1891aa4 | 29 | { .cpu = 1, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_CMD_RECORD, }, |
f21d1815 | 30 | /* perf [libc] malloc() */ |
a1891aa4 | 31 | { .cpu = 1, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, }, |
f21d1815 | 32 | /* perf [libc] free() */ |
a1891aa4 | 33 | { .cpu = 2, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_FREE, }, |
f21d1815 | 34 | /* perf [perf] main() */ |
a1891aa4 | 35 | { .cpu = 2, .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, }, |
f21d1815 | 36 | /* perf [kernel] page_fault() */ |
a1891aa4 | 37 | { .cpu = 2, .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, }, |
f21d1815 | 38 | /* bash [bash] main() */ |
a1891aa4 | 39 | { .cpu = 3, .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_MAIN, }, |
f21d1815 | 40 | /* bash [bash] xmalloc() */ |
a1891aa4 | 41 | { .cpu = 0, .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_XMALLOC, }, |
f21d1815 | 42 | /* bash [kernel] page_fault() */ |
a1891aa4 | 43 | { .cpu = 1, .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, }, |
f21d1815 NK |
44 | }; |
45 | ||
46 | static int add_hist_entries(struct hists *hists, struct machine *machine) | |
47 | { | |
48 | struct addr_location al; | |
69bcb019 | 49 | struct perf_evsel *evsel = hists_to_evsel(hists); |
f21d1815 NK |
50 | struct perf_sample sample = { .period = 100, }; |
51 | size_t i; | |
52 | ||
53 | for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { | |
54 | const union perf_event event = { | |
55 | .header = { | |
56 | .misc = PERF_RECORD_MISC_USER, | |
57 | }, | |
58 | }; | |
69bcb019 | 59 | struct hist_entry_iter iter = { |
063bd936 NK |
60 | .evsel = evsel, |
61 | .sample = &sample, | |
69bcb019 NK |
62 | .ops = &hist_iter_normal, |
63 | .hide_unresolved = false, | |
64 | }; | |
f21d1815 NK |
65 | |
66 | sample.cpu = fake_samples[i].cpu; | |
67 | sample.pid = fake_samples[i].pid; | |
68 | sample.tid = fake_samples[i].pid; | |
69 | sample.ip = fake_samples[i].ip; | |
70 | ||
71 | if (perf_event__preprocess_sample(&event, machine, &al, | |
72 | &sample) < 0) | |
73 | goto out; | |
74 | ||
063bd936 NK |
75 | if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH, |
76 | NULL) < 0) { | |
b91fc39f | 77 | addr_location__put(&al); |
f21d1815 | 78 | goto out; |
b91fc39f | 79 | } |
f21d1815 NK |
80 | |
81 | fake_samples[i].thread = al.thread; | |
82 | fake_samples[i].map = al.map; | |
83 | fake_samples[i].sym = al.sym; | |
84 | } | |
85 | ||
86 | return TEST_OK; | |
87 | ||
88 | out: | |
89 | pr_debug("Not enough memory for adding a hist entry\n"); | |
90 | return TEST_FAIL; | |
91 | } | |
92 | ||
93 | static void del_hist_entries(struct hists *hists) | |
94 | { | |
95 | struct hist_entry *he; | |
96 | struct rb_root *root_in; | |
97 | struct rb_root *root_out; | |
98 | struct rb_node *node; | |
99 | ||
100 | if (sort__need_collapse) | |
101 | root_in = &hists->entries_collapsed; | |
102 | else | |
103 | root_in = hists->entries_in; | |
104 | ||
105 | root_out = &hists->entries; | |
106 | ||
107 | while (!RB_EMPTY_ROOT(root_out)) { | |
108 | node = rb_first(root_out); | |
109 | ||
110 | he = rb_entry(node, struct hist_entry, rb_node); | |
111 | rb_erase(node, root_out); | |
112 | rb_erase(&he->rb_node_in, root_in); | |
6733d1bf | 113 | hist_entry__delete(he); |
f21d1815 NK |
114 | } |
115 | } | |
116 | ||
117 | typedef int (*test_fn_t)(struct perf_evsel *, struct machine *); | |
118 | ||
119 | #define COMM(he) (thread__comm_str(he->thread)) | |
120 | #define DSO(he) (he->ms.map->dso->short_name) | |
121 | #define SYM(he) (he->ms.sym->name) | |
122 | #define CPU(he) (he->cpu) | |
123 | #define PID(he) (he->thread->tid) | |
124 | ||
125 | /* default sort keys (no field) */ | |
126 | static int test1(struct perf_evsel *evsel, struct machine *machine) | |
127 | { | |
128 | int err; | |
4ea062ed | 129 | struct hists *hists = evsel__hists(evsel); |
f21d1815 NK |
130 | struct hist_entry *he; |
131 | struct rb_root *root; | |
132 | struct rb_node *node; | |
133 | ||
134 | field_order = NULL; | |
135 | sort_order = NULL; /* equivalent to sort_order = "comm,dso,sym" */ | |
136 | ||
40184c46 | 137 | setup_sorting(NULL); |
f21d1815 NK |
138 | |
139 | /* | |
140 | * expected output: | |
141 | * | |
142 | * Overhead Command Shared Object Symbol | |
143 | * ======== ======= ============= ============== | |
144 | * 20.00% perf perf [.] main | |
145 | * 10.00% bash [kernel] [k] page_fault | |
146 | * 10.00% bash bash [.] main | |
147 | * 10.00% bash bash [.] xmalloc | |
148 | * 10.00% perf [kernel] [k] page_fault | |
149 | * 10.00% perf [kernel] [k] schedule | |
150 | * 10.00% perf libc [.] free | |
151 | * 10.00% perf libc [.] malloc | |
152 | * 10.00% perf perf [.] cmd_record | |
153 | */ | |
154 | err = add_hist_entries(hists, machine); | |
155 | if (err < 0) | |
156 | goto out; | |
157 | ||
158 | hists__collapse_resort(hists, NULL); | |
452ce03b | 159 | perf_evsel__output_resort(evsel, NULL); |
f21d1815 NK |
160 | |
161 | if (verbose > 2) { | |
162 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | |
163 | print_hists_out(hists); | |
164 | } | |
165 | ||
4ea062ed | 166 | root = &hists->entries; |
f21d1815 NK |
167 | node = rb_first(root); |
168 | he = rb_entry(node, struct hist_entry, rb_node); | |
169 | TEST_ASSERT_VAL("Invalid hist entry", | |
170 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && | |
171 | !strcmp(SYM(he), "main") && he->stat.period == 200); | |
172 | ||
173 | node = rb_next(node); | |
174 | he = rb_entry(node, struct hist_entry, rb_node); | |
175 | TEST_ASSERT_VAL("Invalid hist entry", | |
176 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "[kernel]") && | |
177 | !strcmp(SYM(he), "page_fault") && he->stat.period == 100); | |
178 | ||
179 | node = rb_next(node); | |
180 | he = rb_entry(node, struct hist_entry, rb_node); | |
181 | TEST_ASSERT_VAL("Invalid hist entry", | |
182 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && | |
183 | !strcmp(SYM(he), "main") && he->stat.period == 100); | |
184 | ||
185 | node = rb_next(node); | |
186 | he = rb_entry(node, struct hist_entry, rb_node); | |
187 | TEST_ASSERT_VAL("Invalid hist entry", | |
188 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && | |
189 | !strcmp(SYM(he), "xmalloc") && he->stat.period == 100); | |
190 | ||
191 | node = rb_next(node); | |
192 | he = rb_entry(node, struct hist_entry, rb_node); | |
193 | TEST_ASSERT_VAL("Invalid hist entry", | |
194 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && | |
195 | !strcmp(SYM(he), "page_fault") && he->stat.period == 100); | |
196 | ||
197 | node = rb_next(node); | |
198 | he = rb_entry(node, struct hist_entry, rb_node); | |
199 | TEST_ASSERT_VAL("Invalid hist entry", | |
200 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && | |
201 | !strcmp(SYM(he), "schedule") && he->stat.period == 100); | |
202 | ||
203 | node = rb_next(node); | |
204 | he = rb_entry(node, struct hist_entry, rb_node); | |
205 | TEST_ASSERT_VAL("Invalid hist entry", | |
206 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && | |
207 | !strcmp(SYM(he), "free") && he->stat.period == 100); | |
208 | ||
209 | node = rb_next(node); | |
210 | he = rb_entry(node, struct hist_entry, rb_node); | |
211 | TEST_ASSERT_VAL("Invalid hist entry", | |
212 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && | |
213 | !strcmp(SYM(he), "malloc") && he->stat.period == 100); | |
214 | ||
215 | node = rb_next(node); | |
216 | he = rb_entry(node, struct hist_entry, rb_node); | |
217 | TEST_ASSERT_VAL("Invalid hist entry", | |
218 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && | |
219 | !strcmp(SYM(he), "cmd_record") && he->stat.period == 100); | |
220 | ||
221 | out: | |
222 | del_hist_entries(hists); | |
223 | reset_output_field(); | |
224 | return err; | |
225 | } | |
226 | ||
227 | /* mixed fields and sort keys */ | |
228 | static int test2(struct perf_evsel *evsel, struct machine *machine) | |
229 | { | |
230 | int err; | |
4ea062ed | 231 | struct hists *hists = evsel__hists(evsel); |
f21d1815 NK |
232 | struct hist_entry *he; |
233 | struct rb_root *root; | |
234 | struct rb_node *node; | |
235 | ||
236 | field_order = "overhead,cpu"; | |
237 | sort_order = "pid"; | |
238 | ||
40184c46 | 239 | setup_sorting(NULL); |
f21d1815 NK |
240 | |
241 | /* | |
242 | * expected output: | |
243 | * | |
244 | * Overhead CPU Command: Pid | |
245 | * ======== === ============= | |
246 | * 30.00% 1 perf : 100 | |
247 | * 10.00% 0 perf : 100 | |
248 | * 10.00% 2 perf : 100 | |
249 | * 20.00% 2 perf : 200 | |
250 | * 10.00% 0 bash : 300 | |
251 | * 10.00% 1 bash : 300 | |
252 | * 10.00% 3 bash : 300 | |
253 | */ | |
254 | err = add_hist_entries(hists, machine); | |
255 | if (err < 0) | |
256 | goto out; | |
257 | ||
258 | hists__collapse_resort(hists, NULL); | |
452ce03b | 259 | perf_evsel__output_resort(evsel, NULL); |
f21d1815 NK |
260 | |
261 | if (verbose > 2) { | |
262 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | |
263 | print_hists_out(hists); | |
264 | } | |
265 | ||
4ea062ed | 266 | root = &hists->entries; |
f21d1815 NK |
267 | node = rb_first(root); |
268 | he = rb_entry(node, struct hist_entry, rb_node); | |
269 | TEST_ASSERT_VAL("Invalid hist entry", | |
270 | CPU(he) == 1 && PID(he) == 100 && he->stat.period == 300); | |
271 | ||
272 | node = rb_next(node); | |
273 | he = rb_entry(node, struct hist_entry, rb_node); | |
274 | TEST_ASSERT_VAL("Invalid hist entry", | |
275 | CPU(he) == 0 && PID(he) == 100 && he->stat.period == 100); | |
276 | ||
277 | out: | |
278 | del_hist_entries(hists); | |
279 | reset_output_field(); | |
280 | return err; | |
281 | } | |
282 | ||
283 | /* fields only (no sort key) */ | |
284 | static int test3(struct perf_evsel *evsel, struct machine *machine) | |
285 | { | |
286 | int err; | |
4ea062ed | 287 | struct hists *hists = evsel__hists(evsel); |
f21d1815 NK |
288 | struct hist_entry *he; |
289 | struct rb_root *root; | |
290 | struct rb_node *node; | |
291 | ||
292 | field_order = "comm,overhead,dso"; | |
293 | sort_order = NULL; | |
294 | ||
40184c46 | 295 | setup_sorting(NULL); |
f21d1815 NK |
296 | |
297 | /* | |
298 | * expected output: | |
299 | * | |
300 | * Command Overhead Shared Object | |
301 | * ======= ======== ============= | |
302 | * bash 20.00% bash | |
303 | * bash 10.00% [kernel] | |
304 | * perf 30.00% perf | |
305 | * perf 20.00% [kernel] | |
306 | * perf 20.00% libc | |
307 | */ | |
308 | err = add_hist_entries(hists, machine); | |
309 | if (err < 0) | |
310 | goto out; | |
311 | ||
312 | hists__collapse_resort(hists, NULL); | |
452ce03b | 313 | perf_evsel__output_resort(evsel, NULL); |
f21d1815 NK |
314 | |
315 | if (verbose > 2) { | |
316 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | |
317 | print_hists_out(hists); | |
318 | } | |
319 | ||
4ea062ed | 320 | root = &hists->entries; |
f21d1815 NK |
321 | node = rb_first(root); |
322 | he = rb_entry(node, struct hist_entry, rb_node); | |
323 | TEST_ASSERT_VAL("Invalid hist entry", | |
324 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && | |
325 | he->stat.period == 200); | |
326 | ||
327 | node = rb_next(node); | |
328 | he = rb_entry(node, struct hist_entry, rb_node); | |
329 | TEST_ASSERT_VAL("Invalid hist entry", | |
330 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "[kernel]") && | |
331 | he->stat.period == 100); | |
332 | ||
333 | node = rb_next(node); | |
334 | he = rb_entry(node, struct hist_entry, rb_node); | |
335 | TEST_ASSERT_VAL("Invalid hist entry", | |
336 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && | |
337 | he->stat.period == 300); | |
338 | ||
339 | node = rb_next(node); | |
340 | he = rb_entry(node, struct hist_entry, rb_node); | |
341 | TEST_ASSERT_VAL("Invalid hist entry", | |
342 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && | |
343 | he->stat.period == 200); | |
344 | ||
345 | node = rb_next(node); | |
346 | he = rb_entry(node, struct hist_entry, rb_node); | |
347 | TEST_ASSERT_VAL("Invalid hist entry", | |
348 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && | |
349 | he->stat.period == 200); | |
350 | ||
351 | out: | |
352 | del_hist_entries(hists); | |
353 | reset_output_field(); | |
354 | return err; | |
355 | } | |
356 | ||
357 | /* handle duplicate 'dso' field */ | |
358 | static int test4(struct perf_evsel *evsel, struct machine *machine) | |
359 | { | |
360 | int err; | |
4ea062ed | 361 | struct hists *hists = evsel__hists(evsel); |
f21d1815 NK |
362 | struct hist_entry *he; |
363 | struct rb_root *root; | |
364 | struct rb_node *node; | |
365 | ||
366 | field_order = "dso,sym,comm,overhead,dso"; | |
367 | sort_order = "sym"; | |
368 | ||
40184c46 | 369 | setup_sorting(NULL); |
f21d1815 NK |
370 | |
371 | /* | |
372 | * expected output: | |
373 | * | |
374 | * Shared Object Symbol Command Overhead | |
375 | * ============= ============== ======= ======== | |
376 | * perf [.] cmd_record perf 10.00% | |
377 | * libc [.] free perf 10.00% | |
378 | * bash [.] main bash 10.00% | |
379 | * perf [.] main perf 20.00% | |
380 | * libc [.] malloc perf 10.00% | |
381 | * [kernel] [k] page_fault bash 10.00% | |
382 | * [kernel] [k] page_fault perf 10.00% | |
383 | * [kernel] [k] schedule perf 10.00% | |
384 | * bash [.] xmalloc bash 10.00% | |
385 | */ | |
386 | err = add_hist_entries(hists, machine); | |
387 | if (err < 0) | |
388 | goto out; | |
389 | ||
390 | hists__collapse_resort(hists, NULL); | |
452ce03b | 391 | perf_evsel__output_resort(evsel, NULL); |
f21d1815 NK |
392 | |
393 | if (verbose > 2) { | |
394 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | |
395 | print_hists_out(hists); | |
396 | } | |
397 | ||
4ea062ed | 398 | root = &hists->entries; |
f21d1815 NK |
399 | node = rb_first(root); |
400 | he = rb_entry(node, struct hist_entry, rb_node); | |
401 | TEST_ASSERT_VAL("Invalid hist entry", | |
402 | !strcmp(DSO(he), "perf") && !strcmp(SYM(he), "cmd_record") && | |
403 | !strcmp(COMM(he), "perf") && he->stat.period == 100); | |
404 | ||
405 | node = rb_next(node); | |
406 | he = rb_entry(node, struct hist_entry, rb_node); | |
407 | TEST_ASSERT_VAL("Invalid hist entry", | |
408 | !strcmp(DSO(he), "libc") && !strcmp(SYM(he), "free") && | |
409 | !strcmp(COMM(he), "perf") && he->stat.period == 100); | |
410 | ||
411 | node = rb_next(node); | |
412 | he = rb_entry(node, struct hist_entry, rb_node); | |
413 | TEST_ASSERT_VAL("Invalid hist entry", | |
414 | !strcmp(DSO(he), "bash") && !strcmp(SYM(he), "main") && | |
415 | !strcmp(COMM(he), "bash") && he->stat.period == 100); | |
416 | ||
417 | node = rb_next(node); | |
418 | he = rb_entry(node, struct hist_entry, rb_node); | |
419 | TEST_ASSERT_VAL("Invalid hist entry", | |
420 | !strcmp(DSO(he), "perf") && !strcmp(SYM(he), "main") && | |
421 | !strcmp(COMM(he), "perf") && he->stat.period == 200); | |
422 | ||
423 | node = rb_next(node); | |
424 | he = rb_entry(node, struct hist_entry, rb_node); | |
425 | TEST_ASSERT_VAL("Invalid hist entry", | |
426 | !strcmp(DSO(he), "libc") && !strcmp(SYM(he), "malloc") && | |
427 | !strcmp(COMM(he), "perf") && he->stat.period == 100); | |
428 | ||
429 | node = rb_next(node); | |
430 | he = rb_entry(node, struct hist_entry, rb_node); | |
431 | TEST_ASSERT_VAL("Invalid hist entry", | |
432 | !strcmp(DSO(he), "[kernel]") && !strcmp(SYM(he), "page_fault") && | |
433 | !strcmp(COMM(he), "bash") && he->stat.period == 100); | |
434 | ||
435 | node = rb_next(node); | |
436 | he = rb_entry(node, struct hist_entry, rb_node); | |
437 | TEST_ASSERT_VAL("Invalid hist entry", | |
438 | !strcmp(DSO(he), "[kernel]") && !strcmp(SYM(he), "page_fault") && | |
439 | !strcmp(COMM(he), "perf") && he->stat.period == 100); | |
440 | ||
441 | node = rb_next(node); | |
442 | he = rb_entry(node, struct hist_entry, rb_node); | |
443 | TEST_ASSERT_VAL("Invalid hist entry", | |
444 | !strcmp(DSO(he), "[kernel]") && !strcmp(SYM(he), "schedule") && | |
445 | !strcmp(COMM(he), "perf") && he->stat.period == 100); | |
446 | ||
447 | node = rb_next(node); | |
448 | he = rb_entry(node, struct hist_entry, rb_node); | |
449 | TEST_ASSERT_VAL("Invalid hist entry", | |
450 | !strcmp(DSO(he), "bash") && !strcmp(SYM(he), "xmalloc") && | |
451 | !strcmp(COMM(he), "bash") && he->stat.period == 100); | |
452 | ||
453 | out: | |
454 | del_hist_entries(hists); | |
455 | reset_output_field(); | |
456 | return err; | |
457 | } | |
458 | ||
459 | /* full sort keys w/o overhead field */ | |
460 | static int test5(struct perf_evsel *evsel, struct machine *machine) | |
461 | { | |
462 | int err; | |
4ea062ed | 463 | struct hists *hists = evsel__hists(evsel); |
f21d1815 NK |
464 | struct hist_entry *he; |
465 | struct rb_root *root; | |
466 | struct rb_node *node; | |
467 | ||
468 | field_order = "cpu,pid,comm,dso,sym"; | |
469 | sort_order = "dso,pid"; | |
470 | ||
40184c46 | 471 | setup_sorting(NULL); |
f21d1815 NK |
472 | |
473 | /* | |
474 | * expected output: | |
475 | * | |
476 | * CPU Command: Pid Command Shared Object Symbol | |
477 | * === ============= ======= ============= ============== | |
478 | * 0 perf: 100 perf [kernel] [k] schedule | |
479 | * 2 perf: 200 perf [kernel] [k] page_fault | |
480 | * 1 bash: 300 bash [kernel] [k] page_fault | |
481 | * 0 bash: 300 bash bash [.] xmalloc | |
482 | * 3 bash: 300 bash bash [.] main | |
483 | * 1 perf: 100 perf libc [.] malloc | |
484 | * 2 perf: 100 perf libc [.] free | |
485 | * 1 perf: 100 perf perf [.] cmd_record | |
486 | * 1 perf: 100 perf perf [.] main | |
487 | * 2 perf: 200 perf perf [.] main | |
488 | */ | |
489 | err = add_hist_entries(hists, machine); | |
490 | if (err < 0) | |
491 | goto out; | |
492 | ||
493 | hists__collapse_resort(hists, NULL); | |
452ce03b | 494 | perf_evsel__output_resort(evsel, NULL); |
f21d1815 NK |
495 | |
496 | if (verbose > 2) { | |
497 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | |
498 | print_hists_out(hists); | |
499 | } | |
500 | ||
4ea062ed | 501 | root = &hists->entries; |
f21d1815 NK |
502 | node = rb_first(root); |
503 | he = rb_entry(node, struct hist_entry, rb_node); | |
504 | ||
505 | TEST_ASSERT_VAL("Invalid hist entry", | |
506 | CPU(he) == 0 && PID(he) == 100 && | |
507 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && | |
508 | !strcmp(SYM(he), "schedule") && he->stat.period == 100); | |
509 | ||
510 | node = rb_next(node); | |
511 | he = rb_entry(node, struct hist_entry, rb_node); | |
512 | TEST_ASSERT_VAL("Invalid hist entry", | |
513 | CPU(he) == 2 && PID(he) == 200 && | |
514 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && | |
515 | !strcmp(SYM(he), "page_fault") && he->stat.period == 100); | |
516 | ||
517 | node = rb_next(node); | |
518 | he = rb_entry(node, struct hist_entry, rb_node); | |
519 | TEST_ASSERT_VAL("Invalid hist entry", | |
520 | CPU(he) == 1 && PID(he) == 300 && | |
521 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "[kernel]") && | |
522 | !strcmp(SYM(he), "page_fault") && he->stat.period == 100); | |
523 | ||
524 | node = rb_next(node); | |
525 | he = rb_entry(node, struct hist_entry, rb_node); | |
526 | TEST_ASSERT_VAL("Invalid hist entry", | |
527 | CPU(he) == 0 && PID(he) == 300 && | |
528 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && | |
529 | !strcmp(SYM(he), "xmalloc") && he->stat.period == 100); | |
530 | ||
531 | node = rb_next(node); | |
532 | he = rb_entry(node, struct hist_entry, rb_node); | |
533 | TEST_ASSERT_VAL("Invalid hist entry", | |
534 | CPU(he) == 3 && PID(he) == 300 && | |
535 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && | |
536 | !strcmp(SYM(he), "main") && he->stat.period == 100); | |
537 | ||
538 | node = rb_next(node); | |
539 | he = rb_entry(node, struct hist_entry, rb_node); | |
540 | TEST_ASSERT_VAL("Invalid hist entry", | |
541 | CPU(he) == 1 && PID(he) == 100 && | |
542 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && | |
543 | !strcmp(SYM(he), "malloc") && he->stat.period == 100); | |
544 | ||
545 | node = rb_next(node); | |
546 | he = rb_entry(node, struct hist_entry, rb_node); | |
547 | TEST_ASSERT_VAL("Invalid hist entry", | |
548 | CPU(he) == 2 && PID(he) == 100 && | |
549 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && | |
550 | !strcmp(SYM(he), "free") && he->stat.period == 100); | |
551 | ||
552 | node = rb_next(node); | |
553 | he = rb_entry(node, struct hist_entry, rb_node); | |
554 | TEST_ASSERT_VAL("Invalid hist entry", | |
555 | CPU(he) == 1 && PID(he) == 100 && | |
556 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && | |
557 | !strcmp(SYM(he), "cmd_record") && he->stat.period == 100); | |
558 | ||
559 | node = rb_next(node); | |
560 | he = rb_entry(node, struct hist_entry, rb_node); | |
561 | TEST_ASSERT_VAL("Invalid hist entry", | |
562 | CPU(he) == 1 && PID(he) == 100 && | |
563 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && | |
564 | !strcmp(SYM(he), "main") && he->stat.period == 100); | |
565 | ||
566 | node = rb_next(node); | |
567 | he = rb_entry(node, struct hist_entry, rb_node); | |
568 | TEST_ASSERT_VAL("Invalid hist entry", | |
569 | CPU(he) == 2 && PID(he) == 200 && | |
570 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && | |
571 | !strcmp(SYM(he), "main") && he->stat.period == 100); | |
572 | ||
573 | out: | |
574 | del_hist_entries(hists); | |
575 | reset_output_field(); | |
576 | return err; | |
577 | } | |
578 | ||
721a1f53 | 579 | int test__hists_output(int subtest __maybe_unused) |
f21d1815 NK |
580 | { |
581 | int err = TEST_FAIL; | |
582 | struct machines machines; | |
583 | struct machine *machine; | |
584 | struct perf_evsel *evsel; | |
585 | struct perf_evlist *evlist = perf_evlist__new(); | |
586 | size_t i; | |
587 | test_fn_t testcases[] = { | |
588 | test1, | |
589 | test2, | |
590 | test3, | |
591 | test4, | |
592 | test5, | |
593 | }; | |
594 | ||
595 | TEST_ASSERT_VAL("No memory", evlist); | |
596 | ||
b39b8393 | 597 | err = parse_events(evlist, "cpu-clock", NULL); |
f21d1815 NK |
598 | if (err) |
599 | goto out; | |
b0500c16 | 600 | err = TEST_FAIL; |
f21d1815 NK |
601 | |
602 | machines__init(&machines); | |
603 | ||
604 | /* setup threads/dso/map/symbols also */ | |
605 | machine = setup_fake_machine(&machines); | |
606 | if (!machine) | |
607 | goto out; | |
608 | ||
609 | if (verbose > 1) | |
610 | machine__fprintf(machine, stderr); | |
611 | ||
612 | evsel = perf_evlist__first(evlist); | |
613 | ||
614 | for (i = 0; i < ARRAY_SIZE(testcases); i++) { | |
615 | err = testcases[i](evsel, machine); | |
616 | if (err < 0) | |
617 | break; | |
618 | } | |
619 | ||
620 | out: | |
621 | /* tear down everything */ | |
622 | perf_evlist__delete(evlist); | |
623 | machines__exit(&machines); | |
624 | ||
625 | return err; | |
626 | } |