| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/metrics/persistent_memory_allocator.h" | 5 #include "base/metrics/persistent_memory_allocator.h" |
| 6 | 6 |
| 7 #include "base/files/file.h" | 7 #include "base/files/file.h" |
| 8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 9 #include "base/files/memory_mapped_file.h" | 9 #include "base/files/memory_mapped_file.h" |
| 10 #include "base/files/scoped_temp_dir.h" | 10 #include "base/files/scoped_temp_dir.h" |
| 11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/memory/shared_memory.h" |
| 12 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 13 #include "base/rand_util.h" | 14 #include "base/rand_util.h" |
| 14 #include "base/strings/safe_sprintf.h" | 15 #include "base/strings/safe_sprintf.h" |
| 15 #include "base/threading/simple_thread.h" | 16 #include "base/threading/simple_thread.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" | 17 #include "testing/gmock/include/gmock/gmock.h" |
| 17 | 18 |
| 18 namespace { | 19 namespace { |
| 19 | 20 |
| 20 const uint32_t TEST_MEMORY_SIZE = 1 << 20; // 1 MiB | 21 const uint32_t TEST_MEMORY_SIZE = 1 << 20; // 1 MiB |
| 21 const uint32_t TEST_MEMORY_PAGE = 64 << 10; // 64 KiB | 22 const uint32_t TEST_MEMORY_PAGE = 64 << 10; // 64 KiB |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 | 381 |
| 381 TEST(LocalPersistentMemoryAllocatorTest, CreationTest) { | 382 TEST(LocalPersistentMemoryAllocatorTest, CreationTest) { |
| 382 LocalPersistentMemoryAllocator allocator(TEST_MEMORY_SIZE, 42, ""); | 383 LocalPersistentMemoryAllocator allocator(TEST_MEMORY_SIZE, 42, ""); |
| 383 EXPECT_EQ(42U, allocator.Id()); | 384 EXPECT_EQ(42U, allocator.Id()); |
| 384 EXPECT_NE(0U, allocator.Allocate(24, 1)); | 385 EXPECT_NE(0U, allocator.Allocate(24, 1)); |
| 385 EXPECT_FALSE(allocator.IsFull()); | 386 EXPECT_FALSE(allocator.IsFull()); |
| 386 EXPECT_FALSE(allocator.IsCorrupt()); | 387 EXPECT_FALSE(allocator.IsCorrupt()); |
| 387 } | 388 } |
| 388 | 389 |
| 389 | 390 |
| 391 //----- SharedPersistentMemoryAllocator ---------------------------------------- |
| 392 |
| 393 TEST(SharedPersistentMemoryAllocatorTest, CreationTest) { |
| 394 SharedMemoryHandle shared_handle; |
| 395 |
| 396 PersistentMemoryAllocator::MemoryInfo meminfo1; |
| 397 Reference r123, r456, r789; |
| 398 { |
| 399 scoped_ptr<SharedMemory> shmem1(new SharedMemory()); |
| 400 ASSERT_TRUE(shmem1->CreateAndMapAnonymous(TEST_MEMORY_SIZE)); |
| 401 SharedPersistentMemoryAllocator local(std::move(shmem1), TEST_ID, "", |
| 402 false); |
| 403 EXPECT_FALSE(local.IsReadonly()); |
| 404 r123 = local.Allocate(123, 123); |
| 405 r456 = local.Allocate(456, 456); |
| 406 r789 = local.Allocate(789, 789); |
| 407 local.MakeIterable(r123); |
| 408 local.SetType(r456, 654); |
| 409 local.MakeIterable(r789); |
| 410 local.GetMemoryInfo(&meminfo1); |
| 411 EXPECT_FALSE(local.IsFull()); |
| 412 EXPECT_FALSE(local.IsCorrupt()); |
| 413 |
| 414 ASSERT_TRUE(local.shared_memory()->ShareToProcess( |
| 415 GetCurrentProcessHandle(), |
| 416 &shared_handle)); |
| 417 } |
| 418 |
| 419 // Read-only test. |
| 420 scoped_ptr<SharedMemory> shmem2(new SharedMemory(shared_handle, |
| 421 /*readonly=*/true)); |
| 422 ASSERT_TRUE(shmem2->Map(TEST_MEMORY_SIZE)); |
| 423 |
| 424 SharedPersistentMemoryAllocator shalloc2(std::move(shmem2), 0, "", true); |
| 425 EXPECT_TRUE(shalloc2.IsReadonly()); |
| 426 EXPECT_EQ(TEST_ID, shalloc2.Id()); |
| 427 EXPECT_FALSE(shalloc2.IsFull()); |
| 428 EXPECT_FALSE(shalloc2.IsCorrupt()); |
| 429 |
| 430 PersistentMemoryAllocator::Iterator iter2; |
| 431 uint32_t type; |
| 432 shalloc2.CreateIterator(&iter2); |
| 433 EXPECT_EQ(r123, shalloc2.GetNextIterable(&iter2, &type)); |
| 434 EXPECT_EQ(r789, shalloc2.GetNextIterable(&iter2, &type)); |
| 435 EXPECT_EQ(0U, shalloc2.GetNextIterable(&iter2, &type)); |
| 436 |
| 437 EXPECT_EQ(123U, shalloc2.GetType(r123)); |
| 438 EXPECT_EQ(654U, shalloc2.GetType(r456)); |
| 439 EXPECT_EQ(789U, shalloc2.GetType(r789)); |
| 440 |
| 441 PersistentMemoryAllocator::MemoryInfo meminfo2; |
| 442 shalloc2.GetMemoryInfo(&meminfo2); |
| 443 EXPECT_EQ(meminfo1.total, meminfo2.total); |
| 444 EXPECT_EQ(meminfo1.free, meminfo2.free); |
| 445 |
| 446 // Read/write test. |
| 447 scoped_ptr<SharedMemory> shmem3(new SharedMemory(shared_handle, |
| 448 /*readonly=*/false)); |
| 449 ASSERT_TRUE(shmem3->Map(TEST_MEMORY_SIZE)); |
| 450 |
| 451 SharedPersistentMemoryAllocator shalloc3(std::move(shmem3), 0, "", false); |
| 452 EXPECT_FALSE(shalloc3.IsReadonly()); |
| 453 EXPECT_EQ(TEST_ID, shalloc3.Id()); |
| 454 EXPECT_FALSE(shalloc3.IsFull()); |
| 455 EXPECT_FALSE(shalloc3.IsCorrupt()); |
| 456 |
| 457 PersistentMemoryAllocator::Iterator iter3; |
| 458 shalloc3.CreateIterator(&iter3); |
| 459 EXPECT_EQ(r123, shalloc3.GetNextIterable(&iter3, &type)); |
| 460 EXPECT_EQ(r789, shalloc3.GetNextIterable(&iter3, &type)); |
| 461 EXPECT_EQ(0U, shalloc3.GetNextIterable(&iter3, &type)); |
| 462 |
| 463 EXPECT_EQ(123U, shalloc3.GetType(r123)); |
| 464 EXPECT_EQ(654U, shalloc3.GetType(r456)); |
| 465 EXPECT_EQ(789U, shalloc3.GetType(r789)); |
| 466 |
| 467 PersistentMemoryAllocator::MemoryInfo meminfo3; |
| 468 shalloc3.GetMemoryInfo(&meminfo3); |
| 469 EXPECT_EQ(meminfo1.total, meminfo3.total); |
| 470 EXPECT_EQ(meminfo1.free, meminfo3.free); |
| 471 |
| 472 // Interconnectivity test. |
| 473 Reference obj = shalloc3.Allocate(42, 42); |
| 474 ASSERT_TRUE(obj); |
| 475 shalloc3.MakeIterable(obj); |
| 476 EXPECT_EQ(obj, shalloc2.GetNextIterable(&iter2, &type)); |
| 477 EXPECT_EQ(42U, type); |
| 478 } |
| 479 |
| 480 |
| 390 //----- FilePersistentMemoryAllocator ------------------------------------------ | 481 //----- FilePersistentMemoryAllocator ------------------------------------------ |
| 391 | 482 |
| 392 TEST(FilePersistentMemoryAllocatorTest, CreationTest) { | 483 TEST(FilePersistentMemoryAllocatorTest, CreationTest) { |
| 393 ScopedTempDir temp_dir; | 484 ScopedTempDir temp_dir; |
| 394 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 485 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 395 FilePath file_path = temp_dir.path().AppendASCII("persistent_memory"); | 486 FilePath file_path = temp_dir.path().AppendASCII("persistent_memory"); |
| 396 | 487 |
| 397 PersistentMemoryAllocator::MemoryInfo meminfo1; | 488 PersistentMemoryAllocator::MemoryInfo meminfo1; |
| 398 Reference r123, r456, r789; | 489 Reference r123, r456, r789; |
| 399 { | 490 { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 413 ASSERT_TRUE(writer.IsValid()); | 504 ASSERT_TRUE(writer.IsValid()); |
| 414 writer.Write(0, (const char*)local.data(), local.used()); | 505 writer.Write(0, (const char*)local.data(), local.used()); |
| 415 } | 506 } |
| 416 | 507 |
| 417 scoped_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile()); | 508 scoped_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile()); |
| 418 mmfile->Initialize(file_path); | 509 mmfile->Initialize(file_path); |
| 419 EXPECT_TRUE(mmfile->IsValid()); | 510 EXPECT_TRUE(mmfile->IsValid()); |
| 420 const size_t mmlength = mmfile->length(); | 511 const size_t mmlength = mmfile->length(); |
| 421 EXPECT_GE(meminfo1.total, mmlength); | 512 EXPECT_GE(meminfo1.total, mmlength); |
| 422 | 513 |
| 423 FilePersistentMemoryAllocator file(mmfile.release(), 0, ""); | 514 FilePersistentMemoryAllocator file(std::move(mmfile), 0, ""); |
| 424 EXPECT_TRUE(file.IsReadonly()); | 515 EXPECT_TRUE(file.IsReadonly()); |
| 425 EXPECT_EQ(TEST_ID, file.Id()); | 516 EXPECT_EQ(TEST_ID, file.Id()); |
| 426 EXPECT_FALSE(file.IsFull()); | 517 EXPECT_FALSE(file.IsFull()); |
| 427 EXPECT_FALSE(file.IsCorrupt()); | 518 EXPECT_FALSE(file.IsCorrupt()); |
| 428 | 519 |
| 429 PersistentMemoryAllocator::Iterator iter; | 520 PersistentMemoryAllocator::Iterator iter; |
| 430 uint32_t type; | 521 uint32_t type; |
| 431 file.CreateIterator(&iter); | 522 file.CreateIterator(&iter); |
| 432 EXPECT_EQ(r123, file.GetNextIterable(&iter, &type)); | 523 EXPECT_EQ(r123, file.GetNextIterable(&iter, &type)); |
| 433 EXPECT_EQ(r789, file.GetNextIterable(&iter, &type)); | 524 EXPECT_EQ(r789, file.GetNextIterable(&iter, &type)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 ASSERT_TRUE(writer.IsValid()); | 559 ASSERT_TRUE(writer.IsValid()); |
| 469 writer.Write(0, (const char*)local.data(), filesize); | 560 writer.Write(0, (const char*)local.data(), filesize); |
| 470 } | 561 } |
| 471 ASSERT_TRUE(PathExists(file_path)); | 562 ASSERT_TRUE(PathExists(file_path)); |
| 472 | 563 |
| 473 mmfile.reset(new MemoryMappedFile()); | 564 mmfile.reset(new MemoryMappedFile()); |
| 474 mmfile->Initialize(file_path); | 565 mmfile->Initialize(file_path); |
| 475 EXPECT_EQ(filesize, mmfile->length()); | 566 EXPECT_EQ(filesize, mmfile->length()); |
| 476 if (FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile)) { | 567 if (FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile)) { |
| 477 // Make sure construction doesn't crash. | 568 // Make sure construction doesn't crash. |
| 478 FilePersistentMemoryAllocator allocator(mmfile.release(), 0, ""); | 569 FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, ""); |
| 479 // Also make sure that iteration doesn't crash. | 570 // Also make sure that iteration doesn't crash. |
| 480 PersistentMemoryAllocator::Iterator iter; | 571 PersistentMemoryAllocator::Iterator iter; |
| 481 allocator.CreateIterator(&iter); | 572 allocator.CreateIterator(&iter); |
| 482 for (;;) { | 573 for (;;) { |
| 483 Reference ref = allocator.GetNextIterable(&iter, 0); | 574 Reference ref = allocator.GetNextIterable(&iter, 0); |
| 484 if (!ref) | 575 if (!ref) |
| 485 break; | 576 break; |
| 486 const char* data = allocator.GetAsObject<char>(ref, 0); | 577 const char* data = allocator.GetAsObject<char>(ref, 0); |
| 487 uint32_t type = allocator.GetType(ref); | 578 uint32_t type = allocator.GetType(ref); |
| 488 size_t size = allocator.GetAllocSize(ref); | 579 size_t size = allocator.GetAllocSize(ref); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 508 ASSERT_TRUE(writer.IsValid()); | 599 ASSERT_TRUE(writer.IsValid()); |
| 509 writer.Write(0, (const char*)garbage.get(), filesize); | 600 writer.Write(0, (const char*)garbage.get(), filesize); |
| 510 } | 601 } |
| 511 ASSERT_TRUE(PathExists(file_path)); | 602 ASSERT_TRUE(PathExists(file_path)); |
| 512 | 603 |
| 513 mmfile.reset(new MemoryMappedFile()); | 604 mmfile.reset(new MemoryMappedFile()); |
| 514 mmfile->Initialize(file_path); | 605 mmfile->Initialize(file_path); |
| 515 EXPECT_EQ(filesize, mmfile->length()); | 606 EXPECT_EQ(filesize, mmfile->length()); |
| 516 if (FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile)) { | 607 if (FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile)) { |
| 517 // Just need to make sure it doesn't crash. | 608 // Just need to make sure it doesn't crash. |
| 518 FilePersistentMemoryAllocator allocator(mmfile.release(), 0, "") ; | 609 FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, ""); |
| 519 EXPECT_TRUE(allocator.IsCorrupt()); // Garbage data so it should be. | 610 EXPECT_TRUE(allocator.IsCorrupt()); // Garbage data so it should be. |
| 520 } else { | 611 } else { |
| 521 // For filesize >= minsize, the file must be acceptable. This | 612 // For filesize >= minsize, the file must be acceptable. This |
| 522 // else clause (file-not-acceptable) should be reached only if | 613 // else clause (file-not-acceptable) should be reached only if |
| 523 // filesize < minsize. | 614 // filesize < minsize. |
| 524 EXPECT_GT(minsize, filesize); | 615 EXPECT_GT(minsize, filesize); |
| 525 } | 616 } |
| 526 } | 617 } |
| 527 } | 618 } |
| 528 | 619 |
| 529 } // namespace base | 620 } // namespace base |
| OLD | NEW |