linux/tools/perf/tests/hists_cumulate.c
<<
>>
Prefs
   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
  13struct sample {
  14        u32 pid;
  15        u64 ip;
  16        struct thread *thread;
  17        struct map *map;
  18        struct symbol *sym;
  19};
  20
  21/* For the numbers, see hists_common.c */
  22static struct sample fake_samples[] = {
  23        /* perf [kernel] schedule() */
  24        { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, },
  25        /* perf [perf]   main() */
  26        { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, },
  27        /* perf [perf]   cmd_record() */
  28        { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_CMD_RECORD, },
  29        /* perf [libc]   malloc() */
  30        { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, },
  31        /* perf [libc]   free() */
  32        { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_FREE, },
  33        /* perf [perf]   main() */
  34        { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, },
  35        /* perf [kernel] page_fault() */
  36        { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
  37        /* bash [bash]   main() */
  38        { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_BASH_MAIN, },
  39        /* bash [bash]   xmalloc() */
  40        { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_BASH_XMALLOC, },
  41        /* bash [kernel] page_fault() */
  42        { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
  43};
  44
  45/*
  46 * Will be casted to struct ip_callchain which has all 64 bit entries
  47 * of nr and ips[].
  48 */
  49static u64 fake_callchains[][10] = {
  50        /*   schedule => run_command => main */
  51        { 3, FAKE_IP_KERNEL_SCHEDULE, FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, },
  52        /*   main  */
  53        { 1, FAKE_IP_PERF_MAIN, },
  54        /*   cmd_record => run_command => main */
  55        { 3, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, },
  56        /*   malloc => cmd_record => run_command => main */
  57        { 4, FAKE_IP_LIBC_MALLOC, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND,
  58             FAKE_IP_PERF_MAIN, },
  59        /*   free => cmd_record => run_command => main */
  60        { 4, FAKE_IP_LIBC_FREE, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND,
  61             FAKE_IP_PERF_MAIN, },
  62        /*   main */
  63        { 1, FAKE_IP_PERF_MAIN, },
  64        /*   page_fault => sys_perf_event_open => run_command => main */
  65        { 4, FAKE_IP_KERNEL_PAGE_FAULT, FAKE_IP_KERNEL_SYS_PERF_EVENT_OPEN,
  66             FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, },
  67        /*   main */
  68        { 1, FAKE_IP_BASH_MAIN, },
  69        /*   xmalloc => malloc => xmalloc => malloc => xmalloc => main */
  70        { 6, FAKE_IP_BASH_XMALLOC, FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_XMALLOC,
  71             FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_XMALLOC, FAKE_IP_BASH_MAIN, },
  72        /*   page_fault => malloc => main */
  73        { 3, FAKE_IP_KERNEL_PAGE_FAULT, FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_MAIN, },
  74};
  75
  76static int add_hist_entries(struct hists *hists, struct machine *machine)
  77{
  78        struct addr_location al;
  79        struct perf_evsel *evsel = hists_to_evsel(hists);
  80        struct perf_sample sample = { .period = 1000, };
  81        size_t i;
  82
  83        for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
  84                struct hist_entry_iter iter = {
  85                        .evsel = evsel,
  86                        .sample = &sample,
  87                        .hide_unresolved = false,
  88                };
  89
  90                if (symbol_conf.cumulate_callchain)
  91                        iter.ops = &hist_iter_cumulative;
  92                else
  93                        iter.ops = &hist_iter_normal;
  94
  95                sample.cpumode = PERF_RECORD_MISC_USER;
  96                sample.pid = fake_samples[i].pid;
  97                sample.tid = fake_samples[i].pid;
  98                sample.ip = fake_samples[i].ip;
  99                sample.callchain = (struct ip_callchain *)fake_callchains[i];
 100
 101                if (machine__resolve(machine, &al, &sample) < 0)
 102                        goto out;
 103
 104                if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack,
 105                                         NULL) < 0) {
 106                        addr_location__put(&al);
 107                        goto out;
 108                }
 109
 110                fake_samples[i].thread = al.thread;
 111                fake_samples[i].map = al.map;
 112                fake_samples[i].sym = al.sym;
 113        }
 114
 115        return TEST_OK;
 116
 117out:
 118        pr_debug("Not enough memory for adding a hist entry\n");
 119        return TEST_FAIL;
 120}
 121
 122static void del_hist_entries(struct hists *hists)
 123{
 124        struct hist_entry *he;
 125        struct rb_root *root_in;
 126        struct rb_root *root_out;
 127        struct rb_node *node;
 128
 129        if (hists__has(hists, need_collapse))
 130                root_in = &hists->entries_collapsed;
 131        else
 132                root_in = hists->entries_in;
 133
 134        root_out = &hists->entries;
 135
 136        while (!RB_EMPTY_ROOT(root_out)) {
 137                node = rb_first(root_out);
 138
 139                he = rb_entry(node, struct hist_entry, rb_node);
 140                rb_erase(node, root_out);
 141                rb_erase(&he->rb_node_in, root_in);
 142                hist_entry__delete(he);
 143        }
 144}
 145
 146typedef int (*test_fn_t)(struct perf_evsel *, struct machine *);
 147
 148#define COMM(he)  (thread__comm_str(he->thread))
 149#define DSO(he)   (he->ms.map->dso->short_name)
 150#define SYM(he)   (he->ms.sym->name)
 151#define CPU(he)   (he->cpu)
 152#define PID(he)   (he->thread->tid)
 153#define DEPTH(he) (he->callchain->max_depth)
 154#define CDSO(cl)  (cl->ms.map->dso->short_name)
 155#define CSYM(cl)  (cl->ms.sym->name)
 156
 157struct result {
 158        u64 children;
 159        u64 self;
 160        const char *comm;
 161        const char *dso;
 162        const char *sym;
 163};
 164
 165struct callchain_result {
 166        u64 nr;
 167        struct {
 168                const char *dso;
 169                const char *sym;
 170        } node[10];
 171};
 172
 173static int do_test(struct hists *hists, struct result *expected, size_t nr_expected,
 174                   struct callchain_result *expected_callchain, size_t nr_callchain)
 175{
 176        char buf[32];
 177        size_t i, c;
 178        struct hist_entry *he;
 179        struct rb_root *root;
 180        struct rb_node *node;
 181        struct callchain_node *cnode;
 182        struct callchain_list *clist;
 183
 184        /*
 185         * adding and deleting hist entries must be done outside of this
 186         * function since TEST_ASSERT_VAL() returns in case of failure.
 187         */
 188        hists__collapse_resort(hists, NULL);
 189        perf_evsel__output_resort(hists_to_evsel(hists), NULL);
 190
 191        if (verbose > 2) {
 192                pr_info("use callchain: %d, cumulate callchain: %d\n",
 193                        symbol_conf.use_callchain,
 194                        symbol_conf.cumulate_callchain);
 195                print_hists_out(hists);
 196        }
 197
 198        root = &hists->entries;
 199        for (node = rb_first(root), i = 0;
 200             node && (he = rb_entry(node, struct hist_entry, rb_node));
 201             node = rb_next(node), i++) {
 202                scnprintf(buf, sizeof(buf), "Invalid hist entry #%zd", i);
 203
 204                TEST_ASSERT_VAL("Incorrect number of hist entry",
 205                                i < nr_expected);
 206                TEST_ASSERT_VAL(buf, he->stat.period == expected[i].self &&
 207                                !strcmp(COMM(he), expected[i].comm) &&
 208                                !strcmp(DSO(he), expected[i].dso) &&
 209                                !strcmp(SYM(he), expected[i].sym));
 210
 211                if (symbol_conf.cumulate_callchain)
 212                        TEST_ASSERT_VAL(buf, he->stat_acc->period == expected[i].children);
 213
 214                if (!symbol_conf.use_callchain)
 215                        continue;
 216
 217                /* check callchain entries */
 218                root = &he->callchain->node.rb_root;
 219
 220                TEST_ASSERT_VAL("callchains expected", !RB_EMPTY_ROOT(root));
 221                cnode = rb_entry(rb_first(root), struct callchain_node, rb_node);
 222
 223                c = 0;
 224                list_for_each_entry(clist, &cnode->val, list) {
 225                        scnprintf(buf, sizeof(buf), "Invalid callchain entry #%zd/%zd", i, c);
 226
 227                        TEST_ASSERT_VAL("Incorrect number of callchain entry",
 228                                        c < expected_callchain[i].nr);
 229                        TEST_ASSERT_VAL(buf,
 230                                !strcmp(CDSO(clist), expected_callchain[i].node[c].dso) &&
 231                                !strcmp(CSYM(clist), expected_callchain[i].node[c].sym));
 232                        c++;
 233                }
 234                /* TODO: handle multiple child nodes properly */
 235                TEST_ASSERT_VAL("Incorrect number of callchain entry",
 236                                c <= expected_callchain[i].nr);
 237        }
 238        TEST_ASSERT_VAL("Incorrect number of hist entry",
 239                        i == nr_expected);
 240        TEST_ASSERT_VAL("Incorrect number of callchain entry",
 241                        !symbol_conf.use_callchain || nr_expected == nr_callchain);
 242        return 0;
 243}
 244
 245/* NO callchain + NO children */
 246static int test1(struct perf_evsel *evsel, struct machine *machine)
 247{
 248        int err;
 249        struct hists *hists = evsel__hists(evsel);
 250        /*
 251         * expected output:
 252         *
 253         * Overhead  Command  Shared Object          Symbol
 254         * ========  =======  =============  ==============
 255         *   20.00%     perf  perf           [.] main
 256         *   10.00%     bash  [kernel]       [k] page_fault
 257         *   10.00%     bash  bash           [.] main
 258         *   10.00%     bash  bash           [.] xmalloc
 259         *   10.00%     perf  [kernel]       [k] page_fault
 260         *   10.00%     perf  [kernel]       [k] schedule
 261         *   10.00%     perf  libc           [.] free
 262         *   10.00%     perf  libc           [.] malloc
 263         *   10.00%     perf  perf           [.] cmd_record
 264         */
 265        struct result expected[] = {
 266                { 0, 2000, "perf", "perf",     "main" },
 267                { 0, 1000, "bash", "[kernel]", "page_fault" },
 268                { 0, 1000, "bash", "bash",     "main" },
 269                { 0, 1000, "bash", "bash",     "xmalloc" },
 270                { 0, 1000, "perf", "[kernel]", "page_fault" },
 271                { 0, 1000, "perf", "[kernel]", "schedule" },
 272                { 0, 1000, "perf", "libc",     "free" },
 273                { 0, 1000, "perf", "libc",     "malloc" },
 274                { 0, 1000, "perf", "perf",     "cmd_record" },
 275        };
 276
 277        symbol_conf.use_callchain = false;
 278        symbol_conf.cumulate_callchain = false;
 279        perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
 280
 281        setup_sorting(NULL);
 282        callchain_register_param(&callchain_param);
 283
 284        err = add_hist_entries(hists, machine);
 285        if (err < 0)
 286                goto out;
 287
 288        err = do_test(hists, expected, ARRAY_SIZE(expected), NULL, 0);
 289
 290out:
 291        del_hist_entries(hists);
 292        reset_output_field();
 293        return err;
 294}
 295
 296/* callcain + NO children */
 297static int test2(struct perf_evsel *evsel, struct machine *machine)
 298{
 299        int err;
 300        struct hists *hists = evsel__hists(evsel);
 301        /*
 302         * expected output:
 303         *
 304         * Overhead  Command  Shared Object          Symbol
 305         * ========  =======  =============  ==============
 306         *   20.00%     perf  perf           [.] main
 307         *              |
 308         *              --- main
 309         *
 310         *   10.00%     bash  [kernel]       [k] page_fault
 311         *              |
 312         *              --- page_fault
 313         *                  malloc
 314         *                  main
 315         *
 316         *   10.00%     bash  bash           [.] main
 317         *              |
 318         *              --- main
 319         *
 320         *   10.00%     bash  bash           [.] xmalloc
 321         *              |
 322         *              --- xmalloc
 323         *                  malloc
 324         *                  xmalloc     <--- NOTE: there's a cycle
 325         *                  malloc
 326         *                  xmalloc
 327         *                  main
 328         *
 329         *   10.00%     perf  [kernel]       [k] page_fault
 330         *              |
 331         *              --- page_fault
 332         *                  sys_perf_event_open
 333         *                  run_command
 334         *                  main
 335         *
 336         *   10.00%     perf  [kernel]       [k] schedule
 337         *              |
 338         *              --- schedule
 339         *                  run_command
 340         *                  main
 341         *
 342         *   10.00%     perf  libc           [.] free
 343         *              |
 344         *              --- free
 345         *                  cmd_record
 346         *                  run_command
 347         *                  main
 348         *
 349         *   10.00%     perf  libc           [.] malloc
 350         *              |
 351         *              --- malloc
 352         *                  cmd_record
 353         *                  run_command
 354         *                  main
 355         *
 356         *   10.00%     perf  perf           [.] cmd_record
 357         *              |
 358         *              --- cmd_record
 359         *                  run_command
 360         *                  main
 361         *
 362         */
 363        struct result expected[] = {
 364                { 0, 2000, "perf", "perf",     "main" },
 365                { 0, 1000, "bash", "[kernel]", "page_fault" },
 366                { 0, 1000, "bash", "bash",     "main" },
 367                { 0, 1000, "bash", "bash",     "xmalloc" },
 368                { 0, 1000, "perf", "[kernel]", "page_fault" },
 369                { 0, 1000, "perf", "[kernel]", "schedule" },
 370                { 0, 1000, "perf", "libc",     "free" },
 371                { 0, 1000, "perf", "libc",     "malloc" },
 372                { 0, 1000, "perf", "perf",     "cmd_record" },
 373        };
 374        struct callchain_result expected_callchain[] = {
 375                {
 376                        1, {    { "perf",     "main" }, },
 377                },
 378                {
 379                        3, {    { "[kernel]", "page_fault" },
 380                                { "libc",     "malloc" },
 381                                { "bash",     "main" }, },
 382                },
 383                {
 384                        1, {    { "bash",     "main" }, },
 385                },
 386                {
 387                        6, {    { "bash",     "xmalloc" },
 388                                { "libc",     "malloc" },
 389                                { "bash",     "xmalloc" },
 390                                { "libc",     "malloc" },
 391                                { "bash",     "xmalloc" },
 392                                { "bash",     "main" }, },
 393                },
 394                {
 395                        4, {    { "[kernel]", "page_fault" },
 396                                { "[kernel]", "sys_perf_event_open" },
 397                                { "perf",     "run_command" },
 398                                { "perf",     "main" }, },
 399                },
 400                {
 401                        3, {    { "[kernel]", "schedule" },
 402                                { "perf",     "run_command" },
 403                                { "perf",     "main" }, },
 404                },
 405                {
 406                        4, {    { "libc",     "free" },
 407                                { "perf",     "cmd_record" },
 408                                { "perf",     "run_command" },
 409                                { "perf",     "main" }, },
 410                },
 411                {
 412                        4, {    { "libc",     "malloc" },
 413                                { "perf",     "cmd_record" },
 414                                { "perf",     "run_command" },
 415                                { "perf",     "main" }, },
 416                },
 417                {
 418                        3, {    { "perf",     "cmd_record" },
 419                                { "perf",     "run_command" },
 420                                { "perf",     "main" }, },
 421                },
 422        };
 423
 424        symbol_conf.use_callchain = true;
 425        symbol_conf.cumulate_callchain = false;
 426        perf_evsel__set_sample_bit(evsel, CALLCHAIN);
 427
 428        setup_sorting(NULL);
 429        callchain_register_param(&callchain_param);
 430
 431        err = add_hist_entries(hists, machine);
 432        if (err < 0)
 433                goto out;
 434
 435        err = do_test(hists, expected, ARRAY_SIZE(expected),
 436                      expected_callchain, ARRAY_SIZE(expected_callchain));
 437
 438out:
 439        del_hist_entries(hists);
 440        reset_output_field();
 441        return err;
 442}
 443
 444/* NO callchain + children */
 445static int test3(struct perf_evsel *evsel, struct machine *machine)
 446{
 447        int err;
 448        struct hists *hists = evsel__hists(evsel);
 449        /*
 450         * expected output:
 451         *
 452         * Children      Self  Command  Shared Object                   Symbol
 453         * ========  ========  =======  =============  =======================
 454         *   70.00%    20.00%     perf  perf           [.] main
 455         *   50.00%     0.00%     perf  perf           [.] run_command
 456         *   30.00%    10.00%     bash  bash           [.] main
 457         *   30.00%    10.00%     perf  perf           [.] cmd_record
 458         *   20.00%     0.00%     bash  libc           [.] malloc
 459         *   10.00%    10.00%     bash  [kernel]       [k] page_fault
 460         *   10.00%    10.00%     bash  bash           [.] xmalloc
 461         *   10.00%    10.00%     perf  [kernel]       [k] page_fault
 462         *   10.00%    10.00%     perf  libc           [.] malloc
 463         *   10.00%    10.00%     perf  [kernel]       [k] schedule
 464         *   10.00%    10.00%     perf  libc           [.] free
 465         *   10.00%     0.00%     perf  [kernel]       [k] sys_perf_event_open
 466         */
 467        struct result expected[] = {
 468                { 7000, 2000, "perf", "perf",     "main" },
 469                { 5000,    0, "perf", "perf",     "run_command" },
 470                { 3000, 1000, "bash", "bash",     "main" },
 471                { 3000, 1000, "perf", "perf",     "cmd_record" },
 472                { 2000,    0, "bash", "libc",     "malloc" },
 473                { 1000, 1000, "bash", "[kernel]", "page_fault" },
 474                { 1000, 1000, "bash", "bash",     "xmalloc" },
 475                { 1000, 1000, "perf", "[kernel]", "page_fault" },
 476                { 1000, 1000, "perf", "[kernel]", "schedule" },
 477                { 1000, 1000, "perf", "libc",     "free" },
 478                { 1000, 1000, "perf", "libc",     "malloc" },
 479                { 1000,    0, "perf", "[kernel]", "sys_perf_event_open" },
 480        };
 481
 482        symbol_conf.use_callchain = false;
 483        symbol_conf.cumulate_callchain = true;
 484        perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
 485
 486        setup_sorting(NULL);
 487        callchain_register_param(&callchain_param);
 488
 489        err = add_hist_entries(hists, machine);
 490        if (err < 0)
 491                goto out;
 492
 493        err = do_test(hists, expected, ARRAY_SIZE(expected), NULL, 0);
 494
 495out:
 496        del_hist_entries(hists);
 497        reset_output_field();
 498        return err;
 499}
 500
 501/* callchain + children */
 502static int test4(struct perf_evsel *evsel, struct machine *machine)
 503{
 504        int err;
 505        struct hists *hists = evsel__hists(evsel);
 506        /*
 507         * expected output:
 508         *
 509         * Children      Self  Command  Shared Object                   Symbol
 510         * ========  ========  =======  =============  =======================
 511         *   70.00%    20.00%     perf  perf           [.] main
 512         *              |
 513         *              --- main
 514         *
 515         *   50.00%     0.00%     perf  perf           [.] run_command
 516         *              |
 517         *              --- run_command
 518         *                  main
 519         *
 520         *   30.00%    10.00%     bash  bash           [.] main
 521         *              |
 522         *              --- main
 523         *
 524         *   30.00%    10.00%     perf  perf           [.] cmd_record
 525         *              |
 526         *              --- cmd_record
 527         *                  run_command
 528         *                  main
 529         *
 530         *   20.00%     0.00%     bash  libc           [.] malloc
 531         *              |
 532         *              --- malloc
 533         *                 |
 534         *                 |--50.00%-- xmalloc
 535         *                 |           main
 536         *                  --50.00%-- main
 537         *
 538         *   10.00%    10.00%     bash  [kernel]       [k] page_fault
 539         *              |
 540         *              --- page_fault
 541         *                  malloc
 542         *                  main
 543         *
 544         *   10.00%    10.00%     bash  bash           [.] xmalloc
 545         *              |
 546         *              --- xmalloc
 547         *                  malloc
 548         *                  xmalloc     <--- NOTE: there's a cycle
 549         *                  malloc
 550         *                  xmalloc
 551         *                  main
 552         *
 553         *   10.00%     0.00%     perf  [kernel]       [k] sys_perf_event_open
 554         *              |
 555         *              --- sys_perf_event_open
 556         *                  run_command
 557         *                  main
 558         *
 559         *   10.00%    10.00%     perf  [kernel]       [k] page_fault
 560         *              |
 561         *              --- page_fault
 562         *                  sys_perf_event_open
 563         *                  run_command
 564         *                  main
 565         *
 566         *   10.00%    10.00%     perf  [kernel]       [k] schedule
 567         *              |
 568         *              --- schedule
 569         *                  run_command
 570         *                  main
 571         *
 572         *   10.00%    10.00%     perf  libc           [.] free
 573         *              |
 574         *              --- free
 575         *                  cmd_record
 576         *                  run_command
 577         *                  main
 578         *
 579         *   10.00%    10.00%     perf  libc           [.] malloc
 580         *              |
 581         *              --- malloc
 582         *                  cmd_record
 583         *                  run_command
 584         *                  main
 585         *
 586         */
 587        struct result expected[] = {
 588                { 7000, 2000, "perf", "perf",     "main" },
 589                { 5000,    0, "perf", "perf",     "run_command" },
 590                { 3000, 1000, "bash", "bash",     "main" },
 591                { 3000, 1000, "perf", "perf",     "cmd_record" },
 592                { 2000,    0, "bash", "libc",     "malloc" },
 593                { 1000, 1000, "bash", "[kernel]", "page_fault" },
 594                { 1000, 1000, "bash", "bash",     "xmalloc" },
 595                { 1000,    0, "perf", "[kernel]", "sys_perf_event_open" },
 596                { 1000, 1000, "perf", "[kernel]", "page_fault" },
 597                { 1000, 1000, "perf", "[kernel]", "schedule" },
 598                { 1000, 1000, "perf", "libc",     "free" },
 599                { 1000, 1000, "perf", "libc",     "malloc" },
 600        };
 601        struct callchain_result expected_callchain[] = {
 602                {
 603                        1, {    { "perf",     "main" }, },
 604                },
 605                {
 606                        2, {    { "perf",     "run_command" },
 607                                { "perf",     "main" }, },
 608                },
 609                {
 610                        1, {    { "bash",     "main" }, },
 611                },
 612                {
 613                        3, {    { "perf",     "cmd_record" },
 614                                { "perf",     "run_command" },
 615                                { "perf",     "main" }, },
 616                },
 617                {
 618                        4, {    { "libc",     "malloc" },
 619                                { "bash",     "xmalloc" },
 620                                { "bash",     "main" },
 621                                { "bash",     "main" }, },
 622                },
 623                {
 624                        3, {    { "[kernel]", "page_fault" },
 625                                { "libc",     "malloc" },
 626                                { "bash",     "main" }, },
 627                },
 628                {
 629                        6, {    { "bash",     "xmalloc" },
 630                                { "libc",     "malloc" },
 631                                { "bash",     "xmalloc" },
 632                                { "libc",     "malloc" },
 633                                { "bash",     "xmalloc" },
 634                                { "bash",     "main" }, },
 635                },
 636                {
 637                        3, {    { "[kernel]", "sys_perf_event_open" },
 638                                { "perf",     "run_command" },
 639                                { "perf",     "main" }, },
 640                },
 641                {
 642                        4, {    { "[kernel]", "page_fault" },
 643                                { "[kernel]", "sys_perf_event_open" },
 644                                { "perf",     "run_command" },
 645                                { "perf",     "main" }, },
 646                },
 647                {
 648                        3, {    { "[kernel]", "schedule" },
 649                                { "perf",     "run_command" },
 650                                { "perf",     "main" }, },
 651                },
 652                {
 653                        4, {    { "libc",     "free" },
 654                                { "perf",     "cmd_record" },
 655                                { "perf",     "run_command" },
 656                                { "perf",     "main" }, },
 657                },
 658                {
 659                        4, {    { "libc",     "malloc" },
 660                                { "perf",     "cmd_record" },
 661                                { "perf",     "run_command" },
 662                                { "perf",     "main" }, },
 663                },
 664        };
 665
 666        symbol_conf.use_callchain = true;
 667        symbol_conf.cumulate_callchain = true;
 668        perf_evsel__set_sample_bit(evsel, CALLCHAIN);
 669
 670        setup_sorting(NULL);
 671
 672        callchain_param = callchain_param_default;
 673        callchain_register_param(&callchain_param);
 674
 675        err = add_hist_entries(hists, machine);
 676        if (err < 0)
 677                goto out;
 678
 679        err = do_test(hists, expected, ARRAY_SIZE(expected),
 680                      expected_callchain, ARRAY_SIZE(expected_callchain));
 681
 682out:
 683        del_hist_entries(hists);
 684        reset_output_field();
 685        return err;
 686}
 687
 688int test__hists_cumulate(int subtest __maybe_unused)
 689{
 690        int err = TEST_FAIL;
 691        struct machines machines;
 692        struct machine *machine;
 693        struct perf_evsel *evsel;
 694        struct perf_evlist *evlist = perf_evlist__new();
 695        size_t i;
 696        test_fn_t testcases[] = {
 697                test1,
 698                test2,
 699                test3,
 700                test4,
 701        };
 702
 703        TEST_ASSERT_VAL("No memory", evlist);
 704
 705        err = parse_events(evlist, "cpu-clock", NULL);
 706        if (err)
 707                goto out;
 708        err = TEST_FAIL;
 709
 710        machines__init(&machines);
 711
 712        /* setup threads/dso/map/symbols also */
 713        machine = setup_fake_machine(&machines);
 714        if (!machine)
 715                goto out;
 716
 717        if (verbose > 1)
 718                machine__fprintf(machine, stderr);
 719
 720        evsel = perf_evlist__first(evlist);
 721
 722        for (i = 0; i < ARRAY_SIZE(testcases); i++) {
 723                err = testcases[i](evsel, machine);
 724                if (err < 0)
 725                        break;
 726        }
 727
 728out:
 729        /* tear down everything */
 730        perf_evlist__delete(evlist);
 731        machines__exit(&machines);
 732
 733        return err;
 734}
 735