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 
8 #include "include/core/SkRefCnt.h"
9 #include "include/core/SkSpan.h"
10 #include "include/utils/SkRandom.h"
11 #include "src/core/SkEnumerate.h"
12 #include "src/core/SkTSearch.h"
13 #include "src/core/SkTSort.h"
14 #include "src/core/SkZip.h"
15 #include "tests/Test.h"
16 
17 #include <array>
18 #include <initializer_list>
19 #include <tuple>
20 #include <vector>
21 
22 class RefClass : public SkRefCnt {
23 public:
RefClass(int n)24     RefClass(int n) : fN(n) {}
get() const25     int get() const { return fN; }
26 
27 private:
28     int fN;
29 
30     using INHERITED = SkRefCnt;
31 };
32 
test_autounref(skiatest::Reporter * reporter)33 static void test_autounref(skiatest::Reporter* reporter) {
34     RefClass obj(0);
35     REPORTER_ASSERT(reporter, obj.unique());
36 
37     sk_sp<RefClass> tmp(&obj);
38     REPORTER_ASSERT(reporter, &obj == tmp.get());
39     REPORTER_ASSERT(reporter, obj.unique());
40 
41     REPORTER_ASSERT(reporter, &obj == tmp.release());
42     REPORTER_ASSERT(reporter, obj.unique());
43     REPORTER_ASSERT(reporter, nullptr == tmp.release());
44     REPORTER_ASSERT(reporter, nullptr == tmp.get());
45 
46     obj.ref();
47     REPORTER_ASSERT(reporter, !obj.unique());
48     {
49         sk_sp<RefClass> tmp2(&obj);
50     }
51     REPORTER_ASSERT(reporter, obj.unique());
52 }
53 
test_autostarray(skiatest::Reporter * reporter)54 static void test_autostarray(skiatest::Reporter* reporter) {
55     RefClass obj0(0);
56     RefClass obj1(1);
57     REPORTER_ASSERT(reporter, obj0.unique());
58     REPORTER_ASSERT(reporter, obj1.unique());
59 
60     {
61         SkAutoSTArray<2, sk_sp<RefClass> > tmp;
62         REPORTER_ASSERT(reporter, 0 == tmp.count());
63 
64         tmp.reset(0);   // test out reset(0) when already at 0
65         tmp.reset(4);   // this should force a new allocation
66         REPORTER_ASSERT(reporter, 4 == tmp.count());
67         tmp[0].reset(SkRef(&obj0));
68         tmp[1].reset(SkRef(&obj1));
69         REPORTER_ASSERT(reporter, !obj0.unique());
70         REPORTER_ASSERT(reporter, !obj1.unique());
71 
72         // test out reset with data in the array (and a new allocation)
73         tmp.reset(0);
74         REPORTER_ASSERT(reporter, 0 == tmp.count());
75         REPORTER_ASSERT(reporter, obj0.unique());
76         REPORTER_ASSERT(reporter, obj1.unique());
77 
78         tmp.reset(2);   // this should use the preexisting allocation
79         REPORTER_ASSERT(reporter, 2 == tmp.count());
80         tmp[0].reset(SkRef(&obj0));
81         tmp[1].reset(SkRef(&obj1));
82     }
83 
84     // test out destructor with data in the array (and using existing allocation)
85     REPORTER_ASSERT(reporter, obj0.unique());
86     REPORTER_ASSERT(reporter, obj1.unique());
87 
88     {
89         // test out allocating ctor (this should allocate new memory)
90         SkAutoSTArray<2, sk_sp<RefClass> > tmp(4);
91         REPORTER_ASSERT(reporter, 4 == tmp.count());
92 
93         tmp[0].reset(SkRef(&obj0));
94         tmp[1].reset(SkRef(&obj1));
95         REPORTER_ASSERT(reporter, !obj0.unique());
96         REPORTER_ASSERT(reporter, !obj1.unique());
97 
98         // Test out resut with data in the array and malloced storage
99         tmp.reset(0);
100         REPORTER_ASSERT(reporter, obj0.unique());
101         REPORTER_ASSERT(reporter, obj1.unique());
102 
103         tmp.reset(2);   // this should use the preexisting storage
104         tmp[0].reset(SkRef(&obj0));
105         tmp[1].reset(SkRef(&obj1));
106         REPORTER_ASSERT(reporter, !obj0.unique());
107         REPORTER_ASSERT(reporter, !obj1.unique());
108 
109         tmp.reset(4);   // this should force a new malloc
110         REPORTER_ASSERT(reporter, obj0.unique());
111         REPORTER_ASSERT(reporter, obj1.unique());
112 
113         tmp[0].reset(SkRef(&obj0));
114         tmp[1].reset(SkRef(&obj1));
115         REPORTER_ASSERT(reporter, !obj0.unique());
116         REPORTER_ASSERT(reporter, !obj1.unique());
117     }
118 
119     REPORTER_ASSERT(reporter, obj0.unique());
120     REPORTER_ASSERT(reporter, obj1.unique());
121 }
122 
123 /////////////////////////////////////////////////////////////////////////////
124 
125 #define kSEARCH_COUNT   91
126 
test_search(skiatest::Reporter * reporter)127 static void test_search(skiatest::Reporter* reporter) {
128     int         i, array[kSEARCH_COUNT];
129     SkRandom    rand;
130 
131     for (i = 0; i < kSEARCH_COUNT; i++) {
132         array[i] = rand.nextS();
133     }
134 
135     SkTHeapSort<int>(array, kSEARCH_COUNT);
136     // make sure we got sorted properly
137     for (i = 1; i < kSEARCH_COUNT; i++) {
138         REPORTER_ASSERT(reporter, array[i-1] <= array[i]);
139     }
140 
141     // make sure we can find all of our values
142     for (i = 0; i < kSEARCH_COUNT; i++) {
143         int index = SkTSearch<int>(array, kSEARCH_COUNT, array[i], sizeof(int));
144         REPORTER_ASSERT(reporter, index == i);
145     }
146 
147     // make sure that random values are either found, or the correct
148     // insertion index is returned
149     for (i = 0; i < 10000; i++) {
150         int value = rand.nextS();
151         int index = SkTSearch<int>(array, kSEARCH_COUNT, value, sizeof(int));
152 
153         if (index >= 0) {
154             REPORTER_ASSERT(reporter,
155                             index < kSEARCH_COUNT && array[index] == value);
156         } else {
157             index = ~index;
158             REPORTER_ASSERT(reporter, index <= kSEARCH_COUNT);
159             if (index < kSEARCH_COUNT) {
160                 REPORTER_ASSERT(reporter, value < array[index]);
161                 if (index > 0) {
162                     REPORTER_ASSERT(reporter, value > array[index - 1]);
163                 }
164             } else {
165                 // we should append the new value
166                 REPORTER_ASSERT(reporter, value > array[kSEARCH_COUNT - 1]);
167             }
168         }
169     }
170 }
171 
DEF_TEST(Utils,reporter)172 DEF_TEST(Utils, reporter) {
173     test_search(reporter);
174     test_autounref(reporter);
175     test_autostarray(reporter);
176 }
177 
DEF_TEST(SkSpan,reporter)178 DEF_TEST(SkSpan, reporter) {
179     // Test constness preservation for SkMakeSpan.
180     {
181         std::vector<int> v = {{1, 2, 3, 4, 5}};
182         auto s = SkMakeSpan(v);
183         REPORTER_ASSERT(reporter, s[3] == 4);
184         s[3] = 100;
185         REPORTER_ASSERT(reporter, s[3] == 100);
186     }
187 
188     {
189         std::vector<int> t = {{1, 2, 3, 4, 5}};
190         const std::vector<int>& v = t;
191         auto s = SkMakeSpan(v);
192         //s[3] = 100; // Should fail to compile
193         REPORTER_ASSERT(reporter, s[3] == 4);
194         REPORTER_ASSERT(reporter, t[3] == 4);
195         t[3] = 100;
196         REPORTER_ASSERT(reporter, s[3] == 100);
197     }
198 
199     {
200         std::array<int, 5> v = {{1, 2, 3, 4, 5}};
201         auto s = SkMakeSpan(v);
202         REPORTER_ASSERT(reporter, s[3] == 4);
203         s[3] = 100;
204         REPORTER_ASSERT(reporter, s[3] == 100);
205         auto s1 = s.subspan(1,3);
206         REPORTER_ASSERT(reporter, s1.size() == 3);
207         REPORTER_ASSERT(reporter, s1.front() == 2);
208         REPORTER_ASSERT(reporter, s1.back() == 100);
209     }
210 
211     {
212         std::array<int, 5> t = {{1, 2, 3, 4, 5}};
213         const std::array<int, 5>& v = t;
214         auto s = SkMakeSpan(v);
215         //s[3] = 100; // Should fail to compile
216         REPORTER_ASSERT(reporter, s[3] == 4);
217         REPORTER_ASSERT(reporter, t[3] == 4);
218         t[3] = 100;
219         REPORTER_ASSERT(reporter, s[3] == 100);
220     }
221 
222     {
223         std::vector<int> v;
224         auto s = SkMakeSpan(v);
225         REPORTER_ASSERT(reporter, s.empty());
226     }
227 }
228 
DEF_TEST(SkEnumerate,reporter)229 DEF_TEST(SkEnumerate, reporter) {
230 
231     int A[] = {1, 2, 3, 4};
232     auto enumeration = SkMakeEnumerate(A);
233 
234     size_t check = 0;
235     for (auto [i, v] : enumeration) {
236         REPORTER_ASSERT(reporter, i == check);
237         REPORTER_ASSERT(reporter, v == (int)check+1);
238 
239         check++;
240     }
241 
242     check = 0;
243     for (auto [i, v] : SkMakeEnumerate(A)) {
244         REPORTER_ASSERT(reporter, i == check);
245         REPORTER_ASSERT(reporter, v == (int)check+1);
246 
247         check++;
248     }
249 
250     check = 0;
251     std::vector<int> vec = {1, 2, 3, 4};
252     for (auto [i, v] : SkMakeEnumerate(vec)) {
253         REPORTER_ASSERT(reporter, i == check);
254         REPORTER_ASSERT(reporter, v == (int)check+1);
255         check++;
256     }
257     REPORTER_ASSERT(reporter, check == 4);
258 
259     check = 0;
260     for (auto [i, v] : SkMakeEnumerate(SkMakeSpan(vec))) {
261         REPORTER_ASSERT(reporter, i == check);
262         REPORTER_ASSERT(reporter, v == (int)check+1);
263         check++;
264     }
265 
266     {
267         auto e = SkMakeEnumerate(SkMakeSpan(vec)).first(2);
268         for (auto[i, v] : e) {
269             REPORTER_ASSERT(reporter, v == (int) i + 1);
270         }
271         REPORTER_ASSERT(reporter, e.size() == 2);
272     }
273 
274     {
275         auto e = SkMakeEnumerate(SkMakeSpan(vec)).last(2);
276         for (auto[i, v] : e) {
277             REPORTER_ASSERT(reporter, v == (int) i + 1);
278         }
279         REPORTER_ASSERT(reporter, e.size() == 2);
280     }
281 
282     {
283         auto e = SkMakeEnumerate(SkMakeSpan(vec)).subspan(1, 2);
284         for (auto[i, v] : e) {
285             REPORTER_ASSERT(reporter, v == (int) i + 1);
286         }
287         REPORTER_ASSERT(reporter, e.size() == 2);
288     }
289 
290     {
291         struct I {
292             I() = default;
293             I(const I&) = default;
294             I(int v) : i{v} { }
295             ~I() {}
296             int i;
297         };
298 
299         I is[10];
300         auto s = SkMakeSpan(is);
301         for (auto [i, v] : SkMakeEnumerate(s)) {
302             new (&v) I(i);
303         }
304 
305         for (size_t i = 0; i < s.size(); i++) {
306             REPORTER_ASSERT(reporter, s[i].i == (int)i);
307             REPORTER_ASSERT(reporter, is[i].i == (int)i);
308         }
309     }
310 
311     {
312         std::unique_ptr<int> is[10];
313         std::unique_ptr<int> os[10];
314         auto s = SkMakeSpan(is);
315         for (auto [i, v] : SkMakeEnumerate(s)) {
316             v = std::make_unique<int>(i);
317         }
318 
319         for (auto [i, v] : SkMakeEnumerate(SkMakeSpan(os))) {
320             v = std::move(s[i]);
321         }
322 
323         for (size_t i = 0; i < s.size(); i++) {
324             REPORTER_ASSERT(reporter, *os[i] == (int)i);
325             REPORTER_ASSERT(reporter, is[i] == nullptr);
326         }
327     }
328 
329     {
330         std::unique_ptr<int> is[10];
331         std::unique_ptr<int> os[10];
332         auto s = SkMakeSpan(is);
333         for (auto [i, v] : SkMakeEnumerate(s)) {
334             v = std::make_unique<int>(i);
335         }
336 
337         for (auto [i, ov, iv] : SkMakeEnumerate(SkMakeZip(os, is))) {
338             ov = std::move(iv);
339         }
340 
341         for (size_t i = 0; i < s.size(); i++) {
342             REPORTER_ASSERT(reporter, *os[i] == (int)i);
343             REPORTER_ASSERT(reporter, is[i] == nullptr);
344         }
345     }
346 }
347 
DEF_TEST(SkZip,reporter)348 DEF_TEST(SkZip, reporter) {
349     uint16_t A[] = {1, 2, 3, 4};
350     const float B[] = {10.f, 20.f, 30.f, 40.f};
351     std::vector<int> C = {{20, 30, 40, 50}};
352     std::array<int, 4> D = {{100, 200, 300, 400}};
353     SkSpan<int> S = SkMakeSpan(C);
354 
355     // Check SkZip calls
356     SkZip<uint16_t, const float, int, int, int>
357             z{4, &A[0], &B[0], C.data(), D.data(), S.data()};
358 
359     REPORTER_ASSERT(reporter, z.size() == 4);
360     REPORTER_ASSERT(reporter, !z.empty());
361 
362     {
363         // Check front
364         auto t = z.front();
365         REPORTER_ASSERT(reporter, std::get<0>(t) == 1);
366         REPORTER_ASSERT(reporter, std::get<1>(t) == 10.f);
367         REPORTER_ASSERT(reporter, std::get<2>(t) == 20);
368         REPORTER_ASSERT(reporter, std::get<3>(t) == 100);
369         REPORTER_ASSERT(reporter, std::get<4>(t) == 20);
370     }
371 
372     {
373         // Check back
374         auto t = z.back();
375         REPORTER_ASSERT(reporter, std::get<0>(t) == 4);
376         REPORTER_ASSERT(reporter, std::get<1>(t) == 40.f);
377     }
378 
379     {
380         // Check ranged-for
381         int i = 0;
382         for (auto [a, b, c, d, s] : z) {
383             REPORTER_ASSERT(reporter, a == A[i]);
384             REPORTER_ASSERT(reporter, b == B[i]);
385             REPORTER_ASSERT(reporter, c == C[i]);
386             REPORTER_ASSERT(reporter, d == D[i]);
387             REPORTER_ASSERT(reporter, s == S[i]);
388 
389             i++;
390         }
391         REPORTER_ASSERT(reporter, i = 4);
392     }
393 
394     {
395         // Check first(n)
396         int i = 0;
397         for (auto [a, b, c, d, s] : z.first(2)) {
398             REPORTER_ASSERT(reporter, a == A[i]);
399             REPORTER_ASSERT(reporter, b == B[i]);
400             REPORTER_ASSERT(reporter, c == C[i]);
401             REPORTER_ASSERT(reporter, d == D[i]);
402             REPORTER_ASSERT(reporter, s == S[i]);
403 
404             i++;
405         }
406         REPORTER_ASSERT(reporter, i = 2);
407     }
408 
409     {
410         // Check last(n)
411         int i = 0;
412         for (auto t : z.last(2)) {
413             uint16_t a; float b; int c; int d; int s;
414             std::tie(a, b, c, d, s) = t;
415             REPORTER_ASSERT(reporter, a == A[i + 2]);
416             REPORTER_ASSERT(reporter, b == B[i + 2]);
417             REPORTER_ASSERT(reporter, c == C[i + 2]);
418             REPORTER_ASSERT(reporter, d == D[i + 2]);
419             REPORTER_ASSERT(reporter, s == S[i + 2]);
420 
421             i++;
422         }
423         REPORTER_ASSERT(reporter, i = 2);
424     }
425 
426     {
427         // Check subspan(offset, count)
428         int i = 0;
429         for (auto t : z.subspan(1, 2)) {
430             uint16_t a; float b; int c; int d; int s;
431             std::tie(a, b, c, d, s) = t;
432             REPORTER_ASSERT(reporter, a == A[i + 1]);
433             REPORTER_ASSERT(reporter, b == B[i + 1]);
434             REPORTER_ASSERT(reporter, c == C[i + 1]);
435             REPORTER_ASSERT(reporter, d == D[i + 1]);
436             REPORTER_ASSERT(reporter, s == S[i + 1]);
437 
438             i++;
439         }
440         REPORTER_ASSERT(reporter, i = 2);
441     }
442 
443     {
444         // Check copy.
445         auto zz{z};
446         int i = 0;
447         for (auto [a, b, c, d, s] : zz) {
448             REPORTER_ASSERT(reporter, a == A[i]);
449             REPORTER_ASSERT(reporter, b == B[i]);
450             REPORTER_ASSERT(reporter, c == C[i]);
451             REPORTER_ASSERT(reporter, d == D[i]);
452             REPORTER_ASSERT(reporter, s == S[i]);
453 
454             i++;
455         }
456         REPORTER_ASSERT(reporter, i = 4);
457     }
458 
459     {
460         // Check const restricting copy
461         SkZip<const uint16_t, const float, const int, int, int> cz = z;
462         int i = 0;
463         for (auto [a, b, c, d, s] : cz) {
464             REPORTER_ASSERT(reporter, a == A[i]);
465             REPORTER_ASSERT(reporter, b == B[i]);
466             REPORTER_ASSERT(reporter, c == C[i]);
467             REPORTER_ASSERT(reporter, d == D[i]);
468             REPORTER_ASSERT(reporter, s == S[i]);
469 
470             i++;
471         }
472         REPORTER_ASSERT(reporter, i = 4);
473     }
474 
475     {
476         // Check data() returns all the original pointers
477         auto ptrs = z.data();
478         REPORTER_ASSERT(reporter,
479                 ptrs == std::make_tuple(&A[0], &B[0], C.data(), D.data(), S.data()));
480     }
481 
482     {
483         // Check index getter
484         auto span = z.get<1>();
485         REPORTER_ASSERT(reporter, span[1] == 20.f);
486     }
487 
488     // The following mutates the data.
489     {
490         // Check indexing
491         auto [a, b, c, d, e] = z[1];
492         REPORTER_ASSERT(reporter, a == 2);
493         REPORTER_ASSERT(reporter, b == 20.f);
494         REPORTER_ASSERT(reporter, c == 30);
495         REPORTER_ASSERT(reporter, d == 200);
496         REPORTER_ASSERT(reporter, e == 30);
497 
498         // Check correct refs returned.
499         REPORTER_ASSERT(reporter, &a == &A[1]);
500         REPORTER_ASSERT(reporter, &b == &B[1]);
501         REPORTER_ASSERT(reporter, &c == &C[1]);
502         REPORTER_ASSERT(reporter, &d == &D[1]);
503         REPORTER_ASSERT(reporter, &e == &S[1]);
504 
505         // Check assignment
506         a = 20;
507         // std::get<1>(t) = 300.f; // is const
508         c = 300;
509         d = 2000;
510         e = 300;
511 
512         auto t1 = z[1];
513         REPORTER_ASSERT(reporter, std::get<0>(t1) == 20);
514         REPORTER_ASSERT(reporter, std::get<1>(t1) == 20.f);
515         REPORTER_ASSERT(reporter, std::get<2>(t1) == 300);
516         REPORTER_ASSERT(reporter, std::get<3>(t1) == 2000);
517         REPORTER_ASSERT(reporter, std::get<4>(t1) == 300);
518     }
519 }
520 
DEF_TEST(SkMakeZip,reporter)521 DEF_TEST(SkMakeZip, reporter) {
522     uint16_t A[] = {1, 2, 3, 4};
523     const float B[] = {10.f, 20.f, 30.f, 40.f};
524     const std::vector<int> C = {{20, 30, 40, 50}};
525     std::array<int, 4> D = {{100, 200, 300, 400}};
526     SkSpan<const int> S = SkMakeSpan(C);
527     uint16_t* P = &A[0];
528     {
529         // Check make zip
530         auto zz = SkMakeZip(&A[0], B, C, D, S, P);
531 
532         int i = 0;
533         for (auto [a, b, c, d, s, p] : zz) {
534             REPORTER_ASSERT(reporter, a == A[i]);
535             REPORTER_ASSERT(reporter, b == B[i]);
536             REPORTER_ASSERT(reporter, c == C[i]);
537             REPORTER_ASSERT(reporter, d == D[i]);
538             REPORTER_ASSERT(reporter, s == S[i]);
539             REPORTER_ASSERT(reporter, p == P[i]);
540 
541             i++;
542         }
543         REPORTER_ASSERT(reporter, i = 4);
544     }
545 
546     {
547         // Check SkMakeZip in ranged for check OneSize calc of B.
548         int i = 0;
549         for (auto [a, b, c, d, s] : SkMakeZip(&A[0], B, C, D, S)) {
550             REPORTER_ASSERT(reporter, a == A[i]);
551             REPORTER_ASSERT(reporter, b == B[i]);
552             REPORTER_ASSERT(reporter, c == C[i]);
553             REPORTER_ASSERT(reporter, d == D[i]);
554             REPORTER_ASSERT(reporter, s == S[i]);
555 
556             i++;
557         }
558         REPORTER_ASSERT(reporter, i = 4);
559     }
560 
561     {
562         // Check SkMakeZip in ranged for OneSize of C
563         int i = 0;
564         for (auto [a, b, c, d, s] : SkMakeZip(&A[0], &B[0], C, D, S)) {
565             REPORTER_ASSERT(reporter, a == A[i]);
566             REPORTER_ASSERT(reporter, b == B[i]);
567             REPORTER_ASSERT(reporter, c == C[i]);
568             REPORTER_ASSERT(reporter, d == D[i]);
569             REPORTER_ASSERT(reporter, s == S[i]);
570 
571             i++;
572         }
573         REPORTER_ASSERT(reporter, i = 4);
574     }
575 
576     {
577         // Check SkMakeZip in ranged for OneSize for S
578         int i = 0;
579         for (auto [s, a, b, c, d] : SkMakeZip(S, A, B, C, D)) {
580             REPORTER_ASSERT(reporter, a == A[i]);
581             REPORTER_ASSERT(reporter, b == B[i]);
582             REPORTER_ASSERT(reporter, c == C[i]);
583             REPORTER_ASSERT(reporter, d == D[i]);
584             REPORTER_ASSERT(reporter, s == S[i]);
585 
586             i++;
587         }
588         REPORTER_ASSERT(reporter, i = 4);
589     }
590 
591     {
592         // Check SkMakeZip in ranged for
593         int i = 0;
594         for (auto [c, s, a, b, d] : SkMakeZip(C, S, A, B, D)) {
595             REPORTER_ASSERT(reporter, a == A[i]);
596             REPORTER_ASSERT(reporter, b == B[i]);
597             REPORTER_ASSERT(reporter, c == C[i]);
598             REPORTER_ASSERT(reporter, d == D[i]);
599             REPORTER_ASSERT(reporter, s == S[i]);
600 
601             i++;
602         }
603         REPORTER_ASSERT(reporter, i = 4);
604     }
605 
606     {
607         // Check SkEnumerate and SkMakeZip in ranged for
608         auto zz = SkMakeZip(A, B, C, D, S);
609         for (auto [i, a, b, c, d, s] : SkMakeEnumerate(zz)) {
610             REPORTER_ASSERT(reporter, a == A[i]);
611             REPORTER_ASSERT(reporter, b == B[i]);
612             REPORTER_ASSERT(reporter, c == C[i]);
613             REPORTER_ASSERT(reporter, d == D[i]);
614             REPORTER_ASSERT(reporter, s == S[i]);
615         }
616     }
617 
618     {
619         // Check SkEnumerate and SkMakeZip in ranged for
620         const auto& zz = SkMakeZip(A, B, C, D, S);
621         for (auto [i, a, b, c, d, s] : SkMakeEnumerate(zz)) {
622             REPORTER_ASSERT(reporter, a == A[i]);
623             REPORTER_ASSERT(reporter, b == B[i]);
624             REPORTER_ASSERT(reporter, c == C[i]);
625             REPORTER_ASSERT(reporter, d == D[i]);
626             REPORTER_ASSERT(reporter, s == S[i]);
627         }
628     }
629 
630     {
631         // Check SkEnumerate and SkMakeZip in ranged for
632         for (auto [i, a, b, c, d, s] : SkMakeEnumerate(SkMakeZip(A, B, C, D, S))) {
633             REPORTER_ASSERT(reporter, a == A[i]);
634             REPORTER_ASSERT(reporter, b == B[i]);
635             REPORTER_ASSERT(reporter, c == C[i]);
636             REPORTER_ASSERT(reporter, d == D[i]);
637             REPORTER_ASSERT(reporter, s == S[i]);
638         }
639     }
640 
641     {
642         std::vector<int>v;
643         auto z = SkMakeZip(v);
644         REPORTER_ASSERT(reporter, z.empty());
645     }
646 
647     {
648         constexpr static uint16_t cA[] = {1, 2, 3, 4};
649         // Not constexpr in stdc++11 library.
650         //constexpr static std::array<int, 4> cD = {{100, 200, 300, 400}};
651         constexpr static const uint16_t* cP = &cA[0];
652         constexpr auto z = SkMakeZip(cA, cP);
653         REPORTER_ASSERT(reporter, !z.empty());
654     }
655 }
656