• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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