| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/memory/discardable_memory_manager.h" | 5 #include "base/memory/discardable_memory_manager.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/run_loop.h" | |
| 9 #include "base/synchronization/waitable_event.h" | 8 #include "base/synchronization/waitable_event.h" |
| 10 #include "base/threading/thread.h" | 9 #include "base/threading/thread.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
| 12 | 11 |
| 13 namespace base { | 12 namespace base { |
| 14 namespace { | 13 namespace { |
| 15 | 14 |
| 16 class TestAllocationImpl : public internal::DiscardableMemoryManagerAllocation { | 15 class TestAllocationImpl : public internal::DiscardableMemoryManagerAllocation { |
| 17 public: | 16 public: |
| 18 TestAllocationImpl() : is_allocated_(false), is_locked_(false) {} | 17 TestAllocationImpl() : is_allocated_(false), is_locked_(false) {} |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 | 60 |
| 62 private: | 61 private: |
| 63 // Overriden from internal::DiscardableMemoryManager: | 62 // Overriden from internal::DiscardableMemoryManager: |
| 64 virtual TimeTicks Now() const OVERRIDE { return now_; } | 63 virtual TimeTicks Now() const OVERRIDE { return now_; } |
| 65 | 64 |
| 66 TimeTicks now_; | 65 TimeTicks now_; |
| 67 }; | 66 }; |
| 68 | 67 |
| 69 class DiscardableMemoryManagerTestBase { | 68 class DiscardableMemoryManagerTestBase { |
| 70 public: | 69 public: |
| 71 DiscardableMemoryManagerTestBase() { | 70 DiscardableMemoryManagerTestBase() {} |
| 72 manager_.RegisterMemoryPressureListener(); | |
| 73 } | |
| 74 | 71 |
| 75 protected: | 72 protected: |
| 76 enum LockStatus { | 73 enum LockStatus { |
| 77 LOCK_STATUS_FAILED, | 74 LOCK_STATUS_FAILED, |
| 78 LOCK_STATUS_PURGED, | 75 LOCK_STATUS_PURGED, |
| 79 LOCK_STATUS_SUCCESS | 76 LOCK_STATUS_SUCCESS |
| 80 }; | 77 }; |
| 81 | 78 |
| 82 size_t BytesAllocated() const { return manager_.GetBytesAllocatedForTest(); } | 79 size_t BytesAllocated() const { return manager_.GetBytesAllocatedForTest(); } |
| 83 | 80 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 manager_.Register(allocation, bytes); | 117 manager_.Register(allocation, bytes); |
| 121 return Lock(allocation); | 118 return Lock(allocation); |
| 122 } | 119 } |
| 123 | 120 |
| 124 bool CanBePurged(TestAllocationImpl* allocation) const { | 121 bool CanBePurged(TestAllocationImpl* allocation) const { |
| 125 return manager_.CanBePurgedForTest(allocation); | 122 return manager_.CanBePurgedForTest(allocation); |
| 126 } | 123 } |
| 127 | 124 |
| 128 void SetNow(TimeTicks now) { manager_.SetNow(now); } | 125 void SetNow(TimeTicks now) { manager_.SetNow(now); } |
| 129 | 126 |
| 127 void PurgeAll() { return manager_.PurgeAll(); } |
| 128 |
| 130 bool ReduceMemoryUsage() { return manager_.ReduceMemoryUsage(); } | 129 bool ReduceMemoryUsage() { return manager_.ReduceMemoryUsage(); } |
| 131 | 130 |
| 131 void ReduceMemoryUsageUntilWithinModeratePressureLimit() { |
| 132 manager_.ReduceMemoryUsageUntilWithinModeratePressureLimit(); |
| 133 } |
| 134 |
| 132 private: | 135 private: |
| 133 MessageLoopForIO message_loop_; | |
| 134 TestDiscardableMemoryManagerImpl manager_; | 136 TestDiscardableMemoryManagerImpl manager_; |
| 135 }; | 137 }; |
| 136 | 138 |
| 137 class DiscardableMemoryManagerTest : public DiscardableMemoryManagerTestBase, | 139 class DiscardableMemoryManagerTest : public DiscardableMemoryManagerTestBase, |
| 138 public testing::Test { | 140 public testing::Test { |
| 139 public: | 141 public: |
| 140 DiscardableMemoryManagerTest() {} | 142 DiscardableMemoryManagerTest() {} |
| 141 }; | 143 }; |
| 142 | 144 |
| 143 TEST_F(DiscardableMemoryManagerTest, CreateAndLock) { | 145 TEST_F(DiscardableMemoryManagerTest, CreateAndLock) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 TestAllocationImpl allocation; | 187 TestAllocationImpl allocation; |
| 186 RegisterAndLock(&allocation, size); | 188 RegisterAndLock(&allocation, size); |
| 187 EXPECT_EQ(1024u, BytesAllocated()); | 189 EXPECT_EQ(1024u, BytesAllocated()); |
| 188 EXPECT_FALSE(CanBePurged(&allocation)); | 190 EXPECT_FALSE(CanBePurged(&allocation)); |
| 189 | 191 |
| 190 // Now unlock so we can lock later. | 192 // Now unlock so we can lock later. |
| 191 Unlock(&allocation); | 193 Unlock(&allocation); |
| 192 EXPECT_TRUE(CanBePurged(&allocation)); | 194 EXPECT_TRUE(CanBePurged(&allocation)); |
| 193 | 195 |
| 194 // Force the system to purge. | 196 // Force the system to purge. |
| 195 MemoryPressureListener::NotifyMemoryPressure( | 197 PurgeAll(); |
| 196 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL); | |
| 197 | |
| 198 // Required because ObserverListThreadSafe notifies via PostTask. | |
| 199 RunLoop().RunUntilIdle(); | |
| 200 | 198 |
| 201 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation)); | 199 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation)); |
| 202 EXPECT_FALSE(CanBePurged(&allocation)); | 200 EXPECT_FALSE(CanBePurged(&allocation)); |
| 203 | 201 |
| 204 Unlock(&allocation); | 202 Unlock(&allocation); |
| 205 Unregister(&allocation); | 203 Unregister(&allocation); |
| 206 } | 204 } |
| 207 | 205 |
| 208 TEST_F(DiscardableMemoryManagerTest, LockAfterPurgeAndCannotReallocate) { | 206 TEST_F(DiscardableMemoryManagerTest, LockAfterPurgeAndCannotReallocate) { |
| 209 size_t size = 1024; | 207 size_t size = 1024; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 if (allocation_[i].is_locked()) | 292 if (allocation_[i].is_locked()) |
| 295 Unlock(&allocation_[i]); | 293 Unlock(&allocation_[i]); |
| 296 Unregister(&allocation_[i]); | 294 Unregister(&allocation_[i]); |
| 297 } | 295 } |
| 298 } | 296 } |
| 299 | 297 |
| 300 private: | 298 private: |
| 301 TestAllocationImpl allocation_[3]; | 299 TestAllocationImpl allocation_[3]; |
| 302 }; | 300 }; |
| 303 | 301 |
| 304 // Verify that memory was discarded in the correct order after applying | 302 // Verify that memory was discarded in the correct order after reducing usage to |
| 305 // memory pressure. | 303 // moderate pressure limit. |
| 306 TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedModeratePressure) { | 304 TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedModeratePressure) { |
| 307 RegisterAndUseAllocations(); | 305 RegisterAndUseAllocations(); |
| 308 | 306 |
| 309 SetBytesToKeepUnderModeratePressure(1024); | 307 SetBytesToKeepUnderModeratePressure(1024); |
| 310 SetMemoryLimit(2048); | 308 SetMemoryLimit(2048); |
| 311 | 309 |
| 312 MemoryPressureListener::NotifyMemoryPressure( | 310 ReduceMemoryUsageUntilWithinModeratePressureLimit(); |
| 313 MemoryPressureListener::MEMORY_PRESSURE_MODERATE); | |
| 314 RunLoop().RunUntilIdle(); | |
| 315 | 311 |
| 316 EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2))); | 312 EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2))); |
| 317 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); | 313 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); |
| 318 // 0 should still be locked. | 314 // 0 should still be locked. |
| 319 EXPECT_TRUE(allocation(0)->is_locked()); | 315 EXPECT_TRUE(allocation(0)->is_locked()); |
| 320 | 316 |
| 321 UnlockAndUnregisterAllocations(); | 317 UnlockAndUnregisterAllocations(); |
| 322 } | 318 } |
| 323 | 319 |
| 324 // Verify that memory was discarded in the correct order after changing | 320 // Verify that memory was discarded in the correct order after changing |
| (...skipping 26 matching lines...) Expand all Loading... |
| 351 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); | 347 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); |
| 352 // 0 should still be locked. | 348 // 0 should still be locked. |
| 353 EXPECT_TRUE(allocation(0)->is_locked()); | 349 EXPECT_TRUE(allocation(0)->is_locked()); |
| 354 | 350 |
| 355 UnlockAndUnregisterAllocations(); | 351 UnlockAndUnregisterAllocations(); |
| 356 } | 352 } |
| 357 | 353 |
| 358 TEST_P(DiscardableMemoryManagerPermutationTest, PurgeFreesAllUnlocked) { | 354 TEST_P(DiscardableMemoryManagerPermutationTest, PurgeFreesAllUnlocked) { |
| 359 RegisterAndUseAllocations(); | 355 RegisterAndUseAllocations(); |
| 360 | 356 |
| 361 MemoryPressureListener::NotifyMemoryPressure( | 357 PurgeAll(); |
| 362 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL); | |
| 363 RunLoop().RunUntilIdle(); | |
| 364 | 358 |
| 365 for (int i = 0; i < 3; ++i) { | 359 for (int i = 0; i < 3; ++i) { |
| 366 if (i == 0) | 360 if (i == 0) |
| 367 EXPECT_TRUE(allocation(i)->is_locked()); | 361 EXPECT_TRUE(allocation(i)->is_locked()); |
| 368 else | 362 else |
| 369 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(i))); | 363 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(i))); |
| 370 } | 364 } |
| 371 | 365 |
| 372 UnlockAndUnregisterAllocations(); | 366 UnlockAndUnregisterAllocations(); |
| 373 } | 367 } |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 Unretained(this))); | 490 Unretained(this))); |
| 497 memory_usage_thread_.message_loop()->PostTask( | 491 memory_usage_thread_.message_loop()->PostTask( |
| 498 FROM_HERE, | 492 FROM_HERE, |
| 499 Bind(&ThreadedDiscardableMemoryManagerTest::SignalHelper, | 493 Bind(&ThreadedDiscardableMemoryManagerTest::SignalHelper, |
| 500 Unretained(this))); | 494 Unretained(this))); |
| 501 thread_sync_.Wait(); | 495 thread_sync_.Wait(); |
| 502 } | 496 } |
| 503 | 497 |
| 504 } // namespace | 498 } // namespace |
| 505 } // namespace base | 499 } // namespace base |
| OLD | NEW |