Home | History | Annotate | Download | only in util
      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