18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include "util/debug.h" 38c2ecf20Sopenharmony_ci#include "util/dso.h" 48c2ecf20Sopenharmony_ci#include "util/event.h" 58c2ecf20Sopenharmony_ci#include "util/map.h" 68c2ecf20Sopenharmony_ci#include "util/symbol.h" 78c2ecf20Sopenharmony_ci#include "util/sort.h" 88c2ecf20Sopenharmony_ci#include "util/evsel.h" 98c2ecf20Sopenharmony_ci#include "util/evlist.h" 108c2ecf20Sopenharmony_ci#include "util/machine.h" 118c2ecf20Sopenharmony_ci#include "util/thread.h" 128c2ecf20Sopenharmony_ci#include "util/parse-events.h" 138c2ecf20Sopenharmony_ci#include "tests/tests.h" 148c2ecf20Sopenharmony_ci#include "tests/hists_common.h" 158c2ecf20Sopenharmony_ci#include <linux/kernel.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistruct sample { 188c2ecf20Sopenharmony_ci u32 cpu; 198c2ecf20Sopenharmony_ci u32 pid; 208c2ecf20Sopenharmony_ci u64 ip; 218c2ecf20Sopenharmony_ci struct thread *thread; 228c2ecf20Sopenharmony_ci struct map *map; 238c2ecf20Sopenharmony_ci struct symbol *sym; 248c2ecf20Sopenharmony_ci}; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* For the numbers, see hists_common.c */ 278c2ecf20Sopenharmony_cistatic struct sample fake_samples[] = { 288c2ecf20Sopenharmony_ci /* perf [kernel] schedule() */ 298c2ecf20Sopenharmony_ci { .cpu = 0, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, }, 308c2ecf20Sopenharmony_ci /* perf [perf] main() */ 318c2ecf20Sopenharmony_ci { .cpu = 1, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, }, 328c2ecf20Sopenharmony_ci /* perf [perf] cmd_record() */ 338c2ecf20Sopenharmony_ci { .cpu = 1, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_CMD_RECORD, }, 348c2ecf20Sopenharmony_ci /* perf [libc] malloc() */ 358c2ecf20Sopenharmony_ci { .cpu = 1, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, }, 368c2ecf20Sopenharmony_ci /* perf [libc] free() */ 378c2ecf20Sopenharmony_ci { .cpu = 2, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_FREE, }, 388c2ecf20Sopenharmony_ci /* perf [perf] main() */ 398c2ecf20Sopenharmony_ci { .cpu = 2, .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, }, 408c2ecf20Sopenharmony_ci /* perf [kernel] page_fault() */ 418c2ecf20Sopenharmony_ci { .cpu = 2, .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, }, 428c2ecf20Sopenharmony_ci /* bash [bash] main() */ 438c2ecf20Sopenharmony_ci { .cpu = 3, .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_MAIN, }, 448c2ecf20Sopenharmony_ci /* bash [bash] xmalloc() */ 458c2ecf20Sopenharmony_ci { .cpu = 0, .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_XMALLOC, }, 468c2ecf20Sopenharmony_ci /* bash [kernel] page_fault() */ 478c2ecf20Sopenharmony_ci { .cpu = 1, .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, }, 488c2ecf20Sopenharmony_ci}; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic int add_hist_entries(struct hists *hists, struct machine *machine) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci struct addr_location al; 538c2ecf20Sopenharmony_ci struct evsel *evsel = hists_to_evsel(hists); 548c2ecf20Sopenharmony_ci struct perf_sample sample = { .period = 100, }; 558c2ecf20Sopenharmony_ci size_t i; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { 588c2ecf20Sopenharmony_ci struct hist_entry_iter iter = { 598c2ecf20Sopenharmony_ci .evsel = evsel, 608c2ecf20Sopenharmony_ci .sample = &sample, 618c2ecf20Sopenharmony_ci .ops = &hist_iter_normal, 628c2ecf20Sopenharmony_ci .hide_unresolved = false, 638c2ecf20Sopenharmony_ci }; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci sample.cpumode = PERF_RECORD_MISC_USER; 668c2ecf20Sopenharmony_ci sample.cpu = fake_samples[i].cpu; 678c2ecf20Sopenharmony_ci sample.pid = fake_samples[i].pid; 688c2ecf20Sopenharmony_ci sample.tid = fake_samples[i].pid; 698c2ecf20Sopenharmony_ci sample.ip = fake_samples[i].ip; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci if (machine__resolve(machine, &al, &sample) < 0) 728c2ecf20Sopenharmony_ci goto out; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack, 758c2ecf20Sopenharmony_ci NULL) < 0) { 768c2ecf20Sopenharmony_ci addr_location__put(&al); 778c2ecf20Sopenharmony_ci goto out; 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci fake_samples[i].thread = al.thread; 818c2ecf20Sopenharmony_ci fake_samples[i].map = al.map; 828c2ecf20Sopenharmony_ci fake_samples[i].sym = al.sym; 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci return TEST_OK; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ciout: 888c2ecf20Sopenharmony_ci pr_debug("Not enough memory for adding a hist entry\n"); 898c2ecf20Sopenharmony_ci return TEST_FAIL; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic void del_hist_entries(struct hists *hists) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci struct hist_entry *he; 958c2ecf20Sopenharmony_ci struct rb_root_cached *root_in; 968c2ecf20Sopenharmony_ci struct rb_root_cached *root_out; 978c2ecf20Sopenharmony_ci struct rb_node *node; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci if (hists__has(hists, need_collapse)) 1008c2ecf20Sopenharmony_ci root_in = &hists->entries_collapsed; 1018c2ecf20Sopenharmony_ci else 1028c2ecf20Sopenharmony_ci root_in = hists->entries_in; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci root_out = &hists->entries; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci while (!RB_EMPTY_ROOT(&root_out->rb_root)) { 1078c2ecf20Sopenharmony_ci node = rb_first_cached(root_out); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 1108c2ecf20Sopenharmony_ci rb_erase_cached(node, root_out); 1118c2ecf20Sopenharmony_ci rb_erase_cached(&he->rb_node_in, root_in); 1128c2ecf20Sopenharmony_ci hist_entry__delete(he); 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_citypedef int (*test_fn_t)(struct evsel *, struct machine *); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci#define COMM(he) (thread__comm_str(he->thread)) 1198c2ecf20Sopenharmony_ci#define DSO(he) (he->ms.map->dso->short_name) 1208c2ecf20Sopenharmony_ci#define SYM(he) (he->ms.sym->name) 1218c2ecf20Sopenharmony_ci#define CPU(he) (he->cpu) 1228c2ecf20Sopenharmony_ci#define PID(he) (he->thread->tid) 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci/* default sort keys (no field) */ 1258c2ecf20Sopenharmony_cistatic int test1(struct evsel *evsel, struct machine *machine) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci int err; 1288c2ecf20Sopenharmony_ci struct hists *hists = evsel__hists(evsel); 1298c2ecf20Sopenharmony_ci struct hist_entry *he; 1308c2ecf20Sopenharmony_ci struct rb_root_cached *root; 1318c2ecf20Sopenharmony_ci struct rb_node *node; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci field_order = NULL; 1348c2ecf20Sopenharmony_ci sort_order = NULL; /* equivalent to sort_order = "comm,dso,sym" */ 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci setup_sorting(NULL); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci /* 1398c2ecf20Sopenharmony_ci * expected output: 1408c2ecf20Sopenharmony_ci * 1418c2ecf20Sopenharmony_ci * Overhead Command Shared Object Symbol 1428c2ecf20Sopenharmony_ci * ======== ======= ============= ============== 1438c2ecf20Sopenharmony_ci * 20.00% perf perf [.] main 1448c2ecf20Sopenharmony_ci * 10.00% bash [kernel] [k] page_fault 1458c2ecf20Sopenharmony_ci * 10.00% bash bash [.] main 1468c2ecf20Sopenharmony_ci * 10.00% bash bash [.] xmalloc 1478c2ecf20Sopenharmony_ci * 10.00% perf [kernel] [k] page_fault 1488c2ecf20Sopenharmony_ci * 10.00% perf [kernel] [k] schedule 1498c2ecf20Sopenharmony_ci * 10.00% perf libc [.] free 1508c2ecf20Sopenharmony_ci * 10.00% perf libc [.] malloc 1518c2ecf20Sopenharmony_ci * 10.00% perf perf [.] cmd_record 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_ci err = add_hist_entries(hists, machine); 1548c2ecf20Sopenharmony_ci if (err < 0) 1558c2ecf20Sopenharmony_ci goto out; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci hists__collapse_resort(hists, NULL); 1588c2ecf20Sopenharmony_ci evsel__output_resort(evsel, NULL); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (verbose > 2) { 1618c2ecf20Sopenharmony_ci pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 1628c2ecf20Sopenharmony_ci print_hists_out(hists); 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci root = &hists->entries; 1668c2ecf20Sopenharmony_ci node = rb_first_cached(root); 1678c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 1688c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 1698c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && 1708c2ecf20Sopenharmony_ci !strcmp(SYM(he), "main") && he->stat.period == 200); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci node = rb_next(node); 1738c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 1748c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 1758c2ecf20Sopenharmony_ci !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "[kernel]") && 1768c2ecf20Sopenharmony_ci !strcmp(SYM(he), "page_fault") && he->stat.period == 100); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci node = rb_next(node); 1798c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 1808c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 1818c2ecf20Sopenharmony_ci !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && 1828c2ecf20Sopenharmony_ci !strcmp(SYM(he), "main") && he->stat.period == 100); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci node = rb_next(node); 1858c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 1868c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 1878c2ecf20Sopenharmony_ci !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && 1888c2ecf20Sopenharmony_ci !strcmp(SYM(he), "xmalloc") && he->stat.period == 100); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci node = rb_next(node); 1918c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 1928c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 1938c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && 1948c2ecf20Sopenharmony_ci !strcmp(SYM(he), "page_fault") && he->stat.period == 100); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci node = rb_next(node); 1978c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 1988c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 1998c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && 2008c2ecf20Sopenharmony_ci !strcmp(SYM(he), "schedule") && he->stat.period == 100); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci node = rb_next(node); 2038c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 2048c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 2058c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && 2068c2ecf20Sopenharmony_ci !strcmp(SYM(he), "free") && he->stat.period == 100); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci node = rb_next(node); 2098c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 2108c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 2118c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && 2128c2ecf20Sopenharmony_ci !strcmp(SYM(he), "malloc") && he->stat.period == 100); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci node = rb_next(node); 2158c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 2168c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 2178c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && 2188c2ecf20Sopenharmony_ci !strcmp(SYM(he), "cmd_record") && he->stat.period == 100); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ciout: 2218c2ecf20Sopenharmony_ci del_hist_entries(hists); 2228c2ecf20Sopenharmony_ci reset_output_field(); 2238c2ecf20Sopenharmony_ci return err; 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci/* mixed fields and sort keys */ 2278c2ecf20Sopenharmony_cistatic int test2(struct evsel *evsel, struct machine *machine) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci int err; 2308c2ecf20Sopenharmony_ci struct hists *hists = evsel__hists(evsel); 2318c2ecf20Sopenharmony_ci struct hist_entry *he; 2328c2ecf20Sopenharmony_ci struct rb_root_cached *root; 2338c2ecf20Sopenharmony_ci struct rb_node *node; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci field_order = "overhead,cpu"; 2368c2ecf20Sopenharmony_ci sort_order = "pid"; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci setup_sorting(NULL); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci /* 2418c2ecf20Sopenharmony_ci * expected output: 2428c2ecf20Sopenharmony_ci * 2438c2ecf20Sopenharmony_ci * Overhead CPU Command: Pid 2448c2ecf20Sopenharmony_ci * ======== === ============= 2458c2ecf20Sopenharmony_ci * 30.00% 1 perf : 100 2468c2ecf20Sopenharmony_ci * 10.00% 0 perf : 100 2478c2ecf20Sopenharmony_ci * 10.00% 2 perf : 100 2488c2ecf20Sopenharmony_ci * 20.00% 2 perf : 200 2498c2ecf20Sopenharmony_ci * 10.00% 0 bash : 300 2508c2ecf20Sopenharmony_ci * 10.00% 1 bash : 300 2518c2ecf20Sopenharmony_ci * 10.00% 3 bash : 300 2528c2ecf20Sopenharmony_ci */ 2538c2ecf20Sopenharmony_ci err = add_hist_entries(hists, machine); 2548c2ecf20Sopenharmony_ci if (err < 0) 2558c2ecf20Sopenharmony_ci goto out; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci hists__collapse_resort(hists, NULL); 2588c2ecf20Sopenharmony_ci evsel__output_resort(evsel, NULL); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci if (verbose > 2) { 2618c2ecf20Sopenharmony_ci pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 2628c2ecf20Sopenharmony_ci print_hists_out(hists); 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci root = &hists->entries; 2668c2ecf20Sopenharmony_ci node = rb_first_cached(root); 2678c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 2688c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 2698c2ecf20Sopenharmony_ci CPU(he) == 1 && PID(he) == 100 && he->stat.period == 300); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci node = rb_next(node); 2728c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 2738c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 2748c2ecf20Sopenharmony_ci CPU(he) == 0 && PID(he) == 100 && he->stat.period == 100); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ciout: 2778c2ecf20Sopenharmony_ci del_hist_entries(hists); 2788c2ecf20Sopenharmony_ci reset_output_field(); 2798c2ecf20Sopenharmony_ci return err; 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci/* fields only (no sort key) */ 2838c2ecf20Sopenharmony_cistatic int test3(struct evsel *evsel, struct machine *machine) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci int err; 2868c2ecf20Sopenharmony_ci struct hists *hists = evsel__hists(evsel); 2878c2ecf20Sopenharmony_ci struct hist_entry *he; 2888c2ecf20Sopenharmony_ci struct rb_root_cached *root; 2898c2ecf20Sopenharmony_ci struct rb_node *node; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci field_order = "comm,overhead,dso"; 2928c2ecf20Sopenharmony_ci sort_order = NULL; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci setup_sorting(NULL); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci /* 2978c2ecf20Sopenharmony_ci * expected output: 2988c2ecf20Sopenharmony_ci * 2998c2ecf20Sopenharmony_ci * Command Overhead Shared Object 3008c2ecf20Sopenharmony_ci * ======= ======== ============= 3018c2ecf20Sopenharmony_ci * bash 20.00% bash 3028c2ecf20Sopenharmony_ci * bash 10.00% [kernel] 3038c2ecf20Sopenharmony_ci * perf 30.00% perf 3048c2ecf20Sopenharmony_ci * perf 20.00% [kernel] 3058c2ecf20Sopenharmony_ci * perf 20.00% libc 3068c2ecf20Sopenharmony_ci */ 3078c2ecf20Sopenharmony_ci err = add_hist_entries(hists, machine); 3088c2ecf20Sopenharmony_ci if (err < 0) 3098c2ecf20Sopenharmony_ci goto out; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci hists__collapse_resort(hists, NULL); 3128c2ecf20Sopenharmony_ci evsel__output_resort(evsel, NULL); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (verbose > 2) { 3158c2ecf20Sopenharmony_ci pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 3168c2ecf20Sopenharmony_ci print_hists_out(hists); 3178c2ecf20Sopenharmony_ci } 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci root = &hists->entries; 3208c2ecf20Sopenharmony_ci node = rb_first_cached(root); 3218c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 3228c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 3238c2ecf20Sopenharmony_ci !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && 3248c2ecf20Sopenharmony_ci he->stat.period == 200); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci node = rb_next(node); 3278c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 3288c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 3298c2ecf20Sopenharmony_ci !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "[kernel]") && 3308c2ecf20Sopenharmony_ci he->stat.period == 100); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci node = rb_next(node); 3338c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 3348c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 3358c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && 3368c2ecf20Sopenharmony_ci he->stat.period == 300); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci node = rb_next(node); 3398c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 3408c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 3418c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && 3428c2ecf20Sopenharmony_ci he->stat.period == 200); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci node = rb_next(node); 3458c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 3468c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 3478c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && 3488c2ecf20Sopenharmony_ci he->stat.period == 200); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ciout: 3518c2ecf20Sopenharmony_ci del_hist_entries(hists); 3528c2ecf20Sopenharmony_ci reset_output_field(); 3538c2ecf20Sopenharmony_ci return err; 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci/* handle duplicate 'dso' field */ 3578c2ecf20Sopenharmony_cistatic int test4(struct evsel *evsel, struct machine *machine) 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci int err; 3608c2ecf20Sopenharmony_ci struct hists *hists = evsel__hists(evsel); 3618c2ecf20Sopenharmony_ci struct hist_entry *he; 3628c2ecf20Sopenharmony_ci struct rb_root_cached *root; 3638c2ecf20Sopenharmony_ci struct rb_node *node; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci field_order = "dso,sym,comm,overhead,dso"; 3668c2ecf20Sopenharmony_ci sort_order = "sym"; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci setup_sorting(NULL); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci /* 3718c2ecf20Sopenharmony_ci * expected output: 3728c2ecf20Sopenharmony_ci * 3738c2ecf20Sopenharmony_ci * Shared Object Symbol Command Overhead 3748c2ecf20Sopenharmony_ci * ============= ============== ======= ======== 3758c2ecf20Sopenharmony_ci * perf [.] cmd_record perf 10.00% 3768c2ecf20Sopenharmony_ci * libc [.] free perf 10.00% 3778c2ecf20Sopenharmony_ci * bash [.] main bash 10.00% 3788c2ecf20Sopenharmony_ci * perf [.] main perf 20.00% 3798c2ecf20Sopenharmony_ci * libc [.] malloc perf 10.00% 3808c2ecf20Sopenharmony_ci * [kernel] [k] page_fault bash 10.00% 3818c2ecf20Sopenharmony_ci * [kernel] [k] page_fault perf 10.00% 3828c2ecf20Sopenharmony_ci * [kernel] [k] schedule perf 10.00% 3838c2ecf20Sopenharmony_ci * bash [.] xmalloc bash 10.00% 3848c2ecf20Sopenharmony_ci */ 3858c2ecf20Sopenharmony_ci err = add_hist_entries(hists, machine); 3868c2ecf20Sopenharmony_ci if (err < 0) 3878c2ecf20Sopenharmony_ci goto out; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci hists__collapse_resort(hists, NULL); 3908c2ecf20Sopenharmony_ci evsel__output_resort(evsel, NULL); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci if (verbose > 2) { 3938c2ecf20Sopenharmony_ci pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 3948c2ecf20Sopenharmony_ci print_hists_out(hists); 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci root = &hists->entries; 3988c2ecf20Sopenharmony_ci node = rb_first_cached(root); 3998c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 4008c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 4018c2ecf20Sopenharmony_ci !strcmp(DSO(he), "perf") && !strcmp(SYM(he), "cmd_record") && 4028c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && he->stat.period == 100); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci node = rb_next(node); 4058c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 4068c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 4078c2ecf20Sopenharmony_ci !strcmp(DSO(he), "libc") && !strcmp(SYM(he), "free") && 4088c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && he->stat.period == 100); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci node = rb_next(node); 4118c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 4128c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 4138c2ecf20Sopenharmony_ci !strcmp(DSO(he), "bash") && !strcmp(SYM(he), "main") && 4148c2ecf20Sopenharmony_ci !strcmp(COMM(he), "bash") && he->stat.period == 100); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci node = rb_next(node); 4178c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 4188c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 4198c2ecf20Sopenharmony_ci !strcmp(DSO(he), "perf") && !strcmp(SYM(he), "main") && 4208c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && he->stat.period == 200); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci node = rb_next(node); 4238c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 4248c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 4258c2ecf20Sopenharmony_ci !strcmp(DSO(he), "libc") && !strcmp(SYM(he), "malloc") && 4268c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && he->stat.period == 100); 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci node = rb_next(node); 4298c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 4308c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 4318c2ecf20Sopenharmony_ci !strcmp(DSO(he), "[kernel]") && !strcmp(SYM(he), "page_fault") && 4328c2ecf20Sopenharmony_ci !strcmp(COMM(he), "bash") && he->stat.period == 100); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci node = rb_next(node); 4358c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 4368c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 4378c2ecf20Sopenharmony_ci !strcmp(DSO(he), "[kernel]") && !strcmp(SYM(he), "page_fault") && 4388c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && he->stat.period == 100); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci node = rb_next(node); 4418c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 4428c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 4438c2ecf20Sopenharmony_ci !strcmp(DSO(he), "[kernel]") && !strcmp(SYM(he), "schedule") && 4448c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && he->stat.period == 100); 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci node = rb_next(node); 4478c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 4488c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 4498c2ecf20Sopenharmony_ci !strcmp(DSO(he), "bash") && !strcmp(SYM(he), "xmalloc") && 4508c2ecf20Sopenharmony_ci !strcmp(COMM(he), "bash") && he->stat.period == 100); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ciout: 4538c2ecf20Sopenharmony_ci del_hist_entries(hists); 4548c2ecf20Sopenharmony_ci reset_output_field(); 4558c2ecf20Sopenharmony_ci return err; 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci/* full sort keys w/o overhead field */ 4598c2ecf20Sopenharmony_cistatic int test5(struct evsel *evsel, struct machine *machine) 4608c2ecf20Sopenharmony_ci{ 4618c2ecf20Sopenharmony_ci int err; 4628c2ecf20Sopenharmony_ci struct hists *hists = evsel__hists(evsel); 4638c2ecf20Sopenharmony_ci struct hist_entry *he; 4648c2ecf20Sopenharmony_ci struct rb_root_cached *root; 4658c2ecf20Sopenharmony_ci struct rb_node *node; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci field_order = "cpu,pid,comm,dso,sym"; 4688c2ecf20Sopenharmony_ci sort_order = "dso,pid"; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci setup_sorting(NULL); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci /* 4738c2ecf20Sopenharmony_ci * expected output: 4748c2ecf20Sopenharmony_ci * 4758c2ecf20Sopenharmony_ci * CPU Command: Pid Command Shared Object Symbol 4768c2ecf20Sopenharmony_ci * === ============= ======= ============= ============== 4778c2ecf20Sopenharmony_ci * 0 perf: 100 perf [kernel] [k] schedule 4788c2ecf20Sopenharmony_ci * 2 perf: 200 perf [kernel] [k] page_fault 4798c2ecf20Sopenharmony_ci * 1 bash: 300 bash [kernel] [k] page_fault 4808c2ecf20Sopenharmony_ci * 0 bash: 300 bash bash [.] xmalloc 4818c2ecf20Sopenharmony_ci * 3 bash: 300 bash bash [.] main 4828c2ecf20Sopenharmony_ci * 1 perf: 100 perf libc [.] malloc 4838c2ecf20Sopenharmony_ci * 2 perf: 100 perf libc [.] free 4848c2ecf20Sopenharmony_ci * 1 perf: 100 perf perf [.] cmd_record 4858c2ecf20Sopenharmony_ci * 1 perf: 100 perf perf [.] main 4868c2ecf20Sopenharmony_ci * 2 perf: 200 perf perf [.] main 4878c2ecf20Sopenharmony_ci */ 4888c2ecf20Sopenharmony_ci err = add_hist_entries(hists, machine); 4898c2ecf20Sopenharmony_ci if (err < 0) 4908c2ecf20Sopenharmony_ci goto out; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci hists__collapse_resort(hists, NULL); 4938c2ecf20Sopenharmony_ci evsel__output_resort(evsel, NULL); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci if (verbose > 2) { 4968c2ecf20Sopenharmony_ci pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 4978c2ecf20Sopenharmony_ci print_hists_out(hists); 4988c2ecf20Sopenharmony_ci } 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci root = &hists->entries; 5018c2ecf20Sopenharmony_ci node = rb_first_cached(root); 5028c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 5058c2ecf20Sopenharmony_ci CPU(he) == 0 && PID(he) == 100 && 5068c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && 5078c2ecf20Sopenharmony_ci !strcmp(SYM(he), "schedule") && he->stat.period == 100); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci node = rb_next(node); 5108c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 5118c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 5128c2ecf20Sopenharmony_ci CPU(he) == 2 && PID(he) == 200 && 5138c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && 5148c2ecf20Sopenharmony_ci !strcmp(SYM(he), "page_fault") && he->stat.period == 100); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci node = rb_next(node); 5178c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 5188c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 5198c2ecf20Sopenharmony_ci CPU(he) == 1 && PID(he) == 300 && 5208c2ecf20Sopenharmony_ci !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "[kernel]") && 5218c2ecf20Sopenharmony_ci !strcmp(SYM(he), "page_fault") && he->stat.period == 100); 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci node = rb_next(node); 5248c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 5258c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 5268c2ecf20Sopenharmony_ci CPU(he) == 0 && PID(he) == 300 && 5278c2ecf20Sopenharmony_ci !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && 5288c2ecf20Sopenharmony_ci !strcmp(SYM(he), "xmalloc") && he->stat.period == 100); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci node = rb_next(node); 5318c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 5328c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 5338c2ecf20Sopenharmony_ci CPU(he) == 3 && PID(he) == 300 && 5348c2ecf20Sopenharmony_ci !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && 5358c2ecf20Sopenharmony_ci !strcmp(SYM(he), "main") && he->stat.period == 100); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci node = rb_next(node); 5388c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 5398c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 5408c2ecf20Sopenharmony_ci CPU(he) == 1 && PID(he) == 100 && 5418c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && 5428c2ecf20Sopenharmony_ci !strcmp(SYM(he), "malloc") && he->stat.period == 100); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci node = rb_next(node); 5458c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 5468c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 5478c2ecf20Sopenharmony_ci CPU(he) == 2 && PID(he) == 100 && 5488c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && 5498c2ecf20Sopenharmony_ci !strcmp(SYM(he), "free") && he->stat.period == 100); 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci node = rb_next(node); 5528c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 5538c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 5548c2ecf20Sopenharmony_ci CPU(he) == 1 && PID(he) == 100 && 5558c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && 5568c2ecf20Sopenharmony_ci !strcmp(SYM(he), "cmd_record") && he->stat.period == 100); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci node = rb_next(node); 5598c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 5608c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 5618c2ecf20Sopenharmony_ci CPU(he) == 1 && PID(he) == 100 && 5628c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && 5638c2ecf20Sopenharmony_ci !strcmp(SYM(he), "main") && he->stat.period == 100); 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci node = rb_next(node); 5668c2ecf20Sopenharmony_ci he = rb_entry(node, struct hist_entry, rb_node); 5678c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Invalid hist entry", 5688c2ecf20Sopenharmony_ci CPU(he) == 2 && PID(he) == 200 && 5698c2ecf20Sopenharmony_ci !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && 5708c2ecf20Sopenharmony_ci !strcmp(SYM(he), "main") && he->stat.period == 100); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ciout: 5738c2ecf20Sopenharmony_ci del_hist_entries(hists); 5748c2ecf20Sopenharmony_ci reset_output_field(); 5758c2ecf20Sopenharmony_ci return err; 5768c2ecf20Sopenharmony_ci} 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ciint test__hists_output(struct test *test __maybe_unused, int subtest __maybe_unused) 5798c2ecf20Sopenharmony_ci{ 5808c2ecf20Sopenharmony_ci int err = TEST_FAIL; 5818c2ecf20Sopenharmony_ci struct machines machines; 5828c2ecf20Sopenharmony_ci struct machine *machine; 5838c2ecf20Sopenharmony_ci struct evsel *evsel; 5848c2ecf20Sopenharmony_ci struct evlist *evlist = evlist__new(); 5858c2ecf20Sopenharmony_ci size_t i; 5868c2ecf20Sopenharmony_ci test_fn_t testcases[] = { 5878c2ecf20Sopenharmony_ci test1, 5888c2ecf20Sopenharmony_ci test2, 5898c2ecf20Sopenharmony_ci test3, 5908c2ecf20Sopenharmony_ci test4, 5918c2ecf20Sopenharmony_ci test5, 5928c2ecf20Sopenharmony_ci }; 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("No memory", evlist); 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci err = parse_events(evlist, "cpu-clock", NULL); 5978c2ecf20Sopenharmony_ci if (err) 5988c2ecf20Sopenharmony_ci goto out; 5998c2ecf20Sopenharmony_ci err = TEST_FAIL; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci machines__init(&machines); 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci /* setup threads/dso/map/symbols also */ 6048c2ecf20Sopenharmony_ci machine = setup_fake_machine(&machines); 6058c2ecf20Sopenharmony_ci if (!machine) 6068c2ecf20Sopenharmony_ci goto out; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci if (verbose > 1) 6098c2ecf20Sopenharmony_ci machine__fprintf(machine, stderr); 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci evsel = evlist__first(evlist); 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(testcases); i++) { 6148c2ecf20Sopenharmony_ci err = testcases[i](evsel, machine); 6158c2ecf20Sopenharmony_ci if (err < 0) 6168c2ecf20Sopenharmony_ci break; 6178c2ecf20Sopenharmony_ci } 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ciout: 6208c2ecf20Sopenharmony_ci /* tear down everything */ 6218c2ecf20Sopenharmony_ci evlist__delete(evlist); 6228c2ecf20Sopenharmony_ci machines__exit(&machines); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci return err; 6258c2ecf20Sopenharmony_ci} 626