Index: base/memory/discardable_memory_manager_unittest.cc |
diff --git a/base/memory/discardable_memory_manager_unittest.cc b/base/memory/discardable_memory_manager_unittest.cc |
deleted file mode 100644 |
index 6717f09fe88ff84a111159749e5aea135fb93964..0000000000000000000000000000000000000000 |
--- a/base/memory/discardable_memory_manager_unittest.cc |
+++ /dev/null |
@@ -1,490 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "base/memory/discardable_memory_manager.h" |
- |
-#include "base/bind.h" |
-#include "base/synchronization/waitable_event.h" |
-#include "base/threading/thread.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-namespace base { |
-namespace { |
- |
-class TestAllocationImpl : public internal::DiscardableMemoryManagerAllocation { |
- public: |
- TestAllocationImpl() : is_allocated_(false), is_locked_(false) {} |
- ~TestAllocationImpl() override { DCHECK(!is_locked_); } |
- |
- // Overridden from internal::DiscardableMemoryManagerAllocation: |
- bool AllocateAndAcquireLock() override { |
- bool was_allocated = is_allocated_; |
- is_allocated_ = true; |
- DCHECK(!is_locked_); |
- is_locked_ = true; |
- return was_allocated; |
- } |
- void ReleaseLock() override { |
- DCHECK(is_locked_); |
- is_locked_ = false; |
- } |
- void Purge() override { |
- DCHECK(is_allocated_); |
- is_allocated_ = false; |
- } |
- |
- bool is_locked() const { return is_locked_; } |
- |
- private: |
- bool is_allocated_; |
- bool is_locked_; |
-}; |
- |
-// Tests can assume that the default limit is at least 1024. Tests that rely on |
-// something else needs to explicit set the limit. |
-const size_t kDefaultMemoryLimit = 1024; |
-const size_t kDefaultSoftMemoryLimit = kDefaultMemoryLimit; |
- |
-class TestDiscardableMemoryManagerImpl |
- : public internal::DiscardableMemoryManager { |
- public: |
- TestDiscardableMemoryManagerImpl() |
- : DiscardableMemoryManager(kDefaultMemoryLimit, |
- kDefaultSoftMemoryLimit, |
- TimeDelta::Max()) {} |
- |
- void SetNow(TimeTicks now) { now_ = now; } |
- |
- private: |
- // Overriden from internal::DiscardableMemoryManager: |
- TimeTicks Now() const override { return now_; } |
- |
- TimeTicks now_; |
-}; |
- |
-class DiscardableMemoryManagerTestBase { |
- public: |
- DiscardableMemoryManagerTestBase() {} |
- |
- protected: |
- enum LockStatus { |
- LOCK_STATUS_FAILED, |
- LOCK_STATUS_PURGED, |
- LOCK_STATUS_SUCCESS |
- }; |
- |
- size_t BytesAllocated() const { return manager_.GetBytesAllocatedForTest(); } |
- |
- void SetMemoryLimit(size_t bytes) { manager_.SetMemoryLimit(bytes); } |
- |
- void SetSoftMemoryLimit(size_t bytes) { manager_.SetSoftMemoryLimit(bytes); } |
- |
- void SetHardMemoryLimitExpirationTime(TimeDelta time) { |
- manager_.SetHardMemoryLimitExpirationTime(time); |
- } |
- |
- void Register(TestAllocationImpl* allocation, size_t bytes) { |
- manager_.Register(allocation, bytes); |
- } |
- |
- void Unregister(TestAllocationImpl* allocation) { |
- manager_.Unregister(allocation); |
- } |
- |
- bool IsRegistered(TestAllocationImpl* allocation) const { |
- return manager_.IsRegisteredForTest(allocation); |
- } |
- |
- LockStatus Lock(TestAllocationImpl* allocation) { |
- bool purged; |
- if (!manager_.AcquireLock(allocation, &purged)) |
- return LOCK_STATUS_FAILED; |
- return purged ? LOCK_STATUS_PURGED : LOCK_STATUS_SUCCESS; |
- } |
- |
- void Unlock(TestAllocationImpl* allocation) { |
- manager_.ReleaseLock(allocation); |
- } |
- |
- LockStatus RegisterAndLock(TestAllocationImpl* allocation, size_t bytes) { |
- manager_.Register(allocation, bytes); |
- return Lock(allocation); |
- } |
- |
- bool CanBePurged(TestAllocationImpl* allocation) const { |
- return manager_.CanBePurgedForTest(allocation); |
- } |
- |
- void SetNow(TimeTicks now) { manager_.SetNow(now); } |
- |
- void PurgeAll() { return manager_.PurgeAll(); } |
- |
- bool ReduceMemoryUsage() { return manager_.ReduceMemoryUsage(); } |
- |
- void ReduceMemoryUsageUntilWithinLimit(size_t bytes) { |
- manager_.ReduceMemoryUsageUntilWithinLimit(bytes); |
- } |
- |
- private: |
- TestDiscardableMemoryManagerImpl manager_; |
-}; |
- |
-class DiscardableMemoryManagerTest : public DiscardableMemoryManagerTestBase, |
- public testing::Test { |
- public: |
- DiscardableMemoryManagerTest() {} |
-}; |
- |
-TEST_F(DiscardableMemoryManagerTest, CreateAndLock) { |
- size_t size = 1024; |
- TestAllocationImpl allocation; |
- Register(&allocation, size); |
- EXPECT_TRUE(IsRegistered(&allocation)); |
- EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation)); |
- EXPECT_TRUE(allocation.is_locked()); |
- EXPECT_EQ(1024u, BytesAllocated()); |
- EXPECT_FALSE(CanBePurged(&allocation)); |
- Unlock(&allocation); |
- Unregister(&allocation); |
-} |
- |
-TEST_F(DiscardableMemoryManagerTest, CreateZeroSize) { |
- size_t size = 0; |
- TestAllocationImpl allocation; |
- Register(&allocation, size); |
- EXPECT_TRUE(IsRegistered(&allocation)); |
- EXPECT_EQ(LOCK_STATUS_FAILED, Lock(&allocation)); |
- EXPECT_EQ(0u, BytesAllocated()); |
- Unregister(&allocation); |
-} |
- |
-TEST_F(DiscardableMemoryManagerTest, LockAfterUnlock) { |
- size_t size = 1024; |
- TestAllocationImpl allocation; |
- RegisterAndLock(&allocation, size); |
- EXPECT_EQ(1024u, BytesAllocated()); |
- EXPECT_FALSE(CanBePurged(&allocation)); |
- |
- // Now unlock so we can lock later. |
- Unlock(&allocation); |
- EXPECT_TRUE(CanBePurged(&allocation)); |
- |
- EXPECT_EQ(LOCK_STATUS_SUCCESS, Lock(&allocation)); |
- EXPECT_FALSE(CanBePurged(&allocation)); |
- Unlock(&allocation); |
- Unregister(&allocation); |
-} |
- |
-TEST_F(DiscardableMemoryManagerTest, LockAfterPurge) { |
- size_t size = 1024; |
- TestAllocationImpl allocation; |
- RegisterAndLock(&allocation, size); |
- EXPECT_EQ(1024u, BytesAllocated()); |
- EXPECT_FALSE(CanBePurged(&allocation)); |
- |
- // Now unlock so we can lock later. |
- Unlock(&allocation); |
- EXPECT_TRUE(CanBePurged(&allocation)); |
- |
- // Force the system to purge. |
- PurgeAll(); |
- |
- EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation)); |
- EXPECT_FALSE(CanBePurged(&allocation)); |
- |
- Unlock(&allocation); |
- Unregister(&allocation); |
-} |
- |
-TEST_F(DiscardableMemoryManagerTest, LockAfterPurgeAndCannotReallocate) { |
- size_t size = 1024; |
- TestAllocationImpl allocation; |
- RegisterAndLock(&allocation, size); |
- EXPECT_EQ(1024u, BytesAllocated()); |
- EXPECT_FALSE(CanBePurged(&allocation)); |
- |
- // Now unlock so we can lock later. |
- Unlock(&allocation); |
- EXPECT_TRUE(CanBePurged(&allocation)); |
- |
- // Set max allowed allocation to 1 byte. This will cause the memory to be |
- // purged. |
- SetMemoryLimit(1); |
- |
- EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation)); |
- EXPECT_FALSE(CanBePurged(&allocation)); |
- |
- Unlock(&allocation); |
- Unregister(&allocation); |
-} |
- |
-TEST_F(DiscardableMemoryManagerTest, Overflow) { |
- size_t size = 1024; |
- { |
- TestAllocationImpl allocation; |
- RegisterAndLock(&allocation, size); |
- EXPECT_EQ(1024u, BytesAllocated()); |
- |
- size_t massive_size = std::numeric_limits<size_t>::max(); |
- TestAllocationImpl massive_allocation; |
- Register(&massive_allocation, massive_size); |
- EXPECT_EQ(LOCK_STATUS_FAILED, Lock(&massive_allocation)); |
- EXPECT_EQ(1024u, BytesAllocated()); |
- |
- Unlock(&allocation); |
- EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&massive_allocation)); |
- Unlock(&massive_allocation); |
- Unregister(&massive_allocation); |
- Unregister(&allocation); |
- } |
- EXPECT_EQ(0u, BytesAllocated()); |
-} |
- |
-class PermutationTestData { |
- public: |
- PermutationTestData(unsigned d0, unsigned d1, unsigned d2) { |
- ordering_[0] = d0; |
- ordering_[1] = d1; |
- ordering_[2] = d2; |
- } |
- |
- const unsigned* ordering() const { return ordering_; } |
- |
- private: |
- unsigned ordering_[3]; |
-}; |
- |
-class DiscardableMemoryManagerPermutationTest |
- : public DiscardableMemoryManagerTestBase, |
- public testing::TestWithParam<PermutationTestData> { |
- public: |
- DiscardableMemoryManagerPermutationTest() {} |
- |
- protected: |
- // Use memory in order specified by ordering parameter. |
- void RegisterAndUseAllocations() { |
- for (int i = 0; i < 3; ++i) { |
- RegisterAndLock(&allocation_[i], 1024); |
- Unlock(&allocation_[i]); |
- } |
- for (int i = 0; i < 3; ++i) { |
- int index = GetParam().ordering()[i]; |
- EXPECT_NE(LOCK_STATUS_FAILED, Lock(&allocation_[index])); |
- // Leave i == 0 locked. |
- if (i > 0) |
- Unlock(&allocation_[index]); |
- } |
- } |
- |
- TestAllocationImpl* allocation(unsigned position) { |
- return &allocation_[GetParam().ordering()[position]]; |
- } |
- |
- void UnlockAndUnregisterAllocations() { |
- for (int i = 0; i < 3; ++i) { |
- if (allocation_[i].is_locked()) |
- Unlock(&allocation_[i]); |
- Unregister(&allocation_[i]); |
- } |
- } |
- |
- private: |
- TestAllocationImpl allocation_[3]; |
-}; |
- |
-// Verify that memory was discarded in the correct order after reducing usage to |
-// limit. |
-TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscarded) { |
- RegisterAndUseAllocations(); |
- |
- SetMemoryLimit(2048); |
- |
- ReduceMemoryUsageUntilWithinLimit(1024); |
- |
- EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2))); |
- EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); |
- // 0 should still be locked. |
- EXPECT_TRUE(allocation(0)->is_locked()); |
- |
- UnlockAndUnregisterAllocations(); |
-} |
- |
-// Verify that memory was discarded in the correct order after changing |
-// memory limit. |
-TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedExceedLimit) { |
- RegisterAndUseAllocations(); |
- |
- SetMemoryLimit(2048); |
- |
- EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2))); |
- EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); |
- // 0 should still be locked. |
- EXPECT_TRUE(allocation(0)->is_locked()); |
- |
- UnlockAndUnregisterAllocations(); |
-} |
- |
-// Verify that no more memory than necessary was discarded after changing |
-// memory limit. |
-TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedAmount) { |
- SetMemoryLimit(4096); |
- |
- RegisterAndUseAllocations(); |
- |
- SetMemoryLimit(2048); |
- |
- EXPECT_EQ(LOCK_STATUS_SUCCESS, Lock(allocation(2))); |
- EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); |
- // 0 should still be locked. |
- EXPECT_TRUE(allocation(0)->is_locked()); |
- |
- UnlockAndUnregisterAllocations(); |
-} |
- |
-TEST_P(DiscardableMemoryManagerPermutationTest, PurgeFreesAllUnlocked) { |
- RegisterAndUseAllocations(); |
- |
- PurgeAll(); |
- |
- for (int i = 0; i < 3; ++i) { |
- if (i == 0) |
- EXPECT_TRUE(allocation(i)->is_locked()); |
- else |
- EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(i))); |
- } |
- |
- UnlockAndUnregisterAllocations(); |
-} |
- |
-INSTANTIATE_TEST_CASE_P(DiscardableMemoryManagerPermutationTests, |
- DiscardableMemoryManagerPermutationTest, |
- ::testing::Values(PermutationTestData(0, 1, 2), |
- PermutationTestData(0, 2, 1), |
- PermutationTestData(1, 0, 2), |
- PermutationTestData(1, 2, 0), |
- PermutationTestData(2, 0, 1), |
- PermutationTestData(2, 1, 0))); |
- |
-TEST_F(DiscardableMemoryManagerTest, NormalDestruction) { |
- { |
- size_t size = 1024; |
- TestAllocationImpl allocation; |
- Register(&allocation, size); |
- Unregister(&allocation); |
- } |
- EXPECT_EQ(0u, BytesAllocated()); |
-} |
- |
-TEST_F(DiscardableMemoryManagerTest, DestructionAfterLocked) { |
- { |
- size_t size = 1024; |
- TestAllocationImpl allocation; |
- RegisterAndLock(&allocation, size); |
- EXPECT_EQ(1024u, BytesAllocated()); |
- EXPECT_FALSE(CanBePurged(&allocation)); |
- Unlock(&allocation); |
- Unregister(&allocation); |
- } |
- EXPECT_EQ(0u, BytesAllocated()); |
-} |
- |
-TEST_F(DiscardableMemoryManagerTest, DestructionAfterPurged) { |
- { |
- size_t size = 1024; |
- TestAllocationImpl allocation; |
- RegisterAndLock(&allocation, size); |
- EXPECT_EQ(1024u, BytesAllocated()); |
- Unlock(&allocation); |
- EXPECT_TRUE(CanBePurged(&allocation)); |
- SetMemoryLimit(0); |
- EXPECT_EQ(0u, BytesAllocated()); |
- Unregister(&allocation); |
- } |
- EXPECT_EQ(0u, BytesAllocated()); |
-} |
- |
-TEST_F(DiscardableMemoryManagerTest, ReduceMemoryUsage) { |
- SetMemoryLimit(3072); |
- SetSoftMemoryLimit(1024); |
- SetHardMemoryLimitExpirationTime(TimeDelta::FromInternalValue(1)); |
- |
- size_t size = 1024; |
- TestAllocationImpl allocation[3]; |
- RegisterAndLock(&allocation[0], size); |
- RegisterAndLock(&allocation[1], size); |
- RegisterAndLock(&allocation[2], size); |
- EXPECT_EQ(3072u, BytesAllocated()); |
- |
- // Above soft limit but nothing that can be purged. |
- EXPECT_FALSE(ReduceMemoryUsage()); |
- |
- SetNow(TimeTicks::FromInternalValue(0)); |
- Unlock(&allocation[0]); |
- |
- // Above soft limit but still nothing that can be purged as all unlocked |
- // allocations are within the hard limit cutoff time. |
- EXPECT_FALSE(ReduceMemoryUsage()); |
- |
- SetNow(TimeTicks::FromInternalValue(1)); |
- Unlock(&allocation[1]); |
- |
- // One unlocked allocation is no longer within the hard limit cutoff time. It |
- // should be purged and ReduceMemoryUsage() should return false as we're not |
- // yet within the soft memory limit. |
- EXPECT_FALSE(ReduceMemoryUsage()); |
- EXPECT_EQ(2048u, BytesAllocated()); |
- |
- // One more unlocked allocation is no longer within the hard limit cutoff |
- // time. It should be purged and ReduceMemoryUsage() should return true as |
- // we're now within the soft memory limit. |
- SetNow(TimeTicks::FromInternalValue(2)); |
- EXPECT_TRUE(ReduceMemoryUsage()); |
- EXPECT_EQ(1024u, BytesAllocated()); |
- |
- Unlock(&allocation[2]); |
- |
- Unregister(&allocation[0]); |
- Unregister(&allocation[1]); |
- Unregister(&allocation[2]); |
-} |
- |
-class ThreadedDiscardableMemoryManagerTest |
- : public DiscardableMemoryManagerTest { |
- public: |
- ThreadedDiscardableMemoryManagerTest() |
- : memory_usage_thread_("memory_usage_thread"), |
- thread_sync_(true, false) {} |
- |
- void SetUp() override { memory_usage_thread_.Start(); } |
- |
- void TearDown() override { memory_usage_thread_.Stop(); } |
- |
- void UseMemoryHelper() { |
- size_t size = 1024; |
- TestAllocationImpl allocation; |
- RegisterAndLock(&allocation, size); |
- Unlock(&allocation); |
- Unregister(&allocation); |
- } |
- |
- void SignalHelper() { thread_sync_.Signal(); } |
- |
- Thread memory_usage_thread_; |
- WaitableEvent thread_sync_; |
-}; |
- |
-TEST_F(ThreadedDiscardableMemoryManagerTest, UseMemoryOnThread) { |
- memory_usage_thread_.message_loop()->PostTask( |
- FROM_HERE, |
- Bind(&ThreadedDiscardableMemoryManagerTest::UseMemoryHelper, |
- Unretained(this))); |
- memory_usage_thread_.message_loop()->PostTask( |
- FROM_HERE, |
- Bind(&ThreadedDiscardableMemoryManagerTest::SignalHelper, |
- Unretained(this))); |
- thread_sync_.Wait(); |
-} |
- |
-} // namespace |
-} // namespace base |