| // Copyright (c) 2011 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. |
| |
| // This file has the unit tests for the IdAllocator class. |
| |
| #include <stdint.h> |
| |
| #include "gpu/command_buffer/common/id_allocator.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace gpu { |
| |
| class IdAllocatorTest : public testing::Test { |
| protected: |
| void SetUp() override {} |
| void TearDown() override {} |
| |
| IdAllocator* id_allocator() { return &id_allocator_; } |
| |
| private: |
| IdAllocator id_allocator_; |
| }; |
| |
| // Checks basic functionality: AllocateID, FreeID, InUse. |
| TEST_F(IdAllocatorTest, TestBasic) { |
| IdAllocator *allocator = id_allocator(); |
| // Check that resource 1 is not in use |
| EXPECT_FALSE(allocator->InUse(1)); |
| |
| // Allocate an ID, check that it's in use. |
| ResourceId id1 = allocator->AllocateID(); |
| EXPECT_TRUE(allocator->InUse(id1)); |
| |
| // Allocate another ID, check that it's in use, and different from the first |
| // one. |
| ResourceId id2 = allocator->AllocateID(); |
| EXPECT_TRUE(allocator->InUse(id2)); |
| EXPECT_NE(id1, id2); |
| |
| // Free one of the IDs, check that it's not in use any more. |
| allocator->FreeID(id1); |
| EXPECT_FALSE(allocator->InUse(id1)); |
| |
| // Frees the other ID, check that it's not in use any more. |
| allocator->FreeID(id2); |
| EXPECT_FALSE(allocator->InUse(id2)); |
| } |
| |
| // Checks that the resource IDs are re-used after being freed. |
| TEST_F(IdAllocatorTest, TestAdvanced) { |
| IdAllocator *allocator = id_allocator(); |
| |
| // Allocate the highest possible ID, to make life awkward. |
| allocator->AllocateIDAtOrAbove(~static_cast<ResourceId>(0)); |
| |
| // Allocate a significant number of resources. |
| const unsigned int kNumResources = 100; |
| ResourceId ids[kNumResources]; |
| for (unsigned int i = 0; i < kNumResources; ++i) { |
| ids[i] = allocator->AllocateID(); |
| EXPECT_TRUE(allocator->InUse(ids[i])); |
| } |
| |
| // Check that a new allocation re-uses the resource we just freed. |
| ResourceId id1 = ids[kNumResources / 2]; |
| allocator->FreeID(id1); |
| EXPECT_FALSE(allocator->InUse(id1)); |
| ResourceId id2 = allocator->AllocateID(); |
| EXPECT_TRUE(allocator->InUse(id2)); |
| EXPECT_EQ(id1, id2); |
| } |
| |
| // Checks that we can choose our own ids and they won't be reused. |
| TEST_F(IdAllocatorTest, MarkAsUsed) { |
| IdAllocator* allocator = id_allocator(); |
| ResourceId id = allocator->AllocateID(); |
| allocator->FreeID(id); |
| EXPECT_FALSE(allocator->InUse(id)); |
| EXPECT_TRUE(allocator->MarkAsUsed(id)); |
| EXPECT_TRUE(allocator->InUse(id)); |
| ResourceId id2 = allocator->AllocateID(); |
| EXPECT_NE(id, id2); |
| EXPECT_TRUE(allocator->MarkAsUsed(id2 + 1)); |
| ResourceId id3 = allocator->AllocateID(); |
| // Checks our algorithm. If the algorithm changes this check should be |
| // changed. |
| EXPECT_EQ(id3, id2 + 2); |
| } |
| |
| // Checks AllocateIdAtOrAbove. |
| TEST_F(IdAllocatorTest, AllocateIdAtOrAbove) { |
| const ResourceId kOffset = 123456; |
| IdAllocator* allocator = id_allocator(); |
| ResourceId id1 = allocator->AllocateIDAtOrAbove(kOffset); |
| EXPECT_EQ(kOffset, id1); |
| ResourceId id2 = allocator->AllocateIDAtOrAbove(kOffset); |
| EXPECT_GT(id2, kOffset); |
| ResourceId id3 = allocator->AllocateIDAtOrAbove(kOffset); |
| EXPECT_GT(id3, kOffset); |
| } |
| |
| // Checks that AllocateIdAtOrAbove wraps around at the maximum value. |
| TEST_F(IdAllocatorTest, AllocateIdAtOrAboveWrapsAround) { |
| const ResourceId kMaxPossibleOffset = ~static_cast<ResourceId>(0); |
| IdAllocator* allocator = id_allocator(); |
| ResourceId id1 = allocator->AllocateIDAtOrAbove(kMaxPossibleOffset); |
| EXPECT_EQ(kMaxPossibleOffset, id1); |
| ResourceId id2 = allocator->AllocateIDAtOrAbove(kMaxPossibleOffset); |
| EXPECT_EQ(1u, id2); |
| ResourceId id3 = allocator->AllocateIDAtOrAbove(kMaxPossibleOffset); |
| EXPECT_EQ(2u, id3); |
| } |
| |
| TEST_F(IdAllocatorTest, RedundantFreeIsIgnored) { |
| IdAllocator* allocator = id_allocator(); |
| ResourceId id1 = allocator->AllocateID(); |
| allocator->FreeID(0); |
| allocator->FreeID(id1); |
| allocator->FreeID(id1); |
| allocator->FreeID(id1 + 1); |
| |
| ResourceId id2 = allocator->AllocateID(); |
| ResourceId id3 = allocator->AllocateID(); |
| EXPECT_NE(id2, id3); |
| EXPECT_NE(kInvalidResource, id2); |
| EXPECT_NE(kInvalidResource, id3); |
| } |
| |
| TEST_F(IdAllocatorTest, AllocateIDRange) { |
| const ResourceId kMaxPossibleOffset = std::numeric_limits<ResourceId>::max(); |
| |
| IdAllocator* allocator = id_allocator(); |
| |
| ResourceId id1 = allocator->AllocateIDRange(1); |
| EXPECT_EQ(1u, id1); |
| ResourceId id2 = allocator->AllocateIDRange(2); |
| EXPECT_EQ(2u, id2); |
| ResourceId id3 = allocator->AllocateIDRange(3); |
| EXPECT_EQ(4u, id3); |
| ResourceId id4 = allocator->AllocateID(); |
| EXPECT_EQ(7u, id4); |
| allocator->FreeID(3); |
| ResourceId id5 = allocator->AllocateIDRange(1); |
| EXPECT_EQ(3u, id5); |
| allocator->FreeID(5); |
| allocator->FreeID(2); |
| allocator->FreeID(4); |
| ResourceId id6 = allocator->AllocateIDRange(2); |
| EXPECT_EQ(4u, id6); |
| ResourceId id7 = allocator->AllocateIDAtOrAbove(kMaxPossibleOffset); |
| EXPECT_EQ(kMaxPossibleOffset, id7); |
| ResourceId id8 = allocator->AllocateIDAtOrAbove(kMaxPossibleOffset); |
| EXPECT_EQ(2u, id8); |
| ResourceId id9 = allocator->AllocateIDRange(50); |
| EXPECT_EQ(8u, id9); |
| ResourceId id10 = allocator->AllocateIDRange(50); |
| EXPECT_EQ(58u, id10); |
| // Remove all the low-numbered ids. |
| allocator->FreeID(1); |
| allocator->FreeID(15); |
| allocator->FreeIDRange(2, 107); |
| ResourceId id11 = allocator->AllocateIDRange(100); |
| EXPECT_EQ(1u, id11); |
| allocator->FreeID(kMaxPossibleOffset); |
| ResourceId id12 = allocator->AllocateIDRange(100); |
| EXPECT_EQ(101u, id12); |
| |
| ResourceId id13 = allocator->AllocateIDAtOrAbove(kMaxPossibleOffset - 2u); |
| EXPECT_EQ(kMaxPossibleOffset - 2u, id13); |
| ResourceId id14 = allocator->AllocateIDRange(3); |
| EXPECT_EQ(201u, id14); |
| } |
| |
| TEST_F(IdAllocatorTest, AllocateIDRangeEndNoEffect) { |
| const ResourceId kMaxPossibleOffset = std::numeric_limits<ResourceId>::max(); |
| |
| IdAllocator* allocator = id_allocator(); |
| ResourceId id1 = allocator->AllocateIDAtOrAbove(kMaxPossibleOffset - 2u); |
| EXPECT_EQ(kMaxPossibleOffset - 2u, id1); |
| ResourceId id3 = allocator->AllocateIDRange(3); |
| EXPECT_EQ(1u, id3); |
| ResourceId id2 = allocator->AllocateIDRange(2); |
| EXPECT_EQ(4u, id2); |
| } |
| |
| TEST_F(IdAllocatorTest, AllocateFullIDRange) { |
| const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max(); |
| const ResourceId kFreedId = 555u; |
| IdAllocator* allocator = id_allocator(); |
| |
| ResourceId id1 = allocator->AllocateIDRange(kMaxPossibleRange); |
| EXPECT_EQ(1u, id1); |
| ResourceId id2 = allocator->AllocateID(); |
| EXPECT_EQ(0u, id2); |
| allocator->FreeID(kFreedId); |
| ResourceId id3 = allocator->AllocateID(); |
| EXPECT_EQ(kFreedId, id3); |
| ResourceId id4 = allocator->AllocateID(); |
| EXPECT_EQ(0u, id4); |
| allocator->FreeID(kFreedId + 1u); |
| allocator->FreeID(kFreedId + 4u); |
| allocator->FreeID(kFreedId + 3u); |
| allocator->FreeID(kFreedId + 5u); |
| allocator->FreeID(kFreedId + 2u); |
| ResourceId id5 = allocator->AllocateIDRange(5); |
| EXPECT_EQ(kFreedId + 1u, id5); |
| } |
| |
| TEST_F(IdAllocatorTest, AllocateIDRangeNoWrapInRange) { |
| const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max(); |
| const ResourceId kAllocId = 10u; |
| IdAllocator* allocator = id_allocator(); |
| |
| ResourceId id1 = allocator->AllocateIDAtOrAbove(kAllocId); |
| EXPECT_EQ(kAllocId, id1); |
| ResourceId id2 = allocator->AllocateIDRange(kMaxPossibleRange - 5u); |
| EXPECT_EQ(0u, id2); |
| ResourceId id3 = allocator->AllocateIDRange(kMaxPossibleRange - kAllocId); |
| EXPECT_EQ(kAllocId + 1u, id3); |
| } |
| |
| TEST_F(IdAllocatorTest, AllocateIdMax) { |
| const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max(); |
| |
| IdAllocator* allocator = id_allocator(); |
| ResourceId id = allocator->AllocateIDRange(kMaxPossibleRange); |
| EXPECT_EQ(1u, id); |
| allocator->FreeIDRange(id, kMaxPossibleRange - 1u); |
| ResourceId id2 = allocator->AllocateIDRange(kMaxPossibleRange); |
| EXPECT_EQ(0u, id2); |
| allocator->FreeIDRange(id, kMaxPossibleRange); |
| ResourceId id3 = allocator->AllocateIDRange(kMaxPossibleRange); |
| EXPECT_EQ(1u, id3); |
| } |
| |
| TEST_F(IdAllocatorTest, ZeroIdCases) { |
| IdAllocator* allocator = id_allocator(); |
| EXPECT_FALSE(allocator->InUse(0)); |
| ResourceId id1 = allocator->AllocateIDAtOrAbove(0); |
| EXPECT_NE(0u, id1); |
| EXPECT_FALSE(allocator->InUse(0)); |
| allocator->FreeID(0); |
| EXPECT_FALSE(allocator->InUse(0)); |
| EXPECT_TRUE(allocator->InUse(id1)); |
| allocator->FreeID(id1); |
| EXPECT_FALSE(allocator->InUse(id1)); |
| } |
| } // namespace gpu |