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