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 "SkRandom.h" 9 #include "SkRefCnt.h" 10 #include "SkTSearch.h" 11 #include "SkTSort.h" 12 #include "SkUtils.h" 13 #include "Test.h" 14 15 class RefClass : public SkRefCnt { 16 public: 17 18 19 RefClass(int n) : fN(n) {} 20 int get() const { return fN; } 21 22 private: 23 int fN; 24 25 typedef SkRefCnt INHERITED; 26 }; 27 28 static void test_autounref(skiatest::Reporter* reporter) { 29 RefClass obj(0); 30 REPORTER_ASSERT(reporter, obj.unique()); 31 32 SkAutoTUnref<RefClass> tmp(&obj); 33 REPORTER_ASSERT(reporter, &obj == tmp.get()); 34 REPORTER_ASSERT(reporter, obj.unique()); 35 36 REPORTER_ASSERT(reporter, &obj == tmp.detach()); 37 REPORTER_ASSERT(reporter, obj.unique()); 38 REPORTER_ASSERT(reporter, nullptr == tmp.detach()); 39 REPORTER_ASSERT(reporter, nullptr == tmp.get()); 40 41 obj.ref(); 42 REPORTER_ASSERT(reporter, !obj.unique()); 43 { 44 SkAutoTUnref<RefClass> tmp2(&obj); 45 } 46 REPORTER_ASSERT(reporter, obj.unique()); 47 } 48 49 static void test_autostarray(skiatest::Reporter* reporter) { 50 RefClass obj0(0); 51 RefClass obj1(1); 52 REPORTER_ASSERT(reporter, obj0.unique()); 53 REPORTER_ASSERT(reporter, obj1.unique()); 54 55 { 56 SkAutoSTArray<2, SkAutoTUnref<RefClass> > tmp; 57 REPORTER_ASSERT(reporter, 0 == tmp.count()); 58 59 tmp.reset(0); // test out reset(0) when already at 0 60 tmp.reset(4); // this should force a new allocation 61 REPORTER_ASSERT(reporter, 4 == tmp.count()); 62 tmp[0].reset(SkRef(&obj0)); 63 tmp[1].reset(SkRef(&obj1)); 64 REPORTER_ASSERT(reporter, !obj0.unique()); 65 REPORTER_ASSERT(reporter, !obj1.unique()); 66 67 // test out reset with data in the array (and a new allocation) 68 tmp.reset(0); 69 REPORTER_ASSERT(reporter, 0 == tmp.count()); 70 REPORTER_ASSERT(reporter, obj0.unique()); 71 REPORTER_ASSERT(reporter, obj1.unique()); 72 73 tmp.reset(2); // this should use the preexisting allocation 74 REPORTER_ASSERT(reporter, 2 == tmp.count()); 75 tmp[0].reset(SkRef(&obj0)); 76 tmp[1].reset(SkRef(&obj1)); 77 } 78 79 // test out destructor with data in the array (and using existing allocation) 80 REPORTER_ASSERT(reporter, obj0.unique()); 81 REPORTER_ASSERT(reporter, obj1.unique()); 82 83 { 84 // test out allocating ctor (this should allocate new memory) 85 SkAutoSTArray<2, SkAutoTUnref<RefClass> > tmp(4); 86 REPORTER_ASSERT(reporter, 4 == tmp.count()); 87 88 tmp[0].reset(SkRef(&obj0)); 89 tmp[1].reset(SkRef(&obj1)); 90 REPORTER_ASSERT(reporter, !obj0.unique()); 91 REPORTER_ASSERT(reporter, !obj1.unique()); 92 93 // Test out resut with data in the array and malloced storage 94 tmp.reset(0); 95 REPORTER_ASSERT(reporter, obj0.unique()); 96 REPORTER_ASSERT(reporter, obj1.unique()); 97 98 tmp.reset(2); // this should use the preexisting storage 99 tmp[0].reset(SkRef(&obj0)); 100 tmp[1].reset(SkRef(&obj1)); 101 REPORTER_ASSERT(reporter, !obj0.unique()); 102 REPORTER_ASSERT(reporter, !obj1.unique()); 103 104 tmp.reset(4); // this should force a new malloc 105 REPORTER_ASSERT(reporter, obj0.unique()); 106 REPORTER_ASSERT(reporter, obj1.unique()); 107 108 tmp[0].reset(SkRef(&obj0)); 109 tmp[1].reset(SkRef(&obj1)); 110 REPORTER_ASSERT(reporter, !obj0.unique()); 111 REPORTER_ASSERT(reporter, !obj1.unique()); 112 } 113 114 REPORTER_ASSERT(reporter, obj0.unique()); 115 REPORTER_ASSERT(reporter, obj1.unique()); 116 } 117 118 ///////////////////////////////////////////////////////////////////////////// 119 120 #define kSEARCH_COUNT 91 121 122 static void test_search(skiatest::Reporter* reporter) { 123 int i, array[kSEARCH_COUNT]; 124 SkRandom rand; 125 126 for (i = 0; i < kSEARCH_COUNT; i++) { 127 array[i] = rand.nextS(); 128 } 129 130 SkTHeapSort<int>(array, kSEARCH_COUNT); 131 // make sure we got sorted properly 132 for (i = 1; i < kSEARCH_COUNT; i++) { 133 REPORTER_ASSERT(reporter, array[i-1] <= array[i]); 134 } 135 136 // make sure we can find all of our values 137 for (i = 0; i < kSEARCH_COUNT; i++) { 138 int index = SkTSearch<int>(array, kSEARCH_COUNT, array[i], sizeof(int)); 139 REPORTER_ASSERT(reporter, index == i); 140 } 141 142 // make sure that random values are either found, or the correct 143 // insertion index is returned 144 for (i = 0; i < 10000; i++) { 145 int value = rand.nextS(); 146 int index = SkTSearch<int>(array, kSEARCH_COUNT, value, sizeof(int)); 147 148 if (index >= 0) { 149 REPORTER_ASSERT(reporter, 150 index < kSEARCH_COUNT && array[index] == value); 151 } else { 152 index = ~index; 153 REPORTER_ASSERT(reporter, index <= kSEARCH_COUNT); 154 if (index < kSEARCH_COUNT) { 155 REPORTER_ASSERT(reporter, value < array[index]); 156 if (index > 0) { 157 REPORTER_ASSERT(reporter, value > array[index - 1]); 158 } 159 } else { 160 // we should append the new value 161 REPORTER_ASSERT(reporter, value > array[kSEARCH_COUNT - 1]); 162 } 163 } 164 } 165 } 166 167 static void test_utf16(skiatest::Reporter* reporter) { 168 static const SkUnichar gUni[] = { 169 0x10000, 0x18080, 0x20202, 0xFFFFF, 0x101234 170 }; 171 172 uint16_t buf[2]; 173 174 for (size_t i = 0; i < SK_ARRAY_COUNT(gUni); i++) { 175 size_t count = SkUTF16_FromUnichar(gUni[i], buf); 176 REPORTER_ASSERT(reporter, count == 2); 177 size_t count2 = SkUTF16_CountUnichars(buf, 2); 178 REPORTER_ASSERT(reporter, count2 == 1); 179 const uint16_t* ptr = buf; 180 SkUnichar c = SkUTF16_NextUnichar(&ptr); 181 REPORTER_ASSERT(reporter, c == gUni[i]); 182 REPORTER_ASSERT(reporter, ptr - buf == 2); 183 } 184 } 185 186 DEF_TEST(Utils, reporter) { 187 static const struct { 188 const char* fUtf8; 189 SkUnichar fUni; 190 } gTest[] = { 191 { "a", 'a' }, 192 { "\x7f", 0x7f }, 193 { "\xC2\x80", 0x80 }, 194 { "\xC3\x83", (3 << 6) | 3 }, 195 { "\xDF\xBF", 0x7ff }, 196 { "\xE0\xA0\x80", 0x800 }, 197 { "\xE0\xB0\xB8", 0xC38 }, 198 { "\xE3\x83\x83", (3 << 12) | (3 << 6) | 3 }, 199 { "\xEF\xBF\xBF", 0xFFFF }, 200 { "\xF0\x90\x80\x80", 0x10000 }, 201 { "\xF3\x83\x83\x83", (3 << 18) | (3 << 12) | (3 << 6) | 3 } 202 }; 203 204 for (size_t i = 0; i < SK_ARRAY_COUNT(gTest); i++) { 205 const char* p = gTest[i].fUtf8; 206 int n = SkUTF8_CountUnichars(p); 207 SkUnichar u0 = SkUTF8_ToUnichar(gTest[i].fUtf8); 208 SkUnichar u1 = SkUTF8_NextUnichar(&p); 209 210 REPORTER_ASSERT(reporter, n == 1); 211 REPORTER_ASSERT(reporter, u0 == u1); 212 REPORTER_ASSERT(reporter, u0 == gTest[i].fUni); 213 REPORTER_ASSERT(reporter, 214 p - gTest[i].fUtf8 == (int)strlen(gTest[i].fUtf8)); 215 } 216 217 test_utf16(reporter); 218 test_search(reporter); 219 test_autounref(reporter); 220 test_autostarray(reporter); 221 } 222