Serenity Operating System
1/*
2 * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7// This is included first on purpose. We specifically do not want LibTest to override VERIFY here so
8// that we can actually test that some String factory methods cause a crash with invalid input.
9#include <AK/String.h>
10
11#include <LibTest/TestCase.h>
12
13#include <AK/MemoryStream.h>
14#include <AK/StringBuilder.h>
15#include <AK/Try.h>
16#include <AK/Utf8View.h>
17#include <AK/Vector.h>
18
19TEST_CASE(construct_empty)
20{
21 String empty;
22 EXPECT(empty.is_empty());
23 EXPECT_EQ(empty.bytes().size(), 0u);
24 EXPECT_EQ(empty, ""sv);
25
26 auto empty2 = MUST(""_string);
27 EXPECT(empty2.is_empty());
28 EXPECT_EQ(empty, empty2);
29
30 auto empty3 = MUST(String::from_utf8(""sv));
31 EXPECT(empty3.is_empty());
32 EXPECT_EQ(empty, empty3);
33}
34
35TEST_CASE(move_assignment)
36{
37 String string1 = MUST("hello"_string);
38 string1 = MUST("friends!"_string);
39 EXPECT_EQ(string1, "friends!"sv);
40}
41
42TEST_CASE(short_strings)
43{
44#ifdef AK_ARCH_64_BIT
45 auto string1 = MUST(String::from_utf8("abcdefg"sv));
46 EXPECT_EQ(string1.is_short_string(), true);
47 EXPECT_EQ(string1.bytes().size(), 7u);
48 EXPECT_EQ(string1.bytes_as_string_view(), "abcdefg"sv);
49
50 constexpr auto string2 = String::from_utf8_short_string("abcdefg"sv);
51 EXPECT_EQ(string2.is_short_string(), true);
52 EXPECT_EQ(string2.bytes().size(), 7u);
53 EXPECT_EQ(string2, string1);
54
55 auto string3 = MUST("abcdefg"_string);
56 EXPECT_EQ(string3.is_short_string(), true);
57 EXPECT_EQ(string3.bytes().size(), 7u);
58 EXPECT_EQ(string3, string1);
59
60 constexpr auto string4 = "abcdefg"_short_string;
61 EXPECT_EQ(string4.is_short_string(), true);
62 EXPECT_EQ(string4.bytes().size(), 7u);
63 EXPECT_EQ(string4, string1);
64#else
65 auto string1 = MUST(String::from_utf8("abc"sv));
66 EXPECT_EQ(string1.is_short_string(), true);
67 EXPECT_EQ(string1.bytes().size(), 3u);
68 EXPECT_EQ(string1.bytes_as_string_view(), "abc"sv);
69
70 constexpr auto string2 = String::from_utf8_short_string("abc"sv);
71 EXPECT_EQ(string2.is_short_string(), true);
72 EXPECT_EQ(string2.bytes().size(), 3u);
73 EXPECT_EQ(string2, string1);
74
75 auto string3 = MUST("abc"_string);
76 EXPECT_EQ(string3.is_short_string(), true);
77 EXPECT_EQ(string3.bytes().size(), 3u);
78 EXPECT_EQ(string3, string1);
79
80 constexpr auto string4 = "abc"_short_string;
81 EXPECT_EQ(string4.is_short_string(), true);
82 EXPECT_EQ(string4.bytes().size(), 3u);
83 EXPECT_EQ(string4, string1);
84#endif
85}
86
87TEST_CASE(long_strings)
88{
89 auto string = MUST(String::from_utf8("abcdefgh"sv));
90 EXPECT_EQ(string.is_short_string(), false);
91 EXPECT_EQ(string.bytes().size(), 8u);
92 EXPECT_EQ(string.bytes_as_string_view(), "abcdefgh"sv);
93}
94
95TEST_CASE(long_streams)
96{
97 {
98 u8 bytes[64] = {};
99 constexpr auto test_view = "Well, hello friends"sv;
100 FixedMemoryStream stream(Bytes { bytes, sizeof(bytes) });
101 MUST(stream.write_until_depleted(test_view.bytes()));
102 MUST(stream.seek(0));
103
104 auto string = MUST(String::from_stream(stream, test_view.length()));
105
106 EXPECT_EQ(string.is_short_string(), false);
107 EXPECT_EQ(string.bytes().size(), 19u);
108 EXPECT_EQ(string.bytes_as_string_view(), test_view);
109 }
110
111 {
112 AllocatingMemoryStream stream;
113 MUST(stream.write_until_depleted(("abc"sv).bytes()));
114
115 auto string = MUST(String::from_stream(stream, 3u));
116
117 EXPECT_EQ(string.is_short_string(), true);
118 EXPECT_EQ(string.bytes().size(), 3u);
119 EXPECT_EQ(string.bytes_as_string_view(), "abc"sv);
120 }
121
122 {
123 AllocatingMemoryStream stream;
124 MUST(stream.write_until_depleted(("0123456789"sv).bytes()));
125
126 auto string = MUST(String::from_stream(stream, 9u));
127
128 EXPECT_EQ(string.is_short_string(), false);
129 EXPECT_EQ(string.bytes().size(), 9u);
130 EXPECT_EQ(string.bytes_as_string_view(), "012345678"sv);
131 }
132
133 {
134 AllocatingMemoryStream stream;
135 MUST(stream.write_value(0xffffffff));
136 MUST(stream.write_value(0xffffffff));
137 MUST(stream.write_value(0xffffffff));
138 auto error_or_string = String::from_stream(stream, stream.used_buffer_size());
139 EXPECT_EQ(error_or_string.is_error(), true);
140 }
141}
142
143TEST_CASE(invalid_utf8)
144{
145 auto string1 = String::from_utf8("long string \xf4\x8f\xbf\xc0"sv); // U+110000
146 EXPECT(string1.is_error());
147 EXPECT(string1.error().string_literal().contains("Input was not valid UTF-8"sv));
148
149 auto string2 = String::from_utf8("\xf4\xa1\xb0\xbd"sv); // U+121C3D
150 EXPECT(string2.is_error());
151 EXPECT(string2.error().string_literal().contains("Input was not valid UTF-8"sv));
152
153 AllocatingMemoryStream stream;
154 MUST(stream.write_value<u8>(0xf4));
155 MUST(stream.write_value<u8>(0xa1));
156 MUST(stream.write_value<u8>(0xb0));
157 MUST(stream.write_value<u8>(0xbd));
158 auto string3 = String::from_stream(stream, stream.used_buffer_size());
159 EXPECT_EQ(string3.is_error(), true);
160 EXPECT(string3.error().string_literal().contains("Input was not valid UTF-8"sv));
161}
162
163TEST_CASE(from_code_points)
164{
165 for (u32 code_point = 0; code_point < 0x80; ++code_point) {
166 auto string = String::from_code_point(code_point);
167
168 auto ch = static_cast<char>(code_point);
169 StringView view { &ch, 1 };
170
171 EXPECT_EQ(string, view);
172 }
173
174 auto string = String::from_code_point(0x10ffff);
175 EXPECT_EQ(string, "\xF4\x8F\xBF\xBF"sv);
176
177 EXPECT_CRASH("Creating a string from an invalid code point", [] {
178 String::from_code_point(0xffffffff);
179 return Test::Crash::Failure::DidNotCrash;
180 });
181}
182
183TEST_CASE(substring)
184{
185 auto superstring = MUST("Hello I am a long string"_string);
186 auto short_substring = MUST(superstring.substring_from_byte_offset(0, 5));
187 EXPECT_EQ(short_substring, "Hello"sv);
188
189 auto long_substring = MUST(superstring.substring_from_byte_offset(0, 10));
190 EXPECT_EQ(long_substring, "Hello I am"sv);
191}
192
193TEST_CASE(substring_with_shared_superstring)
194{
195 auto superstring = MUST("Hello I am a long string"_string);
196
197 auto substring1 = MUST(superstring.substring_from_byte_offset_with_shared_superstring(0, 5));
198 EXPECT_EQ(substring1, "Hello"sv);
199
200 auto substring2 = MUST(superstring.substring_from_byte_offset_with_shared_superstring(0, 10));
201 EXPECT_EQ(substring2, "Hello I am"sv);
202}
203
204TEST_CASE(code_points)
205{
206 auto string = MUST("🦬🪒"_string);
207
208 Vector<u32> code_points;
209 for (auto code_point : string.code_points())
210 code_points.append(code_point);
211
212 EXPECT_EQ(code_points[0], 0x1f9acu);
213 EXPECT_EQ(code_points[1], 0x1fa92u);
214}
215
216TEST_CASE(string_builder)
217{
218 StringBuilder builder;
219 builder.append_code_point(0x1f9acu);
220 builder.append_code_point(0x1fa92u);
221
222 auto string = MUST(builder.to_string());
223 EXPECT_EQ(string, "🦬🪒"sv);
224 EXPECT_EQ(string.bytes().size(), 8u);
225}
226
227TEST_CASE(ak_format)
228{
229 auto foo = MUST(String::formatted("Hello {}", MUST("friends"_string)));
230 EXPECT_EQ(foo, "Hello friends"sv);
231}
232
233TEST_CASE(replace)
234{
235 {
236 auto haystack = MUST("Hello enemies"_string);
237 auto result = MUST(haystack.replace("enemies"sv, "friends"sv, ReplaceMode::All));
238 EXPECT_EQ(result, "Hello friends"sv);
239 }
240
241 {
242 auto base_title = MUST("anon@courage:~"_string);
243 auto result = MUST(base_title.replace("[*]"sv, "(*)"sv, ReplaceMode::FirstOnly));
244 EXPECT_EQ(result, "anon@courage:~"sv);
245 }
246}
247
248TEST_CASE(reverse)
249{
250 auto test_reverse = [](auto test, auto expected) {
251 auto string = MUST(String::from_utf8(test));
252 auto result = MUST(string.reverse());
253
254 EXPECT_EQ(result, expected);
255 };
256
257 test_reverse(""sv, ""sv);
258 test_reverse("a"sv, "a"sv);
259 test_reverse("ab"sv, "ba"sv);
260 test_reverse("ab cd ef"sv, "fe dc ba"sv);
261 test_reverse("😀"sv, "😀"sv);
262 test_reverse("ab😀cd"sv, "dc😀ba"sv);
263}
264
265TEST_CASE(to_lowercase)
266{
267 {
268 auto string = MUST("Aa"_string);
269 auto result = MUST(string.to_lowercase());
270 EXPECT_EQ(result, "aa"sv);
271 }
272 {
273 auto string = MUST("Ωω"_string);
274 auto result = MUST(string.to_lowercase());
275 EXPECT_EQ(result, "ωω"sv);
276 }
277 {
278 auto string = MUST("İi̇"_string);
279 auto result = MUST(string.to_lowercase());
280 EXPECT_EQ(result, "i̇i̇"sv);
281 }
282}
283
284TEST_CASE(to_uppercase)
285{
286 {
287 auto string = MUST("Aa"_string);
288 auto result = MUST(string.to_uppercase());
289 EXPECT_EQ(result, "AA"sv);
290 }
291 {
292 auto string = MUST("Ωω"_string);
293 auto result = MUST(string.to_uppercase());
294 EXPECT_EQ(result, "ΩΩ"sv);
295 }
296 {
297 auto string = MUST("ʼn"_string);
298 auto result = MUST(string.to_uppercase());
299 EXPECT_EQ(result, "ʼN"sv);
300 }
301}
302
303TEST_CASE(to_titlecase)
304{
305 {
306 auto string = MUST("foo bar baz"_string);
307 auto result = MUST(string.to_titlecase());
308 EXPECT_EQ(result, "Foo Bar Baz"sv);
309 }
310 {
311 auto string = MUST("foo \n \r bar \t baz"_string);
312 auto result = MUST(string.to_titlecase());
313 EXPECT_EQ(result, "Foo \n \r Bar \t Baz"sv);
314 }
315 {
316 auto string = MUST("f\"oo\" b'ar'"_string);
317 auto result = MUST(string.to_titlecase());
318 EXPECT_EQ(result, "F\"Oo\" B'ar'"sv);
319 }
320 {
321 auto string = MUST("123dollars"_string);
322 auto result = MUST(string.to_titlecase());
323 EXPECT_EQ(result, "123Dollars"sv);
324 }
325}
326
327TEST_CASE(equals_ignoring_case)
328{
329 {
330 String string1 {};
331 String string2 {};
332
333 EXPECT(string1.equals_ignoring_case(string2));
334 }
335 {
336 auto string1 = MUST("abcd"_string);
337 auto string2 = MUST("ABCD"_string);
338 auto string3 = MUST("AbCd"_string);
339 auto string4 = MUST("dcba"_string);
340 auto string5 = MUST("abce"_string);
341 auto string6 = MUST("abc"_string);
342
343 EXPECT(string1.equals_ignoring_case(string2));
344 EXPECT(string1.equals_ignoring_case(string3));
345 EXPECT(!string1.equals_ignoring_case(string4));
346 EXPECT(!string1.equals_ignoring_case(string5));
347 EXPECT(!string1.equals_ignoring_case(string6));
348
349 EXPECT(string2.equals_ignoring_case(string1));
350 EXPECT(string2.equals_ignoring_case(string3));
351 EXPECT(!string2.equals_ignoring_case(string4));
352 EXPECT(!string2.equals_ignoring_case(string5));
353 EXPECT(!string2.equals_ignoring_case(string6));
354
355 EXPECT(string3.equals_ignoring_case(string1));
356 EXPECT(string3.equals_ignoring_case(string2));
357 EXPECT(!string3.equals_ignoring_case(string4));
358 EXPECT(!string3.equals_ignoring_case(string5));
359 EXPECT(!string3.equals_ignoring_case(string6));
360 }
361 {
362 auto string1 = MUST("\u00DF"_string); // LATIN SMALL LETTER SHARP S
363 auto string2 = MUST("SS"_string);
364 auto string3 = MUST("Ss"_string);
365 auto string4 = MUST("ss"_string);
366 auto string5 = MUST("S"_string);
367 auto string6 = MUST("s"_string);
368
369 EXPECT(string1.equals_ignoring_case(string2));
370 EXPECT(string1.equals_ignoring_case(string3));
371 EXPECT(string1.equals_ignoring_case(string4));
372 EXPECT(!string1.equals_ignoring_case(string5));
373 EXPECT(!string1.equals_ignoring_case(string6));
374
375 EXPECT(string2.equals_ignoring_case(string1));
376 EXPECT(string2.equals_ignoring_case(string3));
377 EXPECT(string2.equals_ignoring_case(string4));
378 EXPECT(!string2.equals_ignoring_case(string5));
379 EXPECT(!string2.equals_ignoring_case(string6));
380
381 EXPECT(string3.equals_ignoring_case(string1));
382 EXPECT(string3.equals_ignoring_case(string2));
383 EXPECT(string3.equals_ignoring_case(string4));
384 EXPECT(!string3.equals_ignoring_case(string5));
385 EXPECT(!string3.equals_ignoring_case(string6));
386
387 EXPECT(string4.equals_ignoring_case(string1));
388 EXPECT(string4.equals_ignoring_case(string2));
389 EXPECT(string4.equals_ignoring_case(string3));
390 EXPECT(!string4.equals_ignoring_case(string5));
391 EXPECT(!string4.equals_ignoring_case(string6));
392 }
393 {
394
395 auto string1 = MUST("Ab\u00DFCd\u00DFeF"_string);
396 auto string2 = MUST("ABSSCDSSEF"_string);
397 auto string3 = MUST("absscdssef"_string);
398 auto string4 = MUST("aBSscDsSEf"_string);
399 auto string5 = MUST("Ab\u00DFCd\u00DFeg"_string);
400 auto string6 = MUST("Ab\u00DFCd\u00DFe"_string);
401
402 EXPECT(string1.equals_ignoring_case(string1));
403 EXPECT(string1.equals_ignoring_case(string2));
404 EXPECT(string1.equals_ignoring_case(string3));
405 EXPECT(string1.equals_ignoring_case(string4));
406 EXPECT(!string1.equals_ignoring_case(string5));
407 EXPECT(!string1.equals_ignoring_case(string6));
408
409 EXPECT(string2.equals_ignoring_case(string1));
410 EXPECT(string2.equals_ignoring_case(string2));
411 EXPECT(string2.equals_ignoring_case(string3));
412 EXPECT(string2.equals_ignoring_case(string4));
413 EXPECT(!string2.equals_ignoring_case(string5));
414 EXPECT(!string2.equals_ignoring_case(string6));
415
416 EXPECT(string3.equals_ignoring_case(string1));
417 EXPECT(string3.equals_ignoring_case(string2));
418 EXPECT(string3.equals_ignoring_case(string3));
419 EXPECT(string3.equals_ignoring_case(string4));
420 EXPECT(!string3.equals_ignoring_case(string5));
421 EXPECT(!string3.equals_ignoring_case(string6));
422
423 EXPECT(string4.equals_ignoring_case(string1));
424 EXPECT(string4.equals_ignoring_case(string2));
425 EXPECT(string4.equals_ignoring_case(string3));
426 EXPECT(string4.equals_ignoring_case(string4));
427 EXPECT(!string4.equals_ignoring_case(string5));
428 EXPECT(!string4.equals_ignoring_case(string6));
429 }
430}
431
432TEST_CASE(is_one_of)
433{
434 auto foo = MUST("foo"_string);
435 auto bar = MUST("bar"_string);
436
437 EXPECT(foo.is_one_of(foo));
438 EXPECT(foo.is_one_of(foo, bar));
439 EXPECT(foo.is_one_of(bar, foo));
440 EXPECT(!foo.is_one_of(bar));
441
442 EXPECT(!bar.is_one_of("foo"sv));
443 EXPECT(bar.is_one_of("foo"sv, "bar"sv));
444 EXPECT(bar.is_one_of("bar"sv, "foo"sv));
445 EXPECT(bar.is_one_of("bar"sv));
446}
447
448TEST_CASE(split)
449{
450 {
451 auto test = MUST("foo bar baz"_string);
452 auto parts = MUST(test.split(' '));
453 EXPECT_EQ(parts.size(), 3u);
454 EXPECT_EQ(parts[0], "foo");
455 EXPECT_EQ(parts[1], "bar");
456 EXPECT_EQ(parts[2], "baz");
457 }
458 {
459 auto test = MUST("ωΣ2ωΣω"_string);
460 auto parts = MUST(test.split(0x03A3u));
461 EXPECT_EQ(parts.size(), 3u);
462 EXPECT_EQ(parts[0], "ω"sv);
463 EXPECT_EQ(parts[1], "2ω"sv);
464 EXPECT_EQ(parts[2], "ω"sv);
465 }
466}
467
468TEST_CASE(find_byte_offset)
469{
470 {
471 String string {};
472 auto index1 = string.find_byte_offset(0);
473 EXPECT(!index1.has_value());
474
475 auto index2 = string.find_byte_offset(""sv);
476 EXPECT(!index2.has_value());
477 }
478 {
479 auto string = MUST("foo"_string);
480
481 auto index1 = string.find_byte_offset('f');
482 EXPECT_EQ(index1, 0u);
483
484 auto index2 = string.find_byte_offset('o');
485 EXPECT_EQ(index2, 1u);
486
487 auto index3 = string.find_byte_offset('o', *index2 + 1);
488 EXPECT_EQ(index3, 2u);
489
490 auto index4 = string.find_byte_offset('b');
491 EXPECT(!index4.has_value());
492 }
493 {
494 auto string = MUST("foo"_string);
495
496 auto index1 = string.find_byte_offset("fo"sv);
497 EXPECT_EQ(index1, 0u);
498
499 auto index2 = string.find_byte_offset("oo"sv);
500 EXPECT_EQ(index2, 1u);
501
502 auto index3 = string.find_byte_offset("o"sv, *index2 + 1);
503 EXPECT_EQ(index3, 2u);
504
505 auto index4 = string.find_byte_offset("fooo"sv);
506 EXPECT(!index4.has_value());
507 }
508 {
509 auto string = MUST("ωΣωΣω"_string);
510
511 auto index1 = string.find_byte_offset(0x03C9U);
512 EXPECT_EQ(index1, 0u);
513
514 auto index2 = string.find_byte_offset(0x03A3u);
515 EXPECT_EQ(index2, 2u);
516
517 auto index3 = string.find_byte_offset(0x03C9U, 2);
518 EXPECT_EQ(index3, 4u);
519
520 auto index4 = string.find_byte_offset(0x03A3u, 4);
521 EXPECT_EQ(index4, 6u);
522
523 auto index5 = string.find_byte_offset(0x03C9U, 6);
524 EXPECT_EQ(index5, 8u);
525 }
526 {
527 auto string = MUST("ωΣωΣω"_string);
528
529 auto index1 = string.find_byte_offset("ω"sv);
530 EXPECT_EQ(index1, 0u);
531
532 auto index2 = string.find_byte_offset("Σ"sv);
533 EXPECT_EQ(index2, 2u);
534
535 auto index3 = string.find_byte_offset("ω"sv, 2);
536 EXPECT_EQ(index3, 4u);
537
538 auto index4 = string.find_byte_offset("Σ"sv, 4);
539 EXPECT_EQ(index4, 6u);
540
541 auto index5 = string.find_byte_offset("ω"sv, 6);
542 EXPECT_EQ(index5, 8u);
543 }
544}
545
546TEST_CASE(repeated)
547{
548 {
549 auto string1 = MUST(String::repeated('a', 0));
550 EXPECT(string1.is_short_string());
551 EXPECT(string1.is_empty());
552
553 auto string2 = MUST(String::repeated(0x03C9U, 0));
554 EXPECT(string2.is_short_string());
555 EXPECT(string2.is_empty());
556
557 auto string3 = MUST(String::repeated(0x10300, 0));
558 EXPECT(string3.is_short_string());
559 EXPECT(string3.is_empty());
560 }
561 {
562 auto string1 = MUST(String::repeated('a', 1));
563 EXPECT(string1.is_short_string());
564 EXPECT_EQ(string1.bytes_as_string_view().length(), 1u);
565 EXPECT_EQ(string1, "a"sv);
566
567 auto string2 = MUST(String::repeated(0x03C9U, 1));
568 EXPECT(string2.is_short_string());
569 EXPECT_EQ(string2.bytes_as_string_view().length(), 2u);
570 EXPECT_EQ(string2, "ω"sv);
571
572 auto string3 = MUST(String::repeated(0x10300, 1));
573#ifdef AK_ARCH_64_BIT
574 EXPECT(string3.is_short_string());
575#else
576 EXPECT(!string3.is_short_string());
577#endif
578 EXPECT_EQ(string3.bytes_as_string_view().length(), 4u);
579 EXPECT_EQ(string3, "𐌀"sv);
580 }
581 {
582 auto string1 = MUST(String::repeated('a', 3));
583 EXPECT(string1.is_short_string());
584 EXPECT_EQ(string1.bytes_as_string_view().length(), 3u);
585 EXPECT_EQ(string1, "aaa"sv);
586
587 auto string2 = MUST(String::repeated(0x03C9U, 3));
588#ifdef AK_ARCH_64_BIT
589 EXPECT(string2.is_short_string());
590#else
591 EXPECT(!string2.is_short_string());
592#endif
593 EXPECT_EQ(string2.bytes_as_string_view().length(), 6u);
594 EXPECT_EQ(string2, "ωωω"sv);
595
596 auto string3 = MUST(String::repeated(0x10300, 3));
597 EXPECT(!string3.is_short_string());
598 EXPECT_EQ(string3.bytes_as_string_view().length(), 12u);
599 EXPECT_EQ(string3, "𐌀𐌀𐌀"sv);
600 }
601 {
602 auto string1 = MUST(String::repeated('a', 10));
603 EXPECT(!string1.is_short_string());
604 EXPECT_EQ(string1.bytes_as_string_view().length(), 10u);
605 EXPECT_EQ(string1, "aaaaaaaaaa"sv);
606
607 auto string2 = MUST(String::repeated(0x03C9U, 10));
608 EXPECT(!string2.is_short_string());
609 EXPECT_EQ(string2.bytes_as_string_view().length(), 20u);
610 EXPECT_EQ(string2, "ωωωωωωωωωω"sv);
611
612 auto string3 = MUST(String::repeated(0x10300, 10));
613 EXPECT(!string3.is_short_string());
614 EXPECT_EQ(string3.bytes_as_string_view().length(), 40u);
615 EXPECT_EQ(string3, "𐌀𐌀𐌀𐌀𐌀𐌀𐌀𐌀𐌀𐌀"sv);
616 }
617
618 EXPECT_CRASH("Creating a string from an invalid code point", [] {
619 (void)String::repeated(0xffffffff, 1);
620 return Test::Crash::Failure::DidNotCrash;
621 });
622}
623
624TEST_CASE(join)
625{
626 auto string1 = MUST(String::join(',', Vector<i32> {}));
627 EXPECT(string1.is_empty());
628
629 auto string2 = MUST(String::join(',', Array { 1 }));
630 EXPECT_EQ(string2, "1"sv);
631
632 auto string3 = MUST(String::join(':', Array { 1 }, "[{}]"sv));
633 EXPECT_EQ(string3, "[1]"sv);
634
635 auto string4 = MUST(String::join(',', Array { 1, 2, 3 }));
636 EXPECT_EQ(string4, "1,2,3"sv);
637
638 auto string5 = MUST(String::join(',', Array { 1, 2, 3 }, "[{}]"sv));
639 EXPECT_EQ(string5, "[1],[2],[3]"sv);
640
641 auto string6 = MUST(String::join("!!!"_short_string, Array { "foo"sv, "bar"sv, "baz"sv }));
642 EXPECT_EQ(string6, "foo!!!bar!!!baz"sv);
643
644 auto string7 = MUST(String::join(" - "sv, Array { 1, 16, 256, 4096 }, "[{:#04x}]"sv));
645 EXPECT_EQ(string7, "[0x0001] - [0x0010] - [0x0100] - [0x1000]"sv);
646}
647
648TEST_CASE(trim)
649{
650 {
651 String string {};
652
653 auto result = MUST(string.trim(" "sv, TrimMode::Both));
654 EXPECT(result.is_empty());
655
656 result = MUST(string.trim(" "sv, TrimMode::Left));
657 EXPECT(result.is_empty());
658
659 result = MUST(string.trim(" "sv, TrimMode::Right));
660 EXPECT(result.is_empty());
661 }
662 {
663 auto string = MUST("word"_string);
664
665 auto result = MUST(string.trim(" "sv, TrimMode::Both));
666 EXPECT_EQ(result, "word"sv);
667
668 result = MUST(string.trim(" "sv, TrimMode::Left));
669 EXPECT_EQ(result, "word"sv);
670
671 result = MUST(string.trim(" "sv, TrimMode::Right));
672 EXPECT_EQ(result, "word"sv);
673 }
674 {
675 auto string = MUST(" word"_string);
676
677 auto result = MUST(string.trim(" "sv, TrimMode::Both));
678 EXPECT_EQ(result, "word"sv);
679
680 result = MUST(string.trim(" "sv, TrimMode::Left));
681 EXPECT_EQ(result, "word"sv);
682
683 result = MUST(string.trim(" "sv, TrimMode::Right));
684 EXPECT_EQ(result, " word"sv);
685 }
686 {
687 auto string = MUST("word "_string);
688
689 auto result = MUST(string.trim(" "sv, TrimMode::Both));
690 EXPECT_EQ(result, "word"sv);
691
692 result = MUST(string.trim(" "sv, TrimMode::Left));
693 EXPECT_EQ(result, "word "sv);
694
695 result = MUST(string.trim(" "sv, TrimMode::Right));
696 EXPECT_EQ(result, "word"sv);
697 }
698 {
699 auto string = MUST(" word "_string);
700
701 auto result = MUST(string.trim(" "sv, TrimMode::Both));
702 EXPECT_EQ(result, "word"sv);
703
704 result = MUST(string.trim(" "sv, TrimMode::Left));
705 EXPECT_EQ(result, "word "sv);
706
707 result = MUST(string.trim(" "sv, TrimMode::Right));
708 EXPECT_EQ(result, " word"sv);
709 }
710 {
711 auto string = MUST(" word "_string);
712
713 auto result = MUST(string.trim("\t"sv, TrimMode::Both));
714 EXPECT_EQ(result, " word "sv);
715
716 result = MUST(string.trim("\t"sv, TrimMode::Left));
717 EXPECT_EQ(result, " word "sv);
718
719 result = MUST(string.trim("\t"sv, TrimMode::Right));
720 EXPECT_EQ(result, " word "sv);
721 }
722 {
723 auto string = MUST("ωΣωΣω"_string);
724
725 auto result = MUST(string.trim("ω"sv, TrimMode::Both));
726 EXPECT_EQ(result, "ΣωΣ"sv);
727
728 result = MUST(string.trim("ω"sv, TrimMode::Left));
729 EXPECT_EQ(result, "ΣωΣω"sv);
730
731 result = MUST(string.trim("ω"sv, TrimMode::Right));
732 EXPECT_EQ(result, "ωΣωΣ"sv);
733 }
734 {
735 auto string = MUST("ωΣωΣω"_string);
736
737 auto result = MUST(string.trim("ωΣ"sv, TrimMode::Both));
738 EXPECT(result.is_empty());
739
740 result = MUST(string.trim("ωΣ"sv, TrimMode::Left));
741 EXPECT(result.is_empty());
742
743 result = MUST(string.trim("ωΣ"sv, TrimMode::Right));
744 EXPECT(result.is_empty());
745 }
746 {
747 auto string = MUST("ωΣωΣω"_string);
748
749 auto result = MUST(string.trim("Σω"sv, TrimMode::Both));
750 EXPECT(result.is_empty());
751
752 result = MUST(string.trim("Σω"sv, TrimMode::Left));
753 EXPECT(result.is_empty());
754
755 result = MUST(string.trim("Σω"sv, TrimMode::Right));
756 EXPECT(result.is_empty());
757 }
758}
759
760TEST_CASE(contains)
761{
762 EXPECT(!String {}.contains({}));
763 EXPECT(!String {}.contains(" "sv));
764 EXPECT(!String {}.contains(0));
765
766 EXPECT("a"_short_string.contains("a"sv));
767 EXPECT(!"a"_short_string.contains({}));
768 EXPECT(!"a"_short_string.contains("b"sv));
769 EXPECT(!"a"_short_string.contains("ab"sv));
770
771 EXPECT("a"_short_string.contains(0x0061));
772 EXPECT(!"a"_short_string.contains(0x0062));
773
774 EXPECT("abc"_short_string.contains("a"sv));
775 EXPECT("abc"_short_string.contains("b"sv));
776 EXPECT("abc"_short_string.contains("c"sv));
777 EXPECT("abc"_short_string.contains("ab"sv));
778 EXPECT("abc"_short_string.contains("bc"sv));
779 EXPECT("abc"_short_string.contains("abc"sv));
780 EXPECT(!"abc"_short_string.contains({}));
781 EXPECT(!"abc"_short_string.contains("ac"sv));
782 EXPECT(!"abc"_short_string.contains("abcd"sv));
783
784 EXPECT("abc"_short_string.contains(0x0061));
785 EXPECT("abc"_short_string.contains(0x0062));
786 EXPECT("abc"_short_string.contains(0x0063));
787 EXPECT(!"abc"_short_string.contains(0x0064));
788
789 auto emoji = MUST("😀"_string);
790 EXPECT(emoji.contains("\xF0"sv));
791 EXPECT(emoji.contains("\x9F"sv));
792 EXPECT(emoji.contains("\x98"sv));
793 EXPECT(emoji.contains("\x80"sv));
794 EXPECT(emoji.contains("\xF0\x9F"sv));
795 EXPECT(emoji.contains("\xF0\x9F\x98"sv));
796 EXPECT(emoji.contains("\xF0\x9F\x98\x80"sv));
797 EXPECT(emoji.contains("\x9F\x98\x80"sv));
798 EXPECT(emoji.contains("\x98\x80"sv));
799 EXPECT(!emoji.contains("a"sv));
800 EXPECT(!emoji.contains("🙃"sv));
801
802 EXPECT(emoji.contains(0x1F600));
803 EXPECT(!emoji.contains(0x1F643));
804}
805
806TEST_CASE(starts_with)
807{
808 EXPECT(String {}.starts_with_bytes({}));
809 EXPECT(!String {}.starts_with_bytes(" "sv));
810 EXPECT(!String {}.starts_with(0));
811
812 EXPECT("a"_short_string.starts_with_bytes({}));
813 EXPECT("a"_short_string.starts_with_bytes("a"sv));
814 EXPECT(!"a"_short_string.starts_with_bytes("b"sv));
815 EXPECT(!"a"_short_string.starts_with_bytes("ab"sv));
816
817 EXPECT("a"_short_string.starts_with(0x0061));
818 EXPECT(!"a"_short_string.starts_with(0x0062));
819
820 EXPECT("abc"_short_string.starts_with_bytes({}));
821 EXPECT("abc"_short_string.starts_with_bytes("a"sv));
822 EXPECT("abc"_short_string.starts_with_bytes("ab"sv));
823 EXPECT("abc"_short_string.starts_with_bytes("abc"sv));
824 EXPECT(!"abc"_short_string.starts_with_bytes("b"sv));
825 EXPECT(!"abc"_short_string.starts_with_bytes("bc"sv));
826
827 EXPECT("abc"_short_string.starts_with(0x0061));
828 EXPECT(!"abc"_short_string.starts_with(0x0062));
829 EXPECT(!"abc"_short_string.starts_with(0x0063));
830
831 auto emoji = MUST("😀🙃"_string);
832 EXPECT(emoji.starts_with_bytes("\xF0"sv));
833 EXPECT(emoji.starts_with_bytes("\xF0\x9F"sv));
834 EXPECT(emoji.starts_with_bytes("\xF0\x9F\x98"sv));
835 EXPECT(emoji.starts_with_bytes("\xF0\x9F\x98\x80"sv));
836 EXPECT(emoji.starts_with_bytes("\xF0\x9F\x98\x80\xF0"sv));
837 EXPECT(emoji.starts_with_bytes("\xF0\x9F\x98\x80\xF0\x9F"sv));
838 EXPECT(emoji.starts_with_bytes("\xF0\x9F\x98\x80\xF0\x9F\x99"sv));
839 EXPECT(emoji.starts_with_bytes("\xF0\x9F\x98\x80\xF0\x9F\x99\x83"sv));
840 EXPECT(!emoji.starts_with_bytes("a"sv));
841 EXPECT(!emoji.starts_with_bytes("🙃"sv));
842
843 EXPECT(emoji.starts_with(0x1F600));
844 EXPECT(!emoji.starts_with(0x1F643));
845}
846
847TEST_CASE(ends_with)
848{
849 EXPECT(String {}.ends_with_bytes({}));
850 EXPECT(!String {}.ends_with_bytes(" "sv));
851 EXPECT(!String {}.ends_with(0));
852
853 EXPECT("a"_short_string.ends_with_bytes({}));
854 EXPECT("a"_short_string.ends_with_bytes("a"sv));
855 EXPECT(!"a"_short_string.ends_with_bytes("b"sv));
856 EXPECT(!"a"_short_string.ends_with_bytes("ba"sv));
857
858 EXPECT("a"_short_string.ends_with(0x0061));
859 EXPECT(!"a"_short_string.ends_with(0x0062));
860
861 EXPECT("abc"_short_string.ends_with_bytes({}));
862 EXPECT("abc"_short_string.ends_with_bytes("c"sv));
863 EXPECT("abc"_short_string.ends_with_bytes("bc"sv));
864 EXPECT("abc"_short_string.ends_with_bytes("abc"sv));
865 EXPECT(!"abc"_short_string.ends_with_bytes("b"sv));
866 EXPECT(!"abc"_short_string.ends_with_bytes("ab"sv));
867
868 EXPECT("abc"_short_string.ends_with(0x0063));
869 EXPECT(!"abc"_short_string.ends_with(0x0062));
870 EXPECT(!"abc"_short_string.ends_with(0x0061));
871
872 auto emoji = MUST("😀🙃"_string);
873 EXPECT(emoji.ends_with_bytes("\x83"sv));
874 EXPECT(emoji.ends_with_bytes("\x99\x83"sv));
875 EXPECT(emoji.ends_with_bytes("\x9F\x99\x83"sv));
876 EXPECT(emoji.ends_with_bytes("\xF0\x9F\x99\x83"sv));
877 EXPECT(emoji.ends_with_bytes("\x80\xF0\x9F\x99\x83"sv));
878 EXPECT(emoji.ends_with_bytes("\x98\x80\xF0\x9F\x99\x83"sv));
879 EXPECT(emoji.ends_with_bytes("\x9F\x98\x80\xF0\x9F\x99\x83"sv));
880 EXPECT(emoji.ends_with_bytes("\xF0\x9F\x98\x80\xF0\x9F\x99\x83"sv));
881 EXPECT(!emoji.ends_with_bytes("a"sv));
882 EXPECT(!emoji.ends_with_bytes("😀"sv));
883
884 EXPECT(emoji.ends_with(0x1F643));
885 EXPECT(!emoji.ends_with(0x1F600));
886}