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

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: address review feedback Created 7 years, 2 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/bind.h"
8 #include "base/memory/discardable_memory.h"
9 #include "base/run_loop.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/threading/thread.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 using base::internal::DiscardableMemoryProvider;
15
16 namespace base {
17
18 class DiscardableMemoryProviderTest : public testing::Test {
19 public:
20 DiscardableMemoryProviderTest()
21 : message_loop_(MessageLoop::TYPE_IO),
22 provider_(new DiscardableMemoryProvider) {
23 // We set a provider here for two reasons:
24 // 1. It ensures that one test cannot affect the next, and
25 // 2. Since the provider listens for pressure notifications on the thread
26 // it was created on, if we create it on the test thread, we can run
27 // the test thread's message loop until idle when we want to process
28 // one of these notifications.
29 DiscardableMemoryProvider::SetInstanceForTest(provider_.get());
30 }
31
32 virtual ~DiscardableMemoryProviderTest() {
33 DiscardableMemoryProvider::SetInstanceForTest(NULL);
34 }
35
36 protected:
37 void Register(const DiscardableMemory* discardable) {
38 DiscardableMemoryProvider::GetInstance()->Register(discardable, 0);
39 }
40
41 void Unregister(const DiscardableMemory* discardable) {
42 DiscardableMemoryProvider::GetInstance()->Unregister(discardable);
43 }
44
45 bool IsRegistered(const DiscardableMemory* discardable) {
46 return DiscardableMemoryProvider::GetInstance()->IsRegisteredForTest(
47 discardable);
48 }
49
50 bool CanBePurged(const DiscardableMemory* discardable) {
51 return DiscardableMemoryProvider::GetInstance()->CanBePurgedForTest(
52 discardable);
53 }
54
55 size_t BytesAllocated() const {
56 return DiscardableMemoryProvider::GetInstance()->
57 GetBytesAllocatedForTest();
58 }
59
60 void* Memory(const DiscardableMemory& discardable) const {
61 return discardable.Memory();
62 }
63
64 void SetDiscardableMemoryLimit(size_t bytes) {
65 DiscardableMemoryProvider::GetInstance()->
66 SetDiscardableMemoryLimit(bytes);
67 }
68
69 void SetBytesToReclaimUnderModeratePressure(size_t bytes) {
70 DiscardableMemoryProvider::GetInstance()->
71 SetBytesToReclaimUnderModeratePressure(bytes);
72 }
73
74 private:
75 MessageLoop message_loop_;
76 scoped_ptr<DiscardableMemoryProvider> provider_;
77 };
78
79 TEST_F(DiscardableMemoryProviderTest, Register) {
80 DiscardableMemory discardable;
81 EXPECT_EQ(0u, BytesAllocated());
82 Register(&discardable);
83 EXPECT_TRUE(IsRegistered(&discardable));
84 EXPECT_EQ(0u, BytesAllocated());
85 Unregister(&discardable);
86 EXPECT_FALSE(IsRegistered(&discardable));
87 }
88
89 TEST_F(DiscardableMemoryProviderTest, InitializeAndLock) {
90 DiscardableMemory discardable;
91 size_t size = 1024;
92 EXPECT_TRUE(discardable.InitializeAndLock(size));
93 EXPECT_TRUE(IsRegistered(&discardable));
94 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable));
95 EXPECT_EQ(1024u, BytesAllocated());
96 EXPECT_FALSE(CanBePurged(&discardable));
97 }
98
99 TEST_F(DiscardableMemoryProviderTest, InitializeAndLockZeroSize) {
100 DiscardableMemory discardable;
101 size_t size = 0;
102 EXPECT_FALSE(discardable.InitializeAndLock(size));
103 EXPECT_TRUE(IsRegistered(&discardable));
104 EXPECT_EQ(0u, BytesAllocated());
105 EXPECT_FALSE(CanBePurged(&discardable));
106 }
107
108 static void AttemptToLockBeforeInitialization(DiscardableMemory* discardable) {
109 EXPECT_EQ(DISCARDABLE_MEMORY_FAILED, discardable->Lock());
110 }
111
112 TEST_F(DiscardableMemoryProviderTest, LockBeforeInitialization) {
113 DiscardableMemory discardable;
114 EXPECT_DEATH(AttemptToLockBeforeInitialization(&discardable),
115 ".*Check failed.*");
116 }
117
118 TEST_F(DiscardableMemoryProviderTest, LockAfterUnlock) {
119 DiscardableMemory discardable;
120 size_t size = 1024;
121 EXPECT_TRUE(discardable.InitializeAndLock(size));
122 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable));
123 EXPECT_EQ(1024u, BytesAllocated());
124 EXPECT_FALSE(CanBePurged(&discardable));
125
126 // Now unlock so we can lock later.
127 discardable.Unlock();
128 EXPECT_TRUE(CanBePurged(&discardable));
129
130 EXPECT_EQ(DISCARDABLE_MEMORY_SUCCESS, discardable.Lock());
131 EXPECT_FALSE(CanBePurged(&discardable));
132 }
133
134 TEST_F(DiscardableMemoryProviderTest, LockAfterPurge) {
135 DiscardableMemory discardable;
136 size_t size = 1024;
137 EXPECT_TRUE(discardable.InitializeAndLock(size));
138 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable));
139 EXPECT_EQ(1024u, BytesAllocated());
140 EXPECT_FALSE(CanBePurged(&discardable));
141
142 // Now unlock so we can lock later.
143 discardable.Unlock();
144 EXPECT_TRUE(CanBePurged(&discardable));
145
146 // Force the system to purge.
147 MemoryPressureListener::NotifyMemoryPressure(
148 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL);
149
150 // Required because ObserverListThreadSafe notifies via PostTask.
151 RunLoop().RunUntilIdle();
152
153 EXPECT_EQ(DISCARDABLE_MEMORY_PURGED, discardable.Lock());
154 EXPECT_FALSE(CanBePurged(&discardable));
155 }
156
157 TEST_F(DiscardableMemoryProviderTest, LockAfterPurgeAndCannotReallocate) {
158 DiscardableMemory discardable;
159 size_t size = 1024;
160 EXPECT_TRUE(discardable.InitializeAndLock(size));
161 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable));
162 EXPECT_EQ(1024u, BytesAllocated());
163 EXPECT_FALSE(CanBePurged(&discardable));
164
165 // Now unlock so we can lock later.
166 discardable.Unlock();
167 EXPECT_TRUE(CanBePurged(&discardable));
168
169 // Force the system to purge.
170 MemoryPressureListener::NotifyMemoryPressure(
171 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL);
172
173 // Required because ObserverListThreadSafe notifies via PostTask.
174 RunLoop().RunUntilIdle();
175
176 // Set max allowed allocation to 1 byte. This will make reallocation fail.
177 SetDiscardableMemoryLimit(1);
178
179 EXPECT_EQ(DISCARDABLE_MEMORY_FAILED, discardable.Lock());
180 EXPECT_FALSE(CanBePurged(&discardable));
181 }
182
183 // Use discardable memory in order specified by d0, d1 and d2 then apply
184 // memory pressure and verify that memory was discarded in the correct order.
185 #define DiscardableMemoryProviderPermutionTest(name, d0, d1, d2, pressure) \
186 TEST_F(DiscardableMemoryProviderTest, name##_##d0##_##d1##_##d2) { \
187 DiscardableMemory discardables[3]; \
188 for (int i = 0; i < 3; ++i) { \
189 EXPECT_TRUE(discardables[i].InitializeAndLock(1024)); \
190 EXPECT_NE(static_cast<void*>(NULL), Memory(discardables[i])); \
191 discardables[i].Unlock(); \
192 } \
193 int ordering[] = { d0, d1, d2 }; \
194 for (int i = 0; i < 3; ++i) { \
195 int current_index = ordering[i]; \
196 EXPECT_NE(DISCARDABLE_MEMORY_FAILED, discardables[current_index].Lock()); \
197 if (i > 0) \
198 discardables[current_index].Unlock(); \
199 } \
200 SetBytesToReclaimUnderModeratePressure(1024); \
201 if (pressure) { \
202 MemoryPressureListener::NotifyMemoryPressure( \
203 MemoryPressureListener::MEMORY_PRESSURE_MODERATE); \
204 RunLoop().RunUntilIdle(); \
205 } else { \
206 SetDiscardableMemoryLimit(2048); \
207 } \
208 EXPECT_NE(DISCARDABLE_MEMORY_FAILED, discardables[ordering[2]].Lock()); \
209 EXPECT_NE(DISCARDABLE_MEMORY_SUCCESS, discardables[ordering[1]].Lock()); \
210 EXPECT_NE(static_cast<void*>(NULL), Memory(discardables[ordering[0]])); \
211 }
212
213 #define DiscardableMemoryProviderPermutions(name, pressure) \
214 DiscardableMemoryProviderPermutionTest(name, 0, 1, 2, pressure); \
215 DiscardableMemoryProviderPermutionTest(name, 0, 2, 1, pressure); \
216 DiscardableMemoryProviderPermutionTest(name, 1, 0, 2, pressure); \
217 DiscardableMemoryProviderPermutionTest(name, 1, 2, 0, pressure); \
218 DiscardableMemoryProviderPermutionTest(name, 2, 0, 1, pressure); \
219 DiscardableMemoryProviderPermutionTest(name, 2, 1, 0, pressure);
220
221 DiscardableMemoryProviderPermutions(LRUDiscardedModeratePressure, true);
222 DiscardableMemoryProviderPermutions(LRUDiscardedExceedLimit, false);
223
224 TEST_F(DiscardableMemoryProviderTest, CriticalPressureFreesAllUnlocked) {
225 DiscardableMemory discardables[3];
226 for (int i = 0; i < 3; ++i) {
227 EXPECT_TRUE(discardables[i].InitializeAndLock(1024));
228 EXPECT_NE(static_cast<void*>(NULL), Memory(discardables[i]));
229 discardables[i].Unlock();
230 }
231
232 for (int i = 0; i < 3; ++i) {
233 EXPECT_NE(DISCARDABLE_MEMORY_FAILED, discardables[i].Lock());
234 if (i > 0)
235 discardables[i].Unlock();
236 }
237
238 MemoryPressureListener::NotifyMemoryPressure(
239 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL);
240 RunLoop().RunUntilIdle();
241
242 for (int i = 0; i < 3; ++i) {
243 if (i == 0)
244 EXPECT_NE(static_cast<void*>(NULL), Memory(discardables[i]));
245 else
246 EXPECT_EQ(DISCARDABLE_MEMORY_PURGED, discardables[i].Lock());
247 }
248 }
249
250 TEST_F(DiscardableMemoryProviderTest, NormalDestruction) {
251 {
252 DiscardableMemory discardable;
253 size_t size = 1024;
254 EXPECT_TRUE(discardable.InitializeAndLock(size));
255 EXPECT_EQ(1024u, BytesAllocated());
256 }
257 EXPECT_EQ(0u, BytesAllocated());
258 }
259
260 TEST_F(DiscardableMemoryProviderTest, DestructionWhileLocked) {
261 {
262 DiscardableMemory discardable;
263 size_t size = 1024;
264 EXPECT_TRUE(discardable.InitializeAndLock(size));
265 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable));
266 EXPECT_EQ(1024u, BytesAllocated());
267 EXPECT_FALSE(CanBePurged(&discardable));
268 }
269 // Should have ignored the "locked" status and freed the discardable memory.
270 EXPECT_EQ(0u, BytesAllocated());
271 }
272
273 TEST_F(DiscardableMemoryProviderTest, MemoryBeforeLock) {
274 DiscardableMemory discardable;
275 // We *must* die if we are asked to vend a pointer to unlocked memory.
276 EXPECT_DEATH(discardable.Memory(), ".*Check failed.*");
277 }
278
279 TEST_F(DiscardableMemoryProviderTest, MemoryAfterUnlock) {
280 DiscardableMemory discardable;
281 size_t size = 1024;
282 EXPECT_TRUE(discardable.InitializeAndLock(size));
283 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable));
284 EXPECT_EQ(1024u, BytesAllocated());
285 EXPECT_FALSE(CanBePurged(&discardable));
286 discardable.Unlock();
287 EXPECT_TRUE(CanBePurged(&discardable));
288 // We *must* die if we are asked to vend a pointer to unlocked memory.
289 EXPECT_DEATH(discardable.Memory(), ".*Check failed.*");
290 }
291
292 class ThreadedDiscardableMemoryProviderTest
293 : public DiscardableMemoryProviderTest {
294 public:
295 ThreadedDiscardableMemoryProviderTest()
296 : memory_usage_thread_("memory_usage_thread"),
297 thread_sync_(true, false) {
298 }
299
300 virtual void SetUp() OVERRIDE {
301 memory_usage_thread_.Start();
302 }
303
304 virtual void TearDown() OVERRIDE {
305 memory_usage_thread_.Stop();
306 }
307
308 void UseMemoryHelper() {
309 DiscardableMemory discardable;
310 size_t size = 1024;
311 EXPECT_TRUE(discardable.InitializeAndLock(size));
312 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable));
313 discardable.Unlock();
314 }
315
316 void SignalHelper() {
317 thread_sync_.Signal();
318 }
319
320 Thread memory_usage_thread_;
321 WaitableEvent thread_sync_;
322 };
323
324 TEST_F(ThreadedDiscardableMemoryProviderTest, UseMemoryOnThread) {
325 memory_usage_thread_.message_loop()->PostTask(
326 FROM_HERE,
327 Bind(&ThreadedDiscardableMemoryProviderTest::UseMemoryHelper,
328 Unretained(this)));
329 memory_usage_thread_.message_loop()->PostTask(
330 FROM_HERE,
331 Bind(&ThreadedDiscardableMemoryProviderTest::SignalHelper,
332 Unretained(this)));
333 thread_sync_.Wait();
334 }
335
336 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698