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