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 <stdarg.h>
11 #include <stdio.h>
12 #include <thread>
13
14 #include "SkString.h"
15 #include "SkStringUtils.h"
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 #if defined(SK_BUILD_FOR_WIN) && (_MSC_VER < 1900)
149 { 3.4028234e38f, "3.4028235e+038" },
150 { -3.4028234e38f, "-3.4028235e+038" },
151 #else
152 { 3.4028234e38f, "3.4028235e+38" },
153 { -3.4028234e38f, "-3.4028235e+38" },
154 #endif
155 };
156 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
157 a.reset();
158 a.appendScalar(gRec[i].fValue);
159 REPORTER_ASSERT(reporter, a.size() <= SkStrAppendScalar_MaxSize);
160 if (!a.equals(gRec[i].fString)) {
161 ERRORF(reporter, "received <%s> expected <%s>\n", a.c_str(), gRec[i].fString);
162 }
163 }
164
165 REPORTER_ASSERT(reporter, SkStringPrintf("%i", 0).equals("0"));
166
167 char buffer [40];
168 memset(buffer, 'a', 40);
169 REPORTER_ASSERT(reporter, buffer[18] == 'a');
170 REPORTER_ASSERT(reporter, buffer[19] == 'a');
171 REPORTER_ASSERT(reporter, buffer[20] == 'a');
172 snprintf(buffer, 20, "%30d", 0);
173 REPORTER_ASSERT(reporter, buffer[18] == ' ');
174 REPORTER_ASSERT(reporter, buffer[19] == 0);
175 REPORTER_ASSERT(reporter, buffer[20] == 'a');
176
177 REPORTER_ASSERT(reporter, SkStringPrintf("%i", 0).equals("0"));
178
179 // 2000 is larger than the static buffer size inside SkString.cpp
180 a = SkStringPrintf("%2000s", " ");
181 REPORTER_ASSERT(reporter, a.size() == 2000);
182 for (size_t i = 0; i < a.size(); ++i) {
183 if (a[i] != ' ') {
184 ERRORF(reporter, "SkStringPrintf fail: a[%d] = '%c'", i, a[i]);
185 break;
186 }
187 }
188 a.reset();
189 a.printf("%2000s", " ");
190 REPORTER_ASSERT(reporter, a.size() == 2000);
191 for (size_t i = 0; i < a.size(); ++i) {
192 if (a[i] != ' ') {
193 ERRORF(reporter, "SkStringPrintf fail: a[%d] = '%c'", i, a[i]);
194 break;
195 }
196 }
197 }
198
DEF_TEST(String_SkStrSplit,r)199 DEF_TEST(String_SkStrSplit, r) {
200 SkTArray<SkString> results;
201
202 SkStrSplit("a-_b_c-dee--f-_-_-g-", "-_", &results);
203 REPORTER_ASSERT(r, results.count() == 6);
204 REPORTER_ASSERT(r, results[0].equals("a"));
205 REPORTER_ASSERT(r, results[1].equals("b"));
206 REPORTER_ASSERT(r, results[2].equals("c"));
207 REPORTER_ASSERT(r, results[3].equals("dee"));
208 REPORTER_ASSERT(r, results[4].equals("f"));
209 REPORTER_ASSERT(r, results[5].equals("g"));
210
211 results.reset();
212 SkStrSplit("\n", "\n", &results);
213 REPORTER_ASSERT(r, results.count() == 0);
214
215 results.reset();
216 SkStrSplit("", "\n", &results);
217 REPORTER_ASSERT(r, results.count() == 0);
218
219 results.reset();
220 SkStrSplit("a", "\n", &results);
221 REPORTER_ASSERT(r, results.count() == 1);
222 REPORTER_ASSERT(r, results[0].equals("a"));
223 }
DEF_TEST(String_SkStrSplit_All,r)224 DEF_TEST(String_SkStrSplit_All, r) {
225 SkTArray<SkString> results;
226 SkStrSplit("a-_b_c-dee--f-_-_-g-", "-_", kStrict_SkStrSplitMode, &results);
227 REPORTER_ASSERT(r, results.count() == 13);
228 REPORTER_ASSERT(r, results[0].equals("a"));
229 REPORTER_ASSERT(r, results[1].equals(""));
230 REPORTER_ASSERT(r, results[2].equals("b"));
231 REPORTER_ASSERT(r, results[3].equals("c"));
232 REPORTER_ASSERT(r, results[4].equals("dee"));
233 REPORTER_ASSERT(r, results[5].equals(""));
234 REPORTER_ASSERT(r, results[6].equals("f"));
235 REPORTER_ASSERT(r, results[7].equals(""));
236 REPORTER_ASSERT(r, results[8].equals(""));
237 REPORTER_ASSERT(r, results[9].equals(""));
238 REPORTER_ASSERT(r, results[10].equals(""));
239 REPORTER_ASSERT(r, results[11].equals("g"));
240 REPORTER_ASSERT(r, results[12].equals(""));
241
242 results.reset();
243 SkStrSplit("\n", "\n", kStrict_SkStrSplitMode, &results);
244 REPORTER_ASSERT(r, results.count() == 2);
245 REPORTER_ASSERT(r, results[0].equals(""));
246 REPORTER_ASSERT(r, results[1].equals(""));
247
248 results.reset();
249 SkStrSplit("", "\n", kStrict_SkStrSplitMode, &results);
250 REPORTER_ASSERT(r, results.count() == 0);
251
252 results.reset();
253 SkStrSplit("a", "\n", kStrict_SkStrSplitMode, &results);
254 REPORTER_ASSERT(r, results.count() == 1);
255 REPORTER_ASSERT(r, results[0].equals("a"));
256
257 results.reset();
258 SkStrSplit(",,", ",", kStrict_SkStrSplitMode, &results);
259 REPORTER_ASSERT(r, results.count() == 3);
260 REPORTER_ASSERT(r, results[0].equals(""));
261 REPORTER_ASSERT(r, results[1].equals(""));
262 REPORTER_ASSERT(r, results[2].equals(""));
263
264 results.reset();
265 SkStrSplit(",a,b,", ",", kStrict_SkStrSplitMode, &results);
266 REPORTER_ASSERT(r, results.count() == 4);
267 REPORTER_ASSERT(r, results[0].equals(""));
268 REPORTER_ASSERT(r, results[1].equals("a"));
269 REPORTER_ASSERT(r, results[2].equals("b"));
270 REPORTER_ASSERT(r, results[3].equals(""));
271 }
272
273 // https://bugs.chromium.org/p/skia/issues/detail?id=7107
DEF_TEST(String_Threaded,r)274 DEF_TEST(String_Threaded, r) {
275 SkString str("foo");
276
277 std::thread threads[5];
278 for (auto& thread : threads) {
279 thread = std::thread([&] {
280 SkString copy = str;
281 (void)copy.equals("test");
282 });
283 }
284 for (auto& thread : threads) {
285 thread.join();
286 }
287 }
288
289 // Ensure that the string allocate doesn't internally overflow any calculations, and accidentally
290 // let us create a string with a requested length longer than we can manage.
DEF_TEST(String_huge,r)291 DEF_TEST(String_huge, r) {
292 // start testing slightly below max 32
293 size_t size = SK_MaxU32 - 16;
294 // See where we crash, and manually check that its at the right point.
295 //
296 // To test, change the false to true
297 while (false) {
298 // On a 64bit build, this should crash when size == 1 << 32, since we can't store
299 // that length in the string's header (which has a u32 slot for the length).
300 //
301 // On a 32bit build, this should crash the first time around, since we can't allocate
302 // anywhere near this amount.
303 //
304 SkString str(size);
305 size += 1;
306 }
307 }
308
DEF_TEST(String_fromUTF16,r)309 DEF_TEST(String_fromUTF16, r) {
310 // test data produced with `iconv`.
311 const uint16_t test1[] = {
312 0xD835, 0xDCD0, 0xD835, 0xDCD1, 0xD835, 0xDCD2, 0xD835, 0xDCD3, 0xD835, 0xDCD4, 0x0020,
313 0xD835, 0xDCD5, 0xD835, 0xDCD6, 0xD835, 0xDCD7, 0xD835, 0xDCD8, 0xD835, 0xDCD9
314 };
315 REPORTER_ASSERT(r, SkStringFromUTF16(test1, SK_ARRAY_COUNT(test1)).equals(" "));
316
317 const uint16_t test2[] = {
318 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0020, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A,
319 };
320 REPORTER_ASSERT(r, SkStringFromUTF16(test2, SK_ARRAY_COUNT(test2)).equals("ABCDE FGHIJ"));
321
322 const uint16_t test3[] = {
323 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x0020, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA,
324 };
325 REPORTER_ASSERT(r, SkStringFromUTF16(test3, SK_ARRAY_COUNT(test3)).equals("αβγδε ζηθικ"));
326 }
327
328