diff options
Diffstat (limited to 'app/l10n_util_unittest.cc')
-rw-r--r-- | app/l10n_util_unittest.cc | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/app/l10n_util_unittest.cc b/app/l10n_util_unittest.cc new file mode 100644 index 0000000..0ca5608 --- /dev/null +++ b/app/l10n_util_unittest.cc @@ -0,0 +1,435 @@ +// Copyright (c) 2006-2008 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 "build/build_config.h" + +#include "app/l10n_util.h" +#include "base/basictypes.h" +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/stl_util-inl.h" +#include "base/string_util.h" +#if defined(OS_WIN) +#include "base/win_util.h" +#endif +#include "chrome/common/chrome_paths.h" +#if !defined(OS_MACOSX) +#include "chrome/test/data/resource.h" +#endif +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" +#include "unicode/locid.h" + +namespace { + +class StringWrapper { + public: + explicit StringWrapper(const std::wstring& string) : string_(string) {} + const std::wstring& string() const { return string_; } + + private: + std::wstring string_; + + DISALLOW_COPY_AND_ASSIGN(StringWrapper); +}; + +l10n_util::TextDirection GetTextDirection(const char* locale_name) { + return l10n_util::GetTextDirectionForLocale(locale_name); +} + +} // namespace + +class L10nUtilTest : public PlatformTest { +}; + +#if defined(OS_WIN) +TEST_F(L10nUtilTest, GetString) { + std::wstring s = l10n_util::GetString(IDS_SIMPLE); + EXPECT_EQ(std::wstring(L"Hello World!"), s); + + s = l10n_util::GetStringF(IDS_PLACEHOLDERS, L"chrome", L"10"); + EXPECT_EQ(std::wstring(L"Hello, chrome. Your number is 10."), s); + + s = l10n_util::GetStringF(IDS_PLACEHOLDERS_2, 20); + EXPECT_EQ(std::wstring(L"You owe me $20."), s); +} +#endif // defined(OS_WIN) + +TEST_F(L10nUtilTest, TruncateString) { + std::wstring string(L"foooooey bxxxar baz"); + + // Make sure it doesn't modify the string if length > string length. + EXPECT_EQ(string, l10n_util::TruncateString(string, 100)); + + // Test no characters. + EXPECT_EQ(L"", l10n_util::TruncateString(string, 0)); + + // Test 1 character. + EXPECT_EQ(L"\x2026", l10n_util::TruncateString(string, 1)); + + // Test adds ... at right spot when there is enough room to break at a + // word boundary. + EXPECT_EQ(L"foooooey\x2026", l10n_util::TruncateString(string, 14)); + + // Test adds ... at right spot when there is not enough space in first word. + EXPECT_EQ(L"f\x2026", l10n_util::TruncateString(string, 2)); + + // Test adds ... at right spot when there is not enough room to break at a + // word boundary. + EXPECT_EQ(L"foooooey\x2026", l10n_util::TruncateString(string, 11)); + + // Test completely truncates string if break is on initial whitespace. + EXPECT_EQ(L"\x2026", l10n_util::TruncateString(L" ", 2)); +} + +void SetICUDefaultLocale(const std::wstring& locale_string) { + Locale locale(WideToASCII(locale_string).c_str()); + UErrorCode error_code = U_ZERO_ERROR; + Locale::setDefault(locale, error_code); + EXPECT_TRUE(U_SUCCESS(error_code)); +} + +#if defined(OS_WIN) || defined(OS_LINUX) +// We are disabling this test on MacOS because GetApplicationLocale() as an +// API isn't something that we'll easily be able to unit test in this manner. +// The meaning of that API, on the Mac, is "the locale used by Cocoa's main +// nib file", which clearly can't be stubbed by a test app that doesn't use +// Cocoa. +TEST_F(L10nUtilTest, GetAppLocale) { + // Use a temporary locale dir so we don't have to actually build the locale + // dlls for this test. + FilePath orig_locale_dir; + PathService::Get(chrome::DIR_LOCALES, &orig_locale_dir); + FilePath new_locale_dir; + EXPECT_TRUE(file_util::CreateNewTempDirectory( + FILE_PATH_LITERAL("l10n_util_test"), + &new_locale_dir)); + PathService::Override(chrome::DIR_LOCALES, new_locale_dir.ToWStringHack()); + // Make fake locale files. + std::string filenames[] = { + "en-US", + "en-GB", + "fr", + "es-419", + "es", + "zh-TW", + "zh-CN", + "he", + "fil", + "nb", + "or", + }; + +#if defined(OS_WIN) + static const char kLocaleFileExtension[] = ".dll"; +#elif defined(OS_POSIX) + static const char kLocaleFileExtension[] = ".pak"; +#endif + for (size_t i = 0; i < arraysize(filenames); ++i) { + FilePath filename = new_locale_dir.AppendASCII( + filenames[i] + kLocaleFileExtension); + file_util::WriteFile(filename, "", 0); + } + + // Keep a copy of ICU's default locale before we overwrite it. + Locale locale = Locale::getDefault(); + + SetICUDefaultLocale(L"en-US"); + EXPECT_EQ(L"en-US", l10n_util::GetApplicationLocale(L"")); + + SetICUDefaultLocale(L"en-GB"); + EXPECT_EQ(L"en-GB", l10n_util::GetApplicationLocale(L"")); + + SetICUDefaultLocale(L"fr-CA"); + EXPECT_EQ(L"fr", l10n_util::GetApplicationLocale(L"")); + + SetICUDefaultLocale(L"xx"); + EXPECT_EQ(L"en-US", l10n_util::GetApplicationLocale(L"")); + + SetICUDefaultLocale(L"en-US"); + EXPECT_EQ(L"fr", l10n_util::GetApplicationLocale(L"fr")); + EXPECT_EQ(L"fr", l10n_util::GetApplicationLocale(L"fr-CA")); + + SetICUDefaultLocale(L"en-US"); + // Aliases iw, no, tl to he, nb, fil. + EXPECT_EQ(L"he", l10n_util::GetApplicationLocale(L"iw")); + EXPECT_EQ(L"nb", l10n_util::GetApplicationLocale(L"no")); + EXPECT_EQ(L"fil", l10n_util::GetApplicationLocale(L"tl")); + // es-419 and es-XX (where XX is not Spain) should be + // mapped to es-419 (Latin American Spanish). + EXPECT_EQ(L"es-419", l10n_util::GetApplicationLocale(L"es-419")); + EXPECT_EQ(L"es", l10n_util::GetApplicationLocale(L"es-ES")); + EXPECT_EQ(L"es-419", l10n_util::GetApplicationLocale(L"es-AR")); + + SetICUDefaultLocale(L"es-MX"); + EXPECT_EQ(L"es-419", l10n_util::GetApplicationLocale(L"")); + + SetICUDefaultLocale(L"es-AR"); + EXPECT_EQ(L"es-419", l10n_util::GetApplicationLocale(L"")); + EXPECT_EQ(L"es", l10n_util::GetApplicationLocale(L"es")); + + SetICUDefaultLocale(L"es-ES"); + EXPECT_EQ(L"es", l10n_util::GetApplicationLocale(L"")); + + SetICUDefaultLocale(L"es"); + EXPECT_EQ(L"es", l10n_util::GetApplicationLocale(L"")); + + SetICUDefaultLocale(L"zh-HK"); + EXPECT_EQ(L"zh-TW", l10n_util::GetApplicationLocale(L"")); + EXPECT_EQ(L"zh-CN", l10n_util::GetApplicationLocale(L"zh-CN")); + + SetICUDefaultLocale(L"zh-MK"); + EXPECT_EQ(L"zh-TW", l10n_util::GetApplicationLocale(L"")); + + SetICUDefaultLocale(L"zh-SG"); + EXPECT_EQ(L"zh-CN", l10n_util::GetApplicationLocale(L"")); + + SetICUDefaultLocale(L"he"); + EXPECT_EQ(L"en-US", l10n_util::GetApplicationLocale(L"en")); + +#if defined(OS_WIN) + // Oriya should be blocked unless OS is Vista or newer. + if (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) { + SetICUDefaultLocale(L"or"); + EXPECT_EQ(L"en-US", l10n_util::GetApplicationLocale(L"")); + SetICUDefaultLocale(L"en-GB"); + EXPECT_EQ(L"en-GB", l10n_util::GetApplicationLocale(L"or")); + } else { + SetICUDefaultLocale(L"or"); + EXPECT_EQ(L"or", l10n_util::GetApplicationLocale(L"")); + SetICUDefaultLocale(L"en-GB"); + EXPECT_EQ(L"or", l10n_util::GetApplicationLocale(L"or")); + } +#endif + + // Clean up. + PathService::Override(chrome::DIR_LOCALES, orig_locale_dir.ToWStringHack()); + file_util::Delete(new_locale_dir, true); + UErrorCode error_code = U_ZERO_ERROR; + Locale::setDefault(locale, error_code); +} +#endif + +TEST_F(L10nUtilTest, SortStringsUsingFunction) { + std::vector<StringWrapper*> strings; + strings.push_back(new StringWrapper(L"C")); + strings.push_back(new StringWrapper(L"d")); + strings.push_back(new StringWrapper(L"b")); + strings.push_back(new StringWrapper(L"a")); + l10n_util::SortStringsUsingMethod(L"en-US", &strings, &StringWrapper::string); + ASSERT_TRUE(L"a" == strings[0]->string()); + ASSERT_TRUE(L"b" == strings[1]->string()); + ASSERT_TRUE(L"C" == strings[2]->string()); + ASSERT_TRUE(L"d" == strings[3]->string()); + STLDeleteElements(&strings); +} + +TEST_F(L10nUtilTest, GetFirstStrongCharacterDirection) { + // Test pure LTR string. + std::wstring string(L"foo bar"); + EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, + l10n_util::GetFirstStrongCharacterDirection(string)); + + // Test bidi string in which the first character with strong directionality + // is a character with type L. + string.assign(L"foo \x05d0 bar"); + EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, + l10n_util::GetFirstStrongCharacterDirection(string)); + + // Test bidi string in which the first character with strong directionality + // is a character with type R. + string.assign(L"\x05d0 foo bar"); + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, + l10n_util::GetFirstStrongCharacterDirection(string)); + + // 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. + string.assign(L"!foo \x05d0 bar"); + EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, + l10n_util::GetFirstStrongCharacterDirection(string)); + + // 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. + string.assign(L",\x05d0 foo bar"); + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, + l10n_util::GetFirstStrongCharacterDirection(string)); + + // Test bidi string in which the first character with strong directionality + // is a character with type LRE. + string.assign(L"\x202a \x05d0 foo bar"); + EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, + l10n_util::GetFirstStrongCharacterDirection(string)); + + // Test bidi string in which the first character with strong directionality + // is a character with type LRO. + string.assign(L"\x202d \x05d0 foo bar"); + EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, + l10n_util::GetFirstStrongCharacterDirection(string)); + + // Test bidi string in which the first character with strong directionality + // is a character with type RLE. + string.assign(L"\x202b foo \x05d0 bar"); + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, + l10n_util::GetFirstStrongCharacterDirection(string)); + + // Test bidi string in which the first character with strong directionality + // is a character with type RLO. + string.assign(L"\x202e foo \x05d0 bar"); + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, + l10n_util::GetFirstStrongCharacterDirection(string)); + + // Test bidi string in which the first character with strong directionality + // is a character with type AL. + string.assign(L"\x0622 foo \x05d0 bar"); + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, + l10n_util::GetFirstStrongCharacterDirection(string)); + + // Test a string without strong directionality characters. + string.assign(L",!.{}"); + EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, + l10n_util::GetFirstStrongCharacterDirection(string)); + + // Test empty string. + string.assign(L""); + EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, + l10n_util::GetFirstStrongCharacterDirection(string)); + + // 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) + string.assign(L" ! \x10910" L"abc 123"); +#elif defined(WCHAR_T_IS_UTF16) + string.assign(L" ! \xd802\xdd10" L"abc 123"); +#else +#error wchar_t should be either UTF-16 or UTF-32 +#endif + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, + l10n_util::GetFirstStrongCharacterDirection(string)); + +#if defined(WCHAR_T_IS_UTF32) + string.assign(L" ! \x10401" L"abc 123"); +#elif defined(WCHAR_T_IS_UTF16) + string.assign(L" ! \xd801\xdc01" L"abc 123"); +#else +#error wchar_t should be either UTF-16 or UTF-32 +#endif + EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, + l10n_util::GetFirstStrongCharacterDirection(string)); +} + +typedef struct { + std::wstring path; + std::wstring wrapped_path; +} PathAndWrappedPath; + +TEST_F(L10nUtilTest, WrapPathWithLTRFormatting) { + std::wstring kSeparator; + kSeparator.push_back(static_cast<wchar_t>(FilePath::kSeparators[0])); + const PathAndWrappedPath test_data[] = { + // Test common path, such as "c:\foo\bar". + { L"c:" + kSeparator + L"foo" + kSeparator + L"bar", + L"\x202a"L"c:" + kSeparator + L"foo" + kSeparator + + L"bar\x202c" + }, + // Test path with file name, such as "c:\foo\bar\test.jpg". + { L"c:" + kSeparator + L"foo" + kSeparator + L"bar" + kSeparator + + L"test.jpg", + L"\x202a"L"c:" + kSeparator + L"foo" + kSeparator + + L"bar" + kSeparator + L"test.jpg\x202c" + }, + // Test path ending with punctuation, such as "c:\(foo)\bar.". + { L"c:" + kSeparator + L"(foo)" + kSeparator + L"bar.", + L"\x202a"L"c:" + kSeparator + L"(foo)" + kSeparator + + L"bar.\x202c" + }, + // Test path ending with separator, such as "c:\foo\bar\". + { L"c:" + kSeparator + L"foo" + kSeparator + L"bar" + kSeparator, + L"\x202a"L"c:" + kSeparator + L"foo" + kSeparator + + L"bar" + kSeparator + L"\x202c", + }, + // Test path with RTL character. + { L"c:" + kSeparator + L"\x05d0", + L"\x202a"L"c:" + kSeparator + L"\x05d0\x202c", + }, + // Test path with 2 level RTL directory names. + { L"c:" + kSeparator + L"\x05d0" + kSeparator + L"\x0622", + L"\x202a"L"c:" + kSeparator + L"\x05d0" + kSeparator + + L"\x0622\x202c", + }, + // Test path with mixed RTL/LTR directory names and ending with punctuation. + { L"c:" + kSeparator + L"\x05d0" + kSeparator + L"\x0622" + kSeparator + + L"(foo)" + kSeparator + L"b.a.r.", + L"\x202a"L"c:" + kSeparator + L"\x05d0" + kSeparator + + L"\x0622" + kSeparator + L"(foo)" + kSeparator + + L"b.a.r.\x202c", + }, + // Test path without driver name, such as "/foo/bar/test/jpg". + { kSeparator + L"foo" + kSeparator + L"bar" + kSeparator + L"test.jpg", + L"\x202a" + kSeparator + L"foo" + kSeparator + L"bar" + + kSeparator + L"test.jpg" + L"\x202c" + }, + // Test path start with current directory, such as "./foo". + { L"." + kSeparator + L"foo", + L"\x202a"L"." + kSeparator + L"foo" + L"\x202c" + }, + // Test path start with parent directory, such as "../foo/bar.jpg". + { L".." + kSeparator + L"foo" + kSeparator + L"bar.jpg", + L"\x202a"L".." + kSeparator + L"foo" + kSeparator + + L"bar.jpg" + L"\x202c" + }, + // Test absolute path, such as "//foo/bar.jpg". + { kSeparator + kSeparator + L"foo" + kSeparator + L"bar.jpg", + L"\x202a" + kSeparator + kSeparator + L"foo" + kSeparator + + L"bar.jpg" + L"\x202c" + }, + // Test path with mixed RTL/LTR directory names. + { L"c:" + kSeparator + L"foo" + kSeparator + L"\x05d0" + kSeparator + + L"\x0622" + kSeparator + L"\x05d1.jpg", + L"\x202a"L"c:" + kSeparator + L"foo" + kSeparator + L"\x05d0" + + kSeparator + L"\x0622" + kSeparator + L"\x05d1.jpg" + L"\x202c", + }, + // Test empty path. + { L"", + L"\x202a\x202c" + } + }; + for (unsigned int i = 0; i < arraysize(test_data); ++i) { + string16 localized_file_path_string; + FilePath path = FilePath::FromWStringHack(test_data[i].path); + l10n_util::WrapPathWithLTRFormatting(path, &localized_file_path_string); + std::wstring wrapped_path = UTF16ToWide(localized_file_path_string); + EXPECT_EQ(wrapped_path, test_data[i].wrapped_path); + } +} + +TEST_F(L10nUtilTest, GetTextDirection) { + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("ar")); + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("ar_EG")); + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("he")); + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("he_IL")); + // iw is an obsolete code for Hebrew. + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("iw")); +#if 0 + // Enable these when we localize to Farsi, Urdu, Azerbaijani + // written in Arabic and Dhivehi. At the moment, our copy of + // ICU data does not have entry for them. + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("fa")); + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("ur")); + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("az_Arab")); + // Dhivehi that uses Thaana script. + EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("dv")); +#endif + EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, GetTextDirection("en")); + // Chinese in China with '-'. + EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, GetTextDirection("zh-CN")); + // Filipino : 3-letter code + EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, GetTextDirection("fil")); + // Russian + EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, GetTextDirection("ru")); + // Japanese that uses multiple scripts + EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, GetTextDirection("ja")); +} |