Serenity Operating System
1/*
2 * Copyright (c) 2020, Fei Wu <f.eiwu@yahoo.com>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibTest/TestCase.h>
8
9#include <AK/ByteBuffer.h>
10#include <AK/Concepts.h>
11#include <AK/FlyString.h>
12#include <AK/String.h>
13#include <AK/StringUtils.h>
14#include <AK/Vector.h>
15
16TEST_CASE(hash_compatible)
17{
18 static_assert(AK::Concepts::HashCompatible<String, StringView>);
19 static_assert(AK::Concepts::HashCompatible<String, FlyString>);
20 static_assert(AK::Concepts::HashCompatible<StringView, String>);
21 static_assert(AK::Concepts::HashCompatible<StringView, FlyString>);
22 static_assert(AK::Concepts::HashCompatible<FlyString, String>);
23 static_assert(AK::Concepts::HashCompatible<FlyString, StringView>);
24
25 static_assert(AK::Concepts::HashCompatible<DeprecatedString, StringView>);
26 static_assert(AK::Concepts::HashCompatible<DeprecatedString, DeprecatedFlyString>);
27 static_assert(AK::Concepts::HashCompatible<StringView, DeprecatedString>);
28 static_assert(AK::Concepts::HashCompatible<StringView, DeprecatedFlyString>);
29 static_assert(AK::Concepts::HashCompatible<DeprecatedFlyString, DeprecatedString>);
30 static_assert(AK::Concepts::HashCompatible<DeprecatedFlyString, StringView>);
31
32 static_assert(AK::Concepts::HashCompatible<StringView, ByteBuffer>);
33 static_assert(AK::Concepts::HashCompatible<ByteBuffer, StringView>);
34}
35
36TEST_CASE(matches_null)
37{
38 EXPECT(AK::StringUtils::matches(StringView(), StringView()));
39
40 EXPECT(!AK::StringUtils::matches(StringView(), ""sv));
41 EXPECT(!AK::StringUtils::matches(StringView(), "*"sv));
42 EXPECT(!AK::StringUtils::matches(StringView(), "?"sv));
43 EXPECT(!AK::StringUtils::matches(StringView(), "a"sv));
44
45 EXPECT(!AK::StringUtils::matches(""sv, StringView()));
46 EXPECT(!AK::StringUtils::matches("a"sv, StringView()));
47}
48
49TEST_CASE(matches_empty)
50{
51 EXPECT(AK::StringUtils::matches(""sv, ""sv));
52
53 EXPECT(AK::StringUtils::matches(""sv, "*"sv));
54 EXPECT(!AK::StringUtils::matches(""sv, "?"sv));
55 EXPECT(!AK::StringUtils::matches(""sv, "a"sv));
56
57 EXPECT(!AK::StringUtils::matches("a"sv, ""sv));
58}
59
60TEST_CASE(matches_case_sensitive)
61{
62 EXPECT(AK::StringUtils::matches("a"sv, "a"sv, CaseSensitivity::CaseSensitive));
63 EXPECT(!AK::StringUtils::matches("a"sv, "A"sv, CaseSensitivity::CaseSensitive));
64 EXPECT(!AK::StringUtils::matches("A"sv, "a"sv, CaseSensitivity::CaseSensitive));
65}
66
67TEST_CASE(matches_case_insensitive)
68{
69 EXPECT(!AK::StringUtils::matches("aa"sv, "a"sv));
70 EXPECT(AK::StringUtils::matches("aa"sv, "*"sv));
71 EXPECT(!AK::StringUtils::matches("cb"sv, "?a"sv));
72 EXPECT(AK::StringUtils::matches("adceb"sv, "a*b"sv));
73 EXPECT(!AK::StringUtils::matches("acdcb"sv, "a*c?b"sv));
74}
75
76TEST_CASE(matches_with_positions)
77{
78 Vector<AK::MaskSpan> spans;
79 EXPECT(AK::StringUtils::matches("abbb"sv, "a*"sv, CaseSensitivity::CaseSensitive, &spans));
80 EXPECT(spans == Vector<AK::MaskSpan>({ { 1, 3 } }));
81
82 spans.clear();
83 EXPECT(AK::StringUtils::matches("abbb"sv, "?*"sv, CaseSensitivity::CaseSensitive, &spans));
84 EXPECT_EQ(spans, Vector<AK::MaskSpan>({ { 0, 1 }, { 1, 3 } }));
85
86 spans.clear();
87 EXPECT(AK::StringUtils::matches("acdcxb"sv, "a*c?b"sv, CaseSensitivity::CaseSensitive, &spans));
88 EXPECT_EQ(spans, Vector<AK::MaskSpan>({ { 1, 2 }, { 4, 1 } }));
89
90 spans.clear();
91 EXPECT(AK::StringUtils::matches("aaaa"sv, "A*"sv, CaseSensitivity::CaseInsensitive, &spans));
92 EXPECT_EQ(spans, Vector<AK::MaskSpan>({ { 1, 3 } }));
93}
94
95// #4607
96TEST_CASE(matches_trailing)
97{
98 EXPECT(AK::StringUtils::matches("ab"sv, "ab*"sv));
99 EXPECT(AK::StringUtils::matches("ab"sv, "ab****"sv));
100 EXPECT(AK::StringUtils::matches("ab"sv, "*ab****"sv));
101}
102
103TEST_CASE(match_backslash_escape)
104{
105 EXPECT(AK::StringUtils::matches("ab*"sv, "ab\\*"sv));
106 EXPECT(!AK::StringUtils::matches("abc"sv, "ab\\*"sv));
107 EXPECT(!AK::StringUtils::matches("abcd"sv, "ab\\*"sv));
108 EXPECT(AK::StringUtils::matches("ab?"sv, "ab\\?"sv));
109 EXPECT(!AK::StringUtils::matches("abc"sv, "ab\\?"sv));
110}
111
112TEST_CASE(match_trailing_backslash)
113{
114 EXPECT(AK::StringUtils::matches("x\\"sv, "x\\"sv));
115 EXPECT(AK::StringUtils::matches("x\\"sv, "x\\\\"sv));
116}
117
118TEST_CASE(convert_to_int)
119{
120 auto value = AK::StringUtils::convert_to_int(StringView());
121 EXPECT(!value.has_value());
122
123 value = AK::StringUtils::convert_to_int(""sv);
124 EXPECT(!value.has_value());
125
126 value = AK::StringUtils::convert_to_int("a"sv);
127 EXPECT(!value.has_value());
128
129 value = AK::StringUtils::convert_to_int("+"sv);
130 EXPECT(!value.has_value());
131
132 value = AK::StringUtils::convert_to_int("-"sv);
133 EXPECT(!value.has_value());
134
135 auto actual = AK::StringUtils::convert_to_int("0"sv);
136 EXPECT_EQ(actual.has_value(), true);
137 EXPECT_EQ(actual.value(), 0);
138
139 actual = AK::StringUtils::convert_to_int("1"sv);
140 EXPECT_EQ(actual.has_value(), true);
141 EXPECT_EQ(actual.value(), 1);
142
143 actual = AK::StringUtils::convert_to_int("+1"sv);
144 EXPECT_EQ(actual.has_value(), true);
145 EXPECT_EQ(actual.value(), 1);
146
147 actual = AK::StringUtils::convert_to_int("-1"sv);
148 EXPECT_EQ(actual.has_value(), true);
149 EXPECT_EQ(actual.value(), -1);
150
151 actual = AK::StringUtils::convert_to_int("01"sv);
152 EXPECT_EQ(actual.has_value(), true);
153 EXPECT_EQ(actual.value(), 1);
154
155 actual = AK::StringUtils::convert_to_int("12345"sv);
156 EXPECT_EQ(actual.has_value(), true);
157 EXPECT_EQ(actual.value(), 12345);
158
159 actual = AK::StringUtils::convert_to_int("-12345"sv);
160 EXPECT_EQ(actual.has_value(), true);
161 EXPECT_EQ(actual.value(), -12345);
162
163 actual = AK::StringUtils::convert_to_int(" \t-12345 \n\n"sv);
164 EXPECT_EQ(actual.has_value(), true);
165 EXPECT_EQ(actual.value(), -12345);
166
167 auto actual_i8 = AK::StringUtils::convert_to_int<i8>("-1"sv);
168 EXPECT(actual_i8.has_value());
169 EXPECT_EQ(actual_i8.value(), -1);
170 EXPECT_EQ(sizeof(actual_i8.value()), (size_t)1);
171 actual_i8 = AK::StringUtils::convert_to_int<i8>("128"sv);
172 EXPECT(!actual_i8.has_value());
173
174 auto actual_i16 = AK::StringUtils::convert_to_int<i16>("-1"sv);
175 EXPECT(actual_i16.has_value());
176 EXPECT_EQ(actual_i16.value(), -1);
177 EXPECT_EQ(sizeof(actual_i16.value()), (size_t)2);
178 actual_i16 = AK::StringUtils::convert_to_int<i16>("32768"sv);
179 EXPECT(!actual_i16.has_value());
180
181 auto actual_i32 = AK::StringUtils::convert_to_int<i32>("-1"sv);
182 EXPECT(actual_i32.has_value());
183 EXPECT_EQ(actual_i32.value(), -1);
184 EXPECT_EQ(sizeof(actual_i32.value()), (size_t)4);
185 actual_i32 = AK::StringUtils::convert_to_int<i32>("2147483648"sv);
186 EXPECT(!actual_i32.has_value());
187
188 auto actual_i64 = AK::StringUtils::convert_to_int<i64>("-1"sv);
189 EXPECT(actual_i64.has_value());
190 EXPECT_EQ(actual_i64.value(), -1);
191 EXPECT_EQ(sizeof(actual_i64.value()), (size_t)8);
192 actual_i64 = AK::StringUtils::convert_to_int<i64>("9223372036854775808"sv);
193 EXPECT(!actual_i64.has_value());
194}
195
196TEST_CASE(convert_to_uint)
197{
198 auto value = AK::StringUtils::convert_to_uint(StringView());
199 EXPECT(!value.has_value());
200
201 value = AK::StringUtils::convert_to_uint(""sv);
202 EXPECT(!value.has_value());
203
204 value = AK::StringUtils::convert_to_uint("a"sv);
205 EXPECT(!value.has_value());
206
207 value = AK::StringUtils::convert_to_uint("+"sv);
208 EXPECT(!value.has_value());
209
210 value = AK::StringUtils::convert_to_uint("-"sv);
211 EXPECT(!value.has_value());
212
213 value = AK::StringUtils::convert_to_uint("+1"sv);
214 EXPECT(!value.has_value());
215
216 value = AK::StringUtils::convert_to_uint("-1"sv);
217 EXPECT(!value.has_value());
218
219 auto actual = AK::StringUtils::convert_to_uint("0"sv);
220 EXPECT_EQ(actual.has_value(), true);
221 EXPECT_EQ(actual.value(), 0u);
222
223 actual = AK::StringUtils::convert_to_uint("1"sv);
224 EXPECT_EQ(actual.has_value(), true);
225 EXPECT_EQ(actual.value(), 1u);
226
227 actual = AK::StringUtils::convert_to_uint("01"sv);
228 EXPECT_EQ(actual.has_value(), true);
229 EXPECT_EQ(actual.value(), 1u);
230
231 actual = AK::StringUtils::convert_to_uint("12345"sv);
232 EXPECT_EQ(actual.has_value(), true);
233 EXPECT_EQ(actual.value(), 12345u);
234
235 actual = AK::StringUtils::convert_to_uint(" \t12345 \n\n"sv);
236 EXPECT_EQ(actual.has_value(), true);
237 EXPECT_EQ(actual.value(), 12345u);
238
239 auto actual_u8 = AK::StringUtils::convert_to_uint<u8>("255"sv);
240 EXPECT(actual_u8.has_value());
241 EXPECT_EQ(actual_u8.value(), 255u);
242 EXPECT_EQ(sizeof(actual_u8.value()), (size_t)1);
243 actual_u8 = AK::StringUtils::convert_to_uint<u8>("256"sv);
244 EXPECT(!actual_u8.has_value());
245
246 auto actual_u16 = AK::StringUtils::convert_to_uint<u16>("65535"sv);
247 EXPECT(actual_u16.has_value());
248 EXPECT_EQ(actual_u16.value(), 65535u);
249 EXPECT_EQ(sizeof(actual_u16.value()), (size_t)2);
250 actual_u16 = AK::StringUtils::convert_to_uint<u16>("65536"sv);
251 EXPECT(!actual_u16.has_value());
252
253 auto actual_u32 = AK::StringUtils::convert_to_uint<u32>("4294967295"sv);
254 EXPECT(actual_u32.has_value());
255 EXPECT_EQ(actual_u32.value(), 4294967295ul);
256 EXPECT_EQ(sizeof(actual_u32.value()), (size_t)4);
257 actual_u32 = AK::StringUtils::convert_to_uint<u32>("4294967296"sv);
258 EXPECT(!actual_u32.has_value());
259
260 auto actual_u64 = AK::StringUtils::convert_to_uint<u64>("18446744073709551615"sv);
261 EXPECT(actual_u64.has_value());
262 EXPECT_EQ(actual_u64.value(), 18446744073709551615ull);
263 EXPECT_EQ(sizeof(actual_u64.value()), (size_t)8);
264 actual_u64 = AK::StringUtils::convert_to_uint<u64>("18446744073709551616"sv);
265 EXPECT(!actual_u64.has_value());
266}
267
268TEST_CASE(convert_to_uint_from_octal)
269{
270 auto value = AK::StringUtils::convert_to_uint_from_octal<u16>(StringView());
271 EXPECT(!value.has_value());
272
273 value = AK::StringUtils::convert_to_uint_from_octal<u16>(""sv);
274 EXPECT(!value.has_value());
275
276 value = AK::StringUtils::convert_to_uint_from_octal<u16>("a"sv);
277 EXPECT(!value.has_value());
278
279 value = AK::StringUtils::convert_to_uint_from_octal<u16>("+"sv);
280 EXPECT(!value.has_value());
281
282 value = AK::StringUtils::convert_to_uint_from_octal<u16>("-"sv);
283 EXPECT(!value.has_value());
284
285 value = AK::StringUtils::convert_to_uint_from_octal<u16>("+1"sv);
286 EXPECT(!value.has_value());
287
288 value = AK::StringUtils::convert_to_uint_from_octal<u16>("-1"sv);
289 EXPECT(!value.has_value());
290
291 value = AK::StringUtils::convert_to_uint_from_octal<u16>("8"sv);
292 EXPECT(!value.has_value());
293
294 auto actual = AK::StringUtils::convert_to_uint_from_octal<u16>("77777777"sv);
295 EXPECT(!actual.has_value());
296
297 actual = AK::StringUtils::convert_to_uint_from_octal<u16>("0"sv);
298 EXPECT_EQ(actual.has_value(), true);
299 EXPECT_EQ(actual.value(), 0u);
300
301 actual = AK::StringUtils::convert_to_uint_from_octal<u16>("1"sv);
302 EXPECT_EQ(actual.has_value(), true);
303 EXPECT_EQ(actual.value(), 1u);
304
305 actual = AK::StringUtils::convert_to_uint_from_octal<u16>("0755"sv);
306 EXPECT_EQ(actual.has_value(), true);
307 EXPECT_EQ(actual.value(), 0755u);
308
309 actual = AK::StringUtils::convert_to_uint_from_octal<u16>("755"sv);
310 EXPECT_EQ(actual.has_value(), true);
311 EXPECT_EQ(actual.value(), 0755u);
312
313 actual = AK::StringUtils::convert_to_uint_from_octal<u16>(" \t644 \n\n"sv);
314 EXPECT_EQ(actual.has_value(), true);
315 EXPECT_EQ(actual.value(), 0644u);
316
317 actual = AK::StringUtils::convert_to_uint_from_octal<u16>("177777"sv);
318 EXPECT_EQ(actual.has_value(), true);
319 EXPECT_EQ(actual.value(), 0177777u);
320}
321
322TEST_CASE(ends_with)
323{
324 DeprecatedString test_string = "ABCDEF";
325 EXPECT(AK::StringUtils::ends_with(test_string, "DEF"sv, CaseSensitivity::CaseSensitive));
326 EXPECT(AK::StringUtils::ends_with(test_string, "ABCDEF"sv, CaseSensitivity::CaseSensitive));
327 EXPECT(!AK::StringUtils::ends_with(test_string, "ABCDE"sv, CaseSensitivity::CaseSensitive));
328 EXPECT(!AK::StringUtils::ends_with(test_string, "ABCDEFG"sv, CaseSensitivity::CaseSensitive));
329 EXPECT(AK::StringUtils::ends_with(test_string, "def"sv, CaseSensitivity::CaseInsensitive));
330 EXPECT(!AK::StringUtils::ends_with(test_string, "def"sv, CaseSensitivity::CaseSensitive));
331}
332
333TEST_CASE(starts_with)
334{
335 DeprecatedString test_string = "ABCDEF";
336 EXPECT(AK::StringUtils::starts_with(test_string, "ABC"sv, CaseSensitivity::CaseSensitive));
337 EXPECT(AK::StringUtils::starts_with(test_string, "ABCDEF"sv, CaseSensitivity::CaseSensitive));
338 EXPECT(!AK::StringUtils::starts_with(test_string, "BCDEF"sv, CaseSensitivity::CaseSensitive));
339 EXPECT(!AK::StringUtils::starts_with(test_string, "ABCDEFG"sv, CaseSensitivity::CaseSensitive));
340 EXPECT(AK::StringUtils::starts_with(test_string, "abc"sv, CaseSensitivity::CaseInsensitive));
341 EXPECT(!AK::StringUtils::starts_with(test_string, "abc"sv, CaseSensitivity::CaseSensitive));
342}
343
344TEST_CASE(contains)
345{
346 DeprecatedString test_string = "ABCDEFABCXYZ";
347 EXPECT(AK::StringUtils::contains(test_string, "ABC"sv, CaseSensitivity::CaseSensitive));
348 EXPECT(AK::StringUtils::contains(test_string, "ABC"sv, CaseSensitivity::CaseInsensitive));
349 EXPECT(AK::StringUtils::contains(test_string, "AbC"sv, CaseSensitivity::CaseInsensitive));
350 EXPECT(AK::StringUtils::contains(test_string, "BCX"sv, CaseSensitivity::CaseSensitive));
351 EXPECT(AK::StringUtils::contains(test_string, "BCX"sv, CaseSensitivity::CaseInsensitive));
352 EXPECT(AK::StringUtils::contains(test_string, "BcX"sv, CaseSensitivity::CaseInsensitive));
353 EXPECT(!AK::StringUtils::contains(test_string, "xyz"sv, CaseSensitivity::CaseSensitive));
354 EXPECT(AK::StringUtils::contains(test_string, "xyz"sv, CaseSensitivity::CaseInsensitive));
355 EXPECT(!AK::StringUtils::contains(test_string, "EFG"sv, CaseSensitivity::CaseSensitive));
356 EXPECT(!AK::StringUtils::contains(test_string, "EfG"sv, CaseSensitivity::CaseInsensitive));
357 EXPECT(AK::StringUtils::contains(test_string, ""sv, CaseSensitivity::CaseSensitive));
358 EXPECT(AK::StringUtils::contains(test_string, ""sv, CaseSensitivity::CaseInsensitive));
359 EXPECT(!AK::StringUtils::contains(""sv, test_string, CaseSensitivity::CaseSensitive));
360 EXPECT(!AK::StringUtils::contains(""sv, test_string, CaseSensitivity::CaseInsensitive));
361 EXPECT(!AK::StringUtils::contains(test_string, "L"sv, CaseSensitivity::CaseSensitive));
362 EXPECT(!AK::StringUtils::contains(test_string, "L"sv, CaseSensitivity::CaseInsensitive));
363
364 DeprecatedString command_palette_bug_string = "Go Go Back";
365 EXPECT(AK::StringUtils::contains(command_palette_bug_string, "Go Back"sv, AK::CaseSensitivity::CaseSensitive));
366 EXPECT(AK::StringUtils::contains(command_palette_bug_string, "gO bAcK"sv, AK::CaseSensitivity::CaseInsensitive));
367}
368
369TEST_CASE(is_whitespace)
370{
371 EXPECT(AK::StringUtils::is_whitespace(""sv));
372 EXPECT(AK::StringUtils::is_whitespace(" "sv));
373 EXPECT(AK::StringUtils::is_whitespace(" \t"sv));
374 EXPECT(AK::StringUtils::is_whitespace(" \t\n"sv));
375 EXPECT(AK::StringUtils::is_whitespace(" \t\n\r\v"sv));
376 EXPECT(!AK::StringUtils::is_whitespace(" a "sv));
377 EXPECT(!AK::StringUtils::is_whitespace("a\t"sv));
378}
379
380TEST_CASE(trim)
381{
382 EXPECT_EQ(AK::StringUtils::trim("aaa.a."sv, "."sv, TrimMode::Right), "aaa.a"sv);
383 EXPECT_EQ(AK::StringUtils::trim("...aaa"sv, "."sv, TrimMode::Left), "aaa"sv);
384 EXPECT_EQ(AK::StringUtils::trim("...aaa.a..."sv, "."sv, TrimMode::Both), "aaa.a"sv);
385 EXPECT_EQ(AK::StringUtils::trim("."sv, "."sv, TrimMode::Right), ""sv);
386 EXPECT_EQ(AK::StringUtils::trim("."sv, "."sv, TrimMode::Left), ""sv);
387 EXPECT_EQ(AK::StringUtils::trim("."sv, "."sv, TrimMode::Both), ""sv);
388 EXPECT_EQ(AK::StringUtils::trim("..."sv, "."sv, TrimMode::Both), ""sv);
389}
390
391TEST_CASE(find)
392{
393 DeprecatedString test_string = "1234567";
394 EXPECT_EQ(AK::StringUtils::find(test_string, "1"sv).value_or(1), 0u);
395 EXPECT_EQ(AK::StringUtils::find(test_string, "2"sv).value_or(2), 1u);
396 EXPECT_EQ(AK::StringUtils::find(test_string, "3"sv).value_or(3), 2u);
397 EXPECT_EQ(AK::StringUtils::find(test_string, "4"sv).value_or(4), 3u);
398 EXPECT_EQ(AK::StringUtils::find(test_string, "5"sv).value_or(5), 4u);
399 EXPECT_EQ(AK::StringUtils::find(test_string, "34"sv).value_or(3), 2u);
400 EXPECT_EQ(AK::StringUtils::find(test_string, "78"sv).has_value(), false);
401}
402
403TEST_CASE(to_snakecase)
404{
405 EXPECT_EQ(AK::StringUtils::to_snakecase("foobar"sv), "foobar");
406 EXPECT_EQ(AK::StringUtils::to_snakecase("Foobar"sv), "foobar");
407 EXPECT_EQ(AK::StringUtils::to_snakecase("FOOBAR"sv), "foobar");
408 EXPECT_EQ(AK::StringUtils::to_snakecase("fooBar"sv), "foo_bar");
409 EXPECT_EQ(AK::StringUtils::to_snakecase("FooBar"sv), "foo_bar");
410 EXPECT_EQ(AK::StringUtils::to_snakecase("fooBAR"sv), "foo_bar");
411 EXPECT_EQ(AK::StringUtils::to_snakecase("FOOBar"sv), "foo_bar");
412 EXPECT_EQ(AK::StringUtils::to_snakecase("foo_bar"sv), "foo_bar");
413 EXPECT_EQ(AK::StringUtils::to_snakecase("FBar"sv), "f_bar");
414 EXPECT_EQ(AK::StringUtils::to_snakecase("FooB"sv), "foo_b");
415}
416
417TEST_CASE(to_titlecase)
418{
419 EXPECT_EQ(AK::StringUtils::to_titlecase(""sv), ""sv);
420 EXPECT_EQ(AK::StringUtils::to_titlecase("f"sv), "F"sv);
421 EXPECT_EQ(AK::StringUtils::to_titlecase("foobar"sv), "Foobar"sv);
422 EXPECT_EQ(AK::StringUtils::to_titlecase("Foobar"sv), "Foobar"sv);
423 EXPECT_EQ(AK::StringUtils::to_titlecase("FOOBAR"sv), "Foobar"sv);
424 EXPECT_EQ(AK::StringUtils::to_titlecase("foo bar"sv), "Foo Bar"sv);
425 EXPECT_EQ(AK::StringUtils::to_titlecase("foo bAR"sv), "Foo Bar"sv);
426 EXPECT_EQ(AK::StringUtils::to_titlecase("foo bar"sv), "Foo Bar"sv);
427 EXPECT_EQ(AK::StringUtils::to_titlecase("foo bar"sv), "Foo Bar"sv);
428 EXPECT_EQ(AK::StringUtils::to_titlecase(" foo bar "sv), " Foo Bar "sv);
429 EXPECT_EQ(AK::StringUtils::to_titlecase("\xc3\xa7"sv), "\xc3\xa7"sv); // U+00E7 LATIN SMALL LETTER C WITH CEDILLA
430 EXPECT_EQ(AK::StringUtils::to_titlecase("\xe1\x80\x80"sv), "\xe1\x80\x80"sv); // U+1000 MYANMAR LETTER KA
431}