| // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "base/i18n/rtl.h" | 
 |  | 
 | #include <stddef.h> | 
 |  | 
 | #include <algorithm> | 
 |  | 
 | #include "base/files/file_path.h" | 
 | #include "base/macros.h" | 
 | #include "base/strings/string_util.h" | 
 | #include "base/strings/sys_string_conversions.h" | 
 | #include "base/strings/utf_string_conversions.h" | 
 | #include "base/test/icu_test_util.h" | 
 | #include "build/build_config.h" | 
 | #include "testing/gtest/include/gtest/gtest.h" | 
 | #include "testing/platform_test.h" | 
 | #include "third_party/icu/source/common/unicode/locid.h" | 
 | #include "third_party/icu/source/i18n/unicode/usearch.h" | 
 |  | 
 | namespace base { | 
 | namespace i18n { | 
 |  | 
 | namespace { | 
 |  | 
 | // A test utility function to set the application default text direction. | 
 | void SetRTL(bool rtl) { | 
 |   // Override the current locale/direction. | 
 |   SetICUDefaultLocale(rtl ? "he" : "en"); | 
 |   EXPECT_EQ(rtl, IsRTL()); | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | class RTLTest : public PlatformTest { | 
 | }; | 
 |  | 
 | TEST_F(RTLTest, GetFirstStrongCharacterDirection) { | 
 |   struct { | 
 |     const wchar_t* text; | 
 |     TextDirection direction; | 
 |   } cases[] = { | 
 |     // Test pure LTR string. | 
 |     { L"foo bar", LEFT_TO_RIGHT }, | 
 |     // Test pure RTL string. | 
 |     { L"\x05d0\x05d1\x05d2 \x05d3\x0d4\x05d5", RIGHT_TO_LEFT}, | 
 |     // Test bidi string in which the first character with strong directionality | 
 |     // is a character with type L. | 
 |     { L"foo \x05d0 bar", LEFT_TO_RIGHT }, | 
 |     // Test bidi string in which the first character with strong directionality | 
 |     // is a character with type R. | 
 |     { L"\x05d0 foo bar", RIGHT_TO_LEFT }, | 
 |     // Test bidi string which starts with a character with weak directionality | 
 |     // and in which the first character with strong directionality is a | 
 |     // character with type L. | 
 |     { L"!foo \x05d0 bar", LEFT_TO_RIGHT }, | 
 |     // Test bidi string which starts with a character with weak directionality | 
 |     // and in which the first character with strong directionality is a | 
 |     // character with type R. | 
 |     { L",\x05d0 foo bar", RIGHT_TO_LEFT }, | 
 |     // Test bidi string in which the first character with strong directionality | 
 |     // is a character with type LRE. | 
 |     { L"\x202a \x05d0 foo  bar", LEFT_TO_RIGHT }, | 
 |     // Test bidi string in which the first character with strong directionality | 
 |     // is a character with type LRO. | 
 |     { L"\x202d \x05d0 foo  bar", LEFT_TO_RIGHT }, | 
 |     // Test bidi string in which the first character with strong directionality | 
 |     // is a character with type RLE. | 
 |     { L"\x202b foo \x05d0 bar", RIGHT_TO_LEFT }, | 
 |     // Test bidi string in which the first character with strong directionality | 
 |     // is a character with type RLO. | 
 |     { L"\x202e foo \x05d0 bar", RIGHT_TO_LEFT }, | 
 |     // Test bidi string in which the first character with strong directionality | 
 |     // is a character with type AL. | 
 |     { L"\x0622 foo \x05d0 bar", RIGHT_TO_LEFT }, | 
 |     // Test a string without strong directionality characters. | 
 |     { L",!.{}", LEFT_TO_RIGHT }, | 
 |     // Test empty string. | 
 |     { L"", LEFT_TO_RIGHT }, | 
 |     // Test characters in non-BMP (e.g. Phoenician letters. Please refer to | 
 |     // http://demo.icu-project.org/icu-bin/ubrowse?scr=151&b=10910 for more | 
 |     // information). | 
 |     { | 
 | #if defined(WCHAR_T_IS_UTF32) | 
 |       L" ! \x10910" L"abc 123", | 
 | #elif defined(WCHAR_T_IS_UTF16) | 
 |       L" ! \xd802\xdd10" L"abc 123", | 
 | #else | 
 | #error wchar_t should be either UTF-16 or UTF-32 | 
 | #endif | 
 |       RIGHT_TO_LEFT }, | 
 |     { | 
 | #if defined(WCHAR_T_IS_UTF32) | 
 |       L" ! \x10401" L"abc 123", | 
 | #elif defined(WCHAR_T_IS_UTF16) | 
 |       L" ! \xd801\xdc01" L"abc 123", | 
 | #else | 
 | #error wchar_t should be either UTF-16 or UTF-32 | 
 | #endif | 
 |       LEFT_TO_RIGHT }, | 
 |    }; | 
 |  | 
 |   for (size_t i = 0; i < arraysize(cases); ++i) | 
 |     EXPECT_EQ(cases[i].direction, | 
 |               GetFirstStrongCharacterDirection(WideToUTF16(cases[i].text))); | 
 | } | 
 |  | 
 |  | 
 | // Note that the cases with LRE, LRO, RLE and RLO are invalid for | 
 | // GetLastStrongCharacterDirection because they should be followed by PDF | 
 | // character. | 
 | TEST_F(RTLTest, GetLastStrongCharacterDirection) { | 
 |   struct { | 
 |     const wchar_t* text; | 
 |     TextDirection direction; | 
 |   } cases[] = { | 
 |     // Test pure LTR string. | 
 |     { L"foo bar", LEFT_TO_RIGHT }, | 
 |     // Test pure RTL string. | 
 |     { L"\x05d0\x05d1\x05d2 \x05d3\x0d4\x05d5", RIGHT_TO_LEFT}, | 
 |     // Test bidi string in which the last character with strong directionality | 
 |     // is a character with type L. | 
 |     { L"foo \x05d0 bar", LEFT_TO_RIGHT }, | 
 |     // Test bidi string in which the last character with strong directionality | 
 |     // is a character with type R. | 
 |     { L"\x05d0 foo bar \x05d3", RIGHT_TO_LEFT }, | 
 |     // Test bidi string which ends with a character with weak directionality | 
 |     // and in which the last character with strong directionality is a | 
 |     // character with type L. | 
 |     { L"!foo \x05d0 bar!", LEFT_TO_RIGHT }, | 
 |     // Test bidi string which ends with a character with weak directionality | 
 |     // and in which the last character with strong directionality is a | 
 |     // character with type R. | 
 |     { L",\x05d0 foo bar \x05d1,", RIGHT_TO_LEFT }, | 
 |     // Test bidi string in which the last character with strong directionality | 
 |     // is a character with type AL. | 
 |     { L"\x0622 foo \x05d0 bar \x0622", RIGHT_TO_LEFT }, | 
 |     // Test a string without strong directionality characters. | 
 |     { L",!.{}", LEFT_TO_RIGHT }, | 
 |     // Test empty string. | 
 |     { L"", LEFT_TO_RIGHT }, | 
 |     // Test characters in non-BMP (e.g. Phoenician letters. Please refer to | 
 |     // http://demo.icu-project.org/icu-bin/ubrowse?scr=151&b=10910 for more | 
 |     // information). | 
 |     { | 
 | #if defined(WCHAR_T_IS_UTF32) | 
 |        L"abc 123" L" ! \x10910 !", | 
 | #elif defined(WCHAR_T_IS_UTF16) | 
 |        L"abc 123" L" ! \xd802\xdd10 !", | 
 | #else | 
 | #error wchar_t should be either UTF-16 or UTF-32 | 
 | #endif | 
 |       RIGHT_TO_LEFT }, | 
 |     { | 
 | #if defined(WCHAR_T_IS_UTF32) | 
 |        L"abc 123" L" ! \x10401 !", | 
 | #elif defined(WCHAR_T_IS_UTF16) | 
 |        L"abc 123" L" ! \xd801\xdc01 !", | 
 | #else | 
 | #error wchar_t should be either UTF-16 or UTF-32 | 
 | #endif | 
 |       LEFT_TO_RIGHT }, | 
 |    }; | 
 |  | 
 |   for (size_t i = 0; i < arraysize(cases); ++i) | 
 |     EXPECT_EQ(cases[i].direction, | 
 |               GetLastStrongCharacterDirection(WideToUTF16(cases[i].text))); | 
 | } | 
 |  | 
 | TEST_F(RTLTest, GetStringDirection) { | 
 |   struct { | 
 |     const wchar_t* text; | 
 |     TextDirection direction; | 
 |   } cases[] = { | 
 |     // Test pure LTR string. | 
 |     { L"foobar", LEFT_TO_RIGHT }, | 
 |     { L".foobar", LEFT_TO_RIGHT }, | 
 |     { L"foo, bar", LEFT_TO_RIGHT }, | 
 |     // Test pure LTR with strong directionality characters of type LRE. | 
 |     { L"\x202a\x202a", LEFT_TO_RIGHT }, | 
 |     { L".\x202a\x202a", LEFT_TO_RIGHT }, | 
 |     { L"\x202a, \x202a", LEFT_TO_RIGHT }, | 
 |     // Test pure LTR with strong directionality characters of type LRO. | 
 |     { L"\x202d\x202d", LEFT_TO_RIGHT }, | 
 |     { L".\x202d\x202d", LEFT_TO_RIGHT }, | 
 |     { L"\x202d, \x202d", LEFT_TO_RIGHT }, | 
 |     // Test pure LTR with various types of strong directionality characters. | 
 |     { L"foo \x202a\x202d", LEFT_TO_RIGHT }, | 
 |     { L".\x202d foo \x202a", LEFT_TO_RIGHT }, | 
 |     { L"\x202a, \x202d foo", LEFT_TO_RIGHT }, | 
 |     // Test pure RTL with strong directionality characters of type R. | 
 |     { L"\x05d0\x05d0", RIGHT_TO_LEFT }, | 
 |     { L".\x05d0\x05d0", RIGHT_TO_LEFT }, | 
 |     { L"\x05d0, \x05d0", RIGHT_TO_LEFT }, | 
 |     // Test pure RTL with strong directionality characters of type RLE. | 
 |     { L"\x202b\x202b", RIGHT_TO_LEFT }, | 
 |     { L".\x202b\x202b", RIGHT_TO_LEFT }, | 
 |     { L"\x202b, \x202b", RIGHT_TO_LEFT }, | 
 |     // Test pure RTL with strong directionality characters of type RLO. | 
 |     { L"\x202e\x202e", RIGHT_TO_LEFT }, | 
 |     { L".\x202e\x202e", RIGHT_TO_LEFT }, | 
 |     { L"\x202e, \x202e", RIGHT_TO_LEFT }, | 
 |     // Test pure RTL with strong directionality characters of type AL. | 
 |     { L"\x0622\x0622", RIGHT_TO_LEFT }, | 
 |     { L".\x0622\x0622", RIGHT_TO_LEFT }, | 
 |     { L"\x0622, \x0622", RIGHT_TO_LEFT }, | 
 |     // Test pure RTL with various types of strong directionality characters. | 
 |     { L"\x05d0\x202b\x202e\x0622", RIGHT_TO_LEFT }, | 
 |     { L".\x202b\x202e\x0622\x05d0", RIGHT_TO_LEFT }, | 
 |     { L"\x0622\x202e, \x202b\x05d0", RIGHT_TO_LEFT }, | 
 |     // Test bidi strings. | 
 |     { L"foo \x05d0 bar", UNKNOWN_DIRECTION }, | 
 |     { L"\x202b foo bar", UNKNOWN_DIRECTION }, | 
 |     { L"!foo \x0622 bar", UNKNOWN_DIRECTION }, | 
 |     { L"\x202a\x202b", UNKNOWN_DIRECTION }, | 
 |     { L"\x202e\x202d", UNKNOWN_DIRECTION }, | 
 |     { L"\x0622\x202a", UNKNOWN_DIRECTION }, | 
 |     { L"\x202d\x05d0", UNKNOWN_DIRECTION }, | 
 |     // Test a string without strong directionality characters. | 
 |     { L",!.{}", LEFT_TO_RIGHT }, | 
 |     // Test empty string. | 
 |     { L"", LEFT_TO_RIGHT }, | 
 |     { | 
 | #if defined(WCHAR_T_IS_UTF32) | 
 |       L" ! \x10910" L"abc 123", | 
 | #elif defined(WCHAR_T_IS_UTF16) | 
 |       L" ! \xd802\xdd10" L"abc 123", | 
 | #else | 
 | #error wchar_t should be either UTF-16 or UTF-32 | 
 | #endif | 
 |       UNKNOWN_DIRECTION }, | 
 |     { | 
 | #if defined(WCHAR_T_IS_UTF32) | 
 |       L" ! \x10401" L"abc 123", | 
 | #elif defined(WCHAR_T_IS_UTF16) | 
 |       L" ! \xd801\xdc01" L"abc 123", | 
 | #else | 
 | #error wchar_t should be either UTF-16 or UTF-32 | 
 | #endif | 
 |       LEFT_TO_RIGHT }, | 
 |    }; | 
 |  | 
 |   for (size_t i = 0; i < arraysize(cases); ++i) | 
 |     EXPECT_EQ(cases[i].direction, | 
 |               GetStringDirection(WideToUTF16(cases[i].text))); | 
 | } | 
 |  | 
 | TEST_F(RTLTest, WrapPathWithLTRFormatting) { | 
 |   const wchar_t* cases[] = { | 
 |     // Test common path, such as "c:\foo\bar". | 
 |     L"c:/foo/bar", | 
 |     // Test path with file name, such as "c:\foo\bar\test.jpg". | 
 |     L"c:/foo/bar/test.jpg", | 
 |     // Test path ending with punctuation, such as "c:\(foo)\bar.". | 
 |     L"c:/(foo)/bar.", | 
 |     // Test path ending with separator, such as "c:\foo\bar\". | 
 |     L"c:/foo/bar/", | 
 |     // Test path with RTL character. | 
 |     L"c:/\x05d0", | 
 |     // Test path with 2 level RTL directory names. | 
 |     L"c:/\x05d0/\x0622", | 
 |     // Test path with mixed RTL/LTR directory names and ending with punctuation. | 
 |     L"c:/\x05d0/\x0622/(foo)/b.a.r.", | 
 |     // Test path without driver name, such as "/foo/bar/test/jpg". | 
 |     L"/foo/bar/test.jpg", | 
 |     // Test path start with current directory, such as "./foo". | 
 |     L"./foo", | 
 |     // Test path start with parent directory, such as "../foo/bar.jpg". | 
 |     L"../foo/bar.jpg", | 
 |     // Test absolute path, such as "//foo/bar.jpg". | 
 |     L"//foo/bar.jpg", | 
 |     // Test path with mixed RTL/LTR directory names. | 
 |     L"c:/foo/\x05d0/\x0622/\x05d1.jpg", | 
 |     // Test empty path. | 
 |     L"" | 
 |   }; | 
 |  | 
 |   for (size_t i = 0; i < arraysize(cases); ++i) { | 
 |     FilePath path; | 
 | #if defined(OS_WIN) | 
 |     std::wstring win_path(cases[i]); | 
 |     std::replace(win_path.begin(), win_path.end(), '/', '\\'); | 
 |     path = FilePath(win_path); | 
 |     std::wstring wrapped_expected = | 
 |         std::wstring(L"\x202a") + win_path + L"\x202c"; | 
 | #else | 
 |     path = FilePath(base::SysWideToNativeMB(cases[i])); | 
 |     std::wstring wrapped_expected = | 
 |         std::wstring(L"\x202a") + cases[i] + L"\x202c"; | 
 | #endif | 
 |     string16 localized_file_path_string; | 
 |     WrapPathWithLTRFormatting(path, &localized_file_path_string); | 
 |  | 
 |     std::wstring wrapped_actual = UTF16ToWide(localized_file_path_string); | 
 |     EXPECT_EQ(wrapped_expected, wrapped_actual); | 
 |   } | 
 | } | 
 |  | 
 | TEST_F(RTLTest, WrapString) { | 
 |   const wchar_t* cases[] = { | 
 |     L" . ", | 
 |     L"abc", | 
 |     L"a" L"\x5d0\x5d1", | 
 |     L"a" L"\x5d1" L"b", | 
 |     L"\x5d0\x5d1\x5d2", | 
 |     L"\x5d0\x5d1" L"a", | 
 |     L"\x5d0" L"a" L"\x5d1", | 
 |   }; | 
 |  | 
 |   const bool was_rtl = IsRTL(); | 
 |  | 
 |   test::ScopedRestoreICUDefaultLocale restore_locale; | 
 |   for (size_t i = 0; i < 2; ++i) { | 
 |     // Toggle the application default text direction (to try each direction). | 
 |     SetRTL(!IsRTL()); | 
 |  | 
 |     string16 empty; | 
 |     WrapStringWithLTRFormatting(&empty); | 
 |     EXPECT_TRUE(empty.empty()); | 
 |     WrapStringWithRTLFormatting(&empty); | 
 |     EXPECT_TRUE(empty.empty()); | 
 |  | 
 |     for (size_t i = 0; i < arraysize(cases); ++i) { | 
 |       string16 input = WideToUTF16(cases[i]); | 
 |       string16 ltr_wrap = input; | 
 |       WrapStringWithLTRFormatting(<r_wrap); | 
 |       EXPECT_EQ(ltr_wrap[0], kLeftToRightEmbeddingMark); | 
 |       EXPECT_EQ(ltr_wrap.substr(1, ltr_wrap.length() - 2), input); | 
 |       EXPECT_EQ(ltr_wrap[ltr_wrap.length() -1], kPopDirectionalFormatting); | 
 |  | 
 |       string16 rtl_wrap = input; | 
 |       WrapStringWithRTLFormatting(&rtl_wrap); | 
 |       EXPECT_EQ(rtl_wrap[0], kRightToLeftEmbeddingMark); | 
 |       EXPECT_EQ(rtl_wrap.substr(1, rtl_wrap.length() - 2), input); | 
 |       EXPECT_EQ(rtl_wrap[rtl_wrap.length() -1], kPopDirectionalFormatting); | 
 |     } | 
 |   } | 
 |  | 
 |   EXPECT_EQ(was_rtl, IsRTL()); | 
 | } | 
 |  | 
 | TEST_F(RTLTest, GetDisplayStringInLTRDirectionality) { | 
 |   struct { | 
 |     const wchar_t* path; | 
 |     bool wrap_ltr; | 
 |     bool wrap_rtl; | 
 |   } cases[] = { | 
 |     { L"test",                   false, true }, | 
 |     { L"test.html",              false, true }, | 
 |     { L"\x05d0\x05d1\x05d2",     true,  true }, | 
 |     { L"\x05d0\x05d1\x05d2.txt", true,  true }, | 
 |     { L"\x05d0" L"abc",          true,  true }, | 
 |     { L"\x05d0" L"abc.txt",      true,  true }, | 
 |     { L"abc\x05d0\x05d1",        false, true }, | 
 |     { L"abc\x05d0\x05d1.jpg",    false, true }, | 
 |   }; | 
 |  | 
 |   const bool was_rtl = IsRTL(); | 
 |  | 
 |   test::ScopedRestoreICUDefaultLocale restore_locale; | 
 |   for (size_t i = 0; i < 2; ++i) { | 
 |     // Toggle the application default text direction (to try each direction). | 
 |     SetRTL(!IsRTL()); | 
 |     for (size_t i = 0; i < arraysize(cases); ++i) { | 
 |       string16 input = WideToUTF16(cases[i].path); | 
 |       string16 output = GetDisplayStringInLTRDirectionality(input); | 
 |       // Test the expected wrapping behavior for the current UI directionality. | 
 |       if (IsRTL() ? cases[i].wrap_rtl : cases[i].wrap_ltr) | 
 |         EXPECT_NE(output, input); | 
 |       else | 
 |         EXPECT_EQ(output, input); | 
 |     } | 
 |   } | 
 |  | 
 |   EXPECT_EQ(was_rtl, IsRTL()); | 
 | } | 
 |  | 
 | TEST_F(RTLTest, GetTextDirection) { | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("ar")); | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("ar_EG")); | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("he")); | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("he_IL")); | 
 |   // iw is an obsolete code for Hebrew. | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("iw")); | 
 |   // Although we're not yet localized to Farsi and Urdu, we | 
 |   // do have the text layout direction information for them. | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("fa")); | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("ur")); | 
 | #if 0 | 
 |   // Enable these when we include the minimal locale data for Azerbaijani | 
 |   // written in Arabic and Dhivehi. At the moment, our copy of | 
 |   // ICU data does not have entries for them. | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("az_Arab")); | 
 |   // Dhivehi that uses Thaana script. | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("dv")); | 
 | #endif | 
 |   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("en")); | 
 |   // Chinese in China with '-'. | 
 |   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("zh-CN")); | 
 |   // Filipino : 3-letter code | 
 |   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("fil")); | 
 |   // Russian | 
 |   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("ru")); | 
 |   // Japanese that uses multiple scripts | 
 |   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("ja")); | 
 | } | 
 |  | 
 | TEST_F(RTLTest, GetTextDirectionForLocaleInStartUp) { | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("ar")); | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("ar_EG")); | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("he")); | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("he_IL")); | 
 |   // iw is an obsolete code for Hebrew. | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("iw")); | 
 |   // Although we're not yet localized to Farsi and Urdu, we | 
 |   // do have the text layout direction information for them. | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("fa")); | 
 |   EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("ur")); | 
 |   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("en")); | 
 |   // Chinese in China with '-'. | 
 |   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("zh-CN")); | 
 |   // Filipino : 3-letter code | 
 |   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("fil")); | 
 |   // Russian | 
 |   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("ru")); | 
 |   // Japanese that uses multiple scripts | 
 |   EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("ja")); | 
 | } | 
 |  | 
 | TEST_F(RTLTest, UnadjustStringForLocaleDirection) { | 
 |   // These test strings are borrowed from WrapPathWithLTRFormatting | 
 |   const wchar_t* cases[] = { | 
 |     L"foo bar", | 
 |     L"foo \x05d0 bar", | 
 |     L"\x05d0 foo bar", | 
 |     L"!foo \x05d0 bar", | 
 |     L",\x05d0 foo bar", | 
 |     L"\x202a \x05d0 foo  bar", | 
 |     L"\x202d \x05d0 foo  bar", | 
 |     L"\x202b foo \x05d0 bar", | 
 |     L"\x202e foo \x05d0 bar", | 
 |     L"\x0622 foo \x05d0 bar", | 
 |   }; | 
 |  | 
 |   const bool was_rtl = IsRTL(); | 
 |  | 
 |   test::ScopedRestoreICUDefaultLocale restore_locale; | 
 |   for (size_t i = 0; i < 2; ++i) { | 
 |     // Toggle the application default text direction (to try each direction). | 
 |     SetRTL(!IsRTL()); | 
 |  | 
 |     for (size_t i = 0; i < arraysize(cases); ++i) { | 
 |       string16 test_case = WideToUTF16(cases[i]); | 
 |       string16 adjusted_string = test_case; | 
 |  | 
 |       if (!AdjustStringForLocaleDirection(&adjusted_string)) | 
 |         continue; | 
 |  | 
 |       EXPECT_NE(test_case, adjusted_string); | 
 |       EXPECT_TRUE(UnadjustStringForLocaleDirection(&adjusted_string)); | 
 |       EXPECT_EQ(test_case, adjusted_string) << " for test case [" << test_case | 
 |                                             << "] with IsRTL() == " << IsRTL(); | 
 |     } | 
 |   } | 
 |  | 
 |   EXPECT_EQ(was_rtl, IsRTL()); | 
 | } | 
 |  | 
 | TEST_F(RTLTest, EnsureTerminatedDirectionalFormatting) { | 
 |   struct { | 
 |     const wchar_t* unformated_text; | 
 |     const wchar_t* formatted_text; | 
 |   } cases[] = { | 
 |       // Tests string without any dir-formatting characters. | 
 |       {L"google.com", L"google.com"}, | 
 |       // Tests string with properly terminated dir-formatting character. | 
 |       {L"\x202egoogle.com\x202c", L"\x202egoogle.com\x202c"}, | 
 |       // Tests string with over-terminated dir-formatting characters. | 
 |       {L"\x202egoogle\x202c.com\x202c", L"\x202egoogle\x202c.com\x202c"}, | 
 |       // Tests string beginning with a dir-formatting character. | 
 |       {L"\x202emoc.elgoog", L"\x202emoc.elgoog\x202c"}, | 
 |       // Tests string that over-terminates then re-opens. | 
 |       {L"\x202egoogle\x202c\x202c.\x202eom", | 
 |        L"\x202egoogle\x202c\x202c.\x202eom\x202c"}, | 
 |       // Tests string containing a dir-formatting character in the middle. | 
 |       {L"google\x202e.com", L"google\x202e.com\x202c"}, | 
 |       // Tests string with multiple dir-formatting characters. | 
 |       {L"\x202egoogle\x202e.com/\x202eguest", | 
 |        L"\x202egoogle\x202e.com/\x202eguest\x202c\x202c\x202c"}, | 
 |       // Test the other dir-formatting characters (U+202A, U+202B, and U+202D). | 
 |       {L"\x202agoogle.com", L"\x202agoogle.com\x202c"}, | 
 |       {L"\x202bgoogle.com", L"\x202bgoogle.com\x202c"}, | 
 |       {L"\x202dgoogle.com", L"\x202dgoogle.com\x202c"}, | 
 |   }; | 
 |  | 
 |   const bool was_rtl = IsRTL(); | 
 |  | 
 |   test::ScopedRestoreICUDefaultLocale restore_locale; | 
 |   for (size_t i = 0; i < 2; ++i) { | 
 |     // Toggle the application default text direction (to try each direction). | 
 |     SetRTL(!IsRTL()); | 
 |     for (size_t i = 0; i < arraysize(cases); ++i) { | 
 |       string16 unsanitized_text = WideToUTF16(cases[i].unformated_text); | 
 |       string16 sanitized_text = WideToUTF16(cases[i].formatted_text); | 
 |       EnsureTerminatedDirectionalFormatting(&unsanitized_text); | 
 |       EXPECT_EQ(sanitized_text, unsanitized_text); | 
 |     } | 
 |   } | 
 |   EXPECT_EQ(was_rtl, IsRTL()); | 
 | } | 
 |  | 
 | TEST_F(RTLTest, SanitizeUserSuppliedString) { | 
 |   struct { | 
 |     const wchar_t* unformatted_text; | 
 |     const wchar_t* formatted_text; | 
 |   } cases[] = { | 
 |       // Tests RTL string with properly terminated dir-formatting character. | 
 |       {L"\x202eكبير Google التطبيق\x202c", L"\x202eكبير Google التطبيق\x202c"}, | 
 |       // Tests RTL string with over-terminated dir-formatting characters. | 
 |       {L"\x202eكبير Google\x202cالتطبيق\x202c", | 
 |        L"\x202eكبير Google\x202cالتطبيق\x202c"}, | 
 |       // Tests RTL string that over-terminates then re-opens. | 
 |       {L"\x202eكبير Google\x202c\x202cالتطبيق\x202e", | 
 |        L"\x202eكبير Google\x202c\x202cالتطبيق\x202e\x202c"}, | 
 |       // Tests RTL string with multiple dir-formatting characters. | 
 |       {L"\x202eك\x202eبير Google الت\x202eطبيق", | 
 |        L"\x202eك\x202eبير Google الت\x202eطبيق\x202c\x202c\x202c"}, | 
 |       // Test the other dir-formatting characters (U+202A, U+202B, and U+202D). | 
 |       {L"\x202aكبير Google التطبيق", L"\x202aكبير Google التطبيق\x202c"}, | 
 |       {L"\x202bكبير Google التطبيق", L"\x202bكبير Google التطبيق\x202c"}, | 
 |       {L"\x202dكبير Google التطبيق", L"\x202dكبير Google التطبيق\x202c"}, | 
 |  | 
 |   }; | 
 |  | 
 |   for (size_t i = 0; i < arraysize(cases); ++i) { | 
 |     // On Windows for an LTR locale, no changes to the string are made. | 
 |     string16 prefix, suffix = WideToUTF16(L""); | 
 | #if !defined(OS_WIN) | 
 |     prefix = WideToUTF16(L"\x200e\x202b"); | 
 |     suffix = WideToUTF16(L"\x202c\x200e"); | 
 | #endif  // !OS_WIN | 
 |     string16 unsanitized_text = WideToUTF16(cases[i].unformatted_text); | 
 |     string16 sanitized_text = | 
 |         prefix + WideToUTF16(cases[i].formatted_text) + suffix; | 
 |     SanitizeUserSuppliedString(&unsanitized_text); | 
 |     EXPECT_EQ(sanitized_text, unsanitized_text); | 
 |   } | 
 | } | 
 |  | 
 | class SetICULocaleTest : public PlatformTest {}; | 
 |  | 
 | TEST_F(SetICULocaleTest, OverlongLocaleId) { | 
 |   test::ScopedRestoreICUDefaultLocale restore_locale; | 
 |   std::string id("fr-ca-x-foo"); | 
 |   while (id.length() < 152) | 
 |     id.append("-x-foo"); | 
 |   SetICUDefaultLocale(id); | 
 |   EXPECT_STRNE("en_US", icu::Locale::getDefault().getName()); | 
 |   id.append("zzz"); | 
 |   SetICUDefaultLocale(id); | 
 |   EXPECT_STREQ("en_US", icu::Locale::getDefault().getName()); | 
 | } | 
 |  | 
 | }  // namespace i18n | 
 | }  // namespace base |