aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/Makefile.perf1
-rw-r--r--tools/perf/tests/builtin-test.c4
-rw-r--r--tools/perf/tests/hists_common.c4
-rw-r--r--tools/perf/tests/hists_filter.c1
-rw-r--r--tools/perf/tests/hists_link.c1
-rw-r--r--tools/perf/tests/hists_output.c618
-rw-r--r--tools/perf/tests/tests.h1
7 files changed, 628 insertions, 2 deletions
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index dea2d633c374..02f0a4dd1a80 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -399,6 +399,7 @@ LIB_OBJS += $(OUTPUT)tests/pmu.o
399LIB_OBJS += $(OUTPUT)tests/hists_common.o 399LIB_OBJS += $(OUTPUT)tests/hists_common.o
400LIB_OBJS += $(OUTPUT)tests/hists_link.o 400LIB_OBJS += $(OUTPUT)tests/hists_link.o
401LIB_OBJS += $(OUTPUT)tests/hists_filter.o 401LIB_OBJS += $(OUTPUT)tests/hists_filter.o
402LIB_OBJS += $(OUTPUT)tests/hists_output.o
402LIB_OBJS += $(OUTPUT)tests/python-use.o 403LIB_OBJS += $(OUTPUT)tests/python-use.o
403LIB_OBJS += $(OUTPUT)tests/bp_signal.o 404LIB_OBJS += $(OUTPUT)tests/bp_signal.o
404LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o 405LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 5e0764b09317..831f52cae197 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -136,6 +136,10 @@ static struct test {
136 .func = test__thread_mg_share, 136 .func = test__thread_mg_share,
137 }, 137 },
138 { 138 {
139 .desc = "Test output sorting of hist entries",
140 .func = test__hists_output,
141 },
142 {
139 .func = NULL, 143 .func = NULL,
140 }, 144 },
141}; 145};
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c
index 040a85b17aee..e4e01aadc3be 100644
--- a/tools/perf/tests/hists_common.c
+++ b/tools/perf/tests/hists_common.c
@@ -193,8 +193,8 @@ void print_hists_out(struct hists *hists)
193 he = rb_entry(node, struct hist_entry, rb_node); 193 he = rb_entry(node, struct hist_entry, rb_node);
194 194
195 if (!he->filtered) { 195 if (!he->filtered) {
196 pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n", 196 pr_info("%2d: entry: %8s:%5d [%-8s] %20s: period = %"PRIu64"\n",
197 i, thread__comm_str(he->thread), 197 i, thread__comm_str(he->thread), he->thread->tid,
198 he->ms.map->dso->short_name, 198 he->ms.map->dso->short_name,
199 he->ms.sym->name, he->stat.period); 199 he->ms.sym->name, he->stat.period);
200 } 200 }
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 13c8cf49225e..c5ba924a3581 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -283,6 +283,7 @@ int test__hists_filter(void)
283out: 283out:
284 /* tear down everything */ 284 /* tear down everything */
285 perf_evlist__delete(evlist); 285 perf_evlist__delete(evlist);
286 reset_output_field();
286 machines__exit(&machines); 287 machines__exit(&machines);
287 288
288 return err; 289 return err;
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 4e783db60bba..5ffa2c3eb77d 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -332,6 +332,7 @@ int test__hists_link(void)
332out: 332out:
333 /* tear down everything */ 333 /* tear down everything */
334 perf_evlist__delete(evlist); 334 perf_evlist__delete(evlist);
335 reset_output_field();
335 machines__exit(&machines); 336 machines__exit(&machines);
336 337
337 return err; 338 return err;
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
new file mode 100644
index 000000000000..a16850551797
--- /dev/null
+++ b/tools/perf/tests/hists_output.c
@@ -0,0 +1,618 @@
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 cpu;
15 u32 pid;
16 u64 ip;
17 struct thread *thread;
18 struct map *map;
19 struct symbol *sym;
20};
21
22/* For the numbers, see hists_common.c */
23static struct sample fake_samples[] = {
24 /* perf [kernel] schedule() */
25 { .cpu = 0, .pid = 100, .ip = 0xf0000 + 700, },
26 /* perf [perf] main() */
27 { .cpu = 1, .pid = 100, .ip = 0x40000 + 700, },
28 /* perf [perf] cmd_record() */
29 { .cpu = 1, .pid = 100, .ip = 0x40000 + 900, },
30 /* perf [libc] malloc() */
31 { .cpu = 1, .pid = 100, .ip = 0x50000 + 700, },
32 /* perf [libc] free() */
33 { .cpu = 2, .pid = 100, .ip = 0x50000 + 800, },
34 /* perf [perf] main() */
35 { .cpu = 2, .pid = 200, .ip = 0x40000 + 700, },
36 /* perf [kernel] page_fault() */
37 { .cpu = 2, .pid = 200, .ip = 0xf0000 + 800, },
38 /* bash [bash] main() */
39 { .cpu = 3, .pid = 300, .ip = 0x40000 + 700, },
40 /* bash [bash] xmalloc() */
41 { .cpu = 0, .pid = 300, .ip = 0x40000 + 800, },
42 /* bash [kernel] page_fault() */
43 { .cpu = 1, .pid = 300, .ip = 0xf0000 + 800, },
44};
45
46static int add_hist_entries(struct hists *hists, struct machine *machine)
47{
48 struct addr_location al;
49 struct hist_entry *he;
50 struct perf_sample sample = { .period = 100, };
51 size_t i;
52
53 for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
54 const union perf_event event = {
55 .header = {
56 .misc = PERF_RECORD_MISC_USER,
57 },
58 };
59
60 sample.cpu = fake_samples[i].cpu;
61 sample.pid = fake_samples[i].pid;
62 sample.tid = fake_samples[i].pid;
63 sample.ip = fake_samples[i].ip;
64
65 if (perf_event__preprocess_sample(&event, machine, &al,
66 &sample) < 0)
67 goto out;
68
69 he = __hists__add_entry(hists, &al, NULL, NULL, NULL,
70 sample.period, 1, 0);
71 if (he == NULL)
72 goto out;
73
74 fake_samples[i].thread = al.thread;
75 fake_samples[i].map = al.map;
76 fake_samples[i].sym = al.sym;
77 }
78
79 return TEST_OK;
80
81out:
82 pr_debug("Not enough memory for adding a hist entry\n");
83 return TEST_FAIL;
84}
85
86static void del_hist_entries(struct hists *hists)
87{
88 struct hist_entry *he;
89 struct rb_root *root_in;
90 struct rb_root *root_out;
91 struct rb_node *node;
92
93 if (sort__need_collapse)
94 root_in = &hists->entries_collapsed;
95 else
96 root_in = hists->entries_in;
97
98 root_out = &hists->entries;
99
100 while (!RB_EMPTY_ROOT(root_out)) {
101 node = rb_first(root_out);
102
103 he = rb_entry(node, struct hist_entry, rb_node);
104 rb_erase(node, root_out);
105 rb_erase(&he->rb_node_in, root_in);
106 hist_entry__free(he);
107 }
108}
109
110typedef int (*test_fn_t)(struct perf_evsel *, struct machine *);
111
112#define COMM(he) (thread__comm_str(he->thread))
113#define DSO(he) (he->ms.map->dso->short_name)
114#define SYM(he) (he->ms.sym->name)
115#define CPU(he) (he->cpu)
116#define PID(he) (he->thread->tid)
117
118/* default sort keys (no field) */
119static int test1(struct perf_evsel *evsel, struct machine *machine)
120{
121 i