Home | History | Annotate | Download | only in tests
      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 "SkRefCnt.h"
      9 #include "SkTArray.h"
     10 #include "Test.h"
     11 
     12 // Tests the SkTArray<T> class template.
     13 
     14 template <bool MEM_MOVE>
     15 static void TestTSet_basic(skiatest::Reporter* reporter) {
     16     SkTArray<int, MEM_MOVE> a;
     17 
     18     // Starts empty.
     19     REPORTER_ASSERT(reporter, a.empty());
     20     REPORTER_ASSERT(reporter, a.count() == 0);
     21 
     22     // { }, add a default constructed element
     23     a.push_back() = 0;
     24     REPORTER_ASSERT(reporter, !a.empty());
     25     REPORTER_ASSERT(reporter, a.count() == 1);
     26 
     27     // { 0 }, removeShuffle the only element.
     28     a.removeShuffle(0);
     29     REPORTER_ASSERT(reporter, a.empty());
     30     REPORTER_ASSERT(reporter, a.count() == 0);
     31 
     32     // { }, add a default, add a 1, remove first
     33     a.push_back() = 0;
     34     REPORTER_ASSERT(reporter, a.push_back() = 1);
     35     a.removeShuffle(0);
     36     REPORTER_ASSERT(reporter, !a.empty());
     37     REPORTER_ASSERT(reporter, a.count() == 1);
     38     REPORTER_ASSERT(reporter, a[0] == 1);
     39 
     40     // { 1 }, replace with new array
     41     int b[5] = { 0, 1, 2, 3, 4 };
     42     a.reset(b, SK_ARRAY_COUNT(b));
     43     REPORTER_ASSERT(reporter, a.count() == SK_ARRAY_COUNT(b));
     44     REPORTER_ASSERT(reporter, a[2] == 2);
     45     REPORTER_ASSERT(reporter, a[4] == 4);
     46 
     47     // { 0, 1, 2, 3, 4 }, removeShuffle the last
     48     a.removeShuffle(4);
     49     REPORTER_ASSERT(reporter, a.count() == SK_ARRAY_COUNT(b) - 1);
     50     REPORTER_ASSERT(reporter, a[3] == 3);
     51 
     52     // { 0, 1, 2, 3 }, remove a middle, note shuffle
     53     a.removeShuffle(1);
     54     REPORTER_ASSERT(reporter, a.count() == SK_ARRAY_COUNT(b) - 2);
     55     REPORTER_ASSERT(reporter, a[0] == 0);
     56     REPORTER_ASSERT(reporter, a[1] == 3);
     57     REPORTER_ASSERT(reporter, a[2] == 2);
     58 
     59     // {0, 3, 2 }
     60 }
     61 
     62 template <typename T> static void test_swap(skiatest::Reporter* reporter,
     63                                             SkTArray<T>* (&arrays)[4],
     64                                             int (&sizes)[7])
     65 {
     66     for (auto a : arrays) {
     67     for (auto b : arrays) {
     68         if (a == b) {
     69             continue;
     70         }
     71 
     72         for (auto sizeA : sizes) {
     73         for (auto sizeB : sizes) {
     74             a->reset();
     75             b->reset();
     76 
     77             int curr = 0;
     78             for (int i = 0; i < sizeA; i++) { a->push_back(curr++); }
     79             for (int i = 0; i < sizeB; i++) { b->push_back(curr++); }
     80 
     81             a->swap(b);
     82             REPORTER_ASSERT(reporter, b->count() == sizeA);
     83             REPORTER_ASSERT(reporter, a->count() == sizeB);
     84 
     85             curr = 0;
     86             for (auto&& x : *b) { REPORTER_ASSERT(reporter, x == curr++); }
     87             for (auto&& x : *a) { REPORTER_ASSERT(reporter, x == curr++); }
     88 
     89             a->swap(a);
     90             curr = sizeA;
     91             for (auto&& x : *a) { REPORTER_ASSERT(reporter, x == curr++); }
     92         }}
     93     }}
     94 }
     95 
     96 static void test_swap(skiatest::Reporter* reporter) {
     97     int sizes[] = {0, 1, 5, 10, 15, 20, 25};
     98 
     99     SkTArray<int> arr;
    100     SkSTArray< 5, int> arr5;
    101     SkSTArray<10, int> arr10;
    102     SkSTArray<20, int> arr20;
    103     SkTArray<int>* arrays[] = { &arr, &arr5, &arr10, &arr20 };
    104     test_swap(reporter, arrays, sizes);
    105 
    106     struct MoveOnlyInt {
    107         MoveOnlyInt(int i) : fInt(i) {}
    108         MoveOnlyInt(MoveOnlyInt&& that) : fInt(that.fInt) {}
    109         bool operator==(int i) { return fInt == i; }
    110         int fInt;
    111     };
    112 
    113     SkTArray<MoveOnlyInt> moi;
    114     SkSTArray< 5, MoveOnlyInt> moi5;
    115     SkSTArray<10, MoveOnlyInt> moi10;
    116     SkSTArray<20, MoveOnlyInt> moi20;
    117     SkTArray<MoveOnlyInt>* arraysMoi[] = { &moi, &moi5, &moi10, &moi20 };
    118     test_swap(reporter, arraysMoi, sizes);
    119 }
    120 
    121 template <typename T, bool MEM_MOVE>
    122 void test_copy_ctor(skiatest::Reporter* reporter, SkTArray<T, MEM_MOVE>&& array) {
    123     SkASSERT(array.empty());
    124     for (int i = 0; i < 5; ++i) {
    125         array.emplace_back(new SkRefCnt);
    126         REPORTER_ASSERT(reporter, array.back()->unique());
    127     }
    128 
    129     {
    130         SkTArray<T, MEM_MOVE> copy(array);
    131         for (const auto& ref : array)
    132             REPORTER_ASSERT(reporter, !ref->unique());
    133         for (const auto& ref : copy)
    134             REPORTER_ASSERT(reporter, !ref->unique());
    135     }
    136 
    137     for (const auto& ref : array)
    138         REPORTER_ASSERT(reporter, ref->unique());
    139 }
    140 
    141 static void test_move(skiatest::Reporter* reporter) {
    142 #define TEST_MOVE do {                                 \
    143     SRC_T src;                                         \
    144     src.emplace_back(sk_make_sp<SkRefCnt>());          \
    145     {                                                  \
    146         /* copy ctor */                                \
    147         DST_T copy(src);                               \
    148         REPORTER_ASSERT(reporter, !copy[0]->unique()); \
    149     }                                                  \
    150     {                                                  \
    151         /* move ctor */                                \
    152         DST_T move(std::move(src));                    \
    153         REPORTER_ASSERT(reporter, move[0]->unique());  \
    154     }                                                  \
    155     REPORTER_ASSERT(reporter, src.empty());            \
    156     src.emplace_back(sk_make_sp<SkRefCnt>());          \
    157     {                                                  \
    158         /* copy assignment */                          \
    159         DST_T copy;                                    \
    160         copy = src;                                    \
    161         REPORTER_ASSERT(reporter, !copy[0]->unique()); \
    162     }                                                  \
    163     {                                                  \
    164         /* move assignment */                          \
    165         DST_T move;                                    \
    166         move = std::move(src);                         \
    167         REPORTER_ASSERT(reporter, move[0]->unique());  \
    168     }                                                  \
    169     REPORTER_ASSERT(reporter, src.empty());            \
    170 } while (false)
    171 
    172     {
    173         using SRC_T = SkTArray<sk_sp<SkRefCnt>, false>;
    174         using DST_T = SkTArray<sk_sp<SkRefCnt>, false>;
    175         TEST_MOVE;
    176     }
    177 
    178     {
    179         using SRC_T = SkTArray<sk_sp<SkRefCnt>, true>;
    180         using DST_T = SkTArray<sk_sp<SkRefCnt>, true>;
    181         TEST_MOVE;
    182     }
    183 
    184     {
    185         using SRC_T = SkSTArray<1, sk_sp<SkRefCnt>, false>;
    186         using DST_T = SkSTArray<1, sk_sp<SkRefCnt>, false>;
    187         TEST_MOVE;
    188     }
    189 
    190     {
    191         using SRC_T = SkSTArray<1, sk_sp<SkRefCnt>, true>;
    192         using DST_T = SkSTArray<1, sk_sp<SkRefCnt>, true>;
    193         TEST_MOVE;
    194     }
    195 
    196     {
    197         using SRC_T = SkTArray<sk_sp<SkRefCnt>, false>;
    198         using DST_T = SkSTArray<1, sk_sp<SkRefCnt>, false>;
    199         TEST_MOVE;
    200     }
    201 
    202     {
    203         using SRC_T = SkTArray<sk_sp<SkRefCnt>, true>;
    204         using DST_T = SkSTArray<1, sk_sp<SkRefCnt>, true>;
    205         TEST_MOVE;
    206     }
    207 
    208     {
    209         using SRC_T = SkSTArray<1, sk_sp<SkRefCnt>, false>;
    210         using DST_T = SkTArray<sk_sp<SkRefCnt>, false>;
    211         TEST_MOVE;
    212     }
    213 
    214     {
    215         using SRC_T = SkSTArray<1, sk_sp<SkRefCnt>, true>;
    216         using DST_T = SkTArray<sk_sp<SkRefCnt>, true>;
    217         TEST_MOVE;
    218     }
    219 #undef TEST_MOVE
    220 }
    221 
    222 template <typename T, bool MEM_MOVE> int SkTArray<T, MEM_MOVE>::allocCntForTest() const {
    223     return fAllocCount;
    224 }
    225 
    226 void test_unnecessary_alloc(skiatest::Reporter* reporter) {
    227     {
    228         SkTArray<int> a;
    229         REPORTER_ASSERT(reporter, a.allocCntForTest() == 0);
    230     }
    231     {
    232         SkSTArray<10, int> a;
    233         REPORTER_ASSERT(reporter, a.allocCntForTest() == 10);
    234     }
    235     {
    236         SkTArray<int> a(1);
    237         REPORTER_ASSERT(reporter, a.allocCntForTest() >= 1);
    238     }
    239     {
    240         SkTArray<int> a, b;
    241         b = a;
    242         REPORTER_ASSERT(reporter, b.allocCntForTest() == 0);
    243     }
    244     {
    245         SkSTArray<10, int> a;
    246         SkTArray<int> b;
    247         b = a;
    248         REPORTER_ASSERT(reporter, b.allocCntForTest() == 0);
    249     }
    250     {
    251         SkTArray<int> a;
    252         SkTArray<int> b(a);
    253         REPORTER_ASSERT(reporter, b.allocCntForTest() == 0);
    254     }
    255     {
    256         SkSTArray<10, int> a;
    257         SkTArray<int> b(a);
    258         REPORTER_ASSERT(reporter, b.allocCntForTest() == 0);
    259     }
    260     {
    261         SkTArray<int> a;
    262         SkTArray<int> b(std::move(a));
    263         REPORTER_ASSERT(reporter, b.allocCntForTest() == 0);
    264     }
    265     {
    266         SkSTArray<10, int> a;
    267         SkTArray<int> b(std::move(a));
    268         REPORTER_ASSERT(reporter, b.allocCntForTest() == 0);
    269     }
    270     {
    271         SkTArray<int> a;
    272         SkTArray<int> b;
    273         b = std::move(a);
    274         REPORTER_ASSERT(reporter, b.allocCntForTest() == 0);
    275     }
    276     {
    277         SkSTArray<10, int> a;
    278         SkTArray<int> b;
    279         b = std::move(a);
    280         REPORTER_ASSERT(reporter, b.allocCntForTest() == 0);
    281     }
    282 }
    283 
    284 static void test_self_assignment(skiatest::Reporter* reporter) {
    285     SkTArray<int> a;
    286     a.push_back(1);
    287     REPORTER_ASSERT(reporter, !a.empty());
    288     REPORTER_ASSERT(reporter, a.count() == 1);
    289     REPORTER_ASSERT(reporter, a[0] == 1);
    290 
    291     a = a;
    292     REPORTER_ASSERT(reporter, !a.empty());
    293     REPORTER_ASSERT(reporter, a.count() == 1);
    294     REPORTER_ASSERT(reporter, a[0] == 1);
    295 }
    296 
    297 DEF_TEST(TArray, reporter) {
    298     TestTSet_basic<true>(reporter);
    299     TestTSet_basic<false>(reporter);
    300     test_swap(reporter);
    301 
    302     test_copy_ctor(reporter, SkTArray<sk_sp<SkRefCnt>, false>());
    303     test_copy_ctor(reporter, SkTArray<sk_sp<SkRefCnt>,  true>());
    304     test_copy_ctor(reporter, SkSTArray< 1, sk_sp<SkRefCnt>, false>());
    305     test_copy_ctor(reporter, SkSTArray< 1, sk_sp<SkRefCnt>,  true>());
    306     test_copy_ctor(reporter, SkSTArray<10, sk_sp<SkRefCnt>, false>());
    307     test_copy_ctor(reporter, SkSTArray<10, sk_sp<SkRefCnt>,  true>());
    308 
    309     test_move(reporter);
    310 
    311     test_unnecessary_alloc(reporter);
    312 
    313     test_self_assignment(reporter);
    314 }
    315