1 /*
   2  * Copyright (c) 2007, 2011, 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
  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 
  64 import java.text.*;
  65 import java.util.Locale;
  66 import java.util.MissingResourceException;
  67 import java.util.Date;
  68 import java.util.Calendar;
  69 import java.io.*;
  70 
  71 public 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 7066203
 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 != 250)
 444             errln("Expected getISOCountries to return 250 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 /*
 512 test 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 }