• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/temp_file.h"
21 #include "src/base/test/test_task_runner.h"
22 #include "src/traced/probes/common/cpu_freq_info_for_testing.h"
23 #include "src/traced/probes/sys_stats/sys_stats_data_source.h"
24 #include "src/tracing/core/trace_writer_for_testing.h"
25 #include "test/gtest_and_gmock.h"
26 
27 #include "protos/perfetto/common/sys_stats_counters.gen.h"
28 #include "protos/perfetto/config/data_source_config.gen.h"
29 #include "protos/perfetto/config/sys_stats/sys_stats_config.gen.h"
30 #include "protos/perfetto/trace/sys_stats/sys_stats.gen.h"
31 
32 using ::testing::_;
33 using ::testing::Invoke;
34 using ::testing::Return;
35 using ::testing::UnorderedElementsAre;
36 
37 namespace perfetto {
38 namespace {
39 
40 const char kMockMeminfo[] = R"(
41 MemTotal:        3744240 kB
42 MemFree:           73328 kB
43 MemAvailable:     629896 kB
44 Buffers:           19296 kB
45 Cached:           731032 kB
46 SwapCached:         4936 kB
47 Active:          1616348 kB
48 Inactive:         745492 kB
49 Active(anon):    1322636 kB
50 Inactive(anon):   449172 kB
51 Active(file):     293712 kB
52 Inactive(file):   296320 kB
53 Unevictable:      142152 kB
54 Mlocked:          142152 kB
55 SwapTotal:        524284 kB
56 SwapFree:            128 kB
57 Dirty:                 0 kB
58 Writeback:             0 kB
59 AnonPages:       1751140 kB
60 Mapped:           508372 kB
61 Shmem:             18604 kB
62 Slab:             240352 kB
63 SReclaimable:      64684 kB
64 SUnreclaim:       175668 kB
65 KernelStack:       62672 kB
66 PageTables:        70108 kB
67 NFS_Unstable:          0 kB
68 Bounce:                0 kB
69 WritebackTmp:          0 kB
70 CommitLimit:     2396404 kB
71 Committed_AS:   81911488 kB
72 VmallocTotal:   258867136 kB
73 VmallocUsed:           0 kB
74 VmallocChunk:          0 kB
75 CmaTotal:         196608 kB
76 CmaFree:              60 kB)";
77 
78 const char kMockVmstat[] = R"(
79 nr_free_pages 16449
80 nr_alloc_batch 79
81 nr_inactive_anon 112545
82 nr_active_anon 322027
83 nr_inactive_file 75904
84 nr_active_file 87939
85 nr_unevictable 35538
86 nr_mlock 35538
87 nr_anon_pages 429005
88 nr_mapped 125844
89 nr_file_pages 205523
90 nr_dirty 23
91 nr_writeback 0
92 nr_slab_reclaimable 15840
93 nr_slab_unreclaimable 43912
94 nr_page_table_pages 17158
95 nr_kernel_stack 3822
96 nr_overhead 0
97 nr_unstable 0
98 nr_bounce 0
99 nr_vmscan_write 558690
100 nr_vmscan_immediate_reclaim 14853
101 nr_writeback_temp 0
102 nr_isolated_anon 0
103 nr_isolated_file 0
104 nr_shmem 5027
105 nr_dirtied 6732417
106 nr_written 6945513
107 nr_pages_scanned 0
108 workingset_refault 32784684
109 workingset_activate 8200928
110 workingset_nodereclaim 0
111 nr_anon_transparent_hugepages 0
112 nr_free_cma 0
113 nr_swapcache 1254
114 nr_dirty_threshold 33922
115 nr_dirty_background_threshold 8449
116 pgpgin 161257156
117 pgpgout 35973852
118 pgpgoutclean 37181384
119 pswpin 185308
120 pswpout 557662
121 pgalloc_dma 79259070
122 pgalloc_normal 88265512
123 pgalloc_movable 0
124 pgfree 175051592
125 pgactivate 11897892
126 pgdeactivate 20412230
127 pgfault 181696234
128 pgmajfault 1060871
129 pgrefill_dma 12970047
130 pgrefill_normal 14391564
131 pgrefill_movable 0
132 pgsteal_kswapd_dma 19471476
133 pgsteal_kswapd_normal 21138380
134 pgsteal_kswapd_movable 0
135 pgsteal_direct 91537
136 pgsteal_direct_dma 40625
137 pgsteal_direct_normal 50912
138 pgsteal_direct_movable 0
139 pgscan_kswapd_dma 23544417
140 pgscan_kswapd_normal 25623715
141 pgscan_kswapd_movable 0
142 pgscan_direct_dma 50369
143 pgscan_direct_normal 66284
144 pgscan_direct_movable 0
145 pgscan_direct_throttle 0
146 pginodesteal 0
147 slabs_scanned 39582828
148 kswapd_inodesteal 110199
149 kswapd_low_wmark_hit_quickly 21321
150 kswapd_high_wmark_hit_quickly 4112
151 pageoutrun 37666
152 allocstall 1587
153 pgrotated 12086
154 drop_pagecache 0
155 drop_slab 0
156 pgmigrate_success 5923482
157 pgmigrate_fail 3439
158 compact_migrate_scanned 92906456
159 compact_free_scanned 467077168
160 compact_isolated 13456528
161 compact_stall 197
162 compact_fail 42
163 compact_success 155
164 compact_daemon_wake 2131
165 unevictable_pgs_culled 50170
166 unevictable_pgs_scanned 0
167 unevictable_pgs_rescued 14640
168 unevictable_pgs_mlocked 52520
169 unevictable_pgs_munlocked 14640
170 unevictable_pgs_cleared 2342
171 unevictable_pgs_stranded 2342)";
172 
173 const char kMockStat[] = R"(
174 cpu  2655987 822682 2352153 8801203 41917 322733 175055 0 0 0
175 cpu0 762178 198125 902284 8678856 41716 152974 68262 0 0 0
176 cpu1 613833 243394 504323 15194 96 60625 28785 0 0 0
177 cpu2 207349 95060 248856 17351 42 32148 26108 0 0 0
178 cpu3 138474 92158 174852 17537 48 25076 25035 0 0 0
179 cpu4 278720 34689 141048 18117 1 20782 5873 0 0 0
180 cpu5 235376 33907 85098 18278 2 10049 3774 0 0 0
181 cpu6 239568 67149 155814 17890 5 11518 3807 0 0 0
182 cpu7 180484 58196 139874 17975 3 9556 13407 0 0 0
183 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
184 ctxt 373122860
185 btime 1536912218
186 processes 243320
187 procs_running 1
188 procs_blocked 0
189 softirq 84611084 10220177 28299167 155083 3035679 6390543 66234 4396819 15604187 0 16443195)";
190 
191 const char kDevfreq1[] = "1000000";
192 const char kDevfreq2[] = "20000000";
193 
194 class TestSysStatsDataSource : public SysStatsDataSource {
195  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)196   TestSysStatsDataSource(base::TaskRunner* task_runner,
197                          TracingSessionID id,
198                          std::unique_ptr<TraceWriter> writer,
199                          const DataSourceConfig& config,
200                          std::unique_ptr<CpuFreqInfo> cpu_freq_info,
201                          OpenFunction open_fn)
202       : SysStatsDataSource(task_runner,
203                            id,
204                            std::move(writer),
205                            config,
206                            std::move(cpu_freq_info),
207                            open_fn) {}
208 
209   MOCK_METHOD0(OpenDevfreqDir, base::ScopedDir());
210   MOCK_METHOD1(ReadDevfreqCurFreq, const char*(const std::string& deviceName));
211 };
212 
MockOpenReadOnly(const char * path)213 base::ScopedFile MockOpenReadOnly(const char* path) {
214   base::TempFile tmp_ = base::TempFile::CreateUnlinked();
215   if (!strcmp(path, "/proc/meminfo")) {
216     EXPECT_GT(pwrite(tmp_.fd(), kMockMeminfo, strlen(kMockMeminfo), 0), 0);
217   } else if (!strcmp(path, "/proc/vmstat")) {
218     EXPECT_GT(pwrite(tmp_.fd(), kMockVmstat, strlen(kMockVmstat), 0), 0);
219   } else if (!strcmp(path, "/proc/stat")) {
220     EXPECT_GT(pwrite(tmp_.fd(), kMockStat, strlen(kMockStat), 0), 0);
221   } else {
222     PERFETTO_FATAL("Unexpected file opened %s", path);
223   }
224   return tmp_.ReleaseFD();
225 }
226 
227 class SysStatsDataSourceTest : public ::testing::Test {
228  protected:
GetSysStatsDataSource(const DataSourceConfig & cfg)229   std::unique_ptr<TestSysStatsDataSource> GetSysStatsDataSource(
230       const DataSourceConfig& cfg) {
231     auto writer =
232         std::unique_ptr<TraceWriterForTesting>(new TraceWriterForTesting());
233     writer_raw_ = writer.get();
234     auto instance =
235         std::unique_ptr<TestSysStatsDataSource>(new TestSysStatsDataSource(
236             &task_runner_, 0, std::move(writer), cfg,
237             cpu_freq_info_for_testing_.GetInstance(), MockOpenReadOnly));
238     instance->set_ns_per_user_hz_for_testing(1000000000ull / 100);  // 100 Hz.
239     instance->Start();
240     return instance;
241   }
242 
Poller(SysStatsDataSource * ds,std::function<void ()> checkpoint)243   void Poller(SysStatsDataSource* ds, std::function<void()> checkpoint) {
244     if (ds->tick_for_testing())
245       checkpoint();
246     else
247       task_runner_.PostDelayedTask(
248           [ds, checkpoint, this] { Poller(ds, checkpoint); }, 1);
249   }
250 
WaitTick(SysStatsDataSource * data_source)251   void WaitTick(SysStatsDataSource* data_source) {
252     auto checkpoint = task_runner_.CreateCheckpoint("on_tick");
253     Poller(data_source, checkpoint);
254     task_runner_.RunUntilCheckpoint("on_tick");
255   }
256 
257   TraceWriterForTesting* writer_raw_ = nullptr;
258   base::TestTaskRunner task_runner_;
259   CpuFreqInfoForTesting cpu_freq_info_for_testing_;
260 };
261 
TEST_F(SysStatsDataSourceTest,Meminfo)262 TEST_F(SysStatsDataSourceTest, Meminfo) {
263   using C = protos::gen::MeminfoCounters;
264   DataSourceConfig config;
265   protos::gen::SysStatsConfig sys_cfg;
266   sys_cfg.set_meminfo_period_ms(10);
267   sys_cfg.add_meminfo_counters(C::MEMINFO_MEM_TOTAL);
268   sys_cfg.add_meminfo_counters(C::MEMINFO_MEM_FREE);
269   sys_cfg.add_meminfo_counters(C::MEMINFO_ACTIVE_ANON);
270   sys_cfg.add_meminfo_counters(C::MEMINFO_INACTIVE_FILE);
271   sys_cfg.add_meminfo_counters(C::MEMINFO_CMA_FREE);
272   config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
273   auto data_source = GetSysStatsDataSource(config);
274 
275   WaitTick(data_source.get());
276 
277   protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
278   ASSERT_TRUE(packet.has_sys_stats());
279   const auto& sys_stats = packet.sys_stats();
280   EXPECT_EQ(sys_stats.vmstat_size(), 0);
281   EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
282   EXPECT_EQ(sys_stats.devfreq_size(), 0);
283 
284   using KV = std::pair<int, uint64_t>;
285   std::vector<KV> kvs;
286   for (const auto& kv : sys_stats.meminfo())
287     kvs.push_back({kv.key(), kv.value()});
288 
289   EXPECT_THAT(kvs,
290               UnorderedElementsAre(KV{C::MEMINFO_MEM_TOTAL, 3744240},     //
291                                    KV{C::MEMINFO_MEM_FREE, 73328},        //
292                                    KV{C::MEMINFO_ACTIVE_ANON, 1322636},   //
293                                    KV{C::MEMINFO_INACTIVE_FILE, 296320},  //
294                                    KV{C::MEMINFO_CMA_FREE, 60}));
295 }
296 
TEST_F(SysStatsDataSourceTest,MeminfoAll)297 TEST_F(SysStatsDataSourceTest, MeminfoAll) {
298   DataSourceConfig config;
299   protos::gen::SysStatsConfig sys_cfg;
300   sys_cfg.set_meminfo_period_ms(10);
301   config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
302   auto data_source = GetSysStatsDataSource(config);
303 
304   WaitTick(data_source.get());
305 
306   protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
307   ASSERT_TRUE(packet.has_sys_stats());
308   const auto& sys_stats = packet.sys_stats();
309   EXPECT_EQ(sys_stats.vmstat_size(), 0);
310   EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
311   EXPECT_EQ(sys_stats.devfreq_size(), 0);
312   EXPECT_GE(sys_stats.meminfo_size(), 10);
313 }
314 
TEST_F(SysStatsDataSourceTest,Vmstat)315 TEST_F(SysStatsDataSourceTest, Vmstat) {
316   using C = protos::gen::VmstatCounters;
317   DataSourceConfig config;
318   protos::gen::SysStatsConfig sys_cfg;
319   sys_cfg.set_vmstat_period_ms(10);
320   sys_cfg.add_vmstat_counters(C::VMSTAT_NR_FREE_PAGES);
321   sys_cfg.add_vmstat_counters(C::VMSTAT_PGACTIVATE);
322   sys_cfg.add_vmstat_counters(C::VMSTAT_PGMIGRATE_FAIL);
323   sys_cfg.add_vmstat_counters(C::VMSTAT_PGSTEAL_DIRECT);
324   config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
325   auto data_source = GetSysStatsDataSource(config);
326 
327   WaitTick(data_source.get());
328 
329   protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
330   ASSERT_TRUE(packet.has_sys_stats());
331   const auto& sys_stats = packet.sys_stats();
332   EXPECT_EQ(sys_stats.meminfo_size(), 0);
333   EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
334   EXPECT_EQ(sys_stats.devfreq_size(), 0);
335 
336   using KV = std::pair<int, uint64_t>;
337   std::vector<KV> kvs;
338   for (const auto& kv : sys_stats.vmstat())
339     kvs.push_back({kv.key(), kv.value()});
340 
341   EXPECT_THAT(kvs, UnorderedElementsAre(KV{C::VMSTAT_NR_FREE_PAGES, 16449},  //
342                                         KV{C::VMSTAT_PGACTIVATE, 11897892},  //
343                                         KV{C::VMSTAT_PGMIGRATE_FAIL, 3439},  //
344                                         KV{C::VMSTAT_PGSTEAL_DIRECT, 91537}  //
345                                         ));
346 }
347 
TEST_F(SysStatsDataSourceTest,VmstatAll)348 TEST_F(SysStatsDataSourceTest, VmstatAll) {
349   DataSourceConfig config;
350   protos::gen::SysStatsConfig sys_cfg;
351   sys_cfg.set_vmstat_period_ms(10);
352   config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
353   auto data_source = GetSysStatsDataSource(config);
354 
355   WaitTick(data_source.get());
356 
357   protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
358   ASSERT_TRUE(packet.has_sys_stats());
359   const auto& sys_stats = packet.sys_stats();
360   EXPECT_EQ(sys_stats.meminfo_size(), 0);
361   EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
362   EXPECT_EQ(sys_stats.devfreq_size(), 0);
363   EXPECT_GE(sys_stats.vmstat_size(), 10);
364 }
365 
TEST_F(SysStatsDataSourceTest,DevfreqAll)366 TEST_F(SysStatsDataSourceTest, DevfreqAll) {
367   DataSourceConfig config;
368   protos::gen::SysStatsConfig sys_cfg;
369   sys_cfg.set_devfreq_period_ms(10);
370   config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
371   auto data_source = GetSysStatsDataSource(config);
372 
373   // Create dirs and symlinks, but only read the symlinks.
374   std::vector<std::string> dirs_to_delete;
375   std::vector<std::string> symlinks_to_delete;
376   auto make_devfreq_paths = [&symlinks_to_delete, &dirs_to_delete](
377                                 base::TempDir& temp_dir, base::TempDir& sym_dir,
378                                 const char* name) {
379     char path[256];
380     sprintf(path, "%s/%s", temp_dir.path().c_str(), name);
381     dirs_to_delete.push_back(path);
382     mkdir(path, 0755);
383     char sym_path[256];
384     sprintf(sym_path, "%s/%s", sym_dir.path().c_str(), name);
385     symlinks_to_delete.push_back(sym_path);
386     symlink(path, sym_path);
387   };
388   auto fake_devfreq = base::TempDir::Create();
389   auto fake_devfreq_symdir = base::TempDir::Create();
390   static const char* const devfreq_names[] = {"10010.devfreq_device_a",
391                                               "10020.devfreq_device_b"};
392   for (auto dev : devfreq_names) {
393     make_devfreq_paths(fake_devfreq, fake_devfreq_symdir, dev);
394   }
395 
396   EXPECT_CALL(*data_source, OpenDevfreqDir())
397       .WillRepeatedly(Invoke([&fake_devfreq_symdir] {
398         return base::ScopedDir(opendir(fake_devfreq_symdir.path().c_str()));
399       }));
400   EXPECT_CALL(*data_source, ReadDevfreqCurFreq("10010.devfreq_device_a"))
401       .WillRepeatedly(Return(kDevfreq1));
402   EXPECT_CALL(*data_source, ReadDevfreqCurFreq("10020.devfreq_device_b"))
403       .WillRepeatedly(Return(kDevfreq2));
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 
413   using KV = std::pair<std::string, uint64_t>;
414   std::vector<KV> kvs;
415   for (const auto& kv : sys_stats.devfreq())
416     kvs.push_back({kv.key(), kv.value()});
417   EXPECT_THAT(kvs,
418               UnorderedElementsAre(KV{"10010.devfreq_device_a", 1000000},
419                                    KV{"10020.devfreq_device_b", 20000000}));
420   for (const std::string& path : dirs_to_delete)
421     base::Rmdir(path);
422   for (const std::string& path : symlinks_to_delete)
423     remove(path.c_str());
424 }
425 
TEST_F(SysStatsDataSourceTest,StatAll)426 TEST_F(SysStatsDataSourceTest, StatAll) {
427   DataSourceConfig config;
428   protos::gen::SysStatsConfig sys_cfg;
429   sys_cfg.set_stat_period_ms(10);
430   config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
431   auto data_source = GetSysStatsDataSource(config);
432 
433   WaitTick(data_source.get());
434 
435   protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
436   ASSERT_TRUE(packet.has_sys_stats());
437   const auto& sys_stats = packet.sys_stats();
438   EXPECT_EQ(sys_stats.meminfo_size(), 0);
439   EXPECT_EQ(sys_stats.vmstat_size(), 0);
440 
441   ASSERT_EQ(sys_stats.cpu_stat_size(), 8);
442   EXPECT_EQ(sys_stats.cpu_stat()[0].user_ns(), 762178 * 10000000ull);
443   EXPECT_EQ(sys_stats.cpu_stat()[0].system_mode_ns(), 902284 * 10000000ull);
444   EXPECT_EQ(sys_stats.cpu_stat()[0].softirq_ns(), 68262 * 10000000ull);
445   EXPECT_EQ(sys_stats.cpu_stat()[7].user_ns(), 180484 * 10000000ull);
446   EXPECT_EQ(sys_stats.cpu_stat()[7].system_mode_ns(), 139874 * 10000000ull);
447   EXPECT_EQ(sys_stats.cpu_stat()[7].softirq_ns(), 13407 * 10000000ull);
448 
449   EXPECT_EQ(sys_stats.num_forks(), 243320u);
450 
451   EXPECT_EQ(sys_stats.num_irq_total(), 238128517u);
452   ASSERT_EQ(sys_stats.num_irq_size(), 102);
453   EXPECT_EQ(sys_stats.num_irq()[0].count(), 63500984u);
454   EXPECT_EQ(sys_stats.num_irq()[0].irq(), 3);
455   EXPECT_EQ(sys_stats.num_irq()[1].count(), 6253792u);
456   EXPECT_EQ(sys_stats.num_irq()[1].irq(), 5);
457   EXPECT_EQ(sys_stats.num_irq()[101].count(), 680u);
458 
459   EXPECT_EQ(sys_stats.num_softirq_total(), 84611084u);
460   ASSERT_EQ(sys_stats.num_softirq_size(), 10);
461   EXPECT_EQ(sys_stats.num_softirq()[0].count(), 10220177u);
462   EXPECT_EQ(sys_stats.num_softirq()[9].count(), 16443195u);
463 
464   EXPECT_EQ(sys_stats.num_softirq_total(), 84611084u);
465 }
466 
TEST_F(SysStatsDataSourceTest,StatForksOnly)467 TEST_F(SysStatsDataSourceTest, StatForksOnly) {
468   protos::gen::SysStatsConfig cfg;
469   cfg.set_stat_period_ms(10);
470   cfg.add_stat_counters(protos::gen::SysStatsConfig::STAT_FORK_COUNT);
471   DataSourceConfig config_obj;
472   config_obj.set_sys_stats_config_raw(cfg.SerializeAsString());
473   auto data_source = GetSysStatsDataSource(config_obj);
474 
475   WaitTick(data_source.get());
476 
477   protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
478   ASSERT_TRUE(packet.has_sys_stats());
479   const auto& sys_stats = packet.sys_stats();
480   EXPECT_EQ(sys_stats.meminfo_size(), 0);
481   EXPECT_EQ(sys_stats.vmstat_size(), 0);
482   ASSERT_EQ(sys_stats.cpu_stat_size(), 0);
483   EXPECT_EQ(sys_stats.num_forks(), 243320u);
484   EXPECT_EQ(sys_stats.num_irq_total(), 0u);
485   ASSERT_EQ(sys_stats.num_irq_size(), 0);
486   EXPECT_EQ(sys_stats.num_softirq_total(), 0u);
487   ASSERT_EQ(sys_stats.num_softirq_size(), 0);
488 }
489 
TEST_F(SysStatsDataSourceTest,Cpufreq)490 TEST_F(SysStatsDataSourceTest, Cpufreq) {
491   protos::gen::SysStatsConfig cfg;
492   cfg.set_cpufreq_period_ms(10);
493   DataSourceConfig config_obj;
494   config_obj.set_sys_stats_config_raw(cfg.SerializeAsString());
495   auto data_source = GetSysStatsDataSource(config_obj);
496 
497   WaitTick(data_source.get());
498 
499   protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
500   ASSERT_TRUE(packet.has_sys_stats());
501   const auto& sys_stats = packet.sys_stats();
502   EXPECT_GT(sys_stats.cpufreq_khz_size(), 0);
503   EXPECT_EQ(sys_stats.cpufreq_khz()[0], 2650000u);
504   if (sys_stats.cpufreq_khz_size() > 1) {
505     // We emulated 2 CPUs but it is possible the test system is single core.
506     EXPECT_EQ(sys_stats.cpufreq_khz()[1], 3698200u);
507   }
508   for (unsigned int i = 2;
509        i < static_cast<unsigned int>(sys_stats.cpufreq_khz_size()); i++) {
510     // For cpux which scaling_cur_freq was not emulated in unittest, cpufreq
511     // should be recorded as 0
512     EXPECT_EQ(sys_stats.cpufreq_khz()[i], 0u);
513   }
514 }
515 
516 }  // namespace
517 }  // namespace perfetto
518