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
17package libcore.java.util;
18
19import java.io.ObjectInputStream;
20import java.text.BreakIterator;
21import java.text.Collator;
22import java.text.DateFormat;
23import java.text.DateFormatSymbols;
24import java.text.DecimalFormatSymbols;
25import java.text.NumberFormat;
26import java.util.Calendar;
27import java.util.IllformedLocaleException;
28import java.util.Locale;
29import java.util.MissingResourceException;
30
31public 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