15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file.
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/files/memory_mapped_file.h"
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/files/file_path.h"
86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/files/file_util.h"
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "testing/platform_test.h"
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace base {
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace {
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Create a temporary buffer and fill it with a watermark sequence.
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_ptr<uint8[]> CreateTestBuffer(size_t size, size_t offset) {
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<uint8[]> buf(new uint8[size]);
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (size_t i = 0; i < size; ++i)
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    buf.get()[i] = static_cast<uint8>((offset + i) % 253);
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return buf.Pass();
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Check that the watermark sequence is consistent with the |offset| provided.
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool CheckBufferContents(const uint8* data, size_t size, size_t offset) {
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<uint8[]> test_data(CreateTestBuffer(size, offset));
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return memcmp(test_data.get(), data, size) == 0;
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class MemoryMappedFileTest : public PlatformTest {
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) protected:
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    PlatformTest::SetUp();
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CreateTemporaryFile(&temp_file_path_);
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void TearDown() { EXPECT_TRUE(DeleteFile(temp_file_path_, false)); }
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void CreateTemporaryTestFile(size_t size) {
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    File file(temp_file_path_,
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              File::FLAG_CREATE_ALWAYS | File::FLAG_READ | File::FLAG_WRITE);
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_TRUE(file.IsValid());
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<uint8[]> test_data(CreateTestBuffer(size, 0));
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t bytes_written =
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        file.Write(0, reinterpret_cast<char*>(test_data.get()), size);
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(size, bytes_written);
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    file.Close();
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const FilePath temp_file_path() const { return temp_file_path_; }
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private:
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  FilePath temp_file_path_;
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(MemoryMappedFileTest, MapWholeFileByPath) {
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kFileSize = 68 * 1024;
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CreateTemporaryTestFile(kFileSize);
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MemoryMappedFile map;
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  map.Initialize(temp_file_path());
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(kFileSize, map.length());
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(map.data() != NULL);
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(map.IsValid());
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(MemoryMappedFileTest, MapWholeFileByFD) {
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kFileSize = 68 * 1024;
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CreateTemporaryTestFile(kFileSize);
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MemoryMappedFile map;
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  map.Initialize(File(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ));
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(kFileSize, map.length());
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(map.data() != NULL);
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(map.IsValid());
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(MemoryMappedFileTest, MapSmallFile) {
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kFileSize = 127;
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CreateTemporaryTestFile(kFileSize);
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MemoryMappedFile map;
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  map.Initialize(temp_file_path());
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(kFileSize, map.length());
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(map.data() != NULL);
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(map.IsValid());
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(MemoryMappedFileTest, MapWholeFileUsingRegion) {
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kFileSize = 157 * 1024;
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CreateTemporaryTestFile(kFileSize);
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MemoryMappedFile map;
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  map.Initialize(file.Pass(), MemoryMappedFile::Region::kWholeFile);
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(kFileSize, map.length());
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(map.data() != NULL);
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(map.IsValid());
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(MemoryMappedFileTest, MapPartialRegionAtBeginning) {
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kFileSize = 157 * 1024;
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kPartialSize = 4 * 1024 + 32;
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CreateTemporaryTestFile(kFileSize);
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MemoryMappedFile map;
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  map.Initialize(file.Pass(), MemoryMappedFile::Region(0, kPartialSize));
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(kPartialSize, map.length());
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(map.data() != NULL);
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(map.IsValid());
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(CheckBufferContents(map.data(), kPartialSize, 0));
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(MemoryMappedFileTest, MapPartialRegionAtEnd) {
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kFileSize = 157 * 1024;
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kPartialSize = 5 * 1024 - 32;
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kOffset = kFileSize - kPartialSize;
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CreateTemporaryTestFile(kFileSize);
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MemoryMappedFile map;
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  map.Initialize(file.Pass(), MemoryMappedFile::Region(kOffset, kPartialSize));
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(kPartialSize, map.length());
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(map.data() != NULL);
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(map.IsValid());
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(CheckBufferContents(map.data(), kPartialSize, kOffset));
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(MemoryMappedFileTest, MapSmallPartialRegionInTheMiddle) {
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kFileSize = 157 * 1024;
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kOffset = 1024 * 5 + 32;
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kPartialSize = 8;
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CreateTemporaryTestFile(kFileSize);
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MemoryMappedFile map;
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  map.Initialize(file.Pass(), MemoryMappedFile::Region(kOffset, kPartialSize));
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(kPartialSize, map.length());
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(map.data() != NULL);
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(map.IsValid());
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(CheckBufferContents(map.data(), kPartialSize, kOffset));
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(MemoryMappedFileTest, MapLargePartialRegionInTheMiddle) {
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kFileSize = 157 * 1024;
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kOffset = 1024 * 5 + 32;
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t kPartialSize = 16 * 1024 - 32;
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CreateTemporaryTestFile(kFileSize);
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MemoryMappedFile map;
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  map.Initialize(file.Pass(), MemoryMappedFile::Region(kOffset, kPartialSize));
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(kPartialSize, map.length());
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(map.data() != NULL);
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(map.IsValid());
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(CheckBufferContents(map.data(), kPartialSize, kOffset));
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace base
167