xref: /aosp_15_r20/external/angle/src/libANGLE/HandleAllocator_unittest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // Unit tests for HandleAllocator.
7*8975f5c5SAndroid Build Coastguard Worker //
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include <unordered_set>
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include "gmock/gmock.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "gtest/gtest.h"
13*8975f5c5SAndroid Build Coastguard Worker 
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/HandleAllocator.h"
15*8975f5c5SAndroid Build Coastguard Worker 
16*8975f5c5SAndroid Build Coastguard Worker namespace
17*8975f5c5SAndroid Build Coastguard Worker {
18*8975f5c5SAndroid Build Coastguard Worker 
TEST(HandleAllocatorTest,ReservationsWithGaps)19*8975f5c5SAndroid Build Coastguard Worker TEST(HandleAllocatorTest, ReservationsWithGaps)
20*8975f5c5SAndroid Build Coastguard Worker {
21*8975f5c5SAndroid Build Coastguard Worker     gl::HandleAllocator allocator;
22*8975f5c5SAndroid Build Coastguard Worker 
23*8975f5c5SAndroid Build Coastguard Worker     std::set<GLuint> allocationList;
24*8975f5c5SAndroid Build Coastguard Worker     for (GLuint id = 2; id < 50; id += 2)
25*8975f5c5SAndroid Build Coastguard Worker     {
26*8975f5c5SAndroid Build Coastguard Worker         allocationList.insert(id);
27*8975f5c5SAndroid Build Coastguard Worker     }
28*8975f5c5SAndroid Build Coastguard Worker 
29*8975f5c5SAndroid Build Coastguard Worker     for (GLuint id : allocationList)
30*8975f5c5SAndroid Build Coastguard Worker     {
31*8975f5c5SAndroid Build Coastguard Worker         allocator.reserve(id);
32*8975f5c5SAndroid Build Coastguard Worker     }
33*8975f5c5SAndroid Build Coastguard Worker 
34*8975f5c5SAndroid Build Coastguard Worker     std::set<GLuint> allocatedList;
35*8975f5c5SAndroid Build Coastguard Worker     for (size_t allocationNum = 0; allocationNum < allocationList.size() * 2; ++allocationNum)
36*8975f5c5SAndroid Build Coastguard Worker     {
37*8975f5c5SAndroid Build Coastguard Worker         GLuint handle = allocator.allocate();
38*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(0u, allocationList.count(handle));
39*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(0u, allocatedList.count(handle));
40*8975f5c5SAndroid Build Coastguard Worker         allocatedList.insert(handle);
41*8975f5c5SAndroid Build Coastguard Worker     }
42*8975f5c5SAndroid Build Coastguard Worker }
43*8975f5c5SAndroid Build Coastguard Worker 
TEST(HandleAllocatorTest,Random)44*8975f5c5SAndroid Build Coastguard Worker TEST(HandleAllocatorTest, Random)
45*8975f5c5SAndroid Build Coastguard Worker {
46*8975f5c5SAndroid Build Coastguard Worker     gl::HandleAllocator allocator;
47*8975f5c5SAndroid Build Coastguard Worker 
48*8975f5c5SAndroid Build Coastguard Worker     std::set<GLuint> allocationList;
49*8975f5c5SAndroid Build Coastguard Worker     for (size_t iterationCount = 0; iterationCount < 40; ++iterationCount)
50*8975f5c5SAndroid Build Coastguard Worker     {
51*8975f5c5SAndroid Build Coastguard Worker         for (size_t randomCount = 0; randomCount < 40; ++randomCount)
52*8975f5c5SAndroid Build Coastguard Worker         {
53*8975f5c5SAndroid Build Coastguard Worker             GLuint randomHandle = (rand() % 1000) + 1;
54*8975f5c5SAndroid Build Coastguard Worker             if (allocationList.count(randomHandle) == 0)
55*8975f5c5SAndroid Build Coastguard Worker             {
56*8975f5c5SAndroid Build Coastguard Worker                 allocator.reserve(randomHandle);
57*8975f5c5SAndroid Build Coastguard Worker                 allocationList.insert(randomHandle);
58*8975f5c5SAndroid Build Coastguard Worker             }
59*8975f5c5SAndroid Build Coastguard Worker         }
60*8975f5c5SAndroid Build Coastguard Worker 
61*8975f5c5SAndroid Build Coastguard Worker         for (size_t normalCount = 0; normalCount < 40; ++normalCount)
62*8975f5c5SAndroid Build Coastguard Worker         {
63*8975f5c5SAndroid Build Coastguard Worker             GLuint normalHandle = allocator.allocate();
64*8975f5c5SAndroid Build Coastguard Worker             EXPECT_EQ(0u, allocationList.count(normalHandle));
65*8975f5c5SAndroid Build Coastguard Worker             allocationList.insert(normalHandle);
66*8975f5c5SAndroid Build Coastguard Worker         }
67*8975f5c5SAndroid Build Coastguard Worker     }
68*8975f5c5SAndroid Build Coastguard Worker }
69*8975f5c5SAndroid Build Coastguard Worker 
TEST(HandleAllocatorTest,Reallocation)70*8975f5c5SAndroid Build Coastguard Worker TEST(HandleAllocatorTest, Reallocation)
71*8975f5c5SAndroid Build Coastguard Worker {
72*8975f5c5SAndroid Build Coastguard Worker     // Note: no current test for overflow
73*8975f5c5SAndroid Build Coastguard Worker     gl::HandleAllocator limitedAllocator(10);
74*8975f5c5SAndroid Build Coastguard Worker 
75*8975f5c5SAndroid Build Coastguard Worker     for (GLuint count = 1; count < 10; count++)
76*8975f5c5SAndroid Build Coastguard Worker     {
77*8975f5c5SAndroid Build Coastguard Worker         GLuint result = limitedAllocator.allocate();
78*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(count, result);
79*8975f5c5SAndroid Build Coastguard Worker     }
80*8975f5c5SAndroid Build Coastguard Worker 
81*8975f5c5SAndroid Build Coastguard Worker     for (GLuint count = 1; count < 10; count++)
82*8975f5c5SAndroid Build Coastguard Worker     {
83*8975f5c5SAndroid Build Coastguard Worker         limitedAllocator.release(count);
84*8975f5c5SAndroid Build Coastguard Worker     }
85*8975f5c5SAndroid Build Coastguard Worker 
86*8975f5c5SAndroid Build Coastguard Worker     for (GLuint count = 2; count < 10; count++)
87*8975f5c5SAndroid Build Coastguard Worker     {
88*8975f5c5SAndroid Build Coastguard Worker         limitedAllocator.reserve(count);
89*8975f5c5SAndroid Build Coastguard Worker     }
90*8975f5c5SAndroid Build Coastguard Worker 
91*8975f5c5SAndroid Build Coastguard Worker     GLint finalResult = limitedAllocator.allocate();
92*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(finalResult, 1);
93*8975f5c5SAndroid Build Coastguard Worker }
94*8975f5c5SAndroid Build Coastguard Worker 
95*8975f5c5SAndroid Build Coastguard Worker // The following test covers reserving a handle with max uint value. See
96*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42260058
TEST(HandleAllocatorTest,ReserveMaxUintHandle)97*8975f5c5SAndroid Build Coastguard Worker TEST(HandleAllocatorTest, ReserveMaxUintHandle)
98*8975f5c5SAndroid Build Coastguard Worker {
99*8975f5c5SAndroid Build Coastguard Worker     gl::HandleAllocator allocator;
100*8975f5c5SAndroid Build Coastguard Worker 
101*8975f5c5SAndroid Build Coastguard Worker     GLuint maxUintHandle = std::numeric_limits<GLuint>::max();
102*8975f5c5SAndroid Build Coastguard Worker     allocator.reserve(maxUintHandle);
103*8975f5c5SAndroid Build Coastguard Worker 
104*8975f5c5SAndroid Build Coastguard Worker     GLuint normalHandle = allocator.allocate();
105*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(1u, normalHandle);
106*8975f5c5SAndroid Build Coastguard Worker }
107*8975f5c5SAndroid Build Coastguard Worker 
108*8975f5c5SAndroid Build Coastguard Worker // The following test covers reserving a handle with max uint value minus one then max uint value.
TEST(HandleAllocatorTest,ReserveMaxUintHandle2)109*8975f5c5SAndroid Build Coastguard Worker TEST(HandleAllocatorTest, ReserveMaxUintHandle2)
110*8975f5c5SAndroid Build Coastguard Worker {
111*8975f5c5SAndroid Build Coastguard Worker     gl::HandleAllocator allocator;
112*8975f5c5SAndroid Build Coastguard Worker 
113*8975f5c5SAndroid Build Coastguard Worker     GLuint maxUintHandle = std::numeric_limits<GLuint>::max();
114*8975f5c5SAndroid Build Coastguard Worker     allocator.reserve(maxUintHandle - 1);
115*8975f5c5SAndroid Build Coastguard Worker     allocator.reserve(maxUintHandle);
116*8975f5c5SAndroid Build Coastguard Worker 
117*8975f5c5SAndroid Build Coastguard Worker     GLuint normalHandle = allocator.allocate();
118*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(1u, normalHandle);
119*8975f5c5SAndroid Build Coastguard Worker }
120*8975f5c5SAndroid Build Coastguard Worker 
121*8975f5c5SAndroid Build Coastguard Worker // To test if the allocator keep the handle in a sorted order.
TEST(HandleAllocatorTest,SortedOrderHandle)122*8975f5c5SAndroid Build Coastguard Worker TEST(HandleAllocatorTest, SortedOrderHandle)
123*8975f5c5SAndroid Build Coastguard Worker {
124*8975f5c5SAndroid Build Coastguard Worker     gl::HandleAllocator allocator;
125*8975f5c5SAndroid Build Coastguard Worker 
126*8975f5c5SAndroid Build Coastguard Worker     allocator.reserve(3);
127*8975f5c5SAndroid Build Coastguard Worker 
128*8975f5c5SAndroid Build Coastguard Worker     GLuint allocatedList[5];
129*8975f5c5SAndroid Build Coastguard Worker     for (GLuint count = 0; count < 5; count++)
130*8975f5c5SAndroid Build Coastguard Worker     {
131*8975f5c5SAndroid Build Coastguard Worker         allocatedList[count] = allocator.allocate();
132*8975f5c5SAndroid Build Coastguard Worker     }
133*8975f5c5SAndroid Build Coastguard Worker 
134*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(1u, allocatedList[0]);
135*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(2u, allocatedList[1]);
136*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(4u, allocatedList[2]);
137*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(5u, allocatedList[3]);
138*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(6u, allocatedList[4]);
139*8975f5c5SAndroid Build Coastguard Worker }
140*8975f5c5SAndroid Build Coastguard Worker 
141*8975f5c5SAndroid Build Coastguard Worker // Tests the reset method.
TEST(HandleAllocatorTest,Reset)142*8975f5c5SAndroid Build Coastguard Worker TEST(HandleAllocatorTest, Reset)
143*8975f5c5SAndroid Build Coastguard Worker {
144*8975f5c5SAndroid Build Coastguard Worker     gl::HandleAllocator allocator;
145*8975f5c5SAndroid Build Coastguard Worker 
146*8975f5c5SAndroid Build Coastguard Worker     for (int iteration = 0; iteration < 1; ++iteration)
147*8975f5c5SAndroid Build Coastguard Worker     {
148*8975f5c5SAndroid Build Coastguard Worker         allocator.reserve(3);
149*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(1u, allocator.allocate());
150*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(2u, allocator.allocate());
151*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(4u, allocator.allocate());
152*8975f5c5SAndroid Build Coastguard Worker         allocator.reset();
153*8975f5c5SAndroid Build Coastguard Worker     }
154*8975f5c5SAndroid Build Coastguard Worker }
155*8975f5c5SAndroid Build Coastguard Worker 
156*8975f5c5SAndroid Build Coastguard Worker // Tests the reset method of custom allocator works as expected.
TEST(HandleAllocatorTest,ResetAndReallocate)157*8975f5c5SAndroid Build Coastguard Worker TEST(HandleAllocatorTest, ResetAndReallocate)
158*8975f5c5SAndroid Build Coastguard Worker {
159*8975f5c5SAndroid Build Coastguard Worker     // Allocates handles - [1, 3]
160*8975f5c5SAndroid Build Coastguard Worker     gl::HandleAllocator allocator(3);
161*8975f5c5SAndroid Build Coastguard Worker     const std::unordered_set<GLuint> expectedHandles = {1, 2, 3};
162*8975f5c5SAndroid Build Coastguard Worker     std::unordered_set<GLuint> handles;
163*8975f5c5SAndroid Build Coastguard Worker 
164*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(allocator.anyHandleAvailableForAllocation(), true);
165*8975f5c5SAndroid Build Coastguard Worker     handles.insert(allocator.allocate());
166*8975f5c5SAndroid Build Coastguard Worker     handles.insert(allocator.allocate());
167*8975f5c5SAndroid Build Coastguard Worker     handles.insert(allocator.allocate());
168*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(expectedHandles, handles);
169*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(allocator.anyHandleAvailableForAllocation(), false);
170*8975f5c5SAndroid Build Coastguard Worker 
171*8975f5c5SAndroid Build Coastguard Worker     // Reset the allocator
172*8975f5c5SAndroid Build Coastguard Worker     allocator.reset();
173*8975f5c5SAndroid Build Coastguard Worker 
174*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(allocator.anyHandleAvailableForAllocation(), true);
175*8975f5c5SAndroid Build Coastguard Worker     handles.insert(allocator.allocate());
176*8975f5c5SAndroid Build Coastguard Worker     handles.insert(allocator.allocate());
177*8975f5c5SAndroid Build Coastguard Worker     handles.insert(allocator.allocate());
178*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(expectedHandles, handles);
179*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(allocator.anyHandleAvailableForAllocation(), false);
180*8975f5c5SAndroid Build Coastguard Worker }
181*8975f5c5SAndroid Build Coastguard Worker 
182*8975f5c5SAndroid Build Coastguard Worker // Covers a particular bug with reserving and allocating sub ranges.
TEST(HandleAllocatorTest,ReserveAndAllocateIterated)183*8975f5c5SAndroid Build Coastguard Worker TEST(HandleAllocatorTest, ReserveAndAllocateIterated)
184*8975f5c5SAndroid Build Coastguard Worker {
185*8975f5c5SAndroid Build Coastguard Worker     gl::HandleAllocator allocator;
186*8975f5c5SAndroid Build Coastguard Worker 
187*8975f5c5SAndroid Build Coastguard Worker     for (int iteration = 0; iteration < 3; ++iteration)
188*8975f5c5SAndroid Build Coastguard Worker     {
189*8975f5c5SAndroid Build Coastguard Worker         allocator.reserve(5);
190*8975f5c5SAndroid Build Coastguard Worker         allocator.reserve(6);
191*8975f5c5SAndroid Build Coastguard Worker         GLuint a = allocator.allocate();
192*8975f5c5SAndroid Build Coastguard Worker         GLuint b = allocator.allocate();
193*8975f5c5SAndroid Build Coastguard Worker         GLuint c = allocator.allocate();
194*8975f5c5SAndroid Build Coastguard Worker         allocator.release(c);
195*8975f5c5SAndroid Build Coastguard Worker         allocator.release(a);
196*8975f5c5SAndroid Build Coastguard Worker         allocator.release(b);
197*8975f5c5SAndroid Build Coastguard Worker         allocator.release(5);
198*8975f5c5SAndroid Build Coastguard Worker         allocator.release(6);
199*8975f5c5SAndroid Build Coastguard Worker     }
200*8975f5c5SAndroid Build Coastguard Worker }
201*8975f5c5SAndroid Build Coastguard Worker 
202*8975f5c5SAndroid Build Coastguard Worker // This test reproduces invalid heap bug when reserve resources after release.
TEST(HandleAllocatorTest,ReserveAfterReleaseBug)203*8975f5c5SAndroid Build Coastguard Worker TEST(HandleAllocatorTest, ReserveAfterReleaseBug)
204*8975f5c5SAndroid Build Coastguard Worker {
205*8975f5c5SAndroid Build Coastguard Worker     gl::HandleAllocator allocator;
206*8975f5c5SAndroid Build Coastguard Worker 
207*8975f5c5SAndroid Build Coastguard Worker     for (int iteration = 1; iteration <= 16; ++iteration)
208*8975f5c5SAndroid Build Coastguard Worker     {
209*8975f5c5SAndroid Build Coastguard Worker         allocator.allocate();
210*8975f5c5SAndroid Build Coastguard Worker     }
211*8975f5c5SAndroid Build Coastguard Worker 
212*8975f5c5SAndroid Build Coastguard Worker     allocator.release(15);
213*8975f5c5SAndroid Build Coastguard Worker     allocator.release(16);
214*8975f5c5SAndroid Build Coastguard Worker 
215*8975f5c5SAndroid Build Coastguard Worker     for (int iteration = 1; iteration <= 14; ++iteration)
216*8975f5c5SAndroid Build Coastguard Worker     {
217*8975f5c5SAndroid Build Coastguard Worker         allocator.release(iteration);
218*8975f5c5SAndroid Build Coastguard Worker     }
219*8975f5c5SAndroid Build Coastguard Worker 
220*8975f5c5SAndroid Build Coastguard Worker     allocator.reserve(1);
221*8975f5c5SAndroid Build Coastguard Worker 
222*8975f5c5SAndroid Build Coastguard Worker     allocator.allocate();
223*8975f5c5SAndroid Build Coastguard Worker }
224*8975f5c5SAndroid Build Coastguard Worker 
225*8975f5c5SAndroid Build Coastguard Worker // This test is to verify that we consolidate handle ranges when releasing a handle.
TEST(HandleAllocatorTest,ConsolidateRangeDuringRelease)226*8975f5c5SAndroid Build Coastguard Worker TEST(HandleAllocatorTest, ConsolidateRangeDuringRelease)
227*8975f5c5SAndroid Build Coastguard Worker {
228*8975f5c5SAndroid Build Coastguard Worker     gl::HandleAllocator allocator;
229*8975f5c5SAndroid Build Coastguard Worker 
230*8975f5c5SAndroid Build Coastguard Worker     // Reserve GLuint(-1)
231*8975f5c5SAndroid Build Coastguard Worker     allocator.reserve(static_cast<GLuint>(-1));
232*8975f5c5SAndroid Build Coastguard Worker     // Allocate a few others
233*8975f5c5SAndroid Build Coastguard Worker     allocator.allocate();
234*8975f5c5SAndroid Build Coastguard Worker     allocator.allocate();
235*8975f5c5SAndroid Build Coastguard Worker 
236*8975f5c5SAndroid Build Coastguard Worker     // Release GLuint(-1)
237*8975f5c5SAndroid Build Coastguard Worker     allocator.release(static_cast<GLuint>(-1));
238*8975f5c5SAndroid Build Coastguard Worker 
239*8975f5c5SAndroid Build Coastguard Worker     // Allocate one more handle.
240*8975f5c5SAndroid Build Coastguard Worker     // Since we consolidate handle ranges during a release we do not expect to get back a
241*8975f5c5SAndroid Build Coastguard Worker     // handle value of GLuint(-1).
242*8975f5c5SAndroid Build Coastguard Worker     GLuint handle = allocator.allocate();
243*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(handle, static_cast<GLuint>(-1));
244*8975f5c5SAndroid Build Coastguard Worker }
245*8975f5c5SAndroid Build Coastguard Worker 
246*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
247