| Index: gpu/command_buffer/client/client_discardable_manager_unittest.cc
 | 
| diff --git a/gpu/command_buffer/client/client_discardable_manager_unittest.cc b/gpu/command_buffer/client/client_discardable_manager_unittest.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..b1629e99c987d69ebeff8d33d77dbaf4c1046b68
 | 
| --- /dev/null
 | 
| +++ b/gpu/command_buffer/client/client_discardable_manager_unittest.cc
 | 
| @@ -0,0 +1,137 @@
 | 
| +// Copyright (c) 2017 The Chromium Authors. All rights reserved.
 | 
| +// Use of this source code is governed by a BSD-style license that can be
 | 
| +// found in the LICENSE file.
 | 
| +
 | 
| +#include "gpu/command_buffer/client/client_discardable_manager.h"
 | 
| +#include "testing/gtest/include/gtest/gtest.h"
 | 
| +
 | 
| +namespace gpu {
 | 
| +namespace {
 | 
| +class FakeCommandBuffer : public CommandBuffer {
 | 
| + public:
 | 
| +  FakeCommandBuffer() = default;
 | 
| +  ~FakeCommandBuffer() override { EXPECT_TRUE(active_ids_.empty()); }
 | 
| +  // Overridden from CommandBuffer:
 | 
| +  State GetLastState() override {
 | 
| +    NOTREACHED();
 | 
| +    return State();
 | 
| +  };
 | 
| +  void Flush(int32_t put_offset) override { NOTREACHED(); }
 | 
| +  void OrderingBarrier(int32_t put_offset) override { NOTREACHED(); }
 | 
| +  State WaitForTokenInRange(int32_t start, int32_t end) override {
 | 
| +    NOTREACHED();
 | 
| +
 | 
| +    return State();
 | 
| +  }
 | 
| +  State WaitForGetOffsetInRange(int32_t start, int32_t end) override {
 | 
| +    NOTREACHED();
 | 
| +    return State();
 | 
| +  }
 | 
| +  void SetGetBuffer(int32_t transfer_buffer_id) override { NOTREACHED(); }
 | 
| +  scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size,
 | 
| +                                                  int32_t* id) override {
 | 
| +    EXPECT_EQ(4096u, size);
 | 
| +    *id = next_id_++;
 | 
| +    active_ids_.insert(*id);
 | 
| +    std::unique_ptr<base::SharedMemory> shared_mem(new base::SharedMemory);
 | 
| +    shared_mem->CreateAndMapAnonymous(size);
 | 
| +    return MakeBufferFromSharedMemory(std::move(shared_mem), size);
 | 
| +  }
 | 
| +  void DestroyTransferBuffer(int32_t id) override {
 | 
| +    auto found = active_ids_.find(id);
 | 
| +    EXPECT_TRUE(found != active_ids_.end());
 | 
| +    active_ids_.erase(found);
 | 
| +  }
 | 
| +
 | 
| + private:
 | 
| +  int32_t next_id_ = 1;
 | 
| +  std::set<int32_t> active_ids_;
 | 
| +};
 | 
| +
 | 
| +void UnlockAndDeleteClientHandleForTesting(
 | 
| +    const ClientDiscardableHandle& client_handle) {
 | 
| +  ServiceDiscardableHandle service_handle(client_handle.BufferForTesting(),
 | 
| +                                          client_handle.byte_offset(),
 | 
| +                                          client_handle.shm_id());
 | 
| +  service_handle.Unlock();
 | 
| +  EXPECT_TRUE(service_handle.Delete());
 | 
| +}
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
| +TEST(ClientDiscardableManagerTest, BasicUsage) {
 | 
| +  FakeCommandBuffer command_buffer;
 | 
| +  ClientDiscardableManager manager;
 | 
| +  {
 | 
| +    ClientDiscardableHandle handle = manager.GetForTexture(&command_buffer, 1);
 | 
| +    EXPECT_TRUE(handle.IsLockedForTesting());
 | 
| +    EXPECT_EQ(handle.shm_id(), 1);
 | 
| +    UnlockAndDeleteClientHandleForTesting(handle);
 | 
| +  }
 | 
| +  manager.FreeForTexture(1);
 | 
| +  manager.CheckPendingForTesting(&command_buffer);
 | 
| +}
 | 
| +
 | 
| +TEST(ClientDiscardableManagerTest, Reuse) {
 | 
| +  FakeCommandBuffer command_buffer;
 | 
| +  ClientDiscardableManager manager;
 | 
| +  manager.SetElementCountForTesting(1024);
 | 
| +  for (int i = 1; i <= 1024; ++i) {
 | 
| +    ClientDiscardableHandle handle = manager.GetForTexture(&command_buffer, i);
 | 
| +    EXPECT_TRUE(handle.IsLockedForTesting());
 | 
| +    EXPECT_EQ(handle.shm_id(), 1);
 | 
| +    UnlockAndDeleteClientHandleForTesting(handle);
 | 
| +  }
 | 
| +  // Delete every other entry.
 | 
| +  for (int i = 1; i <= 1024; i += 2) {
 | 
| +    manager.FreeForTexture(i);
 | 
| +  }
 | 
| +  // Allocate 512 more entries, ensure we re-use the original buffer.
 | 
| +  for (int i = 1; i <= 512; ++i) {
 | 
| +    ClientDiscardableHandle handle =
 | 
| +        manager.GetForTexture(&command_buffer, 1024 + i);
 | 
| +    EXPECT_TRUE(handle.IsLockedForTesting());
 | 
| +    EXPECT_EQ(handle.shm_id(), 1);
 | 
| +    UnlockAndDeleteClientHandleForTesting(handle);
 | 
| +  }
 | 
| +  // Delete the other half of the original allocations.
 | 
| +  for (int i = 2; i <= 1024; i += 2) {
 | 
| +    manager.FreeForTexture(i);
 | 
| +  }
 | 
| +  // And delete the second set of allocations.
 | 
| +  for (int i = 1; i <= 512; ++i) {
 | 
| +    manager.FreeForTexture(1024 + i);
 | 
| +  }
 | 
| +  manager.CheckPendingForTesting(&command_buffer);
 | 
| +}
 | 
| +
 | 
| +TEST(ClientDiscardableManagerTest, MultipleAllocations) {
 | 
| +  FakeCommandBuffer command_buffer;
 | 
| +  ClientDiscardableManager manager;
 | 
| +  manager.SetElementCountForTesting(1024);
 | 
| +  for (int i = 1; i <= 1024; ++i) {
 | 
| +    ClientDiscardableHandle handle = manager.GetForTexture(&command_buffer, i);
 | 
| +    EXPECT_TRUE(handle.IsLockedForTesting());
 | 
| +    EXPECT_EQ(handle.shm_id(), 1);
 | 
| +    UnlockAndDeleteClientHandleForTesting(handle);
 | 
| +  }
 | 
| +  // Allocate and free one entry multiple times, this should cause the
 | 
| +  // allocation and release of a new shm_id each time.
 | 
| +  for (int i = 1; i < 10; ++i) {
 | 
| +    {
 | 
| +      ClientDiscardableHandle handle =
 | 
| +          manager.GetForTexture(&command_buffer, 1024 + i);
 | 
| +      EXPECT_TRUE(handle.IsLockedForTesting());
 | 
| +      EXPECT_EQ(handle.shm_id(), i + 1);
 | 
| +      UnlockAndDeleteClientHandleForTesting(handle);
 | 
| +    }
 | 
| +    manager.FreeForTexture(1024 + i);
 | 
| +  }
 | 
| +  // Delete every other entry.
 | 
| +  for (int i = 1; i <= 1024; ++i) {
 | 
| +    manager.FreeForTexture(i);
 | 
| +  }
 | 
| +  manager.CheckPendingForTesting(&command_buffer);
 | 
| +}
 | 
| +
 | 
| +}  // namespace gpu
 | 
| 
 |