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