blob: 378a4cd4a5219ad55beac5b654763040d0932588 [file] [log] [blame]
Sandeep Patil54d87212018-08-29 17:10:47 -07001/*
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
Christopher Ferris504d2cc2019-07-12 14:25:48 -070017#include <sys/mman.h>
Sandeep Patil54d87212018-08-29 17:10:47 -070018#include <sys/types.h>
19#include <sys/wait.h>
20#include <unistd.h>
21
22#include <gtest/gtest.h>
23
24#include <string>
25#include <vector>
26
27#include <meminfo/pageacct.h>
28#include <meminfo/procmeminfo.h>
29#include <meminfo/sysmeminfo.h>
Sandeep Patil54d87212018-08-29 17:10:47 -070030
31#include <android-base/file.h>
32#include <android-base/logging.h>
Sandeep Patilc24f1e32018-12-29 14:34:20 -080033#include <android-base/stringprintf.h>
Christopher Ferris5db00922019-09-18 10:30:33 -070034#include <android-base/strings.h>
Sandeep Patil54d87212018-08-29 17:10:47 -070035
36using namespace std;
37using namespace android::meminfo;
38
39pid_t pid = -1;
40
Sandeep Patildfa00a72019-01-28 15:05:27 -080041TEST(ProcMemInfo, TestWorkingTestReset) {
Sandeep Patil54d87212018-08-29 17:10:47 -070042 // Expect reset to succeed
Sandeep Patilf1291992018-11-19 15:25:18 -080043 EXPECT_TRUE(ProcMemInfo::ResetWorkingSet(pid));
Sandeep Patil54d87212018-08-29 17:10:47 -070044}
45
Sandeep Patildfa00a72019-01-28 15:05:27 -080046TEST(ProcMemInfo, UsageEmpty) {
Sandeep Patilc6497eb2018-11-20 09:31:36 -080047 // If we created the object for getting working set,
48 // the usage must be empty
49 ProcMemInfo proc_mem(pid, true);
50 const MemUsage& usage = proc_mem.Usage();
51 EXPECT_EQ(usage.rss, 0);
52 EXPECT_EQ(usage.vss, 0);
53 EXPECT_EQ(usage.pss, 0);
54 EXPECT_EQ(usage.uss, 0);
55 EXPECT_EQ(usage.swap, 0);
56}
57
Sandeep Patildfa00a72019-01-28 15:05:27 -080058TEST(ProcMemInfo, MapsNotEmpty) {
59 // Make sure the process maps are never empty
60 ProcMemInfo proc_mem(pid);
61 const std::vector<Vma>& maps = proc_mem.Maps();
62 EXPECT_FALSE(maps.empty());
63}
64
Christopher Ferris504d2cc2019-07-12 14:25:48 -070065TEST(ProcMemInfo, MapsUsageNotEmpty) {
66 ProcMemInfo proc_mem(pid);
67 const std::vector<Vma>& maps = proc_mem.Maps();
68 EXPECT_FALSE(maps.empty());
69 uint64_t total_pss = 0;
70 uint64_t total_rss = 0;
71 uint64_t total_uss = 0;
72 for (auto& map : maps) {
73 ASSERT_NE(0, map.usage.vss);
74 total_rss += map.usage.rss;
75 total_pss += map.usage.pss;
76 total_uss += map.usage.uss;
77 }
78
79 // Crude check that stats are actually being read.
80 EXPECT_NE(0, total_rss) << "RSS zero for all maps, that is not possible.";
81 EXPECT_NE(0, total_pss) << "PSS zero for all maps, that is not possible.";
82 EXPECT_NE(0, total_uss) << "USS zero for all maps, that is not possible.";
83}
84
85TEST(ProcMemInfo, MapsUsageEmpty) {
86 ProcMemInfo proc_mem(pid);
87 const std::vector<Vma>& maps = proc_mem.MapsWithoutUsageStats();
88 EXPECT_FALSE(maps.empty());
89 // Verify that all usage stats are zero in every map.
90 for (auto& map : maps) {
91 ASSERT_EQ(0, map.usage.vss);
92 ASSERT_EQ(0, map.usage.rss);
93 ASSERT_EQ(0, map.usage.pss);
94 ASSERT_EQ(0, map.usage.uss);
95 ASSERT_EQ(0, map.usage.swap);
96 ASSERT_EQ(0, map.usage.swap_pss);
97 ASSERT_EQ(0, map.usage.private_clean);
98 ASSERT_EQ(0, map.usage.private_dirty);
99 ASSERT_EQ(0, map.usage.shared_clean);
100 ASSERT_EQ(0, map.usage.shared_dirty);
101 }
102}
103
Christopher Ferris23f2a0b2019-10-10 13:25:00 -0700104TEST(ProcMemInfo, MapsUsageFillInLater) {
105 ProcMemInfo proc_mem(pid);
106 const std::vector<Vma>& maps = proc_mem.MapsWithoutUsageStats();
107 EXPECT_FALSE(maps.empty());
108 for (auto& map : maps) {
109 Vma update_map(map);
110 ASSERT_EQ(map.start, update_map.start);
111 ASSERT_EQ(map.end, update_map.end);
112 ASSERT_EQ(map.offset, update_map.offset);
113 ASSERT_EQ(map.flags, update_map.flags);
114 ASSERT_EQ(map.name, update_map.name);
115 ASSERT_EQ(0, update_map.usage.vss);
116 ASSERT_EQ(0, update_map.usage.rss);
117 ASSERT_EQ(0, update_map.usage.pss);
118 ASSERT_EQ(0, update_map.usage.uss);
119 ASSERT_EQ(0, update_map.usage.swap);
120 ASSERT_EQ(0, update_map.usage.swap_pss);
121 ASSERT_EQ(0, update_map.usage.private_clean);
122 ASSERT_EQ(0, update_map.usage.private_dirty);
123 ASSERT_EQ(0, update_map.usage.shared_clean);
124 ASSERT_EQ(0, update_map.usage.shared_dirty);
125 ASSERT_TRUE(proc_mem.FillInVmaStats(update_map));
126 // Check that at least one usage stat was updated.
127 ASSERT_NE(0, update_map.usage.vss);
128 }
129}
130
Christopher Ferris504d2cc2019-07-12 14:25:48 -0700131TEST(ProcMemInfo, PageMapPresent) {
132 static constexpr size_t kNumPages = 20;
133 size_t pagesize = getpagesize();
134 void* ptr = mmap(nullptr, pagesize * (kNumPages + 2), PROT_READ | PROT_WRITE,
135 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
136 ASSERT_NE(MAP_FAILED, ptr);
137
138 // Unmap the first page and the last page so that we guarantee this
139 // map is in a map by itself.
140 ASSERT_EQ(0, munmap(ptr, pagesize));
141 uintptr_t addr = reinterpret_cast<uintptr_t>(ptr) + pagesize;
142 ASSERT_EQ(0, munmap(reinterpret_cast<void*>(addr + kNumPages * pagesize), pagesize));
143
144 ProcMemInfo proc_mem(getpid());
145 const std::vector<Vma>& maps = proc_mem.MapsWithoutUsageStats();
146 ASSERT_FALSE(maps.empty());
147
148 // Find the vma associated with our previously created map.
149 const Vma* test_vma = nullptr;
150 for (const Vma& vma : maps) {
151 if (vma.start == addr) {
152 test_vma = &vma;
153 break;
154 }
155 }
156 ASSERT_TRUE(test_vma != nullptr) << "Cannot find test map.";
157
158 // Verify that none of the pages are listed as present.
159 std::vector<uint64_t> pagemap;
160 ASSERT_TRUE(proc_mem.PageMap(*test_vma, &pagemap));
161 ASSERT_EQ(kNumPages, pagemap.size());
162 for (size_t i = 0; i < pagemap.size(); i++) {
163 EXPECT_FALSE(android::meminfo::page_present(pagemap[i]))
164 << "Page " << i << " is present and it should not be.";
165 }
166
167 // Make some of the pages present and verify that we see them
168 // as present.
169 uint8_t* data = reinterpret_cast<uint8_t*>(addr);
170 data[0] = 1;
171 data[pagesize * 5] = 1;
172 data[pagesize * 11] = 1;
173
174 ASSERT_TRUE(proc_mem.PageMap(*test_vma, &pagemap));
175 ASSERT_EQ(kNumPages, pagemap.size());
176 for (size_t i = 0; i < pagemap.size(); i++) {
177 if (i == 0 || i == 5 || i == 11) {
178 EXPECT_TRUE(android::meminfo::page_present(pagemap[i]))
179 << "Page " << i << " is not present and it should be.";
180 } else {
181 EXPECT_FALSE(android::meminfo::page_present(pagemap[i]))
182 << "Page " << i << " is present and it should not be.";
183 }
184 }
185
186 ASSERT_EQ(0, munmap(reinterpret_cast<void*>(addr), kNumPages * pagesize));
187}
188
Sandeep Patildfa00a72019-01-28 15:05:27 -0800189TEST(ProcMemInfo, WssEmpty) {
Sandeep Patilc6497eb2018-11-20 09:31:36 -0800190 // If we created the object for getting usage,
191 // the working set must be empty
192 ProcMemInfo proc_mem(pid, false);
193 const MemUsage& wss = proc_mem.Wss();
194 EXPECT_EQ(wss.rss, 0);
195 EXPECT_EQ(wss.vss, 0);
196 EXPECT_EQ(wss.pss, 0);
197 EXPECT_EQ(wss.uss, 0);
198 EXPECT_EQ(wss.swap, 0);
199}
200
Sandeep Patildfa00a72019-01-28 15:05:27 -0800201TEST(ProcMemInfo, SwapOffsetsEmpty) {
Sandeep Patilc6497eb2018-11-20 09:31:36 -0800202 // If we created the object for getting working set,
203 // the swap offsets must be empty
204 ProcMemInfo proc_mem(pid, true);
205 const std::vector<uint16_t>& swap_offsets = proc_mem.SwapOffsets();
206 EXPECT_EQ(swap_offsets.size(), 0);
207}
208
Sandeep Patildfa00a72019-01-28 15:05:27 -0800209TEST(ProcMemInfo, IsSmapsSupportedTest) {
210 // Get any pid and check if /proc/<pid>/smaps_rollup exists using the API.
211 // The API must return the appropriate value regardless of the after it succeeds
212 // once.
Sandeep Patildfd34be2019-01-13 17:39:08 -0800213 std::string path = ::android::base::StringPrintf("/proc/%d/smaps_rollup", pid);
214 bool supported = IsSmapsRollupSupported(pid);
215 EXPECT_EQ(!access(path.c_str(), F_OK | R_OK), supported);
216 // Second call must return what the first one returned regardless of the pid parameter.
217 // So, deliberately pass invalid pid.
218 EXPECT_EQ(supported, IsSmapsRollupSupported(-1));
219}
220
Sandeep Patildfa00a72019-01-28 15:05:27 -0800221TEST(ProcMemInfo, SmapsOrRollupTest) {
222 // Make sure we can parse 'smaps_rollup' correctly
Sandeep Patilfa2d8d52018-12-29 21:05:38 -0800223 std::string rollup =
224 R"rollup(12c00000-7fe859e000 ---p 00000000 00:00 0 [rollup]
225Rss: 331908 kB
226Pss: 202052 kB
227Shared_Clean: 158492 kB
228Shared_Dirty: 18928 kB
229Private_Clean: 90472 kB
230Private_Dirty: 64016 kB
231Referenced: 318700 kB
232Anonymous: 81984 kB
233AnonHugePages: 0 kB
234Shared_Hugetlb: 0 kB
235Private_Hugetlb: 0 kB
236Swap: 5344 kB
237SwapPss: 442 kB
238Locked: 1523537 kB)rollup";
239
240 TemporaryFile tf;
241 ASSERT_TRUE(tf.fd != -1);
242 ASSERT_TRUE(::android::base::WriteStringToFd(rollup, tf.fd));
243
244 MemUsage stats;
245 ASSERT_EQ(SmapsOrRollupFromFile(tf.path, &stats), true);
246 EXPECT_EQ(stats.rss, 331908);
247 EXPECT_EQ(stats.pss, 202052);
248 EXPECT_EQ(stats.uss, 154488);
249 EXPECT_EQ(stats.private_clean, 90472);
250 EXPECT_EQ(stats.private_dirty, 64016);
251 EXPECT_EQ(stats.swap_pss, 442);
252}
253
Sandeep Patildfa00a72019-01-28 15:05:27 -0800254TEST(ProcMemInfo, SmapsOrRollupSmapsTest) {
255 // Make sure /proc/<pid>/smaps is parsed correctly
Sandeep Patilfa2d8d52018-12-29 21:05:38 -0800256 std::string smaps =
257 R"smaps(12c00000-13440000 rw-p 00000000 00:00 0 [anon:dalvik-main space (region space)]
258Name: [anon:dalvik-main space (region space)]
259Size: 8448 kB
260KernelPageSize: 4 kB
261MMUPageSize: 4 kB
262Rss: 2652 kB
263Pss: 2652 kB
264Shared_Clean: 840 kB
265Shared_Dirty: 40 kB
266Private_Clean: 84 kB
267Private_Dirty: 2652 kB
268Referenced: 2652 kB
269Anonymous: 2652 kB
270AnonHugePages: 0 kB
271ShmemPmdMapped: 0 kB
272Shared_Hugetlb: 0 kB
273Private_Hugetlb: 0 kB
274Swap: 102 kB
275SwapPss: 70 kB
276Locked: 2652 kB
277VmFlags: rd wr mr mw me ac
278)smaps";
279
280 TemporaryFile tf;
281 ASSERT_TRUE(tf.fd != -1);
282 ASSERT_TRUE(::android::base::WriteStringToFd(smaps, tf.fd));
283
284 MemUsage stats;
285 ASSERT_EQ(SmapsOrRollupFromFile(tf.path, &stats), true);
286 EXPECT_EQ(stats.rss, 2652);
287 EXPECT_EQ(stats.pss, 2652);
288 EXPECT_EQ(stats.uss, 2736);
289 EXPECT_EQ(stats.private_clean, 84);
290 EXPECT_EQ(stats.private_dirty, 2652);
291 EXPECT_EQ(stats.swap_pss, 70);
292}
293
Sandeep Patildfa00a72019-01-28 15:05:27 -0800294TEST(ProcMemInfo, SmapsOrRollupPssRollupTest) {
295 // Make sure /proc/<pid>/smaps is parsed correctly
296 // to get the PSS
Sandeep Patil8871e7e2019-01-13 16:47:20 -0800297 std::string smaps =
298 R"smaps(12c00000-13440000 rw-p 00000000 00:00 0 [anon:dalvik-main space (region space)]
299Name: [anon:dalvik-main space (region space)]
300Size: 8448 kB
301KernelPageSize: 4 kB
302MMUPageSize: 4 kB
303Rss: 2652 kB
304Pss: 2652 kB
305Shared_Clean: 840 kB
306Shared_Dirty: 40 kB
307Private_Clean: 84 kB
308Private_Dirty: 2652 kB
309Referenced: 2652 kB
310Anonymous: 2652 kB
311AnonHugePages: 0 kB
312ShmemPmdMapped: 0 kB
313Shared_Hugetlb: 0 kB
314Private_Hugetlb: 0 kB
315Swap: 102 kB
316SwapPss: 70 kB
317Locked: 2652 kB
318VmFlags: rd wr mr mw me ac
319)smaps";
320
321 TemporaryFile tf;
322 ASSERT_TRUE(tf.fd != -1);
323 ASSERT_TRUE(::android::base::WriteStringToFd(smaps, tf.fd));
324
325 uint64_t pss;
326 ASSERT_EQ(SmapsOrRollupPssFromFile(tf.path, &pss), true);
327 EXPECT_EQ(pss, 2652);
328}
329
Sandeep Patildfa00a72019-01-28 15:05:27 -0800330TEST(ProcMemInfo, SmapsOrRollupPssSmapsTest) {
331 // Correctly parse smaps file to gather pss
Sandeep Patil8871e7e2019-01-13 16:47:20 -0800332 std::string exec_dir = ::android::base::GetExecutableDirectory();
333 std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
334
335 uint64_t pss;
336 ASSERT_EQ(SmapsOrRollupPssFromFile(path, &pss), true);
337 EXPECT_EQ(pss, 19119);
338}
339
Sandeep Patildfa00a72019-01-28 15:05:27 -0800340TEST(ProcMemInfo, ForEachVmaFromFileTest) {
341 // Parse smaps file correctly to make callbacks for each virtual memory area (vma)
Sandeep Patil82a48b12019-01-01 16:04:04 -0800342 std::string exec_dir = ::android::base::GetExecutableDirectory();
343 std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
344 ProcMemInfo proc_mem(pid);
345
346 std::vector<Vma> vmas;
347 auto collect_vmas = [&](const Vma& v) { vmas.push_back(v); };
348 ASSERT_TRUE(ForEachVmaFromFile(path, collect_vmas));
349
Sandeep Patil002f02e2019-01-13 19:39:46 -0800350 // We should get a total of 6 vmas
351 ASSERT_EQ(vmas.size(), 6);
352
Sandeep Patil82a48b12019-01-01 16:04:04 -0800353 // Expect values to be equal to what we have in testdata1/smaps_short
354 // Check for sizes first
355 ASSERT_EQ(vmas[0].usage.vss, 32768);
356 EXPECT_EQ(vmas[1].usage.vss, 11204);
357 EXPECT_EQ(vmas[2].usage.vss, 16896);
358 EXPECT_EQ(vmas[3].usage.vss, 260);
359 EXPECT_EQ(vmas[4].usage.vss, 6060);
360 EXPECT_EQ(vmas[5].usage.vss, 4);
361
362 // Check for names
363 EXPECT_EQ(vmas[0].name, "[anon:dalvik-zygote-jit-code-cache]");
364 EXPECT_EQ(vmas[1].name, "/system/framework/x86_64/boot-framework.art");
Christopher Ferris5db00922019-09-18 10:30:33 -0700365 EXPECT_TRUE(vmas[2].name == "[anon:libc_malloc]" ||
366 android::base::StartsWith(vmas[2].name, "[anon:scudo:"))
367 << "Unknown map name " << vmas[2].name;
Sandeep Patil82a48b12019-01-01 16:04:04 -0800368 EXPECT_EQ(vmas[3].name, "/system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex");
369 EXPECT_EQ(vmas[4].name, "/system/lib64/libhwui.so");
370 EXPECT_EQ(vmas[5].name, "[vsyscall]");
371
372 EXPECT_EQ(vmas[0].usage.rss, 2048);
373 EXPECT_EQ(vmas[1].usage.rss, 11188);
374 EXPECT_EQ(vmas[2].usage.rss, 15272);
375 EXPECT_EQ(vmas[3].usage.rss, 260);
376 EXPECT_EQ(vmas[4].usage.rss, 4132);
377 EXPECT_EQ(vmas[5].usage.rss, 0);
378
379 EXPECT_EQ(vmas[0].usage.pss, 113);
380 EXPECT_EQ(vmas[1].usage.pss, 2200);
381 EXPECT_EQ(vmas[2].usage.pss, 15272);
382 EXPECT_EQ(vmas[3].usage.pss, 260);
383 EXPECT_EQ(vmas[4].usage.pss, 1274);
384 EXPECT_EQ(vmas[5].usage.pss, 0);
385
386 EXPECT_EQ(vmas[0].usage.uss, 0);
387 EXPECT_EQ(vmas[1].usage.uss, 1660);
388 EXPECT_EQ(vmas[2].usage.uss, 15272);
389 EXPECT_EQ(vmas[3].usage.uss, 260);
390 EXPECT_EQ(vmas[4].usage.uss, 0);
391 EXPECT_EQ(vmas[5].usage.uss, 0);
392
393 EXPECT_EQ(vmas[0].usage.private_clean, 0);
394 EXPECT_EQ(vmas[1].usage.private_clean, 0);
395 EXPECT_EQ(vmas[2].usage.private_clean, 0);
396 EXPECT_EQ(vmas[3].usage.private_clean, 260);
397 EXPECT_EQ(vmas[4].usage.private_clean, 0);
398 EXPECT_EQ(vmas[5].usage.private_clean, 0);
399
400 EXPECT_EQ(vmas[0].usage.private_dirty, 0);
401 EXPECT_EQ(vmas[1].usage.private_dirty, 1660);
402 EXPECT_EQ(vmas[2].usage.private_dirty, 15272);
403 EXPECT_EQ(vmas[3].usage.private_dirty, 0);
404 EXPECT_EQ(vmas[4].usage.private_dirty, 0);
405 EXPECT_EQ(vmas[5].usage.private_dirty, 0);
406
407 EXPECT_EQ(vmas[0].usage.shared_clean, 0);
408 EXPECT_EQ(vmas[1].usage.shared_clean, 80);
409 EXPECT_EQ(vmas[2].usage.shared_clean, 0);
410 EXPECT_EQ(vmas[3].usage.shared_clean, 0);
411 EXPECT_EQ(vmas[4].usage.shared_clean, 4132);
412 EXPECT_EQ(vmas[5].usage.shared_clean, 0);
413
414 EXPECT_EQ(vmas[0].usage.shared_dirty, 2048);
415 EXPECT_EQ(vmas[1].usage.shared_dirty, 9448);
416 EXPECT_EQ(vmas[2].usage.shared_dirty, 0);
417 EXPECT_EQ(vmas[3].usage.shared_dirty, 0);
418 EXPECT_EQ(vmas[4].usage.shared_dirty, 0);
419 EXPECT_EQ(vmas[5].usage.shared_dirty, 0);
420
421 EXPECT_EQ(vmas[0].usage.swap, 0);
422 EXPECT_EQ(vmas[1].usage.swap, 0);
423 EXPECT_EQ(vmas[2].usage.swap, 0);
424 EXPECT_EQ(vmas[3].usage.swap, 0);
425 EXPECT_EQ(vmas[4].usage.swap, 0);
426 EXPECT_EQ(vmas[5].usage.swap, 0);
427
428 EXPECT_EQ(vmas[0].usage.swap_pss, 0);
429 EXPECT_EQ(vmas[1].usage.swap_pss, 0);
430 EXPECT_EQ(vmas[2].usage.swap_pss, 0);
431 EXPECT_EQ(vmas[3].usage.swap_pss, 0);
432 EXPECT_EQ(vmas[4].usage.swap_pss, 0);
433 EXPECT_EQ(vmas[5].usage.swap_pss, 0);
434}
435
Sandeep Patildfa00a72019-01-28 15:05:27 -0800436TEST(ProcMemInfo, SmapsReturnTest) {
437 // Make sure Smaps() is never empty for any process
Sandeep Patil82a48b12019-01-01 16:04:04 -0800438 ProcMemInfo proc_mem(pid);
439 auto vmas = proc_mem.Smaps();
440 EXPECT_FALSE(vmas.empty());
441}
442
Sandeep Patildfa00a72019-01-28 15:05:27 -0800443TEST(ProcMemInfo, SmapsTest) {
Sandeep Patil82a48b12019-01-01 16:04:04 -0800444 std::string exec_dir = ::android::base::GetExecutableDirectory();
445 std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
446 ProcMemInfo proc_mem(pid);
447 auto vmas = proc_mem.Smaps(path);
448
449 ASSERT_FALSE(vmas.empty());
Sandeep Patil002f02e2019-01-13 19:39:46 -0800450 // We should get a total of 6 vmas
451 ASSERT_EQ(vmas.size(), 6);
Sandeep Patil82a48b12019-01-01 16:04:04 -0800452
453 // Expect values to be equal to what we have in testdata1/smaps_short
454 // Check for sizes first
455 ASSERT_EQ(vmas[0].usage.vss, 32768);
456 EXPECT_EQ(vmas[1].usage.vss, 11204);
457 EXPECT_EQ(vmas[2].usage.vss, 16896);
458 EXPECT_EQ(vmas[3].usage.vss, 260);
459 EXPECT_EQ(vmas[4].usage.vss, 6060);
460 EXPECT_EQ(vmas[5].usage.vss, 4);
461
462 // Check for names
463 EXPECT_EQ(vmas[0].name, "[anon:dalvik-zygote-jit-code-cache]");
464 EXPECT_EQ(vmas[1].name, "/system/framework/x86_64/boot-framework.art");
Christopher Ferris5db00922019-09-18 10:30:33 -0700465 EXPECT_TRUE(vmas[2].name == "[anon:libc_malloc]" ||
466 android::base::StartsWith(vmas[2].name, "[anon:scudo:"))
467 << "Unknown map name " << vmas[2].name;
Sandeep Patil82a48b12019-01-01 16:04:04 -0800468 EXPECT_EQ(vmas[3].name, "/system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex");
469 EXPECT_EQ(vmas[4].name, "/system/lib64/libhwui.so");
470 EXPECT_EQ(vmas[5].name, "[vsyscall]");
471
472 EXPECT_EQ(vmas[0].usage.rss, 2048);
473 EXPECT_EQ(vmas[1].usage.rss, 11188);
474 EXPECT_EQ(vmas[2].usage.rss, 15272);
475 EXPECT_EQ(vmas[3].usage.rss, 260);
476 EXPECT_EQ(vmas[4].usage.rss, 4132);
477 EXPECT_EQ(vmas[5].usage.rss, 0);
478
479 EXPECT_EQ(vmas[0].usage.pss, 113);
480 EXPECT_EQ(vmas[1].usage.pss, 2200);
481 EXPECT_EQ(vmas[2].usage.pss, 15272);
482 EXPECT_EQ(vmas[3].usage.pss, 260);
483 EXPECT_EQ(vmas[4].usage.pss, 1274);
484 EXPECT_EQ(vmas[5].usage.pss, 0);
485
486 EXPECT_EQ(vmas[0].usage.uss, 0);
487 EXPECT_EQ(vmas[1].usage.uss, 1660);
488 EXPECT_EQ(vmas[2].usage.uss, 15272);
489 EXPECT_EQ(vmas[3].usage.uss, 260);
490 EXPECT_EQ(vmas[4].usage.uss, 0);
491 EXPECT_EQ(vmas[5].usage.uss, 0);
492
493 EXPECT_EQ(vmas[0].usage.private_clean, 0);
494 EXPECT_EQ(vmas[1].usage.private_clean, 0);
495 EXPECT_EQ(vmas[2].usage.private_clean, 0);
496 EXPECT_EQ(vmas[3].usage.private_clean, 260);
497 EXPECT_EQ(vmas[4].usage.private_clean, 0);
498 EXPECT_EQ(vmas[5].usage.private_clean, 0);
499
500 EXPECT_EQ(vmas[0].usage.private_dirty, 0);
501 EXPECT_EQ(vmas[1].usage.private_dirty, 1660);
502 EXPECT_EQ(vmas[2].usage.private_dirty, 15272);
503 EXPECT_EQ(vmas[3].usage.private_dirty, 0);
504 EXPECT_EQ(vmas[4].usage.private_dirty, 0);
505 EXPECT_EQ(vmas[5].usage.private_dirty, 0);
506
507 EXPECT_EQ(vmas[0].usage.shared_clean, 0);
508 EXPECT_EQ(vmas[1].usage.shared_clean, 80);
509 EXPECT_EQ(vmas[2].usage.shared_clean, 0);
510 EXPECT_EQ(vmas[3].usage.shared_clean, 0);
511 EXPECT_EQ(vmas[4].usage.shared_clean, 4132);
512 EXPECT_EQ(vmas[5].usage.shared_clean, 0);
513
514 EXPECT_EQ(vmas[0].usage.shared_dirty, 2048);
515 EXPECT_EQ(vmas[1].usage.shared_dirty, 9448);
516 EXPECT_EQ(vmas[2].usage.shared_dirty, 0);
517 EXPECT_EQ(vmas[3].usage.shared_dirty, 0);
518 EXPECT_EQ(vmas[4].usage.shared_dirty, 0);
519 EXPECT_EQ(vmas[5].usage.shared_dirty, 0);
520
521 EXPECT_EQ(vmas[0].usage.swap, 0);
522 EXPECT_EQ(vmas[1].usage.swap, 0);
523 EXPECT_EQ(vmas[2].usage.swap, 0);
524 EXPECT_EQ(vmas[3].usage.swap, 0);
525 EXPECT_EQ(vmas[4].usage.swap, 0);
526 EXPECT_EQ(vmas[5].usage.swap, 0);
527
528 EXPECT_EQ(vmas[0].usage.swap_pss, 0);
529 EXPECT_EQ(vmas[1].usage.swap_pss, 0);
530 EXPECT_EQ(vmas[2].usage.swap_pss, 0);
531 EXPECT_EQ(vmas[3].usage.swap_pss, 0);
532 EXPECT_EQ(vmas[4].usage.swap_pss, 0);
533 EXPECT_EQ(vmas[5].usage.swap_pss, 0);
534}
535
Sandeep Patildfa00a72019-01-28 15:05:27 -0800536TEST(SysMemInfo, TestSysMemInfoFile) {
Sandeep Patil54d87212018-08-29 17:10:47 -0700537 std::string meminfo = R"meminfo(MemTotal: 3019740 kB
538MemFree: 1809728 kB
539MemAvailable: 2546560 kB
540Buffers: 54736 kB
541Cached: 776052 kB
542SwapCached: 0 kB
543Active: 445856 kB
544Inactive: 459092 kB
545Active(anon): 78492 kB
546Inactive(anon): 2240 kB
547Active(file): 367364 kB
548Inactive(file): 456852 kB
549Unevictable: 3096 kB
550Mlocked: 3096 kB
Sandeep Patil2f0b6eb2018-12-11 09:28:38 -0800551SwapTotal: 32768 kB
552SwapFree: 4096 kB
Sandeep Patil54d87212018-08-29 17:10:47 -0700553Dirty: 32 kB
554Writeback: 0 kB
555AnonPages: 74988 kB
556Mapped: 62624 kB
557Shmem: 4020 kB
558Slab: 86464 kB
559SReclaimable: 44432 kB
560SUnreclaim: 42032 kB
561KernelStack: 4880 kB
562PageTables: 2900 kB
563NFS_Unstable: 0 kB
564Bounce: 0 kB
565WritebackTmp: 0 kB
566CommitLimit: 1509868 kB
567Committed_AS: 80296 kB
568VmallocTotal: 263061440 kB
Sandeep Patil2f0b6eb2018-12-11 09:28:38 -0800569VmallocUsed: 65536 kB
Sandeep Patil54d87212018-08-29 17:10:47 -0700570VmallocChunk: 0 kB
571AnonHugePages: 6144 kB
572ShmemHugePages: 0 kB
573ShmemPmdMapped: 0 kB
574CmaTotal: 131072 kB
575CmaFree: 130380 kB
576HugePages_Total: 0
577HugePages_Free: 0
578HugePages_Rsvd: 0
579HugePages_Surp: 0
580Hugepagesize: 2048 kB)meminfo";
581
582 TemporaryFile tf;
583 ASSERT_TRUE(tf.fd != -1);
584 ASSERT_TRUE(::android::base::WriteStringToFd(meminfo, tf.fd));
585
586 SysMemInfo mi;
587 ASSERT_TRUE(mi.ReadMemInfo(tf.path));
588 EXPECT_EQ(mi.mem_total_kb(), 3019740);
Sandeep Patil2f0b6eb2018-12-11 09:28:38 -0800589 EXPECT_EQ(mi.mem_free_kb(), 1809728);
590 EXPECT_EQ(mi.mem_buffers_kb(), 54736);
591 EXPECT_EQ(mi.mem_cached_kb(), 776052);
592 EXPECT_EQ(mi.mem_shmem_kb(), 4020);
593 EXPECT_EQ(mi.mem_slab_kb(), 86464);
594 EXPECT_EQ(mi.mem_slab_reclaimable_kb(), 44432);
595 EXPECT_EQ(mi.mem_slab_unreclaimable_kb(), 42032);
596 EXPECT_EQ(mi.mem_swap_kb(), 32768);
597 EXPECT_EQ(mi.mem_swap_free_kb(), 4096);
598 EXPECT_EQ(mi.mem_mapped_kb(), 62624);
599 EXPECT_EQ(mi.mem_vmalloc_used_kb(), 65536);
Sandeep Patil54d87212018-08-29 17:10:47 -0700600 EXPECT_EQ(mi.mem_page_tables_kb(), 2900);
Sandeep Patil2f0b6eb2018-12-11 09:28:38 -0800601 EXPECT_EQ(mi.mem_kernel_stack_kb(), 4880);
Sandeep Patil54d87212018-08-29 17:10:47 -0700602}
603
Sandeep Patildfa00a72019-01-28 15:05:27 -0800604TEST(SysMemInfo, TestEmptyFile) {
Sandeep Patil54d87212018-08-29 17:10:47 -0700605 TemporaryFile tf;
606 std::string empty_string = "";
607 ASSERT_TRUE(tf.fd != -1);
608 ASSERT_TRUE(::android::base::WriteStringToFd(empty_string, tf.fd));
609
610 SysMemInfo mi;
611 EXPECT_TRUE(mi.ReadMemInfo(tf.path));
612 EXPECT_EQ(mi.mem_total_kb(), 0);
613}
614
Sandeep Patildfa00a72019-01-28 15:05:27 -0800615TEST(SysMemInfo, TestZramTotal) {
Sandeep Patil70fa72d2018-11-09 19:18:29 -0800616 std::string exec_dir = ::android::base::GetExecutableDirectory();
617
618 SysMemInfo mi;
619 std::string zram_mmstat_dir = exec_dir + "/testdata1/";
620 EXPECT_EQ(mi.mem_zram_kb(zram_mmstat_dir), 30504);
621
622 std::string zram_memused_dir = exec_dir + "/testdata2/";
623 EXPECT_EQ(mi.mem_zram_kb(zram_memused_dir), 30504);
624}
625
Sandeep Patil2f0b6eb2018-12-11 09:28:38 -0800626enum {
627 MEMINFO_TOTAL,
628 MEMINFO_FREE,
629 MEMINFO_BUFFERS,
630 MEMINFO_CACHED,
631 MEMINFO_SHMEM,
632 MEMINFO_SLAB,
633 MEMINFO_SLAB_RECLAIMABLE,
634 MEMINFO_SLAB_UNRECLAIMABLE,
635 MEMINFO_SWAP_TOTAL,
636 MEMINFO_SWAP_FREE,
637 MEMINFO_ZRAM_TOTAL,
638 MEMINFO_MAPPED,
639 MEMINFO_VMALLOC_USED,
640 MEMINFO_PAGE_TABLES,
641 MEMINFO_KERNEL_STACK,
642 MEMINFO_COUNT
643};
644
Sandeep Patildfa00a72019-01-28 15:05:27 -0800645TEST(SysMemInfo, TestZramWithTags) {
Sandeep Patil2f0b6eb2018-12-11 09:28:38 -0800646 std::string meminfo = R"meminfo(MemTotal: 3019740 kB
647MemFree: 1809728 kB
648MemAvailable: 2546560 kB
649Buffers: 54736 kB
650Cached: 776052 kB
651SwapCached: 0 kB
652Active: 445856 kB
653Inactive: 459092 kB
654Active(anon): 78492 kB
655Inactive(anon): 2240 kB
656Active(file): 367364 kB
657Inactive(file): 456852 kB
658Unevictable: 3096 kB
659Mlocked: 3096 kB
660SwapTotal: 32768 kB
661SwapFree: 4096 kB
662Dirty: 32 kB
663Writeback: 0 kB
664AnonPages: 74988 kB
665Mapped: 62624 kB
666Shmem: 4020 kB
667Slab: 86464 kB
668SReclaimable: 44432 kB
669SUnreclaim: 42032 kB
670KernelStack: 4880 kB
671PageTables: 2900 kB
672NFS_Unstable: 0 kB
673Bounce: 0 kB
674WritebackTmp: 0 kB
675CommitLimit: 1509868 kB
676Committed_AS: 80296 kB
677VmallocTotal: 263061440 kB
678VmallocUsed: 65536 kB
679VmallocChunk: 0 kB
680AnonHugePages: 6144 kB
681ShmemHugePages: 0 kB
682ShmemPmdMapped: 0 kB
683CmaTotal: 131072 kB
684CmaFree: 130380 kB
685HugePages_Total: 0
686HugePages_Free: 0
687HugePages_Rsvd: 0
688HugePages_Surp: 0
689Hugepagesize: 2048 kB)meminfo";
690
691 TemporaryFile tf;
692 ASSERT_TRUE(tf.fd != -1);
693 ASSERT_TRUE(::android::base::WriteStringToFd(meminfo, tf.fd));
694 std::string file = std::string(tf.path);
695 std::vector<uint64_t> mem(MEMINFO_COUNT);
696 std::vector<std::string> tags(SysMemInfo::kDefaultSysMemInfoTags);
697 auto it = tags.begin();
698 tags.insert(it + MEMINFO_ZRAM_TOTAL, "Zram:");
699 SysMemInfo mi;
700
701 // Read system memory info
702 EXPECT_TRUE(mi.ReadMemInfo(tags, &mem, file));
703
704 EXPECT_EQ(mem[MEMINFO_TOTAL], 3019740);
705 EXPECT_EQ(mem[MEMINFO_FREE], 1809728);
706 EXPECT_EQ(mem[MEMINFO_BUFFERS], 54736);
707 EXPECT_EQ(mem[MEMINFO_CACHED], 776052);
708 EXPECT_EQ(mem[MEMINFO_SHMEM], 4020);
709 EXPECT_EQ(mem[MEMINFO_SLAB], 86464);
710 EXPECT_EQ(mem[MEMINFO_SLAB_RECLAIMABLE], 44432);
711 EXPECT_EQ(mem[MEMINFO_SLAB_UNRECLAIMABLE], 42032);
712 EXPECT_EQ(mem[MEMINFO_SWAP_TOTAL], 32768);
713 EXPECT_EQ(mem[MEMINFO_SWAP_FREE], 4096);
714 EXPECT_EQ(mem[MEMINFO_MAPPED], 62624);
715 EXPECT_EQ(mem[MEMINFO_VMALLOC_USED], 65536);
716 EXPECT_EQ(mem[MEMINFO_PAGE_TABLES], 2900);
717 EXPECT_EQ(mem[MEMINFO_KERNEL_STACK], 4880);
718}
719
Sandeep Patildfa00a72019-01-28 15:05:27 -0800720TEST(SysMemInfo, TestVmallocInfoNoMemory) {
Sandeep Patilc24f1e32018-12-29 14:34:20 -0800721 std::string vmallocinfo =
722 R"vmallocinfo(0x0000000000000000-0x0000000000000000 69632 of_iomap+0x78/0xb0 phys=17a00000 ioremap
7230x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=b220000 ioremap
7240x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=17c90000 ioremap
7250x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=17ca0000 ioremap)vmallocinfo";
726
727 TemporaryFile tf;
728 ASSERT_TRUE(tf.fd != -1);
729 ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
730 std::string file = std::string(tf.path);
731
Sandeep Patile04680d2019-01-19 12:04:18 -0800732 EXPECT_EQ(ReadVmallocInfo(file), 0);
Sandeep Patilc24f1e32018-12-29 14:34:20 -0800733}
734
Sandeep Patildfa00a72019-01-28 15:05:27 -0800735TEST(SysMemInfo, TestVmallocInfoKernel) {
Sandeep Patilc24f1e32018-12-29 14:34:20 -0800736 std::string vmallocinfo =
737 R"vmallocinfo(0x0000000000000000-0x0000000000000000 8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc)vmallocinfo";
738
739 TemporaryFile tf;
740 ASSERT_TRUE(tf.fd != -1);
741 ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
742 std::string file = std::string(tf.path);
743
Sandeep Patile04680d2019-01-19 12:04:18 -0800744 EXPECT_EQ(ReadVmallocInfo(file), getpagesize());
Sandeep Patilc24f1e32018-12-29 14:34:20 -0800745}
746
Sandeep Patildfa00a72019-01-28 15:05:27 -0800747TEST(SysMemInfo, TestVmallocInfoModule) {
Sandeep Patilc24f1e32018-12-29 14:34:20 -0800748 std::string vmallocinfo =
749 R"vmallocinfo(0x0000000000000000-0x0000000000000000 28672 pktlog_alloc_buf+0xc4/0x15c [wlan] pages=6 vmalloc)vmallocinfo";
750
751 TemporaryFile tf;
752 ASSERT_TRUE(tf.fd != -1);
753 ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
754 std::string file = std::string(tf.path);
755
Sandeep Patile04680d2019-01-19 12:04:18 -0800756 EXPECT_EQ(ReadVmallocInfo(file), 6 * getpagesize());
Sandeep Patilc24f1e32018-12-29 14:34:20 -0800757}
758
Sandeep Patildfa00a72019-01-28 15:05:27 -0800759TEST(SysMemInfo, TestVmallocInfoAll) {
Sandeep Patilc24f1e32018-12-29 14:34:20 -0800760 std::string vmallocinfo =
761 R"vmallocinfo(0x0000000000000000-0x0000000000000000 69632 of_iomap+0x78/0xb0 phys=17a00000 ioremap
7620x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=b220000 ioremap
7630x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=17c90000 ioremap
7640x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=17ca0000 ioremap
7650x0000000000000000-0x0000000000000000 8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc
7660x0000000000000000-0x0000000000000000 28672 pktlog_alloc_buf+0xc4/0x15c [wlan] pages=6 vmalloc)vmallocinfo";
767
768 TemporaryFile tf;
769 ASSERT_TRUE(tf.fd != -1);
770 ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
771 std::string file = std::string(tf.path);
772
Sandeep Patile04680d2019-01-19 12:04:18 -0800773 EXPECT_EQ(ReadVmallocInfo(file), 7 * getpagesize());
Sandeep Patilc24f1e32018-12-29 14:34:20 -0800774}
775
Sandeep Patil54d87212018-08-29 17:10:47 -0700776int main(int argc, char** argv) {
777 ::testing::InitGoogleTest(&argc, argv);
Sandeep Patil54d87212018-08-29 17:10:47 -0700778 ::android::base::InitLogging(argv, android::base::StderrLogger);
Sandeep Patildfa00a72019-01-28 15:05:27 -0800779 pid = getpid();
Sandeep Patil54d87212018-08-29 17:10:47 -0700780 return RUN_ALL_TESTS();
781}