1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 ********************************************************************** 6 * Copyright (c) 2015, International Business Machines 7 * Corporation and others. All Rights Reserved. 8 ********************************************************************** 9 * Author: Alan Liu 10 * Created: January 14 2004 11 * Since: ICU 2.8 12 ********************************************************************** 13 */ 14 package android.icu.dev.test.util; 15 16 import java.lang.reflect.InvocationTargetException; 17 import java.lang.reflect.Method; 18 import java.util.ArrayList; 19 import java.util.Arrays; 20 import java.util.Collections; 21 import java.util.LinkedHashSet; 22 import java.util.List; 23 import java.util.Locale; 24 import java.util.Set; 25 26 import org.junit.Test; 27 import org.junit.runner.RunWith; 28 import org.junit.runners.JUnit4; 29 30 import android.icu.dev.test.TestFmwk; 31 import android.icu.text.Collator; 32 import android.icu.text.DisplayContext; 33 import android.icu.text.DisplayContext.Type; 34 import android.icu.text.LocaleDisplayNames; 35 import android.icu.text.LocaleDisplayNames.UiListItem; 36 import android.icu.util.IllformedLocaleException; 37 import android.icu.util.ULocale; 38 import android.icu.testsharding.MainTestShard; 39 40 @MainTestShard 41 @RunWith(JUnit4.class) 42 public class ULocaleCollationTest extends TestFmwk { 43 @Test 44 public void TestCollator() { 45 checkService("ja_JP_YOKOHAMA", new ServiceFacade() { 46 @Override 47 public Object create(ULocale req) { 48 return Collator.getInstance(req); 49 } 50 }, null, new Registrar() { 51 @Override 52 public Object register(ULocale loc, Object prototype) { 53 return Collator.registerInstance((Collator) prototype, loc); 54 } 55 @Override 56 public boolean unregister(Object key) { 57 return Collator.unregister(key); 58 } 59 }); 60 } 61 62 63 /** 64 * Interface used by checkService defining a protocol to create an 65 * object, given a requested locale. 66 */ 67 interface ServiceFacade { 68 Object create(ULocale requestedLocale); 69 } 70 71 /** 72 * Interface used by checkService defining a protocol to get a 73 * contained subobject, given its parent object. 74 */ 75 interface Subobject { 76 Object get(Object parent); 77 } 78 79 /** 80 * Interface used by checkService defining a protocol to register 81 * and unregister a service object prototype. 82 */ 83 interface Registrar { 84 Object register(ULocale loc, Object prototype); 85 boolean unregister(Object key); 86 } 87 88 89 90 /** 91 * Compare two locale IDs. If they are equal, return 0. If `string' 92 * starts with `prefix' plus an additional element, that is, string == 93 * prefix + '_' + x, then return 1. Otherwise return a value < 0. 94 */ 95 static int loccmp(String string, String prefix) { 96 int slen = string.length(), 97 plen = prefix.length(); 98 /* 'root' is "less than" everything */ 99 if (prefix.equals("root")) { 100 return string.equals("root") ? 0 : 1; 101 } 102 // ON JAVA (only -- not on C -- someone correct me if I'm wrong) 103 // consider "" to be an alternate name for "root". 104 if (plen == 0) { 105 return slen == 0 ? 0 : 1; 106 } 107 if (!string.startsWith(prefix)) return -1; /* mismatch */ 108 if (slen == plen) return 0; 109 if (string.charAt(plen) == '_') return 1; 110 return -2; /* false match, e.g. "en_USX" cmp "en_US" */ 111 } 112 113 /** 114 * Check the relationship between requested locales, and report problems. 115 * The caller specifies the expected relationships between requested 116 * and valid (expReqValid) and between valid and actual (expValidActual). 117 * Possible values are: 118 * "gt" strictly greater than, e.g., en_US > en 119 * "ge" greater or equal, e.g., en >= en 120 * "eq" equal, e.g., en == en 121 */ 122 void checklocs(String label, 123 String req, 124 Locale validLoc, 125 Locale actualLoc, 126 String expReqValid, 127 String expValidActual) { 128 String valid = validLoc.toString(); 129 String actual = actualLoc.toString(); 130 int reqValid = loccmp(req, valid); 131 int validActual = loccmp(valid, actual); 132 boolean reqOK = (expReqValid.equals("gt") && reqValid > 0) || 133 (expReqValid.equals("ge") && reqValid >= 0) || 134 (expReqValid.equals("eq") && reqValid == 0); 135 boolean valOK = (expValidActual.equals("gt") && validActual > 0) || 136 (expValidActual.equals("ge") && validActual >= 0) || 137 (expValidActual.equals("eq") && validActual == 0); 138 if (reqOK && valOK) { 139 logln("Ok: " + label + "; req=" + req + ", valid=" + valid + 140 ", actual=" + actual); 141 } else { 142 errln("FAIL: " + label + "; req=" + req + ", valid=" + valid + 143 ", actual=" + actual + 144 (reqOK ? "" : "\n req !" + expReqValid + " valid") + 145 (valOK ? "" : "\n val !" + expValidActual + " actual")); 146 } 147 } 148 149 /** 150 * Use reflection to call getLocale() on the given object to 151 * determine both the valid and the actual locale. Verify these 152 * for correctness. 153 */ 154 void checkObject(String requestedLocale, Object obj, 155 String expReqValid, String expValidActual) { 156 Class[] getLocaleParams = new Class[] { ULocale.Type.class }; 157 try { 158 Class cls = obj.getClass(); 159 Method getLocale = cls.getMethod("getLocale", getLocaleParams); 160 ULocale valid = (ULocale) getLocale.invoke(obj, new Object[] { 161 ULocale.VALID_LOCALE }); 162 ULocale actual = (ULocale) getLocale.invoke(obj, new Object[] { 163 ULocale.ACTUAL_LOCALE }); 164 checklocs(cls.getName(), requestedLocale, 165 valid.toLocale(), actual.toLocale(), 166 expReqValid, expValidActual); 167 } 168 169 // Make the following exceptions _specific_ -- do not 170 // catch(Exception), since that will catch the exception 171 // that errln throws. 172 catch(NoSuchMethodException e1) { 173 // no longer an error, Currency has no getLocale 174 // errln("FAIL: reflection failed: " + e1); 175 } catch(SecurityException e2) { 176 errln("FAIL: reflection failed: " + e2); 177 } catch(IllegalAccessException e3) { 178 errln("FAIL: reflection failed: " + e3); 179 } catch(IllegalArgumentException e4) { 180 errln("FAIL: reflection failed: " + e4); 181 } catch(InvocationTargetException e5) { 182 // no longer an error, Currency has no getLocale 183 // errln("FAIL: reflection failed: " + e5); 184 } 185 } 186 187 /** 188 * Verify the correct getLocale() behavior for the given service. 189 * @param requestedLocale the locale to request. This MUST BE 190 * FAKE. In other words, it should be something like 191 * en_US_FAKEVARIANT so this method can verify correct fallback 192 * behavior. 193 * @param svc a factory object that can create the object to be 194 * tested. This isn't necessary here (one could just pass in the 195 * object) but is required for the overload of this method that 196 * takes a Registrar. 197 */ 198 void checkService(String requestedLocale, ServiceFacade svc) { 199 checkService(requestedLocale, svc, null, null); 200 } 201 202 /** 203 * Verify the correct getLocale() behavior for the given service. 204 * @param requestedLocale the locale to request. This MUST BE 205 * FAKE. In other words, it should be something like 206 * en_US_FAKEVARIANT so this method can verify correct fallback 207 * behavior. 208 * @param svc a factory object that can create the object to be 209 * tested. 210 * @param sub an object that can be used to retrieve a subobject 211 * which should also be tested. May be null. 212 * @param reg an object that supplies the registration and 213 * unregistration functionality to be tested. May be null. 214 */ 215 void checkService(String requestedLocale, ServiceFacade svc, 216 Subobject sub, Registrar reg) { 217 ULocale req = new ULocale(requestedLocale); 218 Object obj = svc.create(req); 219 checkObject(requestedLocale, obj, "gt", "ge"); 220 if (sub != null) { 221 Object subobj = sub.get(obj); 222 checkObject(requestedLocale, subobj, "gt", "ge"); 223 } 224 if (reg != null) { 225 logln("Info: Registering service"); 226 Object key = reg.register(req, obj); 227 Object objReg = svc.create(req); 228 checkObject(requestedLocale, objReg, "eq", "eq"); 229 if (sub != null) { 230 Object subobj = sub.get(obj); 231 // Assume subobjects don't come from services, so 232 // their metadata should be structured normally. 233 checkObject(requestedLocale, subobj, "gt", "ge"); 234 } 235 logln("Info: Unregistering service"); 236 if (!reg.unregister(key)) { 237 errln("FAIL: unregister failed"); 238 } 239 Object objUnreg = svc.create(req); 240 checkObject(requestedLocale, objUnreg, "gt", "ge"); 241 } 242 } 243 244 @Test 245 public void TestNameList() { 246 String[][][] tests = { 247 /* name in French, name in self, minimized, modified */ 248 {{"fr-Cyrl-BE", "fr-Cyrl-CA"}, 249 {"Franais (cyrillique, Belgique)", "Franais (cyrillique, Belgique)", "fr_Cyrl_BE", "fr_Cyrl_BE"}, 250 {"Franais (cyrillique, Canada)", "Franais (cyrillique, Canada)", "fr_Cyrl_CA", "fr_Cyrl_CA"}, 251 }, 252 {{"en", "de", "fr", "zh"}, 253 {"Allemand", "Deutsch", "de", "de"}, 254 {"Anglais", "English", "en", "en"}, 255 {"Chinois", "", "zh", "zh"}, 256 {"Franais", "Franais", "fr", "fr"}, 257 }, 258 // some non-canonical names 259 {{"iw", "iw-US", "no", "no-Cyrl", "in", "in-YU"}, 260 {"Hbreu (tats-Unis)", " ( )", "iw_US", "iw_US"}, 261 {"Hbreu (Isral)", " ()", "iw", "iw_IL"}, 262 {"Indonsien (Indonsie)", "Indonesia (Indonesia)", "in", "in_ID"}, 263 {"Indonsien (Serbie)", "Indonesia (Serbia)", "in_YU", "in_YU"}, 264 {"Norvgien (cyrillique)", "Norsk (kyrillisk)", "no_Cyrl", "no_Cyrl"}, 265 {"Norvgien (latin)", "Norsk (latinsk)", "no", "no_Latn"}, 266 }, 267 {{"zh-Hant-TW", "en", "en-gb", "fr", "zh-Hant", "de", "de-CH", "zh-TW"}, 268 {"Allemand (Allemagne)", "Deutsch (Deutschland)", "de", "de_DE"}, 269 {"Allemand (Suisse)", "Deutsch (Schweiz)", "de_CH", "de_CH"}, 270 {"Anglais (tats-Unis)", "English (United States)", "en", "en_US"}, 271 {"Anglais (Royaume-Uni)", "English (United Kingdom)", "en_GB", "en_GB"}, 272 {"Chinois (traditionnel)", "", "zh_Hant", "zh_Hant"}, 273 {"Franais", "Franais", "fr", "fr"}, 274 }, 275 {{"zh", "en-gb", "en-CA", "fr-Latn-FR"}, 276 {"Anglais (Canada)", "English (Canada)", "en_CA", "en_CA"}, 277 {"Anglais (Royaume-Uni)", "English (United Kingdom)", "en_GB", "en_GB"}, 278 {"Chinois", "", "zh", "zh"}, 279 {"Franais", "Franais", "fr", "fr"}, 280 }, 281 {{"en-gb", "fr", "zh-Hant", "zh-SG", "sr", "sr-Latn"}, 282 {"Anglais (Royaume-Uni)", "English (United Kingdom)", "en_GB", "en_GB"}, 283 {"Chinois (simplifi, Singapour)", "", "zh_SG", "zh_Hans_SG"}, 284 {"Chinois (traditionnel, Tawan)", "", "zh_Hant", "zh_Hant_TW"}, 285 {"Franais", "Franais", "fr", "fr"}, 286 {"Serbe (cyrillique)", " ()", "sr", "sr_Cyrl"}, 287 {"Serbe (latin)", "Srpski (latinica)", "sr_Latn", "sr_Latn"}, 288 }, 289 {{"fr-Cyrl", "fr-Arab"}, 290 {"Franais (arabe)", "Franais (arabe)", "fr_Arab", "fr_Arab"}, 291 {"Franais (cyrillique)", "Franais (cyrillique)", "fr_Cyrl", "fr_Cyrl"}, 292 }, 293 {{"fr-Cyrl-BE", "fr-Arab-CA"}, 294 {"Franais (arabe, Canada)", "Franais (arabe, Canada)", "fr_Arab_CA", "fr_Arab_CA"}, 295 {"Franais (cyrillique, Belgique)", "Franais (cyrillique, Belgique)", "fr_Cyrl_BE", "fr_Cyrl_BE"}, 296 } 297 }; 298 ULocale french = ULocale.FRENCH; 299 LocaleDisplayNames names = LocaleDisplayNames.getInstance(french, 300 DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU); 301 for (Type type : DisplayContext.Type.values()) { 302 logln("Contexts: " + names.getContext(type).toString()); 303 } 304 Collator collator = Collator.getInstance(french); 305 306 for (String[][] test : tests) { 307 Set<ULocale> list = new LinkedHashSet<ULocale>(); 308 List<UiListItem> expected = new ArrayList<UiListItem>(); 309 for (String item : test[0]) { 310 list.add(new ULocale(item)); 311 } 312 for (int i = 1; i < test.length; ++i) { 313 String[] rawRow = test[i]; 314 expected.add(new UiListItem(new ULocale(rawRow[2]), new ULocale(rawRow[3]), rawRow[0], rawRow[1])); 315 } 316 List<UiListItem> newList = names.getUiList(list, false, collator); 317 if (!expected.equals(newList)) { 318 if (expected.size() != newList.size()) { 319 errln(list.toString() + ": wrong size" + expected + ", " + newList); 320 } else { 321 errln(list.toString()); 322 for (int i = 0; i < expected.size(); ++i) { 323 assertEquals(i+"", expected.get(i), newList.get(i)); 324 } 325 } 326 } else { 327 assertEquals(list.toString(), expected, newList); 328 } 329 } 330 } 331 332 @Test 333 public void TestIllformedLocale() { 334 ULocale french = ULocale.FRENCH; 335 Collator collator = Collator.getInstance(french); 336 LocaleDisplayNames names = LocaleDisplayNames.getInstance(french, 337 DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU); 338 for (String malformed : Arrays.asList("en-a", "$", "--a", "en--US")) { 339 try { 340 Set<ULocale> supported = Collections.singleton(new ULocale(malformed)); 341 names.getUiList(supported, false, collator); 342 assertNull("Failed to detect bogus locale " + malformed + "", supported); 343 } catch (IllformedLocaleException e) { 344 logln("Successfully detected ill-formed locale " + malformed + ":" + e.getMessage()); 345 } 346 } 347 } 348 } 349