1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <sys/mman.h>
18 #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>
30 
31 #include <android-base/file.h>
32 #include <android-base/logging.h>
33 #include <android-base/stringprintf.h>
34 #include <android-base/strings.h>
35 
36 using namespace std;
37 using namespace android::meminfo;
38 
39 pid_t pid = -1;
40 
41 TEST(ProcMemInfo, TestWorkingTestReset) {
42     // Expect reset to succeed
43     EXPECT_TRUE(ProcMemInfo::ResetWorkingSet(pid));
44 }
45 
46 TEST(ProcMemInfo, UsageEmpty) {
47     // 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 
58 TEST(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 
65 TEST(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 
85 TEST(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 
104 TEST(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 
131 TEST(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 
189 TEST(ProcMemInfo, WssEmpty) {
190     // 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 
201 TEST(ProcMemInfo, SwapOffsetsEmpty) {
202     // 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<uint64_t>& swap_offsets = proc_mem.SwapOffsets();
206     EXPECT_EQ(swap_offsets.size(), 0);
207 }
208 
209 TEST(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.
213     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 
221 TEST(ProcMemInfo, SmapsOrRollupTest) {
222     // Make sure we can parse 'smaps_rollup' correctly
223     std::string rollup =
224             R"rollup(12c00000-7fe859e000 ---p 00000000 00:00 0                                [rollup]
225 Rss:              331908 kB
226 Pss:              202052 kB
227 Shared_Clean:     158492 kB
228 Shared_Dirty:      18928 kB
229 Private_Clean:     90472 kB
230 Private_Dirty:     64016 kB
231 Referenced:       318700 kB
232 Anonymous:         81984 kB
233 AnonHugePages:         0 kB
234 Shared_Hugetlb:        0 kB
235 Private_Hugetlb:       0 kB
236 Swap:               5344 kB
237 SwapPss:             442 kB
238 Locked:          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 
254 TEST(ProcMemInfo, SmapsOrRollupSmapsTest) {
255     // Make sure /proc/<pid>/smaps is parsed correctly
256     std::string smaps =
257             R"smaps(12c00000-13440000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
258 Name:           [anon:dalvik-main space (region space)]
259 Size:               8448 kB
260 KernelPageSize:        4 kB
261 MMUPageSize:           4 kB
262 Rss:                2652 kB
263 Pss:                2652 kB
264 Shared_Clean:        840 kB
265 Shared_Dirty:         40 kB
266 Private_Clean:        84 kB
267 Private_Dirty:      2652 kB
268 Referenced:         2652 kB
269 Anonymous:          2652 kB
270 AnonHugePages:         0 kB
271 ShmemPmdMapped:        0 kB
272 Shared_Hugetlb:        0 kB
273 Private_Hugetlb:       0 kB
274 Swap:                102 kB
275 SwapPss:              70 kB
276 Locked:             2652 kB
277 VmFlags: 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 
294 TEST(ProcMemInfo, SmapsOrRollupPssRollupTest) {
295     // Make sure /proc/<pid>/smaps is parsed correctly
296     // to get the PSS
297     std::string smaps =
298             R"smaps(12c00000-13440000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
299 Name:           [anon:dalvik-main space (region space)]
300 Size:               8448 kB
301 KernelPageSize:        4 kB
302 MMUPageSize:           4 kB
303 Rss:                2652 kB
304 Pss:                2652 kB
305 Shared_Clean:        840 kB
306 Shared_Dirty:         40 kB
307 Private_Clean:        84 kB
308 Private_Dirty:      2652 kB
309 Referenced:         2652 kB
310 Anonymous:          2652 kB
311 AnonHugePages:         0 kB
312 ShmemPmdMapped:        0 kB
313 Shared_Hugetlb:        0 kB
314 Private_Hugetlb:       0 kB
315 Swap:                102 kB
316 SwapPss:              70 kB
317 Locked:             2652 kB
318 VmFlags: 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 
330 TEST(ProcMemInfo, SmapsOrRollupPssSmapsTest) {
331     // Correctly parse smaps file to gather pss
332     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 
340 TEST(ProcMemInfo, ForEachVmaFromFileTest) {
341     // Parse smaps file correctly to make callbacks for each virtual memory area (vma)
342     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 
350     // We should get a total of 6 vmas
351     ASSERT_EQ(vmas.size(), 6);
352 
353     // 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");
365     EXPECT_TRUE(vmas[2].name == "[anon:libc_malloc]" ||
366                 android::base::StartsWith(vmas[2].name, "[anon:scudo:"))
367             << "Unknown map name " << vmas[2].name;
368     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 
436 TEST(ProcMemInfo, SmapsReturnTest) {
437     // Make sure Smaps() is never empty for any process
438     ProcMemInfo proc_mem(pid);
439     auto vmas = proc_mem.Smaps();
440     EXPECT_FALSE(vmas.empty());
441 }
442 
443 TEST(ProcMemInfo, SmapsTest) {
444     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());
450     // We should get a total of 6 vmas
451     ASSERT_EQ(vmas.size(), 6);
452 
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");
465     EXPECT_TRUE(vmas[2].name == "[anon:libc_malloc]" ||
466                 android::base::StartsWith(vmas[2].name, "[anon:scudo:"))
467             << "Unknown map name " << vmas[2].name;
468     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 
536 TEST(SysMemInfo, TestSysMemInfoFile) {
537     std::string meminfo = R"meminfo(MemTotal:        3019740 kB
538 MemFree:         1809728 kB
539 MemAvailable:    2546560 kB
540 Buffers:           54736 kB
541 Cached:           776052 kB
542 SwapCached:            0 kB
543 Active:           445856 kB
544 Inactive:         459092 kB
545 Active(anon):      78492 kB
546 Inactive(anon):     2240 kB
547 Active(file):     367364 kB
548 Inactive(file):   456852 kB
549 Unevictable:        3096 kB
550 Mlocked:            3096 kB
551 SwapTotal:         32768 kB
552 SwapFree:           4096 kB
553 Dirty:                32 kB
554 Writeback:             0 kB
555 AnonPages:         74988 kB
556 Mapped:            62624 kB
557 Shmem:              4020 kB
558 KReclaimable:      87324 kB
559 Slab:              86464 kB
560 SReclaimable:      44432 kB
561 SUnreclaim:        42032 kB
562 KernelStack:        4880 kB
563 PageTables:         2900 kB
564 NFS_Unstable:          0 kB
565 Bounce:                0 kB
566 WritebackTmp:          0 kB
567 CommitLimit:     1509868 kB
568 Committed_AS:      80296 kB
569 VmallocTotal:   263061440 kB
570 VmallocUsed:       65536 kB
571 VmallocChunk:          0 kB
572 AnonHugePages:      6144 kB
573 ShmemHugePages:        0 kB
574 ShmemPmdMapped:        0 kB
575 CmaTotal:         131072 kB
576 CmaFree:          130380 kB
577 HugePages_Total:       0
578 HugePages_Free:        0
579 HugePages_Rsvd:        0
580 HugePages_Surp:        0
581 Hugepagesize:       2048 kB)meminfo";
582 
583     TemporaryFile tf;
584     ASSERT_TRUE(tf.fd != -1);
585     ASSERT_TRUE(::android::base::WriteStringToFd(meminfo, tf.fd));
586 
587     SysMemInfo mi;
588     ASSERT_TRUE(mi.ReadMemInfo(tf.path));
589     EXPECT_EQ(mi.mem_total_kb(), 3019740);
590     EXPECT_EQ(mi.mem_free_kb(), 1809728);
591     EXPECT_EQ(mi.mem_buffers_kb(), 54736);
592     EXPECT_EQ(mi.mem_cached_kb(), 776052);
593     EXPECT_EQ(mi.mem_shmem_kb(), 4020);
594     EXPECT_EQ(mi.mem_slab_kb(), 86464);
595     EXPECT_EQ(mi.mem_slab_reclaimable_kb(), 44432);
596     EXPECT_EQ(mi.mem_slab_unreclaimable_kb(), 42032);
597     EXPECT_EQ(mi.mem_swap_kb(), 32768);
598     EXPECT_EQ(mi.mem_swap_free_kb(), 4096);
599     EXPECT_EQ(mi.mem_mapped_kb(), 62624);
600     EXPECT_EQ(mi.mem_vmalloc_used_kb(), 65536);
601     EXPECT_EQ(mi.mem_page_tables_kb(), 2900);
602     EXPECT_EQ(mi.mem_kernel_stack_kb(), 4880);
603     EXPECT_EQ(mi.mem_kreclaimable_kb(), 87324);
604 }
605 
606 TEST(SysMemInfo, TestEmptyFile) {
607     TemporaryFile tf;
608     std::string empty_string = "";
609     ASSERT_TRUE(tf.fd != -1);
610     ASSERT_TRUE(::android::base::WriteStringToFd(empty_string, tf.fd));
611 
612     SysMemInfo mi;
613     EXPECT_TRUE(mi.ReadMemInfo(tf.path));
614     EXPECT_EQ(mi.mem_total_kb(), 0);
615 }
616 
617 TEST(SysMemInfo, TestZramTotal) {
618     std::string exec_dir = ::android::base::GetExecutableDirectory();
619 
620     SysMemInfo mi;
621     std::string zram_mmstat_dir = exec_dir + "/testdata1/";
622     EXPECT_EQ(mi.mem_zram_kb(zram_mmstat_dir.c_str()), 30504);
623 
624     std::string zram_memused_dir = exec_dir + "/testdata2/";
625     EXPECT_EQ(mi.mem_zram_kb(zram_memused_dir.c_str()), 30504);
626 }
627 
628 enum {
629     MEMINFO_TOTAL,
630     MEMINFO_FREE,
631     MEMINFO_BUFFERS,
632     MEMINFO_CACHED,
633     MEMINFO_SHMEM,
634     MEMINFO_SLAB,
635     MEMINFO_SLAB_RECLAIMABLE,
636     MEMINFO_SLAB_UNRECLAIMABLE,
637     MEMINFO_SWAP_TOTAL,
638     MEMINFO_SWAP_FREE,
639     MEMINFO_ZRAM_TOTAL,
640     MEMINFO_MAPPED,
641     MEMINFO_VMALLOC_USED,
642     MEMINFO_PAGE_TABLES,
643     MEMINFO_KERNEL_STACK,
644     MEMINFO_KRECLAIMABLE,
645     MEMINFO_COUNT
646 };
647 
648 TEST(SysMemInfo, TestZramWithTags) {
649     std::string meminfo = R"meminfo(MemTotal:        3019740 kB
650 MemFree:         1809728 kB
651 MemAvailable:    2546560 kB
652 Buffers:           54736 kB
653 Cached:           776052 kB
654 SwapCached:            0 kB
655 Active:           445856 kB
656 Inactive:         459092 kB
657 Active(anon):      78492 kB
658 Inactive(anon):     2240 kB
659 Active(file):     367364 kB
660 Inactive(file):   456852 kB
661 Unevictable:        3096 kB
662 Mlocked:            3096 kB
663 SwapTotal:         32768 kB
664 SwapFree:           4096 kB
665 Dirty:                32 kB
666 Writeback:             0 kB
667 AnonPages:         74988 kB
668 Mapped:            62624 kB
669 Shmem:              4020 kB
670 KReclaimable:      87324 kB
671 Slab:              86464 kB
672 SReclaimable:      44432 kB
673 SUnreclaim:        42032 kB
674 KernelStack:        4880 kB
675 PageTables:         2900 kB
676 NFS_Unstable:          0 kB
677 Bounce:                0 kB
678 WritebackTmp:          0 kB
679 CommitLimit:     1509868 kB
680 Committed_AS:      80296 kB
681 VmallocTotal:   263061440 kB
682 VmallocUsed:       65536 kB
683 VmallocChunk:          0 kB
684 AnonHugePages:      6144 kB
685 ShmemHugePages:        0 kB
686 ShmemPmdMapped:        0 kB
687 CmaTotal:         131072 kB
688 CmaFree:          130380 kB
689 HugePages_Total:       0
690 HugePages_Free:        0
691 HugePages_Rsvd:        0
692 HugePages_Surp:        0
693 Hugepagesize:       2048 kB)meminfo";
694 
695     TemporaryFile tf;
696     ASSERT_TRUE(tf.fd != -1);
697     ASSERT_TRUE(::android::base::WriteStringToFd(meminfo, tf.fd));
698     std::string file = std::string(tf.path);
699     std::vector<uint64_t> mem;
700     std::vector<std::string_view> tags(SysMemInfo::kDefaultSysMemInfoTags.begin(),
701                                        SysMemInfo::kDefaultSysMemInfoTags.end());
702     auto it = tags.begin();
703     tags.insert(it + MEMINFO_ZRAM_TOTAL, "Zram:");
704     SysMemInfo mi;
705 
706     // Read system memory info
707     mem.resize(tags.size());
708     EXPECT_TRUE(mi.ReadMemInfo(tags.size(), tags.data(), mem.data(), file.c_str()));
709     EXPECT_EQ(mem[MEMINFO_TOTAL], 3019740);
710     EXPECT_EQ(mem[MEMINFO_FREE], 1809728);
711     EXPECT_EQ(mem[MEMINFO_BUFFERS], 54736);
712     EXPECT_EQ(mem[MEMINFO_CACHED], 776052);
713     EXPECT_EQ(mem[MEMINFO_SHMEM], 4020);
714     EXPECT_EQ(mem[MEMINFO_SLAB], 86464);
715     EXPECT_EQ(mem[MEMINFO_SLAB_RECLAIMABLE], 44432);
716     EXPECT_EQ(mem[MEMINFO_SLAB_UNRECLAIMABLE], 42032);
717     EXPECT_EQ(mem[MEMINFO_SWAP_TOTAL], 32768);
718     EXPECT_EQ(mem[MEMINFO_SWAP_FREE], 4096);
719     EXPECT_EQ(mem[MEMINFO_MAPPED], 62624);
720     EXPECT_EQ(mem[MEMINFO_VMALLOC_USED], 65536);
721     EXPECT_EQ(mem[MEMINFO_PAGE_TABLES], 2900);
722     EXPECT_EQ(mem[MEMINFO_KERNEL_STACK], 4880);
723     EXPECT_EQ(mem[MEMINFO_KRECLAIMABLE], 87324);
724 }
725 
726 TEST(SysMemInfo, TestVmallocInfoNoMemory) {
727     std::string vmallocinfo =
728             R"vmallocinfo(0x0000000000000000-0x0000000000000000   69632 of_iomap+0x78/0xb0 phys=17a00000 ioremap
729 0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=b220000 ioremap
730 0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=17c90000 ioremap
731 0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=17ca0000 ioremap)vmallocinfo";
732 
733     TemporaryFile tf;
734     ASSERT_TRUE(tf.fd != -1);
735     ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
736     std::string file = std::string(tf.path);
737 
738     EXPECT_EQ(ReadVmallocInfo(file.c_str()), 0);
739 }
740 
741 TEST(SysMemInfo, TestVmallocInfoKernel) {
742     std::string vmallocinfo =
743             R"vmallocinfo(0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc)vmallocinfo";
744 
745     TemporaryFile tf;
746     ASSERT_TRUE(tf.fd != -1);
747     ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
748     std::string file = std::string(tf.path);
749 
750     EXPECT_EQ(ReadVmallocInfo(file.c_str()), getpagesize());
751 }
752 
753 TEST(SysMemInfo, TestVmallocInfoModule) {
754     std::string vmallocinfo =
755             R"vmallocinfo(0x0000000000000000-0x0000000000000000   28672 pktlog_alloc_buf+0xc4/0x15c [wlan] pages=6 vmalloc)vmallocinfo";
756 
757     TemporaryFile tf;
758     ASSERT_TRUE(tf.fd != -1);
759     ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
760     std::string file = std::string(tf.path);
761 
762     EXPECT_EQ(ReadVmallocInfo(file.c_str()), 6 * getpagesize());
763 }
764 
765 TEST(SysMemInfo, TestVmallocInfoAll) {
766     std::string vmallocinfo =
767             R"vmallocinfo(0x0000000000000000-0x0000000000000000   69632 of_iomap+0x78/0xb0 phys=17a00000 ioremap
768 0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=b220000 ioremap
769 0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=17c90000 ioremap
770 0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=17ca0000 ioremap
771 0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc
772 0x0000000000000000-0x0000000000000000   28672 pktlog_alloc_buf+0xc4/0x15c [wlan] pages=6 vmalloc)vmallocinfo";
773 
774     TemporaryFile tf;
775     ASSERT_TRUE(tf.fd != -1);
776     ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
777     std::string file = std::string(tf.path);
778 
779     EXPECT_EQ(ReadVmallocInfo(file.c_str()), 7 * getpagesize());
780 }
781 
782 TEST(SysMemInfo, TestReadIonHeapsSizeKb) {
783     std::string total_heaps_kb = R"total_heaps_kb(98480)total_heaps_kb";
784     uint64_t size;
785 
786     TemporaryFile tf;
787     ASSERT_TRUE(tf.fd != -1);
788     ASSERT_TRUE(::android::base::WriteStringToFd(total_heaps_kb, tf.fd));
789     std::string file = std::string(tf.path);
790 
791     ASSERT_TRUE(ReadIonHeapsSizeKb(&size, file));
792     EXPECT_EQ(size, 98480);
793 }
794 
795 TEST(SysMemInfo, TestReadIonPoolsSizeKb) {
796     std::string total_pools_kb = R"total_pools_kb(416)total_pools_kb";
797     uint64_t size;
798 
799     TemporaryFile tf;
800     ASSERT_TRUE(tf.fd != -1);
801     ASSERT_TRUE(::android::base::WriteStringToFd(total_pools_kb, tf.fd));
802     std::string file = std::string(tf.path);
803 
804     ASSERT_TRUE(ReadIonPoolsSizeKb(&size, file));
805     EXPECT_EQ(size, 416);
806 }
807 
808 int main(int argc, char** argv) {
809     ::testing::InitGoogleTest(&argc, argv);
810     ::android::base::InitLogging(argv, android::base::StderrLogger);
811     pid = getpid();
812     return RUN_ALL_TESTS();
813 }
814