Fix emulator build error
[platform/framework/web/chromium-efl.git] / base / i18n / rtl_unittest.cc
1 // Copyright 2011 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/i18n/rtl.h"
6
7 #include <stddef.h>
8
9 #include <algorithm>
10
11 #include "base/files/file_path.h"
12 #include "base/logging.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/test/icu_test_util.h"
17 #include "build/build_config.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "testing/platform_test.h"
20 #include "third_party/icu/source/common/unicode/locid.h"
21 #include "third_party/icu/source/i18n/unicode/usearch.h"
22
23 namespace base {
24 namespace i18n {
25
26 class RTLTest : public PlatformTest {
27 };
28
29 TEST_F(RTLTest, GetFirstStrongCharacterDirection) {
30   struct {
31     const wchar_t* text;
32     TextDirection direction;
33   } cases[] = {
34     // Test pure LTR string.
35     { L"foo bar", LEFT_TO_RIGHT },
36     // Test pure RTL string.
37     { L"\x05d0\x05d1\x05d2 \x05d3\x0d4\x05d5", RIGHT_TO_LEFT},
38     // Test bidi string in which the first character with strong directionality
39     // is a character with type L.
40     { L"foo \x05d0 bar", LEFT_TO_RIGHT },
41     // Test bidi string in which the first character with strong directionality
42     // is a character with type R.
43     { L"\x05d0 foo bar", RIGHT_TO_LEFT },
44     // Test bidi string which starts with a character with weak directionality
45     // and in which the first character with strong directionality is a
46     // character with type L.
47     { L"!foo \x05d0 bar", LEFT_TO_RIGHT },
48     // Test bidi string which starts with a character with weak directionality
49     // and in which the first character with strong directionality is a
50     // character with type R.
51     { L",\x05d0 foo bar", RIGHT_TO_LEFT },
52     // Test bidi string in which the first character with strong directionality
53     // is a character with type LRE.
54     { L"\x202a \x05d0 foo  bar", LEFT_TO_RIGHT },
55     // Test bidi string in which the first character with strong directionality
56     // is a character with type LRO.
57     { L"\x202d \x05d0 foo  bar", LEFT_TO_RIGHT },
58     // Test bidi string in which the first character with strong directionality
59     // is a character with type RLE.
60     { L"\x202b foo \x05d0 bar", RIGHT_TO_LEFT },
61     // Test bidi string in which the first character with strong directionality
62     // is a character with type RLO.
63     { L"\x202e foo \x05d0 bar", RIGHT_TO_LEFT },
64     // Test bidi string in which the first character with strong directionality
65     // is a character with type AL.
66     { L"\x0622 foo \x05d0 bar", RIGHT_TO_LEFT },
67     // Test a string without strong directionality characters.
68     { L",!.{}", LEFT_TO_RIGHT },
69     // Test empty string.
70     { L"", LEFT_TO_RIGHT },
71     // Test characters in non-BMP (e.g. Phoenician letters. Please refer to
72     // http://demo.icu-project.org/icu-bin/ubrowse?scr=151&b=10910 for more
73     // information).
74     {
75 #if defined(WCHAR_T_IS_UTF32)
76       L" ! \x10910" L"abc 123",
77 #elif defined(WCHAR_T_IS_UTF16)
78       L" ! \xd802\xdd10" L"abc 123",
79 #else
80 #error wchar_t should be either UTF-16 or UTF-32
81 #endif
82       RIGHT_TO_LEFT },
83     {
84 #if defined(WCHAR_T_IS_UTF32)
85       L" ! \x10401" L"abc 123",
86 #elif defined(WCHAR_T_IS_UTF16)
87       L" ! \xd801\xdc01" L"abc 123",
88 #else
89 #error wchar_t should be either UTF-16 or UTF-32
90 #endif
91       LEFT_TO_RIGHT },
92    };
93
94   for (auto& i : cases)
95     EXPECT_EQ(i.direction,
96               GetFirstStrongCharacterDirection(WideToUTF16(i.text)));
97 }
98
99
100 // Note that the cases with LRE, LRO, RLE and RLO are invalid for
101 // GetLastStrongCharacterDirection because they should be followed by PDF
102 // character.
103 TEST_F(RTLTest, GetLastStrongCharacterDirection) {
104   struct {
105     const wchar_t* text;
106     TextDirection direction;
107   } cases[] = {
108     // Test pure LTR string.
109     { L"foo bar", LEFT_TO_RIGHT },
110     // Test pure RTL string.
111     { L"\x05d0\x05d1\x05d2 \x05d3\x0d4\x05d5", RIGHT_TO_LEFT},
112     // Test bidi string in which the last character with strong directionality
113     // is a character with type L.
114     { L"foo \x05d0 bar", LEFT_TO_RIGHT },
115     // Test bidi string in which the last character with strong directionality
116     // is a character with type R.
117     { L"\x05d0 foo bar \x05d3", RIGHT_TO_LEFT },
118     // Test bidi string which ends with a character with weak directionality
119     // and in which the last character with strong directionality is a
120     // character with type L.
121     { L"!foo \x05d0 bar!", LEFT_TO_RIGHT },
122     // Test bidi string which ends with a character with weak directionality
123     // and in which the last character with strong directionality is a
124     // character with type R.
125     { L",\x05d0 foo bar \x05d1,", RIGHT_TO_LEFT },
126     // Test bidi string in which the last character with strong directionality
127     // is a character with type AL.
128     { L"\x0622 foo \x05d0 bar \x0622", RIGHT_TO_LEFT },
129     // Test a string without strong directionality characters.
130     { L",!.{}", LEFT_TO_RIGHT },
131     // Test empty string.
132     { L"", LEFT_TO_RIGHT },
133     // Test characters in non-BMP (e.g. Phoenician letters. Please refer to
134     // http://demo.icu-project.org/icu-bin/ubrowse?scr=151&b=10910 for more
135     // information).
136     {
137 #if defined(WCHAR_T_IS_UTF32)
138        L"abc 123" L" ! \x10910 !",
139 #elif defined(WCHAR_T_IS_UTF16)
140        L"abc 123" L" ! \xd802\xdd10 !",
141 #else
142 #error wchar_t should be either UTF-16 or UTF-32
143 #endif
144       RIGHT_TO_LEFT },
145     {
146 #if defined(WCHAR_T_IS_UTF32)
147        L"abc 123" L" ! \x10401 !",
148 #elif defined(WCHAR_T_IS_UTF16)
149        L"abc 123" L" ! \xd801\xdc01 !",
150 #else
151 #error wchar_t should be either UTF-16 or UTF-32
152 #endif
153       LEFT_TO_RIGHT },
154    };
155
156   for (auto& i : cases)
157     EXPECT_EQ(i.direction,
158               GetLastStrongCharacterDirection(WideToUTF16(i.text)));
159 }
160
161 TEST_F(RTLTest, GetStringDirection) {
162   struct {
163     const wchar_t* text;
164     TextDirection direction;
165   } cases[] = {
166     // Test pure LTR string.
167     { L"foobar", LEFT_TO_RIGHT },
168     { L".foobar", LEFT_TO_RIGHT },
169     { L"foo, bar", LEFT_TO_RIGHT },
170     // Test pure LTR with strong directionality characters of type LRE.
171     { L"\x202a\x202a", LEFT_TO_RIGHT },
172     { L".\x202a\x202a", LEFT_TO_RIGHT },
173     { L"\x202a, \x202a", LEFT_TO_RIGHT },
174     // Test pure LTR with strong directionality characters of type LRO.
175     { L"\x202d\x202d", LEFT_TO_RIGHT },
176     { L".\x202d\x202d", LEFT_TO_RIGHT },
177     { L"\x202d, \x202d", LEFT_TO_RIGHT },
178     // Test pure LTR with various types of strong directionality characters.
179     { L"foo \x202a\x202d", LEFT_TO_RIGHT },
180     { L".\x202d foo \x202a", LEFT_TO_RIGHT },
181     { L"\x202a, \x202d foo", LEFT_TO_RIGHT },
182     // Test pure RTL with strong directionality characters of type R.
183     { L"\x05d0\x05d0", RIGHT_TO_LEFT },
184     { L".\x05d0\x05d0", RIGHT_TO_LEFT },
185     { L"\x05d0, \x05d0", RIGHT_TO_LEFT },
186     // Test pure RTL with strong directionality characters of type RLE.
187     { L"\x202b\x202b", RIGHT_TO_LEFT },
188     { L".\x202b\x202b", RIGHT_TO_LEFT },
189     { L"\x202b, \x202b", RIGHT_TO_LEFT },
190     // Test pure RTL with strong directionality characters of type RLO.
191     { L"\x202e\x202e", RIGHT_TO_LEFT },
192     { L".\x202e\x202e", RIGHT_TO_LEFT },
193     { L"\x202e, \x202e", RIGHT_TO_LEFT },
194     // Test pure RTL with strong directionality characters of type AL.
195     { L"\x0622\x0622", RIGHT_TO_LEFT },
196     { L".\x0622\x0622", RIGHT_TO_LEFT },
197     { L"\x0622, \x0622", RIGHT_TO_LEFT },
198     // Test pure RTL with various types of strong directionality characters.
199     { L"\x05d0\x202b\x202e\x0622", RIGHT_TO_LEFT },
200     { L".\x202b\x202e\x0622\x05d0", RIGHT_TO_LEFT },
201     { L"\x0622\x202e, \x202b\x05d0", RIGHT_TO_LEFT },
202     // Test bidi strings.
203     { L"foo \x05d0 bar", UNKNOWN_DIRECTION },
204     { L"\x202b foo bar", UNKNOWN_DIRECTION },
205     { L"!foo \x0622 bar", UNKNOWN_DIRECTION },
206     { L"\x202a\x202b", UNKNOWN_DIRECTION },
207     { L"\x202e\x202d", UNKNOWN_DIRECTION },
208     { L"\x0622\x202a", UNKNOWN_DIRECTION },
209     { L"\x202d\x05d0", UNKNOWN_DIRECTION },
210     // Test a string without strong directionality characters.
211     { L",!.{}", LEFT_TO_RIGHT },
212     // Test empty string.
213     { L"", LEFT_TO_RIGHT },
214     {
215 #if defined(WCHAR_T_IS_UTF32)
216       L" ! \x10910" L"abc 123",
217 #elif defined(WCHAR_T_IS_UTF16)
218       L" ! \xd802\xdd10" L"abc 123",
219 #else
220 #error wchar_t should be either UTF-16 or UTF-32
221 #endif
222       UNKNOWN_DIRECTION },
223     {
224 #if defined(WCHAR_T_IS_UTF32)
225       L" ! \x10401" L"abc 123",
226 #elif defined(WCHAR_T_IS_UTF16)
227       L" ! \xd801\xdc01" L"abc 123",
228 #else
229 #error wchar_t should be either UTF-16 or UTF-32
230 #endif
231       LEFT_TO_RIGHT },
232    };
233
234   for (auto& i : cases)
235     EXPECT_EQ(i.direction, GetStringDirection(WideToUTF16(i.text)));
236 }
237
238 TEST_F(RTLTest, WrapPathWithLTRFormatting) {
239   const wchar_t* cases[] = {
240     // Test common path, such as "c:\foo\bar".
241     L"c:/foo/bar",
242     // Test path with file name, such as "c:\foo\bar\test.jpg".
243     L"c:/foo/bar/test.jpg",
244     // Test path ending with punctuation, such as "c:\(foo)\bar.".
245     L"c:/(foo)/bar.",
246     // Test path ending with separator, such as "c:\foo\bar\".
247     L"c:/foo/bar/",
248     // Test path with RTL character.
249     L"c:/\x05d0",
250     // Test path with 2 level RTL directory names.
251     L"c:/\x05d0/\x0622",
252     // Test path with mixed RTL/LTR directory names and ending with punctuation.
253     L"c:/\x05d0/\x0622/(foo)/b.a.r.",
254     // Test path without driver name, such as "/foo/bar/test/jpg".
255     L"/foo/bar/test.jpg",
256     // Test path start with current directory, such as "./foo".
257     L"./foo",
258     // Test path start with parent directory, such as "../foo/bar.jpg".
259     L"../foo/bar.jpg",
260     // Test absolute path, such as "//foo/bar.jpg".
261     L"//foo/bar.jpg",
262     // Test path with mixed RTL/LTR directory names.
263     L"c:/foo/\x05d0/\x0622/\x05d1.jpg",
264     // Test empty path.
265     L""
266   };
267
268   for (auto*& i : cases) {
269     FilePath path;
270 #if BUILDFLAG(IS_WIN)
271     std::wstring win_path(i);
272     std::replace(win_path.begin(), win_path.end(), '/', '\\');
273     path = FilePath(win_path);
274     std::wstring wrapped_expected =
275         std::wstring(L"\x202a") + win_path + L"\x202c";
276 #else
277     path = FilePath(base::SysWideToNativeMB(i));
278     std::wstring wrapped_expected = std::wstring(L"\x202a") + i + L"\x202c";
279 #endif
280     std::u16string localized_file_path_string;
281     WrapPathWithLTRFormatting(path, &localized_file_path_string);
282
283     std::wstring wrapped_actual = UTF16ToWide(localized_file_path_string);
284     EXPECT_EQ(wrapped_expected, wrapped_actual);
285   }
286 }
287
288 TEST_F(RTLTest, WrapString) {
289   const wchar_t* cases[] = {
290     L" . ",
291     L"abc",
292     L"a" L"\x5d0\x5d1",
293     L"a" L"\x5d1" L"b",
294     L"\x5d0\x5d1\x5d2",
295     L"\x5d0\x5d1" L"a",
296     L"\x5d0" L"a" L"\x5d1",
297   };
298
299   const bool was_rtl = IsRTL();
300
301   test::ScopedRestoreICUDefaultLocale restore_locale;
302   for (size_t i = 0; i < 2; ++i) {
303     // Toggle the application default text direction (to try each direction).
304     SetRTLForTesting(!IsRTL());
305
306     std::u16string empty;
307     WrapStringWithLTRFormatting(&empty);
308     EXPECT_TRUE(empty.empty());
309     WrapStringWithRTLFormatting(&empty);
310     EXPECT_TRUE(empty.empty());
311
312     for (auto*& test_case : cases) {
313       std::u16string input = WideToUTF16(test_case);
314       std::u16string ltr_wrap = input;
315       WrapStringWithLTRFormatting(&ltr_wrap);
316       EXPECT_EQ(ltr_wrap[0], kLeftToRightEmbeddingMark);
317       EXPECT_EQ(ltr_wrap.substr(1, ltr_wrap.length() - 2), input);
318       EXPECT_EQ(ltr_wrap[ltr_wrap.length() -1], kPopDirectionalFormatting);
319
320       std::u16string rtl_wrap = input;
321       WrapStringWithRTLFormatting(&rtl_wrap);
322       EXPECT_EQ(rtl_wrap[0], kRightToLeftEmbeddingMark);
323       EXPECT_EQ(rtl_wrap.substr(1, rtl_wrap.length() - 2), input);
324       EXPECT_EQ(rtl_wrap[rtl_wrap.length() -1], kPopDirectionalFormatting);
325     }
326   }
327
328   EXPECT_EQ(was_rtl, IsRTL());
329 }
330
331 TEST_F(RTLTest, GetDisplayStringInLTRDirectionality) {
332   struct {
333     const wchar_t* path;
334     bool wrap_ltr;
335     bool wrap_rtl;
336   } cases[] = {
337     { L"test",                   false, true },
338     { L"test.html",              false, true },
339     { L"\x05d0\x05d1\x05d2",     true,  true },
340     { L"\x05d0\x05d1\x05d2.txt", true,  true },
341     { L"\x05d0" L"abc",          true,  true },
342     { L"\x05d0" L"abc.txt",      true,  true },
343     { L"abc\x05d0\x05d1",        false, true },
344     { L"abc\x05d0\x05d1.jpg",    false, true },
345   };
346
347   const bool was_rtl = IsRTL();
348
349   test::ScopedRestoreICUDefaultLocale restore_locale;
350   for (size_t i = 0; i < 2; ++i) {
351     // Toggle the application default text direction (to try each direction).
352     SetRTLForTesting(!IsRTL());
353     for (auto& test_case : cases) {
354       std::u16string input = WideToUTF16(test_case.path);
355       std::u16string output = GetDisplayStringInLTRDirectionality(input);
356       // Test the expected wrapping behavior for the current UI directionality.
357       if (IsRTL() ? test_case.wrap_rtl : test_case.wrap_ltr)
358         EXPECT_NE(output, input);
359       else
360         EXPECT_EQ(output, input);
361     }
362   }
363
364   EXPECT_EQ(was_rtl, IsRTL());
365 }
366
367 TEST_F(RTLTest, GetTextDirection) {
368   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("ar"));
369   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("ar_EG"));
370   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("he"));
371   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("he_IL"));
372   // iw is an obsolete code for Hebrew.
373   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("iw"));
374   // Although we're not yet localized to Farsi and Urdu, we
375   // do have the text layout direction information for them.
376   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("fa"));
377   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("ur"));
378 #if 0
379   // Enable these when we include the minimal locale data for Azerbaijani
380   // written in Arabic and Dhivehi. At the moment, our copy of
381   // ICU data does not have entries for them.
382   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("az_Arab"));
383   // Dhivehi that uses Thaana script.
384   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("dv"));
385 #endif
386   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("en"));
387   // Chinese in China with '-'.
388   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("zh-CN"));
389   // Filipino : 3-letter code
390   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("fil"));
391   // Russian
392   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("ru"));
393   // Japanese that uses multiple scripts
394   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("ja"));
395 }
396
397 TEST_F(RTLTest, GetTextDirectionForLocaleInStartUp) {
398   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("ar"));
399   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("ar_EG"));
400   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("he"));
401   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("he_IL"));
402   // iw is an obsolete code for Hebrew.
403   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("iw"));
404   // Although we're not yet localized to Farsi and Urdu, we
405   // do have the text layout direction information for them.
406   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("fa"));
407   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("ur"));
408   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("en"));
409   // Chinese in China with '-'.
410   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("zh-CN"));
411   // Filipino : 3-letter code
412   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("fil"));
413   // Russian
414   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("ru"));
415   // Japanese that uses multiple scripts
416   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("ja"));
417 }
418
419 TEST_F(RTLTest, UnadjustStringForLocaleDirection) {
420   // These test strings are borrowed from WrapPathWithLTRFormatting
421   const wchar_t* cases[] = {
422     L"foo bar",
423     L"foo \x05d0 bar",
424     L"\x05d0 foo bar",
425     L"!foo \x05d0 bar",
426     L",\x05d0 foo bar",
427     L"\x202a \x05d0 foo  bar",
428     L"\x202d \x05d0 foo  bar",
429     L"\x202b foo \x05d0 bar",
430     L"\x202e foo \x05d0 bar",
431     L"\x0622 foo \x05d0 bar",
432   };
433
434   const bool was_rtl = IsRTL();
435
436   test::ScopedRestoreICUDefaultLocale restore_locale;
437   for (size_t i = 0; i < 2; ++i) {
438     // Toggle the application default text direction (to try each direction).
439     SetRTLForTesting(!IsRTL());
440
441     for (auto*& test_case : cases) {
442       std::u16string unadjusted_string = WideToUTF16(test_case);
443       std::u16string adjusted_string = unadjusted_string;
444
445       if (!AdjustStringForLocaleDirection(&adjusted_string))
446         continue;
447
448       EXPECT_NE(unadjusted_string, adjusted_string);
449       EXPECT_TRUE(UnadjustStringForLocaleDirection(&adjusted_string));
450       EXPECT_EQ(unadjusted_string, adjusted_string)
451           << " for test case [" << unadjusted_string
452           << "] with IsRTL() == " << IsRTL();
453     }
454   }
455
456   EXPECT_EQ(was_rtl, IsRTL());
457 }
458
459 TEST_F(RTLTest, EnsureTerminatedDirectionalFormatting) {
460   struct {
461     const wchar_t* unformated_text;
462     const wchar_t* formatted_text;
463   } cases[] = {
464       // Tests string without any dir-formatting characters.
465       {L"google.com", L"google.com"},
466       // Tests string with properly terminated dir-formatting character.
467       {L"\x202egoogle.com\x202c", L"\x202egoogle.com\x202c"},
468       // Tests string with over-terminated dir-formatting characters.
469       {L"\x202egoogle\x202c.com\x202c", L"\x202egoogle\x202c.com\x202c"},
470       // Tests string beginning with a dir-formatting character.
471       {L"\x202emoc.elgoog", L"\x202emoc.elgoog\x202c"},
472       // Tests string that over-terminates then re-opens.
473       {L"\x202egoogle\x202c\x202c.\x202eom",
474        L"\x202egoogle\x202c\x202c.\x202eom\x202c"},
475       // Tests string containing a dir-formatting character in the middle.
476       {L"google\x202e.com", L"google\x202e.com\x202c"},
477       // Tests string with multiple dir-formatting characters.
478       {L"\x202egoogle\x202e.com/\x202eguest",
479        L"\x202egoogle\x202e.com/\x202eguest\x202c\x202c\x202c"},
480       // Test the other dir-formatting characters (U+202A, U+202B, and U+202D).
481       {L"\x202agoogle.com", L"\x202agoogle.com\x202c"},
482       {L"\x202bgoogle.com", L"\x202bgoogle.com\x202c"},
483       {L"\x202dgoogle.com", L"\x202dgoogle.com\x202c"},
484   };
485
486   const bool was_rtl = IsRTL();
487
488   test::ScopedRestoreICUDefaultLocale restore_locale;
489   for (size_t i = 0; i < 2; ++i) {
490     // Toggle the application default text direction (to try each direction).
491     SetRTLForTesting(!IsRTL());
492     for (auto& test_case : cases) {
493       std::u16string unsanitized_text = WideToUTF16(test_case.unformated_text);
494       std::u16string sanitized_text = WideToUTF16(test_case.formatted_text);
495       EnsureTerminatedDirectionalFormatting(&unsanitized_text);
496       EXPECT_EQ(sanitized_text, unsanitized_text);
497     }
498   }
499   EXPECT_EQ(was_rtl, IsRTL());
500 }
501
502 TEST_F(RTLTest, SanitizeUserSuppliedString) {
503   struct {
504     const wchar_t* unformatted_text;
505     const wchar_t* formatted_text;
506   } cases[] = {
507       // Tests RTL string with properly terminated dir-formatting character.
508       {L"\x202eكبير Google التطبيق\x202c", L"\x202eكبير Google التطبيق\x202c"},
509       // Tests RTL string with over-terminated dir-formatting characters.
510       {L"\x202eكبير Google\x202cالتطبيق\x202c",
511        L"\x202eكبير Google\x202cالتطبيق\x202c"},
512       // Tests RTL string that over-terminates then re-opens.
513       {L"\x202eكبير Google\x202c\x202cالتطبيق\x202e",
514        L"\x202eكبير Google\x202c\x202cالتطبيق\x202e\x202c"},
515       // Tests RTL string with multiple dir-formatting characters.
516       {L"\x202eك\x202eبير Google الت\x202eطبيق",
517        L"\x202eك\x202eبير Google الت\x202eطبيق\x202c\x202c\x202c"},
518       // Test the other dir-formatting characters (U+202A, U+202B, and U+202D).
519       {L"\x202aكبير Google التطبيق", L"\x202aكبير Google التطبيق\x202c"},
520       {L"\x202bكبير Google التطبيق", L"\x202bكبير Google التطبيق\x202c"},
521       {L"\x202dكبير Google التطبيق", L"\x202dكبير Google التطبيق\x202c"},
522
523   };
524
525   for (auto& i : cases) {
526     // On Windows for an LTR locale, no changes to the string are made.
527     std::u16string prefix, suffix = u"";
528 #if !BUILDFLAG(IS_WIN)
529     prefix = u"\x200e\x202b";
530     suffix = u"\x202c\x200e";
531 #endif  // !BUILDFLAG(IS_WIN)
532     std::u16string unsanitized_text = WideToUTF16(i.unformatted_text);
533     std::u16string sanitized_text =
534         prefix + WideToUTF16(i.formatted_text) + suffix;
535     SanitizeUserSuppliedString(&unsanitized_text);
536     EXPECT_EQ(sanitized_text, unsanitized_text);
537   }
538 }
539
540 class SetICULocaleTest : public PlatformTest {};
541
542 TEST_F(SetICULocaleTest, OverlongLocaleId) {
543   test::ScopedRestoreICUDefaultLocale restore_locale;
544   std::string id("fr-ca-x-foo");
545   std::string lid("fr_CA@x=foo");
546   while (id.length() < 152) {
547     id.append("-x-foo");
548     lid.append("-x-foo");
549   }
550   SetICUDefaultLocale(id);
551   EXPECT_STRNE("en_US", icu::Locale::getDefault().getName());
552   id.append("zzz");
553   lid.append("zzz");
554   SetICUDefaultLocale(id);
555   // ICU-21639 fix the long locale issue now.
556   EXPECT_STREQ(lid.c_str(), icu::Locale::getDefault().getName());
557 }
558
559 }  // namespace i18n
560 }  // namespace base