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
TEST(NativeLibraryPrefetcherTest,TestIsGoodToPrefetchNoRange)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
TEST(NativeLibraryPrefetcherTest,TestIsGoodToPrefetchUnreadableRange)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
TEST(NativeLibraryPrefetcherTest,TestIsGoodToPrefetchSkipSharedRange)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
TEST(NativeLibraryPrefetcherTest,TestIsGoodToPrefetchLibchromeRange)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
TEST(NativeLibraryPrefetcherTest,TestIsGoodToPrefetchBaseApkRange)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
TEST(NativeLibraryPrefetcherTest,TestFilterLibchromeRangesOnlyIfPossibleNoLibchrome)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
TEST(NativeLibraryPrefetcherTest,TestFilterLibchromeRangesOnlyIfPossibleHasLibchrome)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
TEST(NativeLibraryPrefetcherTest,DISABLED_TestPercentageOfResidentCode)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
TEST(NativeLibraryPrefetcherTest,DISABLED_TestPercentageOfResidentCodeTwoRegions)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