1*bc0d697dSNico Weber #include "test_helpers.h"
2*bc0d697dSNico Weber #include "xray_segmented_array.h"
3*bc0d697dSNico Weber #include "gmock/gmock.h"
4*bc0d697dSNico Weber #include "gtest/gtest.h"
5*bc0d697dSNico Weber #include <algorithm>
6*bc0d697dSNico Weber #include <numeric>
7*bc0d697dSNico Weber #include <vector>
8*bc0d697dSNico Weber
9*bc0d697dSNico Weber namespace __xray {
10*bc0d697dSNico Weber namespace {
11*bc0d697dSNico Weber
12*bc0d697dSNico Weber using ::testing::SizeIs;
13*bc0d697dSNico Weber
14*bc0d697dSNico Weber struct TestData {
15*bc0d697dSNico Weber s64 First;
16*bc0d697dSNico Weber s64 Second;
17*bc0d697dSNico Weber
18*bc0d697dSNico Weber // Need a constructor for emplace operations.
TestData__xray::__anon479df9900111::TestData19*bc0d697dSNico Weber TestData(s64 F, s64 S) : First(F), Second(S) {}
20*bc0d697dSNico Weber };
21*bc0d697dSNico Weber
PrintTo(const TestData & D,std::ostream * OS)22*bc0d697dSNico Weber void PrintTo(const TestData &D, std::ostream *OS) {
23*bc0d697dSNico Weber *OS << "{ " << D.First << ", " << D.Second << " }";
24*bc0d697dSNico Weber }
25*bc0d697dSNico Weber
TEST(SegmentedArrayTest,ConstructWithAllocators)26*bc0d697dSNico Weber TEST(SegmentedArrayTest, ConstructWithAllocators) {
27*bc0d697dSNico Weber using AllocatorType = typename Array<TestData>::AllocatorType;
28*bc0d697dSNico Weber AllocatorType A(1 << 4);
29*bc0d697dSNico Weber Array<TestData> Data(A);
30*bc0d697dSNico Weber (void)Data;
31*bc0d697dSNico Weber }
32*bc0d697dSNico Weber
TEST(SegmentedArrayTest,ConstructAndPopulate)33*bc0d697dSNico Weber TEST(SegmentedArrayTest, ConstructAndPopulate) {
34*bc0d697dSNico Weber using AllocatorType = typename Array<TestData>::AllocatorType;
35*bc0d697dSNico Weber AllocatorType A(1 << 4);
36*bc0d697dSNico Weber Array<TestData> data(A);
37*bc0d697dSNico Weber ASSERT_NE(data.Append(TestData{0, 0}), nullptr);
38*bc0d697dSNico Weber ASSERT_NE(data.Append(TestData{1, 1}), nullptr);
39*bc0d697dSNico Weber ASSERT_EQ(data.size(), 2u);
40*bc0d697dSNico Weber }
41*bc0d697dSNico Weber
TEST(SegmentedArrayTest,ConstructPopulateAndLookup)42*bc0d697dSNico Weber TEST(SegmentedArrayTest, ConstructPopulateAndLookup) {
43*bc0d697dSNico Weber using AllocatorType = typename Array<TestData>::AllocatorType;
44*bc0d697dSNico Weber AllocatorType A(1 << 4);
45*bc0d697dSNico Weber Array<TestData> data(A);
46*bc0d697dSNico Weber ASSERT_NE(data.Append(TestData{0, 1}), nullptr);
47*bc0d697dSNico Weber ASSERT_EQ(data.size(), 1u);
48*bc0d697dSNico Weber ASSERT_EQ(data[0].First, 0);
49*bc0d697dSNico Weber ASSERT_EQ(data[0].Second, 1);
50*bc0d697dSNico Weber }
51*bc0d697dSNico Weber
TEST(SegmentedArrayTest,PopulateWithMoreElements)52*bc0d697dSNico Weber TEST(SegmentedArrayTest, PopulateWithMoreElements) {
53*bc0d697dSNico Weber using AllocatorType = typename Array<TestData>::AllocatorType;
54*bc0d697dSNico Weber AllocatorType A(1 << 24);
55*bc0d697dSNico Weber Array<TestData> data(A);
56*bc0d697dSNico Weber static const auto kMaxElements = 100u;
57*bc0d697dSNico Weber for (auto I = 0u; I < kMaxElements; ++I) {
58*bc0d697dSNico Weber ASSERT_NE(data.Append(TestData{I, I + 1}), nullptr);
59*bc0d697dSNico Weber }
60*bc0d697dSNico Weber ASSERT_EQ(data.size(), kMaxElements);
61*bc0d697dSNico Weber for (auto I = 0u; I < kMaxElements; ++I) {
62*bc0d697dSNico Weber ASSERT_EQ(data[I].First, I);
63*bc0d697dSNico Weber ASSERT_EQ(data[I].Second, I + 1);
64*bc0d697dSNico Weber }
65*bc0d697dSNico Weber }
66*bc0d697dSNico Weber
TEST(SegmentedArrayTest,AppendEmplace)67*bc0d697dSNico Weber TEST(SegmentedArrayTest, AppendEmplace) {
68*bc0d697dSNico Weber using AllocatorType = typename Array<TestData>::AllocatorType;
69*bc0d697dSNico Weber AllocatorType A(1 << 4);
70*bc0d697dSNico Weber Array<TestData> data(A);
71*bc0d697dSNico Weber ASSERT_NE(data.AppendEmplace(1, 1), nullptr);
72*bc0d697dSNico Weber ASSERT_EQ(data[0].First, 1);
73*bc0d697dSNico Weber ASSERT_EQ(data[0].Second, 1);
74*bc0d697dSNico Weber }
75*bc0d697dSNico Weber
TEST(SegmentedArrayTest,AppendAndTrim)76*bc0d697dSNico Weber TEST(SegmentedArrayTest, AppendAndTrim) {
77*bc0d697dSNico Weber using AllocatorType = typename Array<TestData>::AllocatorType;
78*bc0d697dSNico Weber AllocatorType A(1 << 4);
79*bc0d697dSNico Weber Array<TestData> data(A);
80*bc0d697dSNico Weber ASSERT_NE(data.AppendEmplace(1, 1), nullptr);
81*bc0d697dSNico Weber ASSERT_EQ(data.size(), 1u);
82*bc0d697dSNico Weber data.trim(1);
83*bc0d697dSNico Weber ASSERT_EQ(data.size(), 0u);
84*bc0d697dSNico Weber ASSERT_TRUE(data.empty());
85*bc0d697dSNico Weber }
86*bc0d697dSNico Weber
TEST(SegmentedArrayTest,IteratorAdvance)87*bc0d697dSNico Weber TEST(SegmentedArrayTest, IteratorAdvance) {
88*bc0d697dSNico Weber using AllocatorType = typename Array<TestData>::AllocatorType;
89*bc0d697dSNico Weber AllocatorType A(1 << 4);
90*bc0d697dSNico Weber Array<TestData> data(A);
91*bc0d697dSNico Weber ASSERT_TRUE(data.empty());
92*bc0d697dSNico Weber ASSERT_EQ(data.begin(), data.end());
93*bc0d697dSNico Weber auto I0 = data.begin();
94*bc0d697dSNico Weber ASSERT_EQ(I0++, data.begin());
95*bc0d697dSNico Weber ASSERT_NE(I0, data.begin());
96*bc0d697dSNico Weber for (const auto &D : data) {
97*bc0d697dSNico Weber (void)D;
98*bc0d697dSNico Weber FAIL();
99*bc0d697dSNico Weber }
100*bc0d697dSNico Weber ASSERT_NE(data.AppendEmplace(1, 1), nullptr);
101*bc0d697dSNico Weber ASSERT_EQ(data.size(), 1u);
102*bc0d697dSNico Weber ASSERT_NE(data.begin(), data.end());
103*bc0d697dSNico Weber auto &D0 = *data.begin();
104*bc0d697dSNico Weber ASSERT_EQ(D0.First, 1);
105*bc0d697dSNico Weber ASSERT_EQ(D0.Second, 1);
106*bc0d697dSNico Weber }
107*bc0d697dSNico Weber
TEST(SegmentedArrayTest,IteratorRetreat)108*bc0d697dSNico Weber TEST(SegmentedArrayTest, IteratorRetreat) {
109*bc0d697dSNico Weber using AllocatorType = typename Array<TestData>::AllocatorType;
110*bc0d697dSNico Weber AllocatorType A(1 << 4);
111*bc0d697dSNico Weber Array<TestData> data(A);
112*bc0d697dSNico Weber ASSERT_TRUE(data.empty());
113*bc0d697dSNico Weber ASSERT_EQ(data.begin(), data.end());
114*bc0d697dSNico Weber ASSERT_NE(data.AppendEmplace(1, 1), nullptr);
115*bc0d697dSNico Weber ASSERT_EQ(data.size(), 1u);
116*bc0d697dSNico Weber ASSERT_NE(data.begin(), data.end());
117*bc0d697dSNico Weber auto &D0 = *data.begin();
118*bc0d697dSNico Weber ASSERT_EQ(D0.First, 1);
119*bc0d697dSNico Weber ASSERT_EQ(D0.Second, 1);
120*bc0d697dSNico Weber
121*bc0d697dSNico Weber auto I0 = data.end();
122*bc0d697dSNico Weber ASSERT_EQ(I0--, data.end());
123*bc0d697dSNico Weber ASSERT_NE(I0, data.end());
124*bc0d697dSNico Weber ASSERT_EQ(I0, data.begin());
125*bc0d697dSNico Weber ASSERT_EQ(I0->First, 1);
126*bc0d697dSNico Weber ASSERT_EQ(I0->Second, 1);
127*bc0d697dSNico Weber }
128*bc0d697dSNico Weber
TEST(SegmentedArrayTest,IteratorTrimBehaviour)129*bc0d697dSNico Weber TEST(SegmentedArrayTest, IteratorTrimBehaviour) {
130*bc0d697dSNico Weber using AllocatorType = typename Array<TestData>::AllocatorType;
131*bc0d697dSNico Weber AllocatorType A(1 << 20);
132*bc0d697dSNico Weber Array<TestData> Data(A);
133*bc0d697dSNico Weber ASSERT_TRUE(Data.empty());
134*bc0d697dSNico Weber auto I0Begin = Data.begin(), I0End = Data.end();
135*bc0d697dSNico Weber // Add enough elements in Data to have more than one chunk.
136*bc0d697dSNico Weber constexpr auto Segment = Array<TestData>::SegmentSize;
137*bc0d697dSNico Weber constexpr auto SegmentX2 = Segment * 2;
138*bc0d697dSNico Weber for (auto i = SegmentX2; i > 0u; --i) {
139*bc0d697dSNico Weber Data.AppendEmplace(static_cast<s64>(i), static_cast<s64>(i));
140*bc0d697dSNico Weber }
141*bc0d697dSNico Weber ASSERT_EQ(Data.size(), SegmentX2);
142*bc0d697dSNico Weber {
143*bc0d697dSNico Weber auto &Back = Data.back();
144*bc0d697dSNico Weber ASSERT_EQ(Back.First, 1);
145*bc0d697dSNico Weber ASSERT_EQ(Back.Second, 1);
146*bc0d697dSNico Weber }
147*bc0d697dSNico Weber
148*bc0d697dSNico Weber // Trim one chunk's elements worth.
149*bc0d697dSNico Weber Data.trim(Segment);
150*bc0d697dSNico Weber ASSERT_EQ(Data.size(), Segment);
151*bc0d697dSNico Weber
152*bc0d697dSNico Weber // Check that we are still able to access 'back' properly.
153*bc0d697dSNico Weber {
154*bc0d697dSNico Weber auto &Back = Data.back();
155*bc0d697dSNico Weber ASSERT_EQ(Back.First, static_cast<s64>(Segment + 1));
156*bc0d697dSNico Weber ASSERT_EQ(Back.Second, static_cast<s64>(Segment + 1));
157*bc0d697dSNico Weber }
158*bc0d697dSNico Weber
159*bc0d697dSNico Weber // Then trim until it's empty.
160*bc0d697dSNico Weber Data.trim(Segment);
161*bc0d697dSNico Weber ASSERT_TRUE(Data.empty());
162*bc0d697dSNico Weber
163*bc0d697dSNico Weber // Here our iterators should be the same.
164*bc0d697dSNico Weber auto I1Begin = Data.begin(), I1End = Data.end();
165*bc0d697dSNico Weber EXPECT_EQ(I0Begin, I1Begin);
166*bc0d697dSNico Weber EXPECT_EQ(I0End, I1End);
167*bc0d697dSNico Weber
168*bc0d697dSNico Weber // Then we ensure that adding elements back works just fine.
169*bc0d697dSNico Weber for (auto i = SegmentX2; i > 0u; --i) {
170*bc0d697dSNico Weber Data.AppendEmplace(static_cast<s64>(i), static_cast<s64>(i));
171*bc0d697dSNico Weber }
172*bc0d697dSNico Weber EXPECT_EQ(Data.size(), SegmentX2);
173*bc0d697dSNico Weber }
174*bc0d697dSNico Weber
TEST(SegmentedArrayTest,HandleExhaustedAllocator)175*bc0d697dSNico Weber TEST(SegmentedArrayTest, HandleExhaustedAllocator) {
176*bc0d697dSNico Weber using AllocatorType = typename Array<TestData>::AllocatorType;
177*bc0d697dSNico Weber constexpr auto Segment = Array<TestData>::SegmentSize;
178*bc0d697dSNico Weber constexpr auto MaxElements = Array<TestData>::ElementsPerSegment;
179*bc0d697dSNico Weber AllocatorType A(Segment);
180*bc0d697dSNico Weber Array<TestData> Data(A);
181*bc0d697dSNico Weber for (auto i = MaxElements; i > 0u; --i)
182*bc0d697dSNico Weber EXPECT_NE(Data.AppendEmplace(static_cast<s64>(i), static_cast<s64>(i)),
183*bc0d697dSNico Weber nullptr);
184*bc0d697dSNico Weber EXPECT_EQ(Data.AppendEmplace(0, 0), nullptr);
185*bc0d697dSNico Weber EXPECT_THAT(Data, SizeIs(MaxElements));
186*bc0d697dSNico Weber
187*bc0d697dSNico Weber // Trimming more elements than there are in the container should be fine.
188*bc0d697dSNico Weber Data.trim(MaxElements + 1);
189*bc0d697dSNico Weber EXPECT_THAT(Data, SizeIs(0u));
190*bc0d697dSNico Weber }
191*bc0d697dSNico Weber
192*bc0d697dSNico Weber struct ShadowStackEntry {
193*bc0d697dSNico Weber uint64_t EntryTSC = 0;
194*bc0d697dSNico Weber uint64_t *NodePtr = nullptr;
ShadowStackEntry__xray::__anon479df9900111::ShadowStackEntry195*bc0d697dSNico Weber ShadowStackEntry(uint64_t T, uint64_t *N) : EntryTSC(T), NodePtr(N) {}
196*bc0d697dSNico Weber };
197*bc0d697dSNico Weber
TEST(SegmentedArrayTest,SimulateStackBehaviour)198*bc0d697dSNico Weber TEST(SegmentedArrayTest, SimulateStackBehaviour) {
199*bc0d697dSNico Weber using AllocatorType = typename Array<ShadowStackEntry>::AllocatorType;
200*bc0d697dSNico Weber AllocatorType A(1 << 10);
201*bc0d697dSNico Weber Array<ShadowStackEntry> Data(A);
202*bc0d697dSNico Weber static uint64_t Dummy = 0;
203*bc0d697dSNico Weber constexpr uint64_t Max = 9;
204*bc0d697dSNico Weber
205*bc0d697dSNico Weber for (uint64_t i = 0; i < Max; ++i) {
206*bc0d697dSNico Weber auto P = Data.Append({i, &Dummy});
207*bc0d697dSNico Weber ASSERT_NE(P, nullptr);
208*bc0d697dSNico Weber ASSERT_EQ(P->NodePtr, &Dummy);
209*bc0d697dSNico Weber auto &Back = Data.back();
210*bc0d697dSNico Weber ASSERT_EQ(Back.NodePtr, &Dummy);
211*bc0d697dSNico Weber ASSERT_EQ(Back.EntryTSC, i);
212*bc0d697dSNico Weber }
213*bc0d697dSNico Weber
214*bc0d697dSNico Weber // Simulate a stack by checking the data from the end as we're trimming.
215*bc0d697dSNico Weber auto Counter = Max;
216*bc0d697dSNico Weber ASSERT_EQ(Data.size(), size_t(Max));
217*bc0d697dSNico Weber while (!Data.empty()) {
218*bc0d697dSNico Weber const auto &Top = Data.back();
219*bc0d697dSNico Weber uint64_t *TopNode = Top.NodePtr;
220*bc0d697dSNico Weber EXPECT_EQ(TopNode, &Dummy) << "Counter = " << Counter;
221*bc0d697dSNico Weber Data.trim(1);
222*bc0d697dSNico Weber --Counter;
223*bc0d697dSNico Weber ASSERT_EQ(Data.size(), size_t(Counter));
224*bc0d697dSNico Weber }
225*bc0d697dSNico Weber }
226*bc0d697dSNico Weber
TEST(SegmentedArrayTest,PlacementNewOnAlignedStorage)227*bc0d697dSNico Weber TEST(SegmentedArrayTest, PlacementNewOnAlignedStorage) {
228*bc0d697dSNico Weber using AllocatorType = typename Array<ShadowStackEntry>::AllocatorType;
229*bc0d697dSNico Weber typename std::aligned_storage<sizeof(AllocatorType),
230*bc0d697dSNico Weber alignof(AllocatorType)>::type AllocatorStorage;
231*bc0d697dSNico Weber new (&AllocatorStorage) AllocatorType(1 << 10);
232*bc0d697dSNico Weber auto *A = reinterpret_cast<AllocatorType *>(&AllocatorStorage);
233*bc0d697dSNico Weber typename std::aligned_storage<sizeof(Array<ShadowStackEntry>),
234*bc0d697dSNico Weber alignof(Array<ShadowStackEntry>)>::type
235*bc0d697dSNico Weber ArrayStorage;
236*bc0d697dSNico Weber new (&ArrayStorage) Array<ShadowStackEntry>(*A);
237*bc0d697dSNico Weber auto *Data = reinterpret_cast<Array<ShadowStackEntry> *>(&ArrayStorage);
238*bc0d697dSNico Weber
239*bc0d697dSNico Weber static uint64_t Dummy = 0;
240*bc0d697dSNico Weber constexpr uint64_t Max = 9;
241*bc0d697dSNico Weber
242*bc0d697dSNico Weber for (uint64_t i = 0; i < Max; ++i) {
243*bc0d697dSNico Weber auto P = Data->Append({i, &Dummy});
244*bc0d697dSNico Weber ASSERT_NE(P, nullptr);
245*bc0d697dSNico Weber ASSERT_EQ(P->NodePtr, &Dummy);
246*bc0d697dSNico Weber auto &Back = Data->back();
247*bc0d697dSNico Weber ASSERT_EQ(Back.NodePtr, &Dummy);
248*bc0d697dSNico Weber ASSERT_EQ(Back.EntryTSC, i);
249*bc0d697dSNico Weber }
250*bc0d697dSNico Weber
251*bc0d697dSNico Weber // Simulate a stack by checking the data from the end as we're trimming.
252*bc0d697dSNico Weber auto Counter = Max;
253*bc0d697dSNico Weber ASSERT_EQ(Data->size(), size_t(Max));
254*bc0d697dSNico Weber while (!Data->empty()) {
255*bc0d697dSNico Weber const auto &Top = Data->back();
256*bc0d697dSNico Weber uint64_t *TopNode = Top.NodePtr;
257*bc0d697dSNico Weber EXPECT_EQ(TopNode, &Dummy) << "Counter = " << Counter;
258*bc0d697dSNico Weber Data->trim(1);
259*bc0d697dSNico Weber --Counter;
260*bc0d697dSNico Weber ASSERT_EQ(Data->size(), size_t(Counter));
261*bc0d697dSNico Weber }
262*bc0d697dSNico Weber
263*bc0d697dSNico Weber // Once the stack is exhausted, we re-use the storage.
264*bc0d697dSNico Weber for (uint64_t i = 0; i < Max; ++i) {
265*bc0d697dSNico Weber auto P = Data->Append({i, &Dummy});
266*bc0d697dSNico Weber ASSERT_NE(P, nullptr);
267*bc0d697dSNico Weber ASSERT_EQ(P->NodePtr, &Dummy);
268*bc0d697dSNico Weber auto &Back = Data->back();
269*bc0d697dSNico Weber ASSERT_EQ(Back.NodePtr, &Dummy);
270*bc0d697dSNico Weber ASSERT_EQ(Back.EntryTSC, i);
271*bc0d697dSNico Weber }
272*bc0d697dSNico Weber
273*bc0d697dSNico Weber // We re-initialize the storage, by calling the destructor and
274*bc0d697dSNico Weber // placement-new'ing again.
275*bc0d697dSNico Weber Data->~Array();
276*bc0d697dSNico Weber A->~AllocatorType();
277*bc0d697dSNico Weber new (A) AllocatorType(1 << 10);
278*bc0d697dSNico Weber new (Data) Array<ShadowStackEntry>(*A);
279*bc0d697dSNico Weber
280*bc0d697dSNico Weber // Then re-do the test.
281*bc0d697dSNico Weber for (uint64_t i = 0; i < Max; ++i) {
282*bc0d697dSNico Weber auto P = Data->Append({i, &Dummy});
283*bc0d697dSNico Weber ASSERT_NE(P, nullptr);
284*bc0d697dSNico Weber ASSERT_EQ(P->NodePtr, &Dummy);
285*bc0d697dSNico Weber auto &Back = Data->back();
286*bc0d697dSNico Weber ASSERT_EQ(Back.NodePtr, &Dummy);
287*bc0d697dSNico Weber ASSERT_EQ(Back.EntryTSC, i);
288*bc0d697dSNico Weber }
289*bc0d697dSNico Weber
290*bc0d697dSNico Weber // Simulate a stack by checking the data from the end as we're trimming.
291*bc0d697dSNico Weber Counter = Max;
292*bc0d697dSNico Weber ASSERT_EQ(Data->size(), size_t(Max));
293*bc0d697dSNico Weber while (!Data->empty()) {
294*bc0d697dSNico Weber const auto &Top = Data->back();
295*bc0d697dSNico Weber uint64_t *TopNode = Top.NodePtr;
296*bc0d697dSNico Weber EXPECT_EQ(TopNode, &Dummy) << "Counter = " << Counter;
297*bc0d697dSNico Weber Data->trim(1);
298*bc0d697dSNico Weber --Counter;
299*bc0d697dSNico Weber ASSERT_EQ(Data->size(), size_t(Counter));
300*bc0d697dSNico Weber }
301*bc0d697dSNico Weber
302*bc0d697dSNico Weber // Once the stack is exhausted, we re-use the storage.
303*bc0d697dSNico Weber for (uint64_t i = 0; i < Max; ++i) {
304*bc0d697dSNico Weber auto P = Data->Append({i, &Dummy});
305*bc0d697dSNico Weber ASSERT_NE(P, nullptr);
306*bc0d697dSNico Weber ASSERT_EQ(P->NodePtr, &Dummy);
307*bc0d697dSNico Weber auto &Back = Data->back();
308*bc0d697dSNico Weber ASSERT_EQ(Back.NodePtr, &Dummy);
309*bc0d697dSNico Weber ASSERT_EQ(Back.EntryTSC, i);
310*bc0d697dSNico Weber }
311*bc0d697dSNico Weber }
312*bc0d697dSNico Weber
TEST(SegmentedArrayTest,ArrayOfPointersIteratorAccess)313*bc0d697dSNico Weber TEST(SegmentedArrayTest, ArrayOfPointersIteratorAccess) {
314*bc0d697dSNico Weber using PtrArray = Array<int *>;
315*bc0d697dSNico Weber PtrArray::AllocatorType Alloc(16384);
316*bc0d697dSNico Weber Array<int *> A(Alloc);
317*bc0d697dSNico Weber static constexpr size_t Count = 100;
318*bc0d697dSNico Weber std::vector<int> Integers(Count);
319*bc0d697dSNico Weber std::iota(Integers.begin(), Integers.end(), 0);
320*bc0d697dSNico Weber for (auto &I : Integers)
321*bc0d697dSNico Weber ASSERT_NE(A.Append(&I), nullptr);
322*bc0d697dSNico Weber int V = 0;
323*bc0d697dSNico Weber ASSERT_EQ(A.size(), Count);
324*bc0d697dSNico Weber for (auto P : A) {
325*bc0d697dSNico Weber ASSERT_NE(P, nullptr);
326*bc0d697dSNico Weber ASSERT_EQ(*P, V++);
327*bc0d697dSNico Weber }
328*bc0d697dSNico Weber }
329*bc0d697dSNico Weber
TEST(SegmentedArrayTest,ArrayOfPointersIteratorAccessExhaustion)330*bc0d697dSNico Weber TEST(SegmentedArrayTest, ArrayOfPointersIteratorAccessExhaustion) {
331*bc0d697dSNico Weber using PtrArray = Array<int *>;
332*bc0d697dSNico Weber PtrArray::AllocatorType Alloc(4096);
333*bc0d697dSNico Weber Array<int *> A(Alloc);
334*bc0d697dSNico Weber static constexpr size_t Count = 1000;
335*bc0d697dSNico Weber std::vector<int> Integers(Count);
336*bc0d697dSNico Weber std::iota(Integers.begin(), Integers.end(), 0);
337*bc0d697dSNico Weber for (auto &I : Integers)
338*bc0d697dSNico Weber if (A.Append(&I) == nullptr)
339*bc0d697dSNico Weber break;
340*bc0d697dSNico Weber int V = 0;
341*bc0d697dSNico Weber ASSERT_LT(A.size(), Count);
342*bc0d697dSNico Weber for (auto P : A) {
343*bc0d697dSNico Weber ASSERT_NE(P, nullptr);
344*bc0d697dSNico Weber ASSERT_EQ(*P, V++);
345*bc0d697dSNico Weber }
346*bc0d697dSNico Weber }
347*bc0d697dSNico Weber
348*bc0d697dSNico Weber } // namespace
349*bc0d697dSNico Weber } // namespace __xray
350