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