Flutter Engine
The Flutter Engine
StringTest.cpp
Go to the documentation of this file.
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
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
22using namespace skia_private;
23
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);
180 if (!a.equals(gRec[i].fString)) {
181 ERRORF(reporter, "received <%s> expected <%s>\n", a.c_str(), gRec[i].fString);
182 }
183 }
184
186}
187
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
195DEF_TEST(String_overflow, reporter) {
196 // 2000 is larger than the static buffer size inside SkString.cpp
197 SkString a = SkStringPrintf("%2000s", " ");
199
200 a = "X";
201 a.printf("%2000s", " ");
203
204 a = "X";
205 a.appendf("%1999s", " ");
206 REPORTER_ASSERT(reporter, a[0] == 'X');
207 a[0] = ' ';
209
210 a = "X";
211 a.prependf("%1999s", " ");
212 REPORTER_ASSERT(reporter, a[1999] == 'X');
213 a[1999] = ' ';
215}
216
217DEF_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}
242DEF_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
292DEF_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.
309DEF_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
329DEF_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
348static void test_va_list_print(skiatest::Reporter* r, const char format[], ...)
349 SK_PRINTF_LIKE(2, 3);
350
351static void test_va_list_print(skiatest::Reporter* r, const char format[], ...) {
352 va_list args;
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
362static void test_va_list_append(skiatest::Reporter* r, const char format[], ...)
363 SK_PRINTF_LIKE(2, 3);
364
365static void test_va_list_append(skiatest::Reporter* r, const char format[], ...) {
366 va_list args;
368
369 SkString str("123");
371 REPORTER_ASSERT(r, str.equals("123hello world"));
372
373 va_end(args);
374}
375
376static void test_va_list_prepend(skiatest::Reporter* r, const char format[], ...)
377 SK_PRINTF_LIKE(2, 3);
378
379static void test_va_list_prepend(skiatest::Reporter* r, const char format[], ...) {
380 va_list args;
382
383 SkString str("123");
385 REPORTER_ASSERT(r, str.equals("hello world123"));
386
387 va_end(args);
388}
389
390DEF_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
396static void test_va_list_overflow_print(skiatest::Reporter* r, const char format[], ...)
397 SK_PRINTF_LIKE(2, 3);
398
399static void test_va_list_overflow_print(skiatest::Reporter* r, const char format[], ...) {
400 va_list args;
402
403 SkString str("X");
404 str.printVAList(format, args);
405 assert_2000_spaces(r, str);
406
407 va_end(args);
408}
409
410static void test_va_list_overflow_append(skiatest::Reporter* r, const char format[], ...)
411 SK_PRINTF_LIKE(2, 3);
412
413static void test_va_list_overflow_append(skiatest::Reporter* r, const char format[], ...) {
414 va_list args;
416
417 SkString str("X");
419 REPORTER_ASSERT(r, str[0] == 'X');
420 str[0] = ' ';
421 assert_2000_spaces(r, str);
422
423 va_end(args);
424}
425
426static void test_va_list_overflow_prepend(skiatest::Reporter* r, const char format[], ...)
427 SK_PRINTF_LIKE(2, 3);
428
429static void test_va_list_overflow_prepend(skiatest::Reporter* r, const char format[], ...) {
430 va_list args;
432
433 SkString str("X");
435 REPORTER_ASSERT(r, str[1999] == 'X');
436 str[1999] = ' ';
437 assert_2000_spaces(r, str);
438
439 va_end(args);
440}
441
442DEF_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
448DEF_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
455DEF_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
462DEF_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
470DEF_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
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
491DEF_TEST(String_resize_after_copy_construction, r) {
492 SkString s("hello world!");
494}
static const struct @223 gRec[]
reporter
Definition: FontMgrTest.cpp:39
#define SK_PRINTF_LIKE(A, B)
Definition: SkAttributes.h:52
bool equals(SkDrawable *a, SkDrawable *b)
#define SK_Scalar1
Definition: SkScalar.h:18
void SkStrSplit(const char *str, const char *delimiters, SkStrSplitMode splitMode, TArray< SkString > *out)
SkString SkStringFromUTF16(const uint16_t *src, size_t count)
@ kStrict_SkStrSplitMode
Definition: SkStringUtils.h:47
static constexpr int kSkStrAppendScalar_MaxSize
Definition: SkString.h:101
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
static void test_va_list_append(skiatest::Reporter *r, const char format[],...) SK_PRINTF_LIKE(2
Definition: StringTest.cpp:365
static void test_va_list_print(skiatest::Reporter *r, const char format[],...) SK_PRINTF_LIKE(2
Definition: StringTest.cpp:351
static void test_va_list_overflow_prepend(skiatest::Reporter *r, const char format[],...) SK_PRINTF_LIKE(2
Definition: StringTest.cpp:429
static void test_va_list_overflow_append(skiatest::Reporter *r, const char format[],...) SK_PRINTF_LIKE(2
Definition: StringTest.cpp:413
static void test_va_list_prepend(skiatest::Reporter *r, const char format[],...) SK_PRINTF_LIKE(2
Definition: StringTest.cpp:379
static void resize_helper_function(skiatest::Reporter *r, SkString s)
Definition: StringTest.cpp:482
DEF_TEST(String, reporter)
Definition: StringTest.cpp:24
static void assert_2000_spaces(skiatest::Reporter *reporter, const SkString &str)
Definition: StringTest.cpp:188
static void test_va_list_overflow_print(skiatest::Reporter *r, const char format[],...) SK_PRINTF_LIKE(2
Definition: StringTest.cpp:399
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
#define ERRORF(r,...)
Definition: Test.h:293
static void test1(skiatest::Reporter *reporter, SkWriter32 *writer)
void void void void appendVAList(const char format[], va_list) SK_PRINTF_LIKE(2
Definition: SkString.cpp:557
size_t size() const
Definition: SkString.h:131
void void printVAList(const char format[], va_list) SK_PRINTF_LIKE(2
Definition: SkString.cpp:541
void void void void void void prependVAList(const char format[], va_list) SK_PRINTF_LIKE(2
Definition: SkString.cpp:577
void set(const SkString &src)
Definition: SkString.h:186
bool equals(const SkString &) const
Definition: SkString.cpp:324
int size() const
Definition: SkTArray.h:421
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
float SkScalar
Definition: extension.cpp:12
static bool b
struct MyStruct s
struct MyStruct a[10]
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
uint32_t uint32_t * format
Definition: copy.py:1
va_start(args, format)
va_end(args)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259