GPU workaround to simulate Out of Memory errors with large textures
[chromium-blink-merge.git] / content / common / discardable_shared_memory_heap_unittest.cc
blob5297ded0cc49a2fb903189feb1bfd2683cda8957
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
3 // found in the LICENSE file.
5 #include "content/common/discardable_shared_memory_heap.h"
7 #include "base/bind.h"
8 #include "base/memory/discardable_shared_memory.h"
9 #include "base/process/process_metrics.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 namespace content {
13 namespace {
15 void NullTask() {
18 TEST(DiscardableSharedMemoryHeapTest, Basic) {
19 size_t block_size = base::GetPageSize();
20 DiscardableSharedMemoryHeap heap(block_size);
22 // Initial size should be 0.
23 EXPECT_EQ(0u, heap.GetSize());
25 // Initial size of free lists should be 0.
26 EXPECT_EQ(0u, heap.GetSizeOfFreeLists());
28 // Free lists are initially empty.
29 EXPECT_FALSE(heap.SearchFreeLists(1, 0));
31 const size_t kBlocks = 10;
32 size_t memory_size = block_size * kBlocks;
34 scoped_ptr<base::DiscardableSharedMemory> memory(
35 new base::DiscardableSharedMemory);
36 ASSERT_TRUE(memory->CreateAndMap(memory_size));
38 // Create new span for memory.
39 scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(
40 heap.Grow(memory.Pass(), memory_size, base::Bind(NullTask)));
42 // Size should match |memory_size|.
43 EXPECT_EQ(memory_size, heap.GetSize());
45 // Size of free lists should still be 0.
46 EXPECT_EQ(0u, heap.GetSizeOfFreeLists());
48 // Free list should still be empty as |new_span| is currently in use.
49 EXPECT_FALSE(heap.SearchFreeLists(1, 0));
51 // Done using |new_span|. Merge it into the free lists.
52 heap.MergeIntoFreeLists(new_span.Pass());
54 // Size of free lists should now match |memory_size|.
55 EXPECT_EQ(memory_size, heap.GetSizeOfFreeLists());
57 // Free lists should not contain a span that is larger than kBlocks.
58 EXPECT_FALSE(heap.SearchFreeLists(kBlocks + 1, 0));
60 // Free lists should contain a span that satisfies the request for kBlocks.
61 scoped_ptr<DiscardableSharedMemoryHeap::Span> span =
62 heap.SearchFreeLists(kBlocks, 0);
63 ASSERT_TRUE(span);
65 // Free lists should be empty again.
66 EXPECT_FALSE(heap.SearchFreeLists(1, 0));
68 // Merge it into the free lists again.
69 heap.MergeIntoFreeLists(span.Pass());
72 TEST(DiscardableSharedMemoryHeapTest, SplitAndMerge) {
73 size_t block_size = base::GetPageSize();
74 DiscardableSharedMemoryHeap heap(block_size);
76 const size_t kBlocks = 6;
77 size_t memory_size = block_size * kBlocks;
79 scoped_ptr<base::DiscardableSharedMemory> memory(
80 new base::DiscardableSharedMemory);
81 ASSERT_TRUE(memory->CreateAndMap(memory_size));
82 scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(
83 heap.Grow(memory.Pass(), memory_size, base::Bind(NullTask)));
85 // Split span into two.
86 scoped_ptr<DiscardableSharedMemoryHeap::Span> leftover =
87 heap.Split(new_span.get(), 3);
88 ASSERT_TRUE(leftover);
90 // Merge |leftover| into free lists.
91 heap.MergeIntoFreeLists(leftover.Pass());
93 // Some of the memory is still in use.
94 EXPECT_FALSE(heap.SearchFreeLists(kBlocks, 0));
96 // Merge |span| into free lists.
97 heap.MergeIntoFreeLists(new_span.Pass());
99 // Remove a 2 page span from free lists.
100 scoped_ptr<DiscardableSharedMemoryHeap::Span> span1 =
101 heap.SearchFreeLists(2, kBlocks);
102 ASSERT_TRUE(span1);
104 // Remove another 2 page span from free lists.
105 scoped_ptr<DiscardableSharedMemoryHeap::Span> span2 =
106 heap.SearchFreeLists(2, kBlocks);
107 ASSERT_TRUE(span2);
109 // Merge |span1| back into free lists.
110 heap.MergeIntoFreeLists(span1.Pass());
112 // Some of the memory is still in use.
113 EXPECT_FALSE(heap.SearchFreeLists(kBlocks, 0));
115 // Merge |span2| back into free lists.
116 heap.MergeIntoFreeLists(span2.Pass());
118 // All memory has been returned to the free lists.
119 scoped_ptr<DiscardableSharedMemoryHeap::Span> large_span =
120 heap.SearchFreeLists(kBlocks, 0);
121 ASSERT_TRUE(large_span);
123 // Merge it into the free lists again.
124 heap.MergeIntoFreeLists(large_span.Pass());
127 TEST(DiscardableSharedMemoryHeapTest, MergeSingleBlockSpan) {
128 size_t block_size = base::GetPageSize();
129 DiscardableSharedMemoryHeap heap(block_size);
131 const size_t kBlocks = 6;
132 size_t memory_size = block_size * kBlocks;
134 scoped_ptr<base::DiscardableSharedMemory> memory(
135 new base::DiscardableSharedMemory);
136 ASSERT_TRUE(memory->CreateAndMap(memory_size));
137 scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(
138 heap.Grow(memory.Pass(), memory_size, base::Bind(NullTask)));
140 // Split span into two.
141 scoped_ptr<DiscardableSharedMemoryHeap::Span> leftover =
142 heap.Split(new_span.get(), 5);
143 ASSERT_TRUE(leftover);
145 // Merge |new_span| into free lists.
146 heap.MergeIntoFreeLists(new_span.Pass());
148 // Merge |leftover| into free lists.
149 heap.MergeIntoFreeLists(leftover.Pass());
152 TEST(DiscardableSharedMemoryHeapTest, Grow) {
153 size_t block_size = base::GetPageSize();
154 DiscardableSharedMemoryHeap heap(block_size);
156 scoped_ptr<base::DiscardableSharedMemory> memory1(
157 new base::DiscardableSharedMemory);
158 ASSERT_TRUE(memory1->CreateAndMap(block_size));
159 heap.MergeIntoFreeLists(
160 heap.Grow(memory1.Pass(), block_size, base::Bind(NullTask)).Pass());
162 // Remove a span from free lists.
163 scoped_ptr<DiscardableSharedMemoryHeap::Span> span1 =
164 heap.SearchFreeLists(1, 0);
165 EXPECT_TRUE(span1);
167 // No more memory available.
168 EXPECT_FALSE(heap.SearchFreeLists(1, 0));
170 // Grow free lists using new memory.
171 scoped_ptr<base::DiscardableSharedMemory> memory2(
172 new base::DiscardableSharedMemory);
173 ASSERT_TRUE(memory2->CreateAndMap(block_size));
174 heap.MergeIntoFreeLists(
175 heap.Grow(memory2.Pass(), block_size, base::Bind(NullTask)).Pass());
177 // Memory should now be available.
178 scoped_ptr<DiscardableSharedMemoryHeap::Span> span2 =
179 heap.SearchFreeLists(1, 0);
180 EXPECT_TRUE(span2);
182 // Merge spans into the free lists again.
183 heap.MergeIntoFreeLists(span1.Pass());
184 heap.MergeIntoFreeLists(span2.Pass());
187 TEST(DiscardableSharedMemoryHeapTest, ReleaseFreeMemory) {
188 size_t block_size = base::GetPageSize();
189 DiscardableSharedMemoryHeap heap(block_size);
191 scoped_ptr<base::DiscardableSharedMemory> memory(
192 new base::DiscardableSharedMemory);
193 ASSERT_TRUE(memory->CreateAndMap(block_size));
194 scoped_ptr<DiscardableSharedMemoryHeap::Span> span =
195 heap.Grow(memory.Pass(), block_size, base::Bind(NullTask));
197 // Free lists should be empty.
198 EXPECT_EQ(0u, heap.GetSizeOfFreeLists());
200 heap.ReleaseFreeMemory();
202 // Size should still match |block_size|.
203 EXPECT_EQ(block_size, heap.GetSize());
205 heap.MergeIntoFreeLists(span.Pass());
206 heap.ReleaseFreeMemory();
208 // Memory should have been released.
209 EXPECT_EQ(0u, heap.GetSize());
210 EXPECT_EQ(0u, heap.GetSizeOfFreeLists());
213 TEST(DiscardableSharedMemoryHeapTest, ReleasePurgedMemory) {
214 size_t block_size = base::GetPageSize();
215 DiscardableSharedMemoryHeap heap(block_size);
217 scoped_ptr<base::DiscardableSharedMemory> memory(
218 new base::DiscardableSharedMemory);
219 ASSERT_TRUE(memory->CreateAndMap(block_size));
220 scoped_ptr<DiscardableSharedMemoryHeap::Span> span =
221 heap.Grow(memory.Pass(), block_size, base::Bind(NullTask));
223 // Unlock memory so it can be purged.
224 span->shared_memory()->Unlock(0, 0);
226 // Purge and release shared memory.
227 bool rv = span->shared_memory()->Purge(base::Time::Now());
228 EXPECT_TRUE(rv);
229 heap.ReleasePurgedMemory();
231 // Shared memory backing for |span| should be gone.
232 EXPECT_FALSE(span->shared_memory());
234 // Size should be 0.
235 EXPECT_EQ(0u, heap.GetSize());
238 TEST(DiscardableSharedMemoryHeapTest, Slack) {
239 size_t block_size = base::GetPageSize();
240 DiscardableSharedMemoryHeap heap(block_size);
242 const size_t kBlocks = 6;
243 size_t memory_size = block_size * kBlocks;
245 scoped_ptr<base::DiscardableSharedMemory> memory(
246 new base::DiscardableSharedMemory);
247 ASSERT_TRUE(memory->CreateAndMap(memory_size));
248 heap.MergeIntoFreeLists(
249 heap.Grow(memory.Pass(), memory_size, base::Bind(NullTask)).Pass());
251 // No free span that is less or equal to 3 + 1.
252 EXPECT_FALSE(heap.SearchFreeLists(3, 1));
254 // No free span that is less or equal to 3 + 2.
255 EXPECT_FALSE(heap.SearchFreeLists(3, 2));
257 // No free span that is less or equal to 1 + 4.
258 EXPECT_FALSE(heap.SearchFreeLists(1, 4));
260 scoped_ptr<DiscardableSharedMemoryHeap::Span> span =
261 heap.SearchFreeLists(1, 5);
262 EXPECT_TRUE(span);
264 heap.MergeIntoFreeLists(span.Pass());
267 void OnDeleted(bool* deleted) {
268 *deleted = true;
271 TEST(DiscardableSharedMemoryHeapTest, DeletedCallback) {
272 size_t block_size = base::GetPageSize();
273 DiscardableSharedMemoryHeap heap(block_size);
275 scoped_ptr<base::DiscardableSharedMemory> memory(
276 new base::DiscardableSharedMemory);
277 ASSERT_TRUE(memory->CreateAndMap(block_size));
278 bool deleted = false;
279 scoped_ptr<DiscardableSharedMemoryHeap::Span> span =
280 heap.Grow(memory.Pass(), block_size,
281 base::Bind(OnDeleted, base::Unretained(&deleted)));
283 heap.MergeIntoFreeLists(span.Pass());
284 heap.ReleaseFreeMemory();
286 EXPECT_TRUE(deleted);
289 } // namespace
290 } // namespace content