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