1 /* 2 * Copyright (C) 2016 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.server.inputmethod; 18 19 import static org.junit.Assert.assertEquals; 20 21 import android.os.LocaleList; 22 23 import androidx.test.filters.SmallTest; 24 import androidx.test.runner.AndroidJUnit4; 25 26 import org.junit.Test; 27 import org.junit.runner.RunWith; 28 29 import java.util.ArrayList; 30 import java.util.Locale; 31 32 @SmallTest 33 @RunWith(AndroidJUnit4.class) 34 public class LocaleUtilsTest { 35 36 private static final LocaleUtils.LocaleExtractor<Locale> sIdentityMapper = source -> source; 37 38 @Test testFilterByLanguageEmptyLanguageList()39 public void testFilterByLanguageEmptyLanguageList() throws Exception { 40 final ArrayList<Locale> availableLocales = new ArrayList<>(); 41 availableLocales.add(Locale.forLanguageTag("en-US")); 42 availableLocales.add(Locale.forLanguageTag("fr-CA")); 43 availableLocales.add(Locale.forLanguageTag("in")); 44 availableLocales.add(Locale.forLanguageTag("ja")); 45 availableLocales.add(Locale.forLanguageTag("fil")); 46 47 final LocaleList preferredLocales = LocaleList.getEmptyLocaleList(); 48 49 final ArrayList<Locale> dest = new ArrayList<>(); 50 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 51 assertEquals(0, dest.size()); 52 } 53 54 @Test testFilterDoesNotMatchAnything()55 public void testFilterDoesNotMatchAnything() throws Exception { 56 final ArrayList<Locale> availableLocales = new ArrayList<>(); 57 availableLocales.add(Locale.forLanguageTag("en-US")); 58 availableLocales.add(Locale.forLanguageTag("fr-CA")); 59 availableLocales.add(Locale.forLanguageTag("in")); 60 availableLocales.add(Locale.forLanguageTag("ja")); 61 availableLocales.add(Locale.forLanguageTag("fil")); 62 63 final LocaleList preferredLocales = LocaleList.forLanguageTags("zh-Hans-TW"); 64 65 final ArrayList<Locale> dest = new ArrayList<>(); 66 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 67 assertEquals(0, dest.size()); 68 } 69 70 @Test testFilterByLanguageEmptySource()71 public void testFilterByLanguageEmptySource() throws Exception { 72 final ArrayList<Locale> availableLocales = new ArrayList<>(); 73 74 final LocaleList preferredLocales = LocaleList.forLanguageTags("fr,en-US,ja-JP"); 75 76 final ArrayList<Locale> dest = new ArrayList<>(); 77 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 78 assertEquals(0, dest.size()); 79 } 80 81 @Test testFilterByLanguageNullAvailableLocales()82 public void testFilterByLanguageNullAvailableLocales() throws Exception { 83 { 84 final LocaleList preferredLocales = 85 LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN"); 86 final ArrayList<Locale> availableLocales = new ArrayList<>(); 87 availableLocales.add(null); 88 final ArrayList<Locale> dest = new ArrayList<>(); 89 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 90 assertEquals(0, dest.size()); 91 } 92 { 93 final LocaleList preferredLocales = 94 LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN"); 95 final ArrayList<Locale> availableLocales = new ArrayList<>(); 96 availableLocales.add(null); 97 availableLocales.add(null); 98 availableLocales.add(null); 99 final ArrayList<Locale> dest = new ArrayList<>(); 100 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 101 assertEquals(0, dest.size()); 102 } 103 { 104 final LocaleList preferredLocales = 105 LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN"); 106 final ArrayList<Locale> availableLocales = new ArrayList<>(); 107 availableLocales.add(null); 108 availableLocales.add(Locale.forLanguageTag("en-US")); 109 availableLocales.add(null); 110 availableLocales.add(null); 111 final ArrayList<Locale> dest = new ArrayList<>(); 112 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 113 assertEquals(1, dest.size()); 114 assertEquals(availableLocales.get(1), dest.get(0)); // "en-US" 115 } 116 { 117 final LocaleList preferredLocales = 118 LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN"); 119 final ArrayList<Locale> availableLocales = new ArrayList<>(); 120 availableLocales.add(null); 121 availableLocales.add(Locale.forLanguageTag("en")); 122 availableLocales.add(null); 123 availableLocales.add(null); 124 final ArrayList<Locale> dest = new ArrayList<>(); 125 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 126 assertEquals(1, dest.size()); 127 assertEquals(availableLocales.get(1), dest.get(0)); // "en" 128 } 129 { 130 final LocaleList preferredLocales = 131 LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN"); 132 final ArrayList<Locale> availableLocales = new ArrayList<>(); 133 availableLocales.add(null); 134 availableLocales.add(Locale.forLanguageTag("ja-JP")); 135 availableLocales.add(null); 136 availableLocales.add(null); 137 final ArrayList<Locale> dest = new ArrayList<>(); 138 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 139 assertEquals(0, dest.size()); 140 } 141 } 142 143 @Test testFilterByLanguage()144 public void testFilterByLanguage() throws Exception { 145 { 146 final ArrayList<Locale> availableLocales = new ArrayList<>(); 147 availableLocales.add(Locale.forLanguageTag("en-US")); 148 availableLocales.add(Locale.forLanguageTag("fr-CA")); 149 availableLocales.add(Locale.forLanguageTag("in")); 150 availableLocales.add(Locale.forLanguageTag("ja")); 151 availableLocales.add(Locale.forLanguageTag("fil")); 152 153 final LocaleList preferredLocales = LocaleList.forLanguageTags("fr,en-US,ja-JP"); 154 155 final ArrayList<Locale> dest = new ArrayList<>(); 156 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 157 assertEquals(3, dest.size()); 158 assertEquals(availableLocales.get(1), dest.get(0)); // "fr-CA" 159 assertEquals(availableLocales.get(0), dest.get(1)); // "en-US" 160 assertEquals(availableLocales.get(3), dest.get(2)); // "ja" 161 } 162 { 163 final ArrayList<Locale> availableLocales = new ArrayList<>(); 164 availableLocales.add(Locale.forLanguageTag("en-US")); 165 availableLocales.add(Locale.forLanguageTag("en-GB")); 166 availableLocales.add(Locale.forLanguageTag("en-IN")); 167 168 final LocaleList preferredLocales = LocaleList.forLanguageTags("en-US"); 169 170 final ArrayList<Locale> dest = new ArrayList<>(); 171 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 172 assertEquals(1, dest.size()); 173 assertEquals(availableLocales.get(0), dest.get(0)); // "en-US" 174 } 175 } 176 177 @Test testFilterByLanguageTheSameLanguage()178 public void testFilterByLanguageTheSameLanguage() throws Exception { 179 { 180 final LocaleList preferredLocales = 181 LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN"); 182 final ArrayList<Locale> availableLocales = new ArrayList<>(); 183 availableLocales.add(Locale.forLanguageTag("fr-CA")); 184 availableLocales.add(Locale.forLanguageTag("en-US")); 185 final ArrayList<Locale> dest = new ArrayList<>(); 186 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 187 assertEquals(1, dest.size()); 188 assertEquals(availableLocales.get(1), dest.get(0)); // "en-US" 189 } 190 { 191 final LocaleList preferredLocales = 192 LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN"); 193 final ArrayList<Locale> availableLocales = new ArrayList<>(); 194 availableLocales.add(Locale.forLanguageTag("fr-CA")); 195 availableLocales.add(Locale.forLanguageTag("en")); 196 final ArrayList<Locale> dest = new ArrayList<>(); 197 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 198 assertEquals(1, dest.size()); 199 assertEquals(availableLocales.get(1), dest.get(0)); // "en" 200 } 201 { 202 final LocaleList preferredLocales = 203 LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN"); 204 final ArrayList<Locale> availableLocales = new ArrayList<>(); 205 availableLocales.add(Locale.forLanguageTag("fr-CA")); 206 availableLocales.add(Locale.forLanguageTag("en-CA")); 207 availableLocales.add(Locale.forLanguageTag("en-IN")); 208 final ArrayList<Locale> dest = new ArrayList<>(); 209 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 210 assertEquals(1, dest.size()); 211 assertEquals(availableLocales.get(2), dest.get(0)); // "en-IN" 212 } 213 { 214 final LocaleList preferredLocales = 215 LocaleList.forLanguageTags("en-AU,en-GB,en-US,en-IN"); 216 final ArrayList<Locale> availableLocales = new ArrayList<>(); 217 availableLocales.add(Locale.forLanguageTag("fr-CA")); 218 availableLocales.add(Locale.forLanguageTag("en-CA")); 219 availableLocales.add(Locale.forLanguageTag("en-NZ")); 220 availableLocales.add(Locale.forLanguageTag("en-BZ")); 221 final ArrayList<Locale> dest = new ArrayList<>(); 222 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 223 assertEquals(1, dest.size()); 224 assertEquals(availableLocales.get(1), dest.get(0)); // "en-CA" 225 } 226 } 227 228 @Test testFilterByLanguageFallbackRules()229 public void testFilterByLanguageFallbackRules() throws Exception { 230 { 231 final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-Latn-RS"); 232 final ArrayList<Locale> availableLocales = new ArrayList<>(); 233 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-BA")); 234 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-CS")); 235 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-ME")); 236 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-RS")); 237 availableLocales.add(Locale.forLanguageTag("sr-Latn-BA")); 238 availableLocales.add(Locale.forLanguageTag("sr-Latn-CS")); 239 availableLocales.add(Locale.forLanguageTag("sr-Latn-ME")); 240 availableLocales.add(Locale.forLanguageTag("sr-Latn-RS")); 241 final ArrayList<Locale> dest = new ArrayList<>(); 242 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 243 assertEquals(1, dest.size()); 244 assertEquals(availableLocales.get(7), dest.get(0)); // "sr-Latn-RS" 245 } 246 { 247 final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-Latn-RS-x-android"); 248 final ArrayList<Locale> availableLocales = new ArrayList<>(); 249 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-BA")); 250 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-CS")); 251 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-ME")); 252 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-RS")); 253 availableLocales.add(Locale.forLanguageTag("sr-Latn-BA")); 254 availableLocales.add(Locale.forLanguageTag("sr-Latn-CS")); 255 availableLocales.add(Locale.forLanguageTag("sr-Latn-ME")); 256 availableLocales.add(Locale.forLanguageTag("sr-Latn-RS")); 257 final ArrayList<Locale> dest = new ArrayList<>(); 258 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 259 assertEquals(1, dest.size()); 260 assertEquals(availableLocales.get(7), dest.get(0)); // "sr-Latn-RS" 261 } 262 { 263 final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-Latn-RS"); 264 final ArrayList<Locale> availableLocales = new ArrayList<>(); 265 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-BA-x-android")); 266 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-CS-x-android")); 267 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-ME-x-android")); 268 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-RS-x-android")); 269 availableLocales.add(Locale.forLanguageTag("sr-Latn-BA-x-android")); 270 availableLocales.add(Locale.forLanguageTag("sr-Latn-CS-x-android")); 271 availableLocales.add(Locale.forLanguageTag("sr-Latn-ME-x-android")); 272 availableLocales.add(Locale.forLanguageTag("sr-Latn-RS-x-android")); 273 final ArrayList<Locale> dest = new ArrayList<>(); 274 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 275 assertEquals(1, dest.size()); 276 assertEquals(availableLocales.get(7), dest.get(0)); // "sr-Latn-RS-x-android" 277 } 278 279 { 280 final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-Latn-RS"); 281 final ArrayList<Locale> availableLocales = new ArrayList<>(); 282 availableLocales.add(Locale.forLanguageTag("sr")); 283 availableLocales.add(Locale.forLanguageTag("sr-Cyrl")); 284 availableLocales.add(Locale.forLanguageTag("sr-Latn")); 285 final ArrayList<Locale> dest = new ArrayList<>(); 286 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 287 assertEquals(1, dest.size()); 288 assertEquals(availableLocales.get(2), dest.get(0)); // "sr-Latn" 289 } 290 291 { 292 final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-RS"); 293 final ArrayList<Locale> availableLocales = new ArrayList<>(); 294 availableLocales.add(Locale.forLanguageTag("sr")); 295 availableLocales.add(Locale.forLanguageTag("sr-RS")); 296 availableLocales.add(Locale.forLanguageTag("sr-Latn")); 297 final ArrayList<Locale> dest = new ArrayList<>(); 298 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 299 assertEquals(1, dest.size()); 300 assertEquals(availableLocales.get(0), dest.get(0)); // "sr" 301 } 302 303 { 304 final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-Latn"); 305 final ArrayList<Locale> availableLocales = new ArrayList<>(); 306 availableLocales.add(Locale.forLanguageTag("sr")); 307 availableLocales.add(Locale.forLanguageTag("sr-RS")); 308 availableLocales.add(Locale.forLanguageTag("sr-Latn")); 309 final ArrayList<Locale> dest = new ArrayList<>(); 310 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 311 assertEquals(1, dest.size()); 312 assertEquals(availableLocales.get(2), dest.get(0)); // "sr-Latn" 313 } 314 315 { 316 final LocaleList preferredLocales = LocaleList.forLanguageTags("sr"); 317 final ArrayList<Locale> availableLocales = new ArrayList<>(); 318 availableLocales.add(Locale.forLanguageTag("sr")); 319 availableLocales.add(Locale.forLanguageTag("sr-RS")); 320 availableLocales.add(Locale.forLanguageTag("sr-Latn")); 321 final ArrayList<Locale> dest = new ArrayList<>(); 322 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 323 assertEquals(1, dest.size()); 324 assertEquals(availableLocales.get(0), dest.get(0)); // "sr" 325 } 326 { 327 final LocaleList preferredLocales = LocaleList.forLanguageTags("sr"); 328 final ArrayList<Locale> availableLocales = new ArrayList<>(); 329 availableLocales.add(Locale.forLanguageTag("sr-Latn")); 330 availableLocales.add(Locale.forLanguageTag("sr-RS")); 331 availableLocales.add(Locale.forLanguageTag("sr")); 332 final ArrayList<Locale> dest = new ArrayList<>(); 333 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 334 assertEquals(1, dest.size()); 335 assertEquals(availableLocales.get(1), dest.get(0)); // "sr-RS" 336 } 337 338 { 339 final LocaleList preferredLocales = LocaleList.forLanguageTags("sr"); 340 final ArrayList<Locale> availableLocales = new ArrayList<>(); 341 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-RS")); 342 availableLocales.add(Locale.forLanguageTag("sr-Latn-RS")); 343 final ArrayList<Locale> dest = new ArrayList<>(); 344 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 345 assertEquals(1, dest.size()); 346 assertEquals(availableLocales.get(0), dest.get(0)); // "sr-Cyrl-RS" 347 } 348 { 349 final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-Latn"); 350 final ArrayList<Locale> availableLocales = new ArrayList<>(); 351 availableLocales.add(Locale.forLanguageTag("sr-Latn-RS")); 352 availableLocales.add(Locale.forLanguageTag("sr-Cyrl-RS")); 353 final ArrayList<Locale> dest = new ArrayList<>(); 354 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 355 assertEquals(1, dest.size()); 356 assertEquals(availableLocales.get(0), dest.get(0)); // "sr-Latn-RS" 357 } 358 } 359 360 @Test testFilterKnownLimitation()361 public void testFilterKnownLimitation() throws Exception { 362 // Following test cases are not for intentional behavior but checks for preventing the 363 // behavior from becoming worse. 364 { 365 final LocaleList preferredLocales = LocaleList.forLanguageTags("ja-Hrkt"); 366 final ArrayList<Locale> availableLocales = new ArrayList<>(); 367 availableLocales.add(Locale.forLanguageTag("ja-Jpan")); 368 availableLocales.add(Locale.forLanguageTag("ja-Hrkt")); 369 final ArrayList<Locale> dest = new ArrayList<>(); 370 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 371 assertEquals(1, dest.size()); 372 // Should be ja-Jpan since it supports ja-Hrkt and listed before ja-Hrkt. 373 assertEquals(availableLocales.get(1), dest.get(0)); 374 } 375 { 376 final LocaleList preferredLocales = LocaleList.forLanguageTags("zh-Hani"); 377 final ArrayList<Locale> availableLocales = new ArrayList<>(); 378 availableLocales.add(Locale.forLanguageTag("zh-Hans")); 379 availableLocales.add(Locale.forLanguageTag("zh-Hant")); 380 availableLocales.add(Locale.forLanguageTag("zh-Hanb")); 381 availableLocales.add(Locale.forLanguageTag("zh-Hani")); 382 final ArrayList<Locale> dest = new ArrayList<>(); 383 LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest); 384 assertEquals(1, dest.size()); 385 // Should be zh-Hans since it supports zh-Hani. Also zh-Hant, zh-Hanb supports zh-Hani. 386 assertEquals(availableLocales.get(3), dest.get(0)); 387 } 388 } 389 } 390