1 /*
   2  * Copyright (c) 2007, 2013, 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 4449637 8008577
  26  * @summary Basic acceptance test for international J2RE. Verifies that the
  27  * most important locale data and character converters exist and are
  28  * minimally functional.
  29  * @run main/othervm -Djava.locale.providers=JRE,SPI InternationalBAT
  30  */
  31 
  32 import java.io.UnsupportedEncodingException;
  33 import java.text.DateFormat;
  34 import java.util.Calendar;
  35 import java.util.Date;
  36 import java.util.Locale;
  37 import java.util.TimeZone;
  38 
  39 public class InternationalBAT {
  40 
  41     public static void main(String[] args) {
  42         boolean pass = true;
  43 
  44         TimeZone tz = TimeZone.getDefault();
  45         try {
  46             pass &= testRequiredLocales();
  47             pass &= testRequiredEncodings();
  48         } finally {
  49             TimeZone.setDefault(tz);
  50         }
  51 
  52         if (!pass) {
  53             System.out.println("\nSome tests failed.\n"
  54                     + "If you installed the US-only J2RE for Windows, "
  55                     + "failures are expected and OK.\n"
  56                     + "If you installed the international J2RE, or any J2SDK, "
  57                     + "or if this occurs on any platform other than Windows, "
  58                     + "please file a bug report.\n"
  59                     + "Unfortunately, this test cannot determine whether you "
  60                     + "installed a US-only J2RE, an international J2RE, or "
  61                     + "a J2SDK.\n");
  62             throw new RuntimeException();
  63         }
  64     }
  65 
  66     // We require the "fully supported locales" for java.util and java.text:
  67     // http://webwork.eng/j2se/1.4/docs/guide/intl/locale.doc.html#util-text
  68 
  69     private static Locale[] requiredLocales = {
  70         new Locale("ar", "SA"),
  71         new Locale("zh", "CN"),
  72         new Locale("zh", "TW"),
  73         new Locale("nl", "NL"),
  74         new Locale("en", "AU"),
  75         new Locale("en", "CA"),
  76         new Locale("en", "GB"),
  77         new Locale("en", "US"),
  78         new Locale("fr", "CA"),
  79         new Locale("fr", "FR"),
  80         new Locale("de", "DE"),
  81         new Locale("iw", "IL"),
  82         new Locale("hi", "IN"),
  83         new Locale("it", "IT"),
  84         new Locale("ja", "JP"),
  85         new Locale("ko", "KR"),
  86         new Locale("pt", "BR"),
  87         new Locale("es", "ES"),
  88         new Locale("sv", "SE"),
  89         new Locale("th", "TH"),
  90     };
  91 
  92     // Date strings for May 10, 2001, for the required locales
  93     private static String[] requiredLocaleDates = {
  94         "10 \u0645\u0627\u064A\u0648, 2001",
  95         "2001\u5E745\u670810\u65E5 \u661F\u671F\u56DB",
  96         "2001\u5E745\u670810\u65E5 \u661F\u671F\u56DB",
  97         "donderdag 10 mei 2001",
  98         "Thursday, 10 May 2001",
  99         "Thursday, May 10, 2001",
 100         "Thursday, 10 May 2001",
 101         "Thursday, May 10, 2001",
 102         "jeudi 10 mai 2001",
 103         "jeudi 10 mai 2001",
 104         "Donnerstag, 10. Mai 2001",
 105         "\u05D9\u05D5\u05DD \u05D7\u05DE\u05D9\u05E9\u05D9 10 \u05DE\u05D0\u05D9 2001",
 106         "\u0917\u0941\u0930\u0941\u0935\u093E\u0930, \u0967\u0966 \u092E\u0908, \u0968\u0966\u0966\u0967",
 107         "gioved\u00EC 10 maggio 2001",
 108         "2001\u5E745\u670810\u65E5", // ja_JP
 109         "2001\uB144 5\uC6D4 10\uC77C \uBAA9\uC694\uC77C",
 110         "Quinta-feira, 10 de Maio de 2001",
 111         "jueves 10 de mayo de 2001",
 112         "den 10 maj 2001",
 113         "\u0E27\u0E31\u0E19\u0E1E\u0E24\u0E2B\u0E31\u0E2A\u0E1A\u0E14\u0E35\u0E17\u0E35\u0E48 10 \u0E1E\u0E24\u0E29\u0E20\u0E32\u0E04\u0E21 \u0E1E.\u0E28. 2544",
 114     };
 115 
 116     private static boolean testRequiredLocales() {
 117         boolean pass = true;
 118 
 119         TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
 120         Calendar calendar = Calendar.getInstance(Locale.US);
 121         calendar.clear();
 122         calendar.set(2001, 4, 10, 12, 0, 0);
 123         Date date = calendar.getTime();
 124 
 125         Locale[] available = Locale.getAvailableLocales();
 126         for (int i = 0; i < requiredLocales.length; i++) {
 127             Locale locale = requiredLocales[i];
 128             boolean found = false;
 129             for (int j = 0; j < available.length; j++) {
 130                 if (available[j].equals(locale)) {
 131                     found = true;
 132                     break;
 133                 }
 134             }
 135             if (!found) {
 136                 System.out.println("Locale not available: " + locale);
 137                 pass = false;
 138             } else {
 139                 DateFormat format =
 140                         DateFormat.getDateInstance(DateFormat.FULL, locale);
 141                 String dateString = format.format(date);
 142                 if (!dateString.equals(requiredLocaleDates[i])) {
 143                     System.out.println("Incorrect date string for locale "
 144                             + locale + ". Expected: " + requiredLocaleDates[i]
 145                             + ", got: " + dateString);
 146                     pass = false;
 147                 }
 148             }
 149         }
 150         return pass;
 151     }
 152 
 153     // We require the encodings of the fully supported writing systems:
 154     // http://webwork.eng/j2se/1.4/docs/guide/intl/locale.doc.html#jfc
 155 
 156     private static String[] requiredEncodings = {
 157         "Cp1256",
 158         "MS936",
 159         "MS950",
 160         "Cp1255",
 161         "MS932",
 162         "MS949",
 163         "Cp1252",
 164         "MS874",
 165         "ISO8859_6",
 166         "EUC_CN",
 167         "UTF8",
 168         "GBK",
 169         "EUC_TW",
 170         "ISO8859_8",
 171         "EUC_JP",
 172         "PCK",
 173         "EUC_KR",
 174         "ISO8859_1",
 175         "ISO8859_15",
 176         "TIS620",
 177     };
 178 
 179     // one sample locale each for the required encodings
 180 
 181     private static Locale[] sampleLocales = {
 182         new Locale("ar", "SA"),
 183         new Locale("zh", "CN"),
 184         new Locale("zh", "TW"),
 185         new Locale("iw", "IL"),
 186         new Locale("ja", "JP"),
 187         new Locale("ko", "KR"),
 188         new Locale("it", "IT"),
 189         new Locale("th", "TH"),
 190         new Locale("ar", "SA"),
 191         new Locale("zh", "CN"),
 192         new Locale("zh", "CN"),
 193         new Locale("zh", "CN"),
 194         new Locale("zh", "TW"),
 195         new Locale("iw", "IL"),
 196         new Locale("ja", "JP"),
 197         new Locale("ja", "JP"),
 198         new Locale("ko", "KR"),
 199         new Locale("it", "IT"),
 200         new Locale("it", "IT"),
 201         new Locale("th", "TH"),
 202     };
 203 
 204     // expected conversion results for the date strings of the sample locales
 205 
 206     private static byte[][] expectedBytes = {
 207         { 0x31, 0x30, 0x20, (byte) 0xE3, (byte) 0xC7, (byte) 0xED, (byte) 0xE6, 0x2C, 0x20, 0x32, 0x30, 0x30, 0x31, },
 208         { 0x32, 0x30, 0x30, 0x31, (byte) 0xC4, (byte) 0xEA, 0x35, (byte) 0xD4, (byte) 0xC2, 0x31, 0x30, (byte) 0xC8, (byte) 0xD5, 0x20, (byte) 0xD0, (byte) 0xC7, (byte) 0xC6, (byte) 0xDA, (byte) 0xCB, (byte) 0xC4},
 209         { 0x32, 0x30, 0x30, 0x31, (byte) 0xA6, 0x7E, 0x35, (byte) 0xA4, (byte) 0xEB, 0x31, 0x30, (byte) 0xA4, (byte) 0xE9, 0x20, (byte) 0xAC, (byte)0x50, (byte) 0xB4, (byte) 0xC1, (byte) 0xA5, (byte) 0x7C},
 210         { (byte) 0xE9, (byte) 0xE5, (byte) 0xED, 0x20, (byte) 0xE7, (byte) 0xEE, (byte) 0xE9, (byte) 0xF9, (byte) 0xE9, 0x20, 0x31, 0x30, 0x20, (byte) 0xEE, (byte) 0xE0, (byte) 0xE9, 0x20, 0x32, 0x30, 0x30, 0x31, },
 211         { 0x32, 0x30, 0x30, 0x31, (byte) 0x94, 0x4E, 0x35, (byte) 0x8C, (byte) 0x8E, 0x31, 0x30, (byte) 0x93, (byte) 0xFA, },
 212         { 0x32, 0x30, 0x30, 0x31, (byte) 0xB3, (byte) 0xE2, 0x20, 0x35, (byte) 0xBF, (byte) 0xF9, 0x20, 0x31, 0x30, (byte) 0xC0, (byte) 0xCF, 0x20, (byte) 0xB8, (byte) 0xF1, (byte) 0xBF, (byte) 0xE4, (byte) 0xC0, (byte) 0xCF, },
 213         { 0x67, 0x69, 0x6F, 0x76, 0x65, 0x64, (byte) 0xEC, 0x20, 0x31, 0x30, 0x20, 0x6D, 0x61, 0x67, 0x67, 0x69, 0x6F, 0x20, 0x32, 0x30, 0x30, 0x31, },
 214         { (byte) 0xC7, (byte) 0xD1, (byte) 0xB9, (byte) 0xBE, (byte) 0xC4, (byte) 0xCB, (byte) 0xD1, (byte) 0xCA, (byte) 0xBA, (byte) 0xB4, (byte) 0xD5, (byte) 0xB7, (byte) 0xD5, (byte) 0xE8, 0x20, 0x31, 0x30, 0x20, (byte) 0xBE, (byte) 0xC4, (byte) 0xC9, (byte) 0xC0, (byte) 0xD2, (byte) 0xA4, (byte) 0xC1, 0x20, (byte) 0xBE, 0x2E, (byte) 0xC8, 0x2E, 0x20, 0x32, 0x35, 0x34, 0x34, },
 215         { 0x31, 0x30, 0x20, (byte) 0xE5, (byte) 0xC7, (byte) 0xEA, (byte) 0xE8, 0x2C, 0x20, 0x32, 0x30, 0x30, 0x31, },
 216         { 0x32, 0x30, 0x30, 0x31, (byte) 0xC4, (byte) 0xEA, 0x35, (byte) 0xD4, (byte) 0xC2, 0x31, 0x30, (byte) 0xC8, (byte) 0xD5, 0x20, (byte) 0xD0, (byte) 0xC7, (byte) 0xC6, (byte) 0xDA, (byte) 0xCB, (byte) 0xC4},
 217         { 0x32, 0x30, 0x30, 0x31, (byte) 0xE5, (byte) 0xB9, (byte) 0xB4, 0x35, (byte) 0xE6, (byte) 0x9C, (byte) 0x88, 0x31, 0x30, (byte) 0xE6, (byte) 0x97, (byte) 0xA5, 0x20, (byte) 0xE6, (byte)0x98, (byte) 0x9F, (byte) 0xE6, (byte) 0x9C, (byte) 0x9F, (byte) 0xE5, (byte) 0x9B, (byte) 0x9B},
 218         { 0x32, 0x30, 0x30, 0x31, (byte) 0xC4, (byte) 0xEA, 0x35, (byte) 0xD4, (byte) 0xC2, 0x31, 0x30, (byte) 0xC8, (byte) 0xD5, 0x20, (byte) 0xD0, (byte) 0xC7, (byte) 0xC6, (byte) 0xDA, (byte) 0xCB, (byte) 0xC4},
 219         { 0x32, 0x30, 0x30, 0x31, (byte) 0xC8, (byte) 0xA1, 0x35, (byte) 0xC5, (byte) 0xCC, 0x31, 0x30, (byte) 0xC5, (byte) 0xCA, 0x20, (byte) 0xD1, (byte) 0xD3, (byte) 0xDF, (byte) 0xE6, (byte) 0xC6, (byte) 0xBE},
 220         { (byte) 0xE9, (byte) 0xE5, (byte) 0xED, 0x20, (byte) 0xE7, (byte) 0xEE, (byte) 0xE9, (byte) 0xF9, (byte) 0xE9, 0x20, 0x31, 0x30, 0x20, (byte) 0xEE, (byte) 0xE0, (byte) 0xE9, 0x20, 0x32, 0x30, 0x30, 0x31, },
 221         { 0x32, 0x30, 0x30, 0x31, (byte) 0xC7, (byte) 0xAF, 0x35, (byte) 0xB7, (byte) 0xEE, 0x31, 0x30, (byte) 0xC6, (byte) 0xFC, },
 222         { 0x32, 0x30, 0x30, 0x31, (byte) 0x94, 0x4E, 0x35, (byte) 0x8C, (byte) 0x8E, 0x31, 0x30, (byte) 0x93, (byte) 0xFA, },
 223         { 0x32, 0x30, 0x30, 0x31, (byte) 0xB3, (byte) 0xE2, 0x20, 0x35, (byte) 0xBF, (byte) 0xF9, 0x20, 0x31, 0x30, (byte) 0xC0, (byte) 0xCF, 0x20, (byte) 0xB8, (byte) 0xF1, (byte) 0xBF, (byte) 0xE4, (byte) 0xC0, (byte) 0xCF, },
 224         { 0x67, 0x69, 0x6F, 0x76, 0x65, 0x64, (byte) 0xEC, 0x20, 0x31, 0x30, 0x20, 0x6D, 0x61, 0x67, 0x67, 0x69, 0x6F, 0x20, 0x32, 0x30, 0x30, 0x31, },
 225         { 0x67, 0x69, 0x6F, 0x76, 0x65, 0x64, (byte) 0xEC, 0x20, 0x31, 0x30, 0x20, 0x6D, 0x61, 0x67, 0x67, 0x69, 0x6F, 0x20, 0x32, 0x30, 0x30, 0x31, },
 226         { (byte) 0xC7, (byte) 0xD1, (byte) 0xB9, (byte) 0xBE, (byte) 0xC4, (byte) 0xCB, (byte) 0xD1, (byte) 0xCA, (byte) 0xBA, (byte) 0xB4, (byte) 0xD5, (byte) 0xB7, (byte) 0xD5, (byte) 0xE8, 0x20, 0x31, 0x30, 0x20, (byte) 0xBE, (byte) 0xC4, (byte) 0xC9, (byte) 0xC0, (byte) 0xD2, (byte) 0xA4, (byte) 0xC1, 0x20, (byte) 0xBE, 0x2E, (byte) 0xC8, 0x2E, 0x20, 0x32, 0x35, 0x34, 0x34, },
 227     };
 228 
 229 
 230     private static boolean testRequiredEncodings() {
 231         boolean pass = true;
 232 
 233         for (int i = 0; i < requiredEncodings.length; i++) {
 234             String encoding = requiredEncodings[i];
 235             Locale sampleLocale = sampleLocales[i];
 236             try {
 237                 int index = 0;
 238                 while (!sampleLocale.equals(requiredLocales[index])) {
 239                     index++;
 240                 }
 241                 byte[] out = requiredLocaleDates[index].getBytes(encoding);
 242                 byte[] expected = expectedBytes[i];
 243                 if (out.length != expected.length) {
 244                     reportConversionError(encoding, expected, out);
 245                     pass = false;
 246                 } else {
 247                     for (int j = 0; j < out.length; j++) {
 248                         if (out[j] != expected[j]) {
 249                             reportConversionError(encoding, expected, out);
 250                             pass = false;
 251                             break;
 252                         }
 253                     }
 254                 }
 255             } catch (UnsupportedEncodingException e) {
 256                 System.out.println("Encoding not available: " + encoding);
 257                 pass = false;
 258             }
 259         }
 260         return pass;
 261     }
 262 
 263     private static void reportConversionError(String encoding,
 264             byte[] expected, byte[] actual) {
 265 
 266         System.out.println("Incorrect conversion for encoding: " + encoding);
 267         System.out.println("Expected output:");
 268         dumpBytes(expected);
 269         System.out.println("Actual output:");
 270         dumpBytes(actual);
 271     }
 272 
 273     private static void dumpBytes(byte[] bytes) {
 274         System.out.print("        { ");
 275         for (int i = 0; i < bytes.length; i++) {
 276              byte b = bytes[i];
 277              if (b < 0) {
 278                  System.out.print("(byte) ");
 279              }
 280              System.out.print("0x" + toHex((b & 0x00F0) >> 4)
 281                      + toHex((b & 0x000F)) + ", ");
 282         }
 283         System.out.println("},");
 284     }
 285 
 286     private static char toHex(int i) {
 287         if (i <= 9) {
 288             return (char) ('0' + i);
 289         } else {
 290             return (char) ('A' + i - 10);
 291         }
 292     }
 293 }