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/traced/probes/system_info/system_info_data_source.h"
18 #include "src/traced/probes/common/cpu_freq_info_for_testing.h"
19 #include "src/tracing/core/trace_writer_for_testing.h"
20 #include "test/gtest_and_gmock.h"
21
22 #include "protos/perfetto/trace/system_info/cpu_info.gen.h"
23
24 using ::testing::AnyOf;
25 using ::testing::ElementsAre;
26 using ::testing::Return;
27
28 namespace perfetto {
29 namespace {
30
31 static const uint32_t CPU_COUNT = 8;
32
33 const char kMockCpuInfoAndroid[] = R"(
34 Processor : AArch64 Processor rev 13 (aarch64)
35 processor : 0
36 BogoMIPS : 38.00
37 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
38 CPU implementer : 0x51
39 CPU architecture: 8
40 CPU variant : 0x7
41 CPU part : 0x803
42 CPU revision : 12
43
44 processor : 1
45 BogoMIPS : 38.00
46 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
47 CPU implementer : 0x51
48 CPU architecture: 8
49 CPU variant : 0x7
50 CPU part : 0x803
51 CPU revision : 12
52
53 processor : 2
54 BogoMIPS : 38.00
55 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
56 CPU implementer : 0x51
57 CPU architecture: 8
58 CPU variant : 0x7
59 CPU part : 0x803
60 CPU revision : 12
61
62 processor : 3
63 BogoMIPS : 38.00
64 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
65 CPU implementer : 0x51
66 CPU architecture: 8
67 CPU variant : 0x7
68 CPU part : 0x803
69 CPU revision : 12
70
71 processor : 4
72 BogoMIPS : 38.00
73 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
74 CPU implementer : 0x51
75 CPU architecture: 8
76 CPU variant : 0x7
77 CPU part : 0x803
78 CPU revision : 12
79
80 processor : 5
81 BogoMIPS : 38.00
82 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
83 CPU implementer : 0x51
84 CPU architecture: 8
85 CPU variant : 0x7
86 CPU part : 0x803
87 CPU revision : 12
88
89 processor : 6
90 BogoMIPS : 38.00
91 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
92 CPU implementer : 0x51
93 CPU architecture: 8
94 CPU variant : 0x6
95 CPU part : 0x802
96 CPU revision : 13
97
98 processor : 7
99 BogoMIPS : 38.00
100 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
101 CPU implementer : 0x51
102 CPU architecture: 8
103 CPU variant : 0x6
104 CPU part : 0x802
105 CPU revision : 13
106
107 Hardware : Qualcomm Technologies, Inc SDM670
108
109 )";
110
111 const char* kMockCpuCapacityInfoAndroid[8] = {
112 "200\n", "200\n", "200\n", "600\n", "600\n", "600\n", "1024\n", "1024\n"};
113
114 class TestSystemInfoDataSource : public SystemInfoDataSource {
115 public:
TestSystemInfoDataSource(std::unique_ptr<TraceWriter> writer,std::unique_ptr<CpuFreqInfo> cpu_freq_info)116 TestSystemInfoDataSource(std::unique_ptr<TraceWriter> writer,
117 std::unique_ptr<CpuFreqInfo> cpu_freq_info)
118 : SystemInfoDataSource(
119 /* session_id */ 0,
120 std::move(writer),
121 std::move(cpu_freq_info)) {}
122
123 MOCK_METHOD(std::string, ReadFile, (std::string), (override));
124 };
125
126 class SystemInfoDataSourceTest : public ::testing::Test {
127 protected:
GetSystemInfoDataSource()128 std::unique_ptr<TestSystemInfoDataSource> GetSystemInfoDataSource() {
129 auto writer =
130 std::unique_ptr<TraceWriterForTesting>(new TraceWriterForTesting());
131 writer_raw_ = writer.get();
132 auto instance =
133 std::unique_ptr<TestSystemInfoDataSource>(new TestSystemInfoDataSource(
134 std::move(writer), cpu_freq_info_for_testing.GetInstance()));
135 return instance;
136 }
137
138 TraceWriterForTesting* writer_raw_ = nullptr;
139 CpuFreqInfoForTesting cpu_freq_info_for_testing;
140 };
141
TEST_F(SystemInfoDataSourceTest,CpuInfoAndroid)142 TEST_F(SystemInfoDataSourceTest, CpuInfoAndroid) {
143 auto data_source = GetSystemInfoDataSource();
144 EXPECT_CALL(*data_source, ReadFile("/proc/cpuinfo"))
145 .WillOnce(Return(kMockCpuInfoAndroid));
146
147 for (uint32_t cpu_index = 0; cpu_index < CPU_COUNT; cpu_index++) {
148 EXPECT_CALL(*data_source,
149 ReadFile("/sys/devices/system/cpu/cpu" +
150 std::to_string(cpu_index) + "/cpu_capacity"))
151 .WillOnce(Return(kMockCpuCapacityInfoAndroid[cpu_index]));
152 }
153
154 data_source->Start();
155
156 protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
157 ASSERT_TRUE(packet.has_cpu_info());
158 auto cpu_info = packet.cpu_info();
159 ASSERT_EQ(cpu_info.cpus_size(), 8);
160 auto cpu = cpu_info.cpus()[0];
161 ASSERT_EQ(cpu.processor(), "AArch64 Processor rev 13 (aarch64)");
162 ASSERT_THAT(cpu.frequencies(),
163 ElementsAre(300000, 576000, 748800, 998400, 1209600, 1324800,
164 1516800, 1612800, 1708800));
165 ASSERT_TRUE(cpu.has_arm_identifier());
166 auto id = cpu.arm_identifier();
167 ASSERT_EQ(id.implementer(), 0x51U);
168 ASSERT_EQ(id.architecture(), 8U);
169 ASSERT_EQ(id.variant(), 0x7U);
170 ASSERT_EQ(id.part(), 0x803U);
171 ASSERT_EQ(id.revision(), 12U);
172
173 ASSERT_EQ(cpu.capacity(), static_cast<uint32_t>(200));
174 cpu = cpu_info.cpus()[1];
175 ASSERT_EQ(cpu.processor(), "AArch64 Processor rev 13 (aarch64)");
176 ASSERT_THAT(cpu.frequencies(),
177 ElementsAre(300000, 652800, 825600, 979200, 1132800, 1363200,
178 1536000, 1747200, 1843200, 1996800, 2803200));
179 ASSERT_TRUE(cpu.has_arm_identifier());
180 id = cpu.arm_identifier();
181 ASSERT_EQ(id.implementer(), 0x51U);
182 ASSERT_EQ(id.architecture(), 8U);
183 ASSERT_EQ(id.variant(), 0x7U);
184 ASSERT_EQ(id.part(), 0x803U);
185 ASSERT_EQ(id.revision(), 12U);
186
187 cpu = cpu_info.cpus()[7];
188 ASSERT_EQ(cpu.capacity(), static_cast<uint32_t>(1024));
189 ASSERT_TRUE(cpu.has_arm_identifier());
190 id = cpu.arm_identifier();
191 ASSERT_EQ(id.implementer(), 0x51U);
192 ASSERT_EQ(id.architecture(), 8U);
193 ASSERT_EQ(id.variant(), 0x6U);
194 ASSERT_EQ(id.part(), 0x802U);
195 ASSERT_EQ(id.revision(), 13U);
196 }
197
198 } // namespace
199 } // namespace perfetto
200