xref: /aosp_15_r20/external/skia/tests/TArrayTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2014 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkASAN.h"  // IWYU pragma: keep
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkFixedArray.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
13*c8dee2aaSAndroid Build Coastguard Worker 
14*c8dee2aaSAndroid Build Coastguard Worker #include <array>
15*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
16*c8dee2aaSAndroid Build Coastguard Worker #include <initializer_list>
17*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
18*c8dee2aaSAndroid Build Coastguard Worker 
19*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
20*c8dee2aaSAndroid Build Coastguard Worker 
21*c8dee2aaSAndroid Build Coastguard Worker // This class is used to test TArray's behavior with classes containing a vtable.
22*c8dee2aaSAndroid Build Coastguard Worker 
23*c8dee2aaSAndroid Build Coastguard Worker namespace {
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker class TestClass {
26*c8dee2aaSAndroid Build Coastguard Worker public:
27*c8dee2aaSAndroid Build Coastguard Worker     TestClass() = default;
28*c8dee2aaSAndroid Build Coastguard Worker     TestClass(const TestClass&) = default;
29*c8dee2aaSAndroid Build Coastguard Worker     TestClass& operator=(const TestClass&) = default;
TestClass(int v)30*c8dee2aaSAndroid Build Coastguard Worker     TestClass(int v) : value(v) {}
~TestClass()31*c8dee2aaSAndroid Build Coastguard Worker     virtual ~TestClass() {}
32*c8dee2aaSAndroid Build Coastguard Worker 
operator ==(const TestClass & c) const33*c8dee2aaSAndroid Build Coastguard Worker     bool operator==(const TestClass& c) const { return value == c.value; }
operator !=(const TestClass & c) const34*c8dee2aaSAndroid Build Coastguard Worker     bool operator!=(const TestClass& c) const { return value != c.value; }
35*c8dee2aaSAndroid Build Coastguard Worker 
36*c8dee2aaSAndroid Build Coastguard Worker     int value = 0;
37*c8dee2aaSAndroid Build Coastguard Worker };
38*c8dee2aaSAndroid Build Coastguard Worker 
39*c8dee2aaSAndroid Build Coastguard Worker }  // namespace
40*c8dee2aaSAndroid Build Coastguard Worker 
41*c8dee2aaSAndroid Build Coastguard Worker // Tests the TArray<T> class template.
42*c8dee2aaSAndroid Build Coastguard Worker 
43*c8dee2aaSAndroid Build Coastguard Worker template <typename ArrayType>
TestTSet_basic(skiatest::Reporter * reporter)44*c8dee2aaSAndroid Build Coastguard Worker static void TestTSet_basic(skiatest::Reporter* reporter) {
45*c8dee2aaSAndroid Build Coastguard Worker     using T = typename ArrayType::value_type;
46*c8dee2aaSAndroid Build Coastguard Worker     ArrayType a;
47*c8dee2aaSAndroid Build Coastguard Worker 
48*c8dee2aaSAndroid Build Coastguard Worker     // Starts empty.
49*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.empty());
50*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == 0);
51*c8dee2aaSAndroid Build Coastguard Worker 
52*c8dee2aaSAndroid Build Coastguard Worker     // { }, add a default constructed element
53*c8dee2aaSAndroid Build Coastguard Worker     a.push_back() = T{0};
54*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, !a.empty());
55*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == 1);
56*c8dee2aaSAndroid Build Coastguard Worker 
57*c8dee2aaSAndroid Build Coastguard Worker     // { 0 }, removeShuffle the only element.
58*c8dee2aaSAndroid Build Coastguard Worker     a.removeShuffle(0);
59*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.empty());
60*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == 0);
61*c8dee2aaSAndroid Build Coastguard Worker 
62*c8dee2aaSAndroid Build Coastguard Worker     // { }, add a default, add a 1, remove first
63*c8dee2aaSAndroid Build Coastguard Worker     a.push_back() = T{0};
64*c8dee2aaSAndroid Build Coastguard Worker     a.push_back() = T{1};
65*c8dee2aaSAndroid Build Coastguard Worker     a.removeShuffle(0);
66*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, !a.empty());
67*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == 1);
68*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a[0] == T{1});
69*c8dee2aaSAndroid Build Coastguard Worker 
70*c8dee2aaSAndroid Build Coastguard Worker     // { 1 }, replace with new array
71*c8dee2aaSAndroid Build Coastguard Worker     T b[5] = {T{0}, T{1}, T{2}, T{3}, T{4}};
72*c8dee2aaSAndroid Build Coastguard Worker     a.reset(b, std::size(b));
73*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == std::size(b));
74*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a[2] == T{2});
75*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a[4] == T{4});
76*c8dee2aaSAndroid Build Coastguard Worker 
77*c8dee2aaSAndroid Build Coastguard Worker     // { 0, 1, 2, 3, 4 }, removeShuffle the last
78*c8dee2aaSAndroid Build Coastguard Worker     a.removeShuffle(4);
79*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == std::size(b) - 1);
80*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a[3] == T{3});
81*c8dee2aaSAndroid Build Coastguard Worker 
82*c8dee2aaSAndroid Build Coastguard Worker     // { 0, 1, 2, 3 }, remove a middle, note shuffle
83*c8dee2aaSAndroid Build Coastguard Worker     a.removeShuffle(1);
84*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == std::size(b) - 2);
85*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a[0] == T{0});
86*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a[1] == T{3});
87*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a[2] == T{2});
88*c8dee2aaSAndroid Build Coastguard Worker 
89*c8dee2aaSAndroid Build Coastguard Worker     // { 0, 3, 2 }... remove the last element.
90*c8dee2aaSAndroid Build Coastguard Worker     a.pop_back();
91*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == std::size(b) - 3);
92*c8dee2aaSAndroid Build Coastguard Worker 
93*c8dee2aaSAndroid Build Coastguard Worker     // { 0, 3, 5, 5, 5 }... add three elements.
94*c8dee2aaSAndroid Build Coastguard Worker     a.push_back_n(3, 5);
95*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == std::size(b));
96*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a[2] == T{5});
97*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a[3] == T{5});
98*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a[4] == T{5});
99*c8dee2aaSAndroid Build Coastguard Worker 
100*c8dee2aaSAndroid Build Coastguard Worker     // { 0 }... pop four elements.
101*c8dee2aaSAndroid Build Coastguard Worker     a.pop_back_n(4);
102*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == std::size(b) - 4);
103*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a[0] == 0);
104*c8dee2aaSAndroid Build Coastguard Worker }
105*c8dee2aaSAndroid Build Coastguard Worker 
106*c8dee2aaSAndroid Build Coastguard Worker template <typename T>
test_construction(skiatest::Reporter * reporter,bool hasMoveSemantics=true)107*c8dee2aaSAndroid Build Coastguard Worker static void test_construction(skiatest::Reporter* reporter, bool hasMoveSemantics = true) {
108*c8dee2aaSAndroid Build Coastguard Worker     using ValueType = typename T::value_type;
109*c8dee2aaSAndroid Build Coastguard Worker 
110*c8dee2aaSAndroid Build Coastguard Worker     // No arguments: Creates an empty array with no initial storage.
111*c8dee2aaSAndroid Build Coastguard Worker     T arrayNoArgs;
112*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayNoArgs.empty());
113*c8dee2aaSAndroid Build Coastguard Worker 
114*c8dee2aaSAndroid Build Coastguard Worker     // Single integer: Creates an empty array that will preallocate space for reserveCount elements.
115*c8dee2aaSAndroid Build Coastguard Worker     T arrayReserve(15);
116*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayReserve.empty());
117*c8dee2aaSAndroid Build Coastguard Worker     // May get some extra elements for free because sk_allocate_* can round up.
118*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayReserve.capacity() >= 15 && arrayReserve.capacity() < 50);
119*c8dee2aaSAndroid Build Coastguard Worker 
120*c8dee2aaSAndroid Build Coastguard Worker     // Another array, const&: Copies one array to another.
121*c8dee2aaSAndroid Build Coastguard Worker     T arrayInitial;
122*c8dee2aaSAndroid Build Coastguard Worker     arrayInitial.push_back(ValueType{1});
123*c8dee2aaSAndroid Build Coastguard Worker     arrayInitial.push_back(ValueType{2});
124*c8dee2aaSAndroid Build Coastguard Worker     arrayInitial.push_back(ValueType{3});
125*c8dee2aaSAndroid Build Coastguard Worker 
126*c8dee2aaSAndroid Build Coastguard Worker     T arrayCopy(arrayInitial);
127*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayInitial.size() == 3);
128*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayInitial[0] == ValueType{1});
129*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayInitial[1] == ValueType{2});
130*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayInitial[2] == ValueType{3});
131*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayCopy.size() == 3);
132*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayCopy[0] == ValueType{1});
133*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayCopy[1] == ValueType{2});
134*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayCopy[2] == ValueType{3});
135*c8dee2aaSAndroid Build Coastguard Worker 
136*c8dee2aaSAndroid Build Coastguard Worker     // Another array, &&: Moves one array to another.
137*c8dee2aaSAndroid Build Coastguard Worker     T arrayMove(std::move(arrayInitial));
138*c8dee2aaSAndroid Build Coastguard Worker     if (hasMoveSemantics) {
139*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, arrayInitial.empty()); // NOLINT(bugprone-use-after-move)
140*c8dee2aaSAndroid Build Coastguard Worker     }
141*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayMove.size() == 3);
142*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayMove[0] == ValueType{1});
143*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayMove[1] == ValueType{2});
144*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayMove[2] == ValueType{3});
145*c8dee2aaSAndroid Build Coastguard Worker 
146*c8dee2aaSAndroid Build Coastguard Worker     // Pointer and count: Copies contents of a standard C array.
147*c8dee2aaSAndroid Build Coastguard Worker     typename T::value_type data[3] = { 7, 8, 9 };
148*c8dee2aaSAndroid Build Coastguard Worker     T arrayPtrCount(data, 3);
149*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayPtrCount.size() == 3);
150*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayPtrCount[0] == ValueType{7});
151*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayPtrCount[1] == ValueType{8});
152*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayPtrCount[2] == ValueType{9});
153*c8dee2aaSAndroid Build Coastguard Worker 
154*c8dee2aaSAndroid Build Coastguard Worker     // Initializer list.
155*c8dee2aaSAndroid Build Coastguard Worker     T arrayInitializer{8, 6, 7, 5, 3, 0, 9};
156*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayInitializer.size() == 7);
157*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayInitializer[0] == ValueType{8});
158*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayInitializer[1] == ValueType{6});
159*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayInitializer[2] == ValueType{7});
160*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayInitializer[3] == ValueType{5});
161*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayInitializer[4] == ValueType{3});
162*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayInitializer[5] == ValueType{0});
163*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayInitializer[6] == ValueType{9});
164*c8dee2aaSAndroid Build Coastguard Worker }
165*c8dee2aaSAndroid Build Coastguard Worker 
166*c8dee2aaSAndroid Build Coastguard Worker template <typename T, typename U>
test_starray_compatibility(skiatest::Reporter * reporter)167*c8dee2aaSAndroid Build Coastguard Worker static void test_starray_compatibility(skiatest::Reporter* reporter) {
168*c8dee2aaSAndroid Build Coastguard Worker     // We expect TArrays of the same type to be copyable and movable, even when:
169*c8dee2aaSAndroid Build Coastguard Worker     // - one side is an TArray, and the other side is an STArray
170*c8dee2aaSAndroid Build Coastguard Worker     // - both sides are STArray, but each side has a different internal capacity
171*c8dee2aaSAndroid Build Coastguard Worker     T tArray;
172*c8dee2aaSAndroid Build Coastguard Worker     tArray.push_back(1);
173*c8dee2aaSAndroid Build Coastguard Worker     tArray.push_back(2);
174*c8dee2aaSAndroid Build Coastguard Worker     tArray.push_back(3);
175*c8dee2aaSAndroid Build Coastguard Worker     T tArray2 = tArray;
176*c8dee2aaSAndroid Build Coastguard Worker 
177*c8dee2aaSAndroid Build Coastguard Worker     // Copy construction from other-type array.
178*c8dee2aaSAndroid Build Coastguard Worker     U arrayCopy(tArray);
179*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, tArray.size() == 3);
180*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, tArray[0] == 1);
181*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, tArray[1] == 2);
182*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, tArray[2] == 3);
183*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayCopy.size() == 3);
184*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayCopy[0] == 1);
185*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayCopy[1] == 2);
186*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayCopy[2] == 3);
187*c8dee2aaSAndroid Build Coastguard Worker 
188*c8dee2aaSAndroid Build Coastguard Worker     // Assignment from other-type array.
189*c8dee2aaSAndroid Build Coastguard Worker     U arrayAssignment;
190*c8dee2aaSAndroid Build Coastguard Worker     arrayAssignment = tArray;
191*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, tArray.size() == 3);
192*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, tArray[0] == 1);
193*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, tArray[1] == 2);
194*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, tArray[2] == 3);
195*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayAssignment.size() == 3);
196*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayAssignment[0] == 1);
197*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayAssignment[1] == 2);
198*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayAssignment[2] == 3);
199*c8dee2aaSAndroid Build Coastguard Worker 
200*c8dee2aaSAndroid Build Coastguard Worker     // Move construction from other-type array.
201*c8dee2aaSAndroid Build Coastguard Worker     U arrayMove(std::move(tArray));
202*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, tArray.empty()); // NOLINT(bugprone-use-after-move)
203*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayMove.size() == 3);
204*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayMove[0] == 1);
205*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayMove[1] == 2);
206*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayMove[2] == 3);
207*c8dee2aaSAndroid Build Coastguard Worker 
208*c8dee2aaSAndroid Build Coastguard Worker     // Move assignment from other-type array.
209*c8dee2aaSAndroid Build Coastguard Worker     U arrayMoveAssign;
210*c8dee2aaSAndroid Build Coastguard Worker     arrayMoveAssign = std::move(tArray2);
211*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, tArray2.empty()); // NOLINT(bugprone-use-after-move)
212*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayMoveAssign.size() == 3);
213*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayMoveAssign[0] == 1);
214*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayMoveAssign[1] == 2);
215*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, arrayMoveAssign[2] == 3);
216*c8dee2aaSAndroid Build Coastguard Worker }
217*c8dee2aaSAndroid Build Coastguard Worker 
218*c8dee2aaSAndroid Build Coastguard Worker // Move-only type used for testing swap and move_back() of TArray&&'s.
219*c8dee2aaSAndroid Build Coastguard Worker namespace {
220*c8dee2aaSAndroid Build Coastguard Worker struct MoveOnlyInt {
MoveOnlyInt__anon21639d440211::MoveOnlyInt221*c8dee2aaSAndroid Build Coastguard Worker     MoveOnlyInt(int i) : fInt(i) {}
MoveOnlyInt__anon21639d440211::MoveOnlyInt222*c8dee2aaSAndroid Build Coastguard Worker     MoveOnlyInt(MoveOnlyInt&& that) : fInt(that.fInt) {}
operator ==__anon21639d440211::MoveOnlyInt223*c8dee2aaSAndroid Build Coastguard Worker     bool operator==(int i) const { return fInt == i; }
224*c8dee2aaSAndroid Build Coastguard Worker     int fInt;
225*c8dee2aaSAndroid Build Coastguard Worker };
226*c8dee2aaSAndroid Build Coastguard Worker } // anonymous
227*c8dee2aaSAndroid Build Coastguard Worker 
test_swap(skiatest::Reporter * reporter,SkSpan<TArray<T> * > arrays,SkSpan<const int> sizes)228*c8dee2aaSAndroid Build Coastguard Worker template <typename T> static void test_swap(skiatest::Reporter* reporter,
229*c8dee2aaSAndroid Build Coastguard Worker                                             SkSpan<TArray<T>*> arrays,
230*c8dee2aaSAndroid Build Coastguard Worker                                             SkSpan<const int> sizes) {
231*c8dee2aaSAndroid Build Coastguard Worker     for (auto a : arrays) {
232*c8dee2aaSAndroid Build Coastguard Worker     for (auto b : arrays) {
233*c8dee2aaSAndroid Build Coastguard Worker         if (a == b) {
234*c8dee2aaSAndroid Build Coastguard Worker             continue;
235*c8dee2aaSAndroid Build Coastguard Worker         }
236*c8dee2aaSAndroid Build Coastguard Worker 
237*c8dee2aaSAndroid Build Coastguard Worker         for (auto sizeA : sizes) {
238*c8dee2aaSAndroid Build Coastguard Worker         for (auto sizeB : sizes) {
239*c8dee2aaSAndroid Build Coastguard Worker             a->clear();
240*c8dee2aaSAndroid Build Coastguard Worker             b->clear();
241*c8dee2aaSAndroid Build Coastguard Worker 
242*c8dee2aaSAndroid Build Coastguard Worker             int curr = 0;
243*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < sizeA; i++) { a->push_back(curr++); }
244*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < sizeB; i++) { b->push_back(curr++); }
245*c8dee2aaSAndroid Build Coastguard Worker 
246*c8dee2aaSAndroid Build Coastguard Worker             a->swap(*b);
247*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(reporter, b->size() == sizeA);
248*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(reporter, a->size() == sizeB);
249*c8dee2aaSAndroid Build Coastguard Worker 
250*c8dee2aaSAndroid Build Coastguard Worker             curr = 0;
251*c8dee2aaSAndroid Build Coastguard Worker             for (auto&& x : *b) { REPORTER_ASSERT(reporter, x == curr++); }
252*c8dee2aaSAndroid Build Coastguard Worker             for (auto&& x : *a) { REPORTER_ASSERT(reporter, x == curr++); }
253*c8dee2aaSAndroid Build Coastguard Worker 
254*c8dee2aaSAndroid Build Coastguard Worker             a->swap(*a);
255*c8dee2aaSAndroid Build Coastguard Worker             curr = sizeA;
256*c8dee2aaSAndroid Build Coastguard Worker             for (auto&& x : *a) { REPORTER_ASSERT(reporter, x == curr++); }
257*c8dee2aaSAndroid Build Coastguard Worker         }}
258*c8dee2aaSAndroid Build Coastguard Worker     }}
259*c8dee2aaSAndroid Build Coastguard Worker }
260*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(TArray_Swap,reporter)261*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(TArray_Swap, reporter) {
262*c8dee2aaSAndroid Build Coastguard Worker     static constexpr int kSizes[] = {0, 1, 5, 10, 15, 20, 25};
263*c8dee2aaSAndroid Build Coastguard Worker 
264*c8dee2aaSAndroid Build Coastguard Worker     TArray<int> arr;
265*c8dee2aaSAndroid Build Coastguard Worker     STArray< 5, int> arr5;
266*c8dee2aaSAndroid Build Coastguard Worker     STArray<10, int> arr10;
267*c8dee2aaSAndroid Build Coastguard Worker     STArray<20, int> arr20;
268*c8dee2aaSAndroid Build Coastguard Worker     TArray<int>* arrays[] = { &arr, &arr5, &arr10, &arr20 };
269*c8dee2aaSAndroid Build Coastguard Worker     test_swap<int>(reporter, arrays, kSizes);
270*c8dee2aaSAndroid Build Coastguard Worker 
271*c8dee2aaSAndroid Build Coastguard Worker     TArray<MoveOnlyInt> moi;
272*c8dee2aaSAndroid Build Coastguard Worker     STArray< 5, MoveOnlyInt> moi5;
273*c8dee2aaSAndroid Build Coastguard Worker     STArray<10, MoveOnlyInt> moi10;
274*c8dee2aaSAndroid Build Coastguard Worker     STArray<20, MoveOnlyInt> moi20;
275*c8dee2aaSAndroid Build Coastguard Worker     TArray<MoveOnlyInt>* arraysMoi[] = { &moi, &moi5, &moi10, &moi20 };
276*c8dee2aaSAndroid Build Coastguard Worker     test_swap<MoveOnlyInt>(reporter, arraysMoi, kSizes);
277*c8dee2aaSAndroid Build Coastguard Worker }
278*c8dee2aaSAndroid Build Coastguard Worker 
test_array_move(skiatest::Reporter * reporter,SkSpan<TArray<T> * > arrays,SkSpan<const int> sizes)279*c8dee2aaSAndroid Build Coastguard Worker template <typename T> static void test_array_move(skiatest::Reporter* reporter,
280*c8dee2aaSAndroid Build Coastguard Worker                                                   SkSpan<TArray<T>*> arrays,
281*c8dee2aaSAndroid Build Coastguard Worker                                                   SkSpan<const int> sizes) {
282*c8dee2aaSAndroid Build Coastguard Worker     // self test is a no-op
283*c8dee2aaSAndroid Build Coastguard Worker     for (auto a : arrays) {
284*c8dee2aaSAndroid Build Coastguard Worker         for (auto sizeA : sizes) {
285*c8dee2aaSAndroid Build Coastguard Worker             a->clear();
286*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < sizeA; i++) { a->push_back(i); }
287*c8dee2aaSAndroid Build Coastguard Worker             a->move_back(*a);
288*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(reporter, a->size() == sizeA);
289*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < sizeA; i++) {
290*c8dee2aaSAndroid Build Coastguard Worker                 REPORTER_ASSERT(reporter, (*a)[i] == i);
291*c8dee2aaSAndroid Build Coastguard Worker             }
292*c8dee2aaSAndroid Build Coastguard Worker         }
293*c8dee2aaSAndroid Build Coastguard Worker     }
294*c8dee2aaSAndroid Build Coastguard Worker 
295*c8dee2aaSAndroid Build Coastguard Worker     for (auto a : arrays) {
296*c8dee2aaSAndroid Build Coastguard Worker     for (auto b : arrays) {
297*c8dee2aaSAndroid Build Coastguard Worker         if (a == b) {
298*c8dee2aaSAndroid Build Coastguard Worker             continue;
299*c8dee2aaSAndroid Build Coastguard Worker         }
300*c8dee2aaSAndroid Build Coastguard Worker 
301*c8dee2aaSAndroid Build Coastguard Worker         for (auto sizeA : sizes) {
302*c8dee2aaSAndroid Build Coastguard Worker         for (auto sizeB : sizes) {
303*c8dee2aaSAndroid Build Coastguard Worker             a->clear();
304*c8dee2aaSAndroid Build Coastguard Worker             b->clear();
305*c8dee2aaSAndroid Build Coastguard Worker 
306*c8dee2aaSAndroid Build Coastguard Worker             int curr = 0;
307*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < sizeA; i++) { a->push_back(curr++); }
308*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < sizeB; i++) { b->push_back(curr++); }
309*c8dee2aaSAndroid Build Coastguard Worker 
310*c8dee2aaSAndroid Build Coastguard Worker             a->move_back(*b);
311*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(reporter, b->size() == 0);
312*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(reporter, a->size() == sizeA + sizeB);
313*c8dee2aaSAndroid Build Coastguard Worker 
314*c8dee2aaSAndroid Build Coastguard Worker             curr = 0;
315*c8dee2aaSAndroid Build Coastguard Worker             for (auto&& x : *a) { REPORTER_ASSERT(reporter, x == curr++); }
316*c8dee2aaSAndroid Build Coastguard Worker         }}
317*c8dee2aaSAndroid Build Coastguard Worker     }}
318*c8dee2aaSAndroid Build Coastguard Worker }
319*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(TArray_Move,reporter)320*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(TArray_Move, reporter) {
321*c8dee2aaSAndroid Build Coastguard Worker     static constexpr int kSizes[] = {0, 1, 5, 10, 15, 20, 25};
322*c8dee2aaSAndroid Build Coastguard Worker 
323*c8dee2aaSAndroid Build Coastguard Worker     TArray<int> arr;
324*c8dee2aaSAndroid Build Coastguard Worker     STArray< 5, int> arr5;
325*c8dee2aaSAndroid Build Coastguard Worker     STArray<10, int> arr10;
326*c8dee2aaSAndroid Build Coastguard Worker     STArray<20, int> arr20;
327*c8dee2aaSAndroid Build Coastguard Worker     TArray<int>* arrays[] = { &arr, &arr5, &arr10, &arr20 };
328*c8dee2aaSAndroid Build Coastguard Worker     test_array_move<int>(reporter, arrays, kSizes);
329*c8dee2aaSAndroid Build Coastguard Worker 
330*c8dee2aaSAndroid Build Coastguard Worker     TArray<MoveOnlyInt> moi;
331*c8dee2aaSAndroid Build Coastguard Worker     STArray< 5, MoveOnlyInt> moi5;
332*c8dee2aaSAndroid Build Coastguard Worker     STArray<10, MoveOnlyInt> moi10;
333*c8dee2aaSAndroid Build Coastguard Worker     STArray<20, MoveOnlyInt> moi20;
334*c8dee2aaSAndroid Build Coastguard Worker     TArray<MoveOnlyInt>* arraysMoi[] = { &moi, &moi5, &moi10, &moi20 };
335*c8dee2aaSAndroid Build Coastguard Worker     test_array_move<MoveOnlyInt>(reporter, arraysMoi, kSizes);
336*c8dee2aaSAndroid Build Coastguard Worker }
337*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(TArray_NoUnnecessaryAllocs,reporter)338*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(TArray_NoUnnecessaryAllocs, reporter) {
339*c8dee2aaSAndroid Build Coastguard Worker     {
340*c8dee2aaSAndroid Build Coastguard Worker         TArray<int> a;
341*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, a.capacity() == 0);
342*c8dee2aaSAndroid Build Coastguard Worker     }
343*c8dee2aaSAndroid Build Coastguard Worker     {
344*c8dee2aaSAndroid Build Coastguard Worker         STArray<10, int> a;
345*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, a.capacity() == 10);
346*c8dee2aaSAndroid Build Coastguard Worker     }
347*c8dee2aaSAndroid Build Coastguard Worker     {
348*c8dee2aaSAndroid Build Coastguard Worker         TArray<int> a(1);
349*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, a.capacity() >= 1);
350*c8dee2aaSAndroid Build Coastguard Worker     }
351*c8dee2aaSAndroid Build Coastguard Worker     {
352*c8dee2aaSAndroid Build Coastguard Worker         TArray<int> a, b;
353*c8dee2aaSAndroid Build Coastguard Worker         b = a;
354*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, b.capacity() == 0);
355*c8dee2aaSAndroid Build Coastguard Worker     }
356*c8dee2aaSAndroid Build Coastguard Worker     {
357*c8dee2aaSAndroid Build Coastguard Worker         STArray<10, int> a;
358*c8dee2aaSAndroid Build Coastguard Worker         TArray<int> b;
359*c8dee2aaSAndroid Build Coastguard Worker         b = a;
360*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, b.capacity() == 0);
361*c8dee2aaSAndroid Build Coastguard Worker     }
362*c8dee2aaSAndroid Build Coastguard Worker     {
363*c8dee2aaSAndroid Build Coastguard Worker         TArray<int> a;
364*c8dee2aaSAndroid Build Coastguard Worker         TArray<int> b(a);  // NOLINT(performance-unnecessary-copy-initialization)
365*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, b.capacity() == 0);
366*c8dee2aaSAndroid Build Coastguard Worker     }
367*c8dee2aaSAndroid Build Coastguard Worker     {
368*c8dee2aaSAndroid Build Coastguard Worker         STArray<10, int> a;
369*c8dee2aaSAndroid Build Coastguard Worker         TArray<int> b(a);  // NOLINT(performance-unnecessary-copy-initialization)
370*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, b.capacity() == 0);
371*c8dee2aaSAndroid Build Coastguard Worker     }
372*c8dee2aaSAndroid Build Coastguard Worker     {
373*c8dee2aaSAndroid Build Coastguard Worker         TArray<int> a;
374*c8dee2aaSAndroid Build Coastguard Worker         TArray<int> b(std::move(a));
375*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, b.capacity() == 0);
376*c8dee2aaSAndroid Build Coastguard Worker     }
377*c8dee2aaSAndroid Build Coastguard Worker     {
378*c8dee2aaSAndroid Build Coastguard Worker         STArray<10, int> a;
379*c8dee2aaSAndroid Build Coastguard Worker         TArray<int> b(std::move(a));
380*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, b.capacity() == 0);
381*c8dee2aaSAndroid Build Coastguard Worker     }
382*c8dee2aaSAndroid Build Coastguard Worker     {
383*c8dee2aaSAndroid Build Coastguard Worker         TArray<int> a;
384*c8dee2aaSAndroid Build Coastguard Worker         TArray<int> b;
385*c8dee2aaSAndroid Build Coastguard Worker         b = std::move(a);
386*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, b.capacity() == 0);
387*c8dee2aaSAndroid Build Coastguard Worker     }
388*c8dee2aaSAndroid Build Coastguard Worker     {
389*c8dee2aaSAndroid Build Coastguard Worker         STArray<10, int> a;
390*c8dee2aaSAndroid Build Coastguard Worker         TArray<int> b;
391*c8dee2aaSAndroid Build Coastguard Worker         b = std::move(a);
392*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, b.capacity() == 0);
393*c8dee2aaSAndroid Build Coastguard Worker     }
394*c8dee2aaSAndroid Build Coastguard Worker }
395*c8dee2aaSAndroid Build Coastguard Worker 
396*c8dee2aaSAndroid Build Coastguard Worker template <typename ArrayType>
test_self_assignment(skiatest::Reporter * reporter)397*c8dee2aaSAndroid Build Coastguard Worker static void test_self_assignment(skiatest::Reporter* reporter) {
398*c8dee2aaSAndroid Build Coastguard Worker     ArrayType a;
399*c8dee2aaSAndroid Build Coastguard Worker     a.push_back(1);
400*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, !a.empty());
401*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == 1);
402*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a[0] == 1);
403*c8dee2aaSAndroid Build Coastguard Worker 
404*c8dee2aaSAndroid Build Coastguard Worker     a = static_cast<ArrayType&>(a);
405*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, !a.empty());
406*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == 1);
407*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a[0] == 1);
408*c8dee2aaSAndroid Build Coastguard Worker }
409*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(TArray_SelfAssignment,reporter)410*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(TArray_SelfAssignment, reporter) {
411*c8dee2aaSAndroid Build Coastguard Worker     test_self_assignment<TArray<int>>(reporter);
412*c8dee2aaSAndroid Build Coastguard Worker     test_self_assignment<STArray<3, unsigned short>>(reporter);
413*c8dee2aaSAndroid Build Coastguard Worker }
414*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(FixedArray_SelfAssignment,reporter)415*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(FixedArray_SelfAssignment, reporter) {
416*c8dee2aaSAndroid Build Coastguard Worker     test_self_assignment<FixedArray<1, int>>(reporter);
417*c8dee2aaSAndroid Build Coastguard Worker     test_self_assignment<FixedArray<4, unsigned short>>(reporter);
418*c8dee2aaSAndroid Build Coastguard Worker }
419*c8dee2aaSAndroid Build Coastguard Worker 
420*c8dee2aaSAndroid Build Coastguard Worker template <typename ArrayType>
test_comparison(skiatest::Reporter * reporter)421*c8dee2aaSAndroid Build Coastguard Worker static void test_comparison(skiatest::Reporter* reporter) {
422*c8dee2aaSAndroid Build Coastguard Worker     using T = typename ArrayType::value_type;
423*c8dee2aaSAndroid Build Coastguard Worker     ArrayType a, b;
424*c8dee2aaSAndroid Build Coastguard Worker 
425*c8dee2aaSAndroid Build Coastguard Worker     // Empty arrays.
426*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a == b);
427*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, !(a != b));
428*c8dee2aaSAndroid Build Coastguard Worker 
429*c8dee2aaSAndroid Build Coastguard Worker     // Arrays with identical contents.
430*c8dee2aaSAndroid Build Coastguard Worker     for (int x = 0; x < 10; ++x) {
431*c8dee2aaSAndroid Build Coastguard Worker         a.push_back(T(x));
432*c8dee2aaSAndroid Build Coastguard Worker         b.push_back(T(x));
433*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, a == b);
434*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, !(a != b));
435*c8dee2aaSAndroid Build Coastguard Worker     }
436*c8dee2aaSAndroid Build Coastguard Worker 
437*c8dee2aaSAndroid Build Coastguard Worker     // Arrays with differing sizes.
438*c8dee2aaSAndroid Build Coastguard Worker     for (int x = 0; x < 10; ++x) {
439*c8dee2aaSAndroid Build Coastguard Worker         a.pop_back();
440*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, a != b);
441*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, b != a);
442*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, !(a == b));
443*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, !(b == a));
444*c8dee2aaSAndroid Build Coastguard Worker     }
445*c8dee2aaSAndroid Build Coastguard Worker 
446*c8dee2aaSAndroid Build Coastguard Worker     // Arrays with differing contents.
447*c8dee2aaSAndroid Build Coastguard Worker     a = b;
448*c8dee2aaSAndroid Build Coastguard Worker     for (int x = 0; x < 10; ++x) {
449*c8dee2aaSAndroid Build Coastguard Worker         a[x] = T(x + 100);
450*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, a != b);
451*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, b != a);
452*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, !(a == b));
453*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, !(b == a));
454*c8dee2aaSAndroid Build Coastguard Worker         a[x] = T(x);
455*c8dee2aaSAndroid Build Coastguard Worker     }
456*c8dee2aaSAndroid Build Coastguard Worker }
457*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(TArray_Comparison,reporter)458*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(TArray_Comparison, reporter) {
459*c8dee2aaSAndroid Build Coastguard Worker     test_comparison<TArray<int>>(reporter);
460*c8dee2aaSAndroid Build Coastguard Worker     test_comparison<TArray<double>>(reporter);
461*c8dee2aaSAndroid Build Coastguard Worker     test_comparison<TArray<TestClass>>(reporter);
462*c8dee2aaSAndroid Build Coastguard Worker     test_comparison<STArray<1, int>>(reporter);
463*c8dee2aaSAndroid Build Coastguard Worker     test_comparison<STArray<5, char>>(reporter);
464*c8dee2aaSAndroid Build Coastguard Worker     test_comparison<STArray<7, TestClass>>(reporter);
465*c8dee2aaSAndroid Build Coastguard Worker     test_comparison<STArray<10, float>>(reporter);
466*c8dee2aaSAndroid Build Coastguard Worker }
467*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(FixedArray_Comparison,reporter)468*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(FixedArray_Comparison, reporter) {
469*c8dee2aaSAndroid Build Coastguard Worker     test_comparison<FixedArray<15, int>>(reporter);
470*c8dee2aaSAndroid Build Coastguard Worker     test_comparison<FixedArray<20, char>>(reporter);
471*c8dee2aaSAndroid Build Coastguard Worker     test_comparison<FixedArray<25, float>>(reporter);
472*c8dee2aaSAndroid Build Coastguard Worker }
473*c8dee2aaSAndroid Build Coastguard Worker 
test_array_reserve(skiatest::Reporter * reporter,Array * array,int reserveCount)474*c8dee2aaSAndroid Build Coastguard Worker template <typename Array> static void test_array_reserve(skiatest::Reporter* reporter,
475*c8dee2aaSAndroid Build Coastguard Worker                                                          Array* array, int reserveCount) {
476*c8dee2aaSAndroid Build Coastguard Worker     SkRandom random;
477*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, array->capacity() >= reserveCount);
478*c8dee2aaSAndroid Build Coastguard Worker     array->push_back();
479*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, array->capacity() >= reserveCount);
480*c8dee2aaSAndroid Build Coastguard Worker     array->pop_back();
481*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, array->capacity() >= reserveCount);
482*c8dee2aaSAndroid Build Coastguard Worker     while (array->size() < reserveCount) {
483*c8dee2aaSAndroid Build Coastguard Worker         // Two steps forward, one step back
484*c8dee2aaSAndroid Build Coastguard Worker         if (random.nextULessThan(3) < 2) {
485*c8dee2aaSAndroid Build Coastguard Worker             array->push_back();
486*c8dee2aaSAndroid Build Coastguard Worker         } else if (array->size() > 0) {
487*c8dee2aaSAndroid Build Coastguard Worker             array->pop_back();
488*c8dee2aaSAndroid Build Coastguard Worker         }
489*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, array->capacity() >= reserveCount);
490*c8dee2aaSAndroid Build Coastguard Worker     }
491*c8dee2aaSAndroid Build Coastguard Worker }
492*c8dee2aaSAndroid Build Coastguard Worker 
test_reserve(skiatest::Reporter * reporter)493*c8dee2aaSAndroid Build Coastguard Worker template<typename Array> static void test_reserve(skiatest::Reporter* reporter) {
494*c8dee2aaSAndroid Build Coastguard Worker     // Test that our allocated space stays >= to the reserve count until the array is filled to
495*c8dee2aaSAndroid Build Coastguard Worker     // the reserve count
496*c8dee2aaSAndroid Build Coastguard Worker     for (int reserveCount : {1, 2, 10, 100}) {
497*c8dee2aaSAndroid Build Coastguard Worker         // Test setting reserve in constructor.
498*c8dee2aaSAndroid Build Coastguard Worker         Array array1(reserveCount);
499*c8dee2aaSAndroid Build Coastguard Worker         test_array_reserve(reporter, &array1, reserveCount);
500*c8dee2aaSAndroid Build Coastguard Worker 
501*c8dee2aaSAndroid Build Coastguard Worker         // Test setting reserve after constructor.
502*c8dee2aaSAndroid Build Coastguard Worker         Array array2;
503*c8dee2aaSAndroid Build Coastguard Worker         array2.reserve(reserveCount);
504*c8dee2aaSAndroid Build Coastguard Worker         test_array_reserve(reporter, &array2, reserveCount);
505*c8dee2aaSAndroid Build Coastguard Worker 
506*c8dee2aaSAndroid Build Coastguard Worker         // Test increasing reserve after constructor.
507*c8dee2aaSAndroid Build Coastguard Worker         Array array3(reserveCount/2);
508*c8dee2aaSAndroid Build Coastguard Worker         array3.reserve(reserveCount);
509*c8dee2aaSAndroid Build Coastguard Worker         test_array_reserve(reporter, &array3, reserveCount);
510*c8dee2aaSAndroid Build Coastguard Worker 
511*c8dee2aaSAndroid Build Coastguard Worker         // Test setting reserve on non-empty array.
512*c8dee2aaSAndroid Build Coastguard Worker         Array array4;
513*c8dee2aaSAndroid Build Coastguard Worker         array4.push_back_n(reserveCount);
514*c8dee2aaSAndroid Build Coastguard Worker         array4.reserve(2 * reserveCount);
515*c8dee2aaSAndroid Build Coastguard Worker         array4.pop_back_n(reserveCount);
516*c8dee2aaSAndroid Build Coastguard Worker         test_array_reserve(reporter, &array4, 2 * reserveCount);
517*c8dee2aaSAndroid Build Coastguard Worker     }
518*c8dee2aaSAndroid Build Coastguard Worker }
519*c8dee2aaSAndroid Build Coastguard Worker 
520*c8dee2aaSAndroid Build Coastguard Worker template <typename T>
test_inner_push(skiatest::Reporter * reporter)521*c8dee2aaSAndroid Build Coastguard Worker static void test_inner_push(skiatest::Reporter* reporter) {
522*c8dee2aaSAndroid Build Coastguard Worker     T a;
523*c8dee2aaSAndroid Build Coastguard Worker     a.push_back(12345);
524*c8dee2aaSAndroid Build Coastguard Worker     for (int x=0; x<50; ++x) {
525*c8dee2aaSAndroid Build Coastguard Worker         a.push_back(a.front());
526*c8dee2aaSAndroid Build Coastguard Worker     }
527*c8dee2aaSAndroid Build Coastguard Worker     for (int x=0; x<50; ++x) {
528*c8dee2aaSAndroid Build Coastguard Worker         a.push_back(a.back());
529*c8dee2aaSAndroid Build Coastguard Worker     }
530*c8dee2aaSAndroid Build Coastguard Worker 
531*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == 101);
532*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, std::count(a.begin(), a.end(), 12345) == a.size());
533*c8dee2aaSAndroid Build Coastguard Worker }
534*c8dee2aaSAndroid Build Coastguard Worker 
535*c8dee2aaSAndroid Build Coastguard Worker struct EmplaceStruct {
EmplaceStructEmplaceStruct536*c8dee2aaSAndroid Build Coastguard Worker     EmplaceStruct(int v) : fValue(v) {}
537*c8dee2aaSAndroid Build Coastguard Worker     int fValue;
538*c8dee2aaSAndroid Build Coastguard Worker };
539*c8dee2aaSAndroid Build Coastguard Worker 
540*c8dee2aaSAndroid Build Coastguard Worker template <typename T>
test_inner_emplace(skiatest::Reporter * reporter)541*c8dee2aaSAndroid Build Coastguard Worker static void test_inner_emplace(skiatest::Reporter* reporter) {
542*c8dee2aaSAndroid Build Coastguard Worker     T a;
543*c8dee2aaSAndroid Build Coastguard Worker     a.emplace_back(12345);
544*c8dee2aaSAndroid Build Coastguard Worker     for (int x=0; x<50; ++x) {
545*c8dee2aaSAndroid Build Coastguard Worker         a.emplace_back(a.front().fValue);
546*c8dee2aaSAndroid Build Coastguard Worker     }
547*c8dee2aaSAndroid Build Coastguard Worker     for (int x=0; x<50; ++x) {
548*c8dee2aaSAndroid Build Coastguard Worker         a.emplace_back(a.back().fValue);
549*c8dee2aaSAndroid Build Coastguard Worker     }
550*c8dee2aaSAndroid Build Coastguard Worker 
551*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, a.size() == 101);
552*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, std::all_of(a.begin(), a.end(), [](const EmplaceStruct& s) {
553*c8dee2aaSAndroid Build Coastguard Worker                         return s.fValue == 12345;
554*c8dee2aaSAndroid Build Coastguard Worker                     }));
555*c8dee2aaSAndroid Build Coastguard Worker }
556*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(TArray_Basic,reporter)557*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(TArray_Basic, reporter) {
558*c8dee2aaSAndroid Build Coastguard Worker     // ints are POD types and can work with either MEM_MOVE=true or false.
559*c8dee2aaSAndroid Build Coastguard Worker     TestTSet_basic<TArray<int, true>>(reporter);
560*c8dee2aaSAndroid Build Coastguard Worker     TestTSet_basic<TArray<int, false>>(reporter);
561*c8dee2aaSAndroid Build Coastguard Worker 
562*c8dee2aaSAndroid Build Coastguard Worker     // TestClass has a vtable and can only work with MEM_MOVE=false.
563*c8dee2aaSAndroid Build Coastguard Worker     TestTSet_basic<TArray<TestClass, false>>(reporter);
564*c8dee2aaSAndroid Build Coastguard Worker }
565*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(FixedArray_Basic,reporter)566*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(FixedArray_Basic, reporter) {
567*c8dee2aaSAndroid Build Coastguard Worker     TestTSet_basic<FixedArray<5, char>>(reporter);
568*c8dee2aaSAndroid Build Coastguard Worker     TestTSet_basic<FixedArray<7, int>>(reporter);
569*c8dee2aaSAndroid Build Coastguard Worker     TestTSet_basic<FixedArray<100, double>>(reporter);
570*c8dee2aaSAndroid Build Coastguard Worker }
571*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(TArray_Reserve,reporter)572*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(TArray_Reserve, reporter) {
573*c8dee2aaSAndroid Build Coastguard Worker     test_reserve<TArray<int>>(reporter);
574*c8dee2aaSAndroid Build Coastguard Worker     test_reserve<STArray<1, int>>(reporter);
575*c8dee2aaSAndroid Build Coastguard Worker     test_reserve<STArray<2, int>>(reporter);
576*c8dee2aaSAndroid Build Coastguard Worker     test_reserve<STArray<16, int>>(reporter);
577*c8dee2aaSAndroid Build Coastguard Worker 
578*c8dee2aaSAndroid Build Coastguard Worker     test_reserve<TArray<TestClass>>(reporter);
579*c8dee2aaSAndroid Build Coastguard Worker     test_reserve<STArray<1, TestClass>>(reporter);
580*c8dee2aaSAndroid Build Coastguard Worker     test_reserve<STArray<2, TestClass>>(reporter);
581*c8dee2aaSAndroid Build Coastguard Worker     test_reserve<STArray<16, TestClass>>(reporter);
582*c8dee2aaSAndroid Build Coastguard Worker }
583*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(TArray_Construction,reporter)584*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(TArray_Construction, reporter) {
585*c8dee2aaSAndroid Build Coastguard Worker     test_construction<TArray<int>>(reporter);
586*c8dee2aaSAndroid Build Coastguard Worker     test_construction<TArray<double>>(reporter);
587*c8dee2aaSAndroid Build Coastguard Worker     test_construction<TArray<TestClass>>(reporter);
588*c8dee2aaSAndroid Build Coastguard Worker     test_construction<STArray<1, int>>(reporter);
589*c8dee2aaSAndroid Build Coastguard Worker     test_construction<STArray<5, char>>(reporter);
590*c8dee2aaSAndroid Build Coastguard Worker     test_construction<STArray<7, TestClass>>(reporter);
591*c8dee2aaSAndroid Build Coastguard Worker     test_construction<STArray<10, float>>(reporter);
592*c8dee2aaSAndroid Build Coastguard Worker }
593*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(FixedArray_Construction,reporter)594*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(FixedArray_Construction, reporter) {
595*c8dee2aaSAndroid Build Coastguard Worker     test_construction<FixedArray<15, int>>(reporter, /*hasMoveSemantics=*/false);
596*c8dee2aaSAndroid Build Coastguard Worker     test_construction<FixedArray<20, char>>(reporter, /*hasMoveSemantics=*/false);
597*c8dee2aaSAndroid Build Coastguard Worker     test_construction<FixedArray<25, float>>(reporter, /*hasMoveSemantics=*/false);
598*c8dee2aaSAndroid Build Coastguard Worker }
599*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(TArray_InnerPush,reporter)600*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(TArray_InnerPush, reporter) {
601*c8dee2aaSAndroid Build Coastguard Worker     test_inner_push<TArray<int>>(reporter);
602*c8dee2aaSAndroid Build Coastguard Worker     test_inner_push<STArray<1, int>>(reporter);
603*c8dee2aaSAndroid Build Coastguard Worker     test_inner_push<STArray<99, int>>(reporter);
604*c8dee2aaSAndroid Build Coastguard Worker     test_inner_push<STArray<200, int>>(reporter);
605*c8dee2aaSAndroid Build Coastguard Worker }
606*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(FixedArray_InnerPush,reporter)607*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(FixedArray_InnerPush, reporter) {
608*c8dee2aaSAndroid Build Coastguard Worker     test_inner_push<FixedArray<101, int>>(reporter);
609*c8dee2aaSAndroid Build Coastguard Worker     test_inner_push<FixedArray<150, short>>(reporter);
610*c8dee2aaSAndroid Build Coastguard Worker     test_inner_push<FixedArray<250, double>>(reporter);
611*c8dee2aaSAndroid Build Coastguard Worker }
612*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(TArray_InnerEmplace,reporter)613*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(TArray_InnerEmplace, reporter) {
614*c8dee2aaSAndroid Build Coastguard Worker     test_inner_emplace<TArray<EmplaceStruct>>(reporter);
615*c8dee2aaSAndroid Build Coastguard Worker     test_inner_emplace<STArray<1, EmplaceStruct>>(reporter);
616*c8dee2aaSAndroid Build Coastguard Worker     test_inner_emplace<STArray<99, EmplaceStruct>>(reporter);
617*c8dee2aaSAndroid Build Coastguard Worker     test_inner_emplace<STArray<200, EmplaceStruct>>(reporter);
618*c8dee2aaSAndroid Build Coastguard Worker }
619*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(TArray_STArrayCompatibility,reporter)620*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(TArray_STArrayCompatibility, reporter) {
621*c8dee2aaSAndroid Build Coastguard Worker     test_starray_compatibility<STArray<1, int>, TArray<int>>(reporter);
622*c8dee2aaSAndroid Build Coastguard Worker     test_starray_compatibility<STArray<5, char>, TArray<char>>(reporter);
623*c8dee2aaSAndroid Build Coastguard Worker     test_starray_compatibility<STArray<10, float>, TArray<float>>(reporter);
624*c8dee2aaSAndroid Build Coastguard Worker     test_starray_compatibility<TArray<int>, STArray<1, int>>(reporter);
625*c8dee2aaSAndroid Build Coastguard Worker     test_starray_compatibility<TArray<char>, STArray<5, char>>(reporter);
626*c8dee2aaSAndroid Build Coastguard Worker     test_starray_compatibility<TArray<float>, STArray<10, float>>(reporter);
627*c8dee2aaSAndroid Build Coastguard Worker     test_starray_compatibility<STArray<10, uint8_t>, STArray<1, uint8_t>>(reporter);
628*c8dee2aaSAndroid Build Coastguard Worker     test_starray_compatibility<STArray<1, long>, STArray<10, long>>(reporter);
629*c8dee2aaSAndroid Build Coastguard Worker     test_starray_compatibility<STArray<3, double>, STArray<4, double>>(reporter);
630*c8dee2aaSAndroid Build Coastguard Worker     test_starray_compatibility<STArray<2, short>, STArray<1, short>>(reporter);
631*c8dee2aaSAndroid Build Coastguard Worker }
632*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(TArray_BoundsCheck,reporter)633*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(TArray_BoundsCheck, reporter) {
634*c8dee2aaSAndroid Build Coastguard Worker #if 0  // The v[0] fails
635*c8dee2aaSAndroid Build Coastguard Worker     TArray<int> v;
636*c8dee2aaSAndroid Build Coastguard Worker     v[0];
637*c8dee2aaSAndroid Build Coastguard Worker #endif
638*c8dee2aaSAndroid Build Coastguard Worker }
639*c8dee2aaSAndroid Build Coastguard Worker 
640*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_SANITIZE_ADDRESS)
641*c8dee2aaSAndroid Build Coastguard Worker 
642*c8dee2aaSAndroid Build Coastguard Worker template <typename Array>
verify_poison(skiatest::Reporter * r,const Array & array)643*c8dee2aaSAndroid Build Coastguard Worker static void verify_poison(skiatest::Reporter* r, const Array& array) {
644*c8dee2aaSAndroid Build Coastguard Worker     int allocated = array.size() * sizeof(typename Array::value_type);
645*c8dee2aaSAndroid Build Coastguard Worker     int capacity = array.capacity() * sizeof(typename Array::value_type);
646*c8dee2aaSAndroid Build Coastguard Worker     const std::byte* data = reinterpret_cast<const std::byte*>(array.data());
647*c8dee2aaSAndroid Build Coastguard Worker 
648*c8dee2aaSAndroid Build Coastguard Worker     for (int index = 0; index < allocated; ++index) {
649*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, !sk_asan_address_is_poisoned(data + index));
650*c8dee2aaSAndroid Build Coastguard Worker     }
651*c8dee2aaSAndroid Build Coastguard Worker 
652*c8dee2aaSAndroid Build Coastguard Worker     // ASAN user poisoning is conservative for ranges that are smaller than eight bytes long.
653*c8dee2aaSAndroid Build Coastguard Worker     // We guarantee this alignment via SkContainerAllocator (because kCapacityMultiple == 8).
654*c8dee2aaSAndroid Build Coastguard Worker     // https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm#mapping
655*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, capacity >= 8);
656*c8dee2aaSAndroid Build Coastguard Worker     for (int index = allocated; index < capacity; ++index) {
657*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, sk_asan_address_is_poisoned(data + index));
658*c8dee2aaSAndroid Build Coastguard Worker     }
659*c8dee2aaSAndroid Build Coastguard Worker }
660*c8dee2aaSAndroid Build Coastguard Worker 
661*c8dee2aaSAndroid Build Coastguard Worker template <typename Array>
test_poison(skiatest::Reporter * reporter)662*c8dee2aaSAndroid Build Coastguard Worker static void test_poison(skiatest::Reporter* reporter) {
663*c8dee2aaSAndroid Build Coastguard Worker     Array array;
664*c8dee2aaSAndroid Build Coastguard Worker 
665*c8dee2aaSAndroid Build Coastguard Worker     for (int index = 0; index < 20; ++index) {
666*c8dee2aaSAndroid Build Coastguard Worker         array.emplace_back();
667*c8dee2aaSAndroid Build Coastguard Worker         verify_poison(reporter, array);
668*c8dee2aaSAndroid Build Coastguard Worker     }
669*c8dee2aaSAndroid Build Coastguard Worker 
670*c8dee2aaSAndroid Build Coastguard Worker     for (int index = 0; index < 20; ++index) {
671*c8dee2aaSAndroid Build Coastguard Worker         array.pop_back();
672*c8dee2aaSAndroid Build Coastguard Worker         verify_poison(reporter, array);
673*c8dee2aaSAndroid Build Coastguard Worker     }
674*c8dee2aaSAndroid Build Coastguard Worker 
675*c8dee2aaSAndroid Build Coastguard Worker     for (int index = 0; index < 20; ++index) {
676*c8dee2aaSAndroid Build Coastguard Worker         array.reserve(array.capacity() + 3);
677*c8dee2aaSAndroid Build Coastguard Worker         verify_poison(reporter, array);
678*c8dee2aaSAndroid Build Coastguard Worker     }
679*c8dee2aaSAndroid Build Coastguard Worker 
680*c8dee2aaSAndroid Build Coastguard Worker     array.clear();
681*c8dee2aaSAndroid Build Coastguard Worker     verify_poison(reporter, array);
682*c8dee2aaSAndroid Build Coastguard Worker }
683*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(TArray_ASANPoisoning,reporter)684*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(TArray_ASANPoisoning, reporter) {
685*c8dee2aaSAndroid Build Coastguard Worker     test_poison<TArray<int>>(reporter);
686*c8dee2aaSAndroid Build Coastguard Worker     test_poison<STArray<1, double>>(reporter);
687*c8dee2aaSAndroid Build Coastguard Worker     test_poison<STArray<2, char>>(reporter);
688*c8dee2aaSAndroid Build Coastguard Worker     test_poison<STArray<16, TestClass>>(reporter);
689*c8dee2aaSAndroid Build Coastguard Worker }
690*c8dee2aaSAndroid Build Coastguard Worker 
691*c8dee2aaSAndroid Build Coastguard Worker #endif
692