Home | History | Annotate | Download | only in files
      1 // Copyright 2014 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/files/memory_mapped_file.h"
      6 
      7 #include "base/file_util.h"
      8 #include "base/files/file_path.h"
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 #include "testing/platform_test.h"
     11 
     12 namespace base {
     13 
     14 namespace {
     15 
     16 // Create a temporary buffer and fill it with a watermark sequence.
     17 scoped_ptr<uint8[]> CreateTestBuffer(size_t size, size_t offset) {
     18   scoped_ptr<uint8[]> buf(new uint8[size]);
     19   for (size_t i = 0; i < size; ++i)
     20     buf.get()[i] = static_cast<uint8>((offset + i) % 253);
     21   return buf.Pass();
     22 }
     23 
     24 // Check that the watermark sequence is consistent with the |offset| provided.
     25 bool CheckBufferContents(const uint8* data, size_t size, size_t offset) {
     26   scoped_ptr<uint8[]> test_data(CreateTestBuffer(size, offset));
     27   return memcmp(test_data.get(), data, size) == 0;
     28 }
     29 
     30 class MemoryMappedFileTest : public PlatformTest {
     31  protected:
     32   virtual void SetUp() OVERRIDE {
     33     PlatformTest::SetUp();
     34     CreateTemporaryFile(&temp_file_path_);
     35   }
     36 
     37   virtual void TearDown() { EXPECT_TRUE(DeleteFile(temp_file_path_, false)); }
     38 
     39   void CreateTemporaryTestFile(size_t size) {
     40     File file(temp_file_path_,
     41               File::FLAG_CREATE_ALWAYS | File::FLAG_READ | File::FLAG_WRITE);
     42     EXPECT_TRUE(file.IsValid());
     43 
     44     scoped_ptr<uint8[]> test_data(CreateTestBuffer(size, 0));
     45     size_t bytes_written =
     46         file.Write(0, reinterpret_cast<char*>(test_data.get()), size);
     47     EXPECT_EQ(size, bytes_written);
     48     file.Close();
     49   }
     50 
     51   const FilePath temp_file_path() const { return temp_file_path_; }
     52 
     53  private:
     54   FilePath temp_file_path_;
     55 };
     56 
     57 TEST_F(MemoryMappedFileTest, MapWholeFileByPath) {
     58   const size_t kFileSize = 68 * 1024;
     59   CreateTemporaryTestFile(kFileSize);
     60   MemoryMappedFile map;
     61   map.Initialize(temp_file_path());
     62   ASSERT_EQ(kFileSize, map.length());
     63   ASSERT_TRUE(map.data() != NULL);
     64   EXPECT_TRUE(map.IsValid());
     65   ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
     66 }
     67 
     68 TEST_F(MemoryMappedFileTest, MapWholeFileByFD) {
     69   const size_t kFileSize = 68 * 1024;
     70   CreateTemporaryTestFile(kFileSize);
     71   MemoryMappedFile map;
     72   map.Initialize(File(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ));
     73   ASSERT_EQ(kFileSize, map.length());
     74   ASSERT_TRUE(map.data() != NULL);
     75   EXPECT_TRUE(map.IsValid());
     76   ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
     77 }
     78 
     79 TEST_F(MemoryMappedFileTest, MapSmallFile) {
     80   const size_t kFileSize = 127;
     81   CreateTemporaryTestFile(kFileSize);
     82   MemoryMappedFile map;
     83   map.Initialize(temp_file_path());
     84   ASSERT_EQ(kFileSize, map.length());
     85   ASSERT_TRUE(map.data() != NULL);
     86   EXPECT_TRUE(map.IsValid());
     87   ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
     88 }
     89 
     90 TEST_F(MemoryMappedFileTest, MapWholeFileUsingRegion) {
     91   const size_t kFileSize = 157 * 1024;
     92   CreateTemporaryTestFile(kFileSize);
     93   MemoryMappedFile map;
     94 
     95   File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
     96   map.Initialize(file.Pass(), MemoryMappedFile::Region::kWholeFile);
     97   ASSERT_EQ(kFileSize, map.length());
     98   ASSERT_TRUE(map.data() != NULL);
     99   EXPECT_TRUE(map.IsValid());
    100   ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
    101 }
    102 
    103 TEST_F(MemoryMappedFileTest, MapPartialRegionAtBeginning) {
    104   const size_t kFileSize = 157 * 1024;
    105   const size_t kPartialSize = 4 * 1024 + 32;
    106   CreateTemporaryTestFile(kFileSize);
    107   MemoryMappedFile map;
    108 
    109   File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
    110   map.Initialize(file.Pass(), MemoryMappedFile::Region(0, kPartialSize));
    111   ASSERT_EQ(kPartialSize, map.length());
    112   ASSERT_TRUE(map.data() != NULL);
    113   EXPECT_TRUE(map.IsValid());
    114   ASSERT_TRUE(CheckBufferContents(map.data(), kPartialSize, 0));
    115 }
    116 
    117 TEST_F(MemoryMappedFileTest, MapPartialRegionAtEnd) {
    118   const size_t kFileSize = 157 * 1024;
    119   const size_t kPartialSize = 5 * 1024 - 32;
    120   const size_t kOffset = kFileSize - kPartialSize;
    121   CreateTemporaryTestFile(kFileSize);
    122   MemoryMappedFile map;
    123 
    124   File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
    125   map.Initialize(file.Pass(), MemoryMappedFile::Region(kOffset, kPartialSize));
    126   ASSERT_EQ(kPartialSize, map.length());
    127   ASSERT_TRUE(map.data() != NULL);
    128   EXPECT_TRUE(map.IsValid());
    129   ASSERT_TRUE(CheckBufferContents(map.data(), kPartialSize, kOffset));
    130 }
    131 
    132 TEST_F(MemoryMappedFileTest, MapSmallPartialRegionInTheMiddle) {
    133   const size_t kFileSize = 157 * 1024;
    134   const size_t kOffset = 1024 * 5 + 32;
    135   const size_t kPartialSize = 8;
    136 
    137   CreateTemporaryTestFile(kFileSize);
    138   MemoryMappedFile map;
    139 
    140   File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
    141   map.Initialize(file.Pass(), MemoryMappedFile::Region(kOffset, kPartialSize));
    142   ASSERT_EQ(kPartialSize, map.length());
    143   ASSERT_TRUE(map.data() != NULL);
    144   EXPECT_TRUE(map.IsValid());
    145   ASSERT_TRUE(CheckBufferContents(map.data(), kPartialSize, kOffset));
    146 }
    147 
    148 TEST_F(MemoryMappedFileTest, MapLargePartialRegionInTheMiddle) {
    149   const size_t kFileSize = 157 * 1024;
    150   const size_t kOffset = 1024 * 5 + 32;
    151   const size_t kPartialSize = 16 * 1024 - 32;
    152 
    153   CreateTemporaryTestFile(kFileSize);
    154   MemoryMappedFile map;
    155 
    156   File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
    157   map.Initialize(file.Pass(), MemoryMappedFile::Region(kOffset, kPartialSize));
    158   ASSERT_EQ(kPartialSize, map.length());
    159   ASSERT_TRUE(map.data() != NULL);
    160   EXPECT_TRUE(map.IsValid());
    161   ASSERT_TRUE(CheckBufferContents(map.data(), kPartialSize, kOffset));
    162 }
    163 
    164 }  // namespace
    165 
    166 }  // namespace base
    167