1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.app;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNull;
21 import static org.junit.Assert.assertTrue;
22 
23 import android.os.LocaleList;
24 import android.view.inputmethod.InputMethodSubtype;
25 import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
26 
27 import androidx.test.filters.SmallTest;
28 import androidx.test.runner.AndroidJUnit4;
29 
30 import com.android.internal.app.LocaleStore.LocaleInfo;
31 
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 
35 import java.util.ArrayList;
36 import java.util.Collection;
37 import java.util.HashMap;
38 import java.util.HashSet;
39 import java.util.IllformedLocaleException;
40 import java.util.List;
41 import java.util.Locale;
42 import java.util.Set;
43 
44 /** Unit tests for the {@link LocaleStore}. */
45 @SmallTest
46 @RunWith(AndroidJUnit4.class)
47 public class LocaleStoreTest {
48     @Test
testTransformImeLanguageTagToLocaleInfo()49     public void testTransformImeLanguageTagToLocaleInfo() {
50         List<InputMethodSubtype> list = List.of(
51                 new InputMethodSubtypeBuilder().setLanguageTag("en-US").build(),
52                 new InputMethodSubtypeBuilder().setLanguageTag("zh-TW").build(),
53                 new InputMethodSubtypeBuilder().setLanguageTag("ja-JP").build());
54 
55         Set<LocaleInfo> localeSet = LocaleStore.transformImeLanguageTagToLocaleInfo(list);
56 
57         Set<String> expectedLanguageTag = Set.of("en-US", "zh-TW", "ja-JP");
58         assertEquals(localeSet.size(), expectedLanguageTag.size());
59         for (LocaleInfo info : localeSet) {
60             assertEquals(info.mSuggestionFlags, LocaleInfo.SUGGESTION_TYPE_IME_LANGUAGE);
61             assertTrue(expectedLanguageTag.contains(info.getId()));
62         }
63     }
64 
65     @Test
testTransformImeLanguageTagToLocaleInfo_duplicateTagFilter()66     public void testTransformImeLanguageTagToLocaleInfo_duplicateTagFilter() {
67         List<InputMethodSubtype> list = List.of(
68                 new InputMethodSubtypeBuilder().setLanguageTag("en-US").build(),
69                 new InputMethodSubtypeBuilder().setLanguageTag("en-US").build(),
70                 new InputMethodSubtypeBuilder().setLanguageTag("en-US").build(),
71                 new InputMethodSubtypeBuilder().setLanguageTag("zh-TW").build(),
72                 new InputMethodSubtypeBuilder().setLanguageTag("ja-JP").build());
73 
74         Set<LocaleInfo> localeSet = LocaleStore.transformImeLanguageTagToLocaleInfo(list);
75 
76         Set<String> expectedLanguageTag = Set.of("en-US", "zh-TW", "ja-JP");
77         assertEquals(localeSet.size(), expectedLanguageTag.size());
78         for (LocaleInfo info : localeSet) {
79             assertEquals(info.mSuggestionFlags, LocaleInfo.SUGGESTION_TYPE_IME_LANGUAGE);
80             assertTrue(expectedLanguageTag.contains(info.getId()));
81         }
82     }
83 
84     @Test
convertExplicitLocales_noExplicitLcoales_returnEmptyHashMap()85     public void convertExplicitLocales_noExplicitLcoales_returnEmptyHashMap() {
86         Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
87 
88         HashMap<String, LocaleInfo> result =
89                 LocaleStore.convertExplicitLocales(
90                         LocaleList.getEmptyLocaleList(), supportedLocale);
91 
92         assertTrue(result.isEmpty());
93     }
94 
95     @Test
convertExplicitLocales_hasEmptyLocale_receiveException()96     public void convertExplicitLocales_hasEmptyLocale_receiveException() {
97         Locale[] locales = {Locale.forLanguageTag(""), Locale.forLanguageTag("en-US")};
98         LocaleList localelist = new LocaleList(locales);
99         Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
100 
101         boolean isReceiveException = false;
102         try {
103             LocaleStore.convertExplicitLocales(localelist, supportedLocale);
104         } catch (IllformedLocaleException e) {
105             isReceiveException = true;
106         }
107 
108         assertTrue(isReceiveException);
109     }
110 
111     @Test
convertExplicitLocales_hasSameLocale_returnNonSameLocales()112     public void convertExplicitLocales_hasSameLocale_returnNonSameLocales() {
113         LocaleList locales = LocaleList.forLanguageTags("en-US,en-US");
114         Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
115 
116         HashMap<String, LocaleInfo> result =
117                 LocaleStore.convertExplicitLocales(locales, supportedLocale);
118 
119         // Only has "en" and "en-US".
120         assertTrue(result.size() == 2);
121     }
122 
123     @Test
convertExplicitLocales_hasEnUs_resultHasParentEn()124     public void convertExplicitLocales_hasEnUs_resultHasParentEn() {
125         LocaleList locales = LocaleList.forLanguageTags("en-US,ja-JP");
126         Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
127 
128         HashMap<String, LocaleInfo> result =
129                 LocaleStore.convertExplicitLocales(locales, supportedLocale);
130 
131         assertEquals(result.get("en").getId(), "en");
132     }
133 
134     @Test
convertExplicitLocales_hasZhTw_resultZhHantTw()135     public void convertExplicitLocales_hasZhTw_resultZhHantTw() {
136         LocaleList locales = LocaleList.forLanguageTags("zh-TW,en-US,en");
137         Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
138 
139         HashMap<String, LocaleInfo> result =
140                 LocaleStore.convertExplicitLocales(locales, supportedLocale);
141 
142         assertEquals("zh-Hant-TW", result.get("zh-Hant-TW").getId());
143     }
144 
145     @Test
convertExplicitLocales_nonRegularFormat_resultEmptyContry()146     public void convertExplicitLocales_nonRegularFormat_resultEmptyContry() {
147         LocaleList locales = LocaleList.forLanguageTags("de-1996,de-1901");
148         Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
149 
150         HashMap<String, LocaleInfo> result =
151                 LocaleStore.convertExplicitLocales(locales, supportedLocale);
152 
153         assertEquals("de-1996", result.get("de-1996").getId());
154         assertTrue(result.get("de-1996").getLocale().getCountry().isEmpty());
155     }
156 
157     @Test
convertExplicitLocales_differentEnFormat()158     public void convertExplicitLocales_differentEnFormat() {
159         LocaleList locales = LocaleList.forLanguageTags("en-Latn-US,en-US,en");
160         Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
161 
162         HashMap<String, LocaleInfo> result =
163                 LocaleStore.convertExplicitLocales(locales, supportedLocale);
164         assertEquals("en", result.get("en").getId());
165         assertEquals("en-US", result.get("en-US").getId());
166         assertNull(result.get("en-Latn-US"));
167     }
168 
169     @Test
getLevelLocales_languageTier_returnAllSupportLanguages()170     public void getLevelLocales_languageTier_returnAllSupportLanguages() {
171         LocaleList testSupportedLocales =
172                 LocaleList.forLanguageTags(
173                         "en-US,zh-Hant-TW,ja-JP,en-GB,bn-IN-u-nu-arab,ks-Arab-IN,bn-IN");
174 
175         Set<String> ignorableLocales = new HashSet<>();
176         ignorableLocales.add("zh-Hant-HK");
177         LocaleInfo parent = null;
178 
179         Set<LocaleInfo> localeInfos = LocaleStore.getLevelLocales(
180                 null, ignorableLocales, parent, false, testSupportedLocales);
181 
182         assertEquals(5, localeInfos.size());
183         localeInfos.forEach(localeInfo -> {
184             assertTrue(localeInfo.getLocale().getCountry().isEmpty());
185         });
186         assertTrue(localeInfos.stream().anyMatch(
187                 info -> info.getLocale().toLanguageTag().equals("en")));
188         assertTrue(localeInfos.stream().anyMatch(
189                 info -> info.getLocale().toLanguageTag().equals("zh-Hant")));
190         assertTrue(localeInfos.stream().anyMatch(
191                 info -> info.getLocale().toLanguageTag().equals("ja")));
192         assertTrue(localeInfos.stream().anyMatch(
193                 info -> info.getLocale().toLanguageTag().equals("bn")));
194         assertTrue(localeInfos.stream().anyMatch(
195                 info -> info.getLocale().toLanguageTag().equals("ks-Arab")));
196     }
197 
198     @Test
getLevelLocales_regionTierAndParentIsEn_returnEnLocales()199     public void getLevelLocales_regionTierAndParentIsEn_returnEnLocales() {
200         LocaleList testSupportedLocales =
201                 LocaleList.forLanguageTags(
202                         "en-US,en-GB,bn-IN-u-nu-arab,ks-Arab-IN,en-ZA,bn-IN");
203         Set<String> ignorableLocales = new HashSet<>();
204         ignorableLocales.add("zh-Hant-HK");
205         LocaleInfo parent = LocaleStore.fromLocale(Locale.forLanguageTag("en"));
206 
207         Set<LocaleInfo> localeInfos = LocaleStore.getLevelLocales(
208                 null, ignorableLocales, parent, false, testSupportedLocales);
209 
210         assertEquals(3, localeInfos.size());
211         localeInfos.forEach(localeInfo -> {
212             assertEquals("en", localeInfo.getLocale().getLanguage());
213         });
214         assertTrue(localeInfos.stream().anyMatch(
215                 info -> info.getLocale().toLanguageTag().equals("en-US")));
216         assertTrue(localeInfos.stream().anyMatch(
217                 info -> info.getLocale().toLanguageTag().equals("en-GB")));
218         assertTrue(localeInfos.stream().anyMatch(
219                 info -> info.getLocale().toLanguageTag().equals("en-ZA")));
220     }
221 
222     @Test
getLevelLocales_numberingTierAndParentIsBnIn_returnBnInLocales()223     public void getLevelLocales_numberingTierAndParentIsBnIn_returnBnInLocales() {
224         LocaleList testSupportedLocales =
225                 LocaleList.forLanguageTags(
226                         "en-US,zh-Hant-TW,bn-IN-u-nu-arab,ks-Arab-IN,en-ZA,bn-IN,bn-IN-u-nu-adlm");
227         Set<String> ignorableLocales = new HashSet<>();
228         ignorableLocales.add("zh-Hant-HK");
229         LocaleInfo parent = LocaleStore.fromLocale(Locale.forLanguageTag("bn"));
230 
231         Set<LocaleInfo> localeInfos = LocaleStore.getLevelLocales(
232                 null, ignorableLocales, parent, false, testSupportedLocales);
233 
234         assertEquals(1, localeInfos.size());
235         assertEquals("bn-IN", localeInfos.iterator().next().getLocale().toLanguageTag());
236     }
237 
238     @Test
getLevelLocales_regionTierAndParentIsBnInAndIgnoreBn_returnEmpty()239     public void getLevelLocales_regionTierAndParentIsBnInAndIgnoreBn_returnEmpty() {
240         LocaleList testSupportedLocales =
241                 LocaleList.forLanguageTags(
242                         "en-US,zh-Hant-TW,bn-IN-u-nu-arab,ks-Arab-IN,en-ZA,bn-IN,bn-IN-u-nu-adlm");
243         Set<String> ignorableLocales = new HashSet<>();
244         ignorableLocales.add("bn-IN");
245         LocaleInfo parent = LocaleStore.fromLocale(Locale.forLanguageTag("bn-IN"));
246 
247         Set<LocaleInfo> localeInfos = LocaleStore.getLevelLocales(
248                 null, ignorableLocales, parent, false, testSupportedLocales);
249 
250         assertEquals(0, localeInfos.size());
251     }
252 
253     @Test
getLevelLocales_regionTierAndParentIsBnIn_returnBnLocaleFamily()254     public void getLevelLocales_regionTierAndParentIsBnIn_returnBnLocaleFamily() {
255         LocaleList testSupportedLocales =
256                 LocaleList.forLanguageTags(
257                         "en-US,zh-Hant-TW,bn-IN-u-nu-arab,ks-Arab-IN,en-ZA,bn-IN,bn-IN-u-nu-adlm");
258         Set<String> ignorableLocales = new HashSet<>();
259         ignorableLocales.add("en-US");
260         LocaleInfo parent = LocaleStore.fromLocale(Locale.forLanguageTag("bn-IN"));
261 
262         Set<LocaleInfo> localeInfos = LocaleStore.getLevelLocales(
263                 null, ignorableLocales, parent, false, testSupportedLocales);
264 
265         assertEquals(3, localeInfos.size());
266         assertTrue(localeInfos.stream().anyMatch(
267                 info -> info.getLocale().toLanguageTag().equals("bn-IN-u-nu-adlm")));
268         assertTrue(localeInfos.stream().anyMatch(
269                 info -> info.getLocale().toLanguageTag().equals("bn-IN-u-nu-arab")));
270         assertTrue(localeInfos.stream().anyMatch(
271                 info -> info.getLocale().toLanguageTag().equals("bn-IN")));
272     }
273 
getFakeSupportedLocales()274     private ArrayList<LocaleInfo> getFakeSupportedLocales() {
275         String[] locales = {"en-US", "zh-Hant-TW", "ja-JP", "en-GB", "en-US-u-nu-arab"};
276         ArrayList<LocaleInfo> supportedLocales = new ArrayList<>();
277         for (String localeTag : locales) {
278             supportedLocales.add(LocaleStore.fromLocale(Locale.forLanguageTag(localeTag)));
279         }
280         return supportedLocales;
281     }
282 }
283