Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2010 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 libcore.java.util;
     18 
     19 import java.io.ObjectInputStream;
     20 import java.text.BreakIterator;
     21 import java.text.Collator;
     22 import java.text.DateFormat;
     23 import java.text.DateFormatSymbols;
     24 import java.text.DecimalFormatSymbols;
     25 import java.text.NumberFormat;
     26 import java.util.Calendar;
     27 import java.util.IllformedLocaleException;
     28 import java.util.Locale;
     29 import java.util.MissingResourceException;
     30 
     31 public class LocaleTest extends junit.framework.TestCase {
     32     // http://b/2611311; if there's no display language/country/variant, use the raw codes.
     33     public void test_getDisplayName_invalid() throws Exception {
     34         Locale invalid = new Locale("AaBbCc", "DdEeFf", "GgHhIi");
     35 
     36         assertEquals("aabbcc", invalid.getLanguage());
     37         assertEquals("DDEEFF", invalid.getCountry());
     38         assertEquals("GgHhIi", invalid.getVariant());
     39 
     40         // Android using icu4c < 49.2 returned empty strings for display language, country,
     41         // and variant, but a display name made up of the raw strings.
     42         // Newer releases return slightly different results, but no less unreasonable.
     43         assertEquals("aabbcc", invalid.getDisplayLanguage());
     44         assertEquals("DDEEFF", invalid.getDisplayCountry());
     45         assertEquals("GGHHII", invalid.getDisplayVariant());
     46         assertEquals("aabbcc (DDEEFF,GGHHII)", invalid.getDisplayName());
     47     }
     48 
     49     public void test_getDisplayName_emptyCodes() {
     50         Locale emptyLanguage = new Locale("", "DdeEFf");
     51         assertEquals("", emptyLanguage.getDisplayLanguage());
     52 
     53         Locale emptyCountry = new Locale("AaBbCc", "");
     54         assertEquals("", emptyCountry.getDisplayCountry());
     55 
     56         Locale emptyCountryAndLanguage = new Locale("", "", "Farl");
     57         assertEquals("", emptyCountryAndLanguage.getDisplayLanguage());
     58         assertEquals("", emptyCountryAndLanguage.getDisplayCountry());
     59         assertEquals("Farl", emptyCountryAndLanguage.getDisplayVariant());
     60     }
     61 
     62     // http://b/2611311; if there's no display language/country/variant, use the raw codes.
     63     public void test_getDisplayName_unknown() throws Exception {
     64         Locale unknown = new Locale("xx", "YY", "Traditional");
     65         assertEquals("xx", unknown.getLanguage());
     66         assertEquals("YY", unknown.getCountry());
     67         assertEquals("Traditional", unknown.getVariant());
     68 
     69         assertEquals("xx", unknown.getDisplayLanguage());
     70         assertEquals("YY", unknown.getDisplayCountry());
     71         assertEquals("Traditional", unknown.getDisplayVariant());
     72         assertEquals("xx (YY,Traditional)", unknown.getDisplayName());
     73     }
     74 
     75     public void test_getDisplayName_easy() throws Exception {
     76         assertEquals("English", Locale.ENGLISH.getDisplayLanguage(Locale.ENGLISH));
     77         assertEquals("German", Locale.GERMAN.getDisplayLanguage(Locale.ENGLISH));
     78         assertEquals("Englisch", Locale.ENGLISH.getDisplayLanguage(Locale.GERMAN));
     79         assertEquals("Deutsch", Locale.GERMAN.getDisplayLanguage(Locale.GERMAN));
     80     }
     81 
     82     // https://b/issue?id=13790528
     83     public void test_getDisplayName_withScriptsAndVariants() throws Exception {
     84         // Script + Country.
     85         assertEquals("Chinese (Traditional Han,China)",
     86                 Locale.forLanguageTag("zh-Hant-CN").getDisplayName(Locale.US));
     87         // Script + Variant.
     88         assertEquals("Chinese (Traditional Han,VARIANT)",
     89                 Locale.forLanguageTag("zh-Hant-VARIANT").getDisplayName(Locale.US));
     90         // Country + Variant.
     91         assertEquals("Chinese (China,VARIANT)",
     92                 Locale.forLanguageTag("zh-CN-VARIANT").getDisplayName(Locale.US));
     93         // Script + Country + variant.
     94         assertEquals("Chinese (Traditional Han,China,VARIANT)",
     95                 Locale.forLanguageTag("zh-Hant-CN-VARIANT").getDisplayName(Locale.US));
     96     }
     97 
     98     public void test_getDisplayCountry_8870289() throws Exception {
     99         assertEquals("Hong Kong", new Locale("", "HK").getDisplayCountry(Locale.US));
    100         assertEquals("Macau", new Locale("", "MO").getDisplayCountry(Locale.US));
    101         assertEquals("Palestine", new Locale("", "PS").getDisplayCountry(Locale.US));
    102 
    103         assertEquals("Cocos (Keeling) Islands", new Locale("", "CC").getDisplayCountry(Locale.US));
    104         assertEquals("Congo (DRC)", new Locale("", "CD").getDisplayCountry(Locale.US));
    105         assertEquals("Congo (Republic)", new Locale("", "CG").getDisplayCountry(Locale.US));
    106         assertEquals("Falkland Islands (Islas Malvinas)", new Locale("", "FK").getDisplayCountry(Locale.US));
    107         assertEquals("Macedonia (FYROM)", new Locale("", "MK").getDisplayCountry(Locale.US));
    108         assertEquals("Myanmar (Burma)", new Locale("", "MM").getDisplayCountry(Locale.US));
    109         assertEquals("Taiwan", new Locale("", "TW").getDisplayCountry(Locale.US));
    110     }
    111 
    112     public void test_tl_and_fil() throws Exception {
    113         // In jb-mr1, we had a last-minute hack to always return "Filipino" because
    114         // icu4c 4.8 didn't have any localizations for fil. (http://b/7291355).
    115         //
    116         // After the icu4c 4.9 upgrade, we could localize "fil" correctly, though we
    117         // needed another hack to supply "fil" instead of "tl" to icu4c. (http://b/8023288).
    118         //
    119         // These hacks have now been reverted, so "tl" really does represent
    120         // tagalog and not filipino.
    121         Locale tl = new Locale("tl");
    122         Locale tl_PH = new Locale("tl", "PH");
    123         assertEquals("Tagalog", tl.getDisplayLanguage(Locale.ENGLISH));
    124         assertEquals("Tagalog", tl_PH.getDisplayLanguage(Locale.ENGLISH));
    125         assertEquals("tl", tl.getDisplayLanguage(tl));
    126         assertEquals("tl", tl_PH.getDisplayLanguage(tl_PH));
    127 
    128         Locale es_MX = new Locale("es", "MX");
    129         assertEquals("tagalo", tl.getDisplayLanguage(es_MX));
    130         assertEquals("tagalo", tl_PH.getDisplayLanguage(es_MX));
    131 
    132         // Assert that we can deal with "fil" correctly, since we've switched
    133         // to using "fil" for Filipino, and not "tl". (http://b/15873165).
    134         Locale fil = new Locale("fil");
    135         Locale fil_PH = new Locale("fil", "PH");
    136         assertEquals("Filipino", fil.getDisplayLanguage(Locale.ENGLISH));
    137         assertEquals("Filipino", fil_PH.getDisplayLanguage(Locale.ENGLISH));
    138         assertEquals("Filipino", fil.getDisplayLanguage(fil));
    139         assertEquals("Filipino", fil_PH.getDisplayLanguage(fil_PH));
    140 
    141         assertEquals("filipino", fil.getDisplayLanguage(es_MX));
    142         assertEquals("filipino", fil_PH.getDisplayLanguage(es_MX));
    143     }
    144 
    145     // http://b/3452611; Locale.getDisplayLanguage fails for the obsolete language codes.
    146     public void test_getDisplayName_obsolete() throws Exception {
    147         // he (new) -> iw (obsolete)
    148         assertObsolete("he", "iw", "");
    149         // id (new) -> in (obsolete)
    150         assertObsolete("id", "in", "Indonesia");
    151     }
    152 
    153     private static void assertObsolete(String newCode, String oldCode, String displayName) {
    154         // Either code should get you the same locale.
    155         Locale newLocale = new Locale(newCode);
    156         Locale oldLocale = new Locale(oldCode);
    157         assertEquals(newLocale, oldLocale);
    158 
    159         // No matter what code you used to create the locale, you should get the old code back.
    160         assertEquals(oldCode, newLocale.getLanguage());
    161         assertEquals(oldCode, oldLocale.getLanguage());
    162 
    163         // Check we get the right display name.
    164         assertEquals(displayName, newLocale.getDisplayLanguage(newLocale));
    165         assertEquals(displayName, oldLocale.getDisplayLanguage(newLocale));
    166         assertEquals(displayName, newLocale.getDisplayLanguage(oldLocale));
    167         assertEquals(displayName, oldLocale.getDisplayLanguage(oldLocale));
    168 
    169         // Check that none of the 'getAvailableLocales' methods are accidentally returning two
    170         // equal locales (because to ICU they're different, but we mangle one into the other).
    171         assertOnce(newLocale, BreakIterator.getAvailableLocales());
    172         assertOnce(newLocale, Calendar.getAvailableLocales());
    173         assertOnce(newLocale, Collator.getAvailableLocales());
    174         assertOnce(newLocale, DateFormat.getAvailableLocales());
    175         assertOnce(newLocale, DateFormatSymbols.getAvailableLocales());
    176         assertOnce(newLocale, NumberFormat.getAvailableLocales());
    177         assertOnce(newLocale, Locale.getAvailableLocales());
    178     }
    179 
    180     private static void assertOnce(Locale element, Locale[] array) {
    181         int count = 0;
    182         for (Locale l : array) {
    183             if (l.equals(element)) {
    184                 ++count;
    185             }
    186         }
    187         assertEquals(1, count);
    188     }
    189 
    190     public void test_getISO3Country() {
    191         // Empty country code.
    192         assertEquals("", new Locale("en", "").getISO3Country());
    193 
    194         // Invalid country code.
    195         try {
    196             assertEquals("", new Locale("en", "XX").getISO3Country());
    197             fail();
    198         } catch (MissingResourceException expected) {
    199             assertEquals("FormatData_en_XX", expected.getClassName());
    200             assertEquals("ShortCountry", expected.getKey());
    201         }
    202 
    203         // Valid country code.
    204         assertEquals("CAN", new Locale("", "CA").getISO3Country());
    205         assertEquals("CAN", new Locale("en", "CA").getISO3Country());
    206         assertEquals("CAN", new Locale("xx", "CA").getISO3Country());
    207 
    208         // 3 letter country codes.
    209         assertEquals("CAN", new Locale("en", "CAN").getISO3Country());
    210         assertEquals("CAN", new Locale("frankenderp", "CAN").getISO3Country());
    211     }
    212 
    213     public void test_getISO3Language() {
    214         // Empty language code.
    215         assertEquals("", new Locale("", "US").getISO3Language());
    216 
    217         // Invalid language code.
    218         try {
    219             assertEquals("", new Locale("xx", "US").getISO3Language());
    220             fail();
    221         } catch (MissingResourceException expected) {
    222             assertEquals("FormatData_xx_US", expected.getClassName());
    223             assertEquals("ShortLanguage", expected.getKey());
    224         }
    225 
    226         // Valid language code.
    227         assertEquals("eng", new Locale("en", "").getISO3Language());
    228         assertEquals("eng", new Locale("en", "CA").getISO3Language());
    229         assertEquals("eng", new Locale("en", "XX").getISO3Language());
    230 
    231         // 3 letter language code.
    232         assertEquals("eng", new Locale("eng", "USA").getISO3Language());
    233         assertEquals("eng", new Locale("eng", "US").getISO3Language());
    234     }
    235 
    236     public void test_Builder_setLanguage() {
    237         Locale.Builder b = new Locale.Builder();
    238 
    239         // Should normalize to lower case.
    240         b.setLanguage("EN");
    241         assertEquals("en", b.build().getLanguage());
    242 
    243         b = new Locale.Builder();
    244 
    245         // Too short.
    246         try {
    247             b.setLanguage("e");
    248             fail();
    249         } catch (IllformedLocaleException expected) {
    250         }
    251 
    252         // Too long
    253         try {
    254             // note: pre-openJdk Locale assumed that language will be between
    255             // 2-3 characters. openJdk accepts 2-8 character languages.
    256             b.setLanguage("foobarbar");
    257             fail();
    258         } catch (IllformedLocaleException expected) {
    259         }
    260 
    261         // Contains non ASCII characters
    262         try {
    263             b.setLanguage("");
    264             fail();
    265         } catch (IllformedLocaleException expected) {
    266         }
    267 
    268         // Null or empty languages must clear state.
    269         b = new Locale.Builder();
    270         b.setLanguage("en");
    271         b.setLanguage(null);
    272         assertEquals("", b.build().getLanguage());
    273 
    274         b = new Locale.Builder();
    275         b.setLanguage("en");
    276         b.setLanguage("");
    277         assertEquals("", b.build().getLanguage());
    278     }
    279 
    280     public void test_Builder_setRegion() {
    281         Locale.Builder b = new Locale.Builder();
    282 
    283         // Should normalize to upper case.
    284         b.setRegion("us");
    285         assertEquals("US", b.build().getCountry());
    286 
    287         b = new Locale.Builder();
    288 
    289         // Too short.
    290         try {
    291             b.setRegion("e");
    292             fail();
    293         } catch (IllformedLocaleException expected) {
    294         }
    295 
    296         // Too long
    297         try {
    298             b.setRegion("USA");
    299             fail();
    300         } catch (IllformedLocaleException expected) {
    301         }
    302 
    303         // Contains non ASCII characters
    304         try {
    305             b.setLanguage("");
    306             fail();
    307         } catch (IllformedLocaleException expected) {
    308         }
    309 
    310         // Null or empty regions must clear state.
    311         b = new Locale.Builder();
    312         b.setRegion("US");
    313         b.setRegion(null);
    314         assertEquals("", b.build().getCountry());
    315 
    316         b = new Locale.Builder();
    317         b.setRegion("US");
    318         b.setRegion("");
    319         assertEquals("", b.build().getCountry());
    320     }
    321 
    322     public void test_Builder_setVariant() {
    323         Locale.Builder b = new Locale.Builder();
    324 
    325         // Should normalize "_" to "-"
    326         b = new Locale.Builder();
    327         b.setVariant("vArIaNt-VaRiAnT-VARIANT");
    328         assertEquals("vArIaNt_VaRiAnT_VARIANT", b.build().getVariant());
    329 
    330         b = new Locale.Builder();
    331         // Too short
    332         try {
    333             b.setVariant("shor");
    334             fail();
    335         } catch (IllformedLocaleException expected) {
    336         }
    337 
    338         // Too long
    339         try {
    340             b.setVariant("waytoolong");
    341             fail();
    342         } catch (IllformedLocaleException expected) {
    343         }
    344 
    345         try {
    346             b.setVariant("foooo-foooo-fo");
    347             fail();
    348         } catch (IllformedLocaleException expected) {
    349         }
    350 
    351         // Special case. Variants of length 4 are allowed when the first
    352         // character is a digit.
    353         b.setVariant("0ABC");
    354         assertEquals("0ABC", b.build().getVariant());
    355 
    356         b = new Locale.Builder();
    357         b.setVariant("variant");
    358         b.setVariant(null);
    359         assertEquals("", b.build().getVariant());
    360 
    361         b = new Locale.Builder();
    362         b.setVariant("variant");
    363         b.setVariant("");
    364         assertEquals("", b.build().getVariant());
    365     }
    366 
    367     public void test_Builder_setLocale() {
    368         // Default case.
    369         Locale.Builder b = new Locale.Builder();
    370         b.setLocale(Locale.US);
    371         assertEquals("en", b.build().getLanguage());
    372         assertEquals("US", b.build().getCountry());
    373 
    374         // Should throw when locale is malformed.
    375         // - Bad language
    376         Locale bad = new Locale("e", "US");
    377         b = new Locale.Builder();
    378         try {
    379             b.setLocale(bad);
    380             fail();
    381         } catch (IllformedLocaleException expected) {
    382         }
    383         // - Bad country
    384         bad = new Locale("en", "USA");
    385         try {
    386             b.setLocale(bad);
    387             fail();
    388         } catch (IllformedLocaleException expected) {
    389         }
    390 
    391         // - Bad variant
    392         bad = new Locale("en", "US", "c");
    393         try {
    394             b.setLocale(bad);
    395             fail();
    396         } catch (IllformedLocaleException expected) {
    397         }
    398 
    399         // Test values are normalized as they should be
    400         b = new Locale.Builder();
    401         Locale good = new Locale("EN", "us", "variant-VARIANT");
    402         b.setLocale(good);
    403         Locale l = b.build();
    404         assertEquals("en", l.getLanguage());
    405         assertEquals("US", l.getCountry());
    406         assertEquals("variant_VARIANT", l.getVariant());
    407 
    408         // Test that none of the existing fields are messed with
    409         // if the locale update fails.
    410         b = new Locale.Builder();
    411         b.setLanguage("fr").setRegion("FR");
    412 
    413         try {
    414             b.setLocale(bad);
    415             fail();
    416         } catch (IllformedLocaleException expected) {
    417         }
    418 
    419         l = b.build();
    420         assertEquals("fr", l.getLanguage());
    421         assertEquals("FR", l.getCountry());
    422     }
    423 
    424     public void test_Builder_setScript() {
    425         Locale.Builder b = new Locale.Builder();
    426 
    427         // Should normalize variants to lower case.
    428         b.setScript("lAtN");
    429         assertEquals("Latn", b.build().getScript());
    430 
    431         b = new Locale.Builder();
    432         // Too short
    433         try {
    434             b.setScript("lat");
    435             fail();
    436         } catch (IllformedLocaleException expected) {
    437         }
    438 
    439         // Too long
    440         try {
    441             b.setScript("latin");
    442             fail();
    443         } catch (IllformedLocaleException expected) {
    444         }
    445 
    446         b = new Locale.Builder();
    447         b.setScript("Latn");
    448         b.setScript(null);
    449         assertEquals("", b.build().getScript());
    450 
    451         b = new Locale.Builder();
    452         b.setScript("Latn");
    453         b.setScript("");
    454         assertEquals("", b.build().getScript());
    455     }
    456 
    457     public void test_Builder_clear() {
    458         Locale.Builder b = new Locale.Builder();
    459         b.setLanguage("en").setScript("Latn").setRegion("US")
    460                 .setVariant("POSIX").setExtension('g', "foo")
    461                 .setUnicodeLocaleKeyword("fo", "baar")
    462                 .addUnicodeLocaleAttribute("baaaaz");
    463 
    464         Locale l = b.clear().build();
    465         assertEquals("", l.getLanguage());
    466         assertEquals("", l.getCountry());
    467         assertEquals("", l.getVariant());
    468         assertEquals("", l.getScript());
    469         assertTrue(l.getExtensionKeys().isEmpty());
    470     }
    471 
    472     public void test_Builder_setExtension() {
    473         Locale.Builder b = new Locale.Builder();
    474         b.setExtension('g', "FO_ba-BR_bg");
    475 
    476         Locale l = b.build();
    477         assertEquals("fo-ba-br-bg", l.getExtension('g'));
    478 
    479         b = new Locale.Builder();
    480 
    481         // Too short
    482         try {
    483             b.setExtension('g', "fo-ba-br-x");
    484             fail();
    485         } catch (IllformedLocaleException expected) {
    486         }
    487 
    488         // Too long
    489         try {
    490             b.setExtension('g', "fo-ba-br-extension");
    491             fail();
    492         } catch (IllformedLocaleException expected) {
    493         }
    494 
    495         // Special case, the private use extension allows single char subtags.
    496         b.setExtension(Locale.PRIVATE_USE_EXTENSION, "fo-ba-br-m");
    497         l = b.build();
    498         assertEquals("fo-ba-br-m", l.getExtension('x'));
    499 
    500         // Special case, the unicode locale extension must be parsed into
    501         // its individual components. The correctness of the parse is tested
    502         // in test_parseUnicodeExtension.
    503         b.setExtension(Locale.UNICODE_LOCALE_EXTENSION, "foooo_BaaaR-BA_Baz-bI_BIZ");
    504         l = b.build();
    505         // Note that attributes and keywords are sorted alphabetically.
    506         assertEquals("baaar-foooo-ba-baz-bi-biz", l.getExtension('u'));
    507 
    508         assertTrue(l.getUnicodeLocaleAttributes().contains("foooo"));
    509         assertTrue(l.getUnicodeLocaleAttributes().contains("baaar"));
    510         assertEquals("baz", l.getUnicodeLocaleType("ba"));
    511         assertEquals("biz", l.getUnicodeLocaleType("bi"));
    512     }
    513 
    514     public void test_Builder_clearExtensions() {
    515         Locale.Builder b = new Locale.Builder();
    516         b.setExtension('g', "FO_ba-BR_bg");
    517         b.setExtension(Locale.PRIVATE_USE_EXTENSION, "fo-ba-br-m");
    518         b.clearExtensions();
    519 
    520         assertTrue(b.build().getExtensionKeys().isEmpty());
    521     }
    522 
    523     private static Locale fromLanguageTag(String languageTag, boolean useBuilder) {
    524         if (useBuilder) {
    525             return (new Locale.Builder().setLanguageTag(languageTag).build());
    526         } else {
    527             return Locale.forLanguageTag(languageTag);
    528         }
    529     }
    530 
    531     private void test_setLanguageTag_wellFormedsingleSubtag(boolean useBuilder) {
    532         Locale l = fromLanguageTag("en", useBuilder);
    533         assertEquals("en", l.getLanguage());
    534 
    535         l = fromLanguageTag("eng", useBuilder);
    536         assertEquals("eng", l.getLanguage());
    537     }
    538 
    539     private void test_setLanguageTag_twoWellFormedSubtags(boolean useBuilder) {
    540         Locale l =  fromLanguageTag("en-US", useBuilder);
    541         assertEquals("en", l.getLanguage());
    542         assertEquals("US", l.getCountry());
    543 
    544         l =  fromLanguageTag("eng-419", useBuilder);
    545         assertEquals("eng", l.getLanguage());
    546         assertEquals("419", l.getCountry());
    547 
    548         // Script tags shouldn't be mis-recognized as regions.
    549         l =  fromLanguageTag("en-Latn", useBuilder);
    550         assertEquals("en", l.getLanguage());
    551         assertEquals("", l.getCountry());
    552         assertEquals("Latn", l.getScript());
    553 
    554         // Neither should variant tags.
    555         l =  fromLanguageTag("en-POSIX", useBuilder);
    556         assertEquals("en", l.getLanguage());
    557         assertEquals("", l.getCountry());
    558         assertEquals("", l.getScript());
    559         assertEquals("POSIX", l.getVariant());
    560     }
    561 
    562     public void test_Builder_setLanguageTag_malformedTags() {
    563         try {
    564             fromLanguageTag("a", true);
    565             fail();
    566         } catch (IllformedLocaleException ifle) {
    567         }
    568 
    569         // Three subtags
    570         // lang-region-illformedvariant
    571         try {
    572             fromLanguageTag("en-US-BA", true);
    573             fail();
    574         } catch (IllformedLocaleException expected) {
    575         }
    576 
    577         // lang-variant-illformedvariant
    578         try {
    579             fromLanguageTag("en-FOOOO-BA", true);
    580             fail();
    581         } catch (IllformedLocaleException expected) {
    582         }
    583 
    584         // Four or more sub tags
    585         try {
    586             fromLanguageTag("en-US-POSIX-P2", true);
    587             fail();
    588         } catch (IllformedLocaleException expected) {
    589         }
    590 
    591         try {
    592             fromLanguageTag("en-Latn-US-P2", true);
    593             fail();
    594         } catch (IllformedLocaleException expected) {
    595         }
    596 
    597         // Extensions
    598         // Ill-formed empty extension.
    599         try {
    600             fromLanguageTag("en-f-f", true);
    601             fail();
    602         } catch (IllformedLocaleException expected) {
    603         }
    604 
    605         // Ill-formed empty extension.
    606         try {
    607             fromLanguageTag("en-f", true);
    608             fail();
    609         } catch (IllformedLocaleException expected) {
    610         }
    611 
    612         // Two extension keys in a row (i.e, another case of an ill-formed
    613         // empty exception).
    614         try {
    615             fromLanguageTag("en-f-g-fo-baar", true);
    616             fail();
    617         } catch (IllformedLocaleException expected) {
    618         }
    619 
    620         // Dangling empty key after a well formed extension.
    621         try {
    622             fromLanguageTag("en-f-fo-baar-g", true);
    623             fail();
    624         } catch (IllformedLocaleException expected) {
    625         }
    626 
    627         // Ill-formed extension with long subtag.
    628         try {
    629             fromLanguageTag("en-f-fooobaaaz", true);
    630             fail();
    631         } catch (IllformedLocaleException expected) {
    632         }
    633     }
    634 
    635     private void test_setLanguageTag_threeWellFormedSubtags(boolean useBuilder) {
    636         // lang-region-variant
    637         Locale l = fromLanguageTag("en-US-FOOOO", useBuilder);
    638         assertEquals("en", l.getLanguage());
    639         assertEquals("US", l.getCountry());
    640         assertEquals("", l.getScript());
    641         assertEquals("FOOOO", l.getVariant());
    642 
    643         // lang-script-variant
    644         l = fromLanguageTag("en-Latn-FOOOO", useBuilder);
    645         assertEquals("en", l.getLanguage());
    646         assertEquals("", l.getCountry());
    647         assertEquals("Latn", l.getScript());
    648         assertEquals("FOOOO", l.getVariant());
    649 
    650         // lang-script-region
    651         l = fromLanguageTag("en-Latn-US", useBuilder);
    652         assertEquals("en", l.getLanguage());
    653         assertEquals("US", l.getCountry());
    654         assertEquals("Latn", l.getScript());
    655         assertEquals("", l.getVariant());
    656 
    657         // lang-variant-variant
    658         l = fromLanguageTag("en-FOOOO-BAAAR", useBuilder);
    659         assertEquals("en", l.getLanguage());
    660         assertEquals("", l.getCountry());
    661         assertEquals("", l.getScript());
    662         assertEquals("FOOOO_BAAAR", l.getVariant());
    663     }
    664 
    665     private void test_setLanguageTag_fourOrMoreWellFormedSubtags(boolean useBuilder) {
    666         // lang-script-region-variant.
    667         Locale l = fromLanguageTag("en-Latn-US-foooo", useBuilder);
    668         assertEquals("en", l.getLanguage());
    669         assertEquals("Latn", l.getScript());
    670         assertEquals("US", l.getCountry());
    671         assertEquals("foooo", l.getVariant());
    672 
    673         // Variant with multiple subtags.
    674         l = fromLanguageTag("en-Latn-US-foooo-gfffh", useBuilder);
    675         assertEquals("en", l.getLanguage());
    676         assertEquals("Latn", l.getScript());
    677         assertEquals("US", l.getCountry());
    678         assertEquals("foooo_gfffh", l.getVariant());
    679 
    680         // Variant with 3 subtags. POSIX shouldn't be recognized
    681         // as a region or a script.
    682         l = fromLanguageTag("en-POSIX-P2003-P2004", useBuilder);
    683         assertEquals("en", l.getLanguage());
    684         assertEquals("", l.getScript());
    685         assertEquals("", l.getCountry());
    686         assertEquals("POSIX_P2003_P2004", l.getVariant());
    687 
    688         // lang-script-variant-variant.
    689         l = fromLanguageTag("en-Latn-POSIX-P2003", useBuilder);
    690         assertEquals("en", l.getLanguage());
    691         assertEquals("Latn", l.getScript());
    692         assertEquals("", l.getCountry());
    693         assertEquals("POSIX_P2003", l.getVariant());
    694 
    695         // lang-region-variant-variant
    696         l = fromLanguageTag("en-US-POSIX-P2003", useBuilder);
    697         assertEquals("en", l.getLanguage());
    698         assertEquals("", l.getScript());
    699         assertEquals("US", l.getCountry());
    700         assertEquals("POSIX_P2003", l.getVariant());
    701     }
    702 
    703     private void test_setLanguageTag_withWellFormedExtensions(boolean useBuilder) {
    704         Locale l = fromLanguageTag("en-Latn-GB-foooo-g-fo-bar-baaz", useBuilder);
    705         assertEquals("en", l.getLanguage());
    706         assertEquals("Latn", l.getScript());
    707         assertEquals("GB", l.getCountry());
    708         assertEquals("foooo", l.getVariant());
    709         assertEquals("fo-bar-baaz", l.getExtension('g'));
    710 
    711         // Multiple extensions
    712         l = fromLanguageTag("en-Latn-US-foooo-g-fo-bar-h-go-gaz", useBuilder);
    713         assertEquals("en", l.getLanguage());
    714         assertEquals("Latn", l.getScript());
    715         assertEquals("US", l.getCountry());
    716         assertEquals("foooo", l.getVariant());
    717         assertEquals("fo-bar", l.getExtension('g'));
    718         assertEquals("go-gaz", l.getExtension('h'));
    719 
    720         // Unicode locale extension.
    721         l = fromLanguageTag("en-Latn-US-foooo-u-koooo-fo-bar", useBuilder);
    722         assertEquals("en", l.getLanguage());
    723         assertEquals("Latn", l.getScript());
    724         assertEquals("US", l.getCountry());
    725         assertEquals("koooo-fo-bar", l.getExtension('u'));
    726         assertTrue(l.getUnicodeLocaleAttributes().contains("koooo"));
    727         assertEquals("bar", l.getUnicodeLocaleType("fo"));
    728 
    729         // Extensions without variants
    730         l = fromLanguageTag("en-Latn-US-f-fo", useBuilder);
    731         assertEquals("en", l.getLanguage());
    732         assertEquals("Latn", l.getScript());
    733         assertEquals("US", l.getCountry());
    734         assertEquals("fo", l.getExtension('f'));
    735 
    736         l = fromLanguageTag("en-Latn-f-fo", useBuilder);
    737         assertEquals("en", l.getLanguage());
    738         assertEquals("Latn", l.getScript());
    739         assertEquals("fo", l.getExtension('f'));
    740 
    741         l = fromLanguageTag("en-f-fo", useBuilder);
    742         assertEquals("en", l.getLanguage());
    743         assertEquals("", l.getScript());
    744         assertEquals("", l.getCountry());
    745         assertEquals("fo", l.getExtension('f'));
    746 
    747         l = fromLanguageTag("en-f-fo-x-a-b-c-d-e-fo", useBuilder);
    748         assertEquals("en", l.getLanguage());
    749         assertEquals("", l.getScript());
    750         assertEquals("", l.getCountry());
    751         assertEquals("fo", l.getExtension('f'));
    752         assertEquals("a-b-c-d-e-fo", l.getExtension('x'));
    753     }
    754 
    755     public void test_forLanguageTag() {
    756         test_setLanguageTag_wellFormedsingleSubtag(false);
    757         test_setLanguageTag_twoWellFormedSubtags(false);
    758         test_setLanguageTag_threeWellFormedSubtags(false);
    759         test_setLanguageTag_fourOrMoreWellFormedSubtags(false);
    760         test_setLanguageTag_withWellFormedExtensions(false);
    761     }
    762 
    763     public void test_Builder_setLanguageTag() {
    764         test_setLanguageTag_wellFormedsingleSubtag(true);
    765         test_setLanguageTag_twoWellFormedSubtags(true);
    766         test_setLanguageTag_threeWellFormedSubtags(true);
    767         test_setLanguageTag_fourOrMoreWellFormedSubtags(true);
    768         test_setLanguageTag_withWellFormedExtensions(true);
    769     }
    770 
    771     public void test_getDisplayScript() {
    772         Locale.Builder b = new Locale.Builder();
    773         b.setLanguage("en").setRegion("US").setScript("Latn");
    774 
    775         Locale l = b.build();
    776 
    777         // getDisplayScript() test relies on the default locale. We set it here to avoid test
    778         // failures if the test device is set to a non-English locale.
    779         Locale.setDefault(Locale.US);
    780         assertEquals("Latin", l.getDisplayScript());
    781 
    782         assertEquals("Lateinisch", l.getDisplayScript(Locale.GERMAN));
    783         // Fallback for navajo, a language for which we don't have data.
    784         assertEquals("Latin", l.getDisplayScript(new Locale("nv", "US")));
    785 
    786         b= new Locale.Builder();
    787         b.setLanguage("en").setRegion("US").setScript("Fooo");
    788 
    789         // Will be equivalent to getScriptCode for scripts that aren't
    790         // registered with ISO-15429 (but are otherwise well formed).
    791         l = b.build();
    792         assertEquals("Fooo", l.getDisplayScript());
    793     }
    794 
    795     public void test_setLanguageTag_malformedTags() {
    796         Locale l = fromLanguageTag("a", false);
    797         assertEquals("", l.getLanguage());
    798         assertEquals("", l.getCountry());
    799         assertEquals("", l.getVariant());
    800         assertEquals("", l.getScript());
    801 
    802         l = fromLanguageTag("en-US-BA", false);
    803         assertEquals("en", l.getLanguage());
    804         assertEquals("US", l.getCountry());
    805         assertEquals("", l.getVariant());
    806         assertEquals("", l.getScript());
    807 
    808         l = fromLanguageTag("en-FOOOO-BA", false);
    809         assertEquals("en", l.getLanguage());
    810         assertEquals("", l.getCountry());
    811         assertEquals("FOOOO", l.getVariant());
    812         assertEquals("", l.getScript());
    813 
    814         l = fromLanguageTag("en-US-POSIX-P2", false);
    815         assertEquals("en", l.getLanguage());
    816         assertEquals("US", l.getCountry());
    817         assertEquals("POSIX", l.getVariant());
    818         assertEquals("", l.getScript());
    819 
    820         l = fromLanguageTag("en-Latn-US-P2", false);
    821         assertEquals("en", l.getLanguage());
    822         assertEquals("US", l.getCountry());
    823         assertEquals("Latn", l.getScript());
    824 
    825         l = fromLanguageTag("en-f-f", false);
    826         assertEquals("en", l.getLanguage());
    827         assertEquals("", l.getCountry());
    828         assertEquals("", l.getVariant());
    829         assertEquals("", l.getScript());
    830 
    831         l = fromLanguageTag("en-f", false);
    832         assertEquals("en", l.getLanguage());
    833         assertEquals("", l.getCountry());
    834         assertEquals("", l.getVariant());
    835         assertEquals("", l.getScript());
    836 
    837         l = fromLanguageTag("en-f-fooobaaaz", false);
    838         assertEquals("en", l.getLanguage());
    839         assertEquals("", l.getCountry());
    840         assertEquals("", l.getVariant());
    841         assertEquals("", l.getScript());
    842 
    843         l = fromLanguageTag("en-9-baa", false);
    844         assertEquals("en", l.getLanguage());
    845         assertEquals("", l.getCountry());
    846         assertEquals("", l.getVariant());
    847         assertEquals("", l.getScript());
    848     }
    849 
    850     public void test_Builder_unicodeAttributes() {
    851         // Adding and removing attributes
    852         Locale.Builder b = new Locale.Builder();
    853         b.setLanguage("en");
    854 
    855         // Well formed attribute.
    856         b.addUnicodeLocaleAttribute("foooo");
    857 
    858         try {
    859             b.addUnicodeLocaleAttribute("fo");
    860             fail();
    861         } catch (IllformedLocaleException ifle) {
    862         }
    863 
    864         try {
    865             b.removeUnicodeLocaleAttribute("fo");
    866             fail();
    867         } catch (IllformedLocaleException ifle) {
    868         }
    869 
    870         try {
    871             b.addUnicodeLocaleAttribute("greaterthaneightchars");
    872             fail();
    873         } catch (IllformedLocaleException ifle) {
    874         }
    875 
    876         try {
    877             b.removeUnicodeLocaleAttribute("greaterthaneightchars");
    878             fail();
    879         } catch (IllformedLocaleException ifle) {
    880         }
    881 
    882         try {
    883             b.addUnicodeLocaleAttribute(null);
    884             fail();
    885         } catch (NullPointerException npe) {
    886         }
    887 
    888         try {
    889             b.removeUnicodeLocaleAttribute(null);
    890             fail();
    891         } catch (NullPointerException npe) {
    892         }
    893 
    894         Locale l = b.build();
    895         assertEquals("en-u-foooo", l.toLanguageTag());
    896         assertTrue(l.getUnicodeLocaleAttributes().contains("foooo"));
    897 
    898         b.addUnicodeLocaleAttribute("dAtA");
    899         l = b.build();
    900         assertEquals("data-foooo", l.getExtension('u'));
    901         assertTrue(l.getUnicodeLocaleAttributes().contains("data"));
    902         assertTrue(l.getUnicodeLocaleAttributes().contains("foooo"));
    903     }
    904 
    905     public void test_Builder_unicodeKeywords() {
    906         // Adding and removing attributes
    907         Locale.Builder b = new Locale.Builder();
    908         b.setLanguage("en");
    909 
    910         // Key not of length 2.
    911         try {
    912             b.setUnicodeLocaleKeyword("k", "fooo");
    913             fail();
    914         } catch (IllformedLocaleException ifle) {
    915         }
    916 
    917         // Value too short
    918         try {
    919             b.setUnicodeLocaleKeyword("k", "fo");
    920             fail();
    921         } catch (IllformedLocaleException ifle) {
    922         }
    923 
    924         // Value too long
    925         try {
    926             b.setUnicodeLocaleKeyword("k", "foooooooo");
    927             fail();
    928         } catch (IllformedLocaleException ifle) {
    929         }
    930 
    931 
    932         // Null should clear the key.
    933         b.setUnicodeLocaleKeyword("bo", "baaz");
    934         Locale l = b.build();
    935         assertEquals("bo-baaz", l.getExtension('u'));
    936         assertEquals("baaz", l.getUnicodeLocaleType("bo"));
    937 
    938         b = new Locale.Builder();
    939         b.setUnicodeLocaleKeyword("bo", "baaz");
    940         b.setUnicodeLocaleKeyword("bo", null);
    941         l = b.build();
    942         assertNull(l.getExtension('u'));
    943         assertNull(l.getUnicodeLocaleType("bo"));
    944 
    945         // When we set attributes, they should show up before extensions.
    946         b = new Locale.Builder();
    947         b.addUnicodeLocaleAttribute("fooo");
    948         b.addUnicodeLocaleAttribute("gooo");
    949         b.setUnicodeLocaleKeyword("fo", "baz");
    950         b.setUnicodeLocaleKeyword("ka", "kaz");
    951         l = b.build();
    952         assertEquals("fooo-gooo-fo-baz-ka-kaz", l.getExtension('u'));
    953         assertEquals("baz", l.getUnicodeLocaleType("fo"));
    954         assertEquals("kaz", l.getUnicodeLocaleType("ka"));
    955         assertTrue(l.getUnicodeLocaleAttributes().contains("fooo"));
    956         assertTrue(l.getUnicodeLocaleAttributes().contains("gooo"));
    957     }
    958 
    959     public void test_multipleExtensions() {
    960         Locale.Builder b = new Locale.Builder();
    961         b.setLanguage("en");
    962         b.addUnicodeLocaleAttribute("attrib");
    963         b.addUnicodeLocaleAttribute("attrib2");
    964         b.setExtension('f', "fo-baaz-ga-gaaz");
    965         b.setExtension('x', "xo-baaz-ga-gaaz");
    966         b.setExtension('z', "zo-baaz-ga-gaaz");
    967 
    968         Locale l = b.build();
    969         // Implicitly added because we added unicode locale attributes.
    970         assertEquals("attrib-attrib2", l.getExtension('u'));
    971         assertEquals("fo-baaz-ga-gaaz", l.getExtension('f'));
    972         assertEquals("xo-baaz-ga-gaaz", l.getExtension('x'));
    973         assertEquals("zo-baaz-ga-gaaz", l.getExtension('z'));
    974     }
    975 
    976     public void test_immutability() {
    977         Locale.Builder b = new Locale.Builder();
    978         b.setExtension('g', "fooo-baaz-baar");
    979         b.setExtension('u', "foooo-baaar-ba-baaz-ka-kaaz");
    980 
    981         Locale l = b.build();
    982         try {
    983             l.getExtensionKeys().add('g');
    984             fail();
    985         } catch (UnsupportedOperationException expected) {
    986         }
    987 
    988         try {
    989             l.getUnicodeLocaleAttributes().add("fooo");
    990             fail();
    991         } catch (UnsupportedOperationException expected) {
    992         }
    993     }
    994 
    995     public void test_toLanguageTag() {
    996         Locale.Builder b = new Locale.Builder();
    997 
    998         // Empty builder.
    999         Locale l = b.build();
   1000         assertEquals("und", l.toLanguageTag());
   1001 
   1002         // Only language.
   1003         b = new Locale.Builder();
   1004         b.setLanguage("en");
   1005         assertEquals("en", b.build().toLanguageTag());
   1006 
   1007         // Language & Region
   1008         b = new Locale.Builder();
   1009         b.setLanguage("en").setRegion("US");
   1010         assertEquals("en-US", b.build().toLanguageTag());
   1011 
   1012         // Language & Script
   1013         b = new Locale.Builder();
   1014         b.setLanguage("en").setScript("Latn");
   1015         assertEquals("en-Latn", b.build().toLanguageTag());
   1016 
   1017         // Language & Variant
   1018         b = new Locale.Builder();
   1019         b.setLanguage("en").setVariant("foooo");
   1020         assertEquals("en-foooo", b.build().toLanguageTag());
   1021 
   1022         // Language / script & country
   1023         b = new Locale.Builder();
   1024         b.setLanguage("en").setScript("Latn").setRegion("US");
   1025         assertEquals("en-Latn-US", b.build().toLanguageTag());
   1026 
   1027         // Language / script & variant
   1028         b = new Locale.Builder();
   1029         b.setLanguage("en").setScript("Latn").setVariant("foooo");
   1030         assertEquals("en-Latn-foooo", b.build().toLanguageTag());
   1031 
   1032         // Language / script / country / variant.
   1033         b = new Locale.Builder();
   1034         b.setLanguage("en").setScript("Latn").setVariant("foooo").setRegion("US");
   1035         assertEquals("en-Latn-US-foooo", b.build().toLanguageTag());
   1036 
   1037         // Language / extension
   1038         b = new Locale.Builder();
   1039         b.setLanguage("en").setExtension('x', "fooo-baar");
   1040         assertEquals("en-x-fooo-baar", b.build().toLanguageTag());
   1041 
   1042         // Language & multiple extensions (including unicode).
   1043         b = new Locale.Builder();
   1044         b.setLanguage("en");
   1045         b.addUnicodeLocaleAttribute("attrib");
   1046         b.addUnicodeLocaleAttribute("attrib2");
   1047         b.setExtension('f', "fo-baaz-ga-gaaz");
   1048         b.setExtension('x', "xo-baaz-ga-gaaz");
   1049         b.setExtension('z', "zo-baaz-ga-gaaz");
   1050 
   1051         l = b.build();
   1052         // Implicitly added because we added unicode locale attributes.
   1053         assertEquals("attrib-attrib2", l.getExtension('u'));
   1054         assertEquals("fo-baaz-ga-gaaz", l.getExtension('f'));
   1055         assertEquals("xo-baaz-ga-gaaz", l.getExtension('x'));
   1056         assertEquals("zo-baaz-ga-gaaz", l.getExtension('z'));
   1057 
   1058         assertEquals("en-" +
   1059                 "f-fo-baaz-ga-gaaz-" +   // extension tags in lexical order
   1060                 "u-attrib-attrib2-z-zo-baaz-ga-gaaz-" +  // unicode attribs & keywords in lex order
   1061                 "x-xo-baaz-ga-gaaz", // private use extension unmodified.
   1062                 l.toLanguageTag());
   1063     }
   1064 
   1065     public void test_toString() {
   1066         Locale.Builder b = new Locale.Builder();
   1067 
   1068         // Empty builder.
   1069         Locale l = b.build();
   1070         assertEquals("", l.toString());
   1071 
   1072         // Only language.
   1073         b = new Locale.Builder();
   1074         b.setLanguage("en");
   1075         assertEquals("en", b.build().toString());
   1076 
   1077         // Only region
   1078         b = new Locale.Builder();
   1079         b.setRegion("US");
   1080         assertEquals("_US", b.build().toString());
   1081 
   1082         // Language & Region
   1083         b = new Locale.Builder();
   1084         b.setLanguage("en").setRegion("US");
   1085         assertEquals("en_US", b.build().toString());
   1086 
   1087         // Language & Script
   1088         b = new Locale.Builder();
   1089         b.setLanguage("en").setScript("Latn");
   1090         assertEquals("en__#Latn", b.build().toString());
   1091 
   1092         // Language & Variant
   1093         b = new Locale.Builder();
   1094         b.setLanguage("en").setVariant("foooo");
   1095         assertEquals("en__foooo", b.build().toString());
   1096 
   1097         // Language / script & country
   1098         b = new Locale.Builder();
   1099         b.setLanguage("en").setScript("Latn").setRegion("US");
   1100         assertEquals("en_US_#Latn", b.build().toString());
   1101 
   1102         // Language / script & variant
   1103         b = new Locale.Builder();
   1104         b.setLanguage("en").setScript("Latn").setVariant("foooo");
   1105         assertEquals("en__foooo_#Latn", b.build().toString());
   1106 
   1107         // Language / script / country / variant.
   1108         b = new Locale.Builder();
   1109         b.setLanguage("en").setScript("Latn").setVariant("foooo").setRegion("US");
   1110         assertEquals("en_US_foooo_#Latn", b.build().toString());
   1111 
   1112         // Language / extension
   1113         b = new Locale.Builder();
   1114         b.setLanguage("en").setExtension('x', "fooo-baar");
   1115         assertEquals("en__#x-fooo-baar", b.build().toString());
   1116     }
   1117 
   1118     // Tests cases where our "guess" for the output size is incorrect.
   1119     //
   1120     // https://b.corp.google.com/issue?id=13414549
   1121     public void test_toLanguageTag_largerTag() {
   1122         Locale posix = new Locale.Builder()
   1123                 .setLanguage("en").setRegion("US").setVariant("POSIX")
   1124                 .build();
   1125         assertEquals("en-US-POSIX", posix.toLanguageTag());
   1126     }
   1127 
   1128     public void test_forLanguageTag_grandFatheredLocale() {
   1129         // Regular grandfathered locale.
   1130         Locale gaulish = Locale.forLanguageTag("cel-gaulish");
   1131         assertEquals("xtg", gaulish.getLanguage());
   1132         assertEquals("cel-gaulish", gaulish.getExtension(Locale.PRIVATE_USE_EXTENSION));
   1133         assertEquals("", gaulish.getCountry());
   1134         assertEquals("", gaulish.getScript());
   1135         assertEquals("", gaulish.getVariant());
   1136 
   1137         // Irregular grandfathered locale.
   1138         Locale enochian = Locale.forLanguageTag("i-enochian");
   1139         assertEquals("", enochian.getLanguage());
   1140         assertEquals("i-enochian", enochian.getExtension(Locale.PRIVATE_USE_EXTENSION));
   1141         assertEquals("", enochian.getCountry());
   1142         assertEquals("", enochian.getScript());
   1143         assertEquals("", enochian.getVariant());
   1144     }
   1145 
   1146     // Test case from http://b/16811867
   1147     public void testVariantsCaseSensitive() {
   1148         final Locale locale = new Locale("en", "US", "variant");
   1149         assertEquals("variant", locale.getVariant());
   1150         assertEquals(locale, Locale.forLanguageTag(locale.toLanguageTag()));
   1151     }
   1152 
   1153     public void testArabicDigits() throws Exception {
   1154         // ar-DZ uses latn digits by default, but we can override that.
   1155         Locale ar_DZ = Locale.forLanguageTag("ar-DZ");
   1156         Locale ar_DZ_arab = Locale.forLanguageTag("ar-DZ-u-nu-arab");
   1157         Locale ar_DZ_latn = Locale.forLanguageTag("ar-DZ-u-nu-latn");
   1158         assertEquals('0', new DecimalFormatSymbols(ar_DZ).getZeroDigit());
   1159         assertEquals('\u0660', new DecimalFormatSymbols(ar_DZ_arab).getZeroDigit());
   1160         assertEquals('0', new DecimalFormatSymbols(ar_DZ_latn).getZeroDigit());
   1161 
   1162         // ar-EG uses arab digits by default, but we can override that.
   1163         Locale ar_EG = Locale.forLanguageTag("ar-EG");
   1164         Locale ar_EG_arab = Locale.forLanguageTag("ar-EG-u-nu-arab");
   1165         Locale ar_EG_latn = Locale.forLanguageTag("ar-EG-u-nu-latn");
   1166         assertEquals('\u0660', new DecimalFormatSymbols(ar_EG).getZeroDigit());
   1167         assertEquals('\u0660', new DecimalFormatSymbols(ar_EG_arab).getZeroDigit());
   1168         assertEquals('0', new DecimalFormatSymbols(ar_EG_latn).getZeroDigit());
   1169     }
   1170 
   1171     public void testDefaultLocale() throws Exception {
   1172         final String userLanguage = System.getProperty("user.language", "");
   1173         final String userRegion = System.getProperty("user.region", "");
   1174         final String userLocale = System.getProperty("user.locale", "");
   1175         try {
   1176             // Assert that user.locale gets priority.
   1177             System.setUnchangeableSystemProperty("user.locale", "de-DE");
   1178             System.setUnchangeableSystemProperty("user.language", "en");
   1179             System.setUnchangeableSystemProperty("user.region", "US");
   1180 
   1181             Locale l = Locale.initDefault();
   1182             assertEquals("de", l.getLanguage());
   1183             assertEquals("DE", l.getCountry());
   1184 
   1185             // Assert that it's parsed as a full language tag.
   1186             System.setUnchangeableSystemProperty("user.locale", "de-Latn-DE");
   1187             System.setUnchangeableSystemProperty("user.language", "en");
   1188             System.setUnchangeableSystemProperty("user.region", "US");
   1189 
   1190             l = Locale.initDefault();
   1191             assertEquals("de", l.getLanguage());
   1192             assertEquals("DE", l.getCountry());
   1193             assertEquals("Latn", l.getScript());
   1194 
   1195             // Assert that we don't end up with a null default locale or an exception.
   1196             System.setUnchangeableSystemProperty("user.locale", "toolonglang-Latn-DE");
   1197 
   1198             // Note: pre-enso Locale#fromLanguageTag parser was more error-tolerant
   1199             // then the current one. Result of bad language part of tag from line above
   1200             // will be an empty Locale object.
   1201             l = Locale.initDefault();
   1202             assertEquals("", l.getLanguage());
   1203             assertEquals("", l.getCountry());
   1204         } finally {
   1205             System.setUnchangeableSystemProperty("user.language", userLanguage);
   1206             System.setUnchangeableSystemProperty("user.region", userRegion);
   1207             System.setUnchangeableSystemProperty("user.locale", userLocale);
   1208         }
   1209     }
   1210 
   1211     // http://b/20252611
   1212     public void testLegacyLocalesWithExtensions() {
   1213         Locale ja_JP_JP = new Locale("ja", "JP", "JP");
   1214         assertEquals("ca-japanese", ja_JP_JP.getExtension(Locale.UNICODE_LOCALE_EXTENSION));
   1215         assertEquals("japanese", ja_JP_JP.getUnicodeLocaleType("ca"));
   1216 
   1217         Locale th_TH_TH = new Locale("th", "TH", "TH");
   1218         assertEquals("nu-thai", th_TH_TH.getExtension(Locale.UNICODE_LOCALE_EXTENSION));
   1219         assertEquals("thai", th_TH_TH.getUnicodeLocaleType("nu"));
   1220     }
   1221 
   1222     // http://b/20252611
   1223     public void testLowerCaseExtensionKeys() {
   1224         // We must lowercase extension keys in forLanguageTag..
   1225         Locale ar_EG = Locale.forLanguageTag("ar-EG-U-nu-arab");
   1226         assertEquals("nu-arab", ar_EG.getExtension(Locale.UNICODE_LOCALE_EXTENSION));
   1227         assertEquals("ar-EG-u-nu-arab", ar_EG.toLanguageTag());
   1228 
   1229         // ... and in builders.
   1230         Locale.Builder b = new Locale.Builder();
   1231         b.setLanguage("ar");
   1232         b.setRegion("EG");
   1233         b.setExtension('U', "nu-arab");
   1234         assertEquals("ar-EG-u-nu-arab", b.build().toLanguageTag());
   1235 
   1236         // Corollary : extension keys are case insensitive.
   1237         b = new Locale.Builder();
   1238         b.setLanguage("ar");
   1239         b.setRegion("EG");
   1240         b.setExtension('U', "nu-arab");
   1241         b.setExtension('u', "nu-thai");
   1242         assertEquals("ar-EG-u-nu-thai", b.build().toLanguageTag());
   1243     }
   1244 
   1245     // http://b/26387905
   1246     public void test_SerializationBug_26387905() throws Exception {
   1247         try (ObjectInputStream oinput = new ObjectInputStream(getClass()
   1248                 .getResource("/serialization/org/apache/harmony/tests/java/util/Locale_Bug_26387905.ser")
   1249                 .openStream())) {
   1250             Locale l = (Locale) oinput.readObject();
   1251         }
   1252     }
   1253 
   1254     public void test_setDefault_withCategory() {
   1255         final Locale defaultLocale = Locale.getDefault();
   1256         try {
   1257             Locale.setDefault(Locale.US);
   1258             assertEquals(Locale.US, Locale.getDefault(Locale.Category.FORMAT));
   1259             assertEquals(Locale.US, Locale.getDefault(Locale.Category.DISPLAY));
   1260             assertEquals(Locale.US, Locale.getDefault());
   1261 
   1262             Locale.setDefault(Locale.Category.FORMAT, Locale.UK);
   1263             assertEquals(Locale.UK, Locale.getDefault(Locale.Category.FORMAT));
   1264             assertEquals(Locale.US, Locale.getDefault(Locale.Category.DISPLAY));
   1265             assertEquals(Locale.US, Locale.getDefault());
   1266 
   1267             Locale.setDefault(Locale.Category.DISPLAY, Locale.CANADA);
   1268             assertEquals(Locale.UK, Locale.getDefault(Locale.Category.FORMAT));
   1269             assertEquals(Locale.CANADA, Locale.getDefault(Locale.Category.DISPLAY));
   1270             assertEquals(Locale.US, Locale.getDefault());
   1271 
   1272             Locale.setDefault(Locale.FRANCE);
   1273             assertEquals(Locale.FRANCE, Locale.getDefault(Locale.Category.FORMAT));
   1274             assertEquals(Locale.FRANCE, Locale.getDefault(Locale.Category.DISPLAY));
   1275             assertEquals(Locale.FRANCE, Locale.getDefault());
   1276         } finally {
   1277             Locale.setDefault(defaultLocale);
   1278         }
   1279     }
   1280 }
   1281