Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / common / discardable_shared_memory_heap_unittest.cc
blob20594ecf937368875ad3263928c6cadac951fe00
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;
33 int next_discardable_shared_memory_id = 0;
35 scoped_ptr<base::DiscardableSharedMemory> memory(
36 new base::DiscardableSharedMemory);
37 ASSERT_TRUE(memory->CreateAndMap(memory_size));
39 // Create new span for memory.
40 scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(
41 heap.Grow(memory.Pass(), memory_size, next_discardable_shared_memory_id++,
42 base::Bind(NullTask)));
44 // Size should match |memory_size|.
45 EXPECT_EQ(memory_size, heap.GetSize());
47 // Size of free lists should still be 0.
48 EXPECT_EQ(0u, heap.GetSizeOfFreeLists());
50 // Free list should still be empty as |new_span| is currently in use.
51 EXPECT_FALSE(heap.SearchFreeLists(1, 0));
53 // Done using |new_span|. Merge it into the free lists.
54 heap.MergeIntoFreeLists(new_span.Pass());
56 // Size of free lists should now match |memory_size|.
57 EXPECT_EQ(memory_size, heap.GetSizeOfFreeLists());
59 // Free lists should not contain a span that is larger than kBlocks.
60 EXPECT_FALSE(heap.SearchFreeLists(kBlocks + 1, 0));
62 // Free lists should contain a span that satisfies the request for kBlocks.
63 scoped_ptr<DiscardableSharedMemoryHeap::Span> span =
64 heap.SearchFreeLists(kBlocks, 0);
65 ASSERT_TRUE(span);
67 // Free lists should be empty again.
68 EXPECT_FALSE(heap.SearchFreeLists(1, 0));
70 // Merge it into the free lists again.
71 heap.MergeIntoFreeLists(span.Pass());
74 TEST(DiscardableSharedMemoryHeapTest, SplitAndMerge) {
75 size_t block_size = base::GetPageSize();
76 DiscardableSharedMemoryHeap heap(block_size);
78 const size_t kBlocks = 6;
79 size_t memory_size = block_size * kBlocks;
80 int next_discardable_shared_memory_id = 0;
82 scoped_ptr<base::DiscardableSharedMemory> memory(
83 new base::DiscardableSharedMemory);
84 ASSERT_TRUE(memory->CreateAndMap(memory_size));
85 scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(
86 heap.Grow(memory.Pass(), memory_size, next_discardable_shared_memory_id++,
87 base::Bind(NullTask)));
89 // Split span into two.
90 scoped_ptr<DiscardableSharedMemoryHeap::Span> leftover =
91 heap.Split(new_span.get(), 3);
92 ASSERT_TRUE(leftover);
94 // Merge |leftover| into free lists.
95 heap.MergeIntoFreeLists(leftover.Pass());
97 // Some of the memory is still in use.
98 EXPECT_FALSE(heap.SearchFreeLists(kBlocks, 0));
100 // Merge |span| into free lists.
101 heap.MergeIntoFreeLists(new_span.Pass());
103 // Remove a 2 page span from free lists.
104 scoped_ptr<DiscardableSharedMemoryHeap::Span> span1 =
105 heap.SearchFreeLists(2, kBlocks);
106 ASSERT_TRUE(span1);
108 // Remove another 2 page span from free lists.
109 scoped_ptr<DiscardableSharedMemoryHeap::Span> span2 =
110 heap.SearchFreeLists(2, kBlocks);
111 ASSERT_TRUE(span2);
113 // Merge |span1| back into free lists.
114 heap.MergeIntoFreeLists(span1.Pass());
116 // Some of the memory is still in use.
117 EXPECT_FALSE(heap.SearchFreeLists(kBlocks, 0));
119 // Merge |span2| back into free lists.
120 heap.MergeIntoFreeLists(span2.Pass());
122 // All memory has been returned to the free lists.
123 scoped_ptr<DiscardableSharedMemoryHeap::Span> large_span =
124 heap.SearchFreeLists(kBlocks, 0);
125 ASSERT_TRUE(large_span);
127 // Merge it into the free lists again.
128 heap.MergeIntoFreeLists(large_span.Pass());
131 TEST(DiscardableSharedMemoryHeapTest, MergeSingleBlockSpan) {
132 size_t block_size = base::GetPageSize();
133 DiscardableSharedMemoryHeap heap(block_size);
135 const size_t kBlocks = 6;
136 size_t memory_size = block_size * kBlocks;
137 int next_discardable_shared_memory_id = 0;
139 scoped_ptr<base::DiscardableSharedMemory> memory(
140 new base::DiscardableSharedMemory);
141 ASSERT_TRUE(memory->CreateAndMap(memory_size));
142 scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(
143 heap.Grow(memory.Pass(), memory_size, next_discardable_shared_memory_id++,
144 base::Bind(NullTask)));
146 // Split span into two.
147 scoped_ptr<DiscardableSharedMemoryHeap::Span> leftover =
148 heap.Split(new_span.get(), 5);
149 ASSERT_TRUE(leftover);
151 // Merge |new_span| into free lists.
152 heap.MergeIntoFreeLists(new_span.Pass());
154 // Merge |leftover| into free lists.
155 heap.MergeIntoFreeLists(leftover.Pass());
158 TEST(DiscardableSharedMemoryHeapTest, Grow) {
159 size_t block_size = base::GetPageSize();
160 DiscardableSharedMemoryHeap heap(block_size);
161 int next_discardable_shared_memory_id = 0;
163 scoped_ptr<base::DiscardableSharedMemory> memory1(
164 new base::DiscardableSharedMemory);
165 ASSERT_TRUE(memory1->CreateAndMap(block_size));
166 heap.MergeIntoFreeLists(heap.Grow(memory1.Pass(), block_size,
167 next_discardable_shared_memory_id++,
168 base::Bind(NullTask)).Pass());
170 // Remove a span from free lists.
171 scoped_ptr<DiscardableSharedMemoryHeap::Span> span1 =
172 heap.SearchFreeLists(1, 0);
173 EXPECT_TRUE(span1);
175 // No more memory available.
176 EXPECT_FALSE(heap.SearchFreeLists(1, 0));
178 // Grow free lists using new memory.
179 scoped_ptr<base::DiscardableSharedMemory> memory2(
180 new base::DiscardableSharedMemory);
181 ASSERT_TRUE(memory2->CreateAndMap(block_size));
182 heap.MergeIntoFreeLists(heap.Grow(memory2.Pass(), block_size,
183 next_discardable_shared_memory_id++,
184 base::Bind(NullTask)).Pass());
186 // Memory should now be available.
187 scoped_ptr<DiscardableSharedMemoryHeap::Span> span2 =
188 heap.SearchFreeLists(1, 0);
189 EXPECT_TRUE(span2);
191 // Merge spans into the free lists again.
192 heap.MergeIntoFreeLists(span1.Pass());
193 heap.MergeIntoFreeLists(span2.Pass());
196 TEST(DiscardableSharedMemoryHeapTest, ReleaseFreeMemory) {
197 size_t block_size = base::GetPageSize();
198 DiscardableSharedMemoryHeap heap(block_size);
199 int next_discardable_shared_memory_id = 0;
201 scoped_ptr<base::DiscardableSharedMemory> memory(
202 new base::DiscardableSharedMemory);
203 ASSERT_TRUE(memory->CreateAndMap(block_size));
204 scoped_ptr<DiscardableSharedMemoryHeap::Span> span =
205 heap.Grow(memory.Pass(), block_size, next_discardable_shared_memory_id++,
206 base::Bind(NullTask));
208 // Free lists should be empty.
209 EXPECT_EQ(0u, heap.GetSizeOfFreeLists());
211 heap.ReleaseFreeMemory();
213 // Size should still match |block_size|.
214 EXPECT_EQ(block_size, heap.GetSize());
216 heap.MergeIntoFreeLists(span.Pass());
217 heap.ReleaseFreeMemory();
219 // Memory should have been released.
220 EXPECT_EQ(0u, heap.GetSize());
221 EXPECT_EQ(0u, heap.GetSizeOfFreeLists());
224 TEST(DiscardableSharedMemoryHeapTest, ReleasePurgedMemory) {
225 size_t block_size = base::GetPageSize();
226 DiscardableSharedMemoryHeap heap(block_size);
227 int next_discardable_shared_memory_id = 0;
229 scoped_ptr<base::DiscardableSharedMemory> memory(
230 new base::DiscardableSharedMemory);
231 ASSERT_TRUE(memory->CreateAndMap(block_size));
232 scoped_ptr<DiscardableSharedMemoryHeap::Span> span =
233 heap.Grow(memory.Pass(), block_size, next_discardable_shared_memory_id++,
234 base::Bind(NullTask));
236 // Unlock memory so it can be purged.
237 span->shared_memory()->Unlock(0, 0);
239 // Purge and release shared memory.
240 bool rv = span->shared_memory()->Purge(base::Time::Now());
241 EXPECT_TRUE(rv);
242 heap.ReleasePurgedMemory();
244 // Shared memory backing for |span| should be gone.
245 EXPECT_FALSE(span->shared_memory());
247 // Size should be 0.
248 EXPECT_EQ(0u, heap.GetSize());
251 TEST(DiscardableSharedMemoryHeapTest, Slack) {
252 size_t block_size = base::GetPageSize();
253 DiscardableSharedMemoryHeap heap(block_size);
255 const size_t kBlocks = 6;
256 size_t memory_size = block_size * kBlocks;
257 int next_discardable_shared_memory_id = 0;
259 scoped_ptr<base::DiscardableSharedMemory> memory(
260 new base::DiscardableSharedMemory);
261 ASSERT_TRUE(memory->CreateAndMap(memory_size));
262 heap.MergeIntoFreeLists(heap.Grow(memory.Pass(), memory_size,
263 next_discardable_shared_memory_id++,
264 base::Bind(NullTask)).Pass());
266 // No free span that is less or equal to 3 + 1.
267 EXPECT_FALSE(heap.SearchFreeLists(3, 1));
269 // No free span that is less or equal to 3 + 2.
270 EXPECT_FALSE(heap.SearchFreeLists(3, 2));
272 // No free span that is less or equal to 1 + 4.
273 EXPECT_FALSE(heap.SearchFreeLists(1, 4));
275 scoped_ptr<DiscardableSharedMemoryHeap::Span> span =
276 heap.SearchFreeLists(1, 5);
277 EXPECT_TRUE(span);
279 heap.MergeIntoFreeLists(span.Pass());
282 void OnDeleted(bool* deleted) {
283 *deleted = true;
286 TEST(DiscardableSharedMemoryHeapTest, DeletedCallback) {
287 size_t block_size = base::GetPageSize();
288 DiscardableSharedMemoryHeap heap(block_size);
289 int next_discardable_shared_memory_id = 0;
291 scoped_ptr<base::DiscardableSharedMemory> memory(
292 new base::DiscardableSharedMemory);
293 ASSERT_TRUE(memory->CreateAndMap(block_size));
294 bool deleted = false;
295 scoped_ptr<DiscardableSharedMemoryHeap::Span> span =
296 heap.Grow(memory.Pass(), block_size, next_discardable_shared_memory_id++,
297 base::Bind(OnDeleted, base::Unretained(&deleted)));
299 heap.MergeIntoFreeLists(span.Pass());
300 heap.ReleaseFreeMemory();
302 EXPECT_TRUE(deleted);
305 TEST(DiscardableSharedMemoryHeapTest, CreateMemoryAllocatorDumpTest) {
306 size_t block_size = base::GetPageSize();
307 DiscardableSharedMemoryHeap heap(block_size);
308 int next_discardable_shared_memory_id = 0;
310 scoped_ptr<base::DiscardableSharedMemory> memory(
311 new base::DiscardableSharedMemory);
312 ASSERT_TRUE(memory->CreateAndMap(block_size));
313 scoped_ptr<DiscardableSharedMemoryHeap::Span> span =
314 heap.Grow(memory.Pass(), block_size, next_discardable_shared_memory_id++,
315 base::Bind(NullTask));
317 // Check if allocator dump is created when span exists.
318 scoped_ptr<base::trace_event::ProcessMemoryDump> pmd(
319 new base::trace_event::ProcessMemoryDump(nullptr));
320 EXPECT_TRUE(heap.CreateMemoryAllocatorDump(span.get(), "discardable/test1",
321 pmd.get()));
323 // Unlock, Purge and release shared memory.
324 span->shared_memory()->Unlock(0, 0);
325 bool rv = span->shared_memory()->Purge(base::Time::Now());
326 EXPECT_TRUE(rv);
327 heap.ReleasePurgedMemory();
329 // Check that allocator dump is created after memory is purged.
330 EXPECT_TRUE(heap.CreateMemoryAllocatorDump(span.get(), "discardable/test2",
331 pmd.get()));
334 } // namespace
335 } // namespace content