blob: eb47417bd89a64920bb0ac9ea0ac9f6ebc1836ff [file] [log] [blame]
[email protected]669a09332013-08-30 22:59:141// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/process/process_metrics.h"
6
avibeced7c2015-12-24 06:47:597#include <stddef.h>
8#include <stdint.h>
9
Peter Boström6b701822021-04-15 03:53:0810#include <memory>
[email protected]669a09332013-08-30 22:59:1411#include <sstream>
12#include <string>
Benoit Lize448ee882017-08-31 13:32:1213#include <vector>
[email protected]669a09332013-08-30 22:59:1414
afakhry8c03da072015-12-03 01:26:1915#include "base/bind.h"
thestigcf4c85b2015-12-16 08:33:3016#include "base/command_line.h"
17#include "base/files/file.h"
18#include "base/files/file_util.h"
19#include "base/files/scoped_temp_dir.h"
arthursonzogni38d9bf472019-04-15 13:00:1120#include "base/memory/shared_memory_mapping.h"
21#include "base/memory/writable_shared_memory_region.h"
Anton Bikineeva61fb572020-10-18 08:54:4422#include "base/ranges/algorithm.h"
afakhry8c03da072015-12-03 01:26:1923#include "base/strings/string_number_conversions.h"
Eric Secklerdbc29da2020-07-10 11:54:0524#include "base/strings/string_util.h"
Robert Sesek3aff3362019-01-23 20:16:1625#include "base/strings/stringprintf.h"
Sebastien Marchand75a7cdf2018-11-13 23:47:0326#include "base/system/sys_info.h"
thestigcf4c85b2015-12-16 08:33:3027#include "base/test/multiprocess_test.h"
[email protected]cf46e3752013-12-02 01:01:0128#include "base/threading/thread.h"
avibeced7c2015-12-24 06:47:5929#include "build/build_config.h"
Hidehiko Abe7c68f582020-09-03 15:47:2530#include "build/chromeos_buildflags.h"
[email protected]669a09332013-08-30 22:59:1431#include "testing/gtest/include/gtest/gtest.h"
thestigcf4c85b2015-12-16 08:33:3032#include "testing/multiprocess_func_list.h"
[email protected]669a09332013-08-30 22:59:1433
Xiaohan Wang37e81612022-01-15 18:27:0034#if BUILDFLAG(IS_APPLE)
erikchen863e4742017-03-31 19:57:4335#include <sys/mman.h>
36#endif
37
Xiaohan Wang37e81612022-01-15 18:27:0038#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
Eric Secklerdbc29da2020-07-10 11:54:0539#include "base/process/internal_linux.h"
40#endif
41
[email protected]669a09332013-08-30 22:59:1442namespace base {
43namespace debug {
44
Xiaohan Wang37e81612022-01-15 18:27:0045#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
46 BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_WIN) || \
47 BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
Fabrice de Gans4072fcf2021-08-20 21:35:2948
afakhry8c03da072015-12-03 01:26:1949namespace {
50
51void BusyWork(std::vector<std::string>* vec) {
52 int64_t test_value = 0;
53 for (int i = 0; i < 100000; ++i) {
54 ++test_value;
Raul Tambrea9c13642019-03-25 13:34:4255 vec->push_back(NumberToString(test_value));
afakhry8c03da072015-12-03 01:26:1956 }
57}
58
59} // namespace
Fabrice de Gans4072fcf2021-08-20 21:35:2960
Xiaohan Wang37e81612022-01-15 18:27:0061#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
62 // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_WIN) ||
63 // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
afakhry8c03da072015-12-03 01:26:1964
[email protected]669a09332013-08-30 22:59:1465// Tests for SystemMetrics.
66// Exists as a class so it can be a friend of SystemMetrics.
67class SystemMetricsTest : public testing::Test {
68 public:
Chris Watkinsbb7211c2017-11-29 07:16:3869 SystemMetricsTest() = default;
[email protected]669a09332013-08-30 22:59:1470
Peter Boström75cd3c02021-09-28 15:23:1871 SystemMetricsTest(const SystemMetricsTest&) = delete;
72 SystemMetricsTest& operator=(const SystemMetricsTest&) = delete;
[email protected]669a09332013-08-30 22:59:1473};
74
Xiaohan Wang37e81612022-01-15 18:27:0075#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
[email protected]669a09332013-08-30 22:59:1476TEST_F(SystemMetricsTest, IsValidDiskName) {
Lei Zhang912563e2017-07-20 16:49:5877 const char invalid_input1[] = "";
78 const char invalid_input2[] = "s";
79 const char invalid_input3[] = "sdz+";
80 const char invalid_input4[] = "hda0";
81 const char invalid_input5[] = "mmcbl";
82 const char invalid_input6[] = "mmcblka";
83 const char invalid_input7[] = "mmcblkb";
84 const char invalid_input8[] = "mmmblk0";
[email protected]669a09332013-08-30 22:59:1485
86 EXPECT_FALSE(IsValidDiskName(invalid_input1));
87 EXPECT_FALSE(IsValidDiskName(invalid_input2));
88 EXPECT_FALSE(IsValidDiskName(invalid_input3));
89 EXPECT_FALSE(IsValidDiskName(invalid_input4));
90 EXPECT_FALSE(IsValidDiskName(invalid_input5));
91 EXPECT_FALSE(IsValidDiskName(invalid_input6));
92 EXPECT_FALSE(IsValidDiskName(invalid_input7));
93 EXPECT_FALSE(IsValidDiskName(invalid_input8));
94
Lei Zhang912563e2017-07-20 16:49:5895 const char valid_input1[] = "sda";
96 const char valid_input2[] = "sdaaaa";
97 const char valid_input3[] = "hdz";
98 const char valid_input4[] = "mmcblk0";
99 const char valid_input5[] = "mmcblk999";
[email protected]669a09332013-08-30 22:59:14100
101 EXPECT_TRUE(IsValidDiskName(valid_input1));
102 EXPECT_TRUE(IsValidDiskName(valid_input2));
103 EXPECT_TRUE(IsValidDiskName(valid_input3));
104 EXPECT_TRUE(IsValidDiskName(valid_input4));
105 EXPECT_TRUE(IsValidDiskName(valid_input5));
106}
[email protected]ded8c42b2013-11-05 22:15:03107
108TEST_F(SystemMetricsTest, ParseMeminfo) {
Lei Zhang912563e2017-07-20 16:49:58109 SystemMemoryInfoKB meminfo;
110 const char invalid_input1[] = "abc";
111 const char invalid_input2[] = "MemTotal:";
[email protected]ded8c42b2013-11-05 22:15:03112 // Partial file with no MemTotal
Lei Zhang912563e2017-07-20 16:49:58113 const char invalid_input3[] =
114 "MemFree: 3913968 kB\n"
115 "Buffers: 2348340 kB\n"
116 "Cached: 49071596 kB\n"
117 "SwapCached: 12 kB\n"
118 "Active: 36393900 kB\n"
119 "Inactive: 21221496 kB\n"
120 "Active(anon): 5674352 kB\n"
121 "Inactive(anon): 633992 kB\n";
[email protected]ded8c42b2013-11-05 22:15:03122 EXPECT_FALSE(ParseProcMeminfo(invalid_input1, &meminfo));
123 EXPECT_FALSE(ParseProcMeminfo(invalid_input2, &meminfo));
124 EXPECT_FALSE(ParseProcMeminfo(invalid_input3, &meminfo));
125
Lei Zhang912563e2017-07-20 16:49:58126 const char valid_input1[] =
127 "MemTotal: 3981504 kB\n"
128 "MemFree: 140764 kB\n"
129 "MemAvailable: 535413 kB\n"
130 "Buffers: 116480 kB\n"
131 "Cached: 406160 kB\n"
132 "SwapCached: 21304 kB\n"
133 "Active: 3152040 kB\n"
134 "Inactive: 472856 kB\n"
135 "Active(anon): 2972352 kB\n"
136 "Inactive(anon): 270108 kB\n"
137 "Active(file): 179688 kB\n"
138 "Inactive(file): 202748 kB\n"
139 "Unevictable: 0 kB\n"
140 "Mlocked: 0 kB\n"
141 "SwapTotal: 5832280 kB\n"
142 "SwapFree: 3672368 kB\n"
143 "Dirty: 184 kB\n"
144 "Writeback: 0 kB\n"
145 "AnonPages: 3101224 kB\n"
146 "Mapped: 142296 kB\n"
147 "Shmem: 140204 kB\n"
148 "Slab: 54212 kB\n"
149 "SReclaimable: 30936 kB\n"
150 "SUnreclaim: 23276 kB\n"
151 "KernelStack: 2464 kB\n"
152 "PageTables: 24812 kB\n"
153 "NFS_Unstable: 0 kB\n"
154 "Bounce: 0 kB\n"
155 "WritebackTmp: 0 kB\n"
156 "CommitLimit: 7823032 kB\n"
157 "Committed_AS: 7973536 kB\n"
158 "VmallocTotal: 34359738367 kB\n"
159 "VmallocUsed: 375940 kB\n"
160 "VmallocChunk: 34359361127 kB\n"
161 "DirectMap4k: 72448 kB\n"
162 "DirectMap2M: 4061184 kB\n";
[email protected]ded8c42b2013-11-05 22:15:03163 // output from a much older kernel where the Active and Inactive aren't
164 // broken down into anon and file and Huge Pages are enabled
Lei Zhang912563e2017-07-20 16:49:58165 const char valid_input2[] =
166 "MemTotal: 255908 kB\n"
167 "MemFree: 69936 kB\n"
168 "Buffers: 15812 kB\n"
169 "Cached: 115124 kB\n"
170 "SwapCached: 0 kB\n"
171 "Active: 92700 kB\n"
172 "Inactive: 63792 kB\n"
173 "HighTotal: 0 kB\n"
174 "HighFree: 0 kB\n"
175 "LowTotal: 255908 kB\n"
176 "LowFree: 69936 kB\n"
177 "SwapTotal: 524280 kB\n"
178 "SwapFree: 524200 kB\n"
179 "Dirty: 4 kB\n"
180 "Writeback: 0 kB\n"
181 "Mapped: 42236 kB\n"
182 "Slab: 25912 kB\n"
183 "Committed_AS: 118680 kB\n"
184 "PageTables: 1236 kB\n"
185 "VmallocTotal: 3874808 kB\n"
186 "VmallocUsed: 1416 kB\n"
187 "VmallocChunk: 3872908 kB\n"
188 "HugePages_Total: 0\n"
189 "HugePages_Free: 0\n"
190 "Hugepagesize: 4096 kB\n";
[email protected]ded8c42b2013-11-05 22:15:03191
192 EXPECT_TRUE(ParseProcMeminfo(valid_input1, &meminfo));
danakj94219a212015-03-09 22:27:25193 EXPECT_EQ(meminfo.total, 3981504);
194 EXPECT_EQ(meminfo.free, 140764);
mkolom01ac10b2017-03-22 01:47:29195 EXPECT_EQ(meminfo.available, 535413);
danakj94219a212015-03-09 22:27:25196 EXPECT_EQ(meminfo.buffers, 116480);
197 EXPECT_EQ(meminfo.cached, 406160);
198 EXPECT_EQ(meminfo.active_anon, 2972352);
199 EXPECT_EQ(meminfo.active_file, 179688);
200 EXPECT_EQ(meminfo.inactive_anon, 270108);
201 EXPECT_EQ(meminfo.inactive_file, 202748);
202 EXPECT_EQ(meminfo.swap_total, 5832280);
203 EXPECT_EQ(meminfo.swap_free, 3672368);
204 EXPECT_EQ(meminfo.dirty, 184);
mkolom01ac10b2017-03-22 01:47:29205 EXPECT_EQ(meminfo.reclaimable, 30936);
Yuta Hijikata000df18f2020-11-18 06:55:58206#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
danakj94219a212015-03-09 22:27:25207 EXPECT_EQ(meminfo.shmem, 140204);
208 EXPECT_EQ(meminfo.slab, 54212);
[email protected]ded8c42b2013-11-05 22:15:03209#endif
mkolom01ac10b2017-03-22 01:47:29210 EXPECT_EQ(355725,
211 base::SysInfo::AmountOfAvailablePhysicalMemory(meminfo) / 1024);
212 // Simulate as if there is no MemAvailable.
213 meminfo.available = 0;
214 EXPECT_EQ(374448,
215 base::SysInfo::AmountOfAvailablePhysicalMemory(meminfo) / 1024);
216 meminfo = {};
[email protected]ded8c42b2013-11-05 22:15:03217 EXPECT_TRUE(ParseProcMeminfo(valid_input2, &meminfo));
danakj94219a212015-03-09 22:27:25218 EXPECT_EQ(meminfo.total, 255908);
219 EXPECT_EQ(meminfo.free, 69936);
mkolom01ac10b2017-03-22 01:47:29220 EXPECT_EQ(meminfo.available, 0);
danakj94219a212015-03-09 22:27:25221 EXPECT_EQ(meminfo.buffers, 15812);
222 EXPECT_EQ(meminfo.cached, 115124);
223 EXPECT_EQ(meminfo.swap_total, 524280);
224 EXPECT_EQ(meminfo.swap_free, 524200);
225 EXPECT_EQ(meminfo.dirty, 4);
mkolom01ac10b2017-03-22 01:47:29226 EXPECT_EQ(69936,
227 base::SysInfo::AmountOfAvailablePhysicalMemory(meminfo) / 1024);
[email protected]ded8c42b2013-11-05 22:15:03228}
229
230TEST_F(SystemMetricsTest, ParseVmstat) {
Kenichi Ishibashi44871522017-10-23 07:12:19231 VmStatInfo vmstat;
Kuo-Hsin Yanga141f592020-09-10 07:09:33232 // Part of vmstat from a 4.19 kernel.
Lei Zhang912563e2017-07-20 16:49:58233 const char valid_input1[] =
Kuo-Hsin Yanga141f592020-09-10 07:09:33234 "pgpgin 2358216\n"
235 "pgpgout 296072\n"
236 "pswpin 345219\n"
237 "pswpout 2605828\n"
238 "pgalloc_dma32 8380235\n"
239 "pgalloc_normal 3384525\n"
Lei Zhang912563e2017-07-20 16:49:58240 "pgalloc_movable 0\n"
Kuo-Hsin Yanga141f592020-09-10 07:09:33241 "allocstall_dma32 0\n"
242 "allocstall_normal 2028\n"
243 "allocstall_movable 32559\n"
244 "pgskip_dma32 0\n"
245 "pgskip_normal 0\n"
246 "pgskip_movable 0\n"
247 "pgfree 11802722\n"
248 "pgactivate 894917\n"
249 "pgdeactivate 3255711\n"
250 "pglazyfree 48\n"
251 "pgfault 10043657\n"
252 "pgmajfault 358901\n"
253 "pgmajfault_s 2100\n"
254 "pgmajfault_a 343211\n"
255 "pgmajfault_f 13590\n"
256 "pglazyfreed 0\n"
257 "pgrefill 3429488\n"
258 "pgsteal_kswapd 1466893\n"
259 "pgsteal_direct 1771759\n"
260 "pgscan_kswapd 1907332\n"
261 "pgscan_direct 2118930\n"
262 "pgscan_direct_throttle 154\n"
263 "pginodesteal 3176\n"
264 "slabs_scanned 293804\n"
265 "kswapd_inodesteal 16753\n"
266 "kswapd_low_wmark_hit_quickly 10\n"
267 "kswapd_high_wmark_hit_quickly 423\n"
268 "pageoutrun 441\n"
269 "pgrotated 1636\n"
270 "drop_pagecache 0\n"
271 "drop_slab 0\n"
272 "oom_kill 18\n";
Lei Zhang912563e2017-07-20 16:49:58273 const char valid_input2[] =
Kuo-Hsin Yanga141f592020-09-10 07:09:33274 "pgpgin 2606135\n"
275 "pgpgout 1359128\n"
276 "pswpin 899959\n"
277 "pswpout 19761244\n"
278 "pgalloc_dma 31\n"
279 "pgalloc_dma32 18139339\n"
280 "pgalloc_normal 44085950\n"
281 "pgalloc_movable 0\n"
282 "allocstall_dma 0\n"
283 "allocstall_dma32 0\n"
284 "allocstall_normal 18881\n"
285 "allocstall_movable 169527\n"
286 "pgskip_dma 0\n"
287 "pgskip_dma32 0\n"
288 "pgskip_normal 0\n"
289 "pgskip_movable 0\n"
290 "pgfree 63060999\n"
291 "pgactivate 1703494\n"
292 "pgdeactivate 20537803\n"
293 "pglazyfree 163\n"
294 "pgfault 45201169\n"
295 "pgmajfault 609626\n"
296 "pgmajfault_s 7488\n"
297 "pgmajfault_a 591793\n"
298 "pgmajfault_f 10345\n"
299 "pglazyfreed 0\n"
300 "pgrefill 20673453\n"
301 "pgsteal_kswapd 11802772\n"
302 "pgsteal_direct 8618160\n"
303 "pgscan_kswapd 12640517\n"
304 "pgscan_direct 9092230\n"
305 "pgscan_direct_throttle 638\n"
306 "pginodesteal 1716\n"
307 "slabs_scanned 2594642\n"
308 "kswapd_inodesteal 67358\n"
309 "kswapd_low_wmark_hit_quickly 52\n"
310 "kswapd_high_wmark_hit_quickly 11\n"
311 "pageoutrun 83\n"
312 "pgrotated 977\n"
313 "drop_pagecache 1\n"
314 "drop_slab 1\n"
315 "oom_kill 1\n"
316 "pgmigrate_success 3202\n"
317 "pgmigrate_fail 795\n";
318 const char valid_input3[] =
Lei Zhang912563e2017-07-20 16:49:58319 "pswpin 12\n"
320 "pswpout 901\n"
Kuo-Hsin Yanga141f592020-09-10 07:09:33321 "pgmajfault 18881\n";
Kenichi Ishibashi44871522017-10-23 07:12:19322 EXPECT_TRUE(ParseProcVmstat(valid_input1, &vmstat));
Kuo-Hsin Yanga141f592020-09-10 07:09:33323 EXPECT_EQ(345219LU, vmstat.pswpin);
324 EXPECT_EQ(2605828LU, vmstat.pswpout);
325 EXPECT_EQ(358901LU, vmstat.pgmajfault);
326 EXPECT_EQ(18LU, vmstat.oom_kill);
Kenichi Ishibashi44871522017-10-23 07:12:19327 EXPECT_TRUE(ParseProcVmstat(valid_input2, &vmstat));
Kuo-Hsin Yanga141f592020-09-10 07:09:33328 EXPECT_EQ(899959LU, vmstat.pswpin);
329 EXPECT_EQ(19761244LU, vmstat.pswpout);
330 EXPECT_EQ(609626LU, vmstat.pgmajfault);
331 EXPECT_EQ(1LU, vmstat.oom_kill);
332 EXPECT_TRUE(ParseProcVmstat(valid_input3, &vmstat));
Kenichi Ishibashi44871522017-10-23 07:12:19333 EXPECT_EQ(12LU, vmstat.pswpin);
334 EXPECT_EQ(901LU, vmstat.pswpout);
Kuo-Hsin Yanga141f592020-09-10 07:09:33335 EXPECT_EQ(18881LU, vmstat.pgmajfault);
336 EXPECT_EQ(0LU, vmstat.oom_kill);
Lei Zhang912563e2017-07-20 16:49:58337
338 const char missing_pgmajfault_input[] =
339 "pswpin 12\n"
340 "pswpout 901\n";
Kenichi Ishibashi44871522017-10-23 07:12:19341 EXPECT_FALSE(ParseProcVmstat(missing_pgmajfault_input, &vmstat));
Lei Zhang912563e2017-07-20 16:49:58342 const char empty_input[] = "";
Kenichi Ishibashi44871522017-10-23 07:12:19343 EXPECT_FALSE(ParseProcVmstat(empty_input, &vmstat));
[email protected]ded8c42b2013-11-05 22:15:03344}
Xiaohan Wang37e81612022-01-15 18:27:00345#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
346 // BUILDFLAG(IS_ANDROID)
[email protected]669a09332013-08-30 22:59:14347
Xiaohan Wang37e81612022-01-15 18:27:00348#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
349 BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_WIN) || \
350 BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
afakhry8c03da072015-12-03 01:26:19351
Wez4ae8f292017-09-11 20:52:03352// Test that ProcessMetrics::GetPlatformIndependentCPUUsage() doesn't return
353// negative values when the number of threads running on the process decreases
354// between two successive calls to it.
afakhry8c03da072015-12-03 01:26:19355TEST_F(SystemMetricsTest, TestNoNegativeCpuUsage) {
thestigcf4c85b2015-12-16 08:33:30356 ProcessHandle handle = GetCurrentProcessHandle();
dcheng093de9b2016-04-04 21:25:51357 std::unique_ptr<ProcessMetrics> metrics(
afakhry8c03da072015-12-03 01:26:19358 ProcessMetrics::CreateProcessMetrics(handle));
359
Wez4ae8f292017-09-11 20:52:03360 EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
afakhry8c03da072015-12-03 01:26:19361 Thread thread1("thread1");
362 Thread thread2("thread2");
363 Thread thread3("thread3");
364
365 thread1.StartAndWaitForTesting();
366 thread2.StartAndWaitForTesting();
367 thread3.StartAndWaitForTesting();
368
369 ASSERT_TRUE(thread1.IsRunning());
370 ASSERT_TRUE(thread2.IsRunning());
371 ASSERT_TRUE(thread3.IsRunning());
372
373 std::vector<std::string> vec1;
374 std::vector<std::string> vec2;
375 std::vector<std::string> vec3;
376
tzik92b7a422017-04-11 15:00:44377 thread1.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec1));
378 thread2.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec2));
379 thread3.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec3));
afakhry8c03da072015-12-03 01:26:19380
Sigurdur Asgeirssoneb27eae72018-05-16 15:29:10381 TimeDelta prev_cpu_usage = metrics->GetCumulativeCPUUsage();
382 EXPECT_GE(prev_cpu_usage, TimeDelta());
Wez4ae8f292017-09-11 20:52:03383 EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
afakhry8c03da072015-12-03 01:26:19384
385 thread1.Stop();
Sigurdur Asgeirssoneb27eae72018-05-16 15:29:10386 TimeDelta current_cpu_usage = metrics->GetCumulativeCPUUsage();
387 EXPECT_GE(current_cpu_usage, prev_cpu_usage);
388 prev_cpu_usage = current_cpu_usage;
Wez4ae8f292017-09-11 20:52:03389 EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
afakhry8c03da072015-12-03 01:26:19390
391 thread2.Stop();
Sigurdur Asgeirssoneb27eae72018-05-16 15:29:10392 current_cpu_usage = metrics->GetCumulativeCPUUsage();
393 EXPECT_GE(current_cpu_usage, prev_cpu_usage);
394 prev_cpu_usage = current_cpu_usage;
Wez4ae8f292017-09-11 20:52:03395 EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
afakhry8c03da072015-12-03 01:26:19396
397 thread3.Stop();
Sigurdur Asgeirssoneb27eae72018-05-16 15:29:10398 current_cpu_usage = metrics->GetCumulativeCPUUsage();
399 EXPECT_GE(current_cpu_usage, prev_cpu_usage);
Wez4ae8f292017-09-11 20:52:03400 EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
afakhry8c03da072015-12-03 01:26:19401}
402
Xiaohan Wang37e81612022-01-15 18:27:00403#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
404 // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_WIN) ||
405 // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
afakhry8c03da072015-12-03 01:26:19406
Yuta Hijikata000df18f2020-11-18 06:55:58407#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
Chung-Sheng Wu838f843b2017-07-21 04:17:58408TEST_F(SystemMetricsTest, ParseZramMmStat) {
409 SwapInfo swapinfo;
410
411 const char invalid_input1[] = "aaa";
412 const char invalid_input2[] = "1 2 3 4 5 6";
413 const char invalid_input3[] = "a 2 3 4 5 6 7";
414 EXPECT_FALSE(ParseZramMmStat(invalid_input1, &swapinfo));
415 EXPECT_FALSE(ParseZramMmStat(invalid_input2, &swapinfo));
416 EXPECT_FALSE(ParseZramMmStat(invalid_input3, &swapinfo));
417
418 const char valid_input1[] =
419 "17715200 5008166 566062 0 1225715712 127 183842";
420 EXPECT_TRUE(ParseZramMmStat(valid_input1, &swapinfo));
421 EXPECT_EQ(17715200ULL, swapinfo.orig_data_size);
422 EXPECT_EQ(5008166ULL, swapinfo.compr_data_size);
423 EXPECT_EQ(566062ULL, swapinfo.mem_used_total);
424}
425
426TEST_F(SystemMetricsTest, ParseZramStat) {
427 SwapInfo swapinfo;
428
429 const char invalid_input1[] = "aaa";
430 const char invalid_input2[] = "1 2 3 4 5 6 7 8 9 10";
431 const char invalid_input3[] = "a 2 3 4 5 6 7 8 9 10 11";
432 EXPECT_FALSE(ParseZramStat(invalid_input1, &swapinfo));
433 EXPECT_FALSE(ParseZramStat(invalid_input2, &swapinfo));
434 EXPECT_FALSE(ParseZramStat(invalid_input3, &swapinfo));
435
436 const char valid_input1[] =
437 "299 0 2392 0 1 0 8 0 0 0 0";
438 EXPECT_TRUE(ParseZramStat(valid_input1, &swapinfo));
439 EXPECT_EQ(299ULL, swapinfo.num_reads);
440 EXPECT_EQ(1ULL, swapinfo.num_writes);
441}
Yuta Hijikata000df18f2020-11-18 06:55:58442#endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
Chung-Sheng Wu838f843b2017-07-21 04:17:58443
Xiaohan Wang37e81612022-01-15 18:27:00444#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \
445 BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
Sonny Rao81a33e82020-02-13 19:30:26446TEST(SystemMetrics2Test, GetSystemMemoryInfo) {
thestigcf4c85b2015-12-16 08:33:30447 SystemMemoryInfoKB info;
448 EXPECT_TRUE(GetSystemMemoryInfo(&info));
[email protected]cf46e3752013-12-02 01:01:01449
450 // Ensure each field received a value.
451 EXPECT_GT(info.total, 0);
Xiaohan Wang37e81612022-01-15 18:27:00452#if BUILDFLAG(IS_WIN)
mkolom01ac10b2017-03-22 01:47:29453 EXPECT_GT(info.avail_phys, 0);
454#else
[email protected]cf46e3752013-12-02 01:01:01455 EXPECT_GT(info.free, 0);
mkolom01ac10b2017-03-22 01:47:29456#endif
Xiaohan Wang37e81612022-01-15 18:27:00457#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
[email protected]cf46e3752013-12-02 01:01:01458 EXPECT_GT(info.buffers, 0);
459 EXPECT_GT(info.cached, 0);
Sonny Rao81a33e82020-02-13 19:30:26460 EXPECT_GT(info.active_anon + info.inactive_anon, 0);
461 EXPECT_GT(info.active_file + info.inactive_file, 0);
Xiaohan Wang37e81612022-01-15 18:27:00462#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
463 // BUILDFLAG(IS_ANDROID)
[email protected]cf46e3752013-12-02 01:01:01464
465 // All the values should be less than the total amount of memory.
Xiaohan Wang37e81612022-01-15 18:27:00466#if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_IOS)
liaoyuke71606ecc2017-04-13 22:46:17467 // TODO(crbug.com/711450): re-enable the following assertion on iOS.
[email protected]cf46e3752013-12-02 01:01:01468 EXPECT_LT(info.free, info.total);
mkolom01ac10b2017-03-22 01:47:29469#endif
Xiaohan Wang37e81612022-01-15 18:27:00470#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
[email protected]cf46e3752013-12-02 01:01:01471 EXPECT_LT(info.buffers, info.total);
472 EXPECT_LT(info.cached, info.total);
473 EXPECT_LT(info.active_anon, info.total);
474 EXPECT_LT(info.inactive_anon, info.total);
475 EXPECT_LT(info.active_file, info.total);
476 EXPECT_LT(info.inactive_file, info.total);
Xiaohan Wang37e81612022-01-15 18:27:00477#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
478 // BUILDFLAG(IS_ANDROID)
[email protected]cf46e3752013-12-02 01:01:01479
Xiaohan Wang37e81612022-01-15 18:27:00480#if BUILDFLAG(IS_APPLE)
mkolom01ac10b2017-03-22 01:47:29481 EXPECT_GT(info.file_backed, 0);
482#endif
483
Yuta Hijikata000df18f2020-11-18 06:55:58484#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
[email protected]cf46e3752013-12-02 01:01:01485 // Chrome OS exposes shmem.
486 EXPECT_GT(info.shmem, 0);
487 EXPECT_LT(info.shmem, info.total);
[email protected]cf46e3752013-12-02 01:01:01488#endif
489}
Xiaohan Wang37e81612022-01-15 18:27:00490#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) ||
491 // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
[email protected]cf46e3752013-12-02 01:01:01492
Xiaohan Wang37e81612022-01-15 18:27:00493#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
[email protected]cf46e3752013-12-02 01:01:01494TEST(ProcessMetricsTest, ParseProcStatCPU) {
495 // /proc/self/stat for a process running "top".
496 const char kTopStat[] = "960 (top) S 16230 960 16230 34818 960 "
497 "4202496 471 0 0 0 "
498 "12 16 0 0 " // <- These are the goods.
499 "20 0 1 0 121946157 15077376 314 18446744073709551615 4194304 "
500 "4246868 140733983044336 18446744073709551615 140244213071219 "
501 "0 0 0 138047495 0 0 0 17 1 0 0 0 0 0";
thestigcf4c85b2015-12-16 08:33:30502 EXPECT_EQ(12 + 16, ParseProcStatCPU(kTopStat));
[email protected]cf46e3752013-12-02 01:01:01503
504 // cat /proc/self/stat on a random other machine I have.
505 const char kSelfStat[] = "5364 (cat) R 5354 5364 5354 34819 5364 "
506 "0 142 0 0 0 "
507 "0 0 0 0 " // <- No CPU, apparently.
508 "16 0 1 0 1676099790 2957312 114 4294967295 134512640 134528148 "
509 "3221224832 3221224344 3086339742 0 0 0 0 0 0 0 17 0 0 0";
510
thestigcf4c85b2015-12-16 08:33:30511 EXPECT_EQ(0, ParseProcStatCPU(kSelfStat));
afakhry597a8512015-02-05 00:51:57512
513 // Some weird long-running process with a weird name that I created for the
514 // purposes of this test.
515 const char kWeirdNameStat[] = "26115 (Hello) You ())) ) R 24614 26115 24614"
516 " 34839 26115 4218880 227 0 0 0 "
517 "5186 11 0 0 "
518 "20 0 1 0 36933953 4296704 90 18446744073709551615 4194304 4196116 "
519 "140735857761568 140735857761160 4195644 0 0 0 0 0 0 0 17 14 0 0 0 0 0 "
520 "6295056 6295616 16519168 140735857770710 140735857770737 "
521 "140735857770737 140735857774557 0";
thestigcf4c85b2015-12-16 08:33:30522 EXPECT_EQ(5186 + 11, ParseProcStatCPU(kWeirdNameStat));
[email protected]cf46e3752013-12-02 01:01:01523}
Eric Secklerdbc29da2020-07-10 11:54:05524
525TEST(ProcessMetricsTest, ParseProcTimeInState) {
526 ProcessHandle handle = GetCurrentProcessHandle();
527 std::unique_ptr<ProcessMetrics> metrics(
528 ProcessMetrics::CreateProcessMetrics(handle));
529 ProcessMetrics::TimeInStatePerThread time_in_state;
530
531 const char kStatThread123[] =
532 "cpu0\n"
533 "100000 4\n"
534 "200000 5\n"
535 "300000 0\n"
536 "cpu4\n"
537 "400000 3\n"
538 "500000 2\n";
539 EXPECT_TRUE(
540 metrics->ParseProcTimeInState(kStatThread123, 123, time_in_state));
541
542 // Zero-valued entry should not exist.
543 ASSERT_EQ(time_in_state.size(), 4u);
544
545 EXPECT_EQ(time_in_state[0].thread_id, 123);
546 EXPECT_EQ(time_in_state[0].cluster_core_index, 0u);
547 EXPECT_EQ(time_in_state[0].core_frequency_khz, 100000u);
Peter Kastinge5a38ed2021-10-02 03:06:35548 EXPECT_EQ(time_in_state[0].cumulative_cpu_time, base::Milliseconds(40));
Eric Secklerdbc29da2020-07-10 11:54:05549 EXPECT_EQ(time_in_state[1].thread_id, 123);
550 EXPECT_EQ(time_in_state[1].cluster_core_index, 0u);
551 EXPECT_EQ(time_in_state[1].core_frequency_khz, 200000u);
Peter Kastinge5a38ed2021-10-02 03:06:35552 EXPECT_EQ(time_in_state[1].cumulative_cpu_time, base::Milliseconds(50));
Eric Secklerdbc29da2020-07-10 11:54:05553 EXPECT_EQ(time_in_state[2].thread_id, 123);
554 EXPECT_EQ(time_in_state[2].cluster_core_index, 4u);
555 EXPECT_EQ(time_in_state[2].core_frequency_khz, 400000u);
Peter Kastinge5a38ed2021-10-02 03:06:35556 EXPECT_EQ(time_in_state[2].cumulative_cpu_time, base::Milliseconds(30));
Eric Secklerdbc29da2020-07-10 11:54:05557 EXPECT_EQ(time_in_state[3].thread_id, 123);
558 EXPECT_EQ(time_in_state[3].cluster_core_index, 4u);
559 EXPECT_EQ(time_in_state[3].core_frequency_khz, 500000u);
Peter Kastinge5a38ed2021-10-02 03:06:35560 EXPECT_EQ(time_in_state[3].cumulative_cpu_time, base::Milliseconds(20));
Eric Secklerdbc29da2020-07-10 11:54:05561
562 // Calling ParseProcTimeInState again adds to the vector.
563 const char kStatThread456[] =
564 "cpu0\n"
565 "\n" // extra empty line is fine.
566 "1000000 10"; // missing "\n" at end is fine.
567 EXPECT_TRUE(
568 metrics->ParseProcTimeInState(kStatThread456, 456, time_in_state));
569
570 ASSERT_EQ(time_in_state.size(), 5u);
571 EXPECT_EQ(time_in_state[4].thread_id, 456);
572 EXPECT_EQ(time_in_state[4].cluster_core_index, 0u);
573 EXPECT_EQ(time_in_state[4].core_frequency_khz, 1000000u);
Peter Kastinge5a38ed2021-10-02 03:06:35574 EXPECT_EQ(time_in_state[4].cumulative_cpu_time, base::Milliseconds(100));
Eric Secklerdbc29da2020-07-10 11:54:05575
576 // Calling ParseProcTimeInState with invalid data returns false.
577 EXPECT_FALSE(
578 metrics->ParseProcTimeInState("100000 5\n" // no header
579 "200000 6\n",
580 123, time_in_state));
581 EXPECT_FALSE(
582 metrics->ParseProcTimeInState("cpu0\n"
583 "100000\n", // no time value
584 123, time_in_state));
585 EXPECT_FALSE(
586 metrics->ParseProcTimeInState("header0\n" // invalid header / line
587 "100000 5\n",
588 123, time_in_state));
589 EXPECT_FALSE(
590 metrics->ParseProcTimeInState("cpu0\n"
591 "100000 5\n"
592 "invalid334 4\n", // invalid header / line
593 123, time_in_state));
594}
Xiaohan Wang37e81612022-01-15 18:27:00595#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
596 // BUILDFLAG(IS_ANDROID)
[email protected]cf46e3752013-12-02 01:01:01597
598// Disable on Android because base_unittests runs inside a Dalvik VM that
599// starts and stop threads (crbug.com/175563).
Xiaohan Wang37e81612022-01-15 18:27:00600#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
[email protected]9792d382014-08-11 16:12:37601// http://crbug.com/396455
602TEST(ProcessMetricsTest, DISABLED_GetNumberOfThreads) {
thestigcf4c85b2015-12-16 08:33:30603 const ProcessHandle current = GetCurrentProcessHandle();
604 const int initial_threads = GetNumberOfThreads(current);
[email protected]cf46e3752013-12-02 01:01:01605 ASSERT_GT(initial_threads, 0);
606 const int kNumAdditionalThreads = 10;
607 {
dcheng093de9b2016-04-04 21:25:51608 std::unique_ptr<Thread> my_threads[kNumAdditionalThreads];
[email protected]cf46e3752013-12-02 01:01:01609 for (int i = 0; i < kNumAdditionalThreads; ++i) {
Peter Boström6b701822021-04-15 03:53:08610 my_threads[i] = std::make_unique<Thread>("GetNumberOfThreadsTest");
[email protected]cf46e3752013-12-02 01:01:01611 my_threads[i]->Start();
thestigcf4c85b2015-12-16 08:33:30612 ASSERT_EQ(GetNumberOfThreads(current), initial_threads + 1 + i);
[email protected]cf46e3752013-12-02 01:01:01613 }
614 }
615 // The Thread destructor will stop them.
thestigcf4c85b2015-12-16 08:33:30616 ASSERT_EQ(initial_threads, GetNumberOfThreads(current));
617}
Xiaohan Wang37e81612022-01-15 18:27:00618#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
thestigcf4c85b2015-12-16 08:33:30619
Xiaohan Wang37e81612022-01-15 18:27:00620#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC)
thestigcf4c85b2015-12-16 08:33:30621namespace {
622
Siddhartha5293d8a2017-12-21 01:09:54623// Keep these in sync so the GetChildOpenFdCount test can refer to correct test
624// main.
thestigcf4c85b2015-12-16 08:33:30625#define ChildMain ChildFdCount
626#define ChildMainString "ChildFdCount"
627
628// Command line flag name and file name used for synchronization.
629const char kTempDirFlag[] = "temp-dir";
Robert Sesek3aff3362019-01-23 20:16:16630
631const char kSignalReady[] = "ready";
632const char kSignalReadyAck[] = "ready-ack";
633const char kSignalOpened[] = "opened";
634const char kSignalOpenedAck[] = "opened-ack";
thestigcf4c85b2015-12-16 08:33:30635const char kSignalClosed[] = "closed";
636
Robert Sesek3aff3362019-01-23 20:16:16637const int kChildNumFilesToOpen = 100;
638
thestigcf4c85b2015-12-16 08:33:30639bool SignalEvent(const FilePath& signal_dir, const char* signal_file) {
640 File file(signal_dir.AppendASCII(signal_file),
641 File::FLAG_CREATE | File::FLAG_WRITE);
642 return file.IsValid();
643}
644
645// Check whether an event was signaled.
646bool CheckEvent(const FilePath& signal_dir, const char* signal_file) {
647 File file(signal_dir.AppendASCII(signal_file),
648 File::FLAG_OPEN | File::FLAG_READ);
649 return file.IsValid();
650}
651
652// Busy-wait for an event to be signaled.
653void WaitForEvent(const FilePath& signal_dir, const char* signal_file) {
654 while (!CheckEvent(signal_dir, signal_file))
Peter Kasting53fd6ee2021-10-05 20:40:48655 PlatformThread::Sleep(Milliseconds(10));
thestigcf4c85b2015-12-16 08:33:30656}
657
658// Subprocess to test the number of open file descriptors.
659MULTIPROCESS_TEST_MAIN(ChildMain) {
660 CommandLine* command_line = CommandLine::ForCurrentProcess();
661 const FilePath temp_path = command_line->GetSwitchValuePath(kTempDirFlag);
662 CHECK(DirectoryExists(temp_path));
663
Robert Sesek3aff3362019-01-23 20:16:16664 CHECK(SignalEvent(temp_path, kSignalReady));
665 WaitForEvent(temp_path, kSignalReadyAck);
666
667 std::vector<File> files;
668 for (int i = 0; i < kChildNumFilesToOpen; ++i) {
669 files.emplace_back(temp_path.AppendASCII(StringPrintf("file.%d", i)),
670 File::FLAG_CREATE | File::FLAG_WRITE);
671 }
672
673 CHECK(SignalEvent(temp_path, kSignalOpened));
674 WaitForEvent(temp_path, kSignalOpenedAck);
675
676 files.clear();
677
thestigcf4c85b2015-12-16 08:33:30678 CHECK(SignalEvent(temp_path, kSignalClosed));
679
680 // Wait to be terminated.
681 while (true)
Peter Kasting53fd6ee2021-10-05 20:40:48682 PlatformThread::Sleep(Seconds(1));
thestigcf4c85b2015-12-16 08:33:30683}
684
685} // namespace
686
Siddhartha5293d8a2017-12-21 01:09:54687TEST(ProcessMetricsTest, GetChildOpenFdCount) {
thestigcf4c85b2015-12-16 08:33:30688 ScopedTempDir temp_dir;
689 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
vabr411f4fc2016-09-08 09:26:27690 const FilePath temp_path = temp_dir.GetPath();
thestigcf4c85b2015-12-16 08:33:30691 CommandLine child_command_line(GetMultiProcessTestChildBaseCommandLine());
692 child_command_line.AppendSwitchPath(kTempDirFlag, temp_path);
Jay Civelli4a44260b2017-08-21 19:26:29693 Process child = SpawnMultiProcessTestChild(
thestigcf4c85b2015-12-16 08:33:30694 ChildMainString, child_command_line, LaunchOptions());
Jay Civelli4a44260b2017-08-21 19:26:29695 ASSERT_TRUE(child.IsValid());
Robert Sesek3aff3362019-01-23 20:16:16696
697 WaitForEvent(temp_path, kSignalReady);
698
699 std::unique_ptr<ProcessMetrics> metrics =
Xiaohan Wang37e81612022-01-15 18:27:00700#if BUILDFLAG(IS_APPLE)
Robert Sesek3aff3362019-01-23 20:16:16701 ProcessMetrics::CreateProcessMetrics(child.Handle(), nullptr);
702#else
703 ProcessMetrics::CreateProcessMetrics(child.Handle());
Xiaohan Wang37e81612022-01-15 18:27:00704#endif // BUILDFLAG(IS_APPLE)
Robert Sesek3aff3362019-01-23 20:16:16705
706 const int fd_count = metrics->GetOpenFdCount();
707 EXPECT_GE(fd_count, 0);
708
709 ASSERT_TRUE(SignalEvent(temp_path, kSignalReadyAck));
710 WaitForEvent(temp_path, kSignalOpened);
711
712 EXPECT_EQ(fd_count + kChildNumFilesToOpen, metrics->GetOpenFdCount());
713 ASSERT_TRUE(SignalEvent(temp_path, kSignalOpenedAck));
714
thestigcf4c85b2015-12-16 08:33:30715 WaitForEvent(temp_path, kSignalClosed);
716
Robert Sesek3aff3362019-01-23 20:16:16717 EXPECT_EQ(fd_count, metrics->GetOpenFdCount());
718
Jay Civelli4a44260b2017-08-21 19:26:29719 ASSERT_TRUE(child.Terminate(0, true));
[email protected]cf46e3752013-12-02 01:01:01720}
Siddhartha5293d8a2017-12-21 01:09:54721
722TEST(ProcessMetricsTest, GetOpenFdCount) {
Robert Sesek3aff3362019-01-23 20:16:16723 base::ProcessHandle process = base::GetCurrentProcessHandle();
724 std::unique_ptr<base::ProcessMetrics> metrics =
Xiaohan Wang37e81612022-01-15 18:27:00725#if BUILDFLAG(IS_APPLE)
Robert Sesek3aff3362019-01-23 20:16:16726 ProcessMetrics::CreateProcessMetrics(process, nullptr);
727#else
728 ProcessMetrics::CreateProcessMetrics(process);
Xiaohan Wang37e81612022-01-15 18:27:00729#endif // BUILDFLAG(IS_APPLE)
Robert Sesek3aff3362019-01-23 20:16:16730
731 ScopedTempDir temp_dir;
732 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
733
Siddhartha5293d8a2017-12-21 01:09:54734 int fd_count = metrics->GetOpenFdCount();
735 EXPECT_GT(fd_count, 0);
Robert Sesek3aff3362019-01-23 20:16:16736 File file(temp_dir.GetPath().AppendASCII("file"),
737 File::FLAG_CREATE | File::FLAG_WRITE);
Siddhartha5293d8a2017-12-21 01:09:54738 int new_fd_count = metrics->GetOpenFdCount();
739 EXPECT_GT(new_fd_count, 0);
740 EXPECT_EQ(new_fd_count, fd_count + 1);
741}
742
Xiaohan Wang37e81612022-01-15 18:27:00743#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC)
Robert Sesek3aff3362019-01-23 20:16:16744
Xiaohan Wang37e81612022-01-15 18:27:00745#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
Eric Seckler9db21392020-06-12 08:48:19746
Benoit Lize448ee882017-08-31 13:32:12747TEST(ProcessMetricsTestLinux, GetPageFaultCounts) {
748 std::unique_ptr<base::ProcessMetrics> process_metrics(
749 base::ProcessMetrics::CreateProcessMetrics(
750 base::GetCurrentProcessHandle()));
751
752 PageFaultCounts counts;
753 ASSERT_TRUE(process_metrics->GetPageFaultCounts(&counts));
754 ASSERT_GT(counts.minor, 0);
755 ASSERT_GE(counts.major, 0);
756
arthursonzogni38d9bf472019-04-15 13:00:11757 // Allocate and touch memory. Touching it is required to make sure that the
758 // page fault count goes up, as memory is typically mapped lazily.
Benoit Lize448ee882017-08-31 13:32:12759 {
arthursonzogni38d9bf472019-04-15 13:00:11760 const size_t kMappedSize = 4 << 20; // 4 MiB.
761
762 WritableSharedMemoryRegion region =
763 WritableSharedMemoryRegion::Create(kMappedSize);
764 ASSERT_TRUE(region.IsValid());
765
766 WritableSharedMemoryMapping mapping = region.Map();
767 ASSERT_TRUE(mapping.IsValid());
768
769 memset(mapping.memory(), 42, kMappedSize);
Benoit Lize448ee882017-08-31 13:32:12770 }
771
772 PageFaultCounts counts_after;
773 ASSERT_TRUE(process_metrics->GetPageFaultCounts(&counts_after));
774 ASSERT_GT(counts_after.minor, counts.minor);
775 ASSERT_GE(counts_after.major, counts.major);
776}
Eric Seckler9db21392020-06-12 08:48:19777
778TEST(ProcessMetricsTestLinux, GetCumulativeCPUUsagePerThread) {
779 ProcessHandle handle = GetCurrentProcessHandle();
780 std::unique_ptr<ProcessMetrics> metrics(
781 ProcessMetrics::CreateProcessMetrics(handle));
782
783 Thread thread1("thread1");
784 thread1.StartAndWaitForTesting();
785 ASSERT_TRUE(thread1.IsRunning());
786
787 std::vector<std::string> vec1;
788 thread1.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec1));
789
790 ProcessMetrics::CPUUsagePerThread prev_thread_times;
791 EXPECT_TRUE(metrics->GetCumulativeCPUUsagePerThread(prev_thread_times));
792
793 // Should have at least the test runner thread and the thread spawned above.
794 EXPECT_GE(prev_thread_times.size(), 2u);
Anton Bikineeva61fb572020-10-18 08:54:44795 EXPECT_TRUE(ranges::any_of(
796 prev_thread_times,
Eric Seckler9db21392020-06-12 08:48:19797 [&thread1](const std::pair<PlatformThreadId, base::TimeDelta>& entry) {
798 return entry.first == thread1.GetThreadId();
799 }));
Anton Bikineeva61fb572020-10-18 08:54:44800 EXPECT_TRUE(ranges::any_of(
801 prev_thread_times,
Eric Seckler9db21392020-06-12 08:48:19802 [](const std::pair<PlatformThreadId, base::TimeDelta>& entry) {
803 return entry.first == base::PlatformThread::CurrentId();
804 }));
805
806 for (const auto& entry : prev_thread_times) {
807 EXPECT_GE(entry.second, base::TimeDelta());
808 }
809
810 thread1.Stop();
811
812 ProcessMetrics::CPUUsagePerThread current_thread_times;
813 EXPECT_TRUE(metrics->GetCumulativeCPUUsagePerThread(current_thread_times));
814
815 // The stopped thread may still be reported until the kernel cleans it up.
816 EXPECT_GE(prev_thread_times.size(), 1u);
Anton Bikineeva61fb572020-10-18 08:54:44817 EXPECT_TRUE(ranges::any_of(
818 current_thread_times,
Eric Seckler9db21392020-06-12 08:48:19819 [](const std::pair<PlatformThreadId, base::TimeDelta>& entry) {
820 return entry.first == base::PlatformThread::CurrentId();
821 }));
822
823 // Reported times should not decrease.
824 for (const auto& entry : current_thread_times) {
Anton Bikineeva61fb572020-10-18 08:54:44825 auto prev_it = ranges::find_if(
826 prev_thread_times,
Eric Seckler9db21392020-06-12 08:48:19827 [&entry](
828 const std::pair<PlatformThreadId, base::TimeDelta>& prev_entry) {
829 return entry.first == prev_entry.first;
830 });
831
832 if (prev_it != prev_thread_times.end())
833 EXPECT_GE(entry.second, prev_it->second);
834 }
835}
836
Eric Secklerdbc29da2020-07-10 11:54:05837TEST(ProcessMetricsTestLinux, GetPerThreadCumulativeCPUTimeInState) {
838 ProcessHandle handle = GetCurrentProcessHandle();
839 std::unique_ptr<ProcessMetrics> metrics(
840 ProcessMetrics::CreateProcessMetrics(handle));
841
842 // Only some test systems will support GetPerThreadCumulativeCPUTimeInState,
843 // as it relies on /proc/pid/task/tid/time_in_state support in the kernel. In
844 // Android, this is only supported in newer kernels with a patch such as this:
845 // https://android-review.googlesource.com/c/kernel/common/+/610460/.
846 bool expect_success;
847 std::string contents;
848 {
849 FilePath time_in_state_path = FilePath("/proc")
850 .Append(NumberToString(handle))
851 .Append("task")
852 .Append(NumberToString(handle))
853 .Append("time_in_state");
854 expect_success = ReadFileToString(time_in_state_path, &contents) &&
855 StartsWith(contents, "cpu", CompareCase::SENSITIVE);
856 }
857
858 ProcessMetrics::TimeInStatePerThread prev_thread_times;
859 EXPECT_EQ(metrics->GetPerThreadCumulativeCPUTimeInState(prev_thread_times),
860 expect_success)
861 << "time_in_state example contents: \n"
862 << contents;
863
864 // Only non-zero entries are reported.
865 for (const auto& entry : prev_thread_times) {
866 EXPECT_NE(entry.thread_id, 0);
867 EXPECT_GT(entry.cumulative_cpu_time, base::TimeDelta());
868 }
869
870 ProcessMetrics::TimeInStatePerThread current_thread_times;
871 EXPECT_EQ(metrics->GetPerThreadCumulativeCPUTimeInState(current_thread_times),
872 expect_success);
873
874 // Reported times should not decrease.
875 for (const auto& entry : current_thread_times) {
Anton Bikineeva61fb572020-10-18 08:54:44876 auto prev_it = ranges::find_if(
877 prev_thread_times,
Eric Secklerdbc29da2020-07-10 11:54:05878 [&entry](const ProcessMetrics::ThreadTimeInState& prev_entry) {
879 return entry.thread_id == prev_entry.thread_id &&
880 entry.core_type == prev_entry.core_type &&
881 entry.core_frequency_khz == prev_entry.core_frequency_khz;
882 });
883
884 if (prev_it != prev_thread_times.end())
885 EXPECT_GE(entry.cumulative_cpu_time, prev_it->cumulative_cpu_time);
886 }
887}
888
Xiaohan Wang37e81612022-01-15 18:27:00889#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) ||
890 // BUILDFLAG(IS_CHROMEOS)
Benoit Lize448ee882017-08-31 13:32:12891
[email protected]669a09332013-08-30 22:59:14892} // namespace debug
893} // namespace base