Home | History | Annotate | Download | only in library_loader
      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