This source file includes following definitions.
- add_hist_entries
- del_hist_entries
- test1
- test2
- test3
- test4
- test5
- test__hists_output
   1 
   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 
  17 struct 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 
  27 static struct sample fake_samples[] = {
  28         
  29         { .cpu = 0, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, },
  30         
  31         { .cpu = 1, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, },
  32         
  33         { .cpu = 1, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_CMD_RECORD, },
  34         
  35         { .cpu = 1, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, },
  36         
  37         { .cpu = 2, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_FREE, },
  38         
  39         { .cpu = 2, .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, },
  40         
  41         { .cpu = 2, .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
  42         
  43         { .cpu = 3, .pid = FAKE_PID_BASH,  .ip = FAKE_IP_BASH_MAIN, },
  44         
  45         { .cpu = 0, .pid = FAKE_PID_BASH,  .ip = FAKE_IP_BASH_XMALLOC, },
  46         
  47         { .cpu = 1, .pid = FAKE_PID_BASH,  .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
  48 };
  49 
  50 static 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 
  87 out:
  88         pr_debug("Not enough memory for adding a hist entry\n");
  89         return TEST_FAIL;
  90 }
  91 
  92 static 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 
 116 typedef 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 
 125 static 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; 
 135 
 136         setup_sorting(NULL);
 137 
 138         
 139 
 140 
 141 
 142 
 143 
 144 
 145 
 146 
 147 
 148 
 149 
 150 
 151 
 152 
 153         err = add_hist_entries(hists, machine);
 154         if (err < 0)
 155                 goto out;
 156 
 157         hists__collapse_resort(hists, NULL);
 158         perf_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 
 220 out:
 221         del_hist_entries(hists);
 222         reset_output_field();
 223         return err;
 224 }
 225 
 226 
 227 static 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 
 242 
 243 
 244 
 245 
 246 
 247 
 248 
 249 
 250 
 251 
 252 
 253         err = add_hist_entries(hists, machine);
 254         if (err < 0)
 255                 goto out;
 256 
 257         hists__collapse_resort(hists, NULL);
 258         perf_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 
 276 out:
 277         del_hist_entries(hists);
 278         reset_output_field();
 279         return err;
 280 }
 281 
 282 
 283 static 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 
 298 
 299 
 300 
 301 
 302 
 303 
 304 
 305 
 306 
 307         err = add_hist_entries(hists, machine);
 308         if (err < 0)
 309                 goto out;
 310 
 311         hists__collapse_resort(hists, NULL);
 312         perf_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 
 350 out:
 351         del_hist_entries(hists);
 352         reset_output_field();
 353         return err;
 354 }
 355 
 356 
 357 static 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 
 372 
 373 
 374 
 375 
 376 
 377 
 378 
 379 
 380 
 381 
 382 
 383 
 384 
 385         err = add_hist_entries(hists, machine);
 386         if (err < 0)
 387                 goto out;
 388 
 389         hists__collapse_resort(hists, NULL);
 390         perf_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 
 452 out:
 453         del_hist_entries(hists);
 454         reset_output_field();
 455         return err;
 456 }
 457 
 458 
 459 static 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 
 474 
 475 
 476 
 477 
 478 
 479 
 480 
 481 
 482 
 483 
 484 
 485 
 486 
 487 
 488         err = add_hist_entries(hists, machine);
 489         if (err < 0)
 490                 goto out;
 491 
 492         hists__collapse_resort(hists, NULL);
 493         perf_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 
 572 out:
 573         del_hist_entries(hists);
 574         reset_output_field();
 575         return err;
 576 }
 577 
 578 int 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         
 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 
 619 out:
 620         
 621         evlist__delete(evlist);
 622         machines__exit(&machines);
 623 
 624         return err;
 625 }