language_selector_unittest.cc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // Copyright 2018 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. #include <string>
  5. #include <tuple>
  6. #include <vector>
  7. #include "base/test/gtest_util.h"
  8. #include "base/win/embedded_i18n/language_selector.h"
  9. #include "testing/gtest/include/gtest/gtest.h"
  10. namespace base {
  11. namespace win {
  12. namespace i18n {
  13. namespace {
  14. constexpr const wchar_t* kExactMatchCandidates[] = {
  15. L"am", L"ar", L"bg", L"bn", L"ca", L"cs", L"da", L"de",
  16. L"el", L"en-gb", L"en-us", L"es", L"es-419", L"et", L"fa", L"fi",
  17. L"fil", L"fr", L"gu", L"hi", L"hr", L"hu", L"id", L"it",
  18. L"iw", L"ja", L"kn", L"ko", L"lt", L"lv", L"ml", L"mr",
  19. L"nl", L"no", L"pl", L"pt-br", L"pt-pt", L"ro", L"ru", L"sk",
  20. L"sl", L"sr", L"sv", L"sw", L"ta", L"te", L"th", L"tr",
  21. L"uk", L"vi", L"zh-cn", L"zh-tw"};
  22. constexpr const wchar_t* kAliasMatchCandidates[] = {
  23. L"he", L"nb", L"tl", L"zh-chs", L"zh-cht",
  24. L"zh-hans", L"zh-hant", L"zh-hk", L"zh-mo"};
  25. constexpr const wchar_t* kWildcardMatchCandidates[] = {L"en-AU", L"es-CO",
  26. L"pt-AB", L"zh-SG"};
  27. std::vector<LanguageSelector::LangToOffset> MakeLanguageOffsetPairs() {
  28. std::vector<LanguageSelector::LangToOffset> language_offset_pairs;
  29. int i = 0;
  30. for (const wchar_t* lang : kExactMatchCandidates) {
  31. language_offset_pairs.emplace_back(lang, i++);
  32. }
  33. return language_offset_pairs;
  34. }
  35. class TestLanguageSelector : public LanguageSelector {
  36. public:
  37. TestLanguageSelector() : TestLanguageSelector(std::vector<std::wstring>()) {}
  38. explicit TestLanguageSelector(const std::vector<std::wstring>& candidates)
  39. : TestLanguageSelector(candidates, MakeLanguageOffsetPairs()) {}
  40. TestLanguageSelector(
  41. const std::vector<std::wstring>& candidates,
  42. span<const LanguageSelector::LangToOffset> languages_to_offset)
  43. : LanguageSelector(candidates, languages_to_offset) {}
  44. };
  45. } // namespace
  46. // Test that a language is selected from the system.
  47. TEST(LanguageSelectorTest, DefaultSelection) {
  48. TestLanguageSelector instance;
  49. EXPECT_FALSE(instance.matched_candidate().empty());
  50. }
  51. // Test some hypothetical candidate sets.
  52. TEST(LanguageSelectorTest, AssortedSelections) {
  53. {
  54. std::vector<std::wstring> candidates = {L"fr-BE", L"fr", L"en"};
  55. TestLanguageSelector instance(candidates);
  56. // Expect the exact match to win.
  57. EXPECT_EQ(L"fr", instance.matched_candidate());
  58. }
  59. {
  60. std::vector<std::wstring> candidates = {L"xx-YY", L"cc-Ssss-RR"};
  61. TestLanguageSelector instance(candidates);
  62. // Expect the fallback to win.
  63. EXPECT_EQ(L"en-us", instance.matched_candidate());
  64. }
  65. {
  66. std::vector<std::wstring> candidates = {L"zh-SG", L"en-GB"};
  67. TestLanguageSelector instance(candidates);
  68. // Expect the alias match to win.
  69. EXPECT_EQ(L"zh-SG", instance.matched_candidate());
  70. }
  71. }
  72. // A fixture for testing sets of single-candidate selections.
  73. class LanguageSelectorMatchCandidateTest
  74. : public ::testing::TestWithParam<const wchar_t*> {};
  75. TEST_P(LanguageSelectorMatchCandidateTest, TestMatchCandidate) {
  76. TestLanguageSelector instance({GetParam()});
  77. EXPECT_EQ(GetParam(), instance.matched_candidate());
  78. }
  79. // Test that all existing translations can be found by exact match.
  80. INSTANTIATE_TEST_SUITE_P(TestExactMatches,
  81. LanguageSelectorMatchCandidateTest,
  82. ::testing::ValuesIn(kExactMatchCandidates));
  83. // Test the alias matches.
  84. INSTANTIATE_TEST_SUITE_P(TestAliasMatches,
  85. LanguageSelectorMatchCandidateTest,
  86. ::testing::ValuesIn(kAliasMatchCandidates));
  87. // Test a few wildcard matches.
  88. INSTANTIATE_TEST_SUITE_P(TestWildcardMatches,
  89. LanguageSelectorMatchCandidateTest,
  90. ::testing::ValuesIn(kWildcardMatchCandidates));
  91. // A fixture for testing aliases that match to an expected translation. The
  92. // first member of the tuple is the expected translation, the second is a
  93. // candidate that should be aliased to the expectation.
  94. class LanguageSelectorAliasTest
  95. : public ::testing::TestWithParam<
  96. std::tuple<const wchar_t*, const wchar_t*>> {};
  97. // Test that the candidate language maps to the aliased translation.
  98. TEST_P(LanguageSelectorAliasTest, AliasesMatch) {
  99. TestLanguageSelector instance({std::get<1>(GetParam())});
  100. EXPECT_EQ(std::get<0>(GetParam()), instance.selected_translation());
  101. }
  102. INSTANTIATE_TEST_SUITE_P(EnGbAliases,
  103. LanguageSelectorAliasTest,
  104. ::testing::Combine(::testing::Values(L"en-gb"),
  105. ::testing::Values(L"en-au",
  106. L"en-ca",
  107. L"en-nz",
  108. L"en-za")));
  109. INSTANTIATE_TEST_SUITE_P(IwAliases,
  110. LanguageSelectorAliasTest,
  111. ::testing::Combine(::testing::Values(L"iw"),
  112. ::testing::Values(L"he")));
  113. INSTANTIATE_TEST_SUITE_P(NoAliases,
  114. LanguageSelectorAliasTest,
  115. ::testing::Combine(::testing::Values(L"no"),
  116. ::testing::Values(L"nb")));
  117. INSTANTIATE_TEST_SUITE_P(FilAliases,
  118. LanguageSelectorAliasTest,
  119. ::testing::Combine(::testing::Values(L"fil"),
  120. ::testing::Values(L"tl")));
  121. INSTANTIATE_TEST_SUITE_P(
  122. ZhCnAliases,
  123. LanguageSelectorAliasTest,
  124. ::testing::Combine(::testing::Values(L"zh-cn"),
  125. ::testing::Values(L"zh-chs", L"zh-hans", L"zh-sg")));
  126. INSTANTIATE_TEST_SUITE_P(ZhTwAliases,
  127. LanguageSelectorAliasTest,
  128. ::testing::Combine(::testing::Values(L"zh-tw"),
  129. ::testing::Values(L"zh-cht",
  130. L"zh-hant",
  131. L"zh-hk",
  132. L"zh-mo")));
  133. // Test that we can get a match of the default language.
  134. TEST(LanguageSelectorTest, DefaultLanguageName) {
  135. TestLanguageSelector instance;
  136. EXPECT_FALSE(instance.selected_translation().empty());
  137. }
  138. // All languages given to the selector must be lower cased (since generally
  139. // the language names are generated by a python script).
  140. TEST(LanguageSelectorTest, InvalidLanguageCasing) {
  141. constexpr LanguageSelector::LangToOffset kLangToOffset[] = {{L"en-US", 0}};
  142. EXPECT_DCHECK_DEATH(LanguageSelector instance(
  143. std::vector<std::wstring>({L"en-us"}), kLangToOffset));
  144. }
  145. // Language name and offset pairs must be ordered when generated by the
  146. // python script.
  147. TEST(LanguageSelectorTest, InvalidLanguageNameOrder) {
  148. constexpr LanguageSelector::LangToOffset kLangToOffset[] = {{L"en-us", 0},
  149. {L"en-gb", 1}};
  150. EXPECT_DCHECK_DEATH(LanguageSelector instance(
  151. std::vector<std::wstring>({L"en-us"}), kLangToOffset));
  152. }
  153. // There needs to be a fallback language available in the generated
  154. // languages if ever the selector is given a language that does not exist.
  155. TEST(LanguageSelectorTest, NoFallbackLanguageAvailable) {
  156. constexpr LanguageSelector::LangToOffset kLangToOffset[] = {{L"en-gb", 0}};
  157. EXPECT_DCHECK_DEATH(LanguageSelector instance(
  158. std::vector<std::wstring>({L"aa-bb"}), kLangToOffset));
  159. }
  160. // No languages available.
  161. TEST(LanguageSelectorTest, NoLanguagesAvailable) {
  162. EXPECT_DCHECK_DEATH(
  163. LanguageSelector instance(std::vector<std::wstring>({L"en-us"}), {}));
  164. }
  165. } // namespace i18n
  166. } // namespace win
  167. } // namespace base