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