1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/trace_processor/importers/common/process_tracker.h"
18
19 #include <optional>
20
21 #include "perfetto/base/logging.h"
22 #include "src/trace_processor/importers/common/args_tracker.h"
23 #include "src/trace_processor/importers/common/event_tracker.h"
24 #include "test/gtest_and_gmock.h"
25
26 namespace perfetto {
27 namespace trace_processor {
28 namespace {
29
30 using ::testing::_;
31 using ::testing::InSequence;
32 using ::testing::Invoke;
33
34 class ProcessTrackerTest : public ::testing::Test {
35 public:
ProcessTrackerTest()36 ProcessTrackerTest() {
37 context.storage.reset(new TraceStorage());
38 context.global_args_tracker.reset(
39 new GlobalArgsTracker(context.storage.get()));
40 context.args_tracker.reset(new ArgsTracker(&context));
41 context.process_tracker.reset(new ProcessTracker(&context));
42 context.event_tracker.reset(new EventTracker(&context));
43 }
44
45 protected:
46 TraceProcessorContext context;
47 };
48
TEST_F(ProcessTrackerTest,PushProcess)49 TEST_F(ProcessTrackerTest, PushProcess) {
50 context.process_tracker->SetProcessMetadata(1, std::nullopt, "test",
51 base::StringView());
52 auto opt_upid = context.process_tracker->UpidForPidForTesting(1);
53 ASSERT_EQ(opt_upid.value_or(-1), 1u);
54 }
55
TEST_F(ProcessTrackerTest,GetOrCreateNewProcess)56 TEST_F(ProcessTrackerTest, GetOrCreateNewProcess) {
57 auto upid = context.process_tracker->GetOrCreateProcess(123);
58 ASSERT_EQ(context.process_tracker->GetOrCreateProcess(123), upid);
59 }
60
TEST_F(ProcessTrackerTest,StartNewProcess)61 TEST_F(ProcessTrackerTest, StartNewProcess) {
62 auto upid = context.process_tracker->StartNewProcess(
63 1000, 0u, 123, kNullStringId, ThreadNamePriority::kFtrace);
64 ASSERT_EQ(context.process_tracker->GetOrCreateProcess(123), upid);
65 ASSERT_EQ(context.storage->process_table().start_ts()[upid], 1000);
66 }
67
TEST_F(ProcessTrackerTest,PushTwoProcessEntries_SamePidAndName)68 TEST_F(ProcessTrackerTest, PushTwoProcessEntries_SamePidAndName) {
69 context.process_tracker->SetProcessMetadata(1, std::nullopt, "test",
70 base::StringView());
71 context.process_tracker->SetProcessMetadata(1, std::nullopt, "test",
72 base::StringView());
73 auto opt_upid = context.process_tracker->UpidForPidForTesting(1);
74 ASSERT_EQ(opt_upid.value_or(-1), 1u);
75 }
76
TEST_F(ProcessTrackerTest,PushTwoProcessEntries_DifferentPid)77 TEST_F(ProcessTrackerTest, PushTwoProcessEntries_DifferentPid) {
78 context.process_tracker->SetProcessMetadata(1, std::nullopt, "test",
79 base::StringView());
80 context.process_tracker->SetProcessMetadata(3, std::nullopt, "test",
81 base::StringView());
82 auto opt_upid = context.process_tracker->UpidForPidForTesting(1);
83 ASSERT_EQ(opt_upid.value_or(-1), 1u);
84 opt_upid = context.process_tracker->UpidForPidForTesting(3);
85 ASSERT_EQ(opt_upid.value_or(-1), 2u);
86 }
87
TEST_F(ProcessTrackerTest,AddProcessEntry_CorrectName)88 TEST_F(ProcessTrackerTest, AddProcessEntry_CorrectName) {
89 context.process_tracker->SetProcessMetadata(1, std::nullopt, "test",
90 base::StringView());
91 auto name = context.storage->process_table().name().GetString(1);
92
93 ASSERT_EQ(name, "test");
94 }
95
TEST_F(ProcessTrackerTest,UpdateThreadCreate)96 TEST_F(ProcessTrackerTest, UpdateThreadCreate) {
97 context.process_tracker->UpdateThread(12, 2);
98
99 // We expect 3 threads: Invalid thread, main thread for pid, tid 12.
100 ASSERT_EQ(context.storage->thread_table().row_count(), 3u);
101
102 auto tid_it = context.process_tracker->UtidsForTidForTesting(12);
103 ASSERT_NE(tid_it.first, tid_it.second);
104 ASSERT_EQ(context.storage->thread_table().upid()[1].value(), 1u);
105 auto opt_upid = context.process_tracker->UpidForPidForTesting(2);
106 ASSERT_TRUE(opt_upid.has_value());
107 ASSERT_EQ(context.storage->process_table().row_count(), 2u);
108 }
109
TEST_F(ProcessTrackerTest,PidReuseWithoutStartAndEndThread)110 TEST_F(ProcessTrackerTest, PidReuseWithoutStartAndEndThread) {
111 UniquePid p1 = context.process_tracker->StartNewProcess(
112 std::nullopt, std::nullopt, /*pid=*/1, kNullStringId,
113 ThreadNamePriority::kFtrace);
114 UniqueTid t1 = context.process_tracker->UpdateThread(/*tid=*/2, /*pid=*/1);
115
116 UniquePid p2 = context.process_tracker->StartNewProcess(
117 std::nullopt, std::nullopt, /*pid=*/1, kNullStringId,
118 ThreadNamePriority::kFtrace);
119 UniqueTid t2 = context.process_tracker->UpdateThread(/*tid=*/2, /*pid=*/1);
120
121 ASSERT_NE(p1, p2);
122 ASSERT_NE(t1, t2);
123
124 // We expect 3 processes: idle process, 2x pid 1.
125 ASSERT_EQ(context.storage->process_table().row_count(), 3u);
126 // We expect 5 threads: Invalid thread, 2x (main thread + sub thread).
127 ASSERT_EQ(context.storage->thread_table().row_count(), 5u);
128 }
129
TEST_F(ProcessTrackerTest,Cmdline)130 TEST_F(ProcessTrackerTest, Cmdline) {
131 UniquePid upid = context.process_tracker->SetProcessMetadata(
132 1, std::nullopt, "test", "cmdline blah");
133 ASSERT_EQ(context.storage->process_table().cmdline().GetString(upid),
134 "cmdline blah");
135 }
136
TEST_F(ProcessTrackerTest,UpdateThreadName)137 TEST_F(ProcessTrackerTest, UpdateThreadName) {
138 auto name1 = context.storage->InternString("name1");
139 auto name2 = context.storage->InternString("name2");
140 auto name3 = context.storage->InternString("name3");
141
142 context.process_tracker->UpdateThreadName(1, name1,
143 ThreadNamePriority::kFtrace);
144 ASSERT_EQ(context.storage->thread_table().row_count(), 2u);
145 ASSERT_EQ(context.storage->thread_table().name()[1], name1);
146
147 context.process_tracker->UpdateThreadName(1, name2,
148 ThreadNamePriority::kProcessTree);
149 // The priority is higher: the name should change.
150 ASSERT_EQ(context.storage->thread_table().row_count(), 2u);
151 ASSERT_EQ(context.storage->thread_table().name()[1], name2);
152
153 context.process_tracker->UpdateThreadName(1, name3,
154 ThreadNamePriority::kFtrace);
155 // The priority is lower: the name should stay the same.
156 ASSERT_EQ(context.storage->thread_table().row_count(), 2u);
157 ASSERT_EQ(context.storage->thread_table().name()[1], name2);
158 }
159
TEST_F(ProcessTrackerTest,SetStartTsIfUnset)160 TEST_F(ProcessTrackerTest, SetStartTsIfUnset) {
161 auto upid = context.process_tracker->StartNewProcess(
162 /*timestamp=*/std::nullopt, 0u, 123, kNullStringId,
163 ThreadNamePriority::kFtrace);
164 context.process_tracker->SetStartTsIfUnset(upid, 1000);
165 ASSERT_EQ(context.storage->process_table().start_ts()[upid], 1000);
166
167 context.process_tracker->SetStartTsIfUnset(upid, 3000);
168 ASSERT_EQ(context.storage->process_table().start_ts()[upid], 1000);
169 }
170
TEST_F(ProcessTrackerTest,PidReuseAfterExplicitEnd)171 TEST_F(ProcessTrackerTest, PidReuseAfterExplicitEnd) {
172 UniquePid upid = context.process_tracker->GetOrCreateProcess(123);
173 context.process_tracker->EndThread(100, 123);
174
175 UniquePid reuse = context.process_tracker->GetOrCreateProcess(123);
176 ASSERT_NE(upid, reuse);
177 }
178
TEST_F(ProcessTrackerTest,TidReuseAfterExplicitEnd)179 TEST_F(ProcessTrackerTest, TidReuseAfterExplicitEnd) {
180 UniqueTid utid = context.process_tracker->UpdateThread(123, 123);
181 context.process_tracker->EndThread(100, 123);
182
183 UniqueTid reuse = context.process_tracker->UpdateThread(123, 123);
184 ASSERT_NE(utid, reuse);
185
186 UniqueTid reuse_again = context.process_tracker->UpdateThread(123, 123);
187 ASSERT_EQ(reuse, reuse_again);
188 }
189
TEST_F(ProcessTrackerTest,EndThreadAfterProcessEnd)190 TEST_F(ProcessTrackerTest, EndThreadAfterProcessEnd) {
191 context.process_tracker->StartNewProcess(
192 100, std::nullopt, 123, kNullStringId, ThreadNamePriority::kFtrace);
193 context.process_tracker->UpdateThread(124, 123);
194
195 context.process_tracker->EndThread(200, 123);
196 context.process_tracker->EndThread(201, 124);
197
198 // We expect two processes: the idle process and 123.
199 ASSERT_EQ(context.storage->process_table().row_count(), 2u);
200
201 // We expect three theads: the idle thread, 123 and 124.
202 ASSERT_EQ(context.storage->thread_table().row_count(), 3u);
203 }
204
TEST_F(ProcessTrackerTest,UpdateTrustedPid)205 TEST_F(ProcessTrackerTest, UpdateTrustedPid) {
206 context.process_tracker->UpdateTrustedPid(/*trusted_pid=*/123, /*uuid=*/1001);
207 context.process_tracker->UpdateTrustedPid(/*trusted_pid=*/456, /*uuid=*/1002);
208
209 ASSERT_EQ(context.process_tracker->GetTrustedPid(1001).value(), 123u);
210 ASSERT_EQ(context.process_tracker->GetTrustedPid(1002).value(), 456u);
211
212 // PID reuse. Multiple track UUIDs map to the same trusted_pid.
213 context.process_tracker->UpdateTrustedPid(/*trusted_pid=*/123, /*uuid=*/1003);
214 ASSERT_EQ(context.process_tracker->GetTrustedPid(1001).value(), 123u);
215 ASSERT_EQ(context.process_tracker->GetTrustedPid(1003).value(), 123u);
216 }
217
TEST_F(ProcessTrackerTest,NamespacedProcessesAndThreads)218 TEST_F(ProcessTrackerTest, NamespacedProcessesAndThreads) {
219 context.process_tracker->UpdateNamespacedProcess(/*pid=*/1001,
220 /*nspid=*/{1001, 190, 1});
221 context.process_tracker->UpdateNamespacedThread(/*pid=*/1001, /*tid=*/1002,
222 /*nstid=*/{1002, 192, 2});
223 context.process_tracker->UpdateNamespacedThread(1001, 1003, {1003, 193, 3});
224
225 context.process_tracker->UpdateNamespacedProcess(/*pid=*/1023,
226 /*nspid=*/{1023, 201, 21});
227 context.process_tracker->UpdateNamespacedThread(/*pid=*/1023, /*tid=*/1026,
228 {1026, 196, 26});
229 context.process_tracker->UpdateNamespacedThread(/*pid=*/1023, /*tid=*/1027,
230 {1027, 197, 27});
231
232 context.process_tracker->UpdateNamespacedProcess(/*pid=*/1024,
233 /*nspid=*/{1024, 202, 22});
234 context.process_tracker->UpdateNamespacedThread(/*pid=*/1024, /*tid=*/1028,
235 /*nstid=*/{1028, 198, 28});
236 context.process_tracker->UpdateNamespacedThread(/*pid=*/1024, /*tid=*/1029,
237 /*nstid=*/{1029, 198, 29});
238
239 // Don't resolve if the process/thread isn't namespaced.
240 ASSERT_EQ(context.process_tracker->ResolveNamespacedTid(2001, 2002),
241 std::nullopt);
242
243 // Resolve from namespace-local PID to root-level PID.
244 ASSERT_EQ(context.process_tracker->ResolveNamespacedTid(1001, 1).value(),
245 1001u);
246 ASSERT_EQ(context.process_tracker->ResolveNamespacedTid(1023, 21).value(),
247 1023u);
248 ASSERT_EQ(context.process_tracker->ResolveNamespacedTid(1024, 22).value(),
249 1024u);
250
251 // Resolve from namespace-local TID to root-level TID.
252 ASSERT_EQ(context.process_tracker->ResolveNamespacedTid(1001, 2).value(),
253 1002u);
254 ASSERT_EQ(context.process_tracker->ResolveNamespacedTid(1001, 3).value(),
255 1003u);
256 ASSERT_EQ(context.process_tracker->ResolveNamespacedTid(1023, 26).value(),
257 1026u);
258 ASSERT_EQ(context.process_tracker->ResolveNamespacedTid(1023, 27).value(),
259 1027u);
260 ASSERT_EQ(context.process_tracker->ResolveNamespacedTid(1024, 28).value(),
261 1028u);
262 ASSERT_EQ(context.process_tracker->ResolveNamespacedTid(1024, 29).value(),
263 1029u);
264 }
265
266 } // namespace
267 } // namespace trace_processor
268 } // namespace perfetto
269