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