1 /*
2 * Copyright (C) 2018 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 <unistd.h>
18
19 #include "perfetto/ext/base/file_utils.h"
20 #include "perfetto/ext/base/string_utils.h"
21 #include "perfetto/ext/base/temp_file.h"
22 #include "src/base/test/test_task_runner.h"
23 #include "src/traced/probes/common/cpu_freq_info_for_testing.h"
24 #include "src/traced/probes/sys_stats/sys_stats_data_source.h"
25 #include "src/tracing/core/trace_writer_for_testing.h"
26 #include "test/gtest_and_gmock.h"
27
28 #include "protos/perfetto/common/sys_stats_counters.gen.h"
29 #include "protos/perfetto/config/data_source_config.gen.h"
30 #include "protos/perfetto/config/sys_stats/sys_stats_config.gen.h"
31 #include "protos/perfetto/trace/sys_stats/sys_stats.gen.h"
32
33 using ::testing::_;
34 using ::testing::Invoke;
35 using ::testing::Return;
36 using ::testing::UnorderedElementsAre;
37
38 namespace perfetto {
39 namespace {
40
41 const char kMockMeminfo[] = R"(
42 MemTotal: 3744240 kB
43 MemFree: 73328 kB
44 MemAvailable: 629896 kB
45 Buffers: 19296 kB
46 Cached: 731032 kB
47 SwapCached: 4936 kB
48 Active: 1616348 kB
49 Inactive: 745492 kB
50 Active(anon): 1322636 kB
51 Inactive(anon): 449172 kB
52 Active(file): 293712 kB
53 Inactive(file): 296320 kB
54 Unevictable: 142152 kB
55 Mlocked: 142152 kB
56 SwapTotal: 524284 kB
57 SwapFree: 128 kB
58 Dirty: 0 kB
59 Writeback: 0 kB
60 AnonPages: 1751140 kB
61 Mapped: 508372 kB
62 Shmem: 18604 kB
63 Slab: 240352 kB
64 SReclaimable: 64684 kB
65 SUnreclaim: 175668 kB
66 KernelStack: 62672 kB
67 PageTables: 70108 kB
68 NFS_Unstable: 0 kB
69 Bounce: 0 kB
70 WritebackTmp: 0 kB
71 CommitLimit: 2396404 kB
72 Committed_AS: 81911488 kB
73 VmallocTotal: 258867136 kB
74 VmallocUsed: 0 kB
75 VmallocChunk: 0 kB
76 CmaTotal: 196608 kB
77 CmaFree: 60 kB)";
78
79 const char kMockVmstat[] = R"(
80 nr_free_pages 16449
81 nr_alloc_batch 79
82 nr_inactive_anon 112545
83 nr_active_anon 322027
84 nr_inactive_file 75904
85 nr_active_file 87939
86 nr_unevictable 35538
87 nr_mlock 35538
88 nr_anon_pages 429005
89 nr_mapped 125844
90 nr_file_pages 205523
91 nr_dirty 23
92 nr_writeback 0
93 nr_slab_reclaimable 15840
94 nr_slab_unreclaimable 43912
95 nr_page_table_pages 17158
96 nr_kernel_stack 3822
97 nr_overhead 0
98 nr_unstable 0
99 nr_bounce 0
100 nr_vmscan_write 558690
101 nr_vmscan_immediate_reclaim 14853
102 nr_writeback_temp 0
103 nr_isolated_anon 0
104 nr_isolated_file 0
105 nr_shmem 5027
106 nr_dirtied 6732417
107 nr_written 6945513
108 nr_pages_scanned 0
109 workingset_refault 32784684
110 workingset_activate 8200928
111 workingset_nodereclaim 0
112 nr_anon_transparent_hugepages 0
113 nr_free_cma 0
114 nr_swapcache 1254
115 nr_dirty_threshold 33922
116 nr_dirty_background_threshold 8449
117 pgpgin 161257156
118 pgpgout 35973852
119 pgpgoutclean 37181384
120 pswpin 185308
121 pswpout 557662
122 pgalloc_dma 79259070
123 pgalloc_normal 88265512
124 pgalloc_movable 0
125 pgfree 175051592
126 pgactivate 11897892
127 pgdeactivate 20412230
128 pgfault 181696234
129 pgmajfault 1060871
130 pgrefill_dma 12970047
131 pgrefill_normal 14391564
132 pgrefill_movable 0
133 pgsteal_kswapd_dma 19471476
134 pgsteal_kswapd_normal 21138380
135 pgsteal_kswapd_movable 0
136 pgsteal_direct 91537
137 pgsteal_direct_dma 40625
138 pgsteal_direct_normal 50912
139 pgsteal_direct_movable 0
140 pgscan_kswapd_dma 23544417
141 pgscan_kswapd_normal 25623715
142 pgscan_kswapd_movable 0
143 pgscan_direct_dma 50369
144 pgscan_direct_normal 66284
145 pgscan_direct_movable 0
146 pgscan_direct_throttle 0
147 pginodesteal 0
148 slabs_scanned 39582828
149 kswapd_inodesteal 110199
150 kswapd_low_wmark_hit_quickly 21321
151 kswapd_high_wmark_hit_quickly 4112
152 pageoutrun 37666
153 allocstall 1587
154 pgrotated 12086
155 drop_pagecache 0
156 drop_slab 0
157 pgmigrate_success 5923482
158 pgmigrate_fail 3439
159 compact_migrate_scanned 92906456
160 compact_free_scanned 467077168
161 compact_isolated 13456528
162 compact_stall 197
163 compact_fail 42
164 compact_success 155
165 compact_daemon_wake 2131
166 unevictable_pgs_culled 50170
167 unevictable_pgs_scanned 0
168 unevictable_pgs_rescued 14640
169 unevictable_pgs_mlocked 52520
170 unevictable_pgs_munlocked 14640
171 unevictable_pgs_cleared 2342
172 unevictable_pgs_stranded 2342
173 vma_lock_abort 1173728)";
174
175 const char kMockStat[] = R"(
176 cpu 2655987 822682 2352153 8801203 41917 322733 175055 0 0 0
177 cpu0 762178 198125 902284 8678856 41716 152974 68262 0 0 0
178 cpu1 613833 243394 504323 15194 96 60625 28785 0 0 0
179 cpu2 207349 95060 248856 17351 42 32148 26108 0 0 0
180 cpu3 138474 92158 174852 17537 48 25076 25035 0 0 0
181 cpu4 278720 34689 141048 18117 1 20782 5873 0 0 0
182 cpu5 235376 33907 85098 18278 2 10049 3774 0 0 0
183 cpu6 239568 67149 155814 17890 5 11518 3807 0 0 0
184 cpu7 180484 58196 139874 17975 3 9556 13407 0 0 0
185 intr 238128517 0 0 0 63500984 0 6253792 6 4 5 0 0 0 0 0 0 0 160331 0 0 14 0 0 0 0 0 0 0 0 0 0 0 20430 2279 11 11 83272 0 0 0 0 0 0 0 5754 220829 0 154753 908545 1824602 7314228 0 0 0 6898259 0 0 10 0 0 2 0 0 0 0 0 0 0 42 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 575816 1447531 134022 0 0 0 0 0 435008 319921 2755476 0 0 0 0 91 310212 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 4 0 0 545 901 554 9 3377 4184 12 10 588851 0 2 1109045 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 8 0 0 0 0 0 0 0 0 0 0 0 0 497 0 0 0 0 0 26172 0 0 0 0 0 0 0 1362 0 0 0 0 0 0 0 424 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23427 0 0 0 0 1 1298 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 108 0 0 0 0 86 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1784935 407979 2140 10562241 52374 74699 6976 84926 222 169088 0 0 0 0 174 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2789 51543 0 83 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 13 11 17 1393 0 0 0 0 0 0 0 0 0 0 26 0 0 2 106 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11150 0 13 0 1 390 6 0 6 4 0 0 0 0 352 284743 2 0 0 24 3 0 3 0 0 0 12 0 668788 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 680 0 0
186 ctxt 373122860
187 btime 1536912218
188 processes 243320
189 procs_running 1
190 procs_blocked 0
191 softirq 84611084 10220177 28299167 155083 3035679 6390543 66234 4396819 15604187 0 16443195)";
192
193 const char kMockBuddy[] = R"(
194 Node 0, zone DMA 2743 1659 2063 685 27 4 0 0 0 0 0
195 Node 0, zone Normal 143 744 89 1080 105 1 0 2 0 2 2
196 Node 0, zone HighMem 345 90 156 3 5 2 0 0 0 0 0
197 Node 1, zone Normal 233 123 453 10 5 1 0 2 0 0 3)";
198
199 const char kDevfreq1[] = "1000000";
200 const char kDevfreq2[] = "20000000";
201
202 const char kMockDiskStat[] = R"(
203 253 0 zram0 13886 0 111088 128 57298 0 458384 48 0 15248 176 0 0 0 0 0 0
204 8 0 sda 54133 5368 8221736 75929 30333 1157434 9599744 143190 0 63672 249858 9595 0 2160072 19411 6649 11327
205 8 1 sda1 18 6 632 7 39 49 704 92 0 156 100 0 0 0 0 0 0)";
206
207 const char kMockPsi[] = R"(
208 some avg10=23.10 avg60=5.06 avg300=15.10 total=417963
209 full avg10=9.00 avg60=19.20 avg300=3.23 total=205933)";
210
211 class TestSysStatsDataSource : public SysStatsDataSource {
212 public:
TestSysStatsDataSource(base::TaskRunner * task_runner,TracingSessionID id,std::unique_ptr<TraceWriter> writer,const DataSourceConfig & config,std::unique_ptr<CpuFreqInfo> cpu_freq_info,OpenFunction open_fn)213 TestSysStatsDataSource(base::TaskRunner* task_runner,
214 TracingSessionID id,
215 std::unique_ptr<TraceWriter> writer,
216 const DataSourceConfig& config,
217 std::unique_ptr<CpuFreqInfo> cpu_freq_info,
218 OpenFunction open_fn)
219 : SysStatsDataSource(task_runner,
220 id,
221 std::move(writer),
222 config,
223 std::move(cpu_freq_info),
224 open_fn) {}
225
226 MOCK_METHOD(base::ScopedDir, OpenDevfreqDir, (), (override));
227 MOCK_METHOD(const char*,
228 ReadDevfreqCurFreq,
229 (const std::string& deviceName),
230 (override));
231 };
232
MockOpenReadOnly(const char * path)233 base::ScopedFile MockOpenReadOnly(const char* path) {
234 base::TempFile tmp_ = base::TempFile::CreateUnlinked();
235 if (!strcmp(path, "/proc/meminfo")) {
236 EXPECT_GT(pwrite(tmp_.fd(), kMockMeminfo, strlen(kMockMeminfo), 0), 0);
237 } else if (!strcmp(path, "/proc/vmstat")) {
238 EXPECT_GT(pwrite(tmp_.fd(), kMockVmstat, strlen(kMockVmstat), 0), 0);
239 } else if (!strcmp(path, "/proc/stat")) {
240 EXPECT_GT(pwrite(tmp_.fd(), kMockStat, strlen(kMockStat), 0), 0);
241 } else if (!strcmp(path, "/proc/buddyinfo")) {
242 EXPECT_GT(pwrite(tmp_.fd(), kMockBuddy, strlen(kMockBuddy), 0), 0);
243 } else if (!strcmp(path, "/proc/diskstats")) {
244 EXPECT_GT(pwrite(tmp_.fd(), kMockDiskStat, strlen(kMockDiskStat), 0), 0);
245 } else if (base::StartsWith(path, "/proc/pressure/")) {
246 EXPECT_GT(pwrite(tmp_.fd(), kMockPsi, strlen(kMockPsi), 0), 0);
247 } else {
248 PERFETTO_FATAL("Unexpected file opened %s", path);
249 }
250 return tmp_.ReleaseFD();
251 }
252
253 class SysStatsDataSourceTest : public ::testing::Test {
254 protected:
GetSysStatsDataSource(const DataSourceConfig & cfg)255 std::unique_ptr<TestSysStatsDataSource> GetSysStatsDataSource(
256 const DataSourceConfig& cfg) {
257 auto writer =
258 std::unique_ptr<TraceWriterForTesting>(new TraceWriterForTesting());
259 writer_raw_ = writer.get();
260 auto instance =
261 std::unique_ptr<TestSysStatsDataSource>(new TestSysStatsDataSource(
262 &task_runner_, 0, std::move(writer), cfg,
263 cpu_freq_info_for_testing_.GetInstance(), MockOpenReadOnly));
264 instance->set_ns_per_user_hz_for_testing(1000000000ull / 100); // 100 Hz.
265 instance->Start();
266 return instance;
267 }
268
Poller(SysStatsDataSource * ds,std::function<void ()> checkpoint)269 void Poller(SysStatsDataSource* ds, std::function<void()> checkpoint) {
270 if (ds->tick_for_testing())
271 checkpoint();
272 else
273 task_runner_.PostDelayedTask(
274 [ds, checkpoint, this] { Poller(ds, checkpoint); }, 1);
275 }
276
WaitTick(SysStatsDataSource * data_source)277 void WaitTick(SysStatsDataSource* data_source) {
278 auto checkpoint = task_runner_.CreateCheckpoint("on_tick");
279 Poller(data_source, checkpoint);
280 task_runner_.RunUntilCheckpoint("on_tick");
281 }
282
283 TraceWriterForTesting* writer_raw_ = nullptr;
284 base::TestTaskRunner task_runner_;
285 CpuFreqInfoForTesting cpu_freq_info_for_testing_;
286 };
287
TEST_F(SysStatsDataSourceTest,Meminfo)288 TEST_F(SysStatsDataSourceTest, Meminfo) {
289 using C = protos::gen::MeminfoCounters;
290 DataSourceConfig config;
291 protos::gen::SysStatsConfig sys_cfg;
292 sys_cfg.set_meminfo_period_ms(10);
293 sys_cfg.add_meminfo_counters(C::MEMINFO_MEM_TOTAL);
294 sys_cfg.add_meminfo_counters(C::MEMINFO_MEM_FREE);
295 sys_cfg.add_meminfo_counters(C::MEMINFO_ACTIVE_ANON);
296 sys_cfg.add_meminfo_counters(C::MEMINFO_INACTIVE_FILE);
297 sys_cfg.add_meminfo_counters(C::MEMINFO_CMA_FREE);
298 config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
299 auto data_source = GetSysStatsDataSource(config);
300
301 WaitTick(data_source.get());
302
303 protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
304 ASSERT_TRUE(packet.has_sys_stats());
305 const auto& sys_stats = packet.sys_stats();
306 EXPECT_EQ(sys_stats.vmstat_size(), 0);
307 EXPECT_EQ(sys_stats.buddy_info_size(), 0);
308 EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
309 EXPECT_EQ(sys_stats.devfreq_size(), 0);
310
311 using KV = std::pair<int, uint64_t>;
312 std::vector<KV> kvs;
313 for (const auto& kv : sys_stats.meminfo())
314 kvs.push_back({kv.key(), kv.value()});
315
316 EXPECT_THAT(kvs,
317 UnorderedElementsAre(KV{C::MEMINFO_MEM_TOTAL, 3744240}, //
318 KV{C::MEMINFO_MEM_FREE, 73328}, //
319 KV{C::MEMINFO_ACTIVE_ANON, 1322636}, //
320 KV{C::MEMINFO_INACTIVE_FILE, 296320}, //
321 KV{C::MEMINFO_CMA_FREE, 60}));
322 }
323
TEST_F(SysStatsDataSourceTest,MeminfoAll)324 TEST_F(SysStatsDataSourceTest, MeminfoAll) {
325 DataSourceConfig config;
326 protos::gen::SysStatsConfig sys_cfg;
327 sys_cfg.set_meminfo_period_ms(10);
328 config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
329 auto data_source = GetSysStatsDataSource(config);
330
331 WaitTick(data_source.get());
332
333 protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
334 ASSERT_TRUE(packet.has_sys_stats());
335 const auto& sys_stats = packet.sys_stats();
336 EXPECT_EQ(sys_stats.vmstat_size(), 0);
337 EXPECT_EQ(sys_stats.buddy_info_size(), 0);
338 EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
339 EXPECT_EQ(sys_stats.devfreq_size(), 0);
340 EXPECT_GE(sys_stats.meminfo_size(), 10);
341 }
342
TEST_F(SysStatsDataSourceTest,Vmstat)343 TEST_F(SysStatsDataSourceTest, Vmstat) {
344 using C = protos::gen::VmstatCounters;
345 DataSourceConfig config;
346 protos::gen::SysStatsConfig sys_cfg;
347 sys_cfg.set_vmstat_period_ms(10);
348 sys_cfg.add_vmstat_counters(C::VMSTAT_NR_FREE_PAGES);
349 sys_cfg.add_vmstat_counters(C::VMSTAT_PGACTIVATE);
350 sys_cfg.add_vmstat_counters(C::VMSTAT_PGMIGRATE_FAIL);
351 sys_cfg.add_vmstat_counters(C::VMSTAT_PGSTEAL_DIRECT);
352 sys_cfg.add_vmstat_counters(C::VMSTAT_VMA_LOCK_ABORT);
353 config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
354 auto data_source = GetSysStatsDataSource(config);
355
356 WaitTick(data_source.get());
357
358 protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
359 ASSERT_TRUE(packet.has_sys_stats());
360 const auto& sys_stats = packet.sys_stats();
361 EXPECT_EQ(sys_stats.meminfo_size(), 0);
362 EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
363 EXPECT_EQ(sys_stats.devfreq_size(), 0);
364
365 using KV = std::pair<int, uint64_t>;
366 std::vector<KV> kvs;
367 for (const auto& kv : sys_stats.vmstat())
368 kvs.push_back({kv.key(), kv.value()});
369
370 EXPECT_THAT(kvs,
371 UnorderedElementsAre(KV{C::VMSTAT_NR_FREE_PAGES, 16449}, //
372 KV{C::VMSTAT_PGACTIVATE, 11897892}, //
373 KV{C::VMSTAT_PGMIGRATE_FAIL, 3439}, //
374 KV{C::VMSTAT_PGSTEAL_DIRECT, 91537}, //
375 KV{C::VMSTAT_VMA_LOCK_ABORT, 1173728} //
376 ));
377 }
378
TEST_F(SysStatsDataSourceTest,VmstatAll)379 TEST_F(SysStatsDataSourceTest, VmstatAll) {
380 DataSourceConfig config;
381 protos::gen::SysStatsConfig sys_cfg;
382 sys_cfg.set_vmstat_period_ms(10);
383 config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
384 auto data_source = GetSysStatsDataSource(config);
385
386 WaitTick(data_source.get());
387
388 protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
389 ASSERT_TRUE(packet.has_sys_stats());
390 const auto& sys_stats = packet.sys_stats();
391 EXPECT_EQ(sys_stats.meminfo_size(), 0);
392 EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
393 EXPECT_EQ(sys_stats.devfreq_size(), 0);
394 EXPECT_EQ(sys_stats.buddy_info_size(), 0);
395 EXPECT_GE(sys_stats.vmstat_size(), 10);
396 }
397
TEST_F(SysStatsDataSourceTest,BuddyinfoAll)398 TEST_F(SysStatsDataSourceTest, BuddyinfoAll) {
399 DataSourceConfig config;
400 protos::gen::SysStatsConfig sys_cfg;
401 sys_cfg.set_buddyinfo_period_ms(10);
402 config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
403 auto data_source = GetSysStatsDataSource(config);
404
405 WaitTick(data_source.get());
406
407 protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
408 ASSERT_TRUE(packet.has_sys_stats());
409 const auto& sys_stats = packet.sys_stats();
410 EXPECT_EQ(sys_stats.meminfo_size(), 0);
411 EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
412 EXPECT_EQ(sys_stats.devfreq_size(), 0);
413 EXPECT_GE(sys_stats.vmstat_size(), 0);
414 EXPECT_EQ(sys_stats.buddy_info_size(), 4);
415
416 EXPECT_EQ(sys_stats.buddy_info()[0].node(), "0");
417 EXPECT_EQ(sys_stats.buddy_info()[0].zone(), "DMA");
418 EXPECT_EQ(sys_stats.buddy_info()[0].order_pages()[0], 2743u);
419 EXPECT_EQ(sys_stats.buddy_info()[0].order_pages()[5], 4u);
420 EXPECT_EQ(sys_stats.buddy_info()[0].order_pages()[10], 0u);
421
422 EXPECT_EQ(sys_stats.buddy_info()[1].node(), "0");
423 EXPECT_EQ(sys_stats.buddy_info()[1].zone(), "Normal");
424 EXPECT_EQ(sys_stats.buddy_info()[1].order_pages()[0], 143u);
425 EXPECT_EQ(sys_stats.buddy_info()[1].order_pages()[5], 1u);
426 EXPECT_EQ(sys_stats.buddy_info()[1].order_pages()[10], 2u);
427
428 EXPECT_EQ(sys_stats.buddy_info()[2].node(), "0");
429 EXPECT_EQ(sys_stats.buddy_info()[2].zone(), "HighMem");
430 EXPECT_EQ(sys_stats.buddy_info()[2].order_pages()[0], 345u);
431 EXPECT_EQ(sys_stats.buddy_info()[2].order_pages()[5], 2u);
432 EXPECT_EQ(sys_stats.buddy_info()[2].order_pages()[10], 0u);
433
434 EXPECT_EQ(sys_stats.buddy_info()[3].node(), "1");
435 EXPECT_EQ(sys_stats.buddy_info()[3].zone(), "Normal");
436 EXPECT_EQ(sys_stats.buddy_info()[3].order_pages()[0], 233u);
437 EXPECT_EQ(sys_stats.buddy_info()[3].order_pages()[5], 1u);
438 EXPECT_EQ(sys_stats.buddy_info()[3].order_pages()[10], 3u);
439 }
440
TEST_F(SysStatsDataSourceTest,DevfreqAll)441 TEST_F(SysStatsDataSourceTest, DevfreqAll) {
442 DataSourceConfig config;
443 protos::gen::SysStatsConfig sys_cfg;
444 sys_cfg.set_devfreq_period_ms(10);
445 config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
446 auto data_source = GetSysStatsDataSource(config);
447
448 // Create dirs and symlinks, but only read the symlinks.
449 std::vector<std::string> dirs_to_delete;
450 std::vector<std::string> symlinks_to_delete;
451 auto make_devfreq_paths = [&symlinks_to_delete, &dirs_to_delete](
452 base::TempDir& temp_dir, base::TempDir& sym_dir,
453 const char* name) {
454 base::StackString<256> path("%s/%s", temp_dir.path().c_str(), name);
455 dirs_to_delete.push_back(path.ToStdString());
456 mkdir(path.c_str(), 0755);
457 base::StackString<256> sym_path("%s/%s", sym_dir.path().c_str(), name);
458 symlinks_to_delete.push_back(sym_path.ToStdString());
459 symlink(path.c_str(), sym_path.c_str());
460 };
461 auto fake_devfreq = base::TempDir::Create();
462 auto fake_devfreq_symdir = base::TempDir::Create();
463 static const char* const devfreq_names[] = {"10010.devfreq_device_a",
464 "10020.devfreq_device_b"};
465 for (auto dev : devfreq_names) {
466 make_devfreq_paths(fake_devfreq, fake_devfreq_symdir, dev);
467 }
468
469 EXPECT_CALL(*data_source, OpenDevfreqDir())
470 .WillRepeatedly(Invoke([&fake_devfreq_symdir] {
471 return base::ScopedDir(opendir(fake_devfreq_symdir.path().c_str()));
472 }));
473 EXPECT_CALL(*data_source, ReadDevfreqCurFreq("10010.devfreq_device_a"))
474 .WillRepeatedly(Return(kDevfreq1));
475 EXPECT_CALL(*data_source, ReadDevfreqCurFreq("10020.devfreq_device_b"))
476 .WillRepeatedly(Return(kDevfreq2));
477
478 WaitTick(data_source.get());
479
480 protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
481 ASSERT_TRUE(packet.has_sys_stats());
482 const auto& sys_stats = packet.sys_stats();
483 EXPECT_EQ(sys_stats.meminfo_size(), 0);
484 EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
485
486 using KV = std::pair<std::string, uint64_t>;
487 std::vector<KV> kvs;
488 for (const auto& kv : sys_stats.devfreq())
489 kvs.push_back({kv.key(), kv.value()});
490 EXPECT_THAT(kvs,
491 UnorderedElementsAre(KV{"10010.devfreq_device_a", 1000000},
492 KV{"10020.devfreq_device_b", 20000000}));
493 for (const std::string& path : dirs_to_delete)
494 base::Rmdir(path);
495 for (const std::string& path : symlinks_to_delete)
496 remove(path.c_str());
497 }
498
TEST_F(SysStatsDataSourceTest,StatAll)499 TEST_F(SysStatsDataSourceTest, StatAll) {
500 DataSourceConfig config;
501 protos::gen::SysStatsConfig sys_cfg;
502 sys_cfg.set_stat_period_ms(10);
503 config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
504 auto data_source = GetSysStatsDataSource(config);
505
506 WaitTick(data_source.get());
507
508 protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
509 ASSERT_TRUE(packet.has_sys_stats());
510 const auto& sys_stats = packet.sys_stats();
511 EXPECT_EQ(sys_stats.meminfo_size(), 0);
512 EXPECT_EQ(sys_stats.vmstat_size(), 0);
513 EXPECT_EQ(sys_stats.buddy_info_size(), 0);
514
515 ASSERT_EQ(sys_stats.cpu_stat_size(), 8);
516 EXPECT_EQ(sys_stats.cpu_stat()[0].user_ns(), 762178 * 10000000ull);
517 EXPECT_EQ(sys_stats.cpu_stat()[0].system_mode_ns(), 902284 * 10000000ull);
518 EXPECT_EQ(sys_stats.cpu_stat()[0].softirq_ns(), 68262 * 10000000ull);
519 EXPECT_EQ(sys_stats.cpu_stat()[7].user_ns(), 180484 * 10000000ull);
520 EXPECT_EQ(sys_stats.cpu_stat()[7].system_mode_ns(), 139874 * 10000000ull);
521 EXPECT_EQ(sys_stats.cpu_stat()[7].softirq_ns(), 13407 * 10000000ull);
522
523 EXPECT_EQ(sys_stats.num_forks(), 243320u);
524
525 EXPECT_EQ(sys_stats.num_irq_total(), 238128517u);
526 ASSERT_EQ(sys_stats.num_irq_size(), 102);
527 EXPECT_EQ(sys_stats.num_irq()[0].count(), 63500984u);
528 EXPECT_EQ(sys_stats.num_irq()[0].irq(), 3);
529 EXPECT_EQ(sys_stats.num_irq()[1].count(), 6253792u);
530 EXPECT_EQ(sys_stats.num_irq()[1].irq(), 5);
531 EXPECT_EQ(sys_stats.num_irq()[101].count(), 680u);
532
533 EXPECT_EQ(sys_stats.num_softirq_total(), 84611084u);
534 ASSERT_EQ(sys_stats.num_softirq_size(), 10);
535 EXPECT_EQ(sys_stats.num_softirq()[0].count(), 10220177u);
536 EXPECT_EQ(sys_stats.num_softirq()[9].count(), 16443195u);
537
538 EXPECT_EQ(sys_stats.num_softirq_total(), 84611084u);
539 }
540
TEST_F(SysStatsDataSourceTest,StatForksOnly)541 TEST_F(SysStatsDataSourceTest, StatForksOnly) {
542 protos::gen::SysStatsConfig cfg;
543 cfg.set_stat_period_ms(10);
544 cfg.add_stat_counters(protos::gen::SysStatsConfig::STAT_FORK_COUNT);
545 DataSourceConfig config_obj;
546 config_obj.set_sys_stats_config_raw(cfg.SerializeAsString());
547 auto data_source = GetSysStatsDataSource(config_obj);
548
549 WaitTick(data_source.get());
550
551 protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
552 ASSERT_TRUE(packet.has_sys_stats());
553 const auto& sys_stats = packet.sys_stats();
554 EXPECT_EQ(sys_stats.meminfo_size(), 0);
555 EXPECT_EQ(sys_stats.vmstat_size(), 0);
556 EXPECT_EQ(sys_stats.buddy_info_size(), 0);
557 ASSERT_EQ(sys_stats.cpu_stat_size(), 0);
558 EXPECT_EQ(sys_stats.num_forks(), 243320u);
559 EXPECT_EQ(sys_stats.num_irq_total(), 0u);
560 ASSERT_EQ(sys_stats.num_irq_size(), 0);
561 EXPECT_EQ(sys_stats.num_softirq_total(), 0u);
562 ASSERT_EQ(sys_stats.num_softirq_size(), 0);
563 }
564
TEST_F(SysStatsDataSourceTest,Cpufreq)565 TEST_F(SysStatsDataSourceTest, Cpufreq) {
566 protos::gen::SysStatsConfig cfg;
567 cfg.set_cpufreq_period_ms(10);
568 DataSourceConfig config_obj;
569 config_obj.set_sys_stats_config_raw(cfg.SerializeAsString());
570 auto data_source = GetSysStatsDataSource(config_obj);
571
572 WaitTick(data_source.get());
573
574 protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
575 ASSERT_TRUE(packet.has_sys_stats());
576 const auto& sys_stats = packet.sys_stats();
577 EXPECT_GT(sys_stats.cpufreq_khz_size(), 0);
578 EXPECT_EQ(sys_stats.cpufreq_khz()[0], 2650000u);
579 if (sys_stats.cpufreq_khz_size() > 1) {
580 // We emulated 2 CPUs but it is possible the test system is single core.
581 EXPECT_EQ(sys_stats.cpufreq_khz()[1], 3698200u);
582 }
583 for (unsigned int i = 2;
584 i < static_cast<unsigned int>(sys_stats.cpufreq_khz_size()); i++) {
585 // For cpux which scaling_cur_freq was not emulated in unittest, cpufreq
586 // should be recorded as 0
587 EXPECT_EQ(sys_stats.cpufreq_khz()[i], 0u);
588 }
589 }
590
TEST_F(SysStatsDataSourceTest,DiskStat)591 TEST_F(SysStatsDataSourceTest, DiskStat) {
592 protos::gen::SysStatsConfig cfg;
593 cfg.set_diskstat_period_ms(10);
594 DataSourceConfig config_obj;
595 config_obj.set_sys_stats_config_raw(cfg.SerializeAsString());
596 auto data_source = GetSysStatsDataSource(config_obj);
597
598 WaitTick(data_source.get());
599
600 protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
601 ASSERT_TRUE(packet.has_sys_stats());
602 const auto& sys_stats = packet.sys_stats();
603 EXPECT_EQ(sys_stats.disk_stat_size(), 3);
604
605 EXPECT_EQ(sys_stats.disk_stat()[0].device_name(), "zram0");
606 EXPECT_EQ(sys_stats.disk_stat()[0].read_sectors(), 111088u);
607 EXPECT_EQ(sys_stats.disk_stat()[0].write_sectors(), 458384u);
608 EXPECT_EQ(sys_stats.disk_stat()[0].discard_sectors(), 0u);
609 EXPECT_EQ(sys_stats.disk_stat()[0].flush_count(), 0u);
610 EXPECT_EQ(sys_stats.disk_stat()[0].read_time_ms(), 128u);
611 EXPECT_EQ(sys_stats.disk_stat()[0].write_time_ms(), 48u);
612 EXPECT_EQ(sys_stats.disk_stat()[0].discard_time_ms(), 0u);
613 EXPECT_EQ(sys_stats.disk_stat()[0].flush_time_ms(), 0u);
614 EXPECT_EQ(sys_stats.disk_stat()[1].device_name(), "sda");
615 EXPECT_EQ(sys_stats.disk_stat()[1].read_sectors(), 8221736u);
616 EXPECT_EQ(sys_stats.disk_stat()[1].write_sectors(), 9599744u);
617 EXPECT_EQ(sys_stats.disk_stat()[1].discard_sectors(), 2160072u);
618 EXPECT_EQ(sys_stats.disk_stat()[1].flush_count(), 6649u);
619 EXPECT_EQ(sys_stats.disk_stat()[1].read_time_ms(), 75929u);
620 EXPECT_EQ(sys_stats.disk_stat()[1].write_time_ms(), 143190u);
621 EXPECT_EQ(sys_stats.disk_stat()[1].discard_time_ms(), 19411u);
622 EXPECT_EQ(sys_stats.disk_stat()[1].flush_time_ms(), 11327u);
623 EXPECT_EQ(sys_stats.disk_stat()[2].device_name(), "sda1");
624 EXPECT_EQ(sys_stats.disk_stat()[2].read_sectors(), 632u);
625 EXPECT_EQ(sys_stats.disk_stat()[2].write_sectors(), 704u);
626 EXPECT_EQ(sys_stats.disk_stat()[2].discard_sectors(), 0u);
627 EXPECT_EQ(sys_stats.disk_stat()[2].flush_count(), 0u);
628 EXPECT_EQ(sys_stats.disk_stat()[2].read_time_ms(), 7u);
629 EXPECT_EQ(sys_stats.disk_stat()[2].write_time_ms(), 92u);
630 EXPECT_EQ(sys_stats.disk_stat()[2].discard_time_ms(), 0u);
631 EXPECT_EQ(sys_stats.disk_stat()[2].flush_time_ms(), 0u);
632 }
633
TEST_F(SysStatsDataSourceTest,Psi)634 TEST_F(SysStatsDataSourceTest, Psi) {
635 protos::gen::SysStatsConfig cfg;
636 cfg.set_psi_period_ms(10);
637 DataSourceConfig config_obj;
638 config_obj.set_sys_stats_config_raw(cfg.SerializeAsString());
639 auto data_source = GetSysStatsDataSource(config_obj);
640
641 WaitTick(data_source.get());
642
643 protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
644 ASSERT_TRUE(packet.has_sys_stats());
645 const auto& sys_stats = packet.sys_stats();
646 ASSERT_EQ(sys_stats.psi_size(), 6);
647
648 using PsiSample = protos::gen::SysStats::PsiSample;
649 EXPECT_EQ(sys_stats.psi()[0].resource(), PsiSample::PSI_RESOURCE_CPU_SOME);
650 EXPECT_EQ(sys_stats.psi()[0].total_ns(), 417963000u);
651 EXPECT_EQ(sys_stats.psi()[1].resource(), PsiSample::PSI_RESOURCE_CPU_FULL);
652 EXPECT_EQ(sys_stats.psi()[1].total_ns(), 205933000U);
653 EXPECT_EQ(sys_stats.psi()[2].resource(), PsiSample::PSI_RESOURCE_IO_SOME);
654 EXPECT_EQ(sys_stats.psi()[2].total_ns(), 417963000u);
655 EXPECT_EQ(sys_stats.psi()[3].resource(), PsiSample::PSI_RESOURCE_IO_FULL);
656 EXPECT_EQ(sys_stats.psi()[3].total_ns(), 205933000U);
657 EXPECT_EQ(sys_stats.psi()[4].resource(), PsiSample::PSI_RESOURCE_MEMORY_SOME);
658 EXPECT_EQ(sys_stats.psi()[4].total_ns(), 417963000u);
659 EXPECT_EQ(sys_stats.psi()[5].resource(), PsiSample::PSI_RESOURCE_MEMORY_FULL);
660 EXPECT_EQ(sys_stats.psi()[5].total_ns(), 205933000U);
661 }
662
663 } // namespace
664 } // namespace perfetto
665