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