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