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