Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / client / fenced_allocator_test.cc
1 // Copyright (c) 2012 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 // This file contains the tests for the FencedAllocator class.
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/memory/aligned_memory.h"
10 #include "base/message_loop/message_loop.h"
11 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
12 #include "gpu/command_buffer/client/fenced_allocator.h"
13 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
14 #include "gpu/command_buffer/service/command_buffer_service.h"
15 #include "gpu/command_buffer/service/gpu_scheduler.h"
16 #include "gpu/command_buffer/service/mocks.h"
17 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 #if defined(OS_MACOSX)
21 #include "base/mac/scoped_nsautorelease_pool.h"
22 #endif
23
24 namespace gpu {
25
26 using testing::Return;
27 using testing::Mock;
28 using testing::Truly;
29 using testing::Sequence;
30 using testing::DoAll;
31 using testing::Invoke;
32 using testing::_;
33
34 class BaseFencedAllocatorTest : public testing::Test {
35  protected:
36   static const unsigned int kBufferSize = 1024;
37   static const int kAllocAlignment = 16;
38
39   virtual void SetUp() {
40     api_mock_.reset(new AsyncAPIMock);
41     // ignore noops in the mock - we don't want to inspect the internals of the
42     // helper.
43     EXPECT_CALL(*api_mock_, DoCommand(cmd::kNoop, 0, _))
44         .WillRepeatedly(Return(error::kNoError));
45     // Forward the SetToken calls to the engine
46     EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _))
47         .WillRepeatedly(DoAll(Invoke(api_mock_.get(), &AsyncAPIMock::SetToken),
48                               Return(error::kNoError)));
49
50     {
51       TransferBufferManager* manager = new TransferBufferManager();
52       transfer_buffer_manager_.reset(manager);
53       EXPECT_TRUE(manager->Initialize());
54     }
55     command_buffer_.reset(
56         new CommandBufferService(transfer_buffer_manager_.get()));
57     EXPECT_TRUE(command_buffer_->Initialize());
58
59     gpu_scheduler_.reset(new GpuScheduler(
60         command_buffer_.get(), api_mock_.get(), NULL));
61     command_buffer_->SetPutOffsetChangeCallback(base::Bind(
62         &GpuScheduler::PutChanged, base::Unretained(gpu_scheduler_.get())));
63     command_buffer_->SetGetBufferChangeCallback(base::Bind(
64         &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get())));
65
66     api_mock_->set_engine(gpu_scheduler_.get());
67
68     helper_.reset(new CommandBufferHelper(command_buffer_.get()));
69     helper_->Initialize(kBufferSize);
70   }
71
72   int32 GetToken() {
73     return command_buffer_->GetState().token;
74   }
75
76 #if defined(OS_MACOSX)
77   base::mac::ScopedNSAutoreleasePool autorelease_pool_;
78 #endif
79   base::MessageLoop message_loop_;
80   scoped_ptr<AsyncAPIMock> api_mock_;
81   scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_;
82   scoped_ptr<CommandBufferService> command_buffer_;
83   scoped_ptr<GpuScheduler> gpu_scheduler_;
84   scoped_ptr<CommandBufferHelper> helper_;
85 };
86
87 #ifndef _MSC_VER
88 const unsigned int BaseFencedAllocatorTest::kBufferSize;
89 #endif
90
91 // Test fixture for FencedAllocator test - Creates a FencedAllocator, using a
92 // CommandBufferHelper with a mock AsyncAPIInterface for its interface (calling
93 // it directly, not through the RPC mechanism), making sure Noops are ignored
94 // and SetToken are properly forwarded to the engine.
95 class FencedAllocatorTest : public BaseFencedAllocatorTest {
96  protected:
97   virtual void SetUp() {
98     BaseFencedAllocatorTest::SetUp();
99     allocator_.reset(new FencedAllocator(kBufferSize, helper_.get()));
100   }
101
102   virtual void TearDown() {
103     // If the GpuScheduler posts any tasks, this forces them to run.
104     base::MessageLoop::current()->RunUntilIdle();
105
106     EXPECT_TRUE(allocator_->CheckConsistency());
107
108     BaseFencedAllocatorTest::TearDown();
109   }
110
111   scoped_ptr<FencedAllocator> allocator_;
112 };
113
114 // Checks basic alloc and free.
115 TEST_F(FencedAllocatorTest, TestBasic) {
116   allocator_->CheckConsistency();
117   EXPECT_FALSE(allocator_->InUse());
118
119   const unsigned int kSize = 16;
120   FencedAllocator::Offset offset = allocator_->Alloc(kSize);
121   EXPECT_TRUE(allocator_->InUse());
122   EXPECT_NE(FencedAllocator::kInvalidOffset, offset);
123   EXPECT_GE(kBufferSize, offset+kSize);
124   EXPECT_TRUE(allocator_->CheckConsistency());
125
126   allocator_->Free(offset);
127   EXPECT_FALSE(allocator_->InUse());
128   EXPECT_TRUE(allocator_->CheckConsistency());
129 }
130
131 // Test alloc 0 fails.
132 TEST_F(FencedAllocatorTest, TestAllocZero) {
133   FencedAllocator::Offset offset = allocator_->Alloc(0);
134   EXPECT_EQ(FencedAllocator::kInvalidOffset, offset);
135   EXPECT_FALSE(allocator_->InUse());
136   EXPECT_TRUE(allocator_->CheckConsistency());
137 }
138
139 // Checks out-of-memory condition.
140 TEST_F(FencedAllocatorTest, TestOutOfMemory) {
141   EXPECT_TRUE(allocator_->CheckConsistency());
142
143   const unsigned int kSize = 16;
144   const unsigned int kAllocCount = kBufferSize / kSize;
145   CHECK(kAllocCount * kSize == kBufferSize);
146
147   // Allocate several buffers to fill in the memory.
148   FencedAllocator::Offset offsets[kAllocCount];
149   for (unsigned int i = 0; i < kAllocCount; ++i) {
150     offsets[i] = allocator_->Alloc(kSize);
151     EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[i]);
152     EXPECT_GE(kBufferSize, offsets[i]+kSize);
153     EXPECT_TRUE(allocator_->CheckConsistency());
154   }
155
156   // This allocation should fail.
157   FencedAllocator::Offset offset_failed = allocator_->Alloc(kSize);
158   EXPECT_EQ(FencedAllocator::kInvalidOffset, offset_failed);
159   EXPECT_TRUE(allocator_->CheckConsistency());
160
161   // Free one successful allocation, reallocate with half the size
162   allocator_->Free(offsets[0]);
163   EXPECT_TRUE(allocator_->CheckConsistency());
164   offsets[0] = allocator_->Alloc(kSize/2);
165   EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[0]);
166   EXPECT_GE(kBufferSize, offsets[0]+kSize);
167   EXPECT_TRUE(allocator_->CheckConsistency());
168
169   // This allocation should fail as well.
170   offset_failed = allocator_->Alloc(kSize);
171   EXPECT_EQ(FencedAllocator::kInvalidOffset, offset_failed);
172   EXPECT_TRUE(allocator_->CheckConsistency());
173
174   // Free up everything.
175   for (unsigned int i = 0; i < kAllocCount; ++i) {
176     allocator_->Free(offsets[i]);
177     EXPECT_TRUE(allocator_->CheckConsistency());
178   }
179 }
180
181 // Checks the free-pending-token mechanism.
182 TEST_F(FencedAllocatorTest, TestFreePendingToken) {
183   EXPECT_TRUE(allocator_->CheckConsistency());
184
185   const unsigned int kSize = 16;
186   const unsigned int kAllocCount = kBufferSize / kSize;
187   CHECK(kAllocCount * kSize == kBufferSize);
188
189   // Allocate several buffers to fill in the memory.
190   FencedAllocator::Offset offsets[kAllocCount];
191   for (unsigned int i = 0; i < kAllocCount; ++i) {
192     offsets[i] = allocator_->Alloc(kSize);
193     EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[i]);
194     EXPECT_GE(kBufferSize, offsets[i]+kSize);
195     EXPECT_TRUE(allocator_->CheckConsistency());
196   }
197
198   // This allocation should fail.
199   FencedAllocator::Offset offset_failed = allocator_->Alloc(kSize);
200   EXPECT_EQ(FencedAllocator::kInvalidOffset, offset_failed);
201   EXPECT_TRUE(allocator_->CheckConsistency());
202
203   // Free one successful allocation, pending fence.
204   int32 token = helper_.get()->InsertToken();
205   allocator_->FreePendingToken(offsets[0], token);
206   EXPECT_TRUE(allocator_->CheckConsistency());
207
208   // The way we hooked up the helper and engine, it won't process commands
209   // until it has to wait for something. Which means the token shouldn't have
210   // passed yet at this point.
211   EXPECT_GT(token, GetToken());
212
213   // This allocation will need to reclaim the space freed above, so that should
214   // process the commands until the token is passed.
215   offsets[0] = allocator_->Alloc(kSize);
216   EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[0]);
217   EXPECT_GE(kBufferSize, offsets[0]+kSize);
218   EXPECT_TRUE(allocator_->CheckConsistency());
219   // Check that the token has indeed passed.
220   EXPECT_LE(token, GetToken());
221
222   // Free up everything.
223   for (unsigned int i = 0; i < kAllocCount; ++i) {
224     allocator_->Free(offsets[i]);
225     EXPECT_TRUE(allocator_->CheckConsistency());
226   }
227 }
228
229 // Checks the free-pending-token mechanism using FreeUnused
230 TEST_F(FencedAllocatorTest, FreeUnused) {
231   EXPECT_TRUE(allocator_->CheckConsistency());
232
233   const unsigned int kSize = 16;
234   const unsigned int kAllocCount = kBufferSize / kSize;
235   CHECK(kAllocCount * kSize == kBufferSize);
236
237   // Allocate several buffers to fill in the memory.
238   FencedAllocator::Offset offsets[kAllocCount];
239   for (unsigned int i = 0; i < kAllocCount; ++i) {
240     offsets[i] = allocator_->Alloc(kSize);
241     EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[i]);
242     EXPECT_GE(kBufferSize, offsets[i]+kSize);
243     EXPECT_TRUE(allocator_->CheckConsistency());
244   }
245   EXPECT_TRUE(allocator_->InUse());
246
247   // No memory should be available.
248   EXPECT_EQ(0u, allocator_->GetLargestFreeSize());
249
250   // Free one successful allocation, pending fence.
251   int32 token = helper_.get()->InsertToken();
252   allocator_->FreePendingToken(offsets[0], token);
253   EXPECT_TRUE(allocator_->CheckConsistency());
254
255   // Force the command buffer to process the token.
256   helper_->Finish();
257
258   // Tell the allocator to update what's available based on the current token.
259   allocator_->FreeUnused();
260
261   // Check that the new largest free size takes into account the unused block.
262   EXPECT_EQ(kSize, allocator_->GetLargestFreeSize());
263
264   // Free two more.
265   token = helper_.get()->InsertToken();
266   allocator_->FreePendingToken(offsets[1], token);
267   token = helper_.get()->InsertToken();
268   allocator_->FreePendingToken(offsets[2], token);
269   EXPECT_TRUE(allocator_->CheckConsistency());
270
271   // Check that nothing has changed.
272   EXPECT_EQ(kSize, allocator_->GetLargestFreeSize());
273
274   // Force the command buffer to process the token.
275   helper_->Finish();
276
277   // Tell the allocator to update what's available based on the current token.
278   allocator_->FreeUnused();
279
280   // Check that the new largest free size takes into account the unused blocks.
281   EXPECT_EQ(kSize * 3, allocator_->GetLargestFreeSize());
282   EXPECT_TRUE(allocator_->InUse());
283
284   // Free up everything.
285   for (unsigned int i = 3; i < kAllocCount; ++i) {
286     allocator_->Free(offsets[i]);
287     EXPECT_TRUE(allocator_->CheckConsistency());
288   }
289   EXPECT_FALSE(allocator_->InUse());
290 }
291
292 // Tests GetLargestFreeSize
293 TEST_F(FencedAllocatorTest, TestGetLargestFreeSize) {
294   EXPECT_TRUE(allocator_->CheckConsistency());
295   EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSize());
296
297   FencedAllocator::Offset offset = allocator_->Alloc(kBufferSize);
298   ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
299   EXPECT_EQ(0u, allocator_->GetLargestFreeSize());
300   allocator_->Free(offset);
301   EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSize());
302
303   const unsigned int kSize = 16;
304   offset = allocator_->Alloc(kSize);
305   ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
306   // The following checks that the buffer is allocated "smartly" - which is
307   // dependent on the implementation. But both first-fit or best-fit would
308   // ensure that.
309   EXPECT_EQ(kBufferSize - kSize, allocator_->GetLargestFreeSize());
310
311   // Allocate 2 more buffers (now 3), and then free the first two. This is to
312   // ensure a hole. Note that this is dependent on the first-fit current
313   // implementation.
314   FencedAllocator::Offset offset1 = allocator_->Alloc(kSize);
315   ASSERT_NE(FencedAllocator::kInvalidOffset, offset1);
316   FencedAllocator::Offset offset2 = allocator_->Alloc(kSize);
317   ASSERT_NE(FencedAllocator::kInvalidOffset, offset2);
318   allocator_->Free(offset);
319   allocator_->Free(offset1);
320   EXPECT_EQ(kBufferSize - 3 * kSize, allocator_->GetLargestFreeSize());
321
322   offset = allocator_->Alloc(kBufferSize - 3 * kSize);
323   ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
324   EXPECT_EQ(2 * kSize, allocator_->GetLargestFreeSize());
325
326   offset1 = allocator_->Alloc(2 * kSize);
327   ASSERT_NE(FencedAllocator::kInvalidOffset, offset1);
328   EXPECT_EQ(0u, allocator_->GetLargestFreeSize());
329
330   allocator_->Free(offset);
331   allocator_->Free(offset1);
332   allocator_->Free(offset2);
333 }
334
335 // Tests GetLargestFreeOrPendingSize
336 TEST_F(FencedAllocatorTest, TestGetLargestFreeOrPendingSize) {
337   EXPECT_TRUE(allocator_->CheckConsistency());
338   EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
339
340   FencedAllocator::Offset offset = allocator_->Alloc(kBufferSize);
341   ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
342   EXPECT_EQ(0u, allocator_->GetLargestFreeOrPendingSize());
343   allocator_->Free(offset);
344   EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
345
346   const unsigned int kSize = 16;
347   offset = allocator_->Alloc(kSize);
348   ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
349   // The following checks that the buffer is allocates "smartly" - which is
350   // dependent on the implementation. But both first-fit or best-fit would
351   // ensure that.
352   EXPECT_EQ(kBufferSize - kSize, allocator_->GetLargestFreeOrPendingSize());
353
354   // Allocate 2 more buffers (now 3), and then free the first two. This is to
355   // ensure a hole. Note that this is dependent on the first-fit current
356   // implementation.
357   FencedAllocator::Offset offset1 = allocator_->Alloc(kSize);
358   ASSERT_NE(FencedAllocator::kInvalidOffset, offset1);
359   FencedAllocator::Offset offset2 = allocator_->Alloc(kSize);
360   ASSERT_NE(FencedAllocator::kInvalidOffset, offset2);
361   allocator_->Free(offset);
362   allocator_->Free(offset1);
363   EXPECT_EQ(kBufferSize - 3 * kSize,
364             allocator_->GetLargestFreeOrPendingSize());
365
366   // Free the last one, pending a token.
367   int32 token = helper_.get()->InsertToken();
368   allocator_->FreePendingToken(offset2, token);
369
370   // Now all the buffers have been freed...
371   EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
372   // .. but one is still waiting for the token.
373   EXPECT_EQ(kBufferSize - 3 * kSize,
374             allocator_->GetLargestFreeSize());
375
376   // The way we hooked up the helper and engine, it won't process commands
377   // until it has to wait for something. Which means the token shouldn't have
378   // passed yet at this point.
379   EXPECT_GT(token, GetToken());
380   // This allocation will need to reclaim the space freed above, so that should
381   // process the commands until the token is passed, but it will succeed.
382   offset = allocator_->Alloc(kBufferSize);
383   ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
384   // Check that the token has indeed passed.
385   EXPECT_LE(token, GetToken());
386   allocator_->Free(offset);
387
388   // Everything now has been freed...
389   EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
390   // ... for real.
391   EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSize());
392 }
393
394 // Test fixture for FencedAllocatorWrapper test - Creates a
395 // FencedAllocatorWrapper, using a CommandBufferHelper with a mock
396 // AsyncAPIInterface for its interface (calling it directly, not through the
397 // RPC mechanism), making sure Noops are ignored and SetToken are properly
398 // forwarded to the engine.
399 class FencedAllocatorWrapperTest : public BaseFencedAllocatorTest {
400  protected:
401   virtual void SetUp() {
402     BaseFencedAllocatorTest::SetUp();
403
404     // Though allocating this buffer isn't strictly necessary, it makes
405     // allocations point to valid addresses, so they could be used for
406     // something.
407     buffer_.reset(static_cast<char*>(base::AlignedAlloc(
408         kBufferSize, kAllocAlignment)));
409     allocator_.reset(new FencedAllocatorWrapper(kBufferSize, helper_.get(),
410                                                 buffer_.get()));
411   }
412
413   virtual void TearDown() {
414     // If the GpuScheduler posts any tasks, this forces them to run.
415     base::MessageLoop::current()->RunUntilIdle();
416
417     EXPECT_TRUE(allocator_->CheckConsistency());
418
419     BaseFencedAllocatorTest::TearDown();
420   }
421
422   scoped_ptr<FencedAllocatorWrapper> allocator_;
423   scoped_ptr<char, base::AlignedFreeDeleter> buffer_;
424 };
425
426 // Checks basic alloc and free.
427 TEST_F(FencedAllocatorWrapperTest, TestBasic) {
428   allocator_->CheckConsistency();
429
430   const unsigned int kSize = 16;
431   void *pointer = allocator_->Alloc(kSize);
432   ASSERT_TRUE(pointer);
433   EXPECT_LE(buffer_.get(), static_cast<char *>(pointer));
434   EXPECT_GE(kBufferSize, static_cast<char *>(pointer) - buffer_.get() + kSize);
435   EXPECT_TRUE(allocator_->CheckConsistency());
436
437   allocator_->Free(pointer);
438   EXPECT_TRUE(allocator_->CheckConsistency());
439
440   char *pointer_char = allocator_->AllocTyped<char>(kSize);
441   ASSERT_TRUE(pointer_char);
442   EXPECT_LE(buffer_.get(), pointer_char);
443   EXPECT_GE(buffer_.get() + kBufferSize, pointer_char + kSize);
444   allocator_->Free(pointer_char);
445   EXPECT_TRUE(allocator_->CheckConsistency());
446
447   unsigned int *pointer_uint = allocator_->AllocTyped<unsigned int>(kSize);
448   ASSERT_TRUE(pointer_uint);
449   EXPECT_LE(buffer_.get(), reinterpret_cast<char *>(pointer_uint));
450   EXPECT_GE(buffer_.get() + kBufferSize,
451             reinterpret_cast<char *>(pointer_uint + kSize));
452
453   // Check that it did allocate kSize * sizeof(unsigned int). We can't tell
454   // directly, except from the remaining size.
455   EXPECT_EQ(kBufferSize - kSize * sizeof(*pointer_uint),
456             allocator_->GetLargestFreeSize());
457   allocator_->Free(pointer_uint);
458 }
459
460 // Test alloc 0 fails.
461 TEST_F(FencedAllocatorWrapperTest, TestAllocZero) {
462   allocator_->CheckConsistency();
463
464   void *pointer = allocator_->Alloc(0);
465   ASSERT_FALSE(pointer);
466   EXPECT_TRUE(allocator_->CheckConsistency());
467 }
468
469 // Checks that allocation offsets are aligned to multiples of 16 bytes.
470 TEST_F(FencedAllocatorWrapperTest, TestAlignment) {
471   allocator_->CheckConsistency();
472
473   const unsigned int kSize1 = 75;
474   void *pointer1 = allocator_->Alloc(kSize1);
475   ASSERT_TRUE(pointer1);
476   EXPECT_EQ(reinterpret_cast<intptr_t>(pointer1) & (kAllocAlignment - 1), 0);
477   EXPECT_TRUE(allocator_->CheckConsistency());
478
479   const unsigned int kSize2 = 43;
480   void *pointer2 = allocator_->Alloc(kSize2);
481   ASSERT_TRUE(pointer2);
482   EXPECT_EQ(reinterpret_cast<intptr_t>(pointer2) & (kAllocAlignment - 1), 0);
483   EXPECT_TRUE(allocator_->CheckConsistency());
484
485   allocator_->Free(pointer2);
486   EXPECT_TRUE(allocator_->CheckConsistency());
487
488   allocator_->Free(pointer1);
489   EXPECT_TRUE(allocator_->CheckConsistency());
490 }
491
492 // Checks out-of-memory condition.
493 TEST_F(FencedAllocatorWrapperTest, TestOutOfMemory) {
494   allocator_->CheckConsistency();
495
496   const unsigned int kSize = 16;
497   const unsigned int kAllocCount = kBufferSize / kSize;
498   CHECK(kAllocCount * kSize == kBufferSize);
499
500   // Allocate several buffers to fill in the memory.
501   void *pointers[kAllocCount];
502   for (unsigned int i = 0; i < kAllocCount; ++i) {
503     pointers[i] = allocator_->Alloc(kSize);
504     EXPECT_TRUE(pointers[i]);
505     EXPECT_TRUE(allocator_->CheckConsistency());
506   }
507
508   // This allocation should fail.
509   void *pointer_failed = allocator_->Alloc(kSize);
510   EXPECT_FALSE(pointer_failed);
511   EXPECT_TRUE(allocator_->CheckConsistency());
512
513   // Free one successful allocation, reallocate with half the size
514   allocator_->Free(pointers[0]);
515   EXPECT_TRUE(allocator_->CheckConsistency());
516   pointers[0] = allocator_->Alloc(kSize/2);
517   EXPECT_TRUE(pointers[0]);
518   EXPECT_TRUE(allocator_->CheckConsistency());
519
520   // This allocation should fail as well.
521   pointer_failed = allocator_->Alloc(kSize);
522   EXPECT_FALSE(pointer_failed);
523   EXPECT_TRUE(allocator_->CheckConsistency());
524
525   // Free up everything.
526   for (unsigned int i = 0; i < kAllocCount; ++i) {
527     allocator_->Free(pointers[i]);
528     EXPECT_TRUE(allocator_->CheckConsistency());
529   }
530 }
531
532 // Checks the free-pending-token mechanism.
533 TEST_F(FencedAllocatorWrapperTest, TestFreePendingToken) {
534   allocator_->CheckConsistency();
535
536   const unsigned int kSize = 16;
537   const unsigned int kAllocCount = kBufferSize / kSize;
538   CHECK(kAllocCount * kSize == kBufferSize);
539
540   // Allocate several buffers to fill in the memory.
541   void *pointers[kAllocCount];
542   for (unsigned int i = 0; i < kAllocCount; ++i) {
543     pointers[i] = allocator_->Alloc(kSize);
544     EXPECT_TRUE(pointers[i]);
545     EXPECT_TRUE(allocator_->CheckConsistency());
546   }
547
548   // This allocation should fail.
549   void *pointer_failed = allocator_->Alloc(kSize);
550   EXPECT_FALSE(pointer_failed);
551   EXPECT_TRUE(allocator_->CheckConsistency());
552
553   // Free one successful allocation, pending fence.
554   int32 token = helper_.get()->InsertToken();
555   allocator_->FreePendingToken(pointers[0], token);
556   EXPECT_TRUE(allocator_->CheckConsistency());
557
558   // The way we hooked up the helper and engine, it won't process commands
559   // until it has to wait for something. Which means the token shouldn't have
560   // passed yet at this point.
561   EXPECT_GT(token, GetToken());
562
563   // This allocation will need to reclaim the space freed above, so that should
564   // process the commands until the token is passed.
565   pointers[0] = allocator_->Alloc(kSize);
566   EXPECT_TRUE(pointers[0]);
567   EXPECT_TRUE(allocator_->CheckConsistency());
568   // Check that the token has indeed passed.
569   EXPECT_LE(token, GetToken());
570
571   // Free up everything.
572   for (unsigned int i = 0; i < kAllocCount; ++i) {
573     allocator_->Free(pointers[i]);
574     EXPECT_TRUE(allocator_->CheckConsistency());
575   }
576 }
577
578 }  // namespace gpu