1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <stdlib.h> |
3 | #include <string.h> |
4 | #include <sys/types.h> |
5 | #include <unistd.h> |
6 | #include <sys/prctl.h> |
7 | #include "tests.h" |
8 | #include "thread_map.h" |
9 | #include "debug.h" |
10 | #include "event.h" |
11 | #include "util/synthetic-events.h" |
12 | #include <linux/zalloc.h> |
13 | #include <perf/event.h> |
14 | #include <internal/threadmap.h> |
15 | |
16 | struct perf_sample; |
17 | struct perf_tool; |
18 | struct machine; |
19 | |
20 | #define NAME (const char *) "perf" |
21 | #define NAMEUL (unsigned long) NAME |
22 | |
23 | static int test__thread_map(struct test_suite *test __maybe_unused, int subtest __maybe_unused) |
24 | { |
25 | struct perf_thread_map *map; |
26 | |
27 | TEST_ASSERT_VAL("failed to set process name" , |
28 | !prctl(PR_SET_NAME, NAMEUL, 0, 0, 0)); |
29 | |
30 | /* test map on current pid */ |
31 | map = thread_map__new_by_pid(getpid()); |
32 | TEST_ASSERT_VAL("failed to alloc map" , map); |
33 | |
34 | thread_map__read_comms(map); |
35 | |
36 | TEST_ASSERT_VAL("wrong nr" , map->nr == 1); |
37 | TEST_ASSERT_VAL("wrong pid" , |
38 | perf_thread_map__pid(map, 0) == getpid()); |
39 | TEST_ASSERT_VAL("wrong comm" , |
40 | perf_thread_map__comm(map, 0) && |
41 | !strcmp(perf_thread_map__comm(map, 0), NAME)); |
42 | TEST_ASSERT_VAL("wrong refcnt" , |
43 | refcount_read(&map->refcnt) == 1); |
44 | perf_thread_map__put(map); |
45 | |
46 | /* test dummy pid */ |
47 | map = perf_thread_map__new_dummy(); |
48 | TEST_ASSERT_VAL("failed to alloc map" , map); |
49 | |
50 | thread_map__read_comms(map); |
51 | |
52 | TEST_ASSERT_VAL("wrong nr" , map->nr == 1); |
53 | TEST_ASSERT_VAL("wrong pid" , perf_thread_map__pid(map, 0) == -1); |
54 | TEST_ASSERT_VAL("wrong comm" , |
55 | perf_thread_map__comm(map, 0) && |
56 | !strcmp(perf_thread_map__comm(map, 0), "dummy" )); |
57 | TEST_ASSERT_VAL("wrong refcnt" , |
58 | refcount_read(&map->refcnt) == 1); |
59 | perf_thread_map__put(map); |
60 | return 0; |
61 | } |
62 | |
63 | static int process_event(struct perf_tool *tool __maybe_unused, |
64 | union perf_event *event, |
65 | struct perf_sample *sample __maybe_unused, |
66 | struct machine *machine __maybe_unused) |
67 | { |
68 | struct perf_record_thread_map *map = &event->thread_map; |
69 | struct perf_thread_map *threads; |
70 | |
71 | TEST_ASSERT_VAL("wrong nr" , map->nr == 1); |
72 | TEST_ASSERT_VAL("wrong pid" , map->entries[0].pid == (u64) getpid()); |
73 | TEST_ASSERT_VAL("wrong comm" , !strcmp(map->entries[0].comm, NAME)); |
74 | |
75 | threads = thread_map__new_event(&event->thread_map); |
76 | TEST_ASSERT_VAL("failed to alloc map" , threads); |
77 | |
78 | TEST_ASSERT_VAL("wrong nr" , threads->nr == 1); |
79 | TEST_ASSERT_VAL("wrong pid" , |
80 | perf_thread_map__pid(threads, 0) == getpid()); |
81 | TEST_ASSERT_VAL("wrong comm" , |
82 | perf_thread_map__comm(threads, 0) && |
83 | !strcmp(perf_thread_map__comm(threads, 0), NAME)); |
84 | TEST_ASSERT_VAL("wrong refcnt" , |
85 | refcount_read(&threads->refcnt) == 1); |
86 | perf_thread_map__put(threads); |
87 | return 0; |
88 | } |
89 | |
90 | static int test__thread_map_synthesize(struct test_suite *test __maybe_unused, int subtest __maybe_unused) |
91 | { |
92 | struct perf_thread_map *threads; |
93 | |
94 | TEST_ASSERT_VAL("failed to set process name" , |
95 | !prctl(PR_SET_NAME, NAMEUL, 0, 0, 0)); |
96 | |
97 | /* test map on current pid */ |
98 | threads = thread_map__new_by_pid(getpid()); |
99 | TEST_ASSERT_VAL("failed to alloc map" , threads); |
100 | |
101 | thread_map__read_comms(threads); |
102 | |
103 | TEST_ASSERT_VAL("failed to synthesize map" , |
104 | !perf_event__synthesize_thread_map2(NULL, threads, process_event, NULL)); |
105 | |
106 | perf_thread_map__put(threads); |
107 | return 0; |
108 | } |
109 | |
110 | static int test__thread_map_remove(struct test_suite *test __maybe_unused, int subtest __maybe_unused) |
111 | { |
112 | struct perf_thread_map *threads; |
113 | char *str; |
114 | |
115 | TEST_ASSERT_VAL("failed to allocate map string" , |
116 | asprintf(&str, "%d,%d" , getpid(), getppid()) >= 0); |
117 | |
118 | threads = thread_map__new_str(str, NULL, 0, false); |
119 | free(str); |
120 | |
121 | TEST_ASSERT_VAL("failed to allocate thread_map" , |
122 | threads); |
123 | |
124 | if (verbose > 0) |
125 | thread_map__fprintf(threads, stderr); |
126 | |
127 | TEST_ASSERT_VAL("failed to remove thread" , |
128 | !thread_map__remove(threads, 0)); |
129 | |
130 | TEST_ASSERT_VAL("thread_map count != 1" , threads->nr == 1); |
131 | |
132 | if (verbose > 0) |
133 | thread_map__fprintf(threads, stderr); |
134 | |
135 | TEST_ASSERT_VAL("failed to remove thread" , |
136 | !thread_map__remove(threads, 0)); |
137 | |
138 | TEST_ASSERT_VAL("thread_map count != 0" , threads->nr == 0); |
139 | |
140 | if (verbose > 0) |
141 | thread_map__fprintf(threads, stderr); |
142 | |
143 | TEST_ASSERT_VAL("failed to not remove thread" , |
144 | thread_map__remove(threads, 0)); |
145 | |
146 | perf_thread_map__put(threads); |
147 | return 0; |
148 | } |
149 | |
150 | DEFINE_SUITE("Thread map" , thread_map); |
151 | DEFINE_SUITE("Synthesize thread map" , thread_map_synthesize); |
152 | DEFINE_SUITE("Remove thread map" , thread_map_remove); |
153 | |