1 // Copyright 2015 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/android/library_loader/library_prefetcher.h" 6 7 #include <stddef.h> 8 #include <stdint.h> 9 #include <sys/mman.h> 10 #include <string> 11 #include <vector> 12 #include "base/debug/proc_maps_linux.h" 13 #include "base/memory/shared_memory.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 namespace base { 17 namespace android { 18 19 namespace { 20 const uint8_t kRead = base::debug::MappedMemoryRegion::READ; 21 const uint8_t kReadPrivate = base::debug::MappedMemoryRegion::READ | 22 base::debug::MappedMemoryRegion::PRIVATE; 23 const uint8_t kExecutePrivate = base::debug::MappedMemoryRegion::EXECUTE | 24 base::debug::MappedMemoryRegion::PRIVATE; 25 const size_t kPageSize = 4096; 26 } // namespace 27 28 TEST(NativeLibraryPrefetcherTest, TestIsGoodToPrefetchNoRange) { 29 const base::debug::MappedMemoryRegion regions[4] = { 30 base::debug::MappedMemoryRegion{0x4000, 0x5000, 10, kReadPrivate, ""}, 31 base::debug::MappedMemoryRegion{0x4000, 0x5000, 10, kReadPrivate, "foo"}, 32 base::debug::MappedMemoryRegion{ 33 0x4000, 0x5000, 10, kReadPrivate, "foobar.apk"}, 34 base::debug::MappedMemoryRegion{ 35 0x4000, 0x5000, 10, kReadPrivate, "libchromium.so"}}; 36 for (int i = 0; i < 4; ++i) { 37 ASSERT_FALSE(NativeLibraryPrefetcher::IsGoodToPrefetch(regions[i])); 38 } 39 } 40 41 TEST(NativeLibraryPrefetcherTest, TestIsGoodToPrefetchUnreadableRange) { 42 const base::debug::MappedMemoryRegion region = { 43 0x4000, 0x5000, 10, kExecutePrivate, "base.apk"}; 44 ASSERT_FALSE(NativeLibraryPrefetcher::IsGoodToPrefetch(region)); 45 } 46 47 TEST(NativeLibraryPrefetcherTest, TestIsGoodToPrefetchSkipSharedRange) { 48 const base::debug::MappedMemoryRegion region = { 49 0x4000, 0x5000, 10, kRead, "base.apk"}; 50 ASSERT_FALSE(NativeLibraryPrefetcher::IsGoodToPrefetch(region)); 51 } 52 53 TEST(NativeLibraryPrefetcherTest, TestIsGoodToPrefetchLibchromeRange) { 54 const base::debug::MappedMemoryRegion region = { 55 0x4000, 0x5000, 10, kReadPrivate, "libchrome.so"}; 56 ASSERT_TRUE(NativeLibraryPrefetcher::IsGoodToPrefetch(region)); 57 } 58 59 TEST(NativeLibraryPrefetcherTest, TestIsGoodToPrefetchBaseApkRange) { 60 const base::debug::MappedMemoryRegion region = { 61 0x4000, 0x5000, 10, kReadPrivate, "base.apk"}; 62 ASSERT_TRUE(NativeLibraryPrefetcher::IsGoodToPrefetch(region)); 63 } 64 65 TEST(NativeLibraryPrefetcherTest, 66 TestFilterLibchromeRangesOnlyIfPossibleNoLibchrome) { 67 std::vector<base::debug::MappedMemoryRegion> regions; 68 regions.push_back( 69 base::debug::MappedMemoryRegion{0x1, 0x2, 0, kReadPrivate, "base.apk"}); 70 regions.push_back( 71 base::debug::MappedMemoryRegion{0x3, 0x4, 0, kReadPrivate, "base.apk"}); 72 std::vector<NativeLibraryPrefetcher::AddressRange> ranges; 73 NativeLibraryPrefetcher::FilterLibchromeRangesOnlyIfPossible(regions, 74 &ranges); 75 EXPECT_EQ(ranges.size(), 2U); 76 EXPECT_EQ(ranges[0].first, 0x1U); 77 EXPECT_EQ(ranges[0].second, 0x2U); 78 EXPECT_EQ(ranges[1].first, 0x3U); 79 EXPECT_EQ(ranges[1].second, 0x4U); 80 } 81 82 TEST(NativeLibraryPrefetcherTest, 83 TestFilterLibchromeRangesOnlyIfPossibleHasLibchrome) { 84 std::vector<base::debug::MappedMemoryRegion> regions; 85 regions.push_back( 86 base::debug::MappedMemoryRegion{0x1, 0x2, 0, kReadPrivate, "base.apk"}); 87 regions.push_back(base::debug::MappedMemoryRegion{ 88 0x6, 0x7, 0, kReadPrivate, "libchrome.so"}); 89 regions.push_back( 90 base::debug::MappedMemoryRegion{0x3, 0x4, 0, kReadPrivate, "base.apk"}); 91 std::vector<NativeLibraryPrefetcher::AddressRange> ranges; 92 NativeLibraryPrefetcher::FilterLibchromeRangesOnlyIfPossible(regions, 93 &ranges); 94 EXPECT_EQ(ranges.size(), 1U); 95 EXPECT_EQ(ranges[0].first, 0x6U); 96 EXPECT_EQ(ranges[0].second, 0x7U); 97 } 98 99 TEST(NativeLibraryPrefetcherTest, DISABLED_TestPercentageOfResidentCode) { 100 size_t length = 4 * kPageSize; 101 base::SharedMemory shared_mem; 102 ASSERT_TRUE(shared_mem.CreateAndMapAnonymous(length)); 103 void* address = shared_mem.memory(); 104 105 std::vector<NativeLibraryPrefetcher::AddressRange> ranges = { 106 {reinterpret_cast<uintptr_t>(address), 107 reinterpret_cast<uintptr_t>(address) + length}}; 108 109 // Remove everything. 110 ASSERT_EQ(0, madvise(address, length, MADV_DONTNEED)); 111 // TODO(lizeb): If flaky, mock mincore(). 112 EXPECT_EQ(0, NativeLibraryPrefetcher::PercentageOfResidentCode(ranges)); 113 114 // Get everything back. 115 ASSERT_EQ(0, mlock(address, length)); 116 EXPECT_EQ(100, NativeLibraryPrefetcher::PercentageOfResidentCode(ranges)); 117 munlock(address, length); 118 } 119 120 TEST(NativeLibraryPrefetcherTest, 121 DISABLED_TestPercentageOfResidentCodeTwoRegions) { 122 size_t length = 4 * kPageSize; 123 base::SharedMemory shared_mem; 124 ASSERT_TRUE(shared_mem.CreateAndMapAnonymous(length)); 125 void* address = shared_mem.memory(); 126 127 size_t length2 = 8 * kPageSize; 128 base::SharedMemory shared_mem2; 129 ASSERT_TRUE(shared_mem2.CreateAndMapAnonymous(length2)); 130 void* address2 = shared_mem2.memory(); 131 132 std::vector<NativeLibraryPrefetcher::AddressRange> ranges = { 133 {reinterpret_cast<uintptr_t>(address), 134 reinterpret_cast<uintptr_t>(address) + length}, 135 {reinterpret_cast<uintptr_t>(address2), 136 reinterpret_cast<uintptr_t>(address2) + length2}}; 137 138 // Remove everything. 139 ASSERT_EQ(0, madvise(address, length, MADV_DONTNEED)); 140 ASSERT_EQ(0, madvise(address2, length, MADV_DONTNEED)); 141 // TODO(lizeb): If flaky, mock mincore(). 142 EXPECT_EQ(0, NativeLibraryPrefetcher::PercentageOfResidentCode(ranges)); 143 144 // Get back the first range. 145 ASSERT_EQ(0, mlock(address, length)); 146 EXPECT_EQ(33, NativeLibraryPrefetcher::PercentageOfResidentCode(ranges)); 147 // The second one. 148 ASSERT_EQ(0, mlock(address2, length2)); 149 EXPECT_EQ(100, NativeLibraryPrefetcher::PercentageOfResidentCode(ranges)); 150 munlock(address, length); 151 munlock(address2, length); 152 } 153 154 } // namespace android 155 } // namespace base 156