Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Functions
TArrayTest.cpp File Reference
#include "include/private/base/SkASAN.h"
#include "include/private/base/SkTArray.h"
#include "src/base/SkRandom.h"
#include "tests/Test.h"
#include <array>
#include <cstdint>
#include <initializer_list>
#include <utility>

Go to the source code of this file.

Classes

struct  EmplaceStruct
 

Functions

template<typename T , bool MEM_MOVE>
static void TestTSet_basic (skiatest::Reporter *reporter)
 
template<typename T >
static void test_construction (skiatest::Reporter *reporter)
 
template<typename T , typename U >
static void test_skstarray_compatibility (skiatest::Reporter *reporter)
 
template<typename T >
static void test_swap (skiatest::Reporter *reporter, SkSpan< TArray< T > * > arrays, SkSpan< const int > sizes)
 
static void test_swap (skiatest::Reporter *reporter)
 
template<typename T >
static void test_array_move (skiatest::Reporter *reporter, SkSpan< TArray< T > * > arrays, SkSpan< const int > sizes)
 
static void test_array_move (skiatest::Reporter *reporter)
 
void test_unnecessary_alloc (skiatest::Reporter *reporter)
 
static void test_self_assignment (skiatest::Reporter *reporter)
 
template<typename Array >
static void test_array_reserve (skiatest::Reporter *reporter, Array *array, int reserveCount)
 
template<typename Array >
static void test_reserve (skiatest::Reporter *reporter)
 
template<typename T >
static void test_inner_push (skiatest::Reporter *reporter)
 
template<typename T >
static void test_inner_emplace (skiatest::Reporter *reporter)
 
 DEF_TEST (TArray, reporter)
 
 DEF_TEST (TArray_BoundsCheck, reporter)
 

Function Documentation

◆ DEF_TEST() [1/2]

DEF_TEST ( TArray  ,
reporter   
)

Definition at line 472 of file TArrayTest.cpp.

472 {
473 // ints are POD types and can work with either MEM_MOVE=true or false.
474 TestTSet_basic<int, true>(reporter);
475 TestTSet_basic<int, false>(reporter);
476
477 // TestClass has a vtable and can only work with MEM_MOVE=false.
478 TestTSet_basic<TestClass, false>(reporter);
479
482
484
486
487 test_reserve<TArray<int>>(reporter);
488 test_reserve<STArray<1, int>>(reporter);
489 test_reserve<STArray<2, int>>(reporter);
490 test_reserve<STArray<16, int>>(reporter);
491
492 test_reserve<TArray<TestClass>>(reporter);
493 test_reserve<STArray<1, TestClass>>(reporter);
494 test_reserve<STArray<2, TestClass>>(reporter);
495 test_reserve<STArray<16, TestClass>>(reporter);
496
497 test_construction<TArray<int>>(reporter);
498 test_construction<TArray<double>>(reporter);
499 test_construction<TArray<TestClass>>(reporter);
500 test_construction<STArray<1, int>>(reporter);
501 test_construction<STArray<5, char>>(reporter);
502 test_construction<STArray<7, TestClass>>(reporter);
503 test_construction<STArray<10, float>>(reporter);
504
505 test_inner_push<TArray<int>>(reporter);
506 test_inner_push<STArray<1, int>>(reporter);
507 test_inner_push<STArray<99, int>>(reporter);
508 test_inner_push<STArray<200, int>>(reporter);
509
510 test_inner_emplace<TArray<EmplaceStruct>>(reporter);
511 test_inner_emplace<STArray<1, EmplaceStruct>>(reporter);
512 test_inner_emplace<STArray<99, EmplaceStruct>>(reporter);
513 test_inner_emplace<STArray<200, EmplaceStruct>>(reporter);
514
515 test_skstarray_compatibility<STArray<1, int>, TArray<int>>(reporter);
516 test_skstarray_compatibility<STArray<5, char>, TArray<char>>(reporter);
517 test_skstarray_compatibility<STArray<10, float>, TArray<float>>(reporter);
518 test_skstarray_compatibility<TArray<int>, STArray<1, int>>(reporter);
519 test_skstarray_compatibility<TArray<char>, STArray<5, char>>(reporter);
520 test_skstarray_compatibility<TArray<float>, STArray<10, float>>(reporter);
521 test_skstarray_compatibility<STArray<10, uint8_t>, STArray<1, uint8_t>>(reporter);
522 test_skstarray_compatibility<STArray<1, long>, STArray<10, long>>(reporter);
523 test_skstarray_compatibility<STArray<3, double>, STArray<4, double>>(reporter);
524 test_skstarray_compatibility<STArray<2, short>, STArray<1, short>>(reporter);
525}
reporter
void test_unnecessary_alloc(skiatest::Reporter *reporter)
static void test_swap(skiatest::Reporter *reporter, SkSpan< TArray< T > * > arrays, SkSpan< const int > sizes)
static void test_array_move(skiatest::Reporter *reporter, SkSpan< TArray< T > * > arrays, SkSpan< const int > sizes)
static void test_self_assignment(skiatest::Reporter *reporter)

◆ DEF_TEST() [2/2]

DEF_TEST ( TArray_BoundsCheck  ,
reporter   
)

Definition at line 527 of file TArrayTest.cpp.

527 {
528#if 0 // The v[0] fails
529 TArray<int> v;
530 v[0];
531#endif
532}

◆ test_array_move() [1/2]

static void test_array_move ( skiatest::Reporter reporter)
static

Definition at line 300 of file TArrayTest.cpp.

300 {
301 static constexpr int kSizes[] = {0, 1, 5, 10, 15, 20, 25};
302
303 TArray<int> arr;
304 STArray< 5, int> arr5;
305 STArray<10, int> arr10;
306 STArray<20, int> arr20;
307 TArray<int>* arrays[] = { &arr, &arr5, &arr10, &arr20 };
308 test_array_move<int>(reporter, arrays, kSizes);
309
314 TArray<MoveOnlyInt>* arraysMoi[] = { &moi, &moi5, &moi10, &moi20 };
315 test_array_move<MoveOnlyInt>(reporter, arraysMoi, kSizes);
316}

◆ test_array_move() [2/2]

template<typename T >
static void test_array_move ( skiatest::Reporter reporter,
SkSpan< TArray< T > * >  arrays,
SkSpan< const int sizes 
)
static

Definition at line 259 of file TArrayTest.cpp.

261 {
262 // self test is a no-op
263 for (auto a : arrays) {
264 for (auto sizeA : sizes) {
265 a->clear();
266 for (int i = 0; i < sizeA; i++) { a->push_back(i); }
267 a->move_back(*a);
268 REPORTER_ASSERT(reporter, a->size() == sizeA);
269 for (int i = 0; i < sizeA; i++) {
270 REPORTER_ASSERT(reporter, (*a)[i] == i);
271 }
272 }
273 }
274
275 for (auto a : arrays) {
276 for (auto b : arrays) {
277 if (a == b) {
278 continue;
279 }
280
281 for (auto sizeA : sizes) {
282 for (auto sizeB : sizes) {
283 a->clear();
284 b->clear();
285
286 int curr = 0;
287 for (int i = 0; i < sizeA; i++) { a->push_back(curr++); }
288 for (int i = 0; i < sizeB; i++) { b->push_back(curr++); }
289
290 a->move_back(*b);
291 REPORTER_ASSERT(reporter, b->size() == 0);
292 REPORTER_ASSERT(reporter, a->size() == sizeA + sizeB);
293
294 curr = 0;
295 for (auto&& x : *a) { REPORTER_ASSERT(reporter, x == curr++); }
296 }}
297 }}
298}
#define REPORTER_ASSERT(r, cond,...)
Definition Test.h:286
static bool b
struct MyStruct a[10]
double x

◆ test_array_reserve()

template<typename Array >
static void test_array_reserve ( skiatest::Reporter reporter,
Array *  array,
int  reserveCount 
)
static

Definition at line 389 of file TArrayTest.cpp.

390 {
391 SkRandom random;
392 REPORTER_ASSERT(reporter, array->capacity() >= reserveCount);
393 array->push_back();
394 REPORTER_ASSERT(reporter, array->capacity() >= reserveCount);
395 array->pop_back();
396 REPORTER_ASSERT(reporter, array->capacity() >= reserveCount);
397 while (array->size() < reserveCount) {
398 // Two steps forward, one step back
399 if (random.nextULessThan(3) < 2) {
400 array->push_back();
401 } else if (array->size() > 0) {
402 array->pop_back();
403 }
404 REPORTER_ASSERT(reporter, array->capacity() >= reserveCount);
405 }
406}
uint32_t nextULessThan(uint32_t count)
Definition SkRandom.h:93

◆ test_construction()

template<typename T >
static void test_construction ( skiatest::Reporter reporter)
static

Definition at line 89 of file TArrayTest.cpp.

89 {
90 using ValueType = typename T::value_type;
91
92 // No arguments: Creates an empty array with no initial storage.
93 T arrayNoArgs;
94 REPORTER_ASSERT(reporter, arrayNoArgs.empty());
95
96 // Single integer: Creates an empty array that will preallocate space for reserveCount elements.
97 T arrayReserve(15);
98 REPORTER_ASSERT(reporter, arrayReserve.empty());
99 // May get some extra elements for free because sk_allocate_* can round up.
100 REPORTER_ASSERT(reporter, arrayReserve.capacity() >= 15 && arrayReserve.capacity() < 50);
101
102 // Another array, const&: Copies one array to another.
103 T arrayInitial;
104 arrayInitial.push_back(ValueType{1});
105 arrayInitial.push_back(ValueType{2});
106 arrayInitial.push_back(ValueType{3});
107
108 T arrayCopy(arrayInitial);
109 REPORTER_ASSERT(reporter, arrayInitial.size() == 3);
110 REPORTER_ASSERT(reporter, arrayInitial[0] == ValueType{1});
111 REPORTER_ASSERT(reporter, arrayInitial[1] == ValueType{2});
112 REPORTER_ASSERT(reporter, arrayInitial[2] == ValueType{3});
113 REPORTER_ASSERT(reporter, arrayCopy.size() == 3);
114 REPORTER_ASSERT(reporter, arrayCopy[0] == ValueType{1});
115 REPORTER_ASSERT(reporter, arrayCopy[1] == ValueType{2});
116 REPORTER_ASSERT(reporter, arrayCopy[2] == ValueType{3});
117
118 // Another array, &&: Moves one array to another.
119 T arrayMove(std::move(arrayInitial));
120 REPORTER_ASSERT(reporter, arrayInitial.empty()); // NOLINT(bugprone-use-after-move)
121 REPORTER_ASSERT(reporter, arrayMove.size() == 3);
122 REPORTER_ASSERT(reporter, arrayMove[0] == ValueType{1});
123 REPORTER_ASSERT(reporter, arrayMove[1] == ValueType{2});
124 REPORTER_ASSERT(reporter, arrayMove[2] == ValueType{3});
125
126 // Pointer and count: Copies contents of a standard C array.
127 typename T::value_type data[3] = { 7, 8, 9 };
128 T arrayPtrCount(data, 3);
129 REPORTER_ASSERT(reporter, arrayPtrCount.size() == 3);
130 REPORTER_ASSERT(reporter, arrayPtrCount[0] == ValueType{7});
131 REPORTER_ASSERT(reporter, arrayPtrCount[1] == ValueType{8});
132 REPORTER_ASSERT(reporter, arrayPtrCount[2] == ValueType{9});
133
134 // Initializer list.
135 T arrayInitializer{8, 6, 7, 5, 3, 0, 9};
136 REPORTER_ASSERT(reporter, arrayInitializer.size() == 7);
137 REPORTER_ASSERT(reporter, arrayInitializer[0] == ValueType{8});
138 REPORTER_ASSERT(reporter, arrayInitializer[1] == ValueType{6});
139 REPORTER_ASSERT(reporter, arrayInitializer[2] == ValueType{7});
140 REPORTER_ASSERT(reporter, arrayInitializer[3] == ValueType{5});
141 REPORTER_ASSERT(reporter, arrayInitializer[4] == ValueType{3});
142 REPORTER_ASSERT(reporter, arrayInitializer[5] == ValueType{0});
143 REPORTER_ASSERT(reporter, arrayInitializer[6] == ValueType{9});
144}
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
#define T

◆ test_inner_emplace()

template<typename T >
static void test_inner_emplace ( skiatest::Reporter reporter)
static

Definition at line 456 of file TArrayTest.cpp.

456 {
457 T a;
458 a.emplace_back(12345);
459 for (int x=0; x<50; ++x) {
460 a.emplace_back(a.front().fValue);
461 }
462 for (int x=0; x<50; ++x) {
463 a.emplace_back(a.back().fValue);
464 }
465
466 REPORTER_ASSERT(reporter, a.size() == 101);
467 REPORTER_ASSERT(reporter, std::all_of(a.begin(), a.end(), [](const EmplaceStruct& s) {
468 return s.fValue == 12345;
469 }));
470}
struct MyStruct s

◆ test_inner_push()

template<typename T >
static void test_inner_push ( skiatest::Reporter reporter)
static

Definition at line 436 of file TArrayTest.cpp.

436 {
437 T a;
438 a.push_back(12345);
439 for (int x=0; x<50; ++x) {
440 a.push_back(a.front());
441 }
442 for (int x=0; x<50; ++x) {
443 a.push_back(a.back());
444 }
445
446 REPORTER_ASSERT(reporter, a.size() == 101);
447 REPORTER_ASSERT(reporter, std::count(a.begin(), a.end(), 12345) == a.size());
448}

◆ test_reserve()

template<typename Array >
static void test_reserve ( skiatest::Reporter reporter)
static

Definition at line 408 of file TArrayTest.cpp.

408 {
409 // Test that our allocated space stays >= to the reserve count until the array is filled to
410 // the reserve count
411 for (int reserveCount : {1, 2, 10, 100}) {
412 // Test setting reserve in constructor.
413 Array array1(reserveCount);
414 test_array_reserve(reporter, &array1, reserveCount);
415
416 // Test setting reserve after constructor.
417 Array array2;
418 array2.reserve(reserveCount);
419 test_array_reserve(reporter, &array2, reserveCount);
420
421 // Test increasing reserve after constructor.
422 Array array3(reserveCount/2);
423 array3.reserve(reserveCount);
424 test_array_reserve(reporter, &array3, reserveCount);
425
426 // Test setting reserve on non-empty array.
427 Array array4;
428 array4.push_back_n(reserveCount);
429 array4.reserve(2 * reserveCount);
430 array4.pop_back_n(reserveCount);
431 test_array_reserve(reporter, &array4, 2 * reserveCount);
432 }
433}
static void test_array_reserve(skiatest::Reporter *reporter, Array *array, int reserveCount)

◆ test_self_assignment()

static void test_self_assignment ( skiatest::Reporter reporter)
static

Definition at line 376 of file TArrayTest.cpp.

376 {
378 a.push_back(1);
379 REPORTER_ASSERT(reporter, !a.empty());
380 REPORTER_ASSERT(reporter, a.size() == 1);
381 REPORTER_ASSERT(reporter, a[0] == 1);
382
383 a = static_cast<decltype(a)&>(a);
384 REPORTER_ASSERT(reporter, !a.empty());
385 REPORTER_ASSERT(reporter, a.size() == 1);
386 REPORTER_ASSERT(reporter, a[0] == 1);
387}

◆ test_skstarray_compatibility()

template<typename T , typename U >
static void test_skstarray_compatibility ( skiatest::Reporter reporter)
static

Definition at line 147 of file TArrayTest.cpp.

147 {
148 // We expect SkTArrays of the same type to be copyable and movable, even when:
149 // - one side is an SkTArray, and the other side is an SkSTArray
150 // - both sides are SkSTArray, but each side has a different internal capacity
151 T tArray;
152 tArray.push_back(1);
153 tArray.push_back(2);
154 tArray.push_back(3);
155 T tArray2 = tArray;
156
157 // Copy construction from other-type array.
158 U arrayCopy(tArray);
159 REPORTER_ASSERT(reporter, tArray.size() == 3);
160 REPORTER_ASSERT(reporter, tArray[0] == 1);
161 REPORTER_ASSERT(reporter, tArray[1] == 2);
162 REPORTER_ASSERT(reporter, tArray[2] == 3);
163 REPORTER_ASSERT(reporter, arrayCopy.size() == 3);
164 REPORTER_ASSERT(reporter, arrayCopy[0] == 1);
165 REPORTER_ASSERT(reporter, arrayCopy[1] == 2);
166 REPORTER_ASSERT(reporter, arrayCopy[2] == 3);
167
168 // Assignment from other-type array.
169 U arrayAssignment;
170 arrayAssignment = tArray;
171 REPORTER_ASSERT(reporter, tArray.size() == 3);
172 REPORTER_ASSERT(reporter, tArray[0] == 1);
173 REPORTER_ASSERT(reporter, tArray[1] == 2);
174 REPORTER_ASSERT(reporter, tArray[2] == 3);
175 REPORTER_ASSERT(reporter, arrayAssignment.size() == 3);
176 REPORTER_ASSERT(reporter, arrayAssignment[0] == 1);
177 REPORTER_ASSERT(reporter, arrayAssignment[1] == 2);
178 REPORTER_ASSERT(reporter, arrayAssignment[2] == 3);
179
180 // Move construction from other-type array.
181 U arrayMove(std::move(tArray));
182 REPORTER_ASSERT(reporter, tArray.empty()); // NOLINT(bugprone-use-after-move)
183 REPORTER_ASSERT(reporter, arrayMove.size() == 3);
184 REPORTER_ASSERT(reporter, arrayMove[0] == 1);
185 REPORTER_ASSERT(reporter, arrayMove[1] == 2);
186 REPORTER_ASSERT(reporter, arrayMove[2] == 3);
187
188 // Move assignment from other-type array.
189 U arrayMoveAssign;
190 arrayMoveAssign = std::move(tArray2);
191 REPORTER_ASSERT(reporter, tArray2.empty()); // NOLINT(bugprone-use-after-move)
192 REPORTER_ASSERT(reporter, arrayMoveAssign.size() == 3);
193 REPORTER_ASSERT(reporter, arrayMoveAssign[0] == 1);
194 REPORTER_ASSERT(reporter, arrayMoveAssign[1] == 2);
195 REPORTER_ASSERT(reporter, arrayMoveAssign[2] == 3);
196}

◆ test_swap() [1/2]

static void test_swap ( skiatest::Reporter reporter)
static

Definition at line 241 of file TArrayTest.cpp.

241 {
242 static constexpr int kSizes[] = {0, 1, 5, 10, 15, 20, 25};
243
244 TArray<int> arr;
245 STArray< 5, int> arr5;
246 STArray<10, int> arr10;
247 STArray<20, int> arr20;
248 TArray<int>* arrays[] = { &arr, &arr5, &arr10, &arr20 };
249 test_swap<int>(reporter, arrays, kSizes);
250
255 TArray<MoveOnlyInt>* arraysMoi[] = { &moi, &moi5, &moi10, &moi20 };
256 test_swap<MoveOnlyInt>(reporter, arraysMoi, kSizes);
257}

◆ test_swap() [2/2]

template<typename T >
static void test_swap ( skiatest::Reporter reporter,
SkSpan< TArray< T > * >  arrays,
SkSpan< const int sizes 
)
static

Definition at line 208 of file TArrayTest.cpp.

210 {
211 for (auto a : arrays) {
212 for (auto b : arrays) {
213 if (a == b) {
214 continue;
215 }
216
217 for (auto sizeA : sizes) {
218 for (auto sizeB : sizes) {
219 a->clear();
220 b->clear();
221
222 int curr = 0;
223 for (int i = 0; i < sizeA; i++) { a->push_back(curr++); }
224 for (int i = 0; i < sizeB; i++) { b->push_back(curr++); }
225
226 a->swap(*b);
227 REPORTER_ASSERT(reporter, b->size() == sizeA);
228 REPORTER_ASSERT(reporter, a->size() == sizeB);
229
230 curr = 0;
231 for (auto&& x : *b) { REPORTER_ASSERT(reporter, x == curr++); }
232 for (auto&& x : *a) { REPORTER_ASSERT(reporter, x == curr++); }
233
234 a->swap(*a);
235 curr = sizeA;
236 for (auto&& x : *a) { REPORTER_ASSERT(reporter, x == curr++); }
237 }}
238 }}
239}

◆ test_unnecessary_alloc()

void test_unnecessary_alloc ( skiatest::Reporter reporter)

Definition at line 318 of file TArrayTest.cpp.

318 {
319 {
321 REPORTER_ASSERT(reporter, a.capacity() == 0);
322 }
323 {
325 REPORTER_ASSERT(reporter, a.capacity() == 10);
326 }
327 {
328 TArray<int> a(1);
329 REPORTER_ASSERT(reporter, a.capacity() >= 1);
330 }
331 {
332 TArray<int> a, b;
333 b = a;
334 REPORTER_ASSERT(reporter, b.capacity() == 0);
335 }
336 {
339 b = a;
340 REPORTER_ASSERT(reporter, b.capacity() == 0);
341 }
342 {
344 TArray<int> b(a); // NOLINT(performance-unnecessary-copy-initialization)
345 REPORTER_ASSERT(reporter, b.capacity() == 0);
346 }
347 {
349 TArray<int> b(a); // NOLINT(performance-unnecessary-copy-initialization)
350 REPORTER_ASSERT(reporter, b.capacity() == 0);
351 }
352 {
354 TArray<int> b(std::move(a));
355 REPORTER_ASSERT(reporter, b.capacity() == 0);
356 }
357 {
359 TArray<int> b(std::move(a));
360 REPORTER_ASSERT(reporter, b.capacity() == 0);
361 }
362 {
365 b = std::move(a);
366 REPORTER_ASSERT(reporter, b.capacity() == 0);
367 }
368 {
371 b = std::move(a);
372 REPORTER_ASSERT(reporter, b.capacity() == 0);
373 }
374}

◆ TestTSet_basic()

template<typename T , bool MEM_MOVE>
static void TestTSet_basic ( skiatest::Reporter reporter)
static

Definition at line 42 of file TArrayTest.cpp.

42 {
44
45 // Starts empty.
46 REPORTER_ASSERT(reporter, a.empty());
47 REPORTER_ASSERT(reporter, a.size() == 0);
48
49 // { }, add a default constructed element
50 a.push_back() = T{0};
51 REPORTER_ASSERT(reporter, !a.empty());
52 REPORTER_ASSERT(reporter, a.size() == 1);
53
54 // { 0 }, removeShuffle the only element.
55 a.removeShuffle(0);
56 REPORTER_ASSERT(reporter, a.empty());
57 REPORTER_ASSERT(reporter, a.size() == 0);
58
59 // { }, add a default, add a 1, remove first
60 a.push_back() = T{0};
61 a.push_back() = T{1};
62 a.removeShuffle(0);
63 REPORTER_ASSERT(reporter, !a.empty());
64 REPORTER_ASSERT(reporter, a.size() == 1);
65 REPORTER_ASSERT(reporter, a[0] == T{1});
66
67 // { 1 }, replace with new array
68 T b[5] = {T{0}, T{1}, T{2}, T{3}, T{4}};
69 a.reset(b, std::size(b));
70 REPORTER_ASSERT(reporter, a.size() == std::size(b));
71 REPORTER_ASSERT(reporter, a[2] == T{2});
72 REPORTER_ASSERT(reporter, a[4] == T{4});
73
74 // { 0, 1, 2, 3, 4 }, removeShuffle the last
75 a.removeShuffle(4);
76 REPORTER_ASSERT(reporter, a.size() == std::size(b) - 1);
77 REPORTER_ASSERT(reporter, a[3] == T{3});
78
79 // { 0, 1, 2, 3 }, remove a middle, note shuffle
80 a.removeShuffle(1);
81 REPORTER_ASSERT(reporter, a.size() == std::size(b) - 2);
82 REPORTER_ASSERT(reporter, a[0] == T{0});
83 REPORTER_ASSERT(reporter, a[1] == T{3});
84 REPORTER_ASSERT(reporter, a[2] == T{2});
85
86 // { 0, 3, 2 }
87}