CurrencyTest.java revision 13901:b2a69d66dc65
1/* 2 * Copyright (c) 2007, 2016, 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 4290801 4692419 4693631 5101540 5104960 6296410 6336600 6371531 26 * 6488442 7036905 8008577 8039317 8074350 8074351 27 * @summary Basic tests for Currency class. 28 * @modules jdk.localedata 29 */ 30 31import java.io.ByteArrayInputStream; 32import java.io.ByteArrayOutputStream; 33import java.io.ObjectInputStream; 34import java.io.ObjectOutputStream; 35import java.util.Calendar; 36import java.util.Date; 37import java.util.Currency; 38import java.util.GregorianCalendar; 39import java.util.Locale; 40import java.util.TimeZone; 41 42 43public class CurrencyTest { 44 45 public static void main(String[] args) throws Exception { 46 CheckDataVersion.check(); 47 testCurrencyCodeValidation(); 48 testLocaleMapping(); 49 testSymbols(); 50 testFractionDigits(); 51 testSerialization(); 52 testDisplayNames(); 53 testFundsCodes(); 54 } 55 56 static void testCurrencyCodeValidation() { 57 // test creation of some valid currencies 58 testValidCurrency("USD"); 59 testValidCurrency("EUR"); 60 testValidCurrency("GBP"); 61 testValidCurrency("JPY"); 62 testValidCurrency("CNY"); 63 testValidCurrency("CHF"); 64 65 // test creation of some fictitious currencies 66 testInvalidCurrency("AQD"); 67 testInvalidCurrency("US$"); 68 testInvalidCurrency("\u20AC"); 69 } 70 71 static void testValidCurrency(String currencyCode) { 72 Currency currency1 = Currency.getInstance(currencyCode); 73 Currency currency2 = Currency.getInstance(currencyCode); 74 if (currency1 != currency2) { 75 throw new RuntimeException("Didn't get same instance for same currency code"); 76 } 77 if (!currency1.getCurrencyCode().equals(currencyCode)) { 78 throw new RuntimeException("Currency code changed"); 79 } 80 } 81 82 static void testInvalidCurrency(String currencyCode) { 83 boolean gotException = false; 84 try { 85 Currency currency = Currency.getInstance(currencyCode); 86 } catch (IllegalArgumentException e) { 87 gotException = true; 88 } 89 if (!gotException) { 90 throw new RuntimeException("didn't get specified exception"); 91 } 92 } 93 94 static void testLocaleMapping() { 95 // very basic test: most countries have their own currency, and then 96 // their currency code is an extension of their country code. 97 Locale[] locales = Locale.getAvailableLocales(); 98 int goodCountries = 0; 99 int ownCurrencies = 0; 100 for (int i = 0; i < locales.length; i++) { 101 Locale locale = locales[i]; 102 String ctryCode = locale.getCountry(); 103 int ctryLength = ctryCode.length(); 104 if (ctryLength == 0 || 105 ctryLength == 3 || // UN M.49 code 106 ctryCode.matches("AA|Q[M-Z]|X[A-Z]|ZZ" + // user defined codes 107 "AC|CP|DG|EA|EU|FX|IC|SU|TA|UK")) { // exceptional reservation codes 108 boolean gotException = false; 109 try { 110 Currency.getInstance(locale); 111 } catch (IllegalArgumentException e) { 112 gotException = true; 113 } 114 if (!gotException) { 115 throw new RuntimeException("didn't get specified exception"); 116 } 117 } else { 118 goodCountries++; 119 Currency currency = Currency.getInstance(locale); 120 if (currency.getCurrencyCode().indexOf(locale.getCountry()) == 0) { 121 ownCurrencies++; 122 } 123 } 124 } 125 System.out.println("Countries tested: " + goodCountries + 126 ", own currencies: " + ownCurrencies); 127 if (ownCurrencies < (goodCountries / 2 + 1)) { 128 throw new RuntimeException("suspicious: not enough countries have their own currency."); 129 } 130 131 // check a few countries that don't change their currencies too often 132 String[] country1 = {"US", "CA", "JP", "CN", "SG", "CH"}; 133 String[] currency1 = {"USD", "CAD", "JPY", "CNY", "SGD", "CHF"}; 134 for (int i = 0; i < country1.length; i++) { 135 checkCountryCurrency(country1[i], currency1[i]); 136 } 137 138 /* 139 * check currency changes 140 * In current implementation, there is no data of old currency and transition date at jdk/src/share/classes/java/util/CurrencyData.properties. 141 * So, all the switch data arrays are empty. In the future, if data of old currency and transition date are necessary for any country, the 142 * arrays here can be updated so that the program can check the currency switch. 143 */ 144 String[] switchOverCtry = {}; 145 String[] switchOverOld = {}; 146 String[] switchOverNew = {}; 147 String[] switchOverTZ = {}; 148 int[] switchOverYear = {}; 149 int[] switchOverMonth = {}; 150 int[] switchOverDay = {}; 151 152 for (int i = 0; i < switchOverCtry.length; i++) { 153 TimeZone.setDefault(TimeZone.getTimeZone(switchOverTZ[i])); 154 Calendar date = new GregorianCalendar(switchOverYear[i], switchOverMonth[i], switchOverDay[i]); 155 long switchOver = date.getTime().getTime(); 156 boolean switchedOver = System.currentTimeMillis() >= switchOver; 157 checkCountryCurrency(switchOverCtry[i], switchedOver ? switchOverNew[i] : switchOverOld[i]); 158 } 159 160 // check a country code which doesn't have a currency 161 checkCountryCurrency("AQ", null); 162 163 // check an invalid country code 164 boolean gotException = false; 165 try { 166 Currency.getInstance(new Locale("", "EU")); 167 } catch (IllegalArgumentException e) { 168 gotException = true; 169 } 170 if (!gotException) { 171 throw new RuntimeException("didn't get specified exception."); 172 } 173 } 174 175 static void checkCountryCurrency(String countryCode, String expected) { 176 Locale locale = new Locale("", countryCode); 177 Currency currency = Currency.getInstance(locale); 178 String code = (currency != null) ? currency.getCurrencyCode() : null; 179 if (!(expected == null ? code == null : expected.equals(code))) { 180 throw new RuntimeException("Wrong currency for " + 181 locale.getDisplayCountry() + 182 ": expected " + expected + ", got " + code); 183 } 184 } 185 186 static void testSymbols() { 187 testSymbol("USD", Locale.US, "$"); 188 testSymbol("EUR", Locale.GERMANY, "\u20AC"); 189 testSymbol("USD", Locale.PRC, "USD"); 190 } 191 192 static void testSymbol(String currencyCode, Locale locale, String expectedSymbol) { 193 String symbol = Currency.getInstance(currencyCode).getSymbol(locale); 194 if (!symbol.equals(expectedSymbol)) { 195 throw new RuntimeException("Wrong symbol for currency " + 196 currencyCode +": expected " + expectedSymbol + 197 ", got " + symbol); 198 } 199 } 200 201 static void testFractionDigits() { 202 testFractionDigits("USD", 2); 203 testFractionDigits("EUR", 2); 204 testFractionDigits("JPY", 0); 205 testFractionDigits("XDR", -1); 206 207 testFractionDigits("BHD", 3); 208 testFractionDigits("IQD", 3); 209 testFractionDigits("JOD", 3); 210 testFractionDigits("KWD", 3); 211 testFractionDigits("LYD", 3); 212 testFractionDigits("OMR", 3); 213 testFractionDigits("TND", 3); 214 215 // Turkish Lira 216 testFractionDigits("TRL", 0); 217 testFractionDigits("TRY", 2); 218 } 219 220 static void testFractionDigits(String currencyCode, int expectedFractionDigits) { 221 int digits = Currency.getInstance(currencyCode).getDefaultFractionDigits(); 222 if (digits != expectedFractionDigits) { 223 throw new RuntimeException("Wrong number of fraction digits for currency " + 224 currencyCode +": expected " + expectedFractionDigits + 225 ", got " + digits); 226 } 227 } 228 229 static void testSerialization() throws Exception { 230 Currency currency1 = Currency.getInstance("DEM"); 231 232 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 233 ObjectOutputStream oStream = new ObjectOutputStream(baos); 234 oStream.writeObject(currency1); 235 oStream.flush(); 236 byte[] bytes = baos.toByteArray(); 237 238 ByteArrayInputStream bais = new ByteArrayInputStream(bytes); 239 ObjectInputStream iStream = new ObjectInputStream(bais); 240 Currency currency2 = (Currency) iStream.readObject(); 241 242 if (currency1 != currency2) { 243 throw new RuntimeException("serialization breaks class invariant"); 244 } 245 } 246 247 static void testDisplayNames() { 248 // null argument test 249 try { 250 testDisplayName("USD", null, ""); 251 throw new RuntimeException("getDisplayName(NULL) did not throw an NPE."); 252 } catch (NullPointerException npe) {} 253 254 testDisplayName("USD", Locale.ENGLISH, "US Dollar"); 255 testDisplayName("FRF", Locale.FRENCH, "franc fran\u00e7ais"); 256 testDisplayName("DEM", Locale.GERMAN, "Deutsche Mark"); 257 testDisplayName("ESP", new Locale("es"), "peseta espa\u00f1ola"); 258 testDisplayName("ITL", new Locale("it"), "lira italiana"); 259 testDisplayName("JPY", Locale.JAPANESE, "\u65e5\u672c\u5186"); 260 testDisplayName("KRW", Locale.KOREAN, "\ub300\ud55c\ubbfc\uad6d \uc6d0"); 261 testDisplayName("SEK", new Locale("sv"), "svensk krona"); 262 testDisplayName("CNY", Locale.SIMPLIFIED_CHINESE, "\u4eba\u6c11\u5e01"); 263 testDisplayName("TWD", Locale.TRADITIONAL_CHINESE, "\u65b0\u81fa\u5e63"); 264 } 265 266 static void testDisplayName(String currencyCode, Locale locale, String expectedName) { 267 String name = Currency.getInstance(currencyCode).getDisplayName(locale); 268 if (!name.equals(expectedName)) { 269 throw new RuntimeException("Wrong display name for currency " + 270 currencyCode +": expected '" + expectedName + 271 "', got '" + name + "'"); 272 } 273 } 274 static void testFundsCodes() { 275 testValidCurrency("BOV"); 276 testValidCurrency("CHE"); 277 testValidCurrency("CHW"); 278 testValidCurrency("CLF"); 279 testValidCurrency("COU"); 280 testValidCurrency("MXV"); 281 testValidCurrency("USN"); 282 testValidCurrency("UYI"); 283 284 testFractionDigits("BOV", 2); 285 testFractionDigits("CHE", 2); 286 testFractionDigits("CHW", 2); 287 testFractionDigits("CLF", 4); 288 testFractionDigits("COU", 2); 289 testFractionDigits("MXV", 2); 290 testFractionDigits("USN", 2); 291 testFractionDigits("UYI", 0); 292 293 testNumericCode("BOV", 984); 294 testNumericCode("CHE", 947); 295 testNumericCode("CHW", 948); 296 testNumericCode("CLF", 990); 297 testNumericCode("COU", 970); 298 testNumericCode("MXV", 979); 299 testNumericCode("USN", 997); 300 testNumericCode("UYI", 940); 301 } 302 303 static void testNumericCode(String currencyCode, int expectedNumeric) { 304 int numeric = Currency.getInstance(currencyCode).getNumericCode(); 305 if (numeric != expectedNumeric) { 306 throw new RuntimeException("Wrong numeric code for currency " + 307 currencyCode +": expected " + expectedNumeric + 308 ", got " + numeric); 309 } 310 } 311} 312