Revert "Reland c91b178b07b0d - Delete dead signin code (SigninGlobalError)"
[chromium-blink-merge.git] / gpu / command_buffer / client / ring_buffer_test.cc
blobdad9cbc368625b3c8f5b1a58782ce22e64f1b946
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.
5 // This file contains the tests for the RingBuffer class.
7 #include "gpu/command_buffer/client/ring_buffer.h"
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
12 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
13 #include "gpu/command_buffer/service/command_buffer_service.h"
14 #include "gpu/command_buffer/service/gpu_scheduler.h"
15 #include "gpu/command_buffer/service/mocks.h"
16 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 namespace gpu {
21 using testing::Return;
22 using testing::Mock;
23 using testing::Truly;
24 using testing::Sequence;
25 using testing::DoAll;
26 using testing::Invoke;
27 using testing::_;
29 class BaseRingBufferTest : public testing::Test {
30 protected:
31 static const unsigned int kBaseOffset = 128;
32 static const unsigned int kBufferSize = 1024;
33 static const unsigned int kAlignment = 4;
35 void RunPendingSetToken() {
36 for (std::vector<const void*>::iterator it = set_token_arguments_.begin();
37 it != set_token_arguments_.end();
38 ++it) {
39 api_mock_->SetToken(cmd::kSetToken, 1, *it);
41 set_token_arguments_.clear();
42 delay_set_token_ = false;
45 void SetToken(unsigned int command,
46 unsigned int arg_count,
47 const void* _args) {
48 EXPECT_EQ(static_cast<unsigned int>(cmd::kSetToken), command);
49 EXPECT_EQ(1u, arg_count);
50 if (delay_set_token_)
51 set_token_arguments_.push_back(_args);
52 else
53 api_mock_->SetToken(cmd::kSetToken, 1, _args);
56 void SetUp() override {
57 delay_set_token_ = false;
58 api_mock_.reset(new AsyncAPIMock(true));
59 // ignore noops in the mock - we don't want to inspect the internals of the
60 // helper.
61 EXPECT_CALL(*api_mock_, DoCommand(cmd::kNoop, 0, _))
62 .WillRepeatedly(Return(error::kNoError));
63 // Forward the SetToken calls to the engine
64 EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _))
65 .WillRepeatedly(DoAll(Invoke(this, &BaseRingBufferTest::SetToken),
66 Return(error::kNoError)));
69 TransferBufferManager* manager = new TransferBufferManager();
70 transfer_buffer_manager_ = manager;
71 EXPECT_TRUE(manager->Initialize());
73 command_buffer_.reset(
74 new CommandBufferService(transfer_buffer_manager_.get()));
75 EXPECT_TRUE(command_buffer_->Initialize());
77 gpu_scheduler_.reset(new GpuScheduler(
78 command_buffer_.get(), api_mock_.get(), NULL));
79 command_buffer_->SetPutOffsetChangeCallback(base::Bind(
80 &GpuScheduler::PutChanged, base::Unretained(gpu_scheduler_.get())));
81 command_buffer_->SetGetBufferChangeCallback(base::Bind(
82 &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get())));
84 api_mock_->set_engine(gpu_scheduler_.get());
86 helper_.reset(new CommandBufferHelper(command_buffer_.get()));
87 helper_->Initialize(kBufferSize);
90 int32 GetToken() {
91 return command_buffer_->GetLastState().token;
94 scoped_ptr<AsyncAPIMock> api_mock_;
95 scoped_refptr<TransferBufferManagerInterface> transfer_buffer_manager_;
96 scoped_ptr<CommandBufferService> command_buffer_;
97 scoped_ptr<GpuScheduler> gpu_scheduler_;
98 scoped_ptr<CommandBufferHelper> helper_;
99 std::vector<const void*> set_token_arguments_;
100 bool delay_set_token_;
102 scoped_ptr<int8[]> buffer_;
103 int8* buffer_start_;
106 #ifndef _MSC_VER
107 const unsigned int BaseRingBufferTest::kBaseOffset;
108 const unsigned int BaseRingBufferTest::kBufferSize;
109 #endif
111 // Test fixture for RingBuffer test - Creates a RingBuffer, using a
112 // CommandBufferHelper with a mock AsyncAPIInterface for its interface (calling
113 // it directly, not through the RPC mechanism), making sure Noops are ignored
114 // and SetToken are properly forwarded to the engine.
115 class RingBufferTest : public BaseRingBufferTest {
116 protected:
117 void SetUp() override {
118 BaseRingBufferTest::SetUp();
120 buffer_.reset(new int8[kBufferSize + kBaseOffset]);
121 buffer_start_ = buffer_.get() + kBaseOffset;
122 allocator_.reset(new RingBuffer(kAlignment, kBaseOffset, kBufferSize,
123 helper_.get(), buffer_start_));
126 void TearDown() override {
127 // If the GpuScheduler posts any tasks, this forces them to run.
128 base::MessageLoop::current()->RunUntilIdle();
130 BaseRingBufferTest::TearDown();
133 scoped_ptr<RingBuffer> allocator_;
136 // Checks basic alloc and free.
137 TEST_F(RingBufferTest, TestBasic) {
138 const unsigned int kSize = 16;
139 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
140 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSizeNoWaiting());
141 void* pointer = allocator_->Alloc(kSize);
142 EXPECT_GE(kBufferSize, allocator_->GetOffset(pointer) - kBaseOffset + kSize);
143 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
144 EXPECT_EQ(kBufferSize - kSize, allocator_->GetLargestFreeSizeNoWaiting());
145 int32 token = helper_->InsertToken();
146 allocator_->FreePendingToken(pointer, token);
149 // Checks the free-pending-token mechanism.
150 TEST_F(RingBufferTest, TestFreePendingToken) {
151 const unsigned int kSize = 16;
152 const unsigned int kAllocCount = kBufferSize / kSize;
153 CHECK(kAllocCount * kSize == kBufferSize);
155 delay_set_token_ = true;
156 // Allocate several buffers to fill in the memory.
157 int32 tokens[kAllocCount];
158 for (unsigned int ii = 0; ii < kAllocCount; ++ii) {
159 void* pointer = allocator_->Alloc(kSize);
160 EXPECT_GE(kBufferSize,
161 allocator_->GetOffset(pointer) - kBaseOffset + kSize);
162 tokens[ii] = helper_->InsertToken();
163 allocator_->FreePendingToken(pointer, tokens[ii]);
166 EXPECT_EQ(kBufferSize - (kSize * kAllocCount),
167 allocator_->GetLargestFreeSizeNoWaiting());
169 RunPendingSetToken();
171 // This allocation will need to reclaim the space freed above, so that should
172 // process the commands until a token is passed.
173 void* pointer1 = allocator_->Alloc(kSize);
174 EXPECT_EQ(kBaseOffset, allocator_->GetOffset(pointer1));
176 // Check that the token has indeed passed.
177 EXPECT_LE(tokens[0], GetToken());
179 allocator_->FreePendingToken(pointer1, helper_->InsertToken());
182 // Tests GetLargestFreeSizeNoWaiting
183 TEST_F(RingBufferTest, TestGetLargestFreeSizeNoWaiting) {
184 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSizeNoWaiting());
186 void* pointer = allocator_->Alloc(kBufferSize);
187 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
188 allocator_->FreePendingToken(pointer, helper_->InsertToken());
191 TEST_F(RingBufferTest, TestFreeBug) {
192 // The first and second allocations must not match.
193 const unsigned int kAlloc1 = 3*kAlignment;
194 const unsigned int kAlloc2 = 20;
195 void* pointer = allocator_->Alloc(kAlloc1);
196 EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting());
197 allocator_->FreePendingToken(pointer, helper_.get()->InsertToken());
198 pointer = allocator_->Alloc(kAlloc2);
199 EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2,
200 allocator_->GetLargestFreeSizeNoWaiting());
201 allocator_->FreePendingToken(pointer, helper_.get()->InsertToken());
202 pointer = allocator_->Alloc(kBufferSize);
203 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
204 allocator_->FreePendingToken(pointer, helper_.get()->InsertToken());
207 // Test that discarding a single allocation clears the block.
208 TEST_F(RingBufferTest, DiscardTest) {
209 const unsigned int kAlloc1 = 3*kAlignment;
210 void* ptr = allocator_->Alloc(kAlloc1);
211 EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting());
212 allocator_->DiscardBlock(ptr);
213 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSizeNoWaiting());
216 // Test that discarding front of the buffer effectively frees the block.
217 TEST_F(RingBufferTest, DiscardFrontTest) {
218 const unsigned int kAlloc1 = 3*kAlignment;
219 const unsigned int kAlloc2 = 2*kAlignment;
220 const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2;
221 void* ptr1 = allocator_->Alloc(kAlloc1);
222 EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting());
223 allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken());
225 void* ptr2 = allocator_->Alloc(kAlloc2);
226 EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1,
227 static_cast<uint8_t*>(ptr2));
228 EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2,
229 allocator_->GetLargestFreeSizeNoWaiting());
230 allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken());
232 void* ptr3 = allocator_->Alloc(kAlloc3);
233 EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2,
234 static_cast<uint8_t*>(ptr3));
235 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
237 // Discard first block should free it up upon GetLargestFreeSizeNoWaiting().
238 allocator_->DiscardBlock(ptr1);
239 EXPECT_EQ(kAlloc1, allocator_->GetLargestFreeSizeNoWaiting());
240 allocator_->FreePendingToken(ptr3, helper_.get()->InsertToken());
243 // Test that discarding middle of the buffer merely marks it as padding.
244 TEST_F(RingBufferTest, DiscardMiddleTest) {
245 const unsigned int kAlloc1 = 3*kAlignment;
246 const unsigned int kAlloc2 = 2*kAlignment;
247 const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2;
248 void* ptr1 = allocator_->Alloc(kAlloc1);
249 EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting());
250 allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken());
252 void* ptr2 = allocator_->Alloc(kAlloc2);
253 EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1,
254 static_cast<uint8_t*>(ptr2));
255 EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2,
256 allocator_->GetLargestFreeSizeNoWaiting());
257 allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken());
259 void* ptr3 = allocator_->Alloc(kAlloc3);
260 EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2,
261 static_cast<uint8_t*>(ptr3));
262 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
264 // Discard middle block should just set it as padding.
265 allocator_->DiscardBlock(ptr2);
266 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
267 allocator_->FreePendingToken(ptr3, helper_.get()->InsertToken());
270 // Test that discarding end of the buffer frees it for no waiting.
271 TEST_F(RingBufferTest, DiscardEndTest) {
272 const unsigned int kAlloc1 = 3*kAlignment;
273 const unsigned int kAlloc2 = 2*kAlignment;
274 const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2;
275 void* ptr1 = allocator_->Alloc(kAlloc1);
276 EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting());
277 allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken());
279 void* ptr2 = allocator_->Alloc(kAlloc2);
280 EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1,
281 static_cast<uint8_t*>(ptr2));
282 EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2,
283 allocator_->GetLargestFreeSizeNoWaiting());
284 allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken());
286 void* ptr3 = allocator_->Alloc(kAlloc3);
287 EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2,
288 static_cast<uint8_t*>(ptr3));
289 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
291 // Discard end block should discard it.
292 allocator_->DiscardBlock(ptr3);
293 EXPECT_EQ(kAlloc3, allocator_->GetLargestFreeSizeNoWaiting());
296 // Test discard end of the buffer that has looped around.
297 TEST_F(RingBufferTest, DiscardLoopedEndTest) {
298 const unsigned int kAlloc1 = 3*kAlignment;
299 const unsigned int kAlloc2 = 2*kAlignment;
300 const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2;
301 void* ptr1 = allocator_->Alloc(kAlloc1);
302 EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting());
303 allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken());
305 void* ptr2 = allocator_->Alloc(kAlloc2);
306 EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1,
307 static_cast<uint8_t*>(ptr2));
308 EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2,
309 allocator_->GetLargestFreeSizeNoWaiting());
310 allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken());
312 void* ptr3 = allocator_->Alloc(kAlloc3);
313 EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2,
314 static_cast<uint8_t*>(ptr3));
315 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
316 allocator_->FreePendingToken(ptr3, helper_.get()->InsertToken());
318 // This allocation should be at the beginning again, we need to utilize
319 // DiscardBlock here to discard the first item so that we can allocate
320 // at the beginning without the FreeOldestBlock() getting called and freeing
321 // the whole ring buffer.
322 allocator_->DiscardBlock(ptr1);
323 void* ptr4 = allocator_->Alloc(kAlloc1);
324 EXPECT_EQ(ptr1, ptr4);
325 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
327 // Discard end block should work properly still.
328 allocator_->DiscardBlock(ptr4);
329 EXPECT_EQ(kAlloc1, allocator_->GetLargestFreeSizeNoWaiting());
332 // Test discard end of the buffer that has looped around with padding.
333 TEST_F(RingBufferTest, DiscardEndWithPaddingTest) {
334 const unsigned int kAlloc1 = 3*kAlignment;
335 const unsigned int kAlloc2 = 2*kAlignment;
336 const unsigned int kPadding = kAlignment;
337 const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2 - kPadding;
338 void* ptr1 = allocator_->Alloc(kAlloc1);
339 EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting());
340 allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken());
342 void* ptr2 = allocator_->Alloc(kAlloc2);
343 EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1,
344 static_cast<uint8_t*>(ptr2));
345 EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2,
346 allocator_->GetLargestFreeSizeNoWaiting());
347 allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken());
349 void* ptr3 = allocator_->Alloc(kAlloc3);
350 EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2,
351 static_cast<uint8_t*>(ptr3));
352 EXPECT_EQ(kPadding, allocator_->GetLargestFreeSizeNoWaiting());
353 allocator_->FreePendingToken(ptr3, helper_.get()->InsertToken());
355 // Cause it to loop around with padding at the end of ptr3.
356 allocator_->DiscardBlock(ptr1);
357 void* ptr4 = allocator_->Alloc(kAlloc1);
358 EXPECT_EQ(ptr1, ptr4);
359 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
361 // Discard end block should also discard the padding.
362 allocator_->DiscardBlock(ptr4);
363 EXPECT_EQ(kAlloc1, allocator_->GetLargestFreeSizeNoWaiting());
365 // We can test that there is padding by attempting to allocate the padding.
366 void* padding = allocator_->Alloc(kPadding);
367 EXPECT_EQ(kAlloc1, allocator_->GetLargestFreeSizeNoWaiting());
368 allocator_->FreePendingToken(padding, helper_.get()->InsertToken());
371 // Test that discard will effectively remove all padding at the end.
372 TEST_F(RingBufferTest, DiscardAllPaddingFromEndTest) {
373 const unsigned int kAlloc1 = 3*kAlignment;
374 const unsigned int kAlloc2 = 2*kAlignment;
375 const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2;
376 void* ptr1 = allocator_->Alloc(kAlloc1);
377 EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting());
378 allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken());
380 void* ptr2 = allocator_->Alloc(kAlloc2);
381 EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1,
382 static_cast<uint8_t*>(ptr2));
383 EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2,
384 allocator_->GetLargestFreeSizeNoWaiting());
385 allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken());
387 void* ptr3 = allocator_->Alloc(kAlloc3);
388 EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2,
389 static_cast<uint8_t*>(ptr3));
390 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
392 // Discarding the middle allocation should turn it into padding.
393 allocator_->DiscardBlock(ptr2);
394 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
396 // Discarding the last allocation should discard the middle padding as well.
397 allocator_->DiscardBlock(ptr3);
398 EXPECT_EQ(kAlloc2 + kAlloc3, allocator_->GetLargestFreeSizeNoWaiting());
401 // Test that discard will effectively remove all padding from the beginning.
402 TEST_F(RingBufferTest, DiscardAllPaddingFromBeginningTest) {
403 const unsigned int kAlloc1 = 3*kAlignment;
404 const unsigned int kAlloc2 = 2*kAlignment;
405 const unsigned int kAlloc3 = kBufferSize - kAlloc1 - kAlloc2;
406 void* ptr1 = allocator_->Alloc(kAlloc1);
407 EXPECT_EQ(kBufferSize - kAlloc1, allocator_->GetLargestFreeSizeNoWaiting());
408 allocator_->FreePendingToken(ptr1, helper_.get()->InsertToken());
410 void* ptr2 = allocator_->Alloc(kAlloc2);
411 EXPECT_EQ(static_cast<uint8_t*>(ptr1) + kAlloc1,
412 static_cast<uint8_t*>(ptr2));
413 EXPECT_EQ(kBufferSize - kAlloc1 - kAlloc2,
414 allocator_->GetLargestFreeSizeNoWaiting());
415 allocator_->FreePendingToken(ptr2, helper_.get()->InsertToken());
417 void* ptr3 = allocator_->Alloc(kAlloc3);
418 EXPECT_EQ(static_cast<uint8_t*>(ptr2) + kAlloc2,
419 static_cast<uint8_t*>(ptr3));
420 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
421 allocator_->FreePendingToken(ptr3, helper_.get()->InsertToken());
423 // Discarding the middle allocation should turn it into padding.
424 allocator_->DiscardBlock(ptr2);
425 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting());
427 // Discarding the first allocation should discard the middle padding as well.
428 allocator_->DiscardBlock(ptr1);
429 EXPECT_EQ(kAlloc1 + kAlloc2, allocator_->GetLargestFreeSizeNoWaiting());
432 } // namespace gpu