| 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
|
|
|