1
2 /*
3 * Copyright (C) 2024 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include "src/trace_redaction/collect_timeline_events.h"
19 #include "protos/perfetto/trace/ftrace/sched.gen.h"
20 #include "src/base/test/status_matchers.h"
21 #include "src/trace_redaction/trace_redaction_framework.h"
22
23 #include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
24 #include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
25 #include "protos/perfetto/trace/ftrace/task.gen.h"
26 #include "protos/perfetto/trace/ps/process_tree.gen.h"
27 #include "protos/perfetto/trace/trace_packet.gen.h"
28
29 namespace perfetto::trace_redaction {
30
31 namespace {
32
33 constexpr uint64_t kPackage = 0;
34 constexpr int32_t kPid = 1093;
35
36 constexpr uint64_t kFullStep = 1000;
37 constexpr uint64_t kTimeA = 0;
38 constexpr uint64_t kTimeB = kFullStep;
39 constexpr uint64_t kTimeC = kFullStep * 2;
40
41 } // namespace
42
43 // Base class for all collect timeline event tests. Creates a simple trace that
44 // contains trace elements that should create timeline events.
45 class CollectTimelineEventsTest : public testing::Test {
46 protected:
SetUp()47 void SetUp() { ASSERT_OK(collector_.Begin(&context_)); }
48
49 Context context_;
50 CollectTimelineEvents collector_;
51 };
52
TEST_F(CollectTimelineEventsTest,OpenEventForProcessTreeProcess)53 TEST_F(CollectTimelineEventsTest, OpenEventForProcessTreeProcess) {
54 {
55 protos::gen::TracePacket packet;
56 packet.set_timestamp(kTimeA);
57
58 auto* process_tree = packet.mutable_process_tree();
59
60 auto* process = process_tree->add_processes();
61 process->set_pid(kPid);
62 process->set_ppid(1);
63 process->set_uid(kPackage);
64
65 auto buffer = packet.SerializeAsString();
66
67 protos::pbzero::TracePacket::Decoder decoder(buffer);
68
69 ASSERT_OK(collector_.Collect(decoder, &context_));
70 }
71
72 ASSERT_OK(collector_.End(&context_));
73
74 const auto* event = context_.timeline->GetOpeningEvent(kTimeA, kPid);
75 ASSERT_TRUE(event);
76 ASSERT_TRUE(event->valid());
77 }
78
TEST_F(CollectTimelineEventsTest,OpenEventForProcessTreeThread)79 TEST_F(CollectTimelineEventsTest, OpenEventForProcessTreeThread) {
80 {
81 protos::gen::TracePacket packet;
82 packet.set_timestamp(kTimeA);
83
84 auto* process_tree = packet.mutable_process_tree();
85
86 auto* process = process_tree->add_threads();
87 process->set_tid(kPid);
88 process->set_tgid(1);
89
90 auto buffer = packet.SerializeAsString();
91
92 protos::pbzero::TracePacket::Decoder decoder(buffer);
93
94 ASSERT_OK(collector_.Collect(decoder, &context_));
95 }
96
97 ASSERT_OK(collector_.End(&context_));
98
99 const auto* event = context_.timeline->GetOpeningEvent(kTimeA, kPid);
100 ASSERT_TRUE(event);
101 ASSERT_TRUE(event->valid());
102 }
103
TEST_F(CollectTimelineEventsTest,OpenEventForNewTask)104 TEST_F(CollectTimelineEventsTest, OpenEventForNewTask) {
105 {
106 protos::gen::TracePacket packet;
107 auto* event = packet.mutable_ftrace_events()->add_event();
108 event->set_timestamp(kTimeA);
109
110 auto* new_task = event->mutable_task_newtask();
111 new_task->set_clone_flags(0);
112 new_task->set_comm("");
113 new_task->set_oom_score_adj(0);
114 new_task->set_pid(kPid);
115
116 auto buffer = packet.SerializeAsString();
117
118 protos::pbzero::TracePacket::Decoder decoder(buffer);
119
120 ASSERT_OK(collector_.Collect(decoder, &context_));
121 }
122
123 ASSERT_OK(collector_.End(&context_));
124
125 const auto* open_event = context_.timeline->GetOpeningEvent(kTimeA, kPid);
126 ASSERT_TRUE(open_event);
127 ASSERT_TRUE(open_event->valid());
128 }
129
TEST_F(CollectTimelineEventsTest,ProcFreeEndsThread)130 TEST_F(CollectTimelineEventsTest, ProcFreeEndsThread) {
131 {
132 protos::gen::TracePacket packet;
133
134 auto* event = packet.mutable_ftrace_events()->add_event();
135 event->set_timestamp(kTimeA);
136
137 auto* new_task = event->mutable_task_newtask();
138 new_task->set_clone_flags(0);
139 new_task->set_comm("");
140 new_task->set_oom_score_adj(0);
141 new_task->set_pid(kPid);
142
143 auto buffer = packet.SerializeAsString();
144
145 protos::pbzero::TracePacket::Decoder decoder(buffer);
146 ASSERT_OK(collector_.Collect(decoder, &context_));
147 }
148
149 {
150 protos::gen::TracePacket packet;
151
152 auto* event = packet.mutable_ftrace_events()->add_event();
153 event->set_timestamp(kTimeB);
154
155 auto* process_free = event->mutable_sched_process_free();
156 process_free->set_comm("");
157 process_free->set_pid(kPid);
158 process_free->set_prio(0);
159
160 auto buffer = packet.SerializeAsString();
161
162 protos::pbzero::TracePacket::Decoder decoder(buffer);
163 ASSERT_OK(collector_.Collect(decoder, &context_));
164 }
165
166 ASSERT_OK(collector_.End(&context_));
167
168 const auto* start = context_.timeline->GetOpeningEvent(kTimeA, kPid);
169 ASSERT_TRUE(start);
170 ASSERT_TRUE(start->valid());
171
172 // The end event was correctly set so that the free event is inclusive.
173 const auto* end = context_.timeline->GetOpeningEvent(kTimeB, kPid);
174 ASSERT_TRUE(end);
175 ASSERT_TRUE(end->valid());
176
177 const auto* after = context_.timeline->GetOpeningEvent(kTimeC, kPid);
178 ASSERT_FALSE(after);
179 }
180
181 } // namespace perfetto::trace_redaction
182