1 /*
2  * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 /**
24  * @test
25  * @bug 4052404 4052440 4084688 4092475 4101316 4105828 4107014 4107953 4110613
26  * 4118587 4118595 4122371 4126371 4126880 4135316 4135752 4139504 4139940 4143951
27  * 4147315 4147317 4147552 4335196 4778440 4940539 5010672 6475525 6544471 6627549
28  * 6786276 7066203 7085757 8008577 8030696 8170840 8255086
29  * @summary test Locales
30  * @library /java/text/testlib
31  * @modules jdk.localedata
32  * @run main/othervm -Djava.locale.providers=JRE,SPI LocaleTest
33  */
34 /*
35  *
36  *
37  * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
38  * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
39  *
40  * Portions copyright (c) 2007 Sun Microsystems, Inc.
41  * All Rights Reserved.
42  *
43  * The original version of this source code and documentation
44  * is copyrighted and owned by Taligent, Inc., a wholly-owned
45  * subsidiary of IBM. These materials are provided under terms
46  * of a License Agreement between Taligent and Sun. This technology
47  * is protected by multiple US and International patents.
48  *
49  * This notice and attribution to Taligent may not be removed.
50  * Taligent is a registered trademark of Taligent, Inc.
51  *
52  * Permission to use, copy, modify, and distribute this software
53  * and its documentation for NON-COMMERCIAL purposes and without
54  * fee is hereby granted provided that this copyright notice
55  * appears in all copies. Please refer to the file "copyright.html"
56  * for further important copyright and licensing information.
57  *
58  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
59  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
60  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
61  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
62  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
63  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
64  *
65  */
66 
67 import java.io.ByteArrayInputStream;
68 import java.io.ByteArrayOutputStream;
69 import java.io.IOException;
70 import java.io.ObjectInputStream;
71 import java.io.ObjectOutputStream;
72 import java.io.OptionalDataException;
73 import java.io.StreamCorruptedException;
74 import java.text.DateFormat;
75 import java.text.DecimalFormat;
76 import java.text.NumberFormat;
77 import java.text.SimpleDateFormat;
78 import java.util.Arrays;
79 import java.util.Calendar;
80 import java.util.Date;
81 import java.util.List;
82 import java.util.Locale;
83 import java.util.MissingResourceException;
84 
85 public class LocaleTest extends IntlTest {
LocaleTest()86     public LocaleTest() {
87     }
88 
89     private int ENGLISH = 0;
90     private int FRENCH = 1;
91     private int CROATIAN = 2;
92     private int GREEK = 3;
93     private int NORWEGIAN = 4;
94     private int ITALIAN = 5;
95     private int DUMMY = 6;
96     private int MAX_LOCALES = 6;
97 
98     private int LANG = 0;
99     private int CTRY = 1;
100     private int VAR = 2;
101     private int NAME = 3;
102     private int LANG3 = 4;
103     private int CTRY3 = 5;
104     private int LCID = 6;
105     private int DLANG_EN = 7;
106     private int DCTRY_EN = 8;
107     private int DVAR_EN = 9;
108     private int DNAME_EN = 10;
109     private int DLANG_FR = 11;
110     private int DCTRY_FR = 12;
111     private int DVAR_FR = 13;
112     private int DNAME_FR = 14;
113     private int DLANG_HR = 15;
114     private int DCTRY_HR = 16;
115     private int DVAR_HR = 17;
116     private int DNAME_HR = 18;
117     private int DLANG_EL = 19;
118     private int DCTRY_EL = 20;
119     private int DVAR_EL = 21;
120     private int DNAME_EL = 22;
121     private int DLANG_ROOT = 23;
122     private int DCTRY_ROOT = 24;
123     private int DVAR_ROOT = 25;
124     private int DNAME_ROOT = 26;
125 
126     private String[][] dataTable = {
127         // language code
128         {   "en",   "fr",   "hr",   "el",   "no",   "it",   "xx"    },
129         // country code
130         {   "US",   "FR",   "HR",   "GR",   "NO",   "",   "YY"    },
131         // variant code
132         {   "",     "",     "",     "",     "NY",   "",   ""    },
133         // full name
134         {   "en_US",    "fr_FR",    "hr_HR",    "el_GR",    "no_NO_NY", "it",   "xx_YY"  },
135         // ISO-3 language
136         {   "eng",  "fra",  "hrv",  "ell",  "nor",  "ita",  ""   },
137         // ISO-3 country
138         {   "USA",  "FRA",  "HRV",  "GRC",  "NOR",  "",     ""   },
139         // LCID (not currently public)
140         {   "0409", "040c", "041a", "0408", "0814", "",     ""  },
141 
142         // display language (English)
143         {   "English",  "French",   "Croatian", "Greek",    "Norwegian",    "Italian",  "xx" },
144         // display country (English)
145         {   "United States",    "France",   "Croatia",  "Greece",   "Norway",   "",     "YY" },
146         // display variant (English)
147         {   "",     "",     "",     "",     "Nynorsk",   "",     ""},
148         // display name (English)
149         // Updated no_NO_NY English display name for new pattern-based algorithm
150         // (part of Euro support).
151         {   "English (United States)", "French (France)", "Croatian (Croatia)", "Greek (Greece)", "Norwegian (Norway,Nynorsk)", "Italian", "xx (YY)" },
152 
153         // display langage (French)
154         {   "anglais",  "fran\u00e7ais",   "croate", "grec",    "norv\u00e9gien",    "italien", "xx" },
155         // display country (French)
156         {   "Etats-Unis",    "France",   "Croatie",  "Gr\u00e8ce",   "Norv\u00e8ge", "",     "YY" },
157         // display variant (French)
158         {   "",     "",     "",     "",     "",     "",    "" },
159         // display name (French)
160         {   "anglais (Etats-Unis)", "fran\u00e7ais (France)", "croate (Croatie)", "grec (Gr\u00e8ce)", "norv\u00e9gien (Norv\u00e8ge,Nynorsk)", "italien", "xx (YY)" },
161 
162         // display langage (Croatian)
163         {   "",  "", "hrvatski", "",    "", "", "xx" },
164         // display country (Croatian)
165         {   "",    "",   "Hrvatska",  "",   "", "", "YY" },
166         // display variant (Croatian)
167         {   "",     "",     "",     "",     "", "", ""},
168         // display name (Croatian)
169         {   "", "", "hrvatski (Hrvatska)", "", "", "", "xx (YY)" },
170 
171         // display langage (Greek)
172         {   "\u0391\u03b3\u03b3\u03bb\u03b9\u03ba\u03ac",  "\u0393\u03b1\u03bb\u03bb\u03b9\u03ba\u03ac", "\u039a\u03c1\u03bf\u03b1\u03c4\u03b9\u03ba\u03ac", "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac",    "\u039d\u03bf\u03c1\u03b2\u03b7\u03b3\u03b9\u03ba\u03ac", "\u0399\u03c4\u03b1\u03bb\u03b9\u03ba\u03ac", "xx" },
173         // display country (Greek)
174         {   "\u0397\u03bd\u03c9\u03bc\u03ad\u03bd\u03b5\u03c2 \u03a0\u03bf\u03bb\u03b9\u03c4\u03b5\u03af\u03b5\u03c2",    "\u0393\u03b1\u03bb\u03bb\u03af\u03b1",   "\u039a\u03c1\u03bf\u03b1\u03c4\u03af\u03b1",  "\u0395\u03bb\u03bb\u03ac\u03b4\u03b1",   "\u039d\u03bf\u03c1\u03b2\u03b7\u03b3\u03af\u03b1", "", "YY" },
175         // display variant (Greek)
176         {   "",     "",     "",     "",     "", "", "" },
177         // display name (Greek)
178         {   "\u0391\u03b3\u03b3\u03bb\u03b9\u03ba\u03ac (\u0397\u03bd\u03c9\u03bc\u03ad\u03bd\u03b5\u03c2 \u03a0\u03bf\u03bb\u03b9\u03c4\u03b5\u03af\u03b5\u03c2)", "\u0393\u03b1\u03bb\u03bb\u03b9\u03ba\u03ac (\u0393\u03b1\u03bb\u03bb\u03af\u03b1)", "\u039a\u03c1\u03bf\u03b1\u03c4\u03b9\u03ba\u03ac (\u039a\u03c1\u03bf\u03b1\u03c4\u03af\u03b1)", "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac (\u0395\u03bb\u03bb\u03ac\u03b4\u03b1)", "\u039d\u03bf\u03c1\u03b2\u03b7\u03b3\u03b9\u03ba\u03ac (\u039d\u03bf\u03c1\u03b2\u03b7\u03b3\u03af\u03b1,Nynorsk)", "\u0399\u03c4\u03b1\u03bb\u03b9\u03ba\u03ac", "xx (YY)" },
179 
180         // display langage (<root>)
181         {   "English",  "French",   "Croatian", "Greek",    "Norwegian",  "Italian",  "xx" },
182         // display country (<root>)
183         {   "United States",    "France",   "Croatia",  "Greece",   "Norway",  "",     "YY" },
184         // display variant (<root>)
185         {   "",     "",     "",     "",     "Nynorsk",   "",     ""},
186         // display name (<root>)
187         {   "English (United States)", "French (France)", "Croatian (Croatia)", "Greek (Greece)", "Norwegian (Norway,Nynorsk)", "Italian", "xx (YY)" },
188     };
189 
main(String[] args)190     public static void main(String[] args) throws Exception {
191         new LocaleTest().run(args);
192     }
193 
TestBasicGetters()194     public void TestBasicGetters() {
195         for (int i = 0; i <= MAX_LOCALES; i++) {
196             Locale testLocale = new Locale(dataTable[LANG][i], dataTable[CTRY][i], dataTable[VAR][i]);
197             logln("Testing " + testLocale + "...");
198 
199             if (!testLocale.getLanguage().equals(dataTable[LANG][i])) {
200                 errln("  Language code mismatch: " + testLocale.getLanguage() + " versus "
201                         + dataTable[LANG][i]);
202             }
203             if (!testLocale.getCountry().equals(dataTable[CTRY][i])) {
204                 errln("  Country code mismatch: " + testLocale.getCountry() + " versus "
205                         + dataTable[CTRY][i]);
206             }
207             if (!testLocale.getVariant().equals(dataTable[VAR][i])) {
208                 errln("  Variant code mismatch: " + testLocale.getVariant() + " versus "
209                         + dataTable[VAR][i]);
210             }
211             if (!testLocale.toString().equals(dataTable[NAME][i])) {
212                 errln("  Locale name mismatch: " + testLocale.toString() + " versus "
213                         + dataTable[NAME][i]);
214             }
215         }
216 
217         logln("Same thing without variant codes...");
218         for (int i = 0; i <= MAX_LOCALES; i++) {
219             Locale testLocale = new Locale(dataTable[LANG][i], dataTable[CTRY][i]);
220             logln("Testing " + testLocale + "...");
221 
222             if (!testLocale.getLanguage().equals(dataTable[LANG][i])) {
223                 errln("  Language code mismatch: " + testLocale.getLanguage() + " versus "
224                         + dataTable[LANG][i]);
225             }
226             if (!testLocale.getCountry().equals(dataTable[CTRY][i])) {
227                 errln("  Country code mismatch: " + testLocale.getCountry() + " versus "
228                         + dataTable[CTRY][i]);
229             }
230             if (!testLocale.getVariant().equals("")) {
231                 errln("  Variant code mismatch: " + testLocale.getVariant() + " versus \"\"");
232             }
233         }
234     }
235 
TestSimpleResourceInfo()236     public void TestSimpleResourceInfo() {
237         for (int i = 0; i <= MAX_LOCALES; i++) {
238             if (dataTable[LANG][i].equals("xx")) {
239                 continue;
240             }
241 
242             Locale testLocale = new Locale(dataTable[LANG][i], dataTable[CTRY][i], dataTable[VAR][i]);
243             logln("Testing " + testLocale + "...");
244 
245             if (!testLocale.getISO3Language().equals(dataTable[LANG3][i])) {
246                 errln("  ISO-3 language code mismatch: " + testLocale.getISO3Language()
247                         + " versus " + dataTable[LANG3][i]);
248             }
249             if (!testLocale.getISO3Country().equals(dataTable[CTRY3][i])) {
250                 errln("  ISO-3 country code mismatch: " + testLocale.getISO3Country()
251                         + " versus " + dataTable[CTRY3][i]);
252             }
253 /*
254             // getLCID() is currently private
255             if (!String.valueOf(testLocale.getLCID()).equals(dataTable[LCID][i]))
256                 errln("  LCID mismatch: " + testLocale.getLCID() + " versus "
257                             + dataTable[LCID][i]);
258 */
259         }
260     }
261 
262     /*
263      * @bug 4101316
264      * @bug 4084688 (This bug appears to be a duplicate of something, because it was fixed
265      *              between 1.1.5 and 1.1.6, but I included a new test for it anyway)
266      * @bug 4052440 Stop falling back to the default locale.
267      */
TestDisplayNames()268     public void TestDisplayNames() {
269         Locale saveDefault = Locale.getDefault();
270         Locale english = new Locale("en", "US");
271         Locale french = new Locale("fr", "FR");
272         Locale croatian = new Locale("hr", "HR");
273         Locale greek = new Locale("el", "GR");
274 
275         Locale.setDefault(english);
276         logln("With default = en_US...");
277         logln("  In default locale...");
278         doTestDisplayNames(null, DLANG_EN, false);
279         logln("  In locale = en_US...");
280         doTestDisplayNames(english, DLANG_EN, false);
281         logln("  In locale = fr_FR...");
282         doTestDisplayNames(french, DLANG_FR, false);
283         logln("  In locale = hr_HR...");
284         doTestDisplayNames(croatian, DLANG_HR, false);
285         logln("  In locale = el_GR...");
286         doTestDisplayNames(greek, DLANG_EL, false);
287 
288         Locale.setDefault(french);
289         logln("With default = fr_FR...");
290         logln("  In default locale...");
291         doTestDisplayNames(null, DLANG_FR, true);
292         logln("  In locale = en_US...");
293         doTestDisplayNames(english, DLANG_EN, true);
294         logln("  In locale = fr_FR...");
295         doTestDisplayNames(french, DLANG_FR, true);
296         logln("  In locale = hr_HR...");
297         doTestDisplayNames(croatian, DLANG_HR, true);
298         logln("  In locale = el_GR...");
299         doTestDisplayNames(greek, DLANG_EL, true);
300 
301         Locale.setDefault(saveDefault);
302     }
303 
doTestDisplayNames(Locale inLocale, int compareIndex, boolean defaultIsFrench)304     private void doTestDisplayNames(Locale inLocale, int compareIndex, boolean defaultIsFrench) {
305         String language = Locale.getDefault().getLanguage();
306 
307         if (defaultIsFrench && !language.equals("fr")) {
308             errln("Default locale should be French, but it's really " + language);
309         } else if (!defaultIsFrench && !language.equals("en")) {
310             errln("Default locale should be English, but it's really " + language);
311         }
312 
313         for (int i = 0; i <= MAX_LOCALES; i++) {
314             Locale testLocale = new Locale(dataTable[LANG][i], dataTable[CTRY][i], dataTable[VAR][i]);
315             logln("  Testing " + testLocale + "...");
316 
317             String testLang;
318             String testCtry;
319             String testVar;
320             String testName;
321 
322             if (inLocale == null) {
323                 testLang = testLocale.getDisplayLanguage();
324                 testCtry = testLocale.getDisplayCountry();
325                 testVar = testLocale.getDisplayVariant();
326                 testName = testLocale.getDisplayName();
327             } else {
328                 testLang = testLocale.getDisplayLanguage(inLocale);
329                 testCtry = testLocale.getDisplayCountry(inLocale);
330                 testVar = testLocale.getDisplayVariant(inLocale);
331                 testName = testLocale.getDisplayName(inLocale);
332             }
333 
334             String expectedLang;
335             String expectedCtry;
336             String expectedVar;
337             String expectedName;
338 
339             expectedLang = dataTable[compareIndex][i];
340             if (expectedLang.equals("") && defaultIsFrench) {
341                 expectedLang = dataTable[DLANG_EN][i];
342             }
343             if (expectedLang.equals("")) {
344                 expectedLang = dataTable[DLANG_ROOT][i];
345             }
346 
347             expectedCtry = dataTable[compareIndex + 1][i];
348             if (expectedCtry.equals("") && defaultIsFrench) {
349                 expectedCtry = dataTable[DCTRY_EN][i];
350             }
351             if (expectedCtry.equals("")) {
352                 expectedCtry = dataTable[DCTRY_ROOT][i];
353             }
354 
355             expectedVar = dataTable[compareIndex + 2][i];
356             if (expectedVar.equals("") && defaultIsFrench) {
357                 expectedVar = dataTable[DVAR_EN][i];
358             }
359             if (expectedVar.equals("")) {
360                 expectedVar = dataTable[DVAR_ROOT][i];
361             }
362 
363             expectedName = dataTable[compareIndex + 3][i];
364             if (expectedName.equals("") && defaultIsFrench) {
365                 expectedName = dataTable[DNAME_EN][i];
366             }
367             if (expectedName.equals("")) {
368                 expectedName = dataTable[DNAME_ROOT][i];
369             }
370 
371             if (!testLang.equals(expectedLang)) {
372                 errln("Display language mismatch: " + testLang + " versus " + expectedLang);
373             }
374             if (!testCtry.equals(expectedCtry)) {
375                 errln("Display country mismatch: " + testCtry + " versus " + expectedCtry);
376             }
377             if (!testVar.equals(expectedVar)) {
378                 errln("Display variant mismatch: " + testVar + " versus " + expectedVar);
379             }
380             if (!testName.equals(expectedName)) {
381                 errln("Display name mismatch: " + testName + " versus " + expectedName);
382             }
383         }
384     }
385 
TestSimpleObjectStuff()386     public void TestSimpleObjectStuff() {
387         Locale test1 = new Locale("aa", "AA");
388         Locale test2 = new Locale("aa", "AA");
389         Locale test3 = (Locale) test1.clone();
390         Locale test4 = new Locale("zz", "ZZ");
391 
392         if (test1 == test2 || test1 == test3 || test1 == test4 || test2 == test3) {
393             errln("Some of the test variables point to the same locale!");
394         }
395 
396         if (test3 == null) {
397             errln("clone() failed to produce a valid object!");
398         }
399 
400         if (!test1.equals(test2) || !test1.equals(test3) || !test2.equals(test3)) {
401             errln("clone() or equals() failed: objects that should compare equal don't");
402         }
403 
404         if (test1.equals(test4) || test2.equals(test4) || test3.equals(test4)) {
405             errln("equals() failed: objects that shouldn't compare equal do");
406         }
407 
408         int hash1 = test1.hashCode();
409         int hash2 = test2.hashCode();
410         int hash3 = test3.hashCode();
411 
412         if (hash1 != hash2 || hash1 != hash3 || hash2 != hash3) {
413             errln("hashCode() failed: objects that should have the same hash code don't");
414         }
415     }
416 
417     /**
418      * @bug 4011756 4011380
419      */
TestISO3Fallback()420     public void TestISO3Fallback() {
421         Locale test = new Locale("xx", "YY", "");
422         boolean gotException = false;
423         String result = "";
424 
425         try {
426             result = test.getISO3Language();
427         } catch (MissingResourceException e) {
428             gotException = true;
429         }
430         if (!gotException) {
431             errln("getISO3Language() on xx_YY returned " + result + " instead of throwing an exception");
432         }
433 
434         gotException = false;
435         try {
436             result = test.getISO3Country();
437         } catch (MissingResourceException e) {
438             gotException = true;
439         }
440         if (!gotException) {
441             errln("getISO3Country() on xx_YY returned " + result + " instead of throwing an exception");
442         }
443     }
444 
445     /**
446      * @bug 4106155 4118587 7066203 7085757
447      */
TestGetLangsAndCountries()448     public void TestGetLangsAndCountries() {
449         // It didn't seem right to just do an exhaustive test of everything here, so I check
450         // for the following things:
451         // 1) Does each list have the right total number of entries?
452         // 2) Does each list contain certain language and country codes we think are important
453         //     (the G7 countries, plus a couple others)?
454         // 3) Does each list have every entry formatted correctly? (i.e., two characters,
455         //     all lower case for the language codes, all upper case for the country codes)
456         // 4) Is each list in sorted order?
457         String[] test = Locale.getISOLanguages();
458         String[] spotCheck1 = {"en", "es", "fr", "de", "it", "ja", "ko", "zh", "th",
459             "he", "id", "iu", "ug", "yi", "za"};
460 
461         if (test.length != 188) {
462             errln("Expected getISOLanguages() to return 188 languages; it returned " + test.length);
463         } else {
464             for (int i = 0; i < spotCheck1.length; i++) {
465                 int j;
466                 for (j = 0; j < test.length; j++) {
467                     if (test[j].equals(spotCheck1[i])) {
468                         break;
469                     }
470                 }
471                 if (j == test.length || !test[j].equals(spotCheck1[i])) {
472                     errln("Couldn't find " + spotCheck1[i] + " in language list.");
473                 }
474             }
475         }
476         for (int i = 0; i < test.length; i++) {
477             if (!test[i].equals(test[i].toLowerCase())) {
478                 errln(test[i] + " is not all lower case.");
479             }
480             if (test[i].length() != 2) {
481                 errln(test[i] + " is not two characters long.");
482             }
483             if (i > 0 && test[i].compareTo(test[i - 1]) <= 0) {
484                 errln(test[i] + " appears in an out-of-order position in the list.");
485             }
486         }
487 
488         test = Locale.getISOCountries();
489         String[] spotCheck2 = {"US", "CA", "GB", "FR", "DE", "IT", "JP", "KR", "CN", "TW", "TH"};
490 
491 
492         if (test.length != 249) {
493             errln("Expected getISOCountries to return 249 countries; it returned " + test.length);
494         } else {
495             for (int i = 0; i < spotCheck2.length; i++) {
496                 int j;
497                 for (j = 0; j < test.length; j++) {
498                     if (test[j].equals(spotCheck2[i])) {
499                         break;
500                     }
501                 }
502                 if (j == test.length || !test[j].equals(spotCheck2[i])) {
503                     errln("Couldn't find " + spotCheck2[i] + " in country list.");
504                 }
505             }
506         }
507         for (int i = 0; i < test.length; i++) {
508             if (!test[i].equals(test[i].toUpperCase())) {
509                 errln(test[i] + " is not all upper case.");
510             }
511             if (test[i].length() != 2) {
512                 errln(test[i] + " is not two characters long.");
513             }
514             if (i > 0 && test[i].compareTo(test[i - 1]) <= 0) {
515                 errln(test[i] + " appears in an out-of-order position in the list.");
516             }
517         }
518     }
519 
520     /**
521      * @bug 4126880
522      */
Test4126880()523     void Test4126880() {
524         String[] test;
525 
526         test = Locale.getISOCountries();
527         test[0] = "SUCKER!!!";
528         test = Locale.getISOCountries();
529         if (test[0].equals("SUCKER!!!")) {
530             errln("Changed internal country code list!");
531         }
532 
533         test = Locale.getISOLanguages();
534         test[0] = "HAHAHAHA!!!";
535         test = Locale.getISOLanguages();
536         if (test[0].equals("HAHAHAHA!!!")) { // Fixed typo
537             errln("Changes internal language code list!");
538         }
539     }
540 
541     /**
542      * @bug 4107014
543      */
TestGetAvailableLocales()544     public void TestGetAvailableLocales() {
545         Locale[] locales = Locale.getAvailableLocales();
546         if (locales == null || locales.length == 0) {
547             errln("Locale.getAvailableLocales() returned no installed locales!");
548         } else {
549             logln("Locale.getAvailableLocales() returned a list of " + locales.length + " locales.");
550             for (int i = 0; i < locales.length; i++) {
551                 logln(locales[i].toString());
552             }
553         }
554     }
555 
556     /**
557      * @bug 4135316
558      */
TestBug4135316()559     public void TestBug4135316() {
560         Locale[] locales1 = Locale.getAvailableLocales();
561         Locale[] locales2 = Locale.getAvailableLocales();
562         if (locales1 == locales2) {
563             errln("Locale.getAvailableLocales() doesn't clone its internal storage!");
564         }
565     }
566 
567     /**
568      * @bug 4107953
569      */
570 /*
571 test commented out pending API-change approval
572     public void TestGetLanguagesForCountry() {
573         String[] languages = Locale.getLanguagesForCountry("US");
574 
575         if (!searchStringArrayFor("en", languages))
576             errln("Didn't get en as a language for US");
577 
578         languages = Locale.getLanguagesForCountry("FR");
579         if (!searchStringArrayFor("fr", languages))
580             errln("Didn't get fr as a language for FR");
581 
582         languages = Locale.getLanguagesForCountry("CH");
583         if (!searchStringArrayFor("fr", languages))
584             errln("Didn't get fr as a language for CH");
585         if (!searchStringArrayFor("it", languages))
586             errln("Didn't get it as a language for CH");
587         if (!searchStringArrayFor("de", languages))
588             errln("Didn't get de as a language for CH");
589 
590         languages = Locale.getLanguagesForCountry("JP");
591         if (!searchStringArrayFor("ja", languages))
592             errln("Didn't get ja as a language for JP");
593     }
594 */
595 
searchStringArrayFor(String s, String[] array)596     private boolean searchStringArrayFor(String s, String[] array) {
597         for (int i = 0; i < array.length; i++)
598             if (s.equals(array[i]))
599                 return true;
600         return false;
601     }
602     /**
603      * @bug 4110613
604      */
TestSerialization()605     public void TestSerialization() throws ClassNotFoundException, OptionalDataException,
606             IOException, StreamCorruptedException {
607         ObjectOutputStream ostream;
608         ByteArrayOutputStream obstream;
609         byte[] bytes = null;
610 
611         obstream = new ByteArrayOutputStream();
612         ostream = new ObjectOutputStream(obstream);
613 
614         Locale test1 = new Locale("zh", "TW", "");
615         int dummy = test1.hashCode();   // fill in the cached hash-code value
616         ostream.writeObject(test1);
617 
618         bytes = obstream.toByteArray();
619 
620         ObjectInputStream istream = new ObjectInputStream(new ByteArrayInputStream(bytes));
621 
622         Locale test2 = (Locale) (istream.readObject());
623 
624         if (!test1.equals(test2) || test1.hashCode() != test2.hashCode()) {
625             errln("Locale failed to deserialize correctly.");
626         }
627     }
628 
629     /**
630      * @bug 4118587
631      */
TestSimpleDisplayNames()632     public void TestSimpleDisplayNames() {
633         // This test is different from TestDisplayNames because TestDisplayNames checks
634         // fallback behavior, combination of language and country names to form locale
635         // names, and other stuff like that.  This test just checks specific language
636         // and country codes to make sure we have the correct names for them.
637         String[] languageCodes = {"he", "id", "iu", "ug", "yi", "za"};
638         String[] languageNames = {"Hebrew", "Indonesian", "Inuktitut", "Uyghur", "Yiddish",
639             "Zhuang"};
640 
641         for (int i = 0; i < languageCodes.length; i++) {
642             String test = (new Locale(languageCodes[i], "", "")).getDisplayLanguage(Locale.US);
643             if (!test.equals(languageNames[i])) {
644                 errln("Got wrong display name for " + languageCodes[i] + ": Expected \""
645                         + languageNames[i] + "\", got \"" + test + "\".");
646             }
647         }
648     }
649 
650     /**
651      * @bug 4118595
652      */
TestUninstalledISO3Names()653     public void TestUninstalledISO3Names() {
654         // This test checks to make sure getISO3Language and getISO3Country work right
655         // even for locales that are not installed.
656         String[] iso2Languages = {"am", "ba", "fy", "mr", "rn", "ss", "tw", "zu"};
657         String[] iso3Languages = {"amh", "bak", "fry", "mar", "run", "ssw", "twi", "zul"};
658 
659         for (int i = 0; i < iso2Languages.length; i++) {
660             String test = (new Locale(iso2Languages[i], "", "")).getISO3Language();
661             if (!test.equals(iso3Languages[i])) {
662                 errln("Got wrong ISO3 code for " + iso2Languages[i] + ": Expected \""
663                         + iso3Languages[i] + "\", got \"" + test + "\".");
664             }
665         }
666 
667         String[] iso2Countries = {"AF", "BW", "KZ", "MO", "MN", "SB", "TC", "ZW"};
668         String[] iso3Countries = {"AFG", "BWA", "KAZ", "MAC", "MNG", "SLB", "TCA", "ZWE"};
669 
670         for (int i = 0; i < iso2Countries.length; i++) {
671             String test = (new Locale("", iso2Countries[i], "")).getISO3Country();
672             if (!test.equals(iso3Countries[i])) {
673                 errln("Got wrong ISO3 code for " + iso2Countries[i] + ": Expected \""
674                         + iso3Countries[i] + "\", got \"" + test + "\".");
675             }
676         }
677     }
678 
679     /**
680      * @bug 4052404 4778440
681      */
TestChangedISO639Codes()682     public void TestChangedISO639Codes() {
683         Locale hebrewOld = new Locale("iw", "IL", "");
684         Locale hebrewNew = new Locale("he", "IL", "");
685         Locale yiddishOld = new Locale("ji", "IL", "");
686         Locale yiddishNew = new Locale("yi", "IL", "");
687         Locale indonesianOld = new Locale("in", "", "");
688         Locale indonesianNew = new Locale("id", "", "");
689 
690         if (!hebrewNew.getLanguage().equals("iw")) {
691             errln("Got back wrong language code for Hebrew: expected \"iw\", got \""
692                     + hebrewNew.getLanguage() + "\"");
693         }
694         if (!yiddishNew.getLanguage().equals("ji")) {
695             errln("Got back wrong language code for Yiddish: expected \"ji\", got \""
696                     + yiddishNew.getLanguage() + "\"");
697         }
698         if (!indonesianNew.getLanguage().equals("in")) {
699             errln("Got back wrong language code for Indonesian: expected \"in\", got \""
700                     + indonesianNew.getLanguage() + "\"");
701         }
702     }
703 
704     /**
705      * @bug 4092475
706      * I could not reproduce this bug.  I'm pretty convinced it was fixed with the
707      * big locale-data reorg of 10/28/97.  The lookup logic for language and country
708      * display names was also changed at that time in that check-in.    --rtg 3/20/98
709 
710      * This test is not designed to work in any other locale but en_US.
711      * Most of the LocaleElements do not contain display names for other languages,
712      * so this test fails (bug 4289223) when run under different locales. For example,
713      * LocaleElements_es as of kestrel does not have a localized name for Japanese, so
714      * the getDisplayName method asks the default locale for a display name. The Japanese
715      * localized name for "Japanese" does not equal "Japanese" so this test fails for es
716      * display names if run under a ja locale. Eventually, he LocaleElements should probably
717      * be updated to contain more localized language and region display names.
718      * 1999-11-19 joconner
719      *
720      */
TestAtypicalLocales()721     public void TestAtypicalLocales() {
722         Locale[] localesToTest = { new Locale("de", "CA"),
723                                    new Locale("ja", "ZA"),
724                                    new Locale("ru", "MX"),
725                                    new Locale("en", "FR"),
726                                    new Locale("es", "DE"),
727                                    new Locale("", "HR"),
728                                    new Locale("", "SE"),
729                                    new Locale("", "DO"),
730                                    new Locale("", "BE") };
731         String[] englishDisplayNames = { "German (Canada)",
732                                          "Japanese (South Africa)",
733                                          "Russian (Mexico)",
734                                          "English (France)",
735                                          "Spanish (Germany)",
736                                          "Croatia",
737                                          "Sweden",
738                                          "Dominican Republic",
739                                          "Belgium" };
740         String[] frenchDisplayNames = { "allemand (Canada)",
741                                         "japonais (Afrique du Sud)",
742                                         "russe (Mexique)",
743                                          "anglais (France)",
744                                          "espagnol (Allemagne)",
745                                         "Croatie",
746                                         "Su\u00e8de",
747                                         "R\u00e9publique Dominicaine",
748                                         "Belgique" };
749         String[] spanishDisplayNames = { "alem\u00E1n (Canad\u00E1)",
750                                          "japon\u00E9s (Sud\u00E1frica)",
751                                          "ruso (M\u00e9xico)",
752                                          "ingl\u00E9s (Francia)",
753                                          "espa\u00f1ol (Alemania)",
754                                          "Croacia",
755                                          "Suecia",
756                                          "Rep\u00fablica Dominicana",
757                                          "B\u00E9lgica" };
758 
759 
760         // save the default locale and set to the new default to en_US
761         Locale defaultLocale = Locale.getDefault();
762         Locale.setDefault(Locale.US);
763 
764         for (int i = 0; i < localesToTest.length; i++) {
765             String name = localesToTest[i].getDisplayName(Locale.US);
766             logln(name);
767             if (!name.equals(englishDisplayNames[i])) {
768                 errln("Lookup in English failed: expected \"" + englishDisplayNames[i]
769                         + "\", got \"" + name + "\"");
770             }
771         }
772 
773         for (int i = 0; i < localesToTest.length; i++) {
774             String name = localesToTest[i].getDisplayName(new Locale("es", "ES"));
775             logln(name);
776             if (!name.equals(spanishDisplayNames[i])) {
777                 errln("Lookup in Spanish failed: expected \"" + spanishDisplayNames[i]
778                         + "\", got \"" + name + "\"");
779             }
780         }
781 
782         for (int i = 0; i < localesToTest.length; i++) {
783             String name = localesToTest[i].getDisplayName(Locale.FRANCE);
784             logln(name);
785             if (!name.equals(frenchDisplayNames[i])) {
786                 errln("Lookup in French failed: expected \"" + frenchDisplayNames[i]
787                         + "\", got \"" + name + "\"");
788             }
789         }
790 
791         // restore the default locale for other tests
792         Locale.setDefault(defaultLocale);
793     }
794 
795     /**
796      * @bug 4126371
797      */
TestNullDefault()798     public void TestNullDefault() {
799         // why on earth anyone would ever try to do this is beyond me, but we should
800         // definitely make sure we don't let them
801         boolean gotException = false;
802         try {
803             Locale.setDefault(null);
804         } catch (NullPointerException e) {
805             // all other exception types propagate through here back to the test harness
806             gotException = true;
807         }
808         if (Locale.getDefault() == null) {
809             errln("Locale.getDefault() allowed us to set default to NULL!");
810         }
811         if (!gotException) {
812             errln("Trying to set default locale to NULL didn't throw exception!");
813         }
814     }
815 
816     /**
817      * @bug 4135752
818      * This would be better tested by the LocaleDataTest.  Will move it when I
819      * get the LocaleDataTest working again.
820      */
TestThaiCurrencyFormat()821     public void TestThaiCurrencyFormat() {
822         DecimalFormat thaiCurrency = (DecimalFormat) NumberFormat.getCurrencyInstance(
823                 new Locale("th", "TH"));
824         if (!thaiCurrency.getPositivePrefix().equals("\u0e3f")) {
825             errln("Thai currency prefix wrong: expected \"\u0e3f\", got \""
826                     + thaiCurrency.getPositivePrefix() + "\"");
827         }
828         if (!thaiCurrency.getPositiveSuffix().equals("")) {
829             errln("Thai currency suffix wrong: expected \"\", got \""
830                     + thaiCurrency.getPositiveSuffix() + "\"");
831         }
832     }
833 
834     /**
835      * @bug 4122371
836      * Confirm that Euro support works.  This test is pretty rudimentary; all it does
837      * is check that any locales with the EURO variant format a number using the
838      * Euro currency symbol.
839      *
840      * ASSUME: All locales encode the Euro character "\u20AC".
841      * If this is changed to use the single-character Euro symbol, this
842      * test must be updated.
843      *
844      * DON'T ASSUME: Any specific countries support the Euro.  Instead,
845      * iterate through all locales.
846      */
TestEuroSupport()847     public void TestEuroSupport() {
848         final String EURO_VARIANT = "EURO";
849         final String EURO_CURRENCY = "\u20AC"; // Look for this string in formatted Euro currency
850 
851         Locale[] locales = NumberFormat.getAvailableLocales();
852         for (int i = 0; i < locales.length; ++i) {
853             Locale loc = locales[i];
854             if (loc.getVariant().indexOf(EURO_VARIANT) >= 0) {
855                 NumberFormat nf = NumberFormat.getCurrencyInstance(loc);
856                 String pos = nf.format(271828.182845);
857                 String neg = nf.format(-271828.182845);
858                 if (pos.indexOf(EURO_CURRENCY) >= 0
859                         && neg.indexOf(EURO_CURRENCY) >= 0) {
860                     logln("Ok: " + loc.toString()
861                             + ": " + pos + " / " + neg);
862                 } else {
863                     errln("Fail: " + loc.toString()
864                             + " formats without " + EURO_CURRENCY
865                             + ": " + pos + " / " + neg
866                             + "\n*** THIS FAILURE MAY ONLY MEAN THAT LOCALE DATA HAS CHANGED ***");
867                 }
868             }
869         }
870     }
871 
872     /**
873      * @bug 4139504
874      * toString() doesn't work with language_VARIANT.
875      */
TestToString()876     public void TestToString() {
877         Object[] DATA = {
878             new Locale("xx", "", ""), "xx",
879             new Locale("", "YY", ""), "_YY",
880             new Locale("", "", "ZZ"), "",
881             new Locale("xx", "YY", ""), "xx_YY",
882             new Locale("xx", "", "ZZ"), "xx__ZZ",
883             new Locale("", "YY", "ZZ"), "_YY_ZZ",
884             new Locale("xx", "YY", "ZZ"), "xx_YY_ZZ",
885         };
886         for (int i = 0; i < DATA.length; i += 2) {
887             Locale loc = (Locale) DATA[i];
888             String fmt = (String) DATA[i + 1];
889             if (!loc.toString().equals(fmt)) {
890                 errln("Fail: Locale.toString(" + fmt + ")=>" + loc);
891             }
892         }
893     }
894 
895     /**
896      * @bug 4105828
897      * Currency symbol in zh is wrong.  We will test this at the NumberFormat
898      * end to test the whole pipe.
899      */
Test4105828()900     public void Test4105828() {
901         Locale[] LOC = {Locale.CHINESE, new Locale("zh", "CN", ""),
902             new Locale("zh", "TW", ""), new Locale("zh", "HK", "")};
903         for (int i = 0; i < LOC.length; ++i) {
904             NumberFormat fmt = NumberFormat.getPercentInstance(LOC[i]);
905             String result = fmt.format(1);
906             if (!result.equals("100%")) {
907                 errln("Percent for " + LOC[i] + " should be 100%, got " + result);
908             }
909         }
910     }
911 
912     /**
913      * @bug 4139940
914      * Couldn't reproduce this bug -- probably was fixed earlier.
915      *
916      * ORIGINAL BUG REPORT:
917      * -- basically, hungarian for monday shouldn't have an \u00f4
918      * (o circumflex)in it instead it should be an o with 2 inclined
919      * (right) lines over it..
920      *
921      * You may wonder -- why do all this -- why not just add a line to
922      * LocaleData?  Well, I could see by inspection that the locale file had the
923      * right character in it, so I wanted to check the rest of the pipeline -- a
924      * very remote possibility, but I wanted to be sure.  The other possibility
925      * is that something is wrong with the font mapping subsystem, but we can't
926      * test that here.
927      */
Test4139940()928     public void Test4139940() {
929         Locale mylocale = new Locale("hu", "", "");
930         @SuppressWarnings("deprecation")
931         Date mydate = new Date(98, 3, 13); // A Monday
932         DateFormat df_full = new SimpleDateFormat("EEEE", mylocale);
933         String str = df_full.format(mydate);
934         // Make sure that o circumflex (\u00F4) is NOT there, and
935         // o double acute (\u0151) IS.
936         if (str.indexOf('\u0151') < 0 || str.indexOf('\u00F4') >= 0) {
937             errln("Fail: Monday in Hungarian is wrong");
938         }
939     }
940 
941     /**
942      * @bug 4143951
943      * Russian first day of week should be Monday. Confirmed.
944      */
Test4143951()945     public void Test4143951() {
946         Calendar cal = Calendar.getInstance(new Locale("ru", "", ""));
947         if (cal.getFirstDayOfWeek() != Calendar.MONDAY) {
948             errln("Fail: First day of week in Russia should be Monday");
949         }
950     }
951 
952     /**
953      * @bug 4147315
954      * java.util.Locale.getISO3Country() works wrong for non ISO-3166 codes.
955      * Should throw an exception for unknown locales
956      */
Test4147315()957     public void Test4147315() {
958         // Try with codes that are the wrong length but happen to match text
959         // at a valid offset in the mapping table
960         Locale locale = new Locale("aaa", "CCC");
961 
962         try {
963             String result = locale.getISO3Country();
964 
965             errln("ERROR: getISO3Country() returns: " + result
966                     + " for locale '" + locale + "' rather than exception");
967         } catch (MissingResourceException e) {
968         }
969     }
970 
971     /**
972      * @bug 4147317 4940539
973      * java.util.Locale.getISO3Language() works wrong for non ISO-639 codes.
974      * Should throw an exception for unknown locales, except they have three
975      * letter language codes.
976      */
Test4147317()977     public void Test4147317() {
978         // Try a three letter language code, and check whether it is
979         // returned as is.
980         Locale locale = new Locale("aaa", "CCC");
981 
982         String result = locale.getISO3Language();
983         if (!result.equals("aaa")) {
984             errln("ERROR: getISO3Language() returns: " + result
985                     + " for locale '" + locale + "' rather than returning it as is");
986         }
987 
988         // Try an invalid two letter language code, and check whether it
989         // throws a MissingResourceException.
990         locale = new Locale("zz", "CCC");
991 
992         try {
993             result = locale.getISO3Language();
994 
995             errln("ERROR: getISO3Language() returns: " + result
996                     + " for locale '" + locale + "' rather than exception");
997         } catch (MissingResourceException e) {
998         }
999     }
1000 
1001     /*
1002      * @bug 4147552 4778440 8030696
1003      */
Test4147552()1004     public void Test4147552() {
1005         Locale[] locales = {new Locale("no", "NO"), new Locale("no", "NO", "B"),
1006             new Locale("no", "NO", "NY"), new Locale("nb", "NO"),
1007             new Locale("nn", "NO")};
1008         String[] englishDisplayNames = {"Norwegian (Norway)",
1009             "Norwegian (Norway,Bokm\u00e5l)",
1010             "Norwegian (Norway,Nynorsk)",
1011             "Norwegian Bokm\u00e5l (Norway)",
1012             "Norwegian Nynorsk (Norway)"};
1013         String[] norwegianDisplayNames = {"norsk (Norge)",
1014             "norsk (Norge,bokm\u00e5l)", "norsk (Noreg,nynorsk)",
1015             "bokm\u00e5l (Norge)", "nynorsk (Noreg)"};
1016 
1017         for (int i = 0; i < locales.length; i++) {
1018             Locale loc = locales[i];
1019             if (!loc.getDisplayName(Locale.US).equals(englishDisplayNames[i])) {
1020                 errln("English display-name mismatch: expected "
1021                         + englishDisplayNames[i] + ", got " + loc.getDisplayName());
1022             }
1023             if (!loc.getDisplayName(loc).equals(norwegianDisplayNames[i])) {
1024                 errln("Norwegian display-name mismatch: expected "
1025                         + norwegianDisplayNames[i] + ", got "
1026                         + loc.getDisplayName(loc));
1027             }
1028         }
1029     }
1030 
1031     /*
1032      * @bug 8030696
1033      */
Test8030696()1034     public void Test8030696() {
1035         List<Locale> av = Arrays.asList(Locale.getAvailableLocales());
1036         if (!av.contains(new Locale("nb", "NO"))
1037                 || !av.contains(new Locale("nn", "NO"))) {
1038             errln("\"nb-NO\" and/or \"nn-NO\" locale(s) not returned from getAvailableLocales().");
1039         }
1040     }
1041 
escapeUnicode(String s)1042     static String escapeUnicode(String s) {
1043         StringBuffer buf = new StringBuffer();
1044         for (int i = 0; i < s.length(); ++i) {
1045             char c = s.charAt(i);
1046             if (c >= 0x20 && c <= 0x7F) {
1047                 buf.append(c);
1048             } else {
1049                 buf.append("\\u");
1050                 String h = "000" + Integer.toHexString(c);
1051                 if (h.length() > 4) {
1052                     h = h.substring(h.length() - 4);
1053                 }
1054                 buf.append(h);
1055             }
1056         }
1057         return buf.toString();
1058     }
1059 }
1060