This source file includes following definitions.
- SetUp
 
- GetToken
 
- EmptyPoll
 
- SetUp
 
- TearDown
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TearDown
 
- TEST_F
 
- SetUp
 
- TearDown
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/aligned_memory.h"
#include "base/message_loop/message_loop.h"
#include "gpu/command_buffer/client/cmd_buffer_helper.h"
#include "gpu/command_buffer/client/fenced_allocator.h"
#include "gpu/command_buffer/service/cmd_buffer_engine.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/command_buffer/service/gpu_scheduler.h"
#include "gpu/command_buffer/service/mocks.h"
#include "gpu/command_buffer/service/transfer_buffer_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
#endif
namespace gpu {
using testing::Return;
using testing::Mock;
using testing::Truly;
using testing::Sequence;
using testing::DoAll;
using testing::Invoke;
using testing::InvokeWithoutArgs;
using testing::_;
class BaseFencedAllocatorTest : public testing::Test {
 protected:
  static const unsigned int kBufferSize = 1024;
  static const int kAllocAlignment = 16;
  virtual void SetUp() {
    api_mock_.reset(new AsyncAPIMock);
    
    
    EXPECT_CALL(*api_mock_, DoCommand(cmd::kNoop, 0, _))
        .WillRepeatedly(Return(error::kNoError));
    
    EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _))
        .WillRepeatedly(DoAll(Invoke(api_mock_.get(), &AsyncAPIMock::SetToken),
                              Return(error::kNoError)));
    {
      TransferBufferManager* manager = new TransferBufferManager();
      transfer_buffer_manager_.reset(manager);
      EXPECT_TRUE(manager->Initialize());
    }
    command_buffer_.reset(
        new CommandBufferService(transfer_buffer_manager_.get()));
    EXPECT_TRUE(command_buffer_->Initialize());
    gpu_scheduler_.reset(new GpuScheduler(
        command_buffer_.get(), api_mock_.get(), NULL));
    command_buffer_->SetPutOffsetChangeCallback(base::Bind(
        &GpuScheduler::PutChanged, base::Unretained(gpu_scheduler_.get())));
    command_buffer_->SetGetBufferChangeCallback(base::Bind(
        &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get())));
    api_mock_->set_engine(gpu_scheduler_.get());
    helper_.reset(new CommandBufferHelper(command_buffer_.get()));
    helper_->Initialize(kBufferSize);
  }
  int32 GetToken() {
    return command_buffer_->GetState().token;
  }
#if defined(OS_MACOSX)
  base::mac::ScopedNSAutoreleasePool autorelease_pool_;
#endif
  base::MessageLoop message_loop_;
  scoped_ptr<AsyncAPIMock> api_mock_;
  scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_;
  scoped_ptr<CommandBufferService> command_buffer_;
  scoped_ptr<GpuScheduler> gpu_scheduler_;
  scoped_ptr<CommandBufferHelper> helper_;
};
#ifndef _MSC_VER
const unsigned int BaseFencedAllocatorTest::kBufferSize;
#endif
namespace {
void EmptyPoll() {
}
}
class FencedAllocatorTest : public BaseFencedAllocatorTest {
 protected:
  virtual void SetUp() {
    BaseFencedAllocatorTest::SetUp();
    allocator_.reset(new FencedAllocator(kBufferSize,
                                         helper_.get(),
                                         base::Bind(&EmptyPoll)));
  }
  virtual void TearDown() {
    
    base::MessageLoop::current()->RunUntilIdle();
    EXPECT_TRUE(allocator_->CheckConsistency());
    BaseFencedAllocatorTest::TearDown();
  }
  scoped_ptr<FencedAllocator> allocator_;
};
TEST_F(FencedAllocatorTest, TestBasic) {
  allocator_->CheckConsistency();
  EXPECT_FALSE(allocator_->InUse());
  const unsigned int kSize = 16;
  FencedAllocator::Offset offset = allocator_->Alloc(kSize);
  EXPECT_TRUE(allocator_->InUse());
  EXPECT_NE(FencedAllocator::kInvalidOffset, offset);
  EXPECT_GE(kBufferSize, offset+kSize);
  EXPECT_TRUE(allocator_->CheckConsistency());
  allocator_->Free(offset);
  EXPECT_FALSE(allocator_->InUse());
  EXPECT_TRUE(allocator_->CheckConsistency());
}
TEST_F(FencedAllocatorTest, TestAllocZero) {
  FencedAllocator::Offset offset = allocator_->Alloc(0);
  EXPECT_EQ(FencedAllocator::kInvalidOffset, offset);
  EXPECT_FALSE(allocator_->InUse());
  EXPECT_TRUE(allocator_->CheckConsistency());
}
TEST_F(FencedAllocatorTest, TestOutOfMemory) {
  EXPECT_TRUE(allocator_->CheckConsistency());
  const unsigned int kSize = 16;
  const unsigned int kAllocCount = kBufferSize / kSize;
  CHECK(kAllocCount * kSize == kBufferSize);
  
  FencedAllocator::Offset offsets[kAllocCount];
  for (unsigned int i = 0; i < kAllocCount; ++i) {
    offsets[i] = allocator_->Alloc(kSize);
    EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[i]);
    EXPECT_GE(kBufferSize, offsets[i]+kSize);
    EXPECT_TRUE(allocator_->CheckConsistency());
  }
  
  FencedAllocator::Offset offset_failed = allocator_->Alloc(kSize);
  EXPECT_EQ(FencedAllocator::kInvalidOffset, offset_failed);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  allocator_->Free(offsets[0]);
  EXPECT_TRUE(allocator_->CheckConsistency());
  offsets[0] = allocator_->Alloc(kSize/2);
  EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[0]);
  EXPECT_GE(kBufferSize, offsets[0]+kSize);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  offset_failed = allocator_->Alloc(kSize);
  EXPECT_EQ(FencedAllocator::kInvalidOffset, offset_failed);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  for (unsigned int i = 0; i < kAllocCount; ++i) {
    allocator_->Free(offsets[i]);
    EXPECT_TRUE(allocator_->CheckConsistency());
  }
}
TEST_F(FencedAllocatorTest, TestFreePendingToken) {
  EXPECT_TRUE(allocator_->CheckConsistency());
  const unsigned int kSize = 16;
  const unsigned int kAllocCount = kBufferSize / kSize;
  CHECK(kAllocCount * kSize == kBufferSize);
  
  FencedAllocator::Offset offsets[kAllocCount];
  for (unsigned int i = 0; i < kAllocCount; ++i) {
    offsets[i] = allocator_->Alloc(kSize);
    EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[i]);
    EXPECT_GE(kBufferSize, offsets[i]+kSize);
    EXPECT_TRUE(allocator_->CheckConsistency());
  }
  
  FencedAllocator::Offset offset_failed = allocator_->Alloc(kSize);
  EXPECT_EQ(FencedAllocator::kInvalidOffset, offset_failed);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  int32 token = helper_.get()->InsertToken();
  allocator_->FreePendingToken(offsets[0], token);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  
  
  EXPECT_GT(token, GetToken());
  
  
  offsets[0] = allocator_->Alloc(kSize);
  EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[0]);
  EXPECT_GE(kBufferSize, offsets[0]+kSize);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  EXPECT_LE(token, GetToken());
  
  for (unsigned int i = 0; i < kAllocCount; ++i) {
    allocator_->Free(offsets[i]);
    EXPECT_TRUE(allocator_->CheckConsistency());
  }
}
TEST_F(FencedAllocatorTest, FreeUnused) {
  EXPECT_TRUE(allocator_->CheckConsistency());
  const unsigned int kSize = 16;
  const unsigned int kAllocCount = kBufferSize / kSize;
  CHECK(kAllocCount * kSize == kBufferSize);
  
  FencedAllocator::Offset offsets[kAllocCount];
  for (unsigned int i = 0; i < kAllocCount; ++i) {
    offsets[i] = allocator_->Alloc(kSize);
    EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[i]);
    EXPECT_GE(kBufferSize, offsets[i]+kSize);
    EXPECT_TRUE(allocator_->CheckConsistency());
  }
  EXPECT_TRUE(allocator_->InUse());
  
  EXPECT_EQ(0u, allocator_->GetLargestFreeSize());
  
  int32 token = helper_.get()->InsertToken();
  allocator_->FreePendingToken(offsets[0], token);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  helper_->Finish();
  
  allocator_->FreeUnused();
  
  EXPECT_EQ(kSize, allocator_->GetLargestFreeSize());
  
  token = helper_.get()->InsertToken();
  allocator_->FreePendingToken(offsets[1], token);
  token = helper_.get()->InsertToken();
  allocator_->FreePendingToken(offsets[2], token);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  EXPECT_EQ(kSize, allocator_->GetLargestFreeSize());
  
  helper_->Finish();
  
  allocator_->FreeUnused();
  
  EXPECT_EQ(kSize * 3, allocator_->GetLargestFreeSize());
  EXPECT_TRUE(allocator_->InUse());
  
  for (unsigned int i = 3; i < kAllocCount; ++i) {
    allocator_->Free(offsets[i]);
    EXPECT_TRUE(allocator_->CheckConsistency());
  }
  EXPECT_FALSE(allocator_->InUse());
}
TEST_F(FencedAllocatorTest, TestGetLargestFreeSize) {
  EXPECT_TRUE(allocator_->CheckConsistency());
  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSize());
  FencedAllocator::Offset offset = allocator_->Alloc(kBufferSize);
  ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
  EXPECT_EQ(0u, allocator_->GetLargestFreeSize());
  allocator_->Free(offset);
  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSize());
  const unsigned int kSize = 16;
  offset = allocator_->Alloc(kSize);
  ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
  
  
  
  EXPECT_EQ(kBufferSize - kSize, allocator_->GetLargestFreeSize());
  
  
  
  FencedAllocator::Offset offset1 = allocator_->Alloc(kSize);
  ASSERT_NE(FencedAllocator::kInvalidOffset, offset1);
  FencedAllocator::Offset offset2 = allocator_->Alloc(kSize);
  ASSERT_NE(FencedAllocator::kInvalidOffset, offset2);
  allocator_->Free(offset);
  allocator_->Free(offset1);
  EXPECT_EQ(kBufferSize - 3 * kSize, allocator_->GetLargestFreeSize());
  offset = allocator_->Alloc(kBufferSize - 3 * kSize);
  ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
  EXPECT_EQ(2 * kSize, allocator_->GetLargestFreeSize());
  offset1 = allocator_->Alloc(2 * kSize);
  ASSERT_NE(FencedAllocator::kInvalidOffset, offset1);
  EXPECT_EQ(0u, allocator_->GetLargestFreeSize());
  allocator_->Free(offset);
  allocator_->Free(offset1);
  allocator_->Free(offset2);
}
TEST_F(FencedAllocatorTest, TestGetLargestFreeOrPendingSize) {
  EXPECT_TRUE(allocator_->CheckConsistency());
  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
  FencedAllocator::Offset offset = allocator_->Alloc(kBufferSize);
  ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
  EXPECT_EQ(0u, allocator_->GetLargestFreeOrPendingSize());
  allocator_->Free(offset);
  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
  const unsigned int kSize = 16;
  offset = allocator_->Alloc(kSize);
  ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
  
  
  
  EXPECT_EQ(kBufferSize - kSize, allocator_->GetLargestFreeOrPendingSize());
  
  
  
  FencedAllocator::Offset offset1 = allocator_->Alloc(kSize);
  ASSERT_NE(FencedAllocator::kInvalidOffset, offset1);
  FencedAllocator::Offset offset2 = allocator_->Alloc(kSize);
  ASSERT_NE(FencedAllocator::kInvalidOffset, offset2);
  allocator_->Free(offset);
  allocator_->Free(offset1);
  EXPECT_EQ(kBufferSize - 3 * kSize,
            allocator_->GetLargestFreeOrPendingSize());
  
  int32 token = helper_.get()->InsertToken();
  allocator_->FreePendingToken(offset2, token);
  
  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
  
  EXPECT_EQ(kBufferSize - 3 * kSize,
            allocator_->GetLargestFreeSize());
  
  
  
  EXPECT_GT(token, GetToken());
  
  
  offset = allocator_->Alloc(kBufferSize);
  ASSERT_NE(FencedAllocator::kInvalidOffset, offset);
  
  EXPECT_LE(token, GetToken());
  allocator_->Free(offset);
  
  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize());
  
  EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSize());
}
class FencedAllocatorPollTest : public BaseFencedAllocatorTest {
 public:
  static const unsigned int kAllocSize = 128;
  MOCK_METHOD0(MockedPoll, void());
 protected:
  virtual void TearDown() {
    
    base::MessageLoop::current()->RunUntilIdle();
    BaseFencedAllocatorTest::TearDown();
  }
};
TEST_F(FencedAllocatorPollTest, TestPoll) {
  scoped_ptr<FencedAllocator> allocator(
      new FencedAllocator(kBufferSize,
                          helper_.get(),
                          base::Bind(&FencedAllocatorPollTest::MockedPoll,
                                     base::Unretained(this))));
  FencedAllocator::Offset mem1 = allocator->Alloc(kAllocSize);
  FencedAllocator::Offset mem2 = allocator->Alloc(kAllocSize);
  EXPECT_NE(mem1, FencedAllocator::kInvalidOffset);
  EXPECT_NE(mem2, FencedAllocator::kInvalidOffset);
  EXPECT_TRUE(allocator->CheckConsistency());
  EXPECT_EQ(allocator->bytes_in_use(), kAllocSize * 2);
  
  EXPECT_CALL(*this, MockedPoll()).RetiresOnSaturation();
  allocator->FreeUnused();
  EXPECT_TRUE(allocator->CheckConsistency());
  EXPECT_EQ(allocator->bytes_in_use(), kAllocSize * 2);
  
  base::Closure free_mem1_closure =
      base::Bind(&FencedAllocator::Free,
                 base::Unretained(allocator.get()),
                 mem1);
  EXPECT_CALL(*this, MockedPoll())
      .WillOnce(InvokeWithoutArgs(&free_mem1_closure, &base::Closure::Run))
      .RetiresOnSaturation();
  allocator->FreeUnused();
  EXPECT_TRUE(allocator->CheckConsistency());
  EXPECT_EQ(allocator->bytes_in_use(), kAllocSize * 1);
  
  EXPECT_CALL(*this, MockedPoll()).RetiresOnSaturation();
  allocator->Free(mem2);
  allocator->FreeUnused();
  EXPECT_TRUE(allocator->CheckConsistency());
  EXPECT_EQ(allocator->bytes_in_use(), 0u);
  allocator.reset();
}
class FencedAllocatorWrapperTest : public BaseFencedAllocatorTest {
 protected:
  virtual void SetUp() {
    BaseFencedAllocatorTest::SetUp();
    
    
    
    buffer_.reset(static_cast<char*>(base::AlignedAlloc(
        kBufferSize, kAllocAlignment)));
    allocator_.reset(new FencedAllocatorWrapper(kBufferSize,
                                                helper_.get(),
                                                base::Bind(&EmptyPoll),
                                                buffer_.get()));
  }
  virtual void TearDown() {
    
    base::MessageLoop::current()->RunUntilIdle();
    EXPECT_TRUE(allocator_->CheckConsistency());
    BaseFencedAllocatorTest::TearDown();
  }
  scoped_ptr<FencedAllocatorWrapper> allocator_;
  scoped_ptr<char, base::AlignedFreeDeleter> buffer_;
};
TEST_F(FencedAllocatorWrapperTest, TestBasic) {
  allocator_->CheckConsistency();
  const unsigned int kSize = 16;
  void *pointer = allocator_->Alloc(kSize);
  ASSERT_TRUE(pointer);
  EXPECT_LE(buffer_.get(), static_cast<char *>(pointer));
  EXPECT_GE(kBufferSize, static_cast<char *>(pointer) - buffer_.get() + kSize);
  EXPECT_TRUE(allocator_->CheckConsistency());
  allocator_->Free(pointer);
  EXPECT_TRUE(allocator_->CheckConsistency());
  char *pointer_char = allocator_->AllocTyped<char>(kSize);
  ASSERT_TRUE(pointer_char);
  EXPECT_LE(buffer_.get(), pointer_char);
  EXPECT_GE(buffer_.get() + kBufferSize, pointer_char + kSize);
  allocator_->Free(pointer_char);
  EXPECT_TRUE(allocator_->CheckConsistency());
  unsigned int *pointer_uint = allocator_->AllocTyped<unsigned int>(kSize);
  ASSERT_TRUE(pointer_uint);
  EXPECT_LE(buffer_.get(), reinterpret_cast<char *>(pointer_uint));
  EXPECT_GE(buffer_.get() + kBufferSize,
            reinterpret_cast<char *>(pointer_uint + kSize));
  
  
  EXPECT_EQ(kBufferSize - kSize * sizeof(*pointer_uint),
            allocator_->GetLargestFreeSize());
  allocator_->Free(pointer_uint);
}
TEST_F(FencedAllocatorWrapperTest, TestAllocZero) {
  allocator_->CheckConsistency();
  void *pointer = allocator_->Alloc(0);
  ASSERT_FALSE(pointer);
  EXPECT_TRUE(allocator_->CheckConsistency());
}
TEST_F(FencedAllocatorWrapperTest, TestAlignment) {
  allocator_->CheckConsistency();
  const unsigned int kSize1 = 75;
  void *pointer1 = allocator_->Alloc(kSize1);
  ASSERT_TRUE(pointer1);
  EXPECT_EQ(reinterpret_cast<intptr_t>(pointer1) & (kAllocAlignment - 1), 0);
  EXPECT_TRUE(allocator_->CheckConsistency());
  const unsigned int kSize2 = 43;
  void *pointer2 = allocator_->Alloc(kSize2);
  ASSERT_TRUE(pointer2);
  EXPECT_EQ(reinterpret_cast<intptr_t>(pointer2) & (kAllocAlignment - 1), 0);
  EXPECT_TRUE(allocator_->CheckConsistency());
  allocator_->Free(pointer2);
  EXPECT_TRUE(allocator_->CheckConsistency());
  allocator_->Free(pointer1);
  EXPECT_TRUE(allocator_->CheckConsistency());
}
TEST_F(FencedAllocatorWrapperTest, TestOutOfMemory) {
  allocator_->CheckConsistency();
  const unsigned int kSize = 16;
  const unsigned int kAllocCount = kBufferSize / kSize;
  CHECK(kAllocCount * kSize == kBufferSize);
  
  void *pointers[kAllocCount];
  for (unsigned int i = 0; i < kAllocCount; ++i) {
    pointers[i] = allocator_->Alloc(kSize);
    EXPECT_TRUE(pointers[i]);
    EXPECT_TRUE(allocator_->CheckConsistency());
  }
  
  void *pointer_failed = allocator_->Alloc(kSize);
  EXPECT_FALSE(pointer_failed);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  allocator_->Free(pointers[0]);
  EXPECT_TRUE(allocator_->CheckConsistency());
  pointers[0] = allocator_->Alloc(kSize/2);
  EXPECT_TRUE(pointers[0]);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  pointer_failed = allocator_->Alloc(kSize);
  EXPECT_FALSE(pointer_failed);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  for (unsigned int i = 0; i < kAllocCount; ++i) {
    allocator_->Free(pointers[i]);
    EXPECT_TRUE(allocator_->CheckConsistency());
  }
}
TEST_F(FencedAllocatorWrapperTest, TestFreePendingToken) {
  allocator_->CheckConsistency();
  const unsigned int kSize = 16;
  const unsigned int kAllocCount = kBufferSize / kSize;
  CHECK(kAllocCount * kSize == kBufferSize);
  
  void *pointers[kAllocCount];
  for (unsigned int i = 0; i < kAllocCount; ++i) {
    pointers[i] = allocator_->Alloc(kSize);
    EXPECT_TRUE(pointers[i]);
    EXPECT_TRUE(allocator_->CheckConsistency());
  }
  
  void *pointer_failed = allocator_->Alloc(kSize);
  EXPECT_FALSE(pointer_failed);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  int32 token = helper_.get()->InsertToken();
  allocator_->FreePendingToken(pointers[0], token);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  
  
  EXPECT_GT(token, GetToken());
  
  
  pointers[0] = allocator_->Alloc(kSize);
  EXPECT_TRUE(pointers[0]);
  EXPECT_TRUE(allocator_->CheckConsistency());
  
  EXPECT_LE(token, GetToken());
  
  for (unsigned int i = 0; i < kAllocCount; ++i) {
    allocator_->Free(pointers[i]);
    EXPECT_TRUE(allocator_->CheckConsistency());
  }
}
}