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