1 /*
2 * Copyright (C) 2020 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/ftrace/sched_event_tracker.h"
18
19 #include "perfetto/base/logging.h"
20 #include "src/trace_processor/importers/common/args_tracker.h"
21 #include "src/trace_processor/importers/common/event_tracker.h"
22 #include "src/trace_processor/importers/common/process_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 SchedEventTrackerTest : public ::testing::Test {
34 public:
SchedEventTrackerTest()35 SchedEventTrackerTest() {
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.event_tracker.reset(new EventTracker(&context));
40 context.process_tracker.reset(new ProcessTracker(&context));
41 sched_tracker = SchedEventTracker::GetOrCreate(&context);
42 }
43
44 protected:
45 TraceProcessorContext context;
46 SchedEventTracker* sched_tracker;
47 };
48
TEST_F(SchedEventTrackerTest,InsertSecondSched)49 TEST_F(SchedEventTrackerTest, InsertSecondSched) {
50 uint32_t cpu = 3;
51 int64_t timestamp = 100;
52 uint32_t pid_1 = 2;
53 int64_t prev_state = 32;
54 static const char kCommProc1[] = "process1";
55 static const char kCommProc2[] = "process2";
56 uint32_t pid_2 = 4;
57 int32_t prio = 1024;
58
59 sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, kCommProc2, prio,
60 prev_state, pid_2, kCommProc1, prio);
61 ASSERT_EQ(context.storage->sched_slice_table().row_count(), 1ul);
62
63 sched_tracker->PushSchedSwitch(cpu, timestamp + 1, pid_2, kCommProc1, prio,
64 prev_state, pid_1, kCommProc2, prio);
65
66 ASSERT_EQ(context.storage->sched_slice_table().row_count(), 2ul);
67
68 const auto& timestamps = context.storage->sched_slice_table().ts();
69 ASSERT_EQ(timestamps[0], timestamp);
70 ASSERT_EQ(context.storage->thread_table().start_ts()[1], base::nullopt);
71
72 auto name =
73 context.storage->GetString(context.storage->thread_table().name()[1]);
74 ASSERT_STREQ(name.c_str(), kCommProc1);
75 ASSERT_EQ(context.storage->sched_slice_table().utid()[0], 1u);
76 ASSERT_EQ(context.storage->sched_slice_table().dur()[0], 1);
77 }
78
TEST_F(SchedEventTrackerTest,InsertThirdSched_SameThread)79 TEST_F(SchedEventTrackerTest, InsertThirdSched_SameThread) {
80 uint32_t cpu = 3;
81 int64_t timestamp = 100;
82 int64_t prev_state = 32;
83 static const char kCommProc1[] = "process1";
84 static const char kCommProc2[] = "process2";
85 int32_t prio = 1024;
86
87 sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/4, kCommProc2, prio,
88 prev_state,
89 /*tid=*/2, kCommProc1, prio);
90 ASSERT_EQ(context.storage->sched_slice_table().row_count(), 1u);
91
92 sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/2, kCommProc1,
93 prio, prev_state,
94 /*tid=*/4, kCommProc2, prio);
95 sched_tracker->PushSchedSwitch(cpu, timestamp + 11, /*tid=*/4, kCommProc2,
96 prio, prev_state,
97 /*tid=*/2, kCommProc1, prio);
98 sched_tracker->PushSchedSwitch(cpu, timestamp + 31, /*tid=*/2, kCommProc1,
99 prio, prev_state,
100 /*tid=*/4, kCommProc2, prio);
101 ASSERT_EQ(context.storage->sched_slice_table().row_count(), 4ul);
102
103 const auto& timestamps = context.storage->sched_slice_table().ts();
104 ASSERT_EQ(timestamps[0], timestamp);
105 ASSERT_EQ(context.storage->thread_table().start_ts()[1], base::nullopt);
106 ASSERT_EQ(context.storage->sched_slice_table().dur()[0], 1u);
107 ASSERT_EQ(context.storage->sched_slice_table().dur()[1], 11u - 1u);
108 ASSERT_EQ(context.storage->sched_slice_table().dur()[2], 31u - 11u);
109 ASSERT_EQ(context.storage->sched_slice_table().utid()[0],
110 context.storage->sched_slice_table().utid()[2]);
111 }
112
TEST_F(SchedEventTrackerTest,UpdateThreadMatch)113 TEST_F(SchedEventTrackerTest, UpdateThreadMatch) {
114 uint32_t cpu = 3;
115 int64_t timestamp = 100;
116 int64_t prev_state = 32;
117 static const char kCommProc1[] = "process1";
118 static const char kCommProc2[] = "process2";
119 int32_t prio = 1024;
120
121 sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, kCommProc2, prio,
122 prev_state,
123 /*tid=*/4, kCommProc1, prio);
124 sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4, kCommProc1,
125 prio, prev_state,
126 /*tid=*/1, kCommProc2, prio);
127
128 context.process_tracker->SetProcessMetadata(2, base::nullopt, "test",
129 base::StringView());
130 context.process_tracker->UpdateThread(4, 2);
131
132 ASSERT_EQ(context.storage->thread_table().tid()[1], 4u);
133 ASSERT_EQ(context.storage->thread_table().upid()[1].value(), 1u);
134 ASSERT_EQ(context.storage->process_table().pid()[1], 2u);
135 ASSERT_EQ(context.storage->process_table().start_ts()[1], base::nullopt);
136 }
137
138 } // namespace
139 } // namespace trace_processor
140 } // namespace perfetto
141