Path: blob/jdk8u272-b10-aarch32-20201026/jdk/test/java/util/Locale/LocaleEnhanceTest.java
48795 views
/*1* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.BufferedReader;24import java.io.ByteArrayInputStream;25import java.io.ByteArrayOutputStream;26import java.io.File;27import java.io.FileInputStream;28import java.io.InputStreamReader;29import java.io.ObjectInputStream;30import java.io.ObjectOutputStream;31import java.net.URISyntaxException;32import java.net.URL;33import java.text.DecimalFormatSymbols;34import java.util.ArrayList;35import java.util.Arrays;36import java.util.Calendar;37import java.util.IllformedLocaleException;38import java.util.List;39import java.util.Locale;40import java.util.Locale.Builder;41import java.util.Set;4243/**44* @test45* @bug 6875847 6992272 7002320 7015500 7023613 7032820 7033504 7004603 704401946* @summary test API changes to Locale47* @compile LocaleEnhanceTest.java48* @run main/othervm -esa LocaleEnhanceTest49*/50public class LocaleEnhanceTest extends LocaleTestFmwk {5152public static void main(String[] args) throws Exception {53List<String> argList = new ArrayList<String>();54argList.addAll(Arrays.asList(args));55argList.add("-nothrow");56new LocaleEnhanceTest().run(argList.toArray(new String[argList.size()]));57}5859public LocaleEnhanceTest() {60}6162///63/// Generic sanity tests64///6566/** A canonical language code. */67private static final String l = "en";6869/** A canonical script code.. */70private static final String s = "Latn";7172/** A canonical region code. */73private static final String c = "US";7475/** A canonical variant code. */76private static final String v = "NewYork";7778/**79* Ensure that Builder builds locales that have the expected80* tag and java6 ID. Note the odd cases for the ID.81*/82public void testCreateLocaleCanonicalValid() {83String[] valids = {84"en-Latn-US-NewYork", "en_US_NewYork_#Latn",85"en-Latn-US", "en_US_#Latn",86"en-Latn-NewYork", "en__NewYork_#Latn", // double underscore87"en-Latn", "en__#Latn", // double underscore88"en-US-NewYork", "en_US_NewYork",89"en-US", "en_US",90"en-NewYork", "en__NewYork", // double underscore91"en", "en",92"und-Latn-US-NewYork", "_US_NewYork_#Latn",93"und-Latn-US", "_US_#Latn",94"und-Latn-NewYork", "", // variant only not supported95"und-Latn", "",96"und-US-NewYork", "_US_NewYork",97"und-US", "_US",98"und-NewYork", "", // variant only not supported99"und", ""100};101102Builder builder = new Builder();103104for (int i = 0; i < valids.length; i += 2) {105String tag = valids[i];106String id = valids[i+1];107108String idl = (i & 16) == 0 ? l : "";109String ids = (i & 8) == 0 ? s : "";110String idc = (i & 4) == 0 ? c : "";111String idv = (i & 2) == 0 ? v : "";112113String msg = String.valueOf(i/2) + ": '" + tag + "' ";114115try {116Locale l = builder117.setLanguage(idl)118.setScript(ids)119.setRegion(idc)120.setVariant(idv)121.build();122assertEquals(msg + "language", idl, l.getLanguage());123assertEquals(msg + "script", ids, l.getScript());124assertEquals(msg + "country", idc, l.getCountry());125assertEquals(msg + "variant", idv, l.getVariant());126assertEquals(msg + "tag", tag, l.toLanguageTag());127assertEquals(msg + "id", id, l.toString());128}129catch (IllegalArgumentException e) {130errln(msg + e.getMessage());131}132}133}134135/**136* Test that locale construction works with 'multiple variants'.137* <p>138* The string "Newer__Yorker" is treated as three subtags,139* "Newer", "", and "Yorker", and concatenated into one140* subtag by omitting empty subtags and joining the remainer141* with underscores. So the resulting variant tag is "Newer_Yorker".142* Note that 'New' and 'York' are invalid BCP47 variant subtags143* because they are too short.144*/145public void testCreateLocaleMultipleVariants() {146147String[] valids = {148"en-Latn-US-Newer-Yorker", "en_US_Newer_Yorker_#Latn",149"en-Latn-Newer-Yorker", "en__Newer_Yorker_#Latn",150"en-US-Newer-Yorker", "en_US_Newer_Yorker",151"en-Newer-Yorker", "en__Newer_Yorker",152"und-Latn-US-Newer-Yorker", "_US_Newer_Yorker_#Latn",153"und-Latn-Newer-Yorker", "",154"und-US-Newer-Yorker", "_US_Newer_Yorker",155"und-Newer-Yorker", "",156};157158Builder builder = new Builder(); // lenient variant159160final String idv = "Newer_Yorker";161for (int i = 0; i < valids.length; i += 2) {162String tag = valids[i];163String id = valids[i+1];164165String idl = (i & 8) == 0 ? l : "";166String ids = (i & 4) == 0 ? s : "";167String idc = (i & 2) == 0 ? c : "";168169String msg = String.valueOf(i/2) + ": " + tag + " ";170try {171Locale l = builder172.setLanguage(idl)173.setScript(ids)174.setRegion(idc)175.setVariant(idv)176.build();177178assertEquals(msg + " language", idl, l.getLanguage());179assertEquals(msg + " script", ids, l.getScript());180assertEquals(msg + " country", idc, l.getCountry());181assertEquals(msg + " variant", idv, l.getVariant());182183assertEquals(msg + "tag", tag, l.toLanguageTag());184assertEquals(msg + "id", id, l.toString());185}186catch (IllegalArgumentException e) {187errln(msg + e.getMessage());188}189}190}191192/**193* Ensure that all these invalid formats are not recognized by194* forLanguageTag.195*/196public void testCreateLocaleCanonicalInvalidSeparator() {197String[] invalids = {198// trailing separator199"en_Latn_US_NewYork_",200"en_Latn_US_",201"en_Latn_",202"en_",203"_",204205// double separator206"en_Latn_US__NewYork",207"_Latn_US__NewYork",208"en_US__NewYork",209"_US__NewYork",210211// are these OK?212// "en_Latn__US_NewYork", // variant is 'US_NewYork'213// "_Latn__US_NewYork", // variant is 'US_NewYork'214// "en__Latn_US_NewYork", // variant is 'Latn_US_NewYork'215// "en__US_NewYork", // variant is 'US_NewYork'216217// double separator without language or script218"__US",219"__NewYork",220221// triple separator anywhere except within variant222"en___NewYork",223"en_Latn___NewYork",224"_Latn___NewYork",225"___NewYork",226};227228for (int i = 0; i < invalids.length; ++i) {229String id = invalids[i];230Locale l = Locale.forLanguageTag(id);231assertEquals(id, "und", l.toLanguageTag());232}233}234235/**236* Ensure that all current locale ids parse. Use DateFormat as a proxy237* for all current locale ids.238*/239public void testCurrentLocales() {240Locale[] locales = java.text.DateFormat.getAvailableLocales();241Builder builder = new Builder();242243for (Locale target : locales) {244String tag = target.toLanguageTag();245246// the tag recreates the original locale,247// except no_NO_NY248Locale tagResult = Locale.forLanguageTag(tag);249if (!target.getVariant().equals("NY")) {250assertEquals("tagResult", target, tagResult);251}252253// the builder also recreates the original locale,254// except ja_JP_JP, th_TH_TH and no_NO_NY255Locale builderResult = builder.setLocale(target).build();256if (target.getVariant().length() != 2) {257assertEquals("builderResult", target, builderResult);258}259}260}261262/**263* Ensure that all icu locale ids parse.264*/265public void testIcuLocales() throws Exception {266BufferedReader br = new BufferedReader(267new InputStreamReader(268LocaleEnhanceTest.class.getResourceAsStream("icuLocales.txt"),269"UTF-8"));270String id = null;271while (null != (id = br.readLine())) {272Locale result = Locale.forLanguageTag(id);273assertEquals("ulocale", id, result.toLanguageTag());274}275}276277///278/// Compatibility tests279///280281public void testConstructor() {282// all the old weirdness still holds, no new weirdness283String[][] tests = {284// language to lower case, region to upper, variant unchanged285// short286{ "X", "y", "z", "x", "Y" },287// long288{ "xXxXxXxXxXxX", "yYyYyYyYyYyYyYyY", "zZzZzZzZzZzZzZzZ",289"xxxxxxxxxxxx", "YYYYYYYYYYYYYYYY" },290// mapped language ids291{ "he", "IW", "", "iw" },292{ "iw", "IW", "", "iw" },293{ "yi", "DE", "", "ji" },294{ "ji", "DE", "", "ji" },295{ "id", "ID", "", "in" },296{ "in", "ID", "", "in" },297// special variants298{ "ja", "JP", "JP" },299{ "th", "TH", "TH" },300{ "no", "NO", "NY" },301{ "no", "NO", "NY" },302// no canonicalization of 3-letter language codes303{ "eng", "US", "" }304};305for (int i = 0; i < tests.length; ++ i) {306String[] test = tests[i];307String id = String.valueOf(i);308Locale locale = new Locale(test[0], test[1], test[2]);309assertEquals(id + " lang", test.length > 3 ? test[3] : test[0], locale.getLanguage());310assertEquals(id + " region", test.length > 4 ? test[4] : test[1], locale.getCountry());311assertEquals(id + " variant", test.length > 5 ? test[5] : test[2], locale.getVariant());312}313}314315///316/// Locale API tests.317///318319public void testGetScript() {320// forLanguageTag normalizes case321Locale locale = Locale.forLanguageTag("und-latn");322assertEquals("forLanguageTag", "Latn", locale.getScript());323324// Builder normalizes case325locale = new Builder().setScript("LATN").build();326assertEquals("builder", "Latn", locale.getScript());327328// empty string is returned, not null, if there is no script329locale = Locale.forLanguageTag("und");330assertEquals("script is empty string", "", locale.getScript());331}332333public void testGetExtension() {334// forLanguageTag does NOT normalize to hyphen335Locale locale = Locale.forLanguageTag("und-a-some_ex-tension");336assertEquals("some_ex-tension", null, locale.getExtension('a'));337338// regular extension339locale = new Builder().setExtension('a', "some-ex-tension").build();340assertEquals("builder", "some-ex-tension", locale.getExtension('a'));341342// returns null if extension is not present343assertEquals("empty b", null, locale.getExtension('b'));344345// throws exception if extension tag is illegal346new ExpectIAE() { public void call() { Locale.forLanguageTag("").getExtension('\uD800'); }};347348// 'x' is not an extension, it's a private use tag, but it's accessed through this API349locale = Locale.forLanguageTag("x-y-z-blork");350assertEquals("x", "y-z-blork", locale.getExtension('x'));351}352353public void testGetExtensionKeys() {354Locale locale = Locale.forLanguageTag("und-a-xx-yy-b-zz-ww");355Set<Character> result = locale.getExtensionKeys();356assertEquals("result size", 2, result.size());357assertTrue("'a','b'", result.contains('a') && result.contains('b'));358359// result is not mutable360try {361result.add('x');362errln("expected exception on add to extension key set");363}364catch (UnsupportedOperationException e) {365// ok366}367368// returns empty set if no extensions369locale = Locale.forLanguageTag("und");370assertTrue("empty result", locale.getExtensionKeys().isEmpty());371}372373public void testGetUnicodeLocaleAttributes() {374Locale locale = Locale.forLanguageTag("en-US-u-abc-def");375Set<String> attributes = locale.getUnicodeLocaleAttributes();376assertEquals("number of attributes", 2, attributes.size());377assertTrue("attribute abc", attributes.contains("abc"));378assertTrue("attribute def", attributes.contains("def"));379380locale = Locale.forLanguageTag("en-US-u-ca-gregory");381attributes = locale.getUnicodeLocaleAttributes();382assertTrue("empty attributes", attributes.isEmpty());383}384385public void testGetUnicodeLocaleType() {386Locale locale = Locale.forLanguageTag("und-u-co-japanese-nu-thai");387assertEquals("collation", "japanese", locale.getUnicodeLocaleType("co"));388assertEquals("numbers", "thai", locale.getUnicodeLocaleType("nu"));389390// Unicode locale extension key is case insensitive391assertEquals("key case", "japanese", locale.getUnicodeLocaleType("Co"));392393// if keyword is not present, returns null394assertEquals("locale keyword not present", null, locale.getUnicodeLocaleType("xx"));395396// if no locale extension is set, returns null397locale = Locale.forLanguageTag("und");398assertEquals("locale extension not present", null, locale.getUnicodeLocaleType("co"));399400// typeless keyword401locale = Locale.forLanguageTag("und-u-kn");402assertEquals("typeless keyword", "", locale.getUnicodeLocaleType("kn"));403404// invalid keys throw exception405new ExpectIAE() { public void call() { Locale.forLanguageTag("").getUnicodeLocaleType("q"); }};406new ExpectIAE() { public void call() { Locale.forLanguageTag("").getUnicodeLocaleType("abcdefghi"); }};407408// null argument throws exception409new ExpectNPE() { public void call() { Locale.forLanguageTag("").getUnicodeLocaleType(null); }};410}411412public void testGetUnicodeLocaleKeys() {413Locale locale = Locale.forLanguageTag("und-u-co-japanese-nu-thai");414Set<String> result = locale.getUnicodeLocaleKeys();415assertEquals("two keys", 2, result.size());416assertTrue("co and nu", result.contains("co") && result.contains("nu"));417418// result is not modifiable419try {420result.add("frobozz");421errln("expected exception when add to locale key set");422}423catch (UnsupportedOperationException e) {424// ok425}426}427428public void testPrivateUseExtension() {429Locale locale = Locale.forLanguageTag("x-y-x-blork-");430assertEquals("blork", "y-x-blork", locale.getExtension(Locale.PRIVATE_USE_EXTENSION));431432locale = Locale.forLanguageTag("und");433assertEquals("no privateuse", null, locale.getExtension(Locale.PRIVATE_USE_EXTENSION));434}435436public void testToLanguageTag() {437// lots of normalization to test here438// test locales created using the constructor439String[][] tests = {440// empty locale canonicalizes to 'und'441{ "", "", "", "und" },442// variant alone is not a valid Locale, but has a valid language tag443{ "", "", "NewYork", "und-NewYork" },444// standard valid locales445{ "", "Us", "", "und-US" },446{ "", "US", "NewYork", "und-US-NewYork" },447{ "EN", "", "", "en" },448{ "EN", "", "NewYork", "en-NewYork" },449{ "EN", "US", "", "en-US" },450{ "EN", "US", "NewYork", "en-US-NewYork" },451// underscore in variant will be emitted as multiple variant subtags452{ "en", "US", "Newer_Yorker", "en-US-Newer-Yorker" },453// invalid variant subtags are appended as private use454{ "en", "US", "new_yorker", "en-US-x-lvariant-new-yorker" },455// the first invalid variant subtags and following variant subtags are appended as private use456{ "en", "US", "Windows_XP_Home", "en-US-Windows-x-lvariant-XP-Home" },457// too long variant and following variant subtags disappear458{ "en", "US", "WindowsVista_SP2", "en-US" },459// invalid region subtag disappears460{ "en", "USA", "", "en" },461// invalid language tag disappears462{ "e", "US", "", "und-US" },463// three-letter language tags are not canonicalized464{ "Eng", "", "", "eng" },465// legacy languages canonicalize to modern equivalents466{ "he", "IW", "", "he-IW" },467{ "iw", "IW", "", "he-IW" },468{ "yi", "DE", "", "yi-DE" },469{ "ji", "DE", "", "yi-DE" },470{ "id", "ID", "", "id-ID" },471{ "in", "ID", "", "id-ID" },472// special values are converted on output473{ "ja", "JP", "JP", "ja-JP-u-ca-japanese-x-lvariant-JP" },474{ "th", "TH", "TH", "th-TH-u-nu-thai-x-lvariant-TH" },475{ "no", "NO", "NY", "nn-NO" }476};477for (int i = 0; i < tests.length; ++i) {478String[] test = tests[i];479Locale locale = new Locale(test[0], test[1], test[2]);480assertEquals("case " + i, test[3], locale.toLanguageTag());481}482483// test locales created from forLanguageTag484String[][] tests1 = {485// case is normalized during the round trip486{ "EN-us", "en-US" },487{ "en-Latn-US", "en-Latn-US" },488// reordering Unicode locale extensions489{ "de-u-co-phonebk-ca-gregory", "de-u-ca-gregory-co-phonebk" },490// private use only language tag is preserved (no extra "und")491{ "x-elmer", "x-elmer" },492{ "x-lvariant-JP", "x-lvariant-JP" },493};494for (String[] test : tests1) {495Locale locale = Locale.forLanguageTag(test[0]);496assertEquals("case " + test[0], test[1], locale.toLanguageTag());497}498499}500501public void testForLanguageTag() {502// forLanguageTag implements the 'Language-Tag' production of503// BCP47, so it handles private use and grandfathered tags,504// unlike locale builder. Tags listed below (except for the505// sample private use tags) come from 4646bis Feb 29, 2009.506507String[][] tests = {508// private use tags only509{ "x-abc", "x-abc" },510{ "x-a-b-c", "x-a-b-c" },511{ "x-a-12345678", "x-a-12345678" },512513// grandfathered tags with preferred mappings514{ "i-ami", "ami" },515{ "i-bnn", "bnn" },516{ "i-hak", "hak" },517{ "i-klingon", "tlh" },518{ "i-lux", "lb" }, // two-letter tag519{ "i-navajo", "nv" }, // two-letter tag520{ "i-pwn", "pwn" },521{ "i-tao", "tao" },522{ "i-tay", "tay" },523{ "i-tsu", "tsu" },524{ "art-lojban", "jbo" },525{ "no-bok", "nb" },526{ "no-nyn", "nn" },527{ "sgn-BE-FR", "sfb" },528{ "sgn-BE-NL", "vgt" },529{ "sgn-CH-DE", "sgg" },530{ "zh-guoyu", "cmn" },531{ "zh-hakka", "hak" },532{ "zh-min-nan", "nan" },533{ "zh-xiang", "hsn" },534535// grandfathered irregular tags, no preferred mappings, drop illegal fields536// from end. If no subtag is mappable, fallback to 'und'537{ "i-default", "en-x-i-default" },538{ "i-enochian", "x-i-enochian" },539{ "i-mingo", "see-x-i-mingo" },540{ "en-GB-oed", "en-GB-x-oed" },541{ "zh-min", "nan-x-zh-min" },542{ "cel-gaulish", "xtg-x-cel-gaulish" },543};544for (int i = 0; i < tests.length; ++i) {545String[] test = tests[i];546Locale locale = Locale.forLanguageTag(test[0]);547assertEquals("grandfathered case " + i, test[1], locale.toLanguageTag());548}549550// forLanguageTag ignores everything past the first place it encounters551// a syntax error552tests = new String[][] {553{ "valid",554"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-12345678-z",555"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-12345678-z" },556{ "segment of private use tag too long",557"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-123456789-z",558"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y" },559{ "segment of private use tag is empty",560"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y--12345678-z",561"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y" },562{ "first segment of private use tag is empty",563"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x--y-12345678-z",564"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def" },565{ "illegal extension tag",566"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-\uD800-y-12345678-z",567"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def" },568{ "locale subtag with no value",569"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-x-y-12345678-z",570"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-x-y-12345678-z" },571{ "locale key subtag invalid",572"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-123456789-def-x-y-12345678-z",573"en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc" },574// locale key subtag invalid in earlier position, all following subtags575// dropped (and so the locale extension dropped as well)576{ "locale key subtag invalid in earlier position",577"en-US-Newer-Yorker-a-bb-cc-dd-u-123456789-abc-bb-def-x-y-12345678-z",578"en-US-Newer-Yorker-a-bb-cc-dd" },579};580for (int i = 0; i < tests.length; ++i) {581String[] test = tests[i];582String msg = "syntax error case " + i + " " + test[0];583try {584Locale locale = Locale.forLanguageTag(test[1]);585assertEquals(msg, test[2], locale.toLanguageTag());586}587catch (IllegalArgumentException e) {588errln(msg + " caught exception: " + e);589}590}591592// duplicated extension are just ignored593Locale locale = Locale.forLanguageTag("und-d-aa-00-bb-01-D-AA-10-cc-11-c-1234");594assertEquals("extension", "aa-00-bb-01", locale.getExtension('d'));595assertEquals("extension c", "1234", locale.getExtension('c'));596597locale = Locale.forLanguageTag("und-U-ca-gregory-u-ca-japanese");598assertEquals("Unicode extension", "ca-gregory", locale.getExtension(Locale.UNICODE_LOCALE_EXTENSION));599600// redundant Unicode locale keys in an extension are ignored601locale = Locale.forLanguageTag("und-u-aa-000-bb-001-bB-002-cc-003-c-1234");602assertEquals("Unicode keywords", "aa-000-bb-001-cc-003", locale.getExtension(Locale.UNICODE_LOCALE_EXTENSION));603assertEquals("Duplicated Unicode locake key followed by an extension", "1234", locale.getExtension('c'));604}605606public void testGetDisplayScript() {607Locale latnLocale = Locale.forLanguageTag("und-latn");608Locale hansLocale = Locale.forLanguageTag("und-hans");609610Locale oldLocale = Locale.getDefault();611612Locale.setDefault(Locale.US);613assertEquals("latn US", "Latin", latnLocale.getDisplayScript());614assertEquals("hans US", "Simplified Han", hansLocale.getDisplayScript());615616Locale.setDefault(Locale.GERMANY);617assertEquals("latn DE", "Lateinisch", latnLocale.getDisplayScript());618assertEquals("hans DE", "Vereinfachte Chinesische Schrift", hansLocale.getDisplayScript());619620Locale.setDefault(oldLocale);621}622623public void testGetDisplayScriptWithLocale() {624Locale latnLocale = Locale.forLanguageTag("und-latn");625Locale hansLocale = Locale.forLanguageTag("und-hans");626627assertEquals("latn US", "Latin", latnLocale.getDisplayScript(Locale.US));628assertEquals("hans US", "Simplified Han", hansLocale.getDisplayScript(Locale.US));629630assertEquals("latn DE", "Lateinisch", latnLocale.getDisplayScript(Locale.GERMANY));631assertEquals("hans DE", "Vereinfachte Chinesische Schrift", hansLocale.getDisplayScript(Locale.GERMANY));632}633634public void testGetDisplayName() {635final Locale[] testLocales = {636Locale.ROOT,637new Locale("en"),638new Locale("en", "US"),639new Locale("", "US"),640new Locale("no", "NO", "NY"),641new Locale("", "", "NY"),642Locale.forLanguageTag("zh-Hans"),643Locale.forLanguageTag("zh-Hant"),644Locale.forLanguageTag("zh-Hans-CN"),645Locale.forLanguageTag("und-Hans"),646};647648final String[] displayNameEnglish = {649"",650"English",651"English (United States)",652"United States",653"Norwegian (Norway,Nynorsk)",654"Nynorsk",655"Chinese (Simplified Han)",656"Chinese (Traditional Han)",657"Chinese (Simplified Han,China)",658"Simplified Han",659};660661final String[] displayNameSimplifiedChinese = {662"",663"\u82f1\u6587",664"\u82f1\u6587 (\u7f8e\u56fd)",665"\u7f8e\u56fd",666"\u632a\u5a01\u6587 (\u632a\u5a01,Nynorsk)",667"Nynorsk",668"\u4e2d\u6587 (\u7b80\u4f53\u4e2d\u6587)",669"\u4e2d\u6587 (\u7e41\u4f53\u4e2d\u6587)",670"\u4e2d\u6587 (\u7b80\u4f53\u4e2d\u6587,\u4e2d\u56fd)",671"\u7b80\u4f53\u4e2d\u6587",672};673674for (int i = 0; i < testLocales.length; i++) {675Locale loc = testLocales[i];676assertEquals("English display name for " + loc.toLanguageTag(),677displayNameEnglish[i], loc.getDisplayName(Locale.ENGLISH));678assertEquals("Simplified Chinese display name for " + loc.toLanguageTag(),679displayNameSimplifiedChinese[i], loc.getDisplayName(Locale.CHINA));680}681}682683///684/// Builder tests685///686687public void testBuilderSetLocale() {688Builder builder = new Builder();689Builder lenientBuilder = new Builder();690691String languageTag = "en-Latn-US-NewYork-a-bb-ccc-u-co-japanese-x-y-z";692String target = "en-Latn-US-NewYork-a-bb-ccc-u-co-japanese-x-y-z";693694Locale locale = Locale.forLanguageTag(languageTag);695Locale result = lenientBuilder696.setLocale(locale)697.build();698assertEquals("long tag", target, result.toLanguageTag());699assertEquals("long tag", locale, result);700701// null is illegal702new BuilderNPE("locale") {703public void call() { b.setLocale(null); }704};705706// builder canonicalizes the three legacy locales:707// ja_JP_JP, th_TH_TH, no_NY_NO.708locale = builder.setLocale(new Locale("ja", "JP", "JP")).build();709assertEquals("ja_JP_JP languagetag", "ja-JP-u-ca-japanese", locale.toLanguageTag());710assertEquals("ja_JP_JP variant", "", locale.getVariant());711712locale = builder.setLocale(new Locale("th", "TH", "TH")).build();713assertEquals("th_TH_TH languagetag", "th-TH-u-nu-thai", locale.toLanguageTag());714assertEquals("th_TH_TH variant", "", locale.getVariant());715716locale = builder.setLocale(new Locale("no", "NO", "NY")).build();717assertEquals("no_NO_NY languagetag", "nn-NO", locale.toLanguageTag());718assertEquals("no_NO_NY language", "nn", locale.getLanguage());719assertEquals("no_NO_NY variant", "", locale.getVariant());720721// non-canonical, non-legacy locales are invalid722new BuilderILE("123_4567_89") {723public void call() {724b.setLocale(new Locale("123", "4567", "89"));725}726};727}728729public void testBuilderSetLanguageTag() {730String source = "eN-LaTn-Us-NewYork-A-Xx-B-Yy-X-1-2-3";731String target = "en-Latn-US-NewYork-a-xx-b-yy-x-1-2-3";732Builder builder = new Builder();733String result = builder734.setLanguageTag(source)735.build()736.toLanguageTag();737assertEquals("language", target, result);738739// redundant extensions cause a failure740new BuilderILE() { public void call() { b.setLanguageTag("und-a-xx-yy-b-ww-A-00-11-c-vv"); }};741742// redundant Unicode locale extension keys within an Unicode locale extension cause a failure743new BuilderILE() { public void call() { b.setLanguageTag("und-u-nu-thai-NU-chinese-xx-1234"); }};744}745746public void testBuilderSetLanguage() {747// language is normalized to lower case748String source = "eN";749String target = "en";750String defaulted = "";751Builder builder = new Builder();752String result = builder753.setLanguage(source)754.build()755.getLanguage();756assertEquals("en", target, result);757758// setting with empty resets759result = builder760.setLanguage(target)761.setLanguage("")762.build()763.getLanguage();764assertEquals("empty", defaulted, result);765766// setting with null resets too767result = builder768.setLanguage(target)769.setLanguage(null)770.build()771.getLanguage();772assertEquals("null", defaulted, result);773774// language codes must be 2-8 alpha775// for forwards compatibility, 4-alpha and 5-8 alpha (registered)776// languages are accepted syntax777new BuilderILE("q", "abcdefghi", "13") { public void call() { b.setLanguage(arg); }};778779// language code validation is NOT performed, any 2-8-alpha passes780assertNotNull("2alpha", builder.setLanguage("zz").build());781assertNotNull("8alpha", builder.setLanguage("abcdefgh").build());782783// three-letter language codes are NOT canonicalized to two-letter784result = builder785.setLanguage("eng")786.build()787.getLanguage();788assertEquals("eng", "eng", result);789}790791public void testBuilderSetScript() {792// script is normalized to title case793String source = "lAtN";794String target = "Latn";795String defaulted = "";796Builder builder = new Builder();797String result = builder798.setScript(source)799.build()800.getScript();801assertEquals("script", target, result);802803// setting with empty resets804result = builder805.setScript(target)806.setScript("")807.build()808.getScript();809assertEquals("empty", defaulted, result);810811// settting with null also resets812result = builder813.setScript(target)814.setScript(null)815.build()816.getScript();817assertEquals("null", defaulted, result);818819// ill-formed script codes throw IAE820// must be 4alpha821new BuilderILE("abc", "abcde", "l3tn") { public void call() { b.setScript(arg); }};822823// script code validation is NOT performed, any 4-alpha passes824assertEquals("4alpha", "Wxyz", builder.setScript("wxyz").build().getScript());825}826827public void testBuilderSetRegion() {828// region is normalized to upper case829String source = "uS";830String target = "US";831String defaulted = "";832Builder builder = new Builder();833String result = builder834.setRegion(source)835.build()836.getCountry();837assertEquals("us", target, result);838839// setting with empty resets840result = builder841.setRegion(target)842.setRegion("")843.build()844.getCountry();845assertEquals("empty", defaulted, result);846847// setting with null also resets848result = builder849.setRegion(target)850.setRegion(null)851.build()852.getCountry();853assertEquals("null", defaulted, result);854855// ill-formed region codes throw IAE856// 2 alpha or 3 numeric857new BuilderILE("q", "abc", "12", "1234", "a3", "12a") { public void call() { b.setRegion(arg); }};858859// region code validation is NOT performed, any 2-alpha or 3-digit passes860assertEquals("2alpha", "ZZ", builder.setRegion("ZZ").build().getCountry());861assertEquals("3digit", "000", builder.setRegion("000").build().getCountry());862}863864public void testBuilderSetVariant() {865// Variant case is not normalized in lenient variant mode866String source = "NewYork";867String target = source;868String defaulted = "";869Builder builder = new Builder();870String result = builder871.setVariant(source)872.build()873.getVariant();874assertEquals("NewYork", target, result);875876result = builder877.setVariant("NeWeR_YoRkEr")878.build()879.toLanguageTag();880assertEquals("newer yorker", "und-NeWeR-YoRkEr", result);881882// subtags of variant are NOT reordered883result = builder884.setVariant("zzzzz_yyyyy_xxxxx")885.build()886.getVariant();887assertEquals("zyx", "zzzzz_yyyyy_xxxxx", result);888889// setting to empty resets890result = builder891.setVariant(target)892.setVariant("")893.build()894.getVariant();895assertEquals("empty", defaulted, result);896897// setting to null also resets898result = builder899.setVariant(target)900.setVariant(null)901.build()902.getVariant();903assertEquals("null", defaulted, result);904905// ill-formed variants throw IAE906// digit followed by 3-7 characters, or alpha followed by 4-8 characters.907new BuilderILE("abcd", "abcdefghi", "1ab", "1abcdefgh") { public void call() { b.setVariant(arg); }};908909// 4 characters is ok as long as the first is a digit910assertEquals("digit+3alpha", "1abc", builder.setVariant("1abc").build().getVariant());911912// all subfields must conform913new BuilderILE("abcde-fg") { public void call() { b.setVariant(arg); }};914}915916public void testBuilderSetExtension() {917// upper case characters are normalized to lower case918final char sourceKey = 'a';919final String sourceValue = "aB-aBcdefgh-12-12345678";920String target = "ab-abcdefgh-12-12345678";921Builder builder = new Builder();922String result = builder923.setExtension(sourceKey, sourceValue)924.build()925.getExtension(sourceKey);926assertEquals("extension", target, result);927928// setting with empty resets929result = builder930.setExtension(sourceKey, sourceValue)931.setExtension(sourceKey, "")932.build()933.getExtension(sourceKey);934assertEquals("empty", null, result);935936// setting with null also resets937result = builder938.setExtension(sourceKey, sourceValue)939.setExtension(sourceKey, null)940.build()941.getExtension(sourceKey);942assertEquals("null", null, result);943944// ill-formed extension keys throw IAE945// must be in [0-9a-ZA-Z]946new BuilderILE("$") { public void call() { b.setExtension('$', sourceValue); }};947948// each segment of value must be 2-8 alphanum949new BuilderILE("ab-cd-123456789") { public void call() { b.setExtension(sourceKey, arg); }};950951// no multiple hyphens.952new BuilderILE("ab--cd") { public void call() { b.setExtension(sourceKey, arg); }};953954// locale extension key has special handling955Locale locale = builder956.setExtension('u', "co-japanese")957.build();958assertEquals("locale extension", "japanese", locale.getUnicodeLocaleType("co"));959960// locale extension has same behavior with set locale keyword961Locale locale2 = builder962.setUnicodeLocaleKeyword("co", "japanese")963.build();964assertEquals("locales with extension", locale, locale2);965966// setting locale extension overrides all previous calls to setLocaleKeyword967Locale locale3 = builder968.setExtension('u', "xxx-nu-thai")969.build();970assertEquals("remove co", null, locale3.getUnicodeLocaleType("co"));971assertEquals("override thai", "thai", locale3.getUnicodeLocaleType("nu"));972assertEquals("override attribute", 1, locale3.getUnicodeLocaleAttributes().size());973974// setting locale keyword extends values already set by the locale extension975Locale locale4 = builder976.setUnicodeLocaleKeyword("co", "japanese")977.build();978assertEquals("extend", "japanese", locale4.getUnicodeLocaleType("co"));979assertEquals("extend", "thai", locale4.getUnicodeLocaleType("nu"));980981// locale extension subtags are reordered982result = builder983.clear()984.setExtension('u', "456-123-zz-123-yy-456-xx-789")985.build()986.toLanguageTag();987assertEquals("reorder", "und-u-123-456-xx-789-yy-456-zz-123", result);988989// multiple keyword types990result = builder991.clear()992.setExtension('u', "nu-thai-foobar")993.build()994.getUnicodeLocaleType("nu");995assertEquals("multiple types", "thai-foobar", result);996997// redundant locale extensions are ignored998result = builder999.clear()1000.setExtension('u', "nu-thai-NU-chinese-xx-1234")1001.build()1002.toLanguageTag();1003assertEquals("duplicate keys", "und-u-nu-thai-xx-1234", result);1004}10051006public void testBuilderAddUnicodeLocaleAttribute() {1007Builder builder = new Builder();1008Locale locale = builder1009.addUnicodeLocaleAttribute("def")1010.addUnicodeLocaleAttribute("abc")1011.build();10121013Set<String> uattrs = locale.getUnicodeLocaleAttributes();1014assertEquals("number of attributes", 2, uattrs.size());1015assertTrue("attribute abc", uattrs.contains("abc"));1016assertTrue("attribute def", uattrs.contains("def"));10171018// remove attribute1019locale = builder.removeUnicodeLocaleAttribute("xxx")1020.build();10211022assertEquals("remove bogus", 2, uattrs.size());10231024// add duplicate1025locale = builder.addUnicodeLocaleAttribute("abc")1026.build();1027assertEquals("add duplicate", 2, uattrs.size());10281029// null attribute throws NPE1030new BuilderNPE("null attribute") { public void call() { b.addUnicodeLocaleAttribute(null); }};10311032// illformed attribute throws IllformedLocaleException1033new BuilderILE("invalid attribute") { public void call() { b.addUnicodeLocaleAttribute("ca"); }};1034}10351036public void testBuildersetUnicodeLocaleKeyword() {1037// Note: most behavior is tested in testBuilderSetExtension1038Builder builder = new Builder();1039Locale locale = builder1040.setUnicodeLocaleKeyword("co", "japanese")1041.setUnicodeLocaleKeyword("nu", "thai")1042.build();1043assertEquals("co", "japanese", locale.getUnicodeLocaleType("co"));1044assertEquals("nu", "thai", locale.getUnicodeLocaleType("nu"));1045assertEquals("keys", 2, locale.getUnicodeLocaleKeys().size());10461047// can clear a keyword by setting to null, others remain1048String result = builder1049.setUnicodeLocaleKeyword("co", null)1050.build()1051.toLanguageTag();1052assertEquals("empty co", "und-u-nu-thai", result);10531054// locale keyword extension goes when all keywords are gone1055result = builder1056.setUnicodeLocaleKeyword("nu", null)1057.build()1058.toLanguageTag();1059assertEquals("empty nu", "und", result);10601061// locale keywords are ordered independent of order of addition1062result = builder1063.setUnicodeLocaleKeyword("zz", "012")1064.setUnicodeLocaleKeyword("aa", "345")1065.build()1066.toLanguageTag();1067assertEquals("reordered", "und-u-aa-345-zz-012", result);10681069// null keyword throws NPE1070new BuilderNPE("keyword") { public void call() { b.setUnicodeLocaleKeyword(null, "thai"); }};10711072// well-formed keywords are two alphanum1073new BuilderILE("a", "abc") { public void call() { b.setUnicodeLocaleKeyword(arg, "value"); }};10741075// well-formed values are 3-8 alphanum1076new BuilderILE("ab", "abcdefghi") { public void call() { b.setUnicodeLocaleKeyword("ab", arg); }};1077}10781079public void testBuilderPrivateUseExtension() {1080// normalizes hyphens to underscore, case to lower1081String source = "c-B-a";1082String target = "c-b-a";1083Builder builder = new Builder();1084String result = builder1085.setExtension(Locale.PRIVATE_USE_EXTENSION, source)1086.build()1087.getExtension(Locale.PRIVATE_USE_EXTENSION);1088assertEquals("abc", target, result);10891090// multiple hyphens are ill-formed1091new BuilderILE("a--b") { public void call() { b.setExtension(Locale.PRIVATE_USE_EXTENSION, arg); }};1092}10931094public void testBuilderClear() {1095String monster = "en-latn-US-NewYork-a-bb-cc-u-co-japanese-x-z-y-x-x";1096Builder builder = new Builder();1097Locale locale = Locale.forLanguageTag(monster);1098String result = builder1099.setLocale(locale)1100.clear()1101.build()1102.toLanguageTag();1103assertEquals("clear", "und", result);1104}11051106public void testBuilderRemoveUnicodeAttribute() {1107// tested in testBuilderAddUnicodeAttribute1108}11091110public void testBuilderBuild() {1111// tested in other test methods1112}11131114public void testSerialize() {1115final Locale[] testLocales = {1116Locale.ROOT,1117new Locale("en"),1118new Locale("en", "US"),1119new Locale("en", "US", "Win"),1120new Locale("en", "US", "Win_XP"),1121new Locale("ja", "JP"),1122new Locale("ja", "JP", "JP"),1123new Locale("th", "TH"),1124new Locale("th", "TH", "TH"),1125new Locale("no", "NO"),1126new Locale("nb", "NO"),1127new Locale("nn", "NO"),1128new Locale("no", "NO", "NY"),1129new Locale("nn", "NO", "NY"),1130new Locale("he", "IL"),1131new Locale("he", "IL", "var"),1132new Locale("Language", "Country", "Variant"),1133new Locale("", "US"),1134new Locale("", "", "Java"),1135Locale.forLanguageTag("en-Latn-US"),1136Locale.forLanguageTag("zh-Hans"),1137Locale.forLanguageTag("zh-Hant-TW"),1138Locale.forLanguageTag("ja-JP-u-ca-japanese"),1139Locale.forLanguageTag("und-Hant"),1140Locale.forLanguageTag("und-a-123-456"),1141Locale.forLanguageTag("en-x-java"),1142Locale.forLanguageTag("th-TH-u-ca-buddist-nu-thai-x-lvariant-TH"),1143};11441145for (Locale locale : testLocales) {1146try {1147// write1148ByteArrayOutputStream bos = new ByteArrayOutputStream();1149ObjectOutputStream oos = new ObjectOutputStream(bos);1150oos.writeObject(locale);11511152// read1153ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());1154ObjectInputStream ois = new ObjectInputStream(bis);1155Object o = ois.readObject();11561157assertEquals("roundtrip " + locale, locale, o);1158} catch (Exception e) {1159errln(locale + " encountered exception:" + e.getLocalizedMessage());1160}1161}1162}11631164public void testDeserialize6() {1165final String TESTFILEPREFIX = "java6locale_";11661167File dataDir = null;1168String dataDirName = System.getProperty("serialized.data.dir");1169if (dataDirName == null) {1170URL resdirUrl = getClass().getClassLoader().getResource("serialized");1171if (resdirUrl != null) {1172try {1173dataDir = new File(resdirUrl.toURI());1174} catch (URISyntaxException urie) {1175}1176}1177} else {1178dataDir = new File(dataDirName);1179}11801181if (dataDir == null || !dataDir.isDirectory()) {1182errln("Could not locate the serialized test case data location");1183return;1184}11851186File[] files = dataDir.listFiles();1187for (File testfile : files) {1188if (testfile.isDirectory()) {1189continue;1190}1191String name = testfile.getName();1192if (!name.startsWith(TESTFILEPREFIX)) {1193continue;1194}1195Locale locale;1196String locStr = name.substring(TESTFILEPREFIX.length());1197if (locStr.equals("ROOT")) {1198locale = Locale.ROOT;1199} else {1200String[] fields = locStr.split("_", 3);1201String lang = fields[0];1202String country = (fields.length >= 2) ? fields[1] : "";1203String variant = (fields.length == 3) ? fields[2] : "";1204locale = new Locale(lang, country, variant);1205}12061207// deserialize1208try (FileInputStream fis = new FileInputStream(testfile);1209ObjectInputStream ois = new ObjectInputStream(fis))1210{1211Object o = ois.readObject();1212assertEquals("Deserialize Java 6 Locale " + locale, o, locale);1213} catch (Exception e) {1214errln("Exception while reading " + testfile.getAbsolutePath() + " - " + e.getMessage());1215}1216}1217}12181219public void testBug7002320() {1220// forLanguageTag() and Builder.setLanguageTag(String)1221// should add a location extension for following two cases.1222//1223// 1. language/country are "ja"/"JP" and the resolved variant (x-lvariant-*)1224// is exactly "JP" and no BCP 47 extensions are available, then add1225// a Unicode locale extension "ca-japanese".1226// 2. language/country are "th"/"TH" and the resolved variant is exactly1227// "TH" and no BCP 47 extensions are available, then add a Unicode locale1228// extension "nu-thai".1229//1230String[][] testdata = {1231{"ja-JP-x-lvariant-JP", "ja-JP-u-ca-japanese-x-lvariant-JP"}, // special case 11232{"ja-JP-x-lvariant-JP-XXX"},1233{"ja-JP-u-ca-japanese-x-lvariant-JP"},1234{"ja-JP-u-ca-gregory-x-lvariant-JP"},1235{"ja-JP-u-cu-jpy-x-lvariant-JP"},1236{"ja-x-lvariant-JP"},1237{"th-TH-x-lvariant-TH", "th-TH-u-nu-thai-x-lvariant-TH"}, // special case 21238{"th-TH-u-nu-thai-x-lvariant-TH"},1239{"en-US-x-lvariant-JP"},1240};12411242Builder bldr = new Builder();12431244for (String[] data : testdata) {1245String in = data[0];1246String expected = (data.length == 1) ? data[0] : data[1];12471248// forLanguageTag1249Locale loc = Locale.forLanguageTag(in);1250String out = loc.toLanguageTag();1251assertEquals("Language tag roundtrip by forLanguageTag with input: " + in, expected, out);12521253// setLanguageTag1254bldr.clear();1255bldr.setLanguageTag(in);1256loc = bldr.build();1257out = loc.toLanguageTag();1258assertEquals("Language tag roundtrip by Builder.setLanguageTag with input: " + in, expected, out);1259}1260}12611262public void testBug7023613() {1263String[][] testdata = {1264{"en-Latn", "en__#Latn"},1265{"en-u-ca-japanese", "en__#u-ca-japanese"},1266};12671268for (String[] data : testdata) {1269String in = data[0];1270String expected = (data.length == 1) ? data[0] : data[1];12711272Locale loc = Locale.forLanguageTag(in);1273String out = loc.toString();1274assertEquals("Empty country field with non-empty script/extension with input: " + in, expected, out);1275}1276}12771278/*1279* 7033504: (lc) incompatible behavior change for ja_JP_JP and th_TH_TH locales1280*/1281public void testBug7033504() {1282checkCalendar(new Locale("ja", "JP", "jp"), "java.util.GregorianCalendar");1283checkCalendar(new Locale("ja", "jp", "jp"), "java.util.GregorianCalendar");1284checkCalendar(new Locale("ja", "JP", "JP"), "java.util.JapaneseImperialCalendar");1285checkCalendar(new Locale("ja", "jp", "JP"), "java.util.JapaneseImperialCalendar");1286checkCalendar(Locale.forLanguageTag("en-u-ca-japanese"),1287"java.util.JapaneseImperialCalendar");12881289checkDigit(new Locale("th", "TH", "th"), '0');1290checkDigit(new Locale("th", "th", "th"), '0');1291checkDigit(new Locale("th", "TH", "TH"), '\u0e50');1292checkDigit(new Locale("th", "TH", "TH"), '\u0e50');1293checkDigit(Locale.forLanguageTag("en-u-nu-thai"), '\u0e50');1294}12951296private void checkCalendar(Locale loc, String expected) {1297Calendar cal = Calendar.getInstance(loc);1298assertEquals("Wrong calendar", expected, cal.getClass().getName());1299}13001301private void checkDigit(Locale loc, Character expected) {1302DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(loc);1303Character zero = dfs.getZeroDigit();1304assertEquals("Wrong digit zero char", expected, zero);1305}13061307///1308/// utility asserts1309///13101311private void assertTrue(String msg, boolean v) {1312if (!v) {1313errln(msg + ": expected true");1314}1315}13161317private void assertFalse(String msg, boolean v) {1318if (v) {1319errln(msg + ": expected false");1320}1321}13221323private void assertEquals(String msg, Object e, Object v) {1324if (e == null ? v != null : !e.equals(v)) {1325if (e != null) {1326e = "'" + e + "'";1327}1328if (v != null) {1329v = "'" + v + "'";1330}1331errln(msg + ": expected " + e + " but got " + v);1332}1333}13341335private void assertNotEquals(String msg, Object e, Object v) {1336if (e == null ? v == null : e.equals(v)) {1337if (e != null) {1338e = "'" + e + "'";1339}1340errln(msg + ": expected not equal " + e);1341}1342}13431344private void assertNull(String msg, Object o) {1345if (o != null) {1346errln(msg + ": expected null but got '" + o + "'");1347}1348}13491350private void assertNotNull(String msg, Object o) {1351if (o == null) {1352errln(msg + ": expected non null");1353}1354}13551356// not currently used, might get rid of exceptions from the API1357private abstract class ExceptionTest {1358private final Class<? extends Exception> exceptionClass;13591360ExceptionTest(Class<? extends Exception> exceptionClass) {1361this.exceptionClass = exceptionClass;1362}13631364public void run() {1365String failMsg = null;1366try {1367call();1368failMsg = "expected " + exceptionClass.getName() + " but no exception thrown.";1369}1370catch (Exception e) {1371if (!exceptionClass.isAssignableFrom(e.getClass())) {1372failMsg = "expected " + exceptionClass.getName() + " but caught " + e;1373}1374}1375if (failMsg != null) {1376String msg = message();1377msg = msg == null ? "" : msg + " ";1378errln(msg + failMsg);1379}1380}13811382public String message() {1383return null;1384}13851386public abstract void call();1387}13881389private abstract class ExpectNPE extends ExceptionTest {1390ExpectNPE() {1391super(NullPointerException.class);1392run();1393}1394}13951396private abstract class BuilderNPE extends ExceptionTest {1397protected final String msg;1398protected final Builder b = new Builder();13991400BuilderNPE(String msg) {1401super(NullPointerException.class);14021403this.msg = msg;14041405run();1406}14071408public String message() {1409return msg;1410}1411}14121413private abstract class ExpectIAE extends ExceptionTest {1414ExpectIAE() {1415super(IllegalArgumentException.class);1416run();1417}1418}14191420private abstract class BuilderILE extends ExceptionTest {1421protected final String[] args;1422protected final Builder b = new Builder();14231424protected String arg; // mutates during call14251426BuilderILE(String... args) {1427super(IllformedLocaleException.class);14281429this.args = args;14301431run();1432}14331434public void run() {1435for (String arg : args) {1436this.arg = arg;1437super.run();1438}1439}14401441public String message() {1442return "arg: '" + arg + "'";1443}1444}1445}144614471448