Flutter Engine
The Flutter Engine
UtilsTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2011 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
11#include "src/base/SkRandom.h"
12#include "src/base/SkTSearch.h"
13#include "src/base/SkTSort.h"
14#include "src/base/SkUtils.h"
15#include "src/base/SkZip.h"
17#include "tests/Test.h"
18
19#include <array>
20#include <cstddef>
21#include <cstdint>
22#include <initializer_list>
23#include <memory>
24#include <new>
25#include <tuple>
26#include <utility>
27#include <vector>
28
29using namespace skia_private;
30
31class RefClass : public SkRefCnt {
32public:
33 RefClass(int n) : fN(n) {}
34 int get() const { return fN; }
35
36private:
37 int fN;
38
39 using INHERITED = SkRefCnt;
40};
41
43 RefClass obj(0);
45
46 sk_sp<RefClass> tmp(&obj);
47 REPORTER_ASSERT(reporter, &obj == tmp.get());
49
50 REPORTER_ASSERT(reporter, &obj == tmp.release());
52 REPORTER_ASSERT(reporter, nullptr == tmp.release());
53 REPORTER_ASSERT(reporter, nullptr == tmp.get());
54
55 obj.ref();
57 {
58 sk_sp<RefClass> tmp2(&obj);
59 }
61}
62
64 RefClass obj0(0);
65 RefClass obj1(1);
68
69 {
71 REPORTER_ASSERT(reporter, 0 == tmp.count());
72
73 tmp.reset(0); // test out reset(0) when already at 0
74 tmp.reset(4); // this should force a new allocation
75 REPORTER_ASSERT(reporter, 4 == tmp.count());
76 tmp[0].reset(SkRef(&obj0));
77 tmp[1].reset(SkRef(&obj1));
80
81 // test out reset with data in the array (and a new allocation)
82 tmp.reset(0);
83 REPORTER_ASSERT(reporter, 0 == tmp.count());
86
87 tmp.reset(2); // this should use the preexisting allocation
88 REPORTER_ASSERT(reporter, 2 == tmp.count());
89 tmp[0].reset(SkRef(&obj0));
90 tmp[1].reset(SkRef(&obj1));
91 }
92
93 // test out destructor with data in the array (and using existing allocation)
96
97 {
98 // test out allocating ctor (this should allocate new memory)
100 REPORTER_ASSERT(reporter, 4 == tmp.count());
101
102 tmp[0].reset(SkRef(&obj0));
103 tmp[1].reset(SkRef(&obj1));
106
107 // Test out resut with data in the array and malloced storage
108 tmp.reset(0);
111
112 tmp.reset(2); // this should use the preexisting storage
113 tmp[0].reset(SkRef(&obj0));
114 tmp[1].reset(SkRef(&obj1));
117
118 tmp.reset(4); // this should force a new malloc
121
122 tmp[0].reset(SkRef(&obj0));
123 tmp[1].reset(SkRef(&obj1));
126 }
127
130}
131
132/////////////////////////////////////////////////////////////////////////////
133
134#define kSEARCH_COUNT 91
135
137 int i, array[kSEARCH_COUNT];
138 SkRandom rand;
139
140 for (i = 0; i < kSEARCH_COUNT; i++) {
141 array[i] = rand.nextS();
142 }
143
144 SkTHeapSort<int>(array, kSEARCH_COUNT);
145 // make sure we got sorted properly
146 for (i = 1; i < kSEARCH_COUNT; i++) {
147 REPORTER_ASSERT(reporter, array[i-1] <= array[i]);
148 }
149
150 // make sure we can find all of our values
151 for (i = 0; i < kSEARCH_COUNT; i++) {
152 int index = SkTSearch<int>(array, kSEARCH_COUNT, array[i], sizeof(int));
153 REPORTER_ASSERT(reporter, index == i);
154 }
155
156 // make sure that random values are either found, or the correct
157 // insertion index is returned
158 for (i = 0; i < 10000; i++) {
159 int value = rand.nextS();
160 int index = SkTSearch<int>(array, kSEARCH_COUNT, value, sizeof(int));
161
162 if (index >= 0) {
164 index < kSEARCH_COUNT && array[index] == value);
165 } else {
166 index = ~index;
168 if (index < kSEARCH_COUNT) {
169 REPORTER_ASSERT(reporter, value < array[index]);
170 if (index > 0) {
171 REPORTER_ASSERT(reporter, value > array[index - 1]);
172 }
173 } else {
174 // we should append the new value
176 }
177 }
178 }
179}
180
185}
186
188
189 int A[] = {1, 2, 3, 4};
190 auto enumeration = SkMakeEnumerate(A);
191
192 size_t check = 0;
193 for (auto [i, v] : enumeration) {
195 REPORTER_ASSERT(reporter, v == (int)check+1);
196
197 check++;
198 }
199
200 check = 0;
201 for (auto [i, v] : SkMakeEnumerate(A)) {
203 REPORTER_ASSERT(reporter, v == (int)check+1);
204
205 check++;
206 }
207
208 check = 0;
209 std::vector<int> vec = {1, 2, 3, 4};
210 for (auto [i, v] : SkMakeEnumerate(vec)) {
212 REPORTER_ASSERT(reporter, v == (int)check+1);
213 check++;
214 }
216
217 check = 0;
218 for (auto [i, v] : SkMakeEnumerate(SkSpan(vec))) {
220 REPORTER_ASSERT(reporter, v == (int)check+1);
221 check++;
222 }
223
224 {
225 auto e = SkMakeEnumerate(SkSpan(vec)).first(2);
226 for (auto[i, v] : e) {
227 REPORTER_ASSERT(reporter, v == (int) i + 1);
228 }
229 REPORTER_ASSERT(reporter, e.size() == 2);
230 }
231
232 {
233 auto e = SkMakeEnumerate(SkSpan(vec)).last(2);
234 for (auto[i, v] : e) {
235 REPORTER_ASSERT(reporter, v == (int) i + 1);
236 }
237 REPORTER_ASSERT(reporter, e.size() == 2);
238 }
239
240 {
241 auto e = SkMakeEnumerate(SkSpan(vec)).subspan(1, 2);
242 for (auto[i, v] : e) {
243 REPORTER_ASSERT(reporter, v == (int) i + 1);
244 }
245 REPORTER_ASSERT(reporter, e.size() == 2);
246 }
247
248 {
249 struct I {
250 I() = default;
251 I(const I&) = default;
252 I(int v) : i{v} { }
253 ~I() {}
254 int i;
255 };
256
257 I is[10];
258 auto s = SkSpan(is);
259 for (auto [i, v] : SkMakeEnumerate(s)) {
260 new (&v) I(i);
261 }
262
263 for (size_t i = 0; i < s.size(); i++) {
264 REPORTER_ASSERT(reporter, s[i].i == (int)i);
265 REPORTER_ASSERT(reporter, is[i].i == (int)i);
266 }
267 }
268
269 {
270 std::unique_ptr<int> is[10];
271 std::unique_ptr<int> os[10];
272 auto s = SkSpan(is);
273 for (auto [i, v] : SkMakeEnumerate(s)) {
274 v = std::make_unique<int>(i);
275 }
276
277 for (auto [i, v] : SkMakeEnumerate(SkSpan(os))) {
278 v = std::move(s[i]);
279 }
280
281 for (size_t i = 0; i < s.size(); i++) {
282 REPORTER_ASSERT(reporter, *os[i] == (int)i);
283 REPORTER_ASSERT(reporter, is[i] == nullptr);
284 }
285 }
286
287 {
288 std::unique_ptr<int> is[10];
289 std::unique_ptr<int> os[10];
290 auto s = SkSpan(is);
291 for (auto [i, v] : SkMakeEnumerate(s)) {
292 v = std::make_unique<int>(i);
293 }
294
295 for (auto [i, ov, iv] : SkMakeEnumerate(SkMakeZip(os, is))) {
296 ov = std::move(iv);
297 }
298
299 for (size_t i = 0; i < s.size(); i++) {
300 REPORTER_ASSERT(reporter, *os[i] == (int)i);
301 REPORTER_ASSERT(reporter, is[i] == nullptr);
302 }
303 }
304}
305
307 uint16_t A[] = {1, 2, 3, 4};
308 const float B[] = {10.f, 20.f, 30.f, 40.f};
309 std::vector<int> C = {{20, 30, 40, 50}};
310 std::array<int, 4> D = {{100, 200, 300, 400}};
312
313 // Check SkZip calls
315 z{4, &A[0], &B[0], C.data(), D.data(), S.data()};
316
317 REPORTER_ASSERT(reporter, z.size() == 4);
318 REPORTER_ASSERT(reporter, !z.empty());
319
320 {
321 // Check front
322 auto t = z.front();
325 REPORTER_ASSERT(reporter, std::get<2>(t) == 20);
326 REPORTER_ASSERT(reporter, std::get<3>(t) == 100);
327 REPORTER_ASSERT(reporter, std::get<4>(t) == 20);
328 }
329
330 {
331 // Check back
332 auto t = z.back();
335 }
336
337 {
338 // Check ranged-for
339 int i = 0;
340 for (auto [a, b, c, d, s] : z) {
343 REPORTER_ASSERT(reporter, c == C[i]);
346
347 i++;
348 }
350 }
351
352 {
353 // Check first(n)
354 int i = 0;
355 for (auto [a, b, c, d, s] : z.first(2)) {
358 REPORTER_ASSERT(reporter, c == C[i]);
361
362 i++;
363 }
365 }
366
367 {
368 // Check last(n)
369 int i = 0;
370 for (auto t : z.last(2)) {
371 uint16_t a; float b; int c; int d; int s;
372 std::tie(a, b, c, d, s) = t;
373 REPORTER_ASSERT(reporter, a == A[i + 2]);
374 REPORTER_ASSERT(reporter, b == B[i + 2]);
375 REPORTER_ASSERT(reporter, c == C[i + 2]);
376 REPORTER_ASSERT(reporter, d == D[i + 2]);
377 REPORTER_ASSERT(reporter, s == S[i + 2]);
378
379 i++;
380 }
382 }
383
384 {
385 // Check subspan(offset, count)
386 int i = 0;
387 for (auto t : z.subspan(1, 2)) {
388 uint16_t a; float b; int c; int d; int s;
389 std::tie(a, b, c, d, s) = t;
390 REPORTER_ASSERT(reporter, a == A[i + 1]);
391 REPORTER_ASSERT(reporter, b == B[i + 1]);
392 REPORTER_ASSERT(reporter, c == C[i + 1]);
393 REPORTER_ASSERT(reporter, d == D[i + 1]);
394 REPORTER_ASSERT(reporter, s == S[i + 1]);
395
396 i++;
397 }
399 }
400
401 {
402 // Check copy.
403 auto zz{z};
404 int i = 0;
405 for (auto [a, b, c, d, s] : zz) {
408 REPORTER_ASSERT(reporter, c == C[i]);
411
412 i++;
413 }
415 }
416
417 {
418 // Check const restricting copy
420 int i = 0;
421 for (auto [a, b, c, d, s] : cz) {
424 REPORTER_ASSERT(reporter, c == C[i]);
427
428 i++;
429 }
431 }
432
433 {
434 // Check data() returns all the original pointers
435 auto ptrs = z.data();
437 ptrs == std::make_tuple(&A[0], &B[0], C.data(), D.data(), S.data()));
438 }
439
440 {
441 // Check index getter
442 auto span = z.get<1>();
443 REPORTER_ASSERT(reporter, span[1] == 20.f);
444 }
445
446 // The following mutates the data.
447 {
448 // Check indexing
449 auto [a, b, c, d, e] = z[1];
451 REPORTER_ASSERT(reporter, b == 20.f);
452 REPORTER_ASSERT(reporter, c == 30);
453 REPORTER_ASSERT(reporter, d == 200);
454 REPORTER_ASSERT(reporter, e == 30);
455
456 // Check correct refs returned.
457 REPORTER_ASSERT(reporter, &a == &A[1]);
458 REPORTER_ASSERT(reporter, &b == &B[1]);
459 REPORTER_ASSERT(reporter, &c == &C[1]);
460 REPORTER_ASSERT(reporter, &d == &D[1]);
461 REPORTER_ASSERT(reporter, &e == &S[1]);
462
463 // Check assignment
464 a = 20;
465 // std::get<1>(t) = 300.f; // is const
466 c = 300;
467 d = 2000;
468 e = 300;
469
470 auto t1 = z[1];
473 REPORTER_ASSERT(reporter, std::get<2>(t1) == 300);
474 REPORTER_ASSERT(reporter, std::get<3>(t1) == 2000);
475 REPORTER_ASSERT(reporter, std::get<4>(t1) == 300);
476 }
477}
478
480 uint16_t A[] = {1, 2, 3, 4};
481 const float B[] = {10.f, 20.f, 30.f, 40.f};
482 const std::vector<int> C = {{20, 30, 40, 50}};
483 std::array<int, 4> D = {{100, 200, 300, 400}};
485 uint16_t* P = &A[0];
486 {
487 // Check make zip
488 auto zz = SkMakeZip(&A[0], B, C, D, S, P);
489
490 int i = 0;
491 for (auto [a, b, c, d, s, p] : zz) {
494 REPORTER_ASSERT(reporter, c == C[i]);
498
499 i++;
500 }
502 }
503
504 {
505 // Check SkMakeZip in ranged for check OneSize calc of B.
506 int i = 0;
507 for (auto [a, b, c, d, s] : SkMakeZip(&A[0], B, C, D, S)) {
510 REPORTER_ASSERT(reporter, c == C[i]);
513
514 i++;
515 }
517 }
518
519 {
520 // Check SkMakeZip in ranged for OneSize of C
521 int i = 0;
522 for (auto [a, b, c, d, s] : SkMakeZip(&A[0], &B[0], C, D, S)) {
525 REPORTER_ASSERT(reporter, c == C[i]);
528
529 i++;
530 }
532 }
533
534 {
535 // Check SkMakeZip in ranged for OneSize for S
536 int i = 0;
537 for (auto [s, a, b, c, d] : SkMakeZip(S, A, B, C, D)) {
540 REPORTER_ASSERT(reporter, c == C[i]);
543
544 i++;
545 }
547 }
548
549 {
550 // Check SkMakeZip in ranged for
551 int i = 0;
552 for (auto [c, s, a, b, d] : SkMakeZip(C, S, A, B, D)) {
555 REPORTER_ASSERT(reporter, c == C[i]);
558
559 i++;
560 }
562 }
563
564 {
565 // Check SkEnumerate and SkMakeZip in ranged for
566 auto zz = SkMakeZip(A, B, C, D, S);
567 for (auto [i, a, b, c, d, s] : SkMakeEnumerate(zz)) {
570 REPORTER_ASSERT(reporter, c == C[i]);
573 }
574 }
575
576 {
577 // Check SkEnumerate and SkMakeZip in ranged for
578 const auto& zz = SkMakeZip(A, B, C, D, S);
579 for (auto [i, a, b, c, d, s] : SkMakeEnumerate(zz)) {
582 REPORTER_ASSERT(reporter, c == C[i]);
585 }
586 }
587
588 {
589 // Check SkEnumerate and SkMakeZip in ranged for
590 for (auto [i, a, b, c, d, s] : SkMakeEnumerate(SkMakeZip(A, B, C, D, S))) {
593 REPORTER_ASSERT(reporter, c == C[i]);
596 }
597 }
598
599 {
600 std::vector<int>v;
601 auto z = SkMakeZip(v);
602 REPORTER_ASSERT(reporter, z.empty());
603 }
604
605 {
606 constexpr static uint16_t cA[] = {1, 2, 3, 4};
607 // Not constexpr in stdc++11 library.
608 //constexpr static std::array<int, 4> cD = {{100, 200, 300, 400}};
609 constexpr static const uint16_t* cP = &cA[0];
610 constexpr auto z = SkMakeZip(cA, cP);
611 REPORTER_ASSERT(reporter, !z.empty());
612 }
613}
614
615DEF_TEST(UtilsPreserveBitPatterns, r) {
616 // Various kinds of floating point bit patterns. We round trip each one through float using
617 // utility functions. If any of them ever do any real FP operation (including loading it into
618 // the x87 FPU on x86 builds), they might change. (In practice, signaling NaN is the only one
619 // that's likely to break -- it can be converted to a quiet NaN).
620 const uint32_t kBitPatterns[] = {
621 0x00400000, // Denormal value
622 0x80000000, // -0.0f
623 0x3f800000, // 1.0f (arbitrary normal float)
624 0x7f800000, // Infinity
625 0x7fa00000, // Signaling NaN
626 0x7fe00000, // Quiet NaN
627 };
628
629 for (uint32_t srcBits : kBitPatterns) {
630 {
631 float floatVal = sk_unaligned_load<float>(&srcBits);
632 uint32_t dstBits = sk_unaligned_load<uint32_t>(&floatVal);
633 REPORTER_ASSERT(r, dstBits == srcBits);
634 }
635
636 {
637 float floatVal;
638 sk_unaligned_store(&floatVal, srcBits);
639 uint32_t dstBits;
640 sk_unaligned_store(&dstBits, floatVal);
641 REPORTER_ASSERT(r, dstBits == srcBits);
642 }
643
644 REPORTER_ASSERT(r, sk_bit_cast<uint32_t>(sk_bit_cast<float>(srcBits)) == srcBits);
645 }
646}
reporter
Definition: FontMgrTest.cpp:39
#define check(reporter, ref, unref, make, kill)
Definition: RefCntTest.cpp:85
constexpr SkEnumerate< Iter > SkMakeEnumerate(C &c)
Definition: SkEnumerate.h:102
static T * SkRef(T *obj)
Definition: SkRefCnt.h:132
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
static SK_ALWAYS_INLINE void SK_FP_SAFE_ABI sk_unaligned_store(P *ptr, T val)
Definition: SkUtils.h:61
constexpr auto SkMakeZip(Ts &&... ts)
Definition: SkZip.h:212
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
static void test_autounref(skiatest::Reporter *reporter)
Definition: UtilsTest.cpp:42
static void test_autostarray(skiatest::Reporter *reporter)
Definition: UtilsTest.cpp:63
#define kSEARCH_COUNT
Definition: UtilsTest.cpp:134
static void test_search(skiatest::Reporter *reporter)
Definition: UtilsTest.cpp:136
DEF_TEST(Utils, reporter)
Definition: UtilsTest.cpp:181
int get() const
Definition: UtilsTest.cpp:34
RefClass(int n)
Definition: UtilsTest.cpp:33
int32_t nextS()
Definition: SkRandom.h:50
void ref() const
Definition: SkRefCnt.h:62
bool unique() const
Definition: SkRefCnt.h:50
Definition: SkZip.h:25
T * get() const
Definition: SkRefCnt.h:303
T * release()
Definition: SkRefCnt.h:324
void reset(int count)
Definition: SkTemplates.h:195
#define C(TEST_CATEGORY)
Definition: colrv1.cpp:248
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
static bool b
struct MyStruct s
struct MyStruct a[10]
uint8_t value
#define I
const myers::Point & get< 1 >(const myers::Segment &s)
Definition: Myers.h:81
const myers::Point & get< 0 >(const myers::Segment &s)
Definition: Myers.h:80
Definition: SkMD5.cpp:134