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/collect_system_info.h"
18 #include "src/base/test/status_matchers.h"
19 #include "src/trace_processor/util/status_macros.h"
20 #include "test/gtest_and_gmock.h"
21
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/sched.gen.h"
25 #include "protos/perfetto/trace/trace_packet.gen.h"
26
27 namespace perfetto::trace_redaction {
28
29 class CollectSystemInfoTest : public testing::Test {
30 protected:
Collect()31 base::Status Collect() {
32 auto buffer = packet_.SerializeAsString();
33 protos::pbzero::TracePacket::Decoder decoder(buffer);
34
35 RETURN_IF_ERROR(collect_.Begin(&context_));
36 RETURN_IF_ERROR(collect_.Collect(decoder, &context_));
37 return collect_.End(&context_);
38 }
39
AppendFtraceEvent(uint32_t event_cpu,uint32_t pid)40 void AppendFtraceEvent(uint32_t event_cpu, uint32_t pid) {
41 auto* events = packet_.mutable_ftrace_events();
42 events->set_cpu(event_cpu);
43
44 auto* event = events->add_event();
45 event->set_pid(pid);
46 }
47
AppendSchedSwitch(int32_t next_pid)48 void AppendSchedSwitch(int32_t next_pid) {
49 auto& event = packet_.mutable_ftrace_events()->mutable_event()->back();
50
51 auto* sched_switch = event.mutable_sched_switch();
52 sched_switch->set_prev_pid(static_cast<int32_t>(event.pid()));
53 sched_switch->set_next_pid(next_pid);
54 }
55
56 protos::gen::TracePacket packet_;
57 Context context_;
58 CollectSystemInfo collect_;
59 };
60
TEST_F(CollectSystemInfoTest,UpdatesCpuCountUsingFtraceEvents)61 TEST_F(CollectSystemInfoTest, UpdatesCpuCountUsingFtraceEvents) {
62 AppendFtraceEvent(7, 8);
63 AppendSchedSwitch(9);
64
65 ASSERT_OK(Collect());
66 ASSERT_EQ(context_.system_info->cpu_count(), 8u);
67
68 AppendFtraceEvent(11, 8);
69 AppendSchedSwitch(9);
70
71 ASSERT_OK(Collect());
72 ASSERT_EQ(context_.system_info->cpu_count(), 12u);
73 }
74
75 // The first synth thread pid should be beyond the range of valid pids.
TEST(SystemInfoTest,FirstSynthThreadPidIsNotAValidPid)76 TEST(SystemInfoTest, FirstSynthThreadPidIsNotAValidPid) {
77 SystemInfo info;
78
79 auto pid = info.AllocateSynthThread();
80 ASSERT_GT(pid, 1 << 22);
81 }
82
TEST(BuildSyntheticProcessTest,CreatesThreadsPerCpu)83 TEST(BuildSyntheticProcessTest, CreatesThreadsPerCpu) {
84 Context context;
85 context.system_info.emplace();
86
87 // The first CPU is always 0, so CPU 7 means there are 8 CPUs.
88 context.system_info->ReserveCpu(7);
89
90 BuildSyntheticThreads build;
91 ASSERT_OK(build.Build(&context));
92
93 ASSERT_NE(context.synthetic_process->tgid(), 0);
94
95 // One main thread and 1 thread per CPU.
96 ASSERT_EQ(context.synthetic_process->tids().size(), 9u);
97 }
98
99 } // namespace perfetto::trace_redaction
100