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