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 "Test.h"
9 
10 #include "SkString.h"
11 #include "SkStringUtils.h"
12 
13 #include <stdarg.h>
14 #include <stdio.h>
15 #include <thread>
16 
17 static const char* gThirtyWideDecimal = "%30d";
18 
DEF_TEST(String,reporter)19 DEF_TEST(String, reporter) {
20     SkString    a;
21     SkString    b((size_t)0);
22     SkString    c("");
23     SkString    d(nullptr, 0);
24 
25     REPORTER_ASSERT(reporter, a.isEmpty());
26     REPORTER_ASSERT(reporter, a == b && a == c && a == d);
27 
28     a.set("hello");
29     b.set("hellox", 5);
30     c.set(a);
31     d.resize(5);
32     memcpy(d.writable_str(), "helloz", 5);
33 
34     REPORTER_ASSERT(reporter, !a.isEmpty());
35     REPORTER_ASSERT(reporter, a.size() == 5);
36     REPORTER_ASSERT(reporter, a == b && a == c && a == d);
37     REPORTER_ASSERT(reporter, a.equals("hello", 5));
38     REPORTER_ASSERT(reporter, a.equals("hello"));
39     REPORTER_ASSERT(reporter, !a.equals("help"));
40 
41     REPORTER_ASSERT(reporter,  a.startsWith("hell"));
42     REPORTER_ASSERT(reporter,  a.startsWith('h'));
43     REPORTER_ASSERT(reporter, !a.startsWith( "ell"));
44     REPORTER_ASSERT(reporter, !a.startsWith( 'e'));
45     REPORTER_ASSERT(reporter,  a.startsWith(""));
46     REPORTER_ASSERT(reporter,  a.endsWith("llo"));
47     REPORTER_ASSERT(reporter,  a.endsWith('o'));
48     REPORTER_ASSERT(reporter, !a.endsWith("ll" ));
49     REPORTER_ASSERT(reporter, !a.endsWith('l'));
50     REPORTER_ASSERT(reporter,  a.endsWith(""));
51     REPORTER_ASSERT(reporter,  a.contains("he"));
52     REPORTER_ASSERT(reporter,  a.contains("ll"));
53     REPORTER_ASSERT(reporter,  a.contains("lo"));
54     REPORTER_ASSERT(reporter,  a.contains("hello"));
55     REPORTER_ASSERT(reporter, !a.contains("hellohello"));
56     REPORTER_ASSERT(reporter,  a.contains(""));
57     REPORTER_ASSERT(reporter,  a.contains('e'));
58     REPORTER_ASSERT(reporter, !a.contains('z'));
59 
60     SkString    e(a);
61     SkString    f("hello");
62     SkString    g("helloz", 5);
63 
64     REPORTER_ASSERT(reporter, a == e && a == f && a == g);
65 
66     b.set("world");
67     c = b;
68     REPORTER_ASSERT(reporter, a != b && a != c && b == c);
69 
70     a.append(" world");
71     e.append("worldz", 5);
72     e.insert(5, " ");
73     f.set("world");
74     f.prepend("hello ");
75     REPORTER_ASSERT(reporter, a.equals("hello world") && a == e && a == f);
76 
77     a.reset();
78     b.resize(0);
79     REPORTER_ASSERT(reporter, a.isEmpty() && b.isEmpty() && a == b);
80 
81     a.set("a");
82     a.set("ab");
83     a.set("abc");
84     a.set("abcd");
85 
86     a.set("");
87     a.appendS32(0x7FFFFFFFL);
88     REPORTER_ASSERT(reporter, a.equals("2147483647"));
89     a.set("");
90     a.appendS32(0x80000001L);
91     REPORTER_ASSERT(reporter, a.equals("-2147483647"));
92     a.set("");
93     a.appendS32(0x80000000L);
94     REPORTER_ASSERT(reporter, a.equals("-2147483648"));
95 
96     a.set("");
97     a.appendU32(0x7FFFFFFFUL);
98     REPORTER_ASSERT(reporter, a.equals("2147483647"));
99     a.set("");
100     a.appendU32(0x80000001UL);
101     REPORTER_ASSERT(reporter, a.equals("2147483649"));
102     a.set("");
103     a.appendU32(0xFFFFFFFFUL);
104     REPORTER_ASSERT(reporter, a.equals("4294967295"));
105 
106     a.set("");
107     a.appendS64(0x7FFFFFFFFFFFFFFFLL, 0);
108     REPORTER_ASSERT(reporter, a.equals("9223372036854775807"));
109     a.set("");
110     a.appendS64(0x8000000000000001LL, 0);
111     REPORTER_ASSERT(reporter, a.equals("-9223372036854775807"));
112     a.set("");
113     a.appendS64(0x8000000000000000LL, 0);
114     REPORTER_ASSERT(reporter, a.equals("-9223372036854775808"));
115     a.set("");
116     a.appendS64(0x0000000001000000LL, 15);
117     REPORTER_ASSERT(reporter, a.equals("000000016777216"));
118     a.set("");
119     a.appendS64(0xFFFFFFFFFF000000LL, 15);
120     REPORTER_ASSERT(reporter, a.equals("-000000016777216"));
121 
122     a.set("");
123     a.appendU64(0x7FFFFFFFFFFFFFFFULL, 0);
124     REPORTER_ASSERT(reporter, a.equals("9223372036854775807"));
125     a.set("");
126     a.appendU64(0x8000000000000001ULL, 0);
127     REPORTER_ASSERT(reporter, a.equals("9223372036854775809"));
128     a.set("");
129     a.appendU64(0xFFFFFFFFFFFFFFFFULL, 0);
130     REPORTER_ASSERT(reporter, a.equals("18446744073709551615"));
131     a.set("");
132     a.appendU64(0x0000000001000000ULL, 15);
133     REPORTER_ASSERT(reporter, a.equals("000000016777216"));
134 
135     a.printf("%i", 0);
136     REPORTER_ASSERT(reporter, a.equals("0"));
137     a.printf("%g", 3.14);
138     REPORTER_ASSERT(reporter, a.equals("3.14"));
139     a.printf("hello %s", "skia");
140     REPORTER_ASSERT(reporter, a.equals("hello skia"));
141 
142     static const struct {
143         SkScalar    fValue;
144         const char* fString;
145     } gRec[] = {
146         { 0,            "0" },
147         { SK_Scalar1,   "1" },
148         { -SK_Scalar1,  "-1" },
149         { SK_Scalar1/2, "0.5" },
150   #if defined(SK_BUILD_FOR_WIN) && (_MSC_VER < 1900)
151         { 3.4028234e38f,   "3.4028235e+038" },
152         { -3.4028234e38f, "-3.4028235e+038" },
153   #else
154         { 3.4028234e38f,   "3.4028235e+38" },
155         { -3.4028234e38f, "-3.4028235e+38" },
156   #endif
157     };
158     for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
159         a.reset();
160         a.appendScalar(gRec[i].fValue);
161         REPORTER_ASSERT(reporter, a.size() <= SkStrAppendScalar_MaxSize);
162         if (!a.equals(gRec[i].fString)) {
163             ERRORF(reporter, "received <%s> expected <%s>\n", a.c_str(), gRec[i].fString);
164         }
165     }
166 
167     REPORTER_ASSERT(reporter, SkStringPrintf("%i", 0).equals("0"));
168 
169     char buffer [40];
170     memset(buffer, 'a', 40);
171     REPORTER_ASSERT(reporter, buffer[18] == 'a');
172     REPORTER_ASSERT(reporter, buffer[19] == 'a');
173     REPORTER_ASSERT(reporter, buffer[20] == 'a');
174     snprintf(buffer, 20, gThirtyWideDecimal, 0);
175     REPORTER_ASSERT(reporter, buffer[18] == ' ');
176     REPORTER_ASSERT(reporter, buffer[19] == 0);
177     REPORTER_ASSERT(reporter, buffer[20] == 'a');
178 
179     REPORTER_ASSERT(reporter, SkStringPrintf("%i", 0).equals("0"));
180 
181     // 2000 is larger than the static buffer size inside SkString.cpp
182     a = SkStringPrintf("%2000s", " ");
183     REPORTER_ASSERT(reporter, a.size() == 2000);
184     for (size_t i = 0; i < a.size(); ++i) {
185         if (a[i] != ' ') {
186             ERRORF(reporter, "SkStringPrintf fail: a[%d] = '%c'", i, a[i]);
187             break;
188         }
189     }
190     a.reset();
191     a.printf("%2000s", " ");
192     REPORTER_ASSERT(reporter, a.size() == 2000);
193     for (size_t i = 0; i < a.size(); ++i) {
194         if (a[i] != ' ') {
195             ERRORF(reporter, "SkString::printf fail: a[%d] = '%c'", i, a[i]);
196             break;
197         }
198     }
199     a.appendf("%2000s", " ");
200     REPORTER_ASSERT(reporter, a.size() == 4000);
201     for (size_t i = 0; i < a.size(); ++i) {
202         if (a[i] != ' ') {
203             ERRORF(reporter, "SkString::appendf fail: a[%d] = '%c'", i, a[i]);
204             break;
205         }
206     }
207 }
208 
DEF_TEST(String_SkStrSplit,r)209 DEF_TEST(String_SkStrSplit, r) {
210     SkTArray<SkString> results;
211 
212     SkStrSplit("a-_b_c-dee--f-_-_-g-", "-_", &results);
213     REPORTER_ASSERT(r, results.count() == 6);
214     REPORTER_ASSERT(r, results[0].equals("a"));
215     REPORTER_ASSERT(r, results[1].equals("b"));
216     REPORTER_ASSERT(r, results[2].equals("c"));
217     REPORTER_ASSERT(r, results[3].equals("dee"));
218     REPORTER_ASSERT(r, results[4].equals("f"));
219     REPORTER_ASSERT(r, results[5].equals("g"));
220 
221     results.reset();
222     SkStrSplit("\n", "\n", &results);
223     REPORTER_ASSERT(r, results.count() == 0);
224 
225     results.reset();
226     SkStrSplit("", "\n", &results);
227     REPORTER_ASSERT(r, results.count() == 0);
228 
229     results.reset();
230     SkStrSplit("a", "\n", &results);
231     REPORTER_ASSERT(r, results.count() == 1);
232     REPORTER_ASSERT(r, results[0].equals("a"));
233 }
DEF_TEST(String_SkStrSplit_All,r)234 DEF_TEST(String_SkStrSplit_All, r) {
235     SkTArray<SkString> results;
236     SkStrSplit("a-_b_c-dee--f-_-_-g-", "-_", kStrict_SkStrSplitMode, &results);
237     REPORTER_ASSERT(r, results.count() == 13);
238     REPORTER_ASSERT(r, results[0].equals("a"));
239     REPORTER_ASSERT(r, results[1].equals(""));
240     REPORTER_ASSERT(r, results[2].equals("b"));
241     REPORTER_ASSERT(r, results[3].equals("c"));
242     REPORTER_ASSERT(r, results[4].equals("dee"));
243     REPORTER_ASSERT(r, results[5].equals(""));
244     REPORTER_ASSERT(r, results[6].equals("f"));
245     REPORTER_ASSERT(r, results[7].equals(""));
246     REPORTER_ASSERT(r, results[8].equals(""));
247     REPORTER_ASSERT(r, results[9].equals(""));
248     REPORTER_ASSERT(r, results[10].equals(""));
249     REPORTER_ASSERT(r, results[11].equals("g"));
250     REPORTER_ASSERT(r, results[12].equals(""));
251 
252     results.reset();
253     SkStrSplit("\n", "\n", kStrict_SkStrSplitMode, &results);
254     REPORTER_ASSERT(r, results.count() == 2);
255     REPORTER_ASSERT(r, results[0].equals(""));
256     REPORTER_ASSERT(r, results[1].equals(""));
257 
258     results.reset();
259     SkStrSplit("", "\n", kStrict_SkStrSplitMode, &results);
260     REPORTER_ASSERT(r, results.count() == 0);
261 
262     results.reset();
263     SkStrSplit("a", "\n", kStrict_SkStrSplitMode, &results);
264     REPORTER_ASSERT(r, results.count() == 1);
265     REPORTER_ASSERT(r, results[0].equals("a"));
266 
267     results.reset();
268     SkStrSplit(",,", ",", kStrict_SkStrSplitMode, &results);
269     REPORTER_ASSERT(r, results.count() == 3);
270     REPORTER_ASSERT(r, results[0].equals(""));
271     REPORTER_ASSERT(r, results[1].equals(""));
272     REPORTER_ASSERT(r, results[2].equals(""));
273 
274     results.reset();
275     SkStrSplit(",a,b,", ",", kStrict_SkStrSplitMode, &results);
276     REPORTER_ASSERT(r, results.count() == 4);
277     REPORTER_ASSERT(r, results[0].equals(""));
278     REPORTER_ASSERT(r, results[1].equals("a"));
279     REPORTER_ASSERT(r, results[2].equals("b"));
280     REPORTER_ASSERT(r, results[3].equals(""));
281 }
282 
283 // https://bugs.chromium.org/p/skia/issues/detail?id=7107
DEF_TEST(String_Threaded,r)284 DEF_TEST(String_Threaded, r) {
285     SkString str("foo");
286 
287     std::thread threads[5];
288     for (auto& thread : threads) {
289         thread = std::thread([&] {
290             SkString copy = str;
291             (void)copy.equals("test");
292         });
293     }
294     for (auto& thread : threads) {
295         thread.join();
296     }
297 }
298 
299 // Ensure that the string allocate doesn't internally overflow any calculations, and accidentally
300 // let us create a string with a requested length longer than we can manage.
DEF_TEST(String_huge,r)301 DEF_TEST(String_huge, r) {
302     // start testing slightly below max 32
303     size_t size = UINT32_MAX - 16;
304     // See where we crash, and manually check that its at the right point.
305     //
306     //  To test, change the false to true
307     while (false) {
308         // On a 64bit build, this should crash when size == 1 << 32, since we can't store
309         // that length in the string's header (which has a u32 slot for the length).
310         //
311         // On a 32bit build, this should crash the first time around, since we can't allocate
312         // anywhere near this amount.
313         //
314         SkString str(size);
315         size += 1;
316     }
317 }
318 
DEF_TEST(String_fromUTF16,r)319 DEF_TEST(String_fromUTF16, r) {
320     // test data produced with `iconv`.
321     const uint16_t test1[] = {
322         0xD835, 0xDCD0, 0xD835, 0xDCD1, 0xD835, 0xDCD2, 0xD835, 0xDCD3, 0xD835, 0xDCD4, 0x0020,
323         0xD835, 0xDCD5, 0xD835, 0xDCD6, 0xD835, 0xDCD7, 0xD835, 0xDCD8, 0xD835, 0xDCD9
324     };
325     REPORTER_ASSERT(r, SkStringFromUTF16(test1, SK_ARRAY_COUNT(test1)).equals("���������� ����������"));
326 
327     const uint16_t test2[] = {
328         0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0020, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A,
329     };
330     REPORTER_ASSERT(r, SkStringFromUTF16(test2, SK_ARRAY_COUNT(test2)).equals("ABCDE FGHIJ"));
331 
332     const uint16_t test3[] = {
333         0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x0020, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA,
334     };
335     REPORTER_ASSERT(r, SkStringFromUTF16(test3, SK_ARRAY_COUNT(test3)).equals("αβγδε ζηθικ"));
336 }
337 
338