Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: base/memory/discardable_memory_provider_unittest.cc

Issue 17106004: Add discardable memory emulation for non-android/mac platforms (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/memory/discardable_memory_provider.h"
6
7 #include "base/memory/discardable_memory.h"
8 #include "base/run_loop.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace base {
12
13 class DiscardableMemoryProviderTest : public testing::Test {
14 public:
15 DiscardableMemoryProviderTest()
16 : message_loop_(MessageLoop::TYPE_IO),
17 provider_(new DiscardableMemoryProvider) {
18 // We set a provider here for two reasons:
19 // 1. It ensures that one test cannot affect the next, and
20 // 2. Since the provider listens for pressure notifications on the thread
21 // it was created on, if we create it on the test thread, we can run
22 // the test thread's message loop until idle when we want to process
23 // on of these notifications.
24 DiscardableMemoryProvider::SetInstanceForTest(provider_.get());
25 }
26
27 virtual ~DiscardableMemoryProviderTest() {
28 DiscardableMemoryProvider::SetInstanceForTest(NULL);
29 }
30
31 protected:
32 void Register(DiscardableMemory* discardable) {
33 DiscardableMemoryProvider::GetInstance()->Register(discardable);
34 }
35
36 const DiscardableMemoryProvider::AllocationMap& allocations() const {
37 return DiscardableMemoryProvider::GetInstance()->allocations_;
38 }
39
40 size_t bytes_allocated() const {
41 return DiscardableMemoryProvider::GetInstance()->bytes_allocated_;
42 }
43
44 void* Memory(const DiscardableMemory& discardable) const {
45 return discardable.memory_;
46 }
47
48 void SetDiscardableMemoryLimit(size_t bytes) {
49 DiscardableMemoryProvider::GetInstance()->
50 SetDiscardableMemoryLimit(bytes);
51 }
52
53 void SetBytesToReclaimUnderModeratePressure(size_t bytes) {
54 DiscardableMemoryProvider::GetInstance()->
55 SetBytesToReclaimUnderModeratePressure(bytes);
56 }
57
58 private:
59 MessageLoop message_loop_;
60 scoped_ptr<DiscardableMemoryProvider> provider_;
61 };
62
63 TEST_F(DiscardableMemoryProviderTest, Register) {
64 DiscardableMemory discardable;
65 Register(&discardable);
66 ASSERT_NE(allocations().end(), allocations().Peek(&discardable));
67 ASSERT_EQ(0u, bytes_allocated());
68 }
69
70 TEST_F(DiscardableMemoryProviderTest, InitializeAndLock) {
71 DiscardableMemory discardable;
72 ASSERT_EQ(static_cast<void*>(NULL), Memory(discardable));
73 size_t size = 1024;
74 ASSERT_TRUE(discardable.InitializeAndLock(size));
75 ASSERT_NE(allocations().end(), allocations().Peek(&discardable));
76 ASSERT_NE(static_cast<void*>(NULL), Memory(discardable));
77 ASSERT_EQ(1024u, bytes_allocated());
78 ASSERT_TRUE(discardable.is_locked());
79 }
80
81 TEST_F(DiscardableMemoryProviderTest, InitializeAndLockZeroSize) {
82 DiscardableMemory discardable;
83 ASSERT_EQ(static_cast<void*>(NULL), Memory(discardable));
84 size_t size = 0;
85 ASSERT_FALSE(discardable.InitializeAndLock(size));
86 ASSERT_NE(allocations().end(), allocations().Peek(&discardable));
87 ASSERT_EQ(static_cast<void*>(NULL), Memory(discardable));
88 ASSERT_EQ(0u, bytes_allocated());
89 ASSERT_FALSE(discardable.is_locked());
90 }
91
92 TEST_F(DiscardableMemoryProviderTest, LockBeforeInitialization) {
93 DiscardableMemory discardable;
94 ASSERT_EQ(DISCARDABLE_MEMORY_FAILED, discardable.Lock());
95 }
96
97 TEST_F(DiscardableMemoryProviderTest, LockAfterUnlock) {
98 DiscardableMemory discardable;
99 ASSERT_EQ(static_cast<void*>(NULL), Memory(discardable));
100 size_t size = 1024;
101 ASSERT_TRUE(discardable.InitializeAndLock(size));
102 ASSERT_NE(allocations().end(), allocations().Peek(&discardable));
103 ASSERT_NE(static_cast<void*>(NULL), Memory(discardable));
104 ASSERT_EQ(1024u, bytes_allocated());
105 ASSERT_TRUE(discardable.is_locked());
106
107 // Now to unlock so we can lock later.
108 discardable.Unlock();
109 ASSERT_FALSE(discardable.is_locked());
110
111 ASSERT_EQ(DISCARDABLE_MEMORY_SUCCESS, discardable.Lock());
112 ASSERT_TRUE(discardable.is_locked());
113 }
114
115 TEST_F(DiscardableMemoryProviderTest, LockAfterPurge) {
116 DiscardableMemory discardable;
117 ASSERT_EQ(static_cast<void*>(NULL), Memory(discardable));
118 size_t size = 1024;
119 ASSERT_TRUE(discardable.InitializeAndLock(size));
120 ASSERT_NE(allocations().end(), allocations().Peek(&discardable));
121 ASSERT_NE(static_cast<void*>(NULL), Memory(discardable));
122 ASSERT_EQ(1024u, bytes_allocated());
123 ASSERT_TRUE(discardable.is_locked());
124
125 // Now to unlock so we can lock later.
126 discardable.Unlock();
127 ASSERT_FALSE(discardable.is_locked());
128
129 // Force the system to purge.
130 MemoryPressureListener::NotifyMemoryPressure(
131 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL);
132
133 // Required because ObserverListThreadSafe notifies via PostTask.
134 RunLoop().RunUntilIdle();
135
136 ASSERT_EQ(DISCARDABLE_MEMORY_PURGED, discardable.Lock());
137 ASSERT_TRUE(discardable.is_locked());
138 }
139
140 TEST_F(DiscardableMemoryProviderTest, LockAfterPurgeAndCannotReallocate) {
141 DiscardableMemory discardable;
142 ASSERT_EQ(static_cast<void*>(NULL), Memory(discardable));
143 size_t size = 1024;
144 ASSERT_TRUE(discardable.InitializeAndLock(size));
145 ASSERT_NE(allocations().end(), allocations().Peek(&discardable));
146 ASSERT_NE(static_cast<void*>(NULL), Memory(discardable));
147 ASSERT_EQ(1024u, bytes_allocated());
148 ASSERT_TRUE(discardable.is_locked());
149
150 // Now to unlock so we can lock later.
151 discardable.Unlock();
152 ASSERT_FALSE(discardable.is_locked());
153
154 // Force the system to purge.
155 MemoryPressureListener::NotifyMemoryPressure(
156 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL);
157
158 // Required because ObserverListThreadSafe notifies via PostTask.
159 RunLoop().RunUntilIdle();
160
161 // Set max allowed allocation to 1 byte. This will make reallocation fail.
162 SetDiscardableMemoryLimit(1);
163
164 ASSERT_EQ(DISCARDABLE_MEMORY_FAILED, discardable.Lock());
165 ASSERT_FALSE(discardable.is_locked());
166 }
167
168 #define DiscardableMemoryProviderPermutionTest(name, d0, d1, d2, pressure) \
169 TEST_F(DiscardableMemoryProviderTest, name##_##d0##_##d1##_##d2) { \
170 DiscardableMemory discardables[3]; \
171 for (int i = 0; i < 3; ++i) { \
172 ASSERT_EQ(static_cast<void*>(NULL), Memory(discardables[i])); \
173 ASSERT_TRUE(discardables[i].InitializeAndLock(1024)); \
174 discardables[i].Unlock(); \
175 ASSERT_NE(static_cast<void*>(NULL), Memory(discardables[i])); \
176 } \
177 int ordering[] = { d0, d1, d2 }; \
178 for (int i = 0; i < 3; ++i) { \
179 int current_index = ordering[i]; \
180 ASSERT_NE(DISCARDABLE_MEMORY_FAILED, discardables[current_index].Lock()); \
181 if (i > 0) \
182 discardables[current_index].Unlock(); \
183 } \
184 SetBytesToReclaimUnderModeratePressure(1024); \
185 if (pressure) { \
186 MemoryPressureListener::NotifyMemoryPressure( \
187 MemoryPressureListener::MEMORY_PRESSURE_MODERATE); \
188 RunLoop().RunUntilIdle(); \
189 } else { \
190 SetDiscardableMemoryLimit(2048); \
191 } \
192 for (int i = 0; i < 3; ++i) { \
193 if (i == 1) \
194 ASSERT_EQ(static_cast<void*>(NULL), Memory(discardables[ordering[i]])); \
195 else \
196 ASSERT_NE(static_cast<void*>(NULL), Memory(discardables[ordering[i]])); \
197 } \
198 }
199
200 #define DiscardableMemoryProviderPermutions(name, pressure) \
201 DiscardableMemoryProviderPermutionTest(name, 0, 1, 2, pressure); \
202 DiscardableMemoryProviderPermutionTest(name, 0, 2, 1, pressure); \
203 DiscardableMemoryProviderPermutionTest(name, 1, 0, 2, pressure); \
204 DiscardableMemoryProviderPermutionTest(name, 1, 2, 0, pressure); \
205 DiscardableMemoryProviderPermutionTest(name, 2, 0, 1, pressure); \
206 DiscardableMemoryProviderPermutionTest(name, 2, 1, 0, pressure);
207
208 DiscardableMemoryProviderPermutions(LRUDiscardedModeratePressure, true);
209 DiscardableMemoryProviderPermutions(LRUDiscardedExceedLimit, false);
210
211 TEST_F(DiscardableMemoryProviderTest, CriticalPressureFreesAllUnlocked) {
212 DiscardableMemory discardables[3];
213 for (int i = 0; i < 3; ++i) {
214 ASSERT_EQ(static_cast<void*>(NULL), Memory(discardables[i]));
215 ASSERT_TRUE(discardables[i].InitializeAndLock(1024));
216 discardables[i].Unlock();
217 ASSERT_NE(static_cast<void*>(NULL), Memory(discardables[i]));
218 }
219
220 for (int i = 0; i < 3; ++i) {
221 ASSERT_NE(DISCARDABLE_MEMORY_FAILED, discardables[i].Lock());
222 if (i > 0)
223 discardables[i].Unlock();
224 }
225
226 MemoryPressureListener::NotifyMemoryPressure(
227 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL);
228 RunLoop().RunUntilIdle();
229
230 for (int i = 0; i < 3; ++i) {
231 if (discardables[i].is_locked())
232 ASSERT_NE(static_cast<void*>(NULL), Memory(discardables[i]));
233 else
234 ASSERT_EQ(static_cast<void*>(NULL), Memory(discardables[i]));
235 }
236 }
237
238 TEST_F(DiscardableMemoryProviderTest, NormalDestruction) {
239 {
240 DiscardableMemory discardable;
241 size_t size = 1024;
242 ASSERT_TRUE(discardable.InitializeAndLock(size));
243 ASSERT_NE(allocations().end(), allocations().Peek(&discardable));
244 ASSERT_EQ(1024u, bytes_allocated());
245 }
246 ASSERT_TRUE(allocations().empty());
247 ASSERT_EQ(0u, bytes_allocated());
248 }
249
250 TEST_F(DiscardableMemoryProviderTest, DestructionWhileLocked) {
251 {
252 DiscardableMemory discardable;
253 ASSERT_EQ(static_cast<void*>(NULL), Memory(discardable));
254 size_t size = 1024;
255 ASSERT_TRUE(discardable.InitializeAndLock(size));
256 ASSERT_NE(allocations().end(), allocations().Peek(&discardable));
257 ASSERT_NE(static_cast<void*>(NULL), Memory(discardable));
258 ASSERT_EQ(1024u, bytes_allocated());
259 ASSERT_TRUE(discardable.is_locked());
260 }
261 // Should have ignored the "locked" status and freed the discardable memory.
262 ASSERT_TRUE(allocations().empty());
263 ASSERT_EQ(0u, bytes_allocated());
264 }
265
266 TEST_F(DiscardableMemoryProviderTest, MemoryBeforeLock) {
267 DiscardableMemory discardable;
268 // We *must* die if we are asked to vend a pointer to unlocked memory.
269 EXPECT_DEATH(discardable.Memory(), ".*Check failed.*");
270 }
271
272 TEST_F(DiscardableMemoryProviderTest, MemoryAfterUnlock) {
273 DiscardableMemory discardable;
274 ASSERT_EQ(static_cast<void*>(NULL), Memory(discardable));
275 size_t size = 1024;
276 ASSERT_TRUE(discardable.InitializeAndLock(size));
277 ASSERT_NE(allocations().end(), allocations().Peek(&discardable));
278 ASSERT_NE(static_cast<void*>(NULL), Memory(discardable));
279 ASSERT_EQ(1024u, bytes_allocated());
280 ASSERT_TRUE(discardable.is_locked());
281 discardable.Unlock();
282 ASSERT_FALSE(discardable.is_locked());
283 // We *must* die if we are asked to vend a pointer to unlocked memory.
284 EXPECT_DEATH(discardable.Memory(), ".*Check failed.*");
285 }
286
287 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698