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 
DEF_TEST(String,reporter)17 DEF_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 
assert_2000_spaces(skiatest::Reporter * reporter,const SkString & str)172 static 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 
DEF_TEST(String_overflow,reporter)179 DEF_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 
DEF_TEST(String_SkStrSplit,r)201 DEF_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 }
DEF_TEST(String_SkStrSplit_All,r)226 DEF_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
DEF_TEST(String_Threaded,r)276 DEF_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.
DEF_TEST(String_huge,r)293 DEF_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 
DEF_TEST(String_fromUTF16,r)311 DEF_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 
test_va_list_print(skiatest::Reporter * r,const char format[],...)330 static 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 
test_va_list_append(skiatest::Reporter * r,const char format[],...)341 static 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 
test_va_list_prepend(skiatest::Reporter * r,const char format[],...)352 static 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 
DEF_TEST(String_VAList,r)363 DEF_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 
test_va_list_overflow_print(skiatest::Reporter * r,const char format[],...)369 static 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 
test_va_list_overflow_append(skiatest::Reporter * r,const char format[],...)380 static 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 
test_va_list_overflow_prepend(skiatest::Reporter * r,const char format[],...)393 static 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 
DEF_TEST(String_VAList_overflow,r)406 DEF_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 
DEF_TEST(String_resize_to_nothing,r)412 DEF_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 
DEF_TEST(String_resize_shrink,r)419 DEF_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 
DEF_TEST(String_resize_grow,r)426 DEF_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 
DEF_TEST(String_resize_after_assignment,r)434 DEF_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 
resize_helper_function(skiatest::Reporter * r,SkString s)446 static 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 
DEF_TEST(String_resize_after_copy_construction,r)455 DEF_TEST(String_resize_after_copy_construction, r) {
456     SkString s("hello world!");
457     resize_helper_function(r, s);
458 }
459