xref: /aosp_15_r20/external/angle/src/libANGLE/ResourceMap_unittest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2018 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 // ResourceMap_unittest:
7*8975f5c5SAndroid Build Coastguard Worker //   Unit tests for the ResourceMap template class.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include <gtest/gtest.h>
11*8975f5c5SAndroid Build Coastguard Worker #include <map>
12*8975f5c5SAndroid Build Coastguard Worker 
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ResourceMap.h"
14*8975f5c5SAndroid Build Coastguard Worker 
15*8975f5c5SAndroid Build Coastguard Worker using namespace gl;
16*8975f5c5SAndroid Build Coastguard Worker 
17*8975f5c5SAndroid Build Coastguard Worker namespace gl
18*8975f5c5SAndroid Build Coastguard Worker {
19*8975f5c5SAndroid Build Coastguard Worker template <>
GetIDValue(int id)20*8975f5c5SAndroid Build Coastguard Worker inline GLuint GetIDValue(int id)
21*8975f5c5SAndroid Build Coastguard Worker {
22*8975f5c5SAndroid Build Coastguard Worker     return id;
23*8975f5c5SAndroid Build Coastguard Worker }
24*8975f5c5SAndroid Build Coastguard Worker template <>
GetIDValue(unsigned int id)25*8975f5c5SAndroid Build Coastguard Worker inline GLuint GetIDValue(unsigned int id)
26*8975f5c5SAndroid Build Coastguard Worker {
27*8975f5c5SAndroid Build Coastguard Worker     return id;
28*8975f5c5SAndroid Build Coastguard Worker }
29*8975f5c5SAndroid Build Coastguard Worker }  // namespace gl
30*8975f5c5SAndroid Build Coastguard Worker 
31*8975f5c5SAndroid Build Coastguard Worker namespace
32*8975f5c5SAndroid Build Coastguard Worker {
33*8975f5c5SAndroid Build Coastguard Worker // The resourceMap class uses a lock for "unsigned int" types to support this unit test.
34*8975f5c5SAndroid Build Coastguard Worker using LocklessType = int;
35*8975f5c5SAndroid Build Coastguard Worker using LockedType   = unsigned int;
36*8975f5c5SAndroid Build Coastguard Worker 
37*8975f5c5SAndroid Build Coastguard Worker template <typename T>
AssignAndErase()38*8975f5c5SAndroid Build Coastguard Worker void AssignAndErase()
39*8975f5c5SAndroid Build Coastguard Worker {
40*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t kSize = 300;
41*8975f5c5SAndroid Build Coastguard Worker     ResourceMap<size_t, T> resourceMap;
42*8975f5c5SAndroid Build Coastguard Worker     std::vector<size_t> objects(kSize, 1);
43*8975f5c5SAndroid Build Coastguard Worker     for (size_t index = 0; index < kSize; ++index)
44*8975f5c5SAndroid Build Coastguard Worker     {
45*8975f5c5SAndroid Build Coastguard Worker         resourceMap.assign(index + 1, &objects[index]);
46*8975f5c5SAndroid Build Coastguard Worker     }
47*8975f5c5SAndroid Build Coastguard Worker 
48*8975f5c5SAndroid Build Coastguard Worker     for (size_t index = 0; index < kSize; ++index)
49*8975f5c5SAndroid Build Coastguard Worker     {
50*8975f5c5SAndroid Build Coastguard Worker         size_t *found = nullptr;
51*8975f5c5SAndroid Build Coastguard Worker         ASSERT_TRUE(resourceMap.erase(index + 1, &found));
52*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(&objects[index], found);
53*8975f5c5SAndroid Build Coastguard Worker     }
54*8975f5c5SAndroid Build Coastguard Worker 
55*8975f5c5SAndroid Build Coastguard Worker     ASSERT_TRUE(UnsafeResourceMapIter(resourceMap).empty());
56*8975f5c5SAndroid Build Coastguard Worker }
57*8975f5c5SAndroid Build Coastguard Worker 
58*8975f5c5SAndroid Build Coastguard Worker // Tests assigning slots in the map and then deleting elements.
TEST(ResourceMapTest,AssignAndEraseLockless)59*8975f5c5SAndroid Build Coastguard Worker TEST(ResourceMapTest, AssignAndEraseLockless)
60*8975f5c5SAndroid Build Coastguard Worker {
61*8975f5c5SAndroid Build Coastguard Worker     AssignAndErase<LocklessType>();
62*8975f5c5SAndroid Build Coastguard Worker }
63*8975f5c5SAndroid Build Coastguard Worker // Tests assigning slots in the map and then deleting elements.
TEST(ResourceMapTest,AssignAndEraseLocked)64*8975f5c5SAndroid Build Coastguard Worker TEST(ResourceMapTest, AssignAndEraseLocked)
65*8975f5c5SAndroid Build Coastguard Worker {
66*8975f5c5SAndroid Build Coastguard Worker     AssignAndErase<LockedType>();
67*8975f5c5SAndroid Build Coastguard Worker }
68*8975f5c5SAndroid Build Coastguard Worker 
69*8975f5c5SAndroid Build Coastguard Worker template <typename T>
AssignAndClear()70*8975f5c5SAndroid Build Coastguard Worker void AssignAndClear()
71*8975f5c5SAndroid Build Coastguard Worker {
72*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t kSize = 280;
73*8975f5c5SAndroid Build Coastguard Worker     ResourceMap<size_t, T> resourceMap;
74*8975f5c5SAndroid Build Coastguard Worker     std::vector<size_t> objects(kSize, 1);
75*8975f5c5SAndroid Build Coastguard Worker     for (size_t index = 0; index < kSize; ++index)
76*8975f5c5SAndroid Build Coastguard Worker     {
77*8975f5c5SAndroid Build Coastguard Worker         resourceMap.assign(index + 1, &objects[index]);
78*8975f5c5SAndroid Build Coastguard Worker     }
79*8975f5c5SAndroid Build Coastguard Worker 
80*8975f5c5SAndroid Build Coastguard Worker     resourceMap.clear();
81*8975f5c5SAndroid Build Coastguard Worker     ASSERT_TRUE(UnsafeResourceMapIter(resourceMap).empty());
82*8975f5c5SAndroid Build Coastguard Worker }
83*8975f5c5SAndroid Build Coastguard Worker 
84*8975f5c5SAndroid Build Coastguard Worker // Tests assigning slots in the map and then using clear() to free it.
TEST(ResourceMapTest,AssignAndClearLockless)85*8975f5c5SAndroid Build Coastguard Worker TEST(ResourceMapTest, AssignAndClearLockless)
86*8975f5c5SAndroid Build Coastguard Worker {
87*8975f5c5SAndroid Build Coastguard Worker     AssignAndClear<LocklessType>();
88*8975f5c5SAndroid Build Coastguard Worker }
89*8975f5c5SAndroid Build Coastguard Worker // Tests assigning slots in the map and then using clear() to free it.
TEST(ResourceMapTest,AssignAndClearLocked)90*8975f5c5SAndroid Build Coastguard Worker TEST(ResourceMapTest, AssignAndClearLocked)
91*8975f5c5SAndroid Build Coastguard Worker {
92*8975f5c5SAndroid Build Coastguard Worker     AssignAndClear<LockedType>();
93*8975f5c5SAndroid Build Coastguard Worker }
94*8975f5c5SAndroid Build Coastguard Worker 
95*8975f5c5SAndroid Build Coastguard Worker template <typename T>
BigGrowth()96*8975f5c5SAndroid Build Coastguard Worker void BigGrowth()
97*8975f5c5SAndroid Build Coastguard Worker {
98*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t kSize = 8;
99*8975f5c5SAndroid Build Coastguard Worker 
100*8975f5c5SAndroid Build Coastguard Worker     ResourceMap<size_t, T> resourceMap;
101*8975f5c5SAndroid Build Coastguard Worker     std::vector<size_t> objects;
102*8975f5c5SAndroid Build Coastguard Worker 
103*8975f5c5SAndroid Build Coastguard Worker     for (size_t index = 0; index < kSize; ++index)
104*8975f5c5SAndroid Build Coastguard Worker     {
105*8975f5c5SAndroid Build Coastguard Worker         objects.push_back(index);
106*8975f5c5SAndroid Build Coastguard Worker     }
107*8975f5c5SAndroid Build Coastguard Worker 
108*8975f5c5SAndroid Build Coastguard Worker     // Assign a large value.
109*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t kLargeIndex = 128;
110*8975f5c5SAndroid Build Coastguard Worker     objects.push_back(kLargeIndex);
111*8975f5c5SAndroid Build Coastguard Worker 
112*8975f5c5SAndroid Build Coastguard Worker     for (size_t &object : objects)
113*8975f5c5SAndroid Build Coastguard Worker     {
114*8975f5c5SAndroid Build Coastguard Worker         resourceMap.assign(object, &object);
115*8975f5c5SAndroid Build Coastguard Worker     }
116*8975f5c5SAndroid Build Coastguard Worker 
117*8975f5c5SAndroid Build Coastguard Worker     for (size_t object : objects)
118*8975f5c5SAndroid Build Coastguard Worker     {
119*8975f5c5SAndroid Build Coastguard Worker         size_t *found = nullptr;
120*8975f5c5SAndroid Build Coastguard Worker         ASSERT_TRUE(resourceMap.erase(object, &found));
121*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(object, *found);
122*8975f5c5SAndroid Build Coastguard Worker     }
123*8975f5c5SAndroid Build Coastguard Worker 
124*8975f5c5SAndroid Build Coastguard Worker     ASSERT_TRUE(UnsafeResourceMapIter(resourceMap).empty());
125*8975f5c5SAndroid Build Coastguard Worker }
126*8975f5c5SAndroid Build Coastguard Worker 
127*8975f5c5SAndroid Build Coastguard Worker // Tests growing a map more than double the size.
TEST(ResourceMapTest,BigGrowthLockless)128*8975f5c5SAndroid Build Coastguard Worker TEST(ResourceMapTest, BigGrowthLockless)
129*8975f5c5SAndroid Build Coastguard Worker {
130*8975f5c5SAndroid Build Coastguard Worker     BigGrowth<LocklessType>();
131*8975f5c5SAndroid Build Coastguard Worker }
132*8975f5c5SAndroid Build Coastguard Worker // Tests growing a map more than double the size.
TEST(ResourceMapTest,BigGrowthLocked)133*8975f5c5SAndroid Build Coastguard Worker TEST(ResourceMapTest, BigGrowthLocked)
134*8975f5c5SAndroid Build Coastguard Worker {
135*8975f5c5SAndroid Build Coastguard Worker     BigGrowth<LockedType>();
136*8975f5c5SAndroid Build Coastguard Worker }
137*8975f5c5SAndroid Build Coastguard Worker 
138*8975f5c5SAndroid Build Coastguard Worker template <typename T>
QueryUnassigned()139*8975f5c5SAndroid Build Coastguard Worker void QueryUnassigned()
140*8975f5c5SAndroid Build Coastguard Worker {
141*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t kSize        = 8;
142*8975f5c5SAndroid Build Coastguard Worker     constexpr T kZero             = 0;
143*8975f5c5SAndroid Build Coastguard Worker     constexpr T kIdInFlatRange    = 10;
144*8975f5c5SAndroid Build Coastguard Worker     constexpr T kIdOutOfFlatRange = 500;
145*8975f5c5SAndroid Build Coastguard Worker 
146*8975f5c5SAndroid Build Coastguard Worker     ResourceMap<size_t, T> resourceMap;
147*8975f5c5SAndroid Build Coastguard Worker     std::vector<size_t> objects;
148*8975f5c5SAndroid Build Coastguard Worker 
149*8975f5c5SAndroid Build Coastguard Worker     for (size_t index = 0; index < kSize; ++index)
150*8975f5c5SAndroid Build Coastguard Worker     {
151*8975f5c5SAndroid Build Coastguard Worker         objects.push_back(index);
152*8975f5c5SAndroid Build Coastguard Worker     }
153*8975f5c5SAndroid Build Coastguard Worker 
154*8975f5c5SAndroid Build Coastguard Worker     ASSERT_FALSE(resourceMap.contains(kZero));
155*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(nullptr, resourceMap.query(kZero));
156*8975f5c5SAndroid Build Coastguard Worker     ASSERT_FALSE(resourceMap.contains(kIdOutOfFlatRange));
157*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(nullptr, resourceMap.query(kIdOutOfFlatRange));
158*8975f5c5SAndroid Build Coastguard Worker 
159*8975f5c5SAndroid Build Coastguard Worker     for (size_t &object : objects)
160*8975f5c5SAndroid Build Coastguard Worker     {
161*8975f5c5SAndroid Build Coastguard Worker         resourceMap.assign(object, &object);
162*8975f5c5SAndroid Build Coastguard Worker     }
163*8975f5c5SAndroid Build Coastguard Worker 
164*8975f5c5SAndroid Build Coastguard Worker     ASSERT_FALSE(UnsafeResourceMapIter(resourceMap).empty());
165*8975f5c5SAndroid Build Coastguard Worker 
166*8975f5c5SAndroid Build Coastguard Worker     for (size_t &object : objects)
167*8975f5c5SAndroid Build Coastguard Worker     {
168*8975f5c5SAndroid Build Coastguard Worker         ASSERT_TRUE(resourceMap.contains(object));
169*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(&object, resourceMap.query(object));
170*8975f5c5SAndroid Build Coastguard Worker     }
171*8975f5c5SAndroid Build Coastguard Worker 
172*8975f5c5SAndroid Build Coastguard Worker     ASSERT_FALSE(resourceMap.contains(kIdInFlatRange));
173*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(nullptr, resourceMap.query(kIdInFlatRange));
174*8975f5c5SAndroid Build Coastguard Worker     ASSERT_FALSE(resourceMap.contains(kIdOutOfFlatRange));
175*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(nullptr, resourceMap.query(kIdOutOfFlatRange));
176*8975f5c5SAndroid Build Coastguard Worker 
177*8975f5c5SAndroid Build Coastguard Worker     for (size_t object : objects)
178*8975f5c5SAndroid Build Coastguard Worker     {
179*8975f5c5SAndroid Build Coastguard Worker         size_t *found = nullptr;
180*8975f5c5SAndroid Build Coastguard Worker         ASSERT_TRUE(resourceMap.erase(object, &found));
181*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(object, *found);
182*8975f5c5SAndroid Build Coastguard Worker     }
183*8975f5c5SAndroid Build Coastguard Worker 
184*8975f5c5SAndroid Build Coastguard Worker     ASSERT_TRUE(UnsafeResourceMapIter(resourceMap).empty());
185*8975f5c5SAndroid Build Coastguard Worker 
186*8975f5c5SAndroid Build Coastguard Worker     ASSERT_FALSE(resourceMap.contains(kZero));
187*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(nullptr, resourceMap.query(kZero));
188*8975f5c5SAndroid Build Coastguard Worker     ASSERT_FALSE(resourceMap.contains(kIdOutOfFlatRange));
189*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(nullptr, resourceMap.query(kIdOutOfFlatRange));
190*8975f5c5SAndroid Build Coastguard Worker }
191*8975f5c5SAndroid Build Coastguard Worker 
192*8975f5c5SAndroid Build Coastguard Worker // Tests querying unassigned or erased values.
TEST(ResourceMapTest,QueryUnassignedLockless)193*8975f5c5SAndroid Build Coastguard Worker TEST(ResourceMapTest, QueryUnassignedLockless)
194*8975f5c5SAndroid Build Coastguard Worker {
195*8975f5c5SAndroid Build Coastguard Worker     QueryUnassigned<LocklessType>();
196*8975f5c5SAndroid Build Coastguard Worker }
197*8975f5c5SAndroid Build Coastguard Worker // Tests querying unassigned or erased values.
TEST(ResourceMapTest,QueryUnassignedLocked)198*8975f5c5SAndroid Build Coastguard Worker TEST(ResourceMapTest, QueryUnassignedLocked)
199*8975f5c5SAndroid Build Coastguard Worker {
200*8975f5c5SAndroid Build Coastguard Worker     QueryUnassigned<LockedType>();
201*8975f5c5SAndroid Build Coastguard Worker }
202*8975f5c5SAndroid Build Coastguard Worker 
ConcurrentAccess(size_t iterations,size_t idCycleSize)203*8975f5c5SAndroid Build Coastguard Worker void ConcurrentAccess(size_t iterations, size_t idCycleSize)
204*8975f5c5SAndroid Build Coastguard Worker {
205*8975f5c5SAndroid Build Coastguard Worker     if (std::is_same_v<ResourceMapMutex, angle::NoOpMutex>)
206*8975f5c5SAndroid Build Coastguard Worker     {
207*8975f5c5SAndroid Build Coastguard Worker         GTEST_SKIP() << "Test skipped: Locking is disabled in build.";
208*8975f5c5SAndroid Build Coastguard Worker     }
209*8975f5c5SAndroid Build Coastguard Worker 
210*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t kThreadCount = 13;
211*8975f5c5SAndroid Build Coastguard Worker 
212*8975f5c5SAndroid Build Coastguard Worker     ResourceMap<size_t, LockedType> resourceMap;
213*8975f5c5SAndroid Build Coastguard Worker 
214*8975f5c5SAndroid Build Coastguard Worker     std::array<std::thread, kThreadCount> threads;
215*8975f5c5SAndroid Build Coastguard Worker     std::array<std::map<LockedType, size_t>, kThreadCount> insertedIds;
216*8975f5c5SAndroid Build Coastguard Worker 
217*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < kThreadCount; ++i)
218*8975f5c5SAndroid Build Coastguard Worker     {
219*8975f5c5SAndroid Build Coastguard Worker         threads[i] = std::thread([&, i]() {
220*8975f5c5SAndroid Build Coastguard Worker             // Each thread manipulates a different set of ids.  The resource map guarantees that the
221*8975f5c5SAndroid Build Coastguard Worker             // data structure itself is thread-safe, not accesses to the same id.
222*8975f5c5SAndroid Build Coastguard Worker             for (size_t j = 0; j < iterations; ++j)
223*8975f5c5SAndroid Build Coastguard Worker             {
224*8975f5c5SAndroid Build Coastguard Worker                 const LockedType id = (j % (idCycleSize / kThreadCount)) * kThreadCount + i;
225*8975f5c5SAndroid Build Coastguard Worker 
226*8975f5c5SAndroid Build Coastguard Worker                 ASSERT_LE(id, 0xFFFFu);
227*8975f5c5SAndroid Build Coastguard Worker                 ASSERT_LE(j, 0xFFFFu);
228*8975f5c5SAndroid Build Coastguard Worker                 const size_t value = id | j << 16;
229*8975f5c5SAndroid Build Coastguard Worker 
230*8975f5c5SAndroid Build Coastguard Worker                 size_t *valuePtr = reinterpret_cast<size_t *>(value);
231*8975f5c5SAndroid Build Coastguard Worker 
232*8975f5c5SAndroid Build Coastguard Worker                 const size_t *queryResult = resourceMap.query(id);
233*8975f5c5SAndroid Build Coastguard Worker                 const bool containsResult = resourceMap.contains(id);
234*8975f5c5SAndroid Build Coastguard Worker 
235*8975f5c5SAndroid Build Coastguard Worker                 const bool expectContains = insertedIds[i].count(id) > 0;
236*8975f5c5SAndroid Build Coastguard Worker                 if (expectContains)
237*8975f5c5SAndroid Build Coastguard Worker                 {
238*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_TRUE(containsResult);
239*8975f5c5SAndroid Build Coastguard Worker                     const LockedType queryResultInt =
240*8975f5c5SAndroid Build Coastguard Worker                         static_cast<LockedType>(reinterpret_cast<size_t>(queryResult) & 0xFFFF);
241*8975f5c5SAndroid Build Coastguard Worker                     const size_t queryResultIteration = reinterpret_cast<size_t>(queryResult) >> 16;
242*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_EQ(queryResultInt, id);
243*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_LT(queryResultIteration, j);
244*8975f5c5SAndroid Build Coastguard Worker 
245*8975f5c5SAndroid Build Coastguard Worker                     size_t *erasedValue = nullptr;
246*8975f5c5SAndroid Build Coastguard Worker                     const bool erased   = resourceMap.erase(id, &erasedValue);
247*8975f5c5SAndroid Build Coastguard Worker 
248*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_TRUE(erased);
249*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_EQ(erasedValue, queryResult);
250*8975f5c5SAndroid Build Coastguard Worker 
251*8975f5c5SAndroid Build Coastguard Worker                     insertedIds[i].erase(id);
252*8975f5c5SAndroid Build Coastguard Worker                 }
253*8975f5c5SAndroid Build Coastguard Worker                 else
254*8975f5c5SAndroid Build Coastguard Worker                 {
255*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_FALSE(containsResult);
256*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_EQ(queryResult, nullptr);
257*8975f5c5SAndroid Build Coastguard Worker 
258*8975f5c5SAndroid Build Coastguard Worker                     resourceMap.assign(id, valuePtr);
259*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_TRUE(resourceMap.contains(id));
260*8975f5c5SAndroid Build Coastguard Worker 
261*8975f5c5SAndroid Build Coastguard Worker                     ASSERT_TRUE(insertedIds[i].count(id) == 0);
262*8975f5c5SAndroid Build Coastguard Worker                     insertedIds[i][id] = value;
263*8975f5c5SAndroid Build Coastguard Worker                 }
264*8975f5c5SAndroid Build Coastguard Worker             }
265*8975f5c5SAndroid Build Coastguard Worker         });
266*8975f5c5SAndroid Build Coastguard Worker     }
267*8975f5c5SAndroid Build Coastguard Worker 
268*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < kThreadCount; ++i)
269*8975f5c5SAndroid Build Coastguard Worker     {
270*8975f5c5SAndroid Build Coastguard Worker         threads[i].join();
271*8975f5c5SAndroid Build Coastguard Worker     }
272*8975f5c5SAndroid Build Coastguard Worker 
273*8975f5c5SAndroid Build Coastguard Worker     // Verify that every value that is expected to be there is actually there
274*8975f5c5SAndroid Build Coastguard Worker     std::map<size_t, size_t> allIds;
275*8975f5c5SAndroid Build Coastguard Worker     size_t allIdsPrevSize = 0;
276*8975f5c5SAndroid Build Coastguard Worker 
277*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < kThreadCount; ++i)
278*8975f5c5SAndroid Build Coastguard Worker     {
279*8975f5c5SAndroid Build Coastguard Worker         // Merge all the sets together.  The sets are disjoint, which is verified by the ASSERT_EQ.
280*8975f5c5SAndroid Build Coastguard Worker         allIds.insert(insertedIds[i].begin(), insertedIds[i].end());
281*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(allIds.size(), allIdsPrevSize + insertedIds[i].size());
282*8975f5c5SAndroid Build Coastguard Worker         allIdsPrevSize = allIds.size();
283*8975f5c5SAndroid Build Coastguard Worker 
284*8975f5c5SAndroid Build Coastguard Worker         // Make sure every id that is expected to be there is actually there.
285*8975f5c5SAndroid Build Coastguard Worker         for (auto &idValue : insertedIds[i])
286*8975f5c5SAndroid Build Coastguard Worker         {
287*8975f5c5SAndroid Build Coastguard Worker             EXPECT_TRUE(resourceMap.contains(idValue.first));
288*8975f5c5SAndroid Build Coastguard Worker             EXPECT_EQ(resourceMap.query(idValue.first), reinterpret_cast<size_t *>(idValue.second));
289*8975f5c5SAndroid Build Coastguard Worker         }
290*8975f5c5SAndroid Build Coastguard Worker     }
291*8975f5c5SAndroid Build Coastguard Worker 
292*8975f5c5SAndroid Build Coastguard Worker     // Verify that every value that is NOT expected to be there isn't actually there
293*8975f5c5SAndroid Build Coastguard Worker     for (auto &idValue : UnsafeResourceMapIter(resourceMap))
294*8975f5c5SAndroid Build Coastguard Worker     {
295*8975f5c5SAndroid Build Coastguard Worker         EXPECT_TRUE(allIds.count(idValue.first) == 1);
296*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(idValue.second, reinterpret_cast<size_t *>(allIds[idValue.first]));
297*8975f5c5SAndroid Build Coastguard Worker     }
298*8975f5c5SAndroid Build Coastguard Worker 
299*8975f5c5SAndroid Build Coastguard Worker     resourceMap.clear();
300*8975f5c5SAndroid Build Coastguard Worker }
301*8975f5c5SAndroid Build Coastguard Worker 
302*8975f5c5SAndroid Build Coastguard Worker // Tests that concurrent access to thread-safe resource maps works for small ids that are mostly in
303*8975f5c5SAndroid Build Coastguard Worker // the flat map range.
TEST(ResourceMapTest,ConcurrentAccessSmallIds)304*8975f5c5SAndroid Build Coastguard Worker TEST(ResourceMapTest, ConcurrentAccessSmallIds)
305*8975f5c5SAndroid Build Coastguard Worker {
306*8975f5c5SAndroid Build Coastguard Worker     ConcurrentAccess(50'000, 128);
307*8975f5c5SAndroid Build Coastguard Worker }
308*8975f5c5SAndroid Build Coastguard Worker // Tests that concurrent access to thread-safe resource maps works for a wider range of ids.
TEST(ResourceMapTest,ConcurrentAccessLargeIds)309*8975f5c5SAndroid Build Coastguard Worker TEST(ResourceMapTest, ConcurrentAccessLargeIds)
310*8975f5c5SAndroid Build Coastguard Worker {
311*8975f5c5SAndroid Build Coastguard Worker     ConcurrentAccess(10'000, 20'000);
312*8975f5c5SAndroid Build Coastguard Worker }
313*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
314