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