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 <stdarg.h> 9 #include <stdio.h> 10 #include "SkString.h" 11 #include "Test.h" 12 #include <thread> 13 14 // Windows vsnprintf doesn't 0-terminate safely), but is so far 15 // encapsulated in SkString that we can't test it directly. 16 17 #ifdef SK_BUILD_FOR_WIN 18 #define VSNPRINTF(buffer, size, format, args) \ 19 vsnprintf_s(buffer, size, _TRUNCATE, format, args) 20 #else 21 #define VSNPRINTF vsnprintf 22 #endif 23 24 #define ARGS_TO_BUFFER(format, buffer, size) \ 25 do { \ 26 va_list args; \ 27 va_start(args, format); \ 28 VSNPRINTF(buffer, size, format, args); \ 29 va_end(args); \ 30 } while (0) 31 32 static void printfAnalog(char* buffer, int size, const char format[], ...) { 33 ARGS_TO_BUFFER(format, buffer, size); 34 } 35 36 DEF_TEST(String, reporter) { 37 SkString a; 38 SkString b((size_t)0); 39 SkString c(""); 40 SkString d(nullptr, 0); 41 42 REPORTER_ASSERT(reporter, a.isEmpty()); 43 REPORTER_ASSERT(reporter, a == b && a == c && a == d); 44 45 a.set("hello"); 46 b.set("hellox", 5); 47 c.set(a); 48 d.resize(5); 49 memcpy(d.writable_str(), "helloz", 5); 50 51 REPORTER_ASSERT(reporter, !a.isEmpty()); 52 REPORTER_ASSERT(reporter, a.size() == 5); 53 REPORTER_ASSERT(reporter, a == b && a == c && a == d); 54 REPORTER_ASSERT(reporter, a.equals("hello", 5)); 55 REPORTER_ASSERT(reporter, a.equals("hello")); 56 REPORTER_ASSERT(reporter, !a.equals("help")); 57 58 REPORTER_ASSERT(reporter, a.startsWith("hell")); 59 REPORTER_ASSERT(reporter, a.startsWith('h')); 60 REPORTER_ASSERT(reporter, !a.startsWith( "ell")); 61 REPORTER_ASSERT(reporter, !a.startsWith( 'e')); 62 REPORTER_ASSERT(reporter, a.startsWith("")); 63 REPORTER_ASSERT(reporter, a.endsWith("llo")); 64 REPORTER_ASSERT(reporter, a.endsWith('o')); 65 REPORTER_ASSERT(reporter, !a.endsWith("ll" )); 66 REPORTER_ASSERT(reporter, !a.endsWith('l')); 67 REPORTER_ASSERT(reporter, a.endsWith("")); 68 REPORTER_ASSERT(reporter, a.contains("he")); 69 REPORTER_ASSERT(reporter, a.contains("ll")); 70 REPORTER_ASSERT(reporter, a.contains("lo")); 71 REPORTER_ASSERT(reporter, a.contains("hello")); 72 REPORTER_ASSERT(reporter, !a.contains("hellohello")); 73 REPORTER_ASSERT(reporter, a.contains("")); 74 REPORTER_ASSERT(reporter, a.contains('e')); 75 REPORTER_ASSERT(reporter, !a.contains('z')); 76 77 SkString e(a); 78 SkString f("hello"); 79 SkString g("helloz", 5); 80 81 REPORTER_ASSERT(reporter, a == e && a == f && a == g); 82 83 b.set("world"); 84 c = b; 85 REPORTER_ASSERT(reporter, a != b && a != c && b == c); 86 87 a.append(" world"); 88 e.append("worldz", 5); 89 e.insert(5, " "); 90 f.set("world"); 91 f.prepend("hello "); 92 REPORTER_ASSERT(reporter, a.equals("hello world") && a == e && a == f); 93 94 a.reset(); 95 b.resize(0); 96 REPORTER_ASSERT(reporter, a.isEmpty() && b.isEmpty() && a == b); 97 98 a.set("a"); 99 a.set("ab"); 100 a.set("abc"); 101 a.set("abcd"); 102 103 a.set(""); 104 a.appendS32(0x7FFFFFFFL); 105 REPORTER_ASSERT(reporter, a.equals("2147483647")); 106 a.set(""); 107 a.appendS32(0x80000001L); 108 REPORTER_ASSERT(reporter, a.equals("-2147483647")); 109 a.set(""); 110 a.appendS32(0x80000000L); 111 REPORTER_ASSERT(reporter, a.equals("-2147483648")); 112 113 a.set(""); 114 a.appendU32(0x7FFFFFFFUL); 115 REPORTER_ASSERT(reporter, a.equals("2147483647")); 116 a.set(""); 117 a.appendU32(0x80000001UL); 118 REPORTER_ASSERT(reporter, a.equals("2147483649")); 119 a.set(""); 120 a.appendU32(0xFFFFFFFFUL); 121 REPORTER_ASSERT(reporter, a.equals("4294967295")); 122 123 a.set(""); 124 a.appendS64(0x7FFFFFFFFFFFFFFFLL, 0); 125 REPORTER_ASSERT(reporter, a.equals("9223372036854775807")); 126 a.set(""); 127 a.appendS64(0x8000000000000001LL, 0); 128 REPORTER_ASSERT(reporter, a.equals("-9223372036854775807")); 129 a.set(""); 130 a.appendS64(0x8000000000000000LL, 0); 131 REPORTER_ASSERT(reporter, a.equals("-9223372036854775808")); 132 a.set(""); 133 a.appendS64(0x0000000001000000LL, 15); 134 REPORTER_ASSERT(reporter, a.equals("000000016777216")); 135 a.set(""); 136 a.appendS64(0xFFFFFFFFFF000000LL, 15); 137 REPORTER_ASSERT(reporter, a.equals("-000000016777216")); 138 139 a.set(""); 140 a.appendU64(0x7FFFFFFFFFFFFFFFULL, 0); 141 REPORTER_ASSERT(reporter, a.equals("9223372036854775807")); 142 a.set(""); 143 a.appendU64(0x8000000000000001ULL, 0); 144 REPORTER_ASSERT(reporter, a.equals("9223372036854775809")); 145 a.set(""); 146 a.appendU64(0xFFFFFFFFFFFFFFFFULL, 0); 147 REPORTER_ASSERT(reporter, a.equals("18446744073709551615")); 148 a.set(""); 149 a.appendU64(0x0000000001000000ULL, 15); 150 REPORTER_ASSERT(reporter, a.equals("000000016777216")); 151 152 a.printf("%i", 0); 153 REPORTER_ASSERT(reporter, a.equals("0")); 154 a.printf("%g", 3.14); 155 REPORTER_ASSERT(reporter, a.equals("3.14")); 156 a.printf("hello %s", "skia"); 157 REPORTER_ASSERT(reporter, a.equals("hello skia")); 158 159 static const struct { 160 SkScalar fValue; 161 const char* fString; 162 } gRec[] = { 163 { 0, "0" }, 164 { SK_Scalar1, "1" }, 165 { -SK_Scalar1, "-1" }, 166 { SK_Scalar1/2, "0.5" }, 167 #if defined(SK_BUILD_FOR_WIN) && (_MSC_VER < 1900) 168 { 3.4028234e38f, "3.4028235e+038" }, 169 { -3.4028234e38f, "-3.4028235e+038" }, 170 #else 171 { 3.4028234e38f, "3.4028235e+38" }, 172 { -3.4028234e38f, "-3.4028235e+38" }, 173 #endif 174 }; 175 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) { 176 a.reset(); 177 a.appendScalar(gRec[i].fValue); 178 REPORTER_ASSERT(reporter, a.size() <= SkStrAppendScalar_MaxSize); 179 if (!a.equals(gRec[i].fString)) { 180 ERRORF(reporter, "received <%s> expected <%s>\n", a.c_str(), gRec[i].fString); 181 } 182 } 183 184 REPORTER_ASSERT(reporter, SkStringPrintf("%i", 0).equals("0")); 185 186 char buffer [40]; 187 memset(buffer, 'a', 40); 188 REPORTER_ASSERT(reporter, buffer[18] == 'a'); 189 REPORTER_ASSERT(reporter, buffer[19] == 'a'); 190 REPORTER_ASSERT(reporter, buffer[20] == 'a'); 191 printfAnalog(buffer, 20, "%30d", 0); 192 REPORTER_ASSERT(reporter, buffer[18] == ' '); 193 REPORTER_ASSERT(reporter, buffer[19] == 0); 194 REPORTER_ASSERT(reporter, buffer[20] == 'a'); 195 196 REPORTER_ASSERT(reporter, SkStringPrintf("%i", 0).equals("0")); 197 198 // 2000 is larger than the static buffer size inside SkString.cpp 199 a = SkStringPrintf("%2000s", " "); 200 REPORTER_ASSERT(reporter, a.size() == 2000); 201 for (size_t i = 0; i < a.size(); ++i) { 202 if (a[i] != ' ') { 203 ERRORF(reporter, "SkStringPrintf fail: a[%d] = '%c'", i, a[i]); 204 break; 205 } 206 } 207 a.reset(); 208 a.printf("%2000s", " "); 209 REPORTER_ASSERT(reporter, a.size() == 2000); 210 for (size_t i = 0; i < a.size(); ++i) { 211 if (a[i] != ' ') { 212 ERRORF(reporter, "SkStringPrintf fail: a[%d] = '%c'", i, a[i]); 213 break; 214 } 215 } 216 } 217 218 DEF_TEST(String_SkStrSplit, r) { 219 SkTArray<SkString> results; 220 221 SkStrSplit("a-_b_c-dee--f-_-_-g-", "-_", &results); 222 REPORTER_ASSERT(r, results.count() == 6); 223 REPORTER_ASSERT(r, results[0].equals("a")); 224 REPORTER_ASSERT(r, results[1].equals("b")); 225 REPORTER_ASSERT(r, results[2].equals("c")); 226 REPORTER_ASSERT(r, results[3].equals("dee")); 227 REPORTER_ASSERT(r, results[4].equals("f")); 228 REPORTER_ASSERT(r, results[5].equals("g")); 229 230 results.reset(); 231 SkStrSplit("\n", "\n", &results); 232 REPORTER_ASSERT(r, results.count() == 0); 233 234 results.reset(); 235 SkStrSplit("", "\n", &results); 236 REPORTER_ASSERT(r, results.count() == 0); 237 238 results.reset(); 239 SkStrSplit("a", "\n", &results); 240 REPORTER_ASSERT(r, results.count() == 1); 241 REPORTER_ASSERT(r, results[0].equals("a")); 242 } 243 DEF_TEST(String_SkStrSplit_All, r) { 244 SkTArray<SkString> results; 245 SkStrSplit("a-_b_c-dee--f-_-_-g-", "-_", kStrict_SkStrSplitMode, &results); 246 REPORTER_ASSERT(r, results.count() == 13); 247 REPORTER_ASSERT(r, results[0].equals("a")); 248 REPORTER_ASSERT(r, results[1].equals("")); 249 REPORTER_ASSERT(r, results[2].equals("b")); 250 REPORTER_ASSERT(r, results[3].equals("c")); 251 REPORTER_ASSERT(r, results[4].equals("dee")); 252 REPORTER_ASSERT(r, results[5].equals("")); 253 REPORTER_ASSERT(r, results[6].equals("f")); 254 REPORTER_ASSERT(r, results[7].equals("")); 255 REPORTER_ASSERT(r, results[8].equals("")); 256 REPORTER_ASSERT(r, results[9].equals("")); 257 REPORTER_ASSERT(r, results[10].equals("")); 258 REPORTER_ASSERT(r, results[11].equals("g")); 259 REPORTER_ASSERT(r, results[12].equals("")); 260 261 results.reset(); 262 SkStrSplit("\n", "\n", kStrict_SkStrSplitMode, &results); 263 REPORTER_ASSERT(r, results.count() == 2); 264 REPORTER_ASSERT(r, results[0].equals("")); 265 REPORTER_ASSERT(r, results[1].equals("")); 266 267 results.reset(); 268 SkStrSplit("", "\n", kStrict_SkStrSplitMode, &results); 269 REPORTER_ASSERT(r, results.count() == 0); 270 271 results.reset(); 272 SkStrSplit("a", "\n", kStrict_SkStrSplitMode, &results); 273 REPORTER_ASSERT(r, results.count() == 1); 274 REPORTER_ASSERT(r, results[0].equals("a")); 275 276 results.reset(); 277 SkStrSplit(",,", ",", kStrict_SkStrSplitMode, &results); 278 REPORTER_ASSERT(r, results.count() == 3); 279 REPORTER_ASSERT(r, results[0].equals("")); 280 REPORTER_ASSERT(r, results[1].equals("")); 281 REPORTER_ASSERT(r, results[2].equals("")); 282 283 results.reset(); 284 SkStrSplit(",a,b,", ",", kStrict_SkStrSplitMode, &results); 285 REPORTER_ASSERT(r, results.count() == 4); 286 REPORTER_ASSERT(r, results[0].equals("")); 287 REPORTER_ASSERT(r, results[1].equals("a")); 288 REPORTER_ASSERT(r, results[2].equals("b")); 289 REPORTER_ASSERT(r, results[3].equals("")); 290 } 291 292 // https://bugs.chromium.org/p/skia/issues/detail?id=7107 293 DEF_TEST(String_Threaded, r) { 294 SkString str("foo"); 295 296 std::thread threads[5]; 297 for (auto& thread : threads) { 298 thread = std::thread([&] { 299 SkString copy = str; 300 (void)copy.equals("test"); 301 }); 302 } 303 for (auto& thread : threads) { 304 thread.join(); 305 } 306 } 307