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