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