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