Path: blob/master/test/jdk/java/text/Format/NumberFormat/NumberTest.java
41152 views
/*1* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 4122840 4135202 4408066 4838107 800857726* @summary test NumberFormat27* @library /java/text/testlib28* @modules java.base/sun.util.resources29* jdk.localedata30* @compile -XDignore.symbol.file NumberTest.java31* @run main/othervm -Djava.locale.providers=COMPAT,SPI NumberTest32*/3334import java.util.*;35import java.text.*;36import sun.util.resources.LocaleData;3738public class NumberTest extends IntlTest39{40public static void main(String[] args) throws Exception {41new NumberTest().run(args);42}4344// Test pattern handling45public void TestPatterns()46{47DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);48String pat[] = { "#.#", "#.", ".#", "#" };49String newpat[] = { "#0.#", "#0.", "#.0", "#" };50String num[] = { "0", "0.", ".0", "0" };51for (int i=0; i<pat.length; ++i)52{53DecimalFormat fmt = new DecimalFormat(pat[i], sym);54String newp = fmt.toPattern();55if (!newp.equals(newpat[i]))56errln("FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +57"; " + newp + " seen instead");5859String s = fmt.format(0);60if (!s.equals(num[i]))61{62errln("FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +63"; " + s + " seen instead");64logln("Min integer digits = " + fmt.getMinimumIntegerDigits());65}66}67}6869// Test exponential pattern70public void TestExponential() {71DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);72String pat[] = { "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]" };73double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };74long lval[] = { 0, -1, 1, 123456789 };75String valFormat[] = {76"1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",77"12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",78"12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",79"1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"80};81String lvalFormat[] = {82"0E0", "-1E0", "1E0", "1.2346E8",83"00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",84"0E000", "-1E000", "1E000", "123.4568E006",85"0E0", "[1E0]", "1E0", "1.235E8"86};87double valParse[] = {880.01234, 123460000, 1.23E300, -3.1416E-271,890.01234, 123460000, 1.23E300, -3.1416E-271,900.01234, 123456800, 1.23E300, -3.141593E-271,910.01234, 123500000, 1.23E300, -3.142E-271,92};93long lvalParse[] = {940, -1, 1, 123460000,950, -1, 1, 123460000,960, -1, 1, 123456800,970, -1, 1, 123500000,98};99int ival = 0, ilval = 0;100for (int p=0; p<pat.length; ++p) {101DecimalFormat fmt = new DecimalFormat(pat[p], sym);102logln("Pattern \"" + pat[p] + "\" -toPattern-> \"" +103fmt.toPattern() + '"');104105for (int v=0; v<val.length; ++v) {106String s = fmt.format(val[v]);107logln(" Format " + val[v] + " -> " + escape(s));108if (!s.equals(valFormat[v+ival])) {109errln("FAIL: Expected " + valFormat[v+ival] +110", got " + s +111", pattern=" + fmt.toPattern());112}113114ParsePosition pos = new ParsePosition(0);115Number a = fmt.parse(s, pos);116if (pos.getIndex() == s.length()) {117logln(" Parse -> " + a);118if (a.doubleValue() != valParse[v+ival]) {119errln("FAIL: Expected " + valParse[v+ival] +120", got " + a.doubleValue() +121", pattern=" + fmt.toPattern());122}123} else {124errln(" FAIL: Partial parse (" + pos.getIndex() +125" chars) -> " + a);126}127}128for (int v=0; v<lval.length; ++v) {129String s = fmt.format(lval[v]);130logln(" Format " + lval[v] + "L -> " + escape(s));131if (!s.equals(lvalFormat[v+ilval])) {132errln("ERROR: Expected " + lvalFormat[v+ilval] +133", got " + s +134", pattern=" + fmt.toPattern());135}136137ParsePosition pos = new ParsePosition(0);138Number a = fmt.parse(s, pos);139if (pos.getIndex() == s.length()) {140logln(" Parse -> " + a);141if (a.longValue() != lvalParse[v+ilval]) {142errln("FAIL: Expected " + lvalParse[v+ilval] +143", got " + a +144", pattern=" + fmt.toPattern());145}146} else {147errln(" FAIL: Partial parse (" + pos.getIndex() +148" chars) -> " + a);149}150}151ival += val.length;152ilval += lval.length;153}154}155156// Test the handling of quotes157public void TestQuotes()158{159String pat;160DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);161DecimalFormat fmt = new DecimalFormat(pat = "a'fo''o'b#", sym);162String s = fmt.format(123);163logln("Pattern \"" + pat + "\"");164logln(" Format 123 -> " + escape(s));165if (!s.equals("afo'ob123")) errln("FAIL: Expected afo'ob123");166167fmt = new DecimalFormat(pat = "a''b#", sym);168s = fmt.format(123);169logln("Pattern \"" + pat + "\"");170logln(" Format 123 -> " + escape(s));171if (!s.equals("a'b123")) errln("FAIL: Expected a'b123");172}173174// Test the use of the currency sign175public void TestCurrencySign()176{177DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);178DecimalFormat fmt = new DecimalFormat("\u00A4#,##0.00;-\u00A4#,##0.00", sym);179// Can't test this properly until currency API goes public180// DecimalFormatSymbols sym = fmt.getDecimalFormatSymbols();181182String s = fmt.format(1234.56);183logln("Pattern \"" + fmt.toPattern() + "\"");184logln(" Format " + 1234.56 + " -> " + escape(s));185if (!s.equals("$1,234.56")) errln("FAIL: Expected $1,234.56");186s = fmt.format(-1234.56);187logln(" Format " + -1234.56 + " -> " + escape(s));188if (!s.equals("-$1,234.56")) errln("FAIL: Expected -$1,234.56");189190fmt = new DecimalFormat("\u00A4\u00A4 #,##0.00;\u00A4\u00A4 -#,##0.00", sym);191s = fmt.format(1234.56);192logln("Pattern \"" + fmt.toPattern() + "\"");193logln(" Format " + 1234.56 + " -> " + escape(s));194if (!s.equals("USD 1,234.56")) errln("FAIL: Expected USD 1,234.56");195s = fmt.format(-1234.56);196logln(" Format " + -1234.56 + " -> " + escape(s));197if (!s.equals("USD -1,234.56")) errln("FAIL: Expected USD -1,234.56");198}199static String escape(String s)200{201StringBuffer buf = new StringBuffer();202char HEX[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };203for (int i=0; i<s.length(); ++i)204{205char c = s.charAt(i);206if (c <= (char)0x7F) buf.append(c);207else208{209buf.append("\\U");210buf.append(HEX[(c & 0xF000) >> 12]);211buf.append(HEX[(c & 0x0F00) >> 8]);212buf.append(HEX[(c & 0x00F0) >> 4]);213buf.append(HEX[c & 0x000F]);214}215}216return buf.toString();217}218219// Test simple currency format220// Bug 4024941; this code used to throw a NumberFormat exception221public void TestCurrency() {222NumberFormat currencyFmt =223NumberFormat.getCurrencyInstance(Locale.CANADA_FRENCH);224String s = currencyFmt.format(1.50);225logln("Un pauvre ici a..........." + s);226if (!s.equals("1,50 $")) {227errln("FAIL: Expected 1,50 $; got " + s + "; "+ dumpFmt(currencyFmt));228}229currencyFmt = NumberFormat.getCurrencyInstance(Locale.GERMANY);230s = currencyFmt.format(1.50);231logln("Un pauvre en Allemagne a.." + s);232if (!s.equals("1,50 \u20AC")) {233errln("FAIL: Expected 1,50 \u20AC; got " + s + "; " + dumpFmt(currencyFmt));234}235currencyFmt = NumberFormat.getCurrencyInstance(Locale.FRANCE);236s = currencyFmt.format(1.50);237logln("Un pauvre en France a....." + s);238if (!s.equals("1,50 \u20AC")) {239errln("FAIL: Expected 1,50 \u20AC; got " + s + "; " + dumpFmt(currencyFmt));240}241}242243String dumpFmt(NumberFormat numfmt) {244DecimalFormat fmt = (DecimalFormat)numfmt;245StringBuffer buf = new StringBuffer();246buf.append("pattern \"");247buf.append(fmt.toPattern());248buf.append("\", currency \"");249buf.append(fmt.getDecimalFormatSymbols().getCurrencySymbol());250buf.append("\"");251return buf.toString();252}253254// Test numeric parsing255// Bug 4059870256public void TestParse()257{258String arg = "0";259java.text.DecimalFormat format = new java.text.DecimalFormat("00");260try {261Number n = format.parse(arg);262logln("parse(" + arg + ") = " + n);263if (n.doubleValue() != 0.0) errln("FAIL: Expected 0");264} catch (Exception e) { errln("Exception caught: " + e); }265}266267// Test rounding268public void TestRounding487() {269NumberFormat nf = NumberFormat.getInstance(Locale.US);270roundingTest(nf, 0.00159999, 4, "0.0016");271roundingTest(nf, 0.00995, 4, "0.01");272roundingTest(nf, 12.7995, 3, "12.8");273roundingTest(nf, 12.4999, 0, "12");274roundingTest(nf, -19.5, 0, "-20");275}276277void roundingTest(NumberFormat nf, double x, int maxFractionDigits, String expected) {278nf.setMaximumFractionDigits(maxFractionDigits);279String out = nf.format(x);280logln("" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);281if (!out.equals(expected)) {282errln("FAIL: Expected " + expected + ", got " + out);283}284}285286/**287* Bug 4135202288* DecimalFormat should recognize not only Latin digits 0-9 (\u0030-\u0039)289* but also various other ranges of Unicode digits, such as Arabic290* digits \u0660-\u0669 and Devanagari digits \u0966-\u096F, to name291* a couple.292* @see java.lang.Character#isDigit(char)293*/294public void TestUnicodeDigits() {295char[] zeros = {2960x0030, // ISO-LATIN-1 digits ('0' through '9')2970x0660, // Arabic-Indic digits2980x06F0, // Extended Arabic-Indic digits2990x0966, // Devanagari digits3000x09E6, // Bengali digits3010x0A66, // Gurmukhi digits3020x0AE6, // Gujarati digits3030x0B66, // Oriya digits3040x0BE6, // Tamil digits3050x0C66, // Telugu digits3060x0CE6, // Kannada digits3070x0D66, // Malayalam digits3080x0E50, // Thai digits3090x0ED0, // Lao digits3100x0F20, // Tibetan digits3110xFF10, // Fullwidth digits312};313NumberFormat format = NumberFormat.getInstance();314for (int i=0; i<zeros.length; ++i) {315char zero = zeros[i];316StringBuffer buf = new StringBuffer();317buf.append((char)(zero+3));318buf.append((char)(zero+1));319buf.append((char)(zero+4));320int n = -1;321try {322n = format.parse(buf.toString()).intValue();323}324catch (ParseException e) { n = -2; }325if (n != 314)326errln("Can't parse Unicode " + Integer.toHexString(zero) + " as digit (" + n + ")");327else328logln("Parse digit " + Integer.toHexString(zero) + " ok");329}330}331332/**333* Bug 4122840334* Make sure that the currency symbol is not hard-coded in any locale.335*/336public void TestCurrencySubstitution() {337final String SYM = "<currency>";338final String INTL_SYM = "<intl.currency>";339Locale[] locales = NumberFormat.getAvailableLocales();340for (int i=0; i<locales.length; ++i) {341NumberFormat nf = NumberFormat.getCurrencyInstance(locales[i]);342if (nf instanceof DecimalFormat) {343DecimalFormat df = (DecimalFormat)nf;344String genericPos = df.format(1234.5678);345String genericNeg = df.format(-1234.5678);346DecimalFormatSymbols sym = df.getDecimalFormatSymbols();347sym.setCurrencySymbol(SYM);348sym.setInternationalCurrencySymbol(INTL_SYM);349// We have to make a new DecimalFormat from scratch in order350// to make the new symbols 'take'. This may be a bug or351// design flaw in DecimalFormat.352String[] patterns = LocaleData.getBundle("sun.text.resources.FormatData", locales[i])353.getStringArray("NumberPatterns");354df = new DecimalFormat(patterns[1 /*CURRENCYSTYLE*/], sym);355String customPos = df.format(1234.5678);356String customNeg = df.format(-1234.5678);357if (genericPos.equals(customPos) || genericNeg.equals(customNeg)) {358errln("FAIL: " + locales[i] +359" not using currency symbol substitution: " + genericPos);360}361else {362if (customPos.indexOf(SYM) >= 0) {363if (customNeg.indexOf(INTL_SYM) >= 0)364errln("Fail: Positive and negative patterns use different symbols");365else366logln("Ok: " + locales[i] +367" uses currency symbol: " + genericPos +368", " + customPos);369}370else if (customPos.indexOf(INTL_SYM) >= 0) {371if (customNeg.indexOf(SYM) >= 0)372errln("Fail: Positive and negative patterns use different symbols");373else374logln("Ok: " + locales[i] +375" uses intl. currency symbol: " + genericPos +376", " + customPos);377}378else {379errln("FAIL: " + locales[i] +380" contains no currency symbol (impossible!)");381}382}383}384else logln("Skipping " + locales[i] + "; not a DecimalFormat");385}386}387388public void TestIntegerFormat() throws ParseException {389NumberFormat format = NumberFormat.getIntegerInstance(Locale.GERMANY);390391float[] formatInput = { 12345.67f, -12345.67f, -0, 0 };392String[] formatExpected = { "12.346", "-12.346", "0", "0" };393394for (int i = 0; i < formatInput.length; i++) {395String result = format.format(formatInput[i]);396if (!result.equals(formatExpected[i])) {397errln("FAIL: Expected " + formatExpected[i] + ", got " + result);398}399}400401String[] parseInput = { "0", "-0", "12.345,67", "-12.345,67" };402float[] parseExpected = { 0, 0, 12345, -12345 };403404for (int i = 0; i < parseInput.length; i++) {405float result = format.parse(parseInput[i]).floatValue();406if (result != parseExpected[i]) {407errln("FAIL: Expected " + parseExpected[i] + ", got " + result);408}409}410}411}412413414