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