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/process_tracker.h"
18
19 #include "perfetto/base/logging.h"
20 #include "src/trace_processor/args_tracker.h"
21 #include "src/trace_processor/event_tracker.h"
22 #include "src/trace_processor/importers/ftrace/sched_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 TraceStorage storage;
49 context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
50 auto pair_it = context.process_tracker->UpidsForPidForTesting(1);
51 ASSERT_EQ(pair_it.first->second, 1u);
52 }
53
TEST_F(ProcessTrackerTest,GetOrCreateNewProcess)54 TEST_F(ProcessTrackerTest, GetOrCreateNewProcess) {
55 TraceStorage storage;
56 auto upid = context.process_tracker->GetOrCreateProcess(123);
57 ASSERT_EQ(context.process_tracker->GetOrCreateProcess(123), upid);
58 }
59
TEST_F(ProcessTrackerTest,StartNewProcess)60 TEST_F(ProcessTrackerTest, StartNewProcess) {
61 TraceStorage storage;
62 auto upid =
63 context.process_tracker->StartNewProcess(1000, 0u, 123, kNullStringId);
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, base::nullopt, "test");
70 context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
71 auto pair_it = context.process_tracker->UpidsForPidForTesting(1);
72 ASSERT_EQ(pair_it.first->second, 1u);
73 ASSERT_EQ(++pair_it.first, pair_it.second);
74 }
75
TEST_F(ProcessTrackerTest,PushTwoProcessEntries_DifferentPid)76 TEST_F(ProcessTrackerTest, PushTwoProcessEntries_DifferentPid) {
77 context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
78 context.process_tracker->SetProcessMetadata(3, base::nullopt, "test");
79 auto pair_it = context.process_tracker->UpidsForPidForTesting(1);
80 ASSERT_EQ(pair_it.first->second, 1u);
81 auto second_pair_it = context.process_tracker->UpidsForPidForTesting(3);
82 ASSERT_EQ(second_pair_it.first->second, 2u);
83 }
84
TEST_F(ProcessTrackerTest,AddProcessEntry_CorrectName)85 TEST_F(ProcessTrackerTest, AddProcessEntry_CorrectName) {
86 context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
87 auto name =
88 context.storage->GetString(context.storage->process_table().name()[1]);
89 ASSERT_EQ(name, "test");
90 }
91
TEST_F(ProcessTrackerTest,UpdateThreadMatch)92 TEST_F(ProcessTrackerTest, UpdateThreadMatch) {
93 uint32_t cpu = 3;
94 int64_t timestamp = 100;
95 int64_t prev_state = 32;
96 static const char kCommProc1[] = "process1";
97 static const char kCommProc2[] = "process2";
98 int32_t prio = 1024;
99 SchedEventTracker* sched_tracker = SchedEventTracker::GetOrCreate(&context);
100
101 sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, kCommProc2, prio,
102 prev_state,
103 /*tid=*/4, kCommProc1, prio);
104 sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4, kCommProc1,
105 prio, prev_state,
106 /*tid=*/1, kCommProc2, prio);
107
108 context.process_tracker->SetProcessMetadata(2, base::nullopt, "test");
109 context.process_tracker->UpdateThread(4, 2);
110
111 ASSERT_EQ(context.storage->thread_table().tid()[1], 4u);
112 ASSERT_EQ(context.storage->thread_table().upid()[1].value(), 1u);
113 ASSERT_EQ(context.storage->process_table().pid()[1], 2u);
114 ASSERT_EQ(context.storage->process_table().start_ts()[1], base::nullopt);
115 }
116
TEST_F(ProcessTrackerTest,UpdateThreadCreate)117 TEST_F(ProcessTrackerTest, UpdateThreadCreate) {
118 context.process_tracker->UpdateThread(12, 2);
119
120 // We expect 3 threads: Invalid thread, main thread for pid, tid 12.
121 ASSERT_EQ(context.storage->thread_table().row_count(), 3u);
122
123 auto tid_it = context.process_tracker->UtidsForTidForTesting(12);
124 ASSERT_NE(tid_it.first, tid_it.second);
125 ASSERT_EQ(context.storage->thread_table().upid()[1].value(), 1u);
126 auto pid_it = context.process_tracker->UpidsForPidForTesting(2);
127 ASSERT_NE(pid_it.first, pid_it.second);
128 ASSERT_EQ(context.storage->process_table().row_count(), 2u);
129 }
130
TEST_F(ProcessTrackerTest,PidReuseWithoutStartAndEndThread)131 TEST_F(ProcessTrackerTest, PidReuseWithoutStartAndEndThread) {
132 UniquePid p1 = context.process_tracker->StartNewProcess(
133 base::nullopt, base::nullopt, /*pid=*/1, kNullStringId);
134 UniqueTid t1 = context.process_tracker->UpdateThread(/*tid=*/2, /*pid=*/1);
135
136 UniquePid p2 = context.process_tracker->StartNewProcess(
137 base::nullopt, base::nullopt, /*pid=*/1, kNullStringId);
138 UniqueTid t2 = context.process_tracker->UpdateThread(/*tid=*/2, /*pid=*/1);
139
140 ASSERT_NE(p1, p2);
141 ASSERT_NE(t1, t2);
142
143 // We expect 3 processes: idle process, 2x pid 1.
144 ASSERT_EQ(context.storage->process_table().row_count(), 3u);
145 // We expect 5 threads: Invalid thread, 2x (main thread + sub thread).
146 ASSERT_EQ(context.storage->thread_table().row_count(), 5u);
147 }
148
149 } // namespace
150 } // namespace trace_processor
151 } // namespace perfetto
152