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