xref: /aosp_15_r20/external/perfetto/src/trace_redaction/redact_process_events_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2024 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_redaction/redact_process_events.h"
18 #include "src/base/test/status_matchers.h"
19 #include "test/gtest_and_gmock.h"
20 
21 #include "protos/perfetto/trace/ftrace/ftrace.gen.h"
22 #include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
23 #include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
24 #include "protos/perfetto/trace/ftrace/power.gen.h"
25 #include "protos/perfetto/trace/ftrace/sched.gen.h"
26 #include "protos/perfetto/trace/ftrace/task.gen.h"
27 #include "protos/perfetto/trace/trace.gen.h"
28 #include "protos/perfetto/trace/trace_packet.gen.h"
29 
30 namespace perfetto::trace_redaction {
31 
32 namespace {
33 constexpr uint64_t kCpu = 1;
34 
35 constexpr uint64_t kUidA = 1;
36 constexpr uint64_t kUidB = 2;
37 
38 constexpr int32_t kNoParent = 10;
39 constexpr int32_t kPidA = 11;
40 constexpr int32_t kPidB = 12;
41 
42 // Used as a child of kPidA.
43 constexpr int32_t kPidAA = kPidA * 10;
44 
45 constexpr uint64_t kTimeA = 0;
46 constexpr uint64_t kTimeB = 1000;
47 
48 constexpr std::string_view kCommA = "comm-a";
49 constexpr std::string_view kCommB = "comm-b";
50 }  // namespace
51 
52 class RedactProcessEventsTest : public testing::Test {
53  protected:
SetUp()54   void SetUp() {
55     redact_.emplace_modifier<DoNothing>();
56     redact_.emplace_filter<AllowAll>();
57   }
58 
59   RedactProcessEvents redact_;
60 };
61 
TEST_F(RedactProcessEventsTest,RejectMissingPackageUid)62 TEST_F(RedactProcessEventsTest, RejectMissingPackageUid) {
63   Context context;
64   context.timeline = std::make_unique<ProcessThreadTimeline>();
65 
66   protos::gen::TracePacket packet;
67   auto packet_str = packet.SerializeAsString();
68 
69   ASSERT_FALSE(redact_.Transform(context, &packet_str).ok());
70 }
71 
TEST_F(RedactProcessEventsTest,RejectMissingTimeline)72 TEST_F(RedactProcessEventsTest, RejectMissingTimeline) {
73   Context context;
74   context.package_uid = kUidA;
75 
76   protos::gen::TracePacket packet;
77   auto packet_str = packet.SerializeAsString();
78 
79   ASSERT_FALSE(redact_.Transform(context, &packet_str).ok());
80 }
81 
TEST_F(RedactProcessEventsTest,RejectMissingPacket)82 TEST_F(RedactProcessEventsTest, RejectMissingPacket) {
83   Context context;
84   context.package_uid = kUidA;
85   context.timeline = std::make_unique<ProcessThreadTimeline>();
86 
87   ASSERT_FALSE(redact_.Transform(context, nullptr).ok());
88 }
89 
TEST_F(RedactProcessEventsTest,EmptyMissingPacket)90 TEST_F(RedactProcessEventsTest, EmptyMissingPacket) {
91   Context context;
92   context.package_uid = kUidA;
93   context.timeline = std::make_unique<ProcessThreadTimeline>();
94 
95   std::string packet_str;
96 
97   ASSERT_FALSE(redact_.Transform(context, &packet_str).ok());
98 }
99 
100 // Tests which nested messages and fields are removed.
101 class RedactNewTaskTest : public testing::Test {
102  protected:
SetUp()103   void SetUp() override {
104     auto* events = packet_.mutable_ftrace_events();
105     events->set_cpu(kCpu);
106 
107     auto* event = events->add_event();
108     event->set_timestamp(kTimeB);
109     event->set_pid(kPidA);
110 
111     auto* new_task = event->mutable_task_newtask();
112     new_task->set_clone_flags(0);
113     new_task->set_comm(std::string(kCommA));
114     new_task->set_oom_score_adj(0);
115     new_task->set_pid(kPidA);
116 
117     // This test breaks the rules for task_newtask and the timeline. The
118     // timeline will report the task existing before the new task event. This
119     // should not happen in the field, but it makes the test more robust.
120 
121     context_.timeline = std::make_unique<ProcessThreadTimeline>();
122 
123     context_.timeline->Append(
124         ProcessThreadTimeline::Event::Open(kTimeA, kPidA, kNoParent, kUidA));
125     context_.timeline->Append(
126         ProcessThreadTimeline::Event::Open(kTimeA, kPidB, kNoParent, kUidB));
127     context_.timeline->Sort();
128 
129     redact_.emplace_modifier<DoNothing>();
130     redact_.emplace_filter<AllowAll>();
131   }
132 
133   RedactProcessEvents redact_;
134   protos::gen::TracePacket packet_;
135   Context context_;
136 };
137 
TEST_F(RedactNewTaskTest,KeepCommInPackage)138 TEST_F(RedactNewTaskTest, KeepCommInPackage) {
139   redact_.emplace_modifier<ClearComms>();
140 
141   // The new task is for Pid A. Pid A is part of Uid A. Keep Uid A; keep new
142   // task.
143   context_.package_uid = kUidA;
144 
145   auto packet_str = packet_.SerializeAsString();
146   ASSERT_OK(redact_.Transform(context_, &packet_str));
147 
148   protos::gen::TracePacket packet;
149   ASSERT_TRUE(packet.ParseFromString(packet_str));
150 
151   ASSERT_TRUE(packet.has_ftrace_events());
152   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
153 
154   const auto& event = packet.ftrace_events().event().at(0);
155   ASSERT_TRUE(event.has_task_newtask());
156 
157   const auto& new_task = event.task_newtask();
158 
159   ASSERT_TRUE(new_task.has_pid());
160   ASSERT_EQ(new_task.pid(), kPidA);
161 
162   ASSERT_TRUE(new_task.has_comm());
163   ASSERT_EQ(new_task.comm(), kCommA);
164 }
165 
TEST_F(RedactNewTaskTest,ClearCommOutsidePackage)166 TEST_F(RedactNewTaskTest, ClearCommOutsidePackage) {
167   redact_.emplace_modifier<ClearComms>();
168 
169   // The new task is for Pid A. Pid A is part of Uid A. Keep Uid B; clear the
170   // comm.
171   context_.package_uid = kUidB;
172 
173   auto packet_str = packet_.SerializeAsString();
174   ASSERT_OK(redact_.Transform(context_, &packet_str));
175 
176   protos::gen::TracePacket packet;
177   ASSERT_TRUE(packet.ParseFromString(packet_str));
178 
179   ASSERT_TRUE(packet.has_ftrace_events());
180   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
181 
182   const auto& event = packet.ftrace_events().event().at(0);
183   ASSERT_TRUE(event.has_task_newtask());
184 
185   const auto& new_task = event.task_newtask();
186 
187   ASSERT_TRUE(new_task.has_pid());
188   ASSERT_EQ(new_task.pid(), kPidA);
189 
190   ASSERT_TRUE(new_task.has_comm());
191   ASSERT_TRUE(new_task.comm().empty());
192 }
193 
TEST_F(RedactNewTaskTest,KeepTaskInPackage)194 TEST_F(RedactNewTaskTest, KeepTaskInPackage) {
195   redact_.emplace_filter<ConnectedToPackage>();
196 
197   // The new task is for Pid A. Pid A is part of Uid A. Keep Uid A; keep new
198   // task.
199   context_.package_uid = kUidA;
200 
201   auto packet_str = packet_.SerializeAsString();
202   ASSERT_OK(redact_.Transform(context_, &packet_str));
203 
204   protos::gen::TracePacket packet;
205   ASSERT_TRUE(packet.ParseFromString(packet_str));
206 
207   ASSERT_TRUE(packet.has_ftrace_events());
208   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
209 
210   const auto& event = packet.ftrace_events().event().at(0);
211   ASSERT_TRUE(event.has_task_newtask());
212 
213   const auto& new_task = event.task_newtask();
214 
215   ASSERT_TRUE(new_task.has_pid());
216   ASSERT_EQ(new_task.pid(), kPidA);
217 }
218 
TEST_F(RedactNewTaskTest,DropTaskOutsidePackage)219 TEST_F(RedactNewTaskTest, DropTaskOutsidePackage) {
220   redact_.emplace_filter<ConnectedToPackage>();
221 
222   // The new task is for Pid A. Pid A is part of Uid A. Keep Uid B; drop new
223   // task event.
224   context_.package_uid = kUidB;
225 
226   auto packet_str = packet_.SerializeAsString();
227   ASSERT_OK(redact_.Transform(context_, &packet_str));
228 
229   protos::gen::TracePacket packet;
230   ASSERT_TRUE(packet.ParseFromString(packet_str));
231 
232   ASSERT_TRUE(packet.has_ftrace_events());
233   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
234 
235   // The task should have been removed, but the event will still remain.
236   ASSERT_FALSE(packet.ftrace_events().event().at(0).has_task_newtask());
237 }
238 
239 class RedactProcessFree : public testing::Test {
240  protected:
SetUp()241   void SetUp() override {
242     auto* events = packet_.mutable_ftrace_events();
243     events->set_cpu(kCpu);
244 
245     auto* event = events->add_event();
246     event->set_timestamp(kTimeB);
247     event->set_pid(kPidA);
248 
249     auto* process_free = event->mutable_sched_process_free();
250     process_free->set_comm(std::string(kCommA));
251     process_free->set_pid(kPidA);
252     process_free->set_prio(0);
253 
254     // By default, this timeline is invalid. sched_process_free would insert
255     // close events. If sched_process_free appended at time B a close event
256     // would be created at time B.
257     //
258     // Timeline spans are inclusive-start but exclusive-end, so a
259     // sched_process_free will never pass a "connected to package" test. The
260     // timeline is created to make testing easier.
261     //
262     // If a test wants a "valid" timeline, it should add a close event at
263     // sched_process_free.
264 
265     context_.timeline = std::make_unique<ProcessThreadTimeline>();
266 
267     context_.timeline->Append(
268         ProcessThreadTimeline::Event::Open(kTimeA, kPidA, kNoParent, kUidA));
269     context_.timeline->Append(
270         ProcessThreadTimeline::Event::Open(kTimeA, kPidB, kNoParent, kUidB));
271     context_.timeline->Sort();
272 
273     redact_.emplace_modifier<DoNothing>();
274     redact_.emplace_filter<AllowAll>();
275   }
276 
277   RedactProcessEvents redact_;
278   protos::gen::TracePacket packet_;
279   Context context_;
280 };
281 
TEST_F(RedactProcessFree,KeepsCommInPackage)282 TEST_F(RedactProcessFree, KeepsCommInPackage) {
283   redact_.emplace_modifier<ClearComms>();
284 
285   // The new task is for Pid A. Pid A is part of Uid A. Keep Uid A; keep comm.
286   context_.package_uid = kUidA;
287 
288   auto packet_str = packet_.SerializeAsString();
289   ASSERT_OK(redact_.Transform(context_, &packet_str));
290 
291   protos::gen::TracePacket packet;
292   ASSERT_TRUE(packet.ParseFromString(packet_str));
293 
294   ASSERT_TRUE(packet.has_ftrace_events());
295   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
296 
297   const auto& event = packet.ftrace_events().event().at(0);
298   ASSERT_TRUE(event.has_sched_process_free());
299 
300   const auto& process_free = event.sched_process_free();
301 
302   ASSERT_TRUE(process_free.has_pid());
303   ASSERT_EQ(process_free.pid(), kPidA);
304 
305   ASSERT_TRUE(process_free.has_comm());
306   ASSERT_EQ(process_free.comm(), kCommA);
307 }
308 
TEST_F(RedactProcessFree,DropsCommOutsidePackage)309 TEST_F(RedactProcessFree, DropsCommOutsidePackage) {
310   redact_.emplace_modifier<ClearComms>();
311 
312   // The new task is for Pid A. Pid A is part of Uid A. Keep Uid B; drop comm.
313   context_.package_uid = kUidB;
314 
315   auto packet_str = packet_.SerializeAsString();
316   ASSERT_OK(redact_.Transform(context_, &packet_str));
317 
318   protos::gen::TracePacket packet;
319   ASSERT_TRUE(packet.ParseFromString(packet_str));
320 
321   ASSERT_TRUE(packet.has_ftrace_events());
322   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
323 
324   const auto& event = packet.ftrace_events().event().at(0);
325   ASSERT_TRUE(event.has_sched_process_free());
326 
327   const auto& process_free = event.sched_process_free();
328 
329   ASSERT_TRUE(process_free.has_pid());
330   ASSERT_EQ(process_free.pid(), kPidA);
331 
332   ASSERT_TRUE(process_free.has_comm());
333   ASSERT_TRUE(process_free.comm().empty());
334 }
335 
TEST_F(RedactProcessFree,KeepsCommAtProcessFree)336 TEST_F(RedactProcessFree, KeepsCommAtProcessFree) {
337   redact_.emplace_modifier<ClearComms>();
338 
339   // The new task is for Pid A. Pid A is part of Uid A. Keep Uid A; Process free
340   // marks the end of Pid A, but process free is inclusive and Pid A is only
341   // free after the event.
342   context_.package_uid = kUidA;
343 
344   context_.timeline->Append(ProcessThreadTimeline::Event::Close(kTimeB, kPidA));
345   context_.timeline->Sort();
346 
347   auto packet_str = packet_.SerializeAsString();
348   ASSERT_OK(redact_.Transform(context_, &packet_str));
349 
350   protos::gen::TracePacket packet;
351   ASSERT_TRUE(packet.ParseFromString(packet_str));
352 
353   ASSERT_TRUE(packet.has_ftrace_events());
354   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
355 
356   const auto& event = packet.ftrace_events().event().at(0);
357   ASSERT_TRUE(event.has_sched_process_free());
358 
359   const auto& process_free = event.sched_process_free();
360 
361   ASSERT_TRUE(process_free.has_pid());
362   ASSERT_EQ(process_free.pid(), kPidA);
363 
364   ASSERT_TRUE(process_free.has_comm());
365   ASSERT_EQ(process_free.comm(), kCommA);
366 }
367 
TEST_F(RedactProcessFree,KeepTaskInPackage)368 TEST_F(RedactProcessFree, KeepTaskInPackage) {
369   redact_.emplace_filter<ConnectedToPackage>();
370 
371   // The new task is for Pid A. Pid A is part of Uid A. Keep Uid A; keep new
372   // task.
373   context_.package_uid = kUidA;
374 
375   auto packet_str = packet_.SerializeAsString();
376   ASSERT_OK(redact_.Transform(context_, &packet_str));
377 
378   protos::gen::TracePacket packet;
379   ASSERT_TRUE(packet.ParseFromString(packet_str));
380 
381   ASSERT_TRUE(packet.has_ftrace_events());
382   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
383 
384   const auto& event = packet.ftrace_events().event().at(0);
385   ASSERT_TRUE(event.has_sched_process_free());
386 
387   const auto& process_free = event.sched_process_free();
388 
389   ASSERT_TRUE(process_free.has_pid());
390   ASSERT_EQ(process_free.pid(), kPidA);
391 }
392 
TEST_F(RedactProcessFree,DropTaskOutsidePackage)393 TEST_F(RedactProcessFree, DropTaskOutsidePackage) {
394   redact_.emplace_filter<ConnectedToPackage>();
395 
396   // The new task is for Pid A. Pid A is part of Uid A. Keep Uid B; drop new
397   // task event.
398   context_.package_uid = kUidB;
399 
400   auto packet_str = packet_.SerializeAsString();
401   ASSERT_OK(redact_.Transform(context_, &packet_str));
402 
403   protos::gen::TracePacket packet;
404   ASSERT_TRUE(packet.ParseFromString(packet_str));
405 
406   ASSERT_TRUE(packet.has_ftrace_events());
407   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
408 
409   // The task should have been removed, but the event will still remain.
410   ASSERT_FALSE(packet.ftrace_events().event().at(0).has_sched_process_free());
411 }
412 
413 class RedactRenameTest : public testing::Test {
414  protected:
SetUp()415   void SetUp() {
416     auto* events = packet_.mutable_ftrace_events();
417     events->set_cpu(kCpu);
418 
419     auto* event = events->add_event();
420     event->set_timestamp(kTimeB);
421     event->set_pid(kPidA);
422 
423     // The rename event pid will match the ftrace event pid.
424     auto* rename = event->mutable_task_rename();
425     rename->set_newcomm(std::string(kCommB));
426     rename->set_oldcomm(std::string(kCommA));
427     rename->set_pid(kPidA);
428     rename->set_oom_score_adj(0);
429 
430     context_.timeline = std::make_unique<ProcessThreadTimeline>();
431 
432     context_.timeline->Append(
433         ProcessThreadTimeline::Event::Open(kTimeA, kPidA, kNoParent, kUidA));
434     context_.timeline->Append(
435         ProcessThreadTimeline::Event::Open(kTimeA, kPidB, kNoParent, kUidB));
436     context_.timeline->Sort();
437 
438     redact_.emplace_modifier<DoNothing>();
439     redact_.emplace_filter<AllowAll>();
440   }
441 
442   RedactProcessEvents redact_;
443   protos::gen::TracePacket packet_;
444   Context context_;
445 };
446 
TEST_F(RedactRenameTest,KeepCommInsidePackage)447 TEST_F(RedactRenameTest, KeepCommInsidePackage) {
448   redact_.emplace_modifier<ClearComms>();
449 
450   // The rename task is for Pid A. Pid A is part of Uid A. Keep Uid A; keep
451   // comm.
452   context_.package_uid = kUidA;
453 
454   auto packet_str = packet_.SerializeAsString();
455   ASSERT_OK(redact_.Transform(context_, &packet_str));
456 
457   protos::gen::TracePacket packet;
458   ASSERT_TRUE(packet.ParseFromString(packet_str));
459 
460   ASSERT_TRUE(packet.has_ftrace_events());
461   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
462 
463   const auto& event = packet.ftrace_events().event().at(0);
464   ASSERT_TRUE(event.has_task_rename());
465 
466   const auto& task_rename = event.task_rename();
467 
468   ASSERT_TRUE(task_rename.has_pid());
469   ASSERT_EQ(task_rename.pid(), kPidA);
470 
471   ASSERT_TRUE(task_rename.has_oldcomm());
472   ASSERT_EQ(task_rename.oldcomm(), kCommA);
473 
474   ASSERT_TRUE(task_rename.has_newcomm());
475   ASSERT_EQ(task_rename.newcomm(), kCommB);
476 }
477 
TEST_F(RedactRenameTest,ClearCommOutsidePackage)478 TEST_F(RedactRenameTest, ClearCommOutsidePackage) {
479   redact_.emplace_modifier<ClearComms>();
480 
481   // The rename task is for Pid A. Pid A is part of Uid A. Keep Uid B; drop
482   // comm.
483   context_.package_uid = kUidB;
484 
485   auto packet_str = packet_.SerializeAsString();
486   ASSERT_OK(redact_.Transform(context_, &packet_str));
487 
488   protos::gen::TracePacket packet;
489   ASSERT_TRUE(packet.ParseFromString(packet_str));
490 
491   ASSERT_TRUE(packet.has_ftrace_events());
492   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
493 
494   const auto& event = packet.ftrace_events().event().at(0);
495   ASSERT_TRUE(event.has_task_rename());
496 
497   const auto& task_rename = event.task_rename();
498 
499   ASSERT_TRUE(task_rename.has_pid());
500   ASSERT_EQ(task_rename.pid(), kPidA);
501 
502   ASSERT_TRUE(task_rename.has_oldcomm());
503   ASSERT_TRUE(task_rename.oldcomm().empty());
504 
505   ASSERT_TRUE(task_rename.has_newcomm());
506   ASSERT_TRUE(task_rename.newcomm().empty());
507 }
508 
TEST_F(RedactRenameTest,KeepTaskInsidePackage)509 TEST_F(RedactRenameTest, KeepTaskInsidePackage) {
510   redact_.emplace_filter<ConnectedToPackage>();
511 
512   // The rename task is for Pid A. Pid A is part of Uid A. Keep Uid A; keep
513   // comm.
514   context_.package_uid = kUidA;
515 
516   auto packet_str = packet_.SerializeAsString();
517   ASSERT_OK(redact_.Transform(context_, &packet_str));
518 
519   protos::gen::TracePacket packet;
520   ASSERT_TRUE(packet.ParseFromString(packet_str));
521 
522   ASSERT_TRUE(packet.has_ftrace_events());
523   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
524 
525   const auto& event = packet.ftrace_events().event().at(0);
526   ASSERT_TRUE(event.has_task_rename());
527 }
528 
TEST_F(RedactRenameTest,DropTaskOutsidePackage)529 TEST_F(RedactRenameTest, DropTaskOutsidePackage) {
530   redact_.emplace_filter<ConnectedToPackage>();
531 
532   // The rename task is for Pid A. Pid A is part of Uid A. Keep Uid B; drop
533   // task.
534   context_.package_uid = kUidB;
535 
536   auto packet_str = packet_.SerializeAsString();
537   ASSERT_OK(redact_.Transform(context_, &packet_str));
538 
539   protos::gen::TracePacket packet;
540   ASSERT_TRUE(packet.ParseFromString(packet_str));
541 
542   ASSERT_TRUE(packet.has_ftrace_events());
543   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
544 
545   // The task should have been removed, but the event will still remain.
546   const auto& event = packet.ftrace_events().event().at(0);
547   ASSERT_FALSE(event.has_task_rename());
548 }
549 
550 class RedactPrintTest : public testing::Test {
551  protected:
SetUp()552   void SetUp() {
553     auto* events = packet_.mutable_ftrace_events();
554     events->set_cpu(kCpu);
555 
556     auto* event = events->add_event();
557     event->set_timestamp(kTimeB);
558     event->set_pid(kPidA);
559 
560     // The rename event pid will match the ftrace event pid.
561     auto* print = event->mutable_print();
562     print->set_buf(std::string(kCommA));
563     print->set_ip(0);
564 
565     context_.timeline = std::make_unique<ProcessThreadTimeline>();
566 
567     context_.timeline->Append(
568         ProcessThreadTimeline::Event::Open(kTimeA, kPidA, kNoParent, kUidA));
569     context_.timeline->Append(
570         ProcessThreadTimeline::Event::Open(kTimeA, kPidB, kNoParent, kUidB));
571     context_.timeline->Sort();
572 
573     redact_.emplace_modifier<DoNothing>();
574     redact_.emplace_filter<AllowAll>();
575   }
576 
577   RedactProcessEvents redact_;
578   protos::gen::TracePacket packet_;
579   Context context_;
580 };
581 
TEST_F(RedactPrintTest,KeepTaskInsidePackage)582 TEST_F(RedactPrintTest, KeepTaskInsidePackage) {
583   redact_.emplace_filter<ConnectedToPackage>();
584 
585   // The rename task is for Pid A. Pid A is part of Uid A. Keep Uid A; keep
586   // comm.
587   context_.package_uid = kUidA;
588 
589   auto packet_str = packet_.SerializeAsString();
590   ASSERT_OK(redact_.Transform(context_, &packet_str));
591 
592   protos::gen::TracePacket packet;
593   ASSERT_TRUE(packet.ParseFromString(packet_str));
594 
595   ASSERT_TRUE(packet.has_ftrace_events());
596   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
597 
598   const auto& event = packet.ftrace_events().event().at(0);
599   ASSERT_TRUE(event.has_print());
600 }
601 
TEST_F(RedactPrintTest,DropTaskOutsidePackage)602 TEST_F(RedactPrintTest, DropTaskOutsidePackage) {
603   redact_.emplace_filter<ConnectedToPackage>();
604 
605   // The rename task is for Pid A. Pid A is part of Uid A. Keep Uid B; drop
606   // task.
607   context_.package_uid = kUidB;
608 
609   auto packet_str = packet_.SerializeAsString();
610   ASSERT_OK(redact_.Transform(context_, &packet_str));
611 
612   protos::gen::TracePacket packet;
613   ASSERT_TRUE(packet.ParseFromString(packet_str));
614 
615   ASSERT_TRUE(packet.has_ftrace_events());
616   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
617 
618   // The task should have been removed, but the event will still remain.
619   const auto& event = packet.ftrace_events().event().at(0);
620   ASSERT_FALSE(event.has_print());
621 }
622 
623 class RedactSuspendResumeTest : public testing::Test {
624  protected:
SetUp()625   void SetUp() {
626     auto* events = packet_.mutable_ftrace_events();
627     events->set_cpu(kCpu);
628 
629     for (const auto& action : {"syscore_suspend", "syscore_resume",
630                                "timekeeping_freeze", "not-allowed"}) {
631       auto* event = events->add_event();
632       event->set_timestamp(kTimeB);
633       event->set_pid(kPidA);
634 
635       auto* suspend_resume = event->mutable_suspend_resume();
636       suspend_resume->set_action(action);
637       suspend_resume->set_start(0);
638       suspend_resume->set_val(3);
639     }
640 
641     context_.timeline = std::make_unique<ProcessThreadTimeline>();
642 
643     context_.timeline->Append(
644         ProcessThreadTimeline::Event::Open(kTimeA, kPidA, kNoParent, kUidA));
645     context_.timeline->Append(
646         ProcessThreadTimeline::Event::Open(kTimeA, kPidB, kNoParent, kUidB));
647     context_.timeline->Sort();
648 
649     redact_.emplace_modifier<DoNothing>();
650     redact_.emplace_filter<AllowAll>();
651   }
652 
653   RedactProcessEvents redact_;
654   protos::gen::TracePacket packet_;
655   Context context_;
656 };
657 
TEST_F(RedactSuspendResumeTest,KeepTaskInsidePackage)658 TEST_F(RedactSuspendResumeTest, KeepTaskInsidePackage) {
659   redact_.emplace_filter<ConnectedToPackage>();
660 
661   context_.package_uid = kUidA;
662 
663   auto packet_str = packet_.SerializeAsString();
664   ASSERT_OK(redact_.Transform(context_, &packet_str));
665 
666   protos::gen::TracePacket packet;
667   ASSERT_TRUE(packet.ParseFromString(packet_str));
668 
669   ASSERT_TRUE(packet.has_ftrace_events());
670   ASSERT_EQ(packet.ftrace_events().event().size(), 4u);
671 }
672 
673 // Only actions in the allowlist should be allowed.
674 //
675 // TODO(vaage): The allowlist is not configurable right now. If moved into the
676 // context, it could be configured.
TEST_F(RedactSuspendResumeTest,FiltersByAllowlist)677 TEST_F(RedactSuspendResumeTest, FiltersByAllowlist) {
678   redact_.emplace_filter<ConnectedToPackage>();
679 
680   context_.package_uid = kUidA;
681 
682   auto packet_str = packet_.SerializeAsString();
683   ASSERT_OK(redact_.Transform(context_, &packet_str));
684 
685   protos::gen::TracePacket packet;
686   ASSERT_TRUE(packet.ParseFromString(packet_str));
687 
688   ASSERT_TRUE(packet.has_ftrace_events());
689   ASSERT_EQ(packet.ftrace_events().event().size(), 4u);
690 
691   {
692     const auto& event = packet.ftrace_events().event().at(0);
693     ASSERT_TRUE(event.has_suspend_resume());
694     ASSERT_EQ(event.suspend_resume().action(), "syscore_suspend");
695   }
696 
697   {
698     const auto& event = packet.ftrace_events().event().at(1);
699     ASSERT_TRUE(event.has_suspend_resume());
700     ASSERT_EQ(event.suspend_resume().action(), "syscore_resume");
701   }
702 
703   {
704     const auto& event = packet.ftrace_events().event().at(2);
705     ASSERT_TRUE(event.has_suspend_resume());
706     ASSERT_EQ(event.suspend_resume().action(), "timekeeping_freeze");
707   }
708 
709   // The fourth entry is an invalid action. While the other entries are valid
710   // and are retained, this one should be dropped.
711   ASSERT_FALSE(packet.ftrace_events().event().at(3).has_suspend_resume());
712 }
713 
TEST_F(RedactSuspendResumeTest,DropTaskOutsidePackage)714 TEST_F(RedactSuspendResumeTest, DropTaskOutsidePackage) {
715   redact_.emplace_filter<ConnectedToPackage>();
716 
717   context_.package_uid = kUidB;
718 
719   auto packet_str = packet_.SerializeAsString();
720   ASSERT_OK(redact_.Transform(context_, &packet_str));
721 
722   protos::gen::TracePacket packet;
723   ASSERT_TRUE(packet.ParseFromString(packet_str));
724 
725   ASSERT_TRUE(packet.has_ftrace_events());
726   ASSERT_EQ(packet.ftrace_events().event().size(), 4u);
727 
728   // The task should have been removed, but the event will still remain.
729   ASSERT_FALSE(packet.ftrace_events().event().at(0).has_suspend_resume());
730   ASSERT_FALSE(packet.ftrace_events().event().at(1).has_suspend_resume());
731   ASSERT_FALSE(packet.ftrace_events().event().at(2).has_suspend_resume());
732   ASSERT_FALSE(packet.ftrace_events().event().at(3).has_suspend_resume());
733 }
734 
735 class RedactSchedBlockReasonTest : public testing::Test {
736  protected:
SetUp()737   void SetUp() {
738     auto* events = packet_.mutable_ftrace_events();
739     events->set_cpu(kCpu);
740 
741     {
742       auto* event = events->add_event();
743       event->set_timestamp(kTimeB);
744       event->set_pid(kPidB);
745 
746       auto* reason = event->mutable_sched_blocked_reason();
747       reason->set_caller(3);
748       reason->set_io_wait(7);
749       reason->set_pid(kPidAA);
750     }
751 
752     context_.timeline = std::make_unique<ProcessThreadTimeline>();
753 
754     context_.timeline->Append(
755         ProcessThreadTimeline::Event::Open(kTimeA, kPidA, kNoParent, kUidA));
756 
757     context_.timeline->Append(
758         ProcessThreadTimeline::Event::Open(kTimeA, kPidAA, kPidA));
759 
760     context_.timeline->Append(
761         ProcessThreadTimeline::Event::Open(kTimeA, kPidB, kNoParent, kUidB));
762 
763     context_.timeline->Sort();
764 
765     redact_.emplace_modifier<DoNothing>();
766     redact_.emplace_filter<AllowAll>();
767   }
768 
769   RedactProcessEvents redact_;
770   protos::gen::TracePacket packet_;
771   Context context_;
772 };
773 
774 // Implementation detail: No events are removed, only inner messages.
TEST_F(RedactSchedBlockReasonTest,KeepTaskInsidePackage)775 TEST_F(RedactSchedBlockReasonTest, KeepTaskInsidePackage) {
776   redact_.emplace_filter<ConnectedToPackage>();
777 
778   // The blocking events target kPidA is connected to kUidA. Since the target is
779   // kUidA, the blocking events should be retained.
780   context_.package_uid = kUidA;
781 
782   auto packet_str = packet_.SerializeAsString();
783   ASSERT_OK(redact_.Transform(context_, &packet_str));
784 
785   protos::gen::TracePacket packet;
786   ASSERT_TRUE(packet.ParseFromString(packet_str));
787 
788   ASSERT_TRUE(packet.has_ftrace_events());
789   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
790 
791   // Assumption, event order does not change. The first event was connected to
792   // kUidA.
793   const auto& event = packet.ftrace_events().event().at(0);
794   ASSERT_TRUE(event.has_sched_blocked_reason());
795   ASSERT_EQ(event.sched_blocked_reason().pid(), kPidAA);
796 }
797 
798 // Implementation detail: No events are removed, only inner messages.
TEST_F(RedactSchedBlockReasonTest,DropTaskOutsidePackage)799 TEST_F(RedactSchedBlockReasonTest, DropTaskOutsidePackage) {
800   redact_.emplace_filter<ConnectedToPackage>();
801 
802   // The blocking events target kPidA is connected to kUidA. Since the target is
803   // kUidB, the blocking events should be dropped.
804   context_.package_uid = kUidB;
805 
806   auto packet_str = packet_.SerializeAsString();
807   ASSERT_OK(redact_.Transform(context_, &packet_str));
808 
809   protos::gen::TracePacket packet;
810   ASSERT_TRUE(packet.ParseFromString(packet_str));
811 
812   ASSERT_TRUE(packet.has_ftrace_events());
813   ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
814 
815   // Assumption, event order does not change. The first event was connected to
816   // kUidA.
817   const auto& event = packet.ftrace_events().event().at(0);
818   ASSERT_FALSE(event.has_sched_blocked_reason());
819 }
820 
821 }  // namespace perfetto::trace_redaction
822