xref: /aosp_15_r20/external/perfetto/src/trace_redaction/scrub_process_stats_integrationtest.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 <cstdint>
18 #include <string>
19 
20 #include "perfetto/base/status.h"
21 #include "src/base/test/status_matchers.h"
22 #include "src/trace_redaction/collect_timeline_events.h"
23 #include "src/trace_redaction/scrub_process_stats.h"
24 #include "src/trace_redaction/trace_redaction_framework.h"
25 #include "src/trace_redaction/trace_redaction_integration_fixture.h"
26 #include "src/trace_redaction/trace_redactor.h"
27 #include "test/gtest_and_gmock.h"
28 
29 #include "protos/perfetto/trace/ps/process_stats.pbzero.h"
30 #include "protos/perfetto/trace/trace.pbzero.h"
31 #include "protos/perfetto/trace/trace_packet.pbzero.h"
32 
33 namespace perfetto::trace_redaction {
34 
35 class ScrubProcessStatsTest : public testing::Test,
36                               protected TraceRedactionIntegrationFixure {
37  protected:
SetUp()38   void SetUp() override {
39     trace_redactor_.emplace_collect<CollectTimelineEvents>();
40 
41     auto* scrub = trace_redactor_.emplace_transform<ScrubProcessStats>();
42     scrub->emplace_filter<ConnectedToPackage>();
43 
44     // Package "com.Unity.com.unity.multiplayer.samples.coop";
45     context_.package_uid = 10252;
46   }
47 
48   // Gets pids from all process_stats messages in the trace (bytes).
GetAllPids(const std::string & bytes) const49   base::FlatSet<int32_t> GetAllPids(const std::string& bytes) const {
50     base::FlatSet<int32_t> pids;
51 
52     protos::pbzero::Trace::Decoder decoder(bytes);
53 
54     for (auto packet = decoder.packet(); packet; ++packet) {
55       protos::pbzero::TracePacket::Decoder trace_packet(packet->as_bytes());
56 
57       if (!trace_packet.has_process_stats()) {
58         continue;
59       }
60 
61       protos::pbzero::ProcessStats::Decoder process_stats(
62           trace_packet.process_stats());
63 
64       for (auto process = process_stats.processes(); process; ++process) {
65         protos::pbzero::ProcessStats::Process::Decoder p(process->as_bytes());
66         PERFETTO_DCHECK(p.has_pid());
67         pids.insert(p.pid());
68       }
69     }
70 
71     return pids;
72   }
73 
74   Context context_;
75   TraceRedactor trace_redactor_;
76 };
77 
78 // This test is a canary for changes to the test data. If the test data was to
79 // change, every test in this file would fail.
80 //
81 //  SELECT DISTINCT pid
82 //  FROM process
83 //  WHERE upid IN (
84 //    SELECT DISTINCT upid
85 //    FROM counter
86 //      JOIN process_counter_track ON counter.track_id=process_counter_track.id
87 //    WHERE name!='oom_score_adj'
88 //  )
89 //  ORDER BY pid
90 //
91 //  NOTE: WHERE name!='oom_score_adj' is used because there are two sources for
92 //  oom_score_adj values and we only want process stats here.
TEST_F(ScrubProcessStatsTest,VerifyTraceStats)93 TEST_F(ScrubProcessStatsTest, VerifyTraceStats) {
94   base::FlatSet<int32_t> expected = {
95       1,     578,   581,   696,   697,   698,   699,   700,   701,   704,
96       709,   710,   718,   728,   749,   750,   751,   752,   756,   760,
97       761,   762,   873,   874,   892,   1046,  1047,  1073,  1074,  1091,
98       1092,  1093,  1101,  1103,  1104,  1105,  1106,  1107,  1110,  1111,
99       1112,  1113,  1115,  1116,  1118,  1119,  1120,  1121,  1123,  1124,
100       1125,  1126,  1127,  1129,  1130,  1131,  1133,  1140,  1145,  1146,
101       1147,  1151,  1159,  1163,  1164,  1165,  1166,  1167,  1168,  1175,
102       1177,  1205,  1206,  1235,  1237,  1238,  1248,  1251,  1254,  1255,
103       1295,  1296,  1298,  1300,  1301,  1303,  1304,  1312,  1317,  1325,
104       1339,  1340,  1363,  1374,  1379,  1383,  1388,  1392,  1408,  1409,
105       1410,  1413,  1422,  1426,  1427,  1428,  1429,  1433,  1436,  1448,
106       1450,  1451,  1744,  1774,  1781,  1814,  2262,  2268,  2286,  2392,
107       2456,  2502,  2510,  2518,  2528,  2569,  3171,  3195,  3262,  3286,
108       3310,  3338,  3442,  3955,  4386,  4759,  5935,  6034,  6062,  6167,
109       6547,  6573,  6720,  6721,  6725,  6944,  6984,  7105,  7207,  7557,
110       7636,  7786,  7874,  7958,  7960,  7967,  15449, 15685, 15697, 16453,
111       19683, 21124, 21839, 23150, 23307, 23876, 24317, 25017, 25126, 25450,
112       25474, 27271, 30604, 32289,
113   };
114 
115   auto original = LoadOriginal();
116   ASSERT_OK(original) << original.status().c_message();
117 
118   auto actual = GetAllPids(*original);
119 
120   for (auto pid : expected) {
121     ASSERT_TRUE(actual.count(pid))
122         << "pid " << pid << " was not found in the trace";
123   }
124 
125   for (auto pid : actual) {
126     ASSERT_TRUE(expected.count(pid))
127         << "pid " << pid << " was found in the trace";
128   }
129 }
130 
131 // Package name: "com.Unity.com.unity.multiplayer.samples.coop"
132 // Package pid: 7105
TEST_F(ScrubProcessStatsTest,OnlyKeepsStatsForPackage)133 TEST_F(ScrubProcessStatsTest, OnlyKeepsStatsForPackage) {
134   auto result = Redact(trace_redactor_, &context_);
135   ASSERT_OK(result) << result.c_message();
136 
137   auto redacted = LoadRedacted();
138   ASSERT_OK(redacted) << redacted.status().c_message();
139 
140   auto actual = GetAllPids(*redacted);
141   ASSERT_EQ(actual.size(), 1u);
142   ASSERT_TRUE(actual.count(7105));
143 }
144 
145 }  // namespace perfetto::trace_redaction
146