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