blob: e689a26795edece55c362986f43e7303e830182f [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
17#include <sys/types.h>
18#include <sys/wait.h>
19#include <unistd.h>
20
21#include <gtest/gtest.h>
22
23#include <string>
24#include <vector>
25
26#include <meminfo/pageacct.h>
27#include <meminfo/procmeminfo.h>
28#include <meminfo/sysmeminfo.h>
29#include <pagemap/pagemap.h>
30
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>
Sandeep Patil54d87212018-08-29 17:10:47 -070034
35using namespace std;
36using namespace android::meminfo;
37
38pid_t pid = -1;
39
40class ValidateProcMemInfo : public ::testing::Test {
41 protected:
42 void SetUp() override {
43 ASSERT_EQ(0, pm_kernel_create(&ker));
44 ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
45 proc_mem = new ProcMemInfo(pid);
46 ASSERT_NE(proc_mem, nullptr);
47 }
48
49 void TearDown() override {
50 delete proc_mem;
51 pm_process_destroy(proc);
52 pm_kernel_destroy(ker);
53 }
54
55 pm_kernel_t* ker;
56 pm_process_t* proc;
57 ProcMemInfo* proc_mem;
58};
59
60TEST_F(ValidateProcMemInfo, TestMapsSize) {
61 const std::vector<Vma>& maps = proc_mem->Maps();
62 ASSERT_FALSE(maps.empty()) << "Process " << getpid() << " maps are empty";
63}
64
65TEST_F(ValidateProcMemInfo, TestMapsEquality) {
66 const std::vector<Vma>& maps = proc_mem->Maps();
67 ASSERT_EQ(proc->num_maps, maps.size());
68
69 for (size_t i = 0; i < maps.size(); ++i) {
70 EXPECT_EQ(proc->maps[i]->start, maps[i].start);
71 EXPECT_EQ(proc->maps[i]->end, maps[i].end);
72 EXPECT_EQ(proc->maps[i]->offset, maps[i].offset);
73 EXPECT_EQ(std::string(proc->maps[i]->name), maps[i].name);
74 }
75}
76
Sandeep Patil2259fdf2018-11-09 16:42:45 -080077TEST_F(ValidateProcMemInfo, TestMaps) {
Sandeep Patil54d87212018-08-29 17:10:47 -070078 const std::vector<Vma>& maps = proc_mem->Maps();
79 ASSERT_FALSE(maps.empty());
80 ASSERT_EQ(proc->num_maps, maps.size());
81
82 pm_memusage_t map_usage, proc_usage;
83 pm_memusage_zero(&map_usage);
84 pm_memusage_zero(&proc_usage);
85 for (size_t i = 0; i < maps.size(); i++) {
86 ASSERT_EQ(0, pm_map_usage(proc->maps[i], &map_usage));
87 EXPECT_EQ(map_usage.vss, maps[i].usage.vss) << "VSS mismatch for map: " << maps[i].name;
88 EXPECT_EQ(map_usage.rss, maps[i].usage.rss) << "RSS mismatch for map: " << maps[i].name;
89 EXPECT_EQ(map_usage.pss, maps[i].usage.pss) << "PSS mismatch for map: " << maps[i].name;
90 EXPECT_EQ(map_usage.uss, maps[i].usage.uss) << "USS mismatch for map: " << maps[i].name;
91 pm_memusage_add(&proc_usage, &map_usage);
92 }
93
94 EXPECT_EQ(proc_usage.vss, proc_mem->Usage().vss);
95 EXPECT_EQ(proc_usage.rss, proc_mem->Usage().rss);
96 EXPECT_EQ(proc_usage.pss, proc_mem->Usage().pss);
97 EXPECT_EQ(proc_usage.uss, proc_mem->Usage().uss);
98}
99
Sandeep Patil2259fdf2018-11-09 16:42:45 -0800100TEST_F(ValidateProcMemInfo, TestSwapUsage) {
101 const std::vector<Vma>& maps = proc_mem->Maps();
102 ASSERT_FALSE(maps.empty());
103 ASSERT_EQ(proc->num_maps, maps.size());
104
105 pm_memusage_t map_usage, proc_usage;
106 pm_memusage_zero(&map_usage);
107 pm_memusage_zero(&proc_usage);
108 for (size_t i = 0; i < maps.size(); i++) {
109 ASSERT_EQ(0, pm_map_usage(proc->maps[i], &map_usage));
110 EXPECT_EQ(map_usage.swap, maps[i].usage.swap) << "SWAP mismatch for map: " << maps[i].name;
111 pm_memusage_add(&proc_usage, &map_usage);
112 }
113
114 EXPECT_EQ(proc_usage.swap, proc_mem->Usage().swap);
115}
116
117TEST_F(ValidateProcMemInfo, TestSwapOffsets) {
118 const MemUsage& proc_usage = proc_mem->Usage();
119 const std::vector<uint16_t>& swap_offsets = proc_mem->SwapOffsets();
120
121 EXPECT_EQ(proc_usage.swap / getpagesize(), swap_offsets.size());
122}
123
Sandeep Patil54d87212018-08-29 17:10:47 -0700124class ValidateProcMemInfoWss : public ::testing::Test {
125 protected:
126 void SetUp() override {
127 ASSERT_EQ(0, pm_kernel_create(&ker));
128 ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
129 proc_mem = new ProcMemInfo(pid, true);
130 ASSERT_NE(proc_mem, nullptr);
131 }
132
133 void TearDown() override {
134 delete proc_mem;
135 pm_process_destroy(proc);
136 pm_kernel_destroy(ker);
137 }
138
139 pm_kernel_t* ker;
140 pm_process_t* proc;
141 ProcMemInfo* proc_mem;
142};
143
144TEST_F(ValidateProcMemInfoWss, TestWorkingTestReset) {
145 // Expect reset to succeed
Sandeep Patilf1291992018-11-19 15:25:18 -0800146 EXPECT_TRUE(ProcMemInfo::ResetWorkingSet(pid));
Sandeep Patil54d87212018-08-29 17:10:47 -0700147}
148
149TEST_F(ValidateProcMemInfoWss, TestWssEquality) {
150 // Read wss using libpagemap
151 pm_memusage_t wss_pagemap;
152 EXPECT_EQ(0, pm_process_workingset(proc, &wss_pagemap, 0));
153
154 // Read wss using libmeminfo
155 MemUsage wss = proc_mem->Wss();
156
157 // compare
158 EXPECT_EQ(wss_pagemap.rss, wss.rss);
159 EXPECT_EQ(wss_pagemap.pss, wss.pss);
160 EXPECT_EQ(wss_pagemap.uss, wss.uss);
161}
162
163class ValidatePageAcct : public ::testing::Test {
164 protected:
165 void SetUp() override {
166 ASSERT_EQ(0, pm_kernel_create(&ker));
167 ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
168 }
169
170 void TearDown() override {
171 pm_process_destroy(proc);
172 pm_kernel_destroy(ker);
173 }
174
175 pm_kernel_t* ker;
176 pm_process_t* proc;
177};
178
179TEST_F(ValidatePageAcct, TestPageFlags) {
180 PageAcct& pi = PageAcct::Instance();
181 pi.InitPageAcct(false);
182
183 uint64_t* pagemap;
184 size_t num_pages;
185 for (size_t i = 0; i < proc->num_maps; i++) {
186 ASSERT_EQ(0, pm_map_pagemap(proc->maps[i], &pagemap, &num_pages));
187 for (size_t j = 0; j < num_pages; j++) {
188 if (!PM_PAGEMAP_PRESENT(pagemap[j])) continue;
189
190 uint64_t pfn = PM_PAGEMAP_PFN(pagemap[j]);
191 uint64_t page_flags_pagemap, page_flags_meminfo;
192
193 ASSERT_EQ(0, pm_kernel_flags(ker, pfn, &page_flags_pagemap));
194 ASSERT_TRUE(pi.PageFlags(pfn, &page_flags_meminfo));
195 // check if page flags equal
196 EXPECT_EQ(page_flags_pagemap, page_flags_meminfo);
197 }
198 free(pagemap);
199 }
200}
201
202TEST_F(ValidatePageAcct, TestPageCounts) {
203 PageAcct& pi = PageAcct::Instance();
204 pi.InitPageAcct(false);
205
206 uint64_t* pagemap;
207 size_t num_pages;
208 for (size_t i = 0; i < proc->num_maps; i++) {
209 ASSERT_EQ(0, pm_map_pagemap(proc->maps[i], &pagemap, &num_pages));
210 for (size_t j = 0; j < num_pages; j++) {
211 uint64_t pfn = PM_PAGEMAP_PFN(pagemap[j]);
212 uint64_t map_count_pagemap, map_count_meminfo;
213
214 ASSERT_EQ(0, pm_kernel_count(ker, pfn, &map_count_pagemap));
215 ASSERT_TRUE(pi.PageMapCount(pfn, &map_count_meminfo));
216 // check if map counts are equal
217 EXPECT_EQ(map_count_pagemap, map_count_meminfo);
218 }
219 free(pagemap);
220 }
221}
222
223TEST_F(ValidatePageAcct, TestPageIdle) {
224 // skip the test if idle page tracking isn't enabled
225 if (pm_kernel_init_page_idle(ker) != 0) {
226 return;
227 }
228
229 PageAcct& pi = PageAcct::Instance();
230 ASSERT_TRUE(pi.InitPageAcct(true));
231
232 uint64_t* pagemap;
233 size_t num_pages;
234 for (size_t i = 0; i < proc->num_maps; i++) {
235 ASSERT_EQ(0, pm_map_pagemap(proc->maps[i], &pagemap, &num_pages));
236 for (size_t j = 0; j < num_pages; j++) {
237 if (!PM_PAGEMAP_PRESENT(pagemap[j])) continue;
238 uint64_t pfn = PM_PAGEMAP_PFN(pagemap[j]);
239
240 ASSERT_EQ(0, pm_kernel_mark_page_idle(ker, &pfn, 1));
241 int idle_status_pagemap = pm_kernel_get_page_idle(ker, pfn);
242 int idle_status_meminfo = pi.IsPageIdle(pfn);
243 EXPECT_EQ(idle_status_pagemap, idle_status_meminfo);
244 }
245 free(pagemap);
246 }
247}
248
Sandeep Patilfa2d8d52018-12-29 21:05:38 -0800249TEST(TestProcMemInfo, MapsEmpty) {
Sandeep Patilc6497eb2018-11-20 09:31:36 -0800250 ProcMemInfo proc_mem(pid);
251 const std::vector<Vma>& maps = proc_mem.Maps();
252 EXPECT_GT(maps.size(), 0);
253}
254
Sandeep Patilfa2d8d52018-12-29 21:05:38 -0800255TEST(TestProcMemInfo, UsageEmpty) {
Sandeep Patilc6497eb2018-11-20 09:31:36 -0800256 // If we created the object for getting working set,
257 // the usage must be empty
258 ProcMemInfo proc_mem(pid, true);
259 const MemUsage& usage = proc_mem.Usage();
260 EXPECT_EQ(usage.rss, 0);
261 EXPECT_EQ(usage.vss, 0);
262 EXPECT_EQ(usage.pss, 0);
263 EXPECT_EQ(usage.uss, 0);
264 EXPECT_EQ(usage.swap, 0);
265}
266
Sandeep Patilfa2d8d52018-12-29 21:05:38 -0800267TEST(TestProcMemInfo, WssEmpty) {
Sandeep Patilc6497eb2018-11-20 09:31:36 -0800268 // If we created the object for getting usage,
269 // the working set must be empty
270 ProcMemInfo proc_mem(pid, false);
271 const MemUsage& wss = proc_mem.Wss();
272 EXPECT_EQ(wss.rss, 0);
273 EXPECT_EQ(wss.vss, 0);
274 EXPECT_EQ(wss.pss, 0);
275 EXPECT_EQ(wss.uss, 0);
276 EXPECT_EQ(wss.swap, 0);
277}
278
Sandeep Patilfa2d8d52018-12-29 21:05:38 -0800279TEST(TestProcMemInfo, SwapOffsetsEmpty) {
Sandeep Patilc6497eb2018-11-20 09:31:36 -0800280 // If we created the object for getting working set,
281 // the swap offsets must be empty
282 ProcMemInfo proc_mem(pid, true);
283 const std::vector<uint16_t>& swap_offsets = proc_mem.SwapOffsets();
284 EXPECT_EQ(swap_offsets.size(), 0);
285}
286
Sandeep Patildfd34be2019-01-13 17:39:08 -0800287TEST(TestProcMemInfo, IsSmapsSupportedTest) {
288 std::string path = ::android::base::StringPrintf("/proc/%d/smaps_rollup", pid);
289 bool supported = IsSmapsRollupSupported(pid);
290 EXPECT_EQ(!access(path.c_str(), F_OK | R_OK), supported);
291 // Second call must return what the first one returned regardless of the pid parameter.
292 // So, deliberately pass invalid pid.
293 EXPECT_EQ(supported, IsSmapsRollupSupported(-1));
294}
295
Sandeep Patilfa2d8d52018-12-29 21:05:38 -0800296TEST(TestProcMemInfo, SmapsOrRollupReturn) {
297 // if /proc/<pid>/smaps_rollup file exists, .SmapsRollup() must return true;
298 // false otherwise
299 std::string path = ::android::base::StringPrintf("/proc/%d/smaps_rollup", pid);
300 ProcMemInfo proc_mem(pid);
301 MemUsage stats;
Sandeep Patildfd34be2019-01-13 17:39:08 -0800302 EXPECT_EQ(!access(path.c_str(), F_OK), proc_mem.SmapsOrRollup(&stats));
Sandeep Patilfa2d8d52018-12-29 21:05:38 -0800303}
304
305TEST(TestProcMemInfo, SmapsOrRollupTest) {
306 std::string rollup =
307 R"rollup(12c00000-7fe859e000 ---p 00000000 00:00 0 [rollup]
308Rss: 331908 kB
309Pss: 202052 kB
310Shared_Clean: 158492 kB
311Shared_Dirty: 18928 kB
312Private_Clean: 90472 kB
313Private_Dirty: 64016 kB
314Referenced: 318700 kB
315Anonymous: 81984 kB
316AnonHugePages: 0 kB
317Shared_Hugetlb: 0 kB
318Private_Hugetlb: 0 kB
319Swap: 5344 kB
320SwapPss: 442 kB
321Locked: 1523537 kB)rollup";
322
323 TemporaryFile tf;
324 ASSERT_TRUE(tf.fd != -1);
325 ASSERT_TRUE(::android::base::WriteStringToFd(rollup, tf.fd));
326
327 MemUsage stats;
328 ASSERT_EQ(SmapsOrRollupFromFile(tf.path, &stats), true);
329 EXPECT_EQ(stats.rss, 331908);
330 EXPECT_EQ(stats.pss, 202052);
331 EXPECT_EQ(stats.uss, 154488);
332 EXPECT_EQ(stats.private_clean, 90472);
333 EXPECT_EQ(stats.private_dirty, 64016);
334 EXPECT_EQ(stats.swap_pss, 442);
335}
336
337TEST(TestProcMemInfo, SmapsOrRollupSmapsTest) {
338 // This is a made up smaps for the test
339 std::string smaps =
340 R"smaps(12c00000-13440000 rw-p 00000000 00:00 0 [anon:dalvik-main space (region space)]
341Name: [anon:dalvik-main space (region space)]
342Size: 8448 kB
343KernelPageSize: 4 kB
344MMUPageSize: 4 kB
345Rss: 2652 kB
346Pss: 2652 kB
347Shared_Clean: 840 kB
348Shared_Dirty: 40 kB
349Private_Clean: 84 kB
350Private_Dirty: 2652 kB
351Referenced: 2652 kB
352Anonymous: 2652 kB
353AnonHugePages: 0 kB
354ShmemPmdMapped: 0 kB
355Shared_Hugetlb: 0 kB
356Private_Hugetlb: 0 kB
357Swap: 102 kB
358SwapPss: 70 kB
359Locked: 2652 kB
360VmFlags: rd wr mr mw me ac
361)smaps";
362
363 TemporaryFile tf;
364 ASSERT_TRUE(tf.fd != -1);
365 ASSERT_TRUE(::android::base::WriteStringToFd(smaps, tf.fd));
366
367 MemUsage stats;
368 ASSERT_EQ(SmapsOrRollupFromFile(tf.path, &stats), true);
369 EXPECT_EQ(stats.rss, 2652);
370 EXPECT_EQ(stats.pss, 2652);
371 EXPECT_EQ(stats.uss, 2736);
372 EXPECT_EQ(stats.private_clean, 84);
373 EXPECT_EQ(stats.private_dirty, 2652);
374 EXPECT_EQ(stats.swap_pss, 70);
375}
376
Sandeep Patil8871e7e2019-01-13 16:47:20 -0800377TEST(TestProcMemInfo, SmapsOrRollupPssRollupTest) {
378 // This is a made up smaps for the test
379 std::string smaps =
380 R"smaps(12c00000-13440000 rw-p 00000000 00:00 0 [anon:dalvik-main space (region space)]
381Name: [anon:dalvik-main space (region space)]
382Size: 8448 kB
383KernelPageSize: 4 kB
384MMUPageSize: 4 kB
385Rss: 2652 kB
386Pss: 2652 kB
387Shared_Clean: 840 kB
388Shared_Dirty: 40 kB
389Private_Clean: 84 kB
390Private_Dirty: 2652 kB
391Referenced: 2652 kB
392Anonymous: 2652 kB
393AnonHugePages: 0 kB
394ShmemPmdMapped: 0 kB
395Shared_Hugetlb: 0 kB
396Private_Hugetlb: 0 kB
397Swap: 102 kB
398SwapPss: 70 kB
399Locked: 2652 kB
400VmFlags: rd wr mr mw me ac
401)smaps";
402
403 TemporaryFile tf;
404 ASSERT_TRUE(tf.fd != -1);
405 ASSERT_TRUE(::android::base::WriteStringToFd(smaps, tf.fd));
406
407 uint64_t pss;
408 ASSERT_EQ(SmapsOrRollupPssFromFile(tf.path, &pss), true);
409 EXPECT_EQ(pss, 2652);
410}
411
412TEST(TestProcMemInfo, SmapsOrRollupPssSmapsTest) {
413 std::string exec_dir = ::android::base::GetExecutableDirectory();
414 std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
415
416 uint64_t pss;
417 ASSERT_EQ(SmapsOrRollupPssFromFile(path, &pss), true);
418 EXPECT_EQ(pss, 19119);
419}
420
Sandeep Patil82a48b12019-01-01 16:04:04 -0800421TEST(TestProcMemInfo, ForEachVmaFromFileTest) {
422 std::string exec_dir = ::android::base::GetExecutableDirectory();
423 std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
424 ProcMemInfo proc_mem(pid);
425
426 std::vector<Vma> vmas;
427 auto collect_vmas = [&](const Vma& v) { vmas.push_back(v); };
428 ASSERT_TRUE(ForEachVmaFromFile(path, collect_vmas));
429
Sandeep Patil002f02e2019-01-13 19:39:46 -0800430 // We should get a total of 6 vmas
431 ASSERT_EQ(vmas.size(), 6);
432
Sandeep Patil82a48b12019-01-01 16:04:04 -0800433 // Expect values to be equal to what we have in testdata1/smaps_short
434 // Check for sizes first
435 ASSERT_EQ(vmas[0].usage.vss, 32768);
436 EXPECT_EQ(vmas[1].usage.vss, 11204);
437 EXPECT_EQ(vmas[2].usage.vss, 16896);
438 EXPECT_EQ(vmas[3].usage.vss, 260);
439 EXPECT_EQ(vmas[4].usage.vss, 6060);
440 EXPECT_EQ(vmas[5].usage.vss, 4);
441
442 // Check for names
443 EXPECT_EQ(vmas[0].name, "[anon:dalvik-zygote-jit-code-cache]");
444 EXPECT_EQ(vmas[1].name, "/system/framework/x86_64/boot-framework.art");
445 EXPECT_EQ(vmas[2].name, "[anon:libc_malloc]");
446 EXPECT_EQ(vmas[3].name, "/system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex");
447 EXPECT_EQ(vmas[4].name, "/system/lib64/libhwui.so");
448 EXPECT_EQ(vmas[5].name, "[vsyscall]");
449
450 EXPECT_EQ(vmas[0].usage.rss, 2048);
451 EXPECT_EQ(vmas[1].usage.rss, 11188);
452 EXPECT_EQ(vmas[2].usage.rss, 15272);
453 EXPECT_EQ(vmas[3].usage.rss, 260);
454 EXPECT_EQ(vmas[4].usage.rss, 4132);
455 EXPECT_EQ(vmas[5].usage.rss, 0);
456
457 EXPECT_EQ(vmas[0].usage.pss, 113);
458 EXPECT_EQ(vmas[1].usage.pss, 2200);
459 EXPECT_EQ(vmas[2].usage.pss, 15272);
460 EXPECT_EQ(vmas[3].usage.pss, 260);
461 EXPECT_EQ(vmas[4].usage.pss, 1274);
462 EXPECT_EQ(vmas[5].usage.pss, 0);
463
464 EXPECT_EQ(vmas[0].usage.uss, 0);
465 EXPECT_EQ(vmas[1].usage.uss, 1660);
466 EXPECT_EQ(vmas[2].usage.uss, 15272);
467 EXPECT_EQ(vmas[3].usage.uss, 260);
468 EXPECT_EQ(vmas[4].usage.uss, 0);
469 EXPECT_EQ(vmas[5].usage.uss, 0);
470
471 EXPECT_EQ(vmas[0].usage.private_clean, 0);
472 EXPECT_EQ(vmas[1].usage.private_clean, 0);
473 EXPECT_EQ(vmas[2].usage.private_clean, 0);
474 EXPECT_EQ(vmas[3].usage.private_clean, 260);
475 EXPECT_EQ(vmas[4].usage.private_clean, 0);
476 EXPECT_EQ(vmas[5].usage.private_clean, 0);
477
478 EXPECT_EQ(vmas[0].usage.private_dirty, 0);
479 EXPECT_EQ(vmas[1].usage.private_dirty, 1660);
480 EXPECT_EQ(vmas[2].usage.private_dirty, 15272);
481 EXPECT_EQ(vmas[3].usage.private_dirty, 0);
482 EXPECT_EQ(vmas[4].usage.private_dirty, 0);
483 EXPECT_EQ(vmas[5].usage.private_dirty, 0);
484
485 EXPECT_EQ(vmas[0].usage.shared_clean, 0);
486 EXPECT_EQ(vmas[1].usage.shared_clean, 80);
487 EXPECT_EQ(vmas[2].usage.shared_clean, 0);
488 EXPECT_EQ(vmas[3].usage.shared_clean, 0);
489 EXPECT_EQ(vmas[4].usage.shared_clean, 4132);
490 EXPECT_EQ(vmas[5].usage.shared_clean, 0);
491
492 EXPECT_EQ(vmas[0].usage.shared_dirty, 2048);
493 EXPECT_EQ(vmas[1].usage.shared_dirty, 9448);
494 EXPECT_EQ(vmas[2].usage.shared_dirty, 0);
495 EXPECT_EQ(vmas[3].usage.shared_dirty, 0);
496 EXPECT_EQ(vmas[4].usage.shared_dirty, 0);
497 EXPECT_EQ(vmas[5].usage.shared_dirty, 0);
498
499 EXPECT_EQ(vmas[0].usage.swap, 0);
500 EXPECT_EQ(vmas[1].usage.swap, 0);
501 EXPECT_EQ(vmas[2].usage.swap, 0);
502 EXPECT_EQ(vmas[3].usage.swap, 0);
503 EXPECT_EQ(vmas[4].usage.swap, 0);
504 EXPECT_EQ(vmas[5].usage.swap, 0);
505
506 EXPECT_EQ(vmas[0].usage.swap_pss, 0);
507 EXPECT_EQ(vmas[1].usage.swap_pss, 0);
508 EXPECT_EQ(vmas[2].usage.swap_pss, 0);
509 EXPECT_EQ(vmas[3].usage.swap_pss, 0);
510 EXPECT_EQ(vmas[4].usage.swap_pss, 0);
511 EXPECT_EQ(vmas[5].usage.swap_pss, 0);
512}
513
514TEST(TestProcMemInfo, SmapsReturnTest) {
515 ProcMemInfo proc_mem(pid);
516 auto vmas = proc_mem.Smaps();
517 EXPECT_FALSE(vmas.empty());
518}
519
520TEST(TestProcMemInfo, SmapsTest) {
521 std::string exec_dir = ::android::base::GetExecutableDirectory();
522 std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
523 ProcMemInfo proc_mem(pid);
524 auto vmas = proc_mem.Smaps(path);
525
526 ASSERT_FALSE(vmas.empty());
Sandeep Patil002f02e2019-01-13 19:39:46 -0800527 // We should get a total of 6 vmas
528 ASSERT_EQ(vmas.size(), 6);
Sandeep Patil82a48b12019-01-01 16:04:04 -0800529
530 // Expect values to be equal to what we have in testdata1/smaps_short
531 // Check for sizes first
532 ASSERT_EQ(vmas[0].usage.vss, 32768);
533 EXPECT_EQ(vmas[1].usage.vss, 11204);
534 EXPECT_EQ(vmas[2].usage.vss, 16896);
535 EXPECT_EQ(vmas[3].usage.vss, 260);
536 EXPECT_EQ(vmas[4].usage.vss, 6060);
537 EXPECT_EQ(vmas[5].usage.vss, 4);
538
539 // Check for names
540 EXPECT_EQ(vmas[0].name, "[anon:dalvik-zygote-jit-code-cache]");
541 EXPECT_EQ(vmas[1].name, "/system/framework/x86_64/boot-framework.art");
542 EXPECT_EQ(vmas[2].name, "[anon:libc_malloc]");
543 EXPECT_EQ(vmas[3].name, "/system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex");
544 EXPECT_EQ(vmas[4].name, "/system/lib64/libhwui.so");
545 EXPECT_EQ(vmas[5].name, "[vsyscall]");
546
547 EXPECT_EQ(vmas[0].usage.rss, 2048);
548 EXPECT_EQ(vmas[1].usage.rss, 11188);
549 EXPECT_EQ(vmas[2].usage.rss, 15272);
550 EXPECT_EQ(vmas[3].usage.rss, 260);
551 EXPECT_EQ(vmas[4].usage.rss, 4132);
552 EXPECT_EQ(vmas[5].usage.rss, 0);
553
554 EXPECT_EQ(vmas[0].usage.pss, 113);
555 EXPECT_EQ(vmas[1].usage.pss, 2200);
556 EXPECT_EQ(vmas[2].usage.pss, 15272);
557 EXPECT_EQ(vmas[3].usage.pss, 260);
558 EXPECT_EQ(vmas[4].usage.pss, 1274);
559 EXPECT_EQ(vmas[5].usage.pss, 0);
560
561 EXPECT_EQ(vmas[0].usage.uss, 0);
562 EXPECT_EQ(vmas[1].usage.uss, 1660);
563 EXPECT_EQ(vmas[2].usage.uss, 15272);
564 EXPECT_EQ(vmas[3].usage.uss, 260);
565 EXPECT_EQ(vmas[4].usage.uss, 0);
566 EXPECT_EQ(vmas[5].usage.uss, 0);
567
568 EXPECT_EQ(vmas[0].usage.private_clean, 0);
569 EXPECT_EQ(vmas[1].usage.private_clean, 0);
570 EXPECT_EQ(vmas[2].usage.private_clean, 0);
571 EXPECT_EQ(vmas[3].usage.private_clean, 260);
572 EXPECT_EQ(vmas[4].usage.private_clean, 0);
573 EXPECT_EQ(vmas[5].usage.private_clean, 0);
574
575 EXPECT_EQ(vmas[0].usage.private_dirty, 0);
576 EXPECT_EQ(vmas[1].usage.private_dirty, 1660);
577 EXPECT_EQ(vmas[2].usage.private_dirty, 15272);
578 EXPECT_EQ(vmas[3].usage.private_dirty, 0);
579 EXPECT_EQ(vmas[4].usage.private_dirty, 0);
580 EXPECT_EQ(vmas[5].usage.private_dirty, 0);
581
582 EXPECT_EQ(vmas[0].usage.shared_clean, 0);
583 EXPECT_EQ(vmas[1].usage.shared_clean, 80);
584 EXPECT_EQ(vmas[2].usage.shared_clean, 0);
585 EXPECT_EQ(vmas[3].usage.shared_clean, 0);
586 EXPECT_EQ(vmas[4].usage.shared_clean, 4132);
587 EXPECT_EQ(vmas[5].usage.shared_clean, 0);
588
589 EXPECT_EQ(vmas[0].usage.shared_dirty, 2048);
590 EXPECT_EQ(vmas[1].usage.shared_dirty, 9448);
591 EXPECT_EQ(vmas[2].usage.shared_dirty, 0);
592 EXPECT_EQ(vmas[3].usage.shared_dirty, 0);
593 EXPECT_EQ(vmas[4].usage.shared_dirty, 0);
594 EXPECT_EQ(vmas[5].usage.shared_dirty, 0);
595
596 EXPECT_EQ(vmas[0].usage.swap, 0);
597 EXPECT_EQ(vmas[1].usage.swap, 0);
598 EXPECT_EQ(vmas[2].usage.swap, 0);
599 EXPECT_EQ(vmas[3].usage.swap, 0);
600 EXPECT_EQ(vmas[4].usage.swap, 0);
601 EXPECT_EQ(vmas[5].usage.swap, 0);
602
603 EXPECT_EQ(vmas[0].usage.swap_pss, 0);
604 EXPECT_EQ(vmas[1].usage.swap_pss, 0);
605 EXPECT_EQ(vmas[2].usage.swap_pss, 0);
606 EXPECT_EQ(vmas[3].usage.swap_pss, 0);
607 EXPECT_EQ(vmas[4].usage.swap_pss, 0);
608 EXPECT_EQ(vmas[5].usage.swap_pss, 0);
609}
610
Sandeep Patil549feab2018-11-19 11:38:40 -0800611TEST(ValidateProcMemInfoFlags, TestPageFlags1) {
612 // Create proc object using libpagemap
613 pm_kernel_t* ker;
614 ASSERT_EQ(0, pm_kernel_create(&ker));
615 pm_process_t* proc;
616 ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
617
618 // count swapbacked pages using libpagemap
619 pm_memusage_t proc_usage;
620 pm_memusage_zero(&proc_usage);
621 ASSERT_EQ(0, pm_process_usage_flags(proc, &proc_usage, (1 << KPF_SWAPBACKED),
622 (1 << KPF_SWAPBACKED)));
623
624 // Create ProcMemInfo that counts swapbacked pages
625 ProcMemInfo proc_mem(pid, false, (1 << KPF_SWAPBACKED), (1 << KPF_SWAPBACKED));
626
627 EXPECT_EQ(proc_usage.vss, proc_mem.Usage().vss);
628 EXPECT_EQ(proc_usage.rss, proc_mem.Usage().rss);
629 EXPECT_EQ(proc_usage.pss, proc_mem.Usage().pss);
630 EXPECT_EQ(proc_usage.uss, proc_mem.Usage().uss);
631
632 pm_process_destroy(proc);
633 pm_kernel_destroy(ker);
634}
635
636TEST(ValidateProcMemInfoFlags, TestPageFlags2) {
637 // Create proc object using libpagemap
638 pm_kernel_t* ker;
639 ASSERT_EQ(0, pm_kernel_create(&ker));
640 pm_process_t* proc;
641 ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
642
643 // count non-swapbacked pages using libpagemap
644 pm_memusage_t proc_usage;
645 pm_memusage_zero(&proc_usage);
646 ASSERT_EQ(0, pm_process_usage_flags(proc, &proc_usage, (1 << KPF_SWAPBACKED), 0));
647
648 // Create ProcMemInfo that counts non-swapbacked pages
649 ProcMemInfo proc_mem(pid, false, 0, (1 << KPF_SWAPBACKED));
650
651 EXPECT_EQ(proc_usage.vss, proc_mem.Usage().vss);
652 EXPECT_EQ(proc_usage.rss, proc_mem.Usage().rss);
653 EXPECT_EQ(proc_usage.pss, proc_mem.Usage().pss);
654 EXPECT_EQ(proc_usage.uss, proc_mem.Usage().uss);
655
656 pm_process_destroy(proc);
657 pm_kernel_destroy(ker);
658}
659
Sandeep Patil54d87212018-08-29 17:10:47 -0700660TEST(SysMemInfoParser, TestSysMemInfoFile) {
661 std::string meminfo = R"meminfo(MemTotal: 3019740 kB
662MemFree: 1809728 kB
663MemAvailable: 2546560 kB
664Buffers: 54736 kB
665Cached: 776052 kB
666SwapCached: 0 kB
667Active: 445856 kB
668Inactive: 459092 kB
669Active(anon): 78492 kB
670Inactive(anon): 2240 kB
671Active(file): 367364 kB
672Inactive(file): 456852 kB
673Unevictable: 3096 kB
674Mlocked: 3096 kB
Sandeep Patil2f0b6eb2018-12-11 09:28:38 -0800675SwapTotal: 32768 kB
676SwapFree: 4096 kB
Sandeep Patil54d87212018-08-29 17:10:47 -0700677Dirty: 32 kB
678Writeback: 0 kB
679AnonPages: 74988 kB
680Mapped: 62624 kB
681Shmem: 4020 kB
682Slab: 86464 kB
683SReclaimable: 44432 kB
684SUnreclaim: 42032 kB
685KernelStack: 4880 kB
686PageTables: 2900 kB
687NFS_Unstable: 0 kB
688Bounce: 0 kB
689WritebackTmp: 0 kB
690CommitLimit: 1509868 kB
691Committed_AS: 80296 kB
692VmallocTotal: 263061440 kB
Sandeep Patil2f0b6eb2018-12-11 09:28:38 -0800693VmallocUsed: 65536 kB
Sandeep Patil54d87212018-08-29 17:10:47 -0700694VmallocChunk: 0 kB
695AnonHugePages: 6144 kB
696ShmemHugePages: 0 kB
697ShmemPmdMapped: 0 kB
698CmaTotal: 131072 kB
699CmaFree: 130380 kB
700HugePages_Total: 0
701HugePages_Free: 0
702HugePages_Rsvd: 0
703HugePages_Surp: 0
704Hugepagesize: 2048 kB)meminfo";
705
706 TemporaryFile tf;
707 ASSERT_TRUE(tf.fd != -1);
708 ASSERT_TRUE(::android::base::WriteStringToFd(meminfo, tf.fd));
709
710 SysMemInfo mi;
711 ASSERT_TRUE(mi.ReadMemInfo(tf.path));
712 EXPECT_EQ(mi.mem_total_kb(), 3019740);
Sandeep Patil2f0b6eb2018-12-11 09:28:38 -0800713 EXPECT_EQ(mi.mem_free_kb(), 1809728);
714 EXPECT_EQ(mi.mem_buffers_kb(), 54736);
715 EXPECT_EQ(mi.mem_cached_kb(), 776052);
716 EXPECT_EQ(mi.mem_shmem_kb(), 4020);
717 EXPECT_EQ(mi.mem_slab_kb(), 86464);
718 EXPECT_EQ(mi.mem_slab_reclaimable_kb(), 44432);
719 EXPECT_EQ(mi.mem_slab_unreclaimable_kb(), 42032);
720 EXPECT_EQ(mi.mem_swap_kb(), 32768);
721 EXPECT_EQ(mi.mem_swap_free_kb(), 4096);
722 EXPECT_EQ(mi.mem_mapped_kb(), 62624);
723 EXPECT_EQ(mi.mem_vmalloc_used_kb(), 65536);
Sandeep Patil54d87212018-08-29 17:10:47 -0700724 EXPECT_EQ(mi.mem_page_tables_kb(), 2900);
Sandeep Patil2f0b6eb2018-12-11 09:28:38 -0800725 EXPECT_EQ(mi.mem_kernel_stack_kb(), 4880);
Sandeep Patil54d87212018-08-29 17:10:47 -0700726}
727
728TEST(SysMemInfoParser, TestEmptyFile) {
729 TemporaryFile tf;
730 std::string empty_string = "";
731 ASSERT_TRUE(tf.fd != -1);
732 ASSERT_TRUE(::android::base::WriteStringToFd(empty_string, tf.fd));
733
734 SysMemInfo mi;
735 EXPECT_TRUE(mi.ReadMemInfo(tf.path));
736 EXPECT_EQ(mi.mem_total_kb(), 0);
737}
738
Sandeep Patil2f0b6eb2018-12-11 09:28:38 -0800739TEST(SysMemInfoParser, TestZramTotal) {
Sandeep Patil70fa72d2018-11-09 19:18:29 -0800740 std::string exec_dir = ::android::base::GetExecutableDirectory();
741
742 SysMemInfo mi;
743 std::string zram_mmstat_dir = exec_dir + "/testdata1/";
744 EXPECT_EQ(mi.mem_zram_kb(zram_mmstat_dir), 30504);
745
746 std::string zram_memused_dir = exec_dir + "/testdata2/";
747 EXPECT_EQ(mi.mem_zram_kb(zram_memused_dir), 30504);
748}
749
Sandeep Patil2f0b6eb2018-12-11 09:28:38 -0800750enum {
751 MEMINFO_TOTAL,
752 MEMINFO_FREE,
753 MEMINFO_BUFFERS,
754 MEMINFO_CACHED,
755 MEMINFO_SHMEM,
756 MEMINFO_SLAB,
757 MEMINFO_SLAB_RECLAIMABLE,
758 MEMINFO_SLAB_UNRECLAIMABLE,
759 MEMINFO_SWAP_TOTAL,
760 MEMINFO_SWAP_FREE,
761 MEMINFO_ZRAM_TOTAL,
762 MEMINFO_MAPPED,
763 MEMINFO_VMALLOC_USED,
764 MEMINFO_PAGE_TABLES,
765 MEMINFO_KERNEL_STACK,
766 MEMINFO_COUNT
767};
768
769TEST(SysMemInfoParser, TestZramWithTags) {
770 std::string meminfo = R"meminfo(MemTotal: 3019740 kB
771MemFree: 1809728 kB
772MemAvailable: 2546560 kB
773Buffers: 54736 kB
774Cached: 776052 kB
775SwapCached: 0 kB
776Active: 445856 kB
777Inactive: 459092 kB
778Active(anon): 78492 kB
779Inactive(anon): 2240 kB
780Active(file): 367364 kB
781Inactive(file): 456852 kB
782Unevictable: 3096 kB
783Mlocked: 3096 kB
784SwapTotal: 32768 kB
785SwapFree: 4096 kB
786Dirty: 32 kB
787Writeback: 0 kB
788AnonPages: 74988 kB
789Mapped: 62624 kB
790Shmem: 4020 kB
791Slab: 86464 kB
792SReclaimable: 44432 kB
793SUnreclaim: 42032 kB
794KernelStack: 4880 kB
795PageTables: 2900 kB
796NFS_Unstable: 0 kB
797Bounce: 0 kB
798WritebackTmp: 0 kB
799CommitLimit: 1509868 kB
800Committed_AS: 80296 kB
801VmallocTotal: 263061440 kB
802VmallocUsed: 65536 kB
803VmallocChunk: 0 kB
804AnonHugePages: 6144 kB
805ShmemHugePages: 0 kB
806ShmemPmdMapped: 0 kB
807CmaTotal: 131072 kB
808CmaFree: 130380 kB
809HugePages_Total: 0
810HugePages_Free: 0
811HugePages_Rsvd: 0
812HugePages_Surp: 0
813Hugepagesize: 2048 kB)meminfo";
814
815 TemporaryFile tf;
816 ASSERT_TRUE(tf.fd != -1);
817 ASSERT_TRUE(::android::base::WriteStringToFd(meminfo, tf.fd));
818 std::string file = std::string(tf.path);
819 std::vector<uint64_t> mem(MEMINFO_COUNT);
820 std::vector<std::string> tags(SysMemInfo::kDefaultSysMemInfoTags);
821 auto it = tags.begin();
822 tags.insert(it + MEMINFO_ZRAM_TOTAL, "Zram:");
823 SysMemInfo mi;
824
825 // Read system memory info
826 EXPECT_TRUE(mi.ReadMemInfo(tags, &mem, file));
827
828 EXPECT_EQ(mem[MEMINFO_TOTAL], 3019740);
829 EXPECT_EQ(mem[MEMINFO_FREE], 1809728);
830 EXPECT_EQ(mem[MEMINFO_BUFFERS], 54736);
831 EXPECT_EQ(mem[MEMINFO_CACHED], 776052);
832 EXPECT_EQ(mem[MEMINFO_SHMEM], 4020);
833 EXPECT_EQ(mem[MEMINFO_SLAB], 86464);
834 EXPECT_EQ(mem[MEMINFO_SLAB_RECLAIMABLE], 44432);
835 EXPECT_EQ(mem[MEMINFO_SLAB_UNRECLAIMABLE], 42032);
836 EXPECT_EQ(mem[MEMINFO_SWAP_TOTAL], 32768);
837 EXPECT_EQ(mem[MEMINFO_SWAP_FREE], 4096);
838 EXPECT_EQ(mem[MEMINFO_MAPPED], 62624);
839 EXPECT_EQ(mem[MEMINFO_VMALLOC_USED], 65536);
840 EXPECT_EQ(mem[MEMINFO_PAGE_TABLES], 2900);
841 EXPECT_EQ(mem[MEMINFO_KERNEL_STACK], 4880);
842}
843
Sandeep Patilc24f1e32018-12-29 14:34:20 -0800844TEST(SysMemInfoParser, TestVmallocInfoNoMemory) {
845 std::string vmallocinfo =
846 R"vmallocinfo(0x0000000000000000-0x0000000000000000 69632 of_iomap+0x78/0xb0 phys=17a00000 ioremap
8470x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=b220000 ioremap
8480x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=17c90000 ioremap
8490x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=17ca0000 ioremap)vmallocinfo";
850
851 TemporaryFile tf;
852 ASSERT_TRUE(tf.fd != -1);
853 ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
854 std::string file = std::string(tf.path);
855
856 SysMemInfo smi;
857 EXPECT_EQ(smi.ReadVmallocInfo(file), 0);
858}
859
860TEST(SysMemInfoParser, TestVmallocInfoKernel) {
861 std::string vmallocinfo =
862 R"vmallocinfo(0x0000000000000000-0x0000000000000000 8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc)vmallocinfo";
863
864 TemporaryFile tf;
865 ASSERT_TRUE(tf.fd != -1);
866 ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
867 std::string file = std::string(tf.path);
868
869 SysMemInfo smi;
870 EXPECT_EQ(smi.ReadVmallocInfo(file), getpagesize());
871}
872
873TEST(SysMemInfoParser, TestVmallocInfoModule) {
874 std::string vmallocinfo =
875 R"vmallocinfo(0x0000000000000000-0x0000000000000000 28672 pktlog_alloc_buf+0xc4/0x15c [wlan] pages=6 vmalloc)vmallocinfo";
876
877 TemporaryFile tf;
878 ASSERT_TRUE(tf.fd != -1);
879 ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
880 std::string file = std::string(tf.path);
881
882 SysMemInfo smi;
883 EXPECT_EQ(smi.ReadVmallocInfo(file), 6 * getpagesize());
884}
885
886TEST(SysMemInfoParser, TestVmallocInfoAll) {
887 std::string vmallocinfo =
888 R"vmallocinfo(0x0000000000000000-0x0000000000000000 69632 of_iomap+0x78/0xb0 phys=17a00000 ioremap
8890x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=b220000 ioremap
8900x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=17c90000 ioremap
8910x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=17ca0000 ioremap
8920x0000000000000000-0x0000000000000000 8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc
8930x0000000000000000-0x0000000000000000 28672 pktlog_alloc_buf+0xc4/0x15c [wlan] pages=6 vmalloc)vmallocinfo";
894
895 TemporaryFile tf;
896 ASSERT_TRUE(tf.fd != -1);
897 ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
898 std::string file = std::string(tf.path);
899
900 SysMemInfo smi;
901 EXPECT_EQ(smi.ReadVmallocInfo(file), 7 * getpagesize());
902}
903
Sandeep Patil54d87212018-08-29 17:10:47 -0700904int main(int argc, char** argv) {
905 ::testing::InitGoogleTest(&argc, argv);
906 if (argc <= 1) {
907 cerr << "Pid of a permanently sleeping process must be provided." << endl;
908 exit(EXIT_FAILURE);
909 }
910 ::android::base::InitLogging(argv, android::base::StderrLogger);
911 pid = std::stoi(std::string(argv[1]));
912 return RUN_ALL_TESTS();
913}