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