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

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

Powered by Google App Engine
This is Rietveld 408576698