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