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