Index: base/metrics/persistent_memory_allocator_unittest.cc |
diff --git a/base/metrics/persistent_memory_allocator_unittest.cc b/base/metrics/persistent_memory_allocator_unittest.cc |
index 70e13921fabfb2989164648262bd88f2b91cb15c..5125ae6f322a141ff8a7d9e9e400a3a0ef7d264a 100644 |
--- a/base/metrics/persistent_memory_allocator_unittest.cc |
+++ b/base/metrics/persistent_memory_allocator_unittest.cc |
@@ -53,7 +53,7 @@ class PersistentMemoryAllocatorTest : public testing::Test { |
}; |
PersistentMemoryAllocatorTest() { |
- kAllocAlignment = PersistentMemoryAllocator::kAllocAlignment; |
+ kAllocAlignment = GetAllocAlignment(); |
mem_segment_.reset(new char[TEST_MEMORY_SIZE]); |
} |
@@ -80,6 +80,10 @@ class PersistentMemoryAllocatorTest : public testing::Test { |
return count; |
} |
+ static uint32_t GetAllocAlignment() { |
+ return PersistentMemoryAllocator::kAllocAlignment; |
+ } |
+ |
protected: |
std::unique_ptr<char[]> mem_segment_; |
std::unique_ptr<PersistentMemoryAllocator> allocator_; |
@@ -611,7 +615,7 @@ TEST(FilePersistentMemoryAllocatorTest, CreationTest) { |
const size_t mmlength = mmfile->length(); |
EXPECT_GE(meminfo1.total, mmlength); |
- FilePersistentMemoryAllocator file(std::move(mmfile), 0, ""); |
+ FilePersistentMemoryAllocator file(std::move(mmfile), 0, 0, "", true); |
EXPECT_TRUE(file.IsReadonly()); |
EXPECT_EQ(TEST_ID, file.Id()); |
EXPECT_FALSE(file.IsFull()); |
@@ -635,10 +639,63 @@ TEST(FilePersistentMemoryAllocatorTest, CreationTest) { |
EXPECT_EQ(0U, meminfo2.free); |
} |
+TEST(FilePersistentMemoryAllocatorTest, ExtendTest) { |
+ ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ FilePath file_path = temp_dir.path().AppendASCII("extend_test"); |
+ MemoryMappedFile::Region region = {0, 16 << 10}; // 16KiB maximum size. |
+ |
+ // Start with a small but valid file of persistent data. |
+ ASSERT_FALSE(PathExists(file_path)); |
+ { |
+ LocalPersistentMemoryAllocator local(TEST_MEMORY_SIZE, TEST_ID, ""); |
+ local.Allocate(1, 1); |
+ local.Allocate(11, 11); |
+ |
+ File writer(file_path, File::FLAG_CREATE | File::FLAG_WRITE); |
+ ASSERT_TRUE(writer.IsValid()); |
+ writer.Write(0, (const char*)local.data(), local.used()); |
+ } |
+ ASSERT_TRUE(PathExists(file_path)); |
+ int64_t before_size; |
+ ASSERT_TRUE(GetFileSize(file_path, &before_size)); |
+ |
+ // Map it as an extendable read/write file and append to it. |
+ { |
+ std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile()); |
+ mmfile->Initialize( |
+ File(file_path, File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE), |
+ region, MemoryMappedFile::READ_WRITE_EXTEND); |
+ FilePersistentMemoryAllocator allocator(std::move(mmfile), region.size, 0, |
+ "", false); |
+ EXPECT_EQ(static_cast<size_t>(before_size), allocator.used()); |
+ |
+ allocator.Allocate(111, 111); |
+ EXPECT_LT(static_cast<size_t>(before_size), allocator.used()); |
+ } |
+ |
+ // Validate that append worked. |
+ int64_t after_size; |
+ ASSERT_TRUE(GetFileSize(file_path, &after_size)); |
+ EXPECT_LT(before_size, after_size); |
+ |
+ // Verify that it's still an acceptable file. |
+ { |
+ std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile()); |
+ mmfile->Initialize( |
+ File(file_path, File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE), |
+ region, MemoryMappedFile::READ_WRITE_EXTEND); |
+ EXPECT_TRUE(FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, true)); |
+ EXPECT_TRUE( |
+ FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, false)); |
+ } |
+} |
+ |
TEST(FilePersistentMemoryAllocatorTest, AcceptableTest) { |
+ const uint32_t kAllocAlignment = |
+ PersistentMemoryAllocatorTest::GetAllocAlignment(); |
ScopedTempDir temp_dir; |
ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
- FilePath file_path_base = temp_dir.path().AppendASCII("persistent_memory_"); |
LocalPersistentMemoryAllocator local(TEST_MEMORY_SIZE, TEST_ID, ""); |
local.MakeIterable(local.Allocate(1, 1)); |
@@ -660,13 +717,23 @@ TEST(FilePersistentMemoryAllocatorTest, AcceptableTest) { |
} |
ASSERT_TRUE(PathExists(file_path)); |
+ // Request read/write access for some sizes that are a multple of the |
+ // allocator's alignment size. The allocator is strict about file size |
+ // being a multiple of its internal alignment when doing read/write access. |
+ const bool read_only = (filesize % (2 * kAllocAlignment)) != 0; |
+ const uint32_t file_flags = |
+ File::FLAG_OPEN | File::FLAG_READ | (read_only ? 0 : File::FLAG_WRITE); |
+ const MemoryMappedFile::Access map_access = |
+ read_only ? MemoryMappedFile::READ_ONLY : MemoryMappedFile::READ_WRITE; |
+ |
mmfile.reset(new MemoryMappedFile()); |
- mmfile->Initialize(file_path); |
+ mmfile->Initialize(File(file_path, file_flags), map_access); |
EXPECT_EQ(filesize, mmfile->length()); |
- if (FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile)) { |
+ if (FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, read_only)) { |
// Make sure construction doesn't crash. It will, however, cause |
// error messages warning about about a corrupted memory segment. |
- FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, ""); |
+ FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, 0, "", |
+ read_only); |
// Also make sure that iteration doesn't crash. |
PersistentMemoryAllocator::Iterator iter(&allocator); |
uint32_t type_id; |
@@ -680,6 +747,7 @@ TEST(FilePersistentMemoryAllocatorTest, AcceptableTest) { |
(void)type; |
(void)size; |
} |
+ |
// Ensure that short files are detected as corrupt and full files are not. |
EXPECT_EQ(filesize != minsize, allocator.IsCorrupt()); |
} else { |
@@ -700,12 +768,13 @@ TEST(FilePersistentMemoryAllocatorTest, AcceptableTest) { |
ASSERT_TRUE(PathExists(file_path)); |
mmfile.reset(new MemoryMappedFile()); |
- mmfile->Initialize(file_path); |
+ mmfile->Initialize(File(file_path, file_flags), map_access); |
EXPECT_EQ(filesize, mmfile->length()); |
- if (FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile)) { |
+ if (FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, read_only)) { |
// Make sure construction doesn't crash. It will, however, cause |
// error messages warning about about a corrupted memory segment. |
- FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, ""); |
+ FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, 0, "", |
+ read_only); |
EXPECT_TRUE(allocator.IsCorrupt()); // Garbage data so it should be. |
} else { |
// For filesize >= minsize, the file must be acceptable. This |