xref: /third_party/skia/tests/StringTest.cpp (revision cb93a386)
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
17DEF_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
172static 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
179DEF_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
201DEF_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}
226DEF_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
276DEF_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.
293DEF_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
311DEF_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
330static 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
341static 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
352static 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
363DEF_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
369static 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
380static 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
393static 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
406DEF_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
412DEF_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
419DEF_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
426DEF_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
434DEF_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
446static 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
455DEF_TEST(String_resize_after_copy_construction, r) {
456    SkString s("hello world!");
457    resize_helper_function(r, s);
458}
459