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 "tests/Test.h" 9 10#include "include/core/SkString.h" 11#include "src/core/SkStringUtils.h" 12 13#include <math.h> 14#include <stdio.h> 15#include <thread> 16 17DEF_TEST(String, reporter) { 18 SkString a; 19 SkString b((size_t)0); 20 SkString c(""); 21 SkString d(nullptr, 0); 22 23 REPORTER_ASSERT(reporter, a.isEmpty()); 24 REPORTER_ASSERT(reporter, a == b && a == c && a == d); 25 26 a.set("hello"); 27 b.set("hellox", 5); 28 c.set(a); 29 d.resize(5); 30 memcpy(d.writable_str(), "helloz", 5); 31 32 REPORTER_ASSERT(reporter, !a.isEmpty()); 33 REPORTER_ASSERT(reporter, a.size() == 5); 34 REPORTER_ASSERT(reporter, a == b && a == c && a == d); 35 REPORTER_ASSERT(reporter, a.equals("hello", 5)); 36 REPORTER_ASSERT(reporter, a.equals("hello")); 37 REPORTER_ASSERT(reporter, !a.equals("help")); 38 39 REPORTER_ASSERT(reporter, a.startsWith("hell")); 40 REPORTER_ASSERT(reporter, a.startsWith('h')); 41 REPORTER_ASSERT(reporter, !a.startsWith( "ell")); 42 REPORTER_ASSERT(reporter, !a.startsWith( 'e')); 43 REPORTER_ASSERT(reporter, a.startsWith("")); 44 REPORTER_ASSERT(reporter, a.endsWith("llo")); 45 REPORTER_ASSERT(reporter, a.endsWith('o')); 46 REPORTER_ASSERT(reporter, !a.endsWith("ll" )); 47 REPORTER_ASSERT(reporter, !a.endsWith('l')); 48 REPORTER_ASSERT(reporter, a.endsWith("")); 49 REPORTER_ASSERT(reporter, a.contains("he")); 50 REPORTER_ASSERT(reporter, a.contains("ll")); 51 REPORTER_ASSERT(reporter, a.contains("lo")); 52 REPORTER_ASSERT(reporter, a.contains("hello")); 53 REPORTER_ASSERT(reporter, !a.contains("hellohello")); 54 REPORTER_ASSERT(reporter, a.contains("")); 55 REPORTER_ASSERT(reporter, a.contains('e')); 56 REPORTER_ASSERT(reporter, !a.contains('z')); 57 58 SkString e(a); 59 SkString f("hello"); 60 SkString g("helloz", 5); 61 62 REPORTER_ASSERT(reporter, a == e && a == f && a == g); 63 64 b.set("world"); 65 c = b; 66 REPORTER_ASSERT(reporter, a != b && a != c && b == c); 67 68 a.append(" world"); 69 e.append("worldz", 5); 70 e.insert(5, " "); 71 f.set("world"); 72 f.prepend("hello "); 73 REPORTER_ASSERT(reporter, a.equals("hello world") && a == e && a == f); 74 75 a.reset(); 76 b.resize(0); 77 REPORTER_ASSERT(reporter, a.isEmpty() && b.isEmpty() && a == b); 78 79 a.set("a"); 80 a.set("ab"); 81 a.set("abc"); 82 a.set("abcd"); 83 84 a.set(""); 85 a.appendS32(0x7FFFFFFFL); 86 REPORTER_ASSERT(reporter, a.equals("2147483647")); 87 a.set(""); 88 a.appendS32(0x80000001L); 89 REPORTER_ASSERT(reporter, a.equals("-2147483647")); 90 a.set(""); 91 a.appendS32(0x80000000L); 92 REPORTER_ASSERT(reporter, a.equals("-2147483648")); 93 94 a.set(""); 95 a.appendU32(0x7FFFFFFFUL); 96 REPORTER_ASSERT(reporter, a.equals("2147483647")); 97 a.set(""); 98 a.appendU32(0x80000001UL); 99 REPORTER_ASSERT(reporter, a.equals("2147483649")); 100 a.set(""); 101 a.appendU32(0xFFFFFFFFUL); 102 REPORTER_ASSERT(reporter, a.equals("4294967295")); 103 104 a.set(""); 105 a.appendS64(0x7FFFFFFFFFFFFFFFLL, 0); 106 REPORTER_ASSERT(reporter, a.equals("9223372036854775807")); 107 a.set(""); 108 a.appendS64(0x8000000000000001LL, 0); 109 REPORTER_ASSERT(reporter, a.equals("-9223372036854775807")); 110 a.set(""); 111 a.appendS64(0x8000000000000000LL, 0); 112 REPORTER_ASSERT(reporter, a.equals("-9223372036854775808")); 113 a.set(""); 114 a.appendS64(0x0000000001000000LL, 15); 115 REPORTER_ASSERT(reporter, a.equals("000000016777216")); 116 a.set(""); 117 a.appendS64(0xFFFFFFFFFF000000LL, 15); 118 REPORTER_ASSERT(reporter, a.equals("-000000016777216")); 119 120 a.set(""); 121 a.appendU64(0x7FFFFFFFFFFFFFFFULL, 0); 122 REPORTER_ASSERT(reporter, a.equals("9223372036854775807")); 123 a.set(""); 124 a.appendU64(0x8000000000000001ULL, 0); 125 REPORTER_ASSERT(reporter, a.equals("9223372036854775809")); 126 a.set(""); 127 a.appendU64(0xFFFFFFFFFFFFFFFFULL, 0); 128 REPORTER_ASSERT(reporter, a.equals("18446744073709551615")); 129 a.set(""); 130 a.appendU64(0x0000000001000000ULL, 15); 131 REPORTER_ASSERT(reporter, a.equals("000000016777216")); 132 133 a.printf("%i", 0); 134 REPORTER_ASSERT(reporter, a.equals("0")); 135 a.printf("%g", 3.14); 136 REPORTER_ASSERT(reporter, a.equals("3.14")); 137 a.printf("hello %s", "skia"); 138 REPORTER_ASSERT(reporter, a.equals("hello skia")); 139 140 static const struct { 141 SkScalar fValue; 142 const char* fString; 143 } gRec[] = { 144 { 0, "0" }, 145 { SK_Scalar1, "1" }, 146 { -SK_Scalar1, "-1" }, 147 { SK_Scalar1/2, "0.5" }, 148 { INFINITY, "inf" }, 149 { -INFINITY, "-inf" }, 150 { NAN, "nan" }, 151 { -NAN, "nan" }, 152 #if defined(SK_BUILD_FOR_WIN) && (_MSC_VER < 1900) 153 { 3.4028234e38f, "3.4028235e+038" }, 154 { -3.4028234e38f, "-3.4028235e+038" }, 155 #else 156 { 3.4028234e38f, "3.4028235e+38" }, 157 { -3.4028234e38f, "-3.4028235e+38" }, 158 #endif 159 }; 160 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) { 161 a.reset(); 162 a.appendScalar(gRec[i].fValue); 163 REPORTER_ASSERT(reporter, a.size() <= kSkStrAppendScalar_MaxSize); 164 if (!a.equals(gRec[i].fString)) { 165 ERRORF(reporter, "received <%s> expected <%s>\n", a.c_str(), gRec[i].fString); 166 } 167 } 168 169 REPORTER_ASSERT(reporter, SkStringPrintf("%i", 0).equals("0")); 170} 171 172static void assert_2000_spaces(skiatest::Reporter* reporter, const SkString& str) { 173 REPORTER_ASSERT(reporter, str.size() == 2000); 174 for (size_t i = 0; i < str.size(); ++i) { 175 REPORTER_ASSERT(reporter, str[i] == ' '); 176 } 177} 178 179DEF_TEST(String_overflow, reporter) { 180 // 2000 is larger than the static buffer size inside SkString.cpp 181 SkString a = SkStringPrintf("%2000s", " "); 182 assert_2000_spaces(reporter, a); 183 184 a = "X"; 185 a.printf("%2000s", " "); 186 assert_2000_spaces(reporter, a); 187 188 a = "X"; 189 a.appendf("%1999s", " "); 190 REPORTER_ASSERT(reporter, a[0] == 'X'); 191 a[0] = ' '; 192 assert_2000_spaces(reporter, a); 193 194 a = "X"; 195 a.prependf("%1999s", " "); 196 REPORTER_ASSERT(reporter, a[1999] == 'X'); 197 a[1999] = ' '; 198 assert_2000_spaces(reporter, a); 199} 200 201DEF_TEST(String_SkStrSplit, r) { 202 SkTArray<SkString> results; 203 204 SkStrSplit("a-_b_c-dee--f-_-_-g-", "-_", &results); 205 REPORTER_ASSERT(r, results.count() == 6); 206 REPORTER_ASSERT(r, results[0].equals("a")); 207 REPORTER_ASSERT(r, results[1].equals("b")); 208 REPORTER_ASSERT(r, results[2].equals("c")); 209 REPORTER_ASSERT(r, results[3].equals("dee")); 210 REPORTER_ASSERT(r, results[4].equals("f")); 211 REPORTER_ASSERT(r, results[5].equals("g")); 212 213 results.reset(); 214 SkStrSplit("\n", "\n", &results); 215 REPORTER_ASSERT(r, results.count() == 0); 216 217 results.reset(); 218 SkStrSplit("", "\n", &results); 219 REPORTER_ASSERT(r, results.count() == 0); 220 221 results.reset(); 222 SkStrSplit("a", "\n", &results); 223 REPORTER_ASSERT(r, results.count() == 1); 224 REPORTER_ASSERT(r, results[0].equals("a")); 225} 226DEF_TEST(String_SkStrSplit_All, r) { 227 SkTArray<SkString> results; 228 SkStrSplit("a-_b_c-dee--f-_-_-g-", "-_", kStrict_SkStrSplitMode, &results); 229 REPORTER_ASSERT(r, results.count() == 13); 230 REPORTER_ASSERT(r, results[0].equals("a")); 231 REPORTER_ASSERT(r, results[1].equals("")); 232 REPORTER_ASSERT(r, results[2].equals("b")); 233 REPORTER_ASSERT(r, results[3].equals("c")); 234 REPORTER_ASSERT(r, results[4].equals("dee")); 235 REPORTER_ASSERT(r, results[5].equals("")); 236 REPORTER_ASSERT(r, results[6].equals("f")); 237 REPORTER_ASSERT(r, results[7].equals("")); 238 REPORTER_ASSERT(r, results[8].equals("")); 239 REPORTER_ASSERT(r, results[9].equals("")); 240 REPORTER_ASSERT(r, results[10].equals("")); 241 REPORTER_ASSERT(r, results[11].equals("g")); 242 REPORTER_ASSERT(r, results[12].equals("")); 243 244 results.reset(); 245 SkStrSplit("\n", "\n", kStrict_SkStrSplitMode, &results); 246 REPORTER_ASSERT(r, results.count() == 2); 247 REPORTER_ASSERT(r, results[0].equals("")); 248 REPORTER_ASSERT(r, results[1].equals("")); 249 250 results.reset(); 251 SkStrSplit("", "\n", kStrict_SkStrSplitMode, &results); 252 REPORTER_ASSERT(r, results.count() == 0); 253 254 results.reset(); 255 SkStrSplit("a", "\n", kStrict_SkStrSplitMode, &results); 256 REPORTER_ASSERT(r, results.count() == 1); 257 REPORTER_ASSERT(r, results[0].equals("a")); 258 259 results.reset(); 260 SkStrSplit(",,", ",", kStrict_SkStrSplitMode, &results); 261 REPORTER_ASSERT(r, results.count() == 3); 262 REPORTER_ASSERT(r, results[0].equals("")); 263 REPORTER_ASSERT(r, results[1].equals("")); 264 REPORTER_ASSERT(r, results[2].equals("")); 265 266 results.reset(); 267 SkStrSplit(",a,b,", ",", kStrict_SkStrSplitMode, &results); 268 REPORTER_ASSERT(r, results.count() == 4); 269 REPORTER_ASSERT(r, results[0].equals("")); 270 REPORTER_ASSERT(r, results[1].equals("a")); 271 REPORTER_ASSERT(r, results[2].equals("b")); 272 REPORTER_ASSERT(r, results[3].equals("")); 273} 274 275// https://bugs.chromium.org/p/skia/issues/detail?id=7107 276DEF_TEST(String_Threaded, r) { 277 SkString str("foo"); 278 279 std::thread threads[5]; 280 for (auto& thread : threads) { 281 thread = std::thread([&] { 282 SkString copy = str; // NOLINT(performance-unnecessary-copy-initialization) 283 (void)copy.equals("test"); 284 }); 285 } 286 for (auto& thread : threads) { 287 thread.join(); 288 } 289} 290 291// Ensure that the string allocate doesn't internally overflow any calculations, and accidentally 292// let us create a string with a requested length longer than we can manage. 293DEF_TEST(String_huge, r) { 294 // start testing slightly below max 32 295 size_t size = UINT32_MAX - 16; 296 // See where we crash, and manually check that its at the right point. 297 // 298 // To test, change the false to true 299 while (false) { 300 // On a 64bit build, this should crash when size == 1 << 32, since we can't store 301 // that length in the string's header (which has a u32 slot for the length). 302 // 303 // On a 32bit build, this should crash the first time around, since we can't allocate 304 // anywhere near this amount. 305 // 306 SkString str(size); 307 size += 1; 308 } 309} 310 311DEF_TEST(String_fromUTF16, r) { 312 // test data produced with `iconv`. 313 const uint16_t test1[] = { 314 0xD835, 0xDCD0, 0xD835, 0xDCD1, 0xD835, 0xDCD2, 0xD835, 0xDCD3, 0xD835, 0xDCD4, 0x0020, 315 0xD835, 0xDCD5, 0xD835, 0xDCD6, 0xD835, 0xDCD7, 0xD835, 0xDCD8, 0xD835, 0xDCD9 316 }; 317 REPORTER_ASSERT(r, SkStringFromUTF16(test1, SK_ARRAY_COUNT(test1)).equals(" ")); 318 319 const uint16_t test2[] = { 320 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0020, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 321 }; 322 REPORTER_ASSERT(r, SkStringFromUTF16(test2, SK_ARRAY_COUNT(test2)).equals("ABCDE FGHIJ")); 323 324 const uint16_t test3[] = { 325 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x0020, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 326 }; 327 REPORTER_ASSERT(r, SkStringFromUTF16(test3, SK_ARRAY_COUNT(test3)).equals("αβγδε ζηθικ")); 328} 329 330static void test_va_list_print(skiatest::Reporter* r, const char format[], ...) { 331 va_list args; 332 va_start(args, format); 333 334 SkString str("123"); 335 str.printVAList(format, args); 336 REPORTER_ASSERT(r, str.equals("hello world")); 337 338 va_end(args); 339} 340 341static void test_va_list_append(skiatest::Reporter* r, const char format[], ...) { 342 va_list args; 343 va_start(args, format); 344 345 SkString str("123"); 346 str.appendVAList(format, args); 347 REPORTER_ASSERT(r, str.equals("123hello world")); 348 349 va_end(args); 350} 351 352static void test_va_list_prepend(skiatest::Reporter* r, const char format[], ...) { 353 va_list args; 354 va_start(args, format); 355 356 SkString str("123"); 357 str.prependVAList(format, args); 358 REPORTER_ASSERT(r, str.equals("hello world123")); 359 360 va_end(args); 361} 362 363DEF_TEST(String_VAList, r) { 364 test_va_list_print(r, "%s %c%c%c%c%c", "hello", 'w', 'o', 'r', 'l', 'd'); 365 test_va_list_append(r, "%s %c%c%c%c%c", "hello", 'w', 'o', 'r', 'l', 'd'); 366 test_va_list_prepend(r, "%s %c%c%c%c%c", "hello", 'w', 'o', 'r', 'l', 'd'); 367} 368 369static void test_va_list_overflow_print(skiatest::Reporter* r, const char format[], ...) { 370 va_list args; 371 va_start(args, format); 372 373 SkString str("X"); 374 str.printVAList(format, args); 375 assert_2000_spaces(r, str); 376 377 va_end(args); 378} 379 380static void test_va_list_overflow_append(skiatest::Reporter* r, const char format[], ...) { 381 va_list args; 382 va_start(args, format); 383 384 SkString str("X"); 385 str.appendVAList(format, args); 386 REPORTER_ASSERT(r, str[0] == 'X'); 387 str[0] = ' '; 388 assert_2000_spaces(r, str); 389 390 va_end(args); 391} 392 393static void test_va_list_overflow_prepend(skiatest::Reporter* r, const char format[], ...) { 394 va_list args; 395 va_start(args, format); 396 397 SkString str("X"); 398 str.prependVAList(format, args); 399 REPORTER_ASSERT(r, str[1999] == 'X'); 400 str[1999] = ' '; 401 assert_2000_spaces(r, str); 402 403 va_end(args); 404} 405 406DEF_TEST(String_VAList_overflow, r) { 407 test_va_list_overflow_print(r, "%2000s", " "); 408 test_va_list_overflow_append(r, "%1999s", " "); 409 test_va_list_overflow_prepend(r, "%1999s", " "); 410} 411 412DEF_TEST(String_resize_to_nothing, r) { 413 SkString s("hello world!"); 414 REPORTER_ASSERT(r, s.equals("hello world!")); 415 s.resize(0); 416 REPORTER_ASSERT(r, s.equals("")); 417} 418 419DEF_TEST(String_resize_shrink, r) { 420 SkString s("hello world!"); 421 REPORTER_ASSERT(r, s.equals("hello world!")); 422 s.resize(5); 423 REPORTER_ASSERT(r, s.equals("hello")); 424} 425 426DEF_TEST(String_resize_grow, r) { 427 SkString s("hello world!"); 428 REPORTER_ASSERT(r, s.equals("hello world!")); 429 s.resize(25); 430 REPORTER_ASSERT(r, 0 == strcmp(s.c_str(), "hello world!")); // no promises about data past \0 431 REPORTER_ASSERT(r, s.size() == 25); 432} 433 434DEF_TEST(String_resize_after_assignment, r) { 435 SkString s("hello world!"); 436 SkString t; 437 t = s; 438 REPORTER_ASSERT(r, s.equals("hello world!")); 439 s.resize(25); 440 REPORTER_ASSERT(r, 0 == strcmp(s.c_str(), "hello world!")); 441 REPORTER_ASSERT(r, s.size() == 25); 442 s.resize(5); 443 REPORTER_ASSERT(r, s.equals("hello")); 444} 445 446static void resize_helper_function(skiatest::Reporter* r, SkString s) { 447 REPORTER_ASSERT(r, s.equals("hello world!")); 448 s.resize(5); 449 REPORTER_ASSERT(r, s.equals("hello")); 450 s.resize(25); 451 REPORTER_ASSERT(r, 0 == strcmp(s.c_str(), "hello")); 452 REPORTER_ASSERT(r, s.size() == 25); 453} 454 455DEF_TEST(String_resize_after_copy_construction, r) { 456 SkString s("hello world!"); 457 resize_helper_function(r, s); 458} 459