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