//##header /***************************************************************************************** * * Copyright (C) 1996-2009, International Business Machines * Corporation and others. All Rights Reserved. **/ /** * Port From: JDK 1.4b1 : java.text.Format.NumberRegression * Source File: java/text/format/NumberRegression.java **/ /** * @test 1.49 01/05/21 * @bug 4052223 4059870 4061302 4062486 4066646 4068693 4070798 4071005 4071014 * 4071492 4071859 4074454 4074620 4075713 4083018 4086575 4087244 4087245 * 4087251 4087535 4088161 4088503 4090489 4090504 4092480 4092561 4095713 * 4098741 4099404 4101481 4106658 4106662 4106664 4108738 4110936 4122840 * 4125885 4134034 4134300 4140009 4141750 4145457 4147295 4147706 4162198 * 4162852 4167494 4170798 4176114 4179818 4185761 4212072 4212073 4216742 * 4217661 4243011 4243108 4330377 4233840 * @summary Regression tests for NumberFormat and associated classes */ package com.ibm.icu.dev.test.format; //import com.ibm.icu.impl.ICULocaleData; import com.ibm.icu.impl.ICUResourceBundle; import com.ibm.icu.text.*; import com.ibm.icu.util.*; import java.io.*; import java.math.BigInteger; import java.text.FieldPosition; import java.text.ParseException; import java.text.ParsePosition; import java.util.Date; import java.util.Locale; public class NumberRegression extends com.ibm.icu.dev.test.TestFmwk { public static void main(String[] args) throws Exception { new NumberRegression().run(args); } private static final char EURO = '\u20ac'; /** * NumberFormat.equals comparing with null should always return false. */ public void Test4075713(){ try { MyNumberFormatTest tmp = new MyNumberFormatTest(); if (!tmp.equals(null)) logln("NumberFormat.equals passed"); } catch (NullPointerException e) { errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception"); } } /** * NumberFormat.equals comparing two obj equal even the setGroupingUsed * flag is different. */ public void Test4074620() { MyNumberFormatTest nf1 = new MyNumberFormatTest(); MyNumberFormatTest nf2 = new MyNumberFormatTest(); nf1.setGroupingUsed(false); nf2.setGroupingUsed(true); if (nf1.equals(nf2)) errln("Test for bug 4074620 failed"); else logln("Test for bug 4074620 passed."); return; } /** * DecimalFormat.format() incorrectly uses maxFractionDigits setting. */ public void Test4088161 (){ DecimalFormat df = new DecimalFormat(); double d = 100; df.setMinimumFractionDigits(0); df.setMaximumFractionDigits(16); StringBuffer sBuf1 = new StringBuffer(""); FieldPosition fp1 = new FieldPosition(0); logln("d = " + d); logln("maxFractionDigits = " + df.getMaximumFractionDigits()); logln(" format(d) = '" + df.format(d, sBuf1, fp1) + "'"); df.setMaximumFractionDigits(17); StringBuffer sBuf2 = new StringBuffer(""); FieldPosition fp2 = new FieldPosition(0); logln("maxFractionDigits = " + df.getMaximumFractionDigits()); df.format(d, sBuf2, fp2); if (!sBuf2.toString().equals("100")) errln(" format(d) = '" + sBuf2 + "'"); } /** * DecimalFormatSymbols should be cloned in the ctor DecimalFormat. * DecimalFormat(String, DecimalFormatSymbols). */ public void Test4087245 (){ DecimalFormatSymbols symbols = new DecimalFormatSymbols(); DecimalFormat df = new DecimalFormat("#,##0.0", symbols); long n = 123; StringBuffer buf1 = new StringBuffer(); StringBuffer buf2 = new StringBuffer(); logln("format(" + n + ") = " + df.format(n, buf1, new FieldPosition(0))); symbols.setDecimalSeparator('p'); // change value of field logln("format(" + n + ") = " + df.format(n, buf2, new FieldPosition(0))); if (!buf1.toString().equals(buf2.toString())) errln("Test for bug 4087245 failed"); } /** * DecimalFormat.format() incorrectly formats 0.0 */ public void Test4087535 () { DecimalFormat df = new DecimalFormat(); df.setMinimumIntegerDigits(0); double n = 0; String buffer = new String(); buffer = df.format(n); if (buffer.length() == 0) errln(n + ": '" + buffer + "'"); n = 0.1; buffer = df.format(n); if (buffer.length() == 0) errln(n + ": '" + buffer + "'"); } /** * DecimalFormat.format fails when groupingSize is set to 0. */ public void Test4088503 (){ DecimalFormat df = new DecimalFormat(); df.setGroupingSize(0); StringBuffer sBuf = new StringBuffer(""); FieldPosition fp = new FieldPosition(0); try { logln(df.format(123, sBuf, fp).toString()); } catch (Exception foo) { errln("Test for bug 4088503 failed."); } } /** * NumberFormat.getCurrencyInstance is wrong. */ public void Test4066646 () { //float returnfloat = 0.0f; //The variable is never used assignFloatValue(2.04f); assignFloatValue(2.03f); assignFloatValue(2.02f); assignFloatValue(0.0f); } public float assignFloatValue(float returnfloat) { logln(" VALUE " + returnfloat); NumberFormat nfcommon = NumberFormat.getCurrencyInstance(Locale.US); nfcommon.setGroupingUsed(false); String stringValue = nfcommon.format(returnfloat).substring(1); if (Float.valueOf(stringValue).floatValue() != returnfloat) errln(" DISPLAYVALUE " + stringValue); return returnfloat; } // End Of assignFloatValue() /** * DecimalFormat throws exception when parsing "0" */ public void Test4059870() { DecimalFormat format = new DecimalFormat("00"); try { logln(format.parse("0").toString()); } catch (Exception e) { errln("Test for bug 4059870 failed : " + e); } } /** * DecimalFormatSymbol.equals should always return false when * comparing with null. */ public void Test4083018 (){ DecimalFormatSymbols dfs = new DecimalFormatSymbols(); try { if (!dfs.equals(null)) logln("Test Passed!"); } catch (Exception foo) { errln("Test for bug 4083018 failed => Message : " + foo.getMessage()); } } /** * DecimalFormat does not round up correctly. */ public void Test4071492 (){ double x = 0.00159999; NumberFormat nf = NumberFormat.getInstance(); nf.setMaximumFractionDigits(4); String out = nf.format(x); logln("0.00159999 formats with 4 fractional digits to " + out); String expected = "0.0016"; if (!out.equals(expected)) errln("FAIL: Expected " + expected); } /** * A space as a group separator for localized pattern causes * wrong format. WorkAround : use non-breaking space. */ public void Test4086575() { NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE); logln("nf toPattern1: " + ((DecimalFormat)nf).toPattern()); logln("nf toLocPattern1: " + ((DecimalFormat)nf).toLocalizedPattern()); // No group separator logln("...applyLocalizedPattern ###,00;(###,00) "); ((DecimalFormat)nf).applyLocalizedPattern("###,00;(###,00)"); logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern()); logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern()); logln("nf: " + nf.format(1234)); // 1234,00 logln("nf: " + nf.format(-1234)); // (1234,00) // Space as group separator logln("...applyLocalizedPattern # ###,00;(# ###,00) "); ((DecimalFormat)nf).applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)"); logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern()); logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern()); String buffer = nf.format(1234); if (!buffer.equals("1\u00a0234,00")) errln("nf : " + buffer); // Expect 1 234,00 buffer = nf.format(-1234); if (!buffer.equals("(1\u00a0234,00)")) errln("nf : " + buffer); // Expect (1 234,00) // Erroneously prints: // 1234,00 , // (1234,00 ,) } /** * DecimalFormat.parse returns wrong value */ public void Test4068693() { logln("----- Test Application -----"); //ParsePosition pos; DecimalFormat df = new DecimalFormat(); Number d = df.parse("123.55456", new ParsePosition(0)); if (!d.toString().equals("123.55456")) { errln("Result -> " + d.doubleValue()); } } /* bugs 4069754, 4067878 * null pointer thrown when accessing a deserialized DecimalFormat * object. */ public void Test4069754() throws Exception { //try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); myformat it = new myformat(); logln(it.Now()); oos.writeObject(it); oos.flush(); baos.close(); logln("Save OK!"); byte [] bytes = baos.toByteArray(); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); myformat o = (myformat)ois.readObject(); ois.close(); it.Now(); logln("Load OK!"); if (!o._dateFormat.equals(it._dateFormat)) { throw new Exception("The saved and loaded object are not equals!"); } logln("Compare OK!"); //} catch (Exception foo) { //errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage()); //} } /** * DecimalFormat.applyPattern(String) allows illegal patterns */ public void Test4087251 (){ DecimalFormat df = new DecimalFormat(); try { df.applyPattern("#.#.#"); logln("toPattern() returns \"" + df.toPattern() + "\""); errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException"); } catch (IllegalArgumentException e) { logln("Caught Illegal Argument Error !"); } // Second test; added 5/11/98 when reported to fail on 1.2b3 try { df.applyPattern("#0.0#0#0"); logln("toPattern() returns \"" + df.toPattern() + "\""); errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException"); } catch (IllegalArgumentException e) { logln("Ok - IllegalArgumentException for #0.0#0#0"); } } /** * DecimalFormat.format() loses precision */ public void Test4090489 (){ DecimalFormat df = new DecimalFormat(); df.setMinimumFractionDigits(10); df.setGroupingUsed(false); double d = 1.000000000000001E7; java.math.BigDecimal bd = new java.math.BigDecimal(d); StringBuffer sb = new StringBuffer(""); FieldPosition fp = new FieldPosition(0); logln("d = " + d); logln("BigDecimal.toString(): " + bd.toString()); df.format(d, sb, fp); if (!sb.toString().equals("10000000.0000000100")) { errln("DecimalFormat.format(): " + sb.toString()); } } /** * DecimalFormat.format() loses precision */ public void Test4090504 () { double d = 1; logln("d = " + d); DecimalFormat df = new DecimalFormat(); StringBuffer sb; FieldPosition fp; try { for (int i = 17; i <= 20; i++) { df.setMaximumFractionDigits(i); sb = new StringBuffer(""); fp = new FieldPosition(0); logln(" getMaximumFractionDigits() = " + i); logln(" formated: " + df.format(d, sb, fp)); } } catch (Exception foo) { errln("Bug 4090504 regression test failed. Message : " + foo.getMessage()); } } /** * DecimalFormat.parse(String str, ParsePosition pp) loses precision */ public void Test4095713 () { DecimalFormat df = new DecimalFormat(); String str = "0.1234"; Double d1 = new Double(str); Number d2 = df.parse(str, new ParsePosition(0)); logln(d1.toString()); if (d2.doubleValue() != d1.doubleValue()) errln("Bug 4095713 test failed, new double value : " + d2.doubleValue()); } /** * DecimalFormat.parse() fails when multiplier is not set to 1 */ public void Test4092561 () { Locale savedLocale = Locale.getDefault(); Locale.setDefault(Locale.US); DecimalFormat df = new DecimalFormat(); String str = Long.toString(Long.MIN_VALUE); logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString()); df.setMultiplier(100); Number num = df.parse(str, new ParsePosition(0)); if (num.doubleValue() != -9.223372036854776E16) { errln("Bug 4092561 test failed when multiplier is set to not 1."); } Locale.setDefault(savedLocale); } /** * DecimalFormat: Negative format ignored. */ public void Test4092480 () { DecimalFormat dfFoo = new DecimalFormat("000"); try { dfFoo.applyPattern("0000;-000"); if (!dfFoo.toPattern().equals("#0000")) errln("dfFoo.toPattern : " + dfFoo.toPattern()); logln(dfFoo.format(42)); logln(dfFoo.format(-42)); dfFoo.applyPattern("000;-000"); if (!dfFoo.toPattern().equals("#000")) errln("dfFoo.toPattern : " + dfFoo.toPattern()); logln(dfFoo.format(42)); logln(dfFoo.format(-42)); dfFoo.applyPattern("000;-0000"); if (!dfFoo.toPattern().equals("#000")) errln("dfFoo.toPattern : " + dfFoo.toPattern()); logln(dfFoo.format(42)); logln(dfFoo.format(-42)); dfFoo.applyPattern("0000;-000"); if (!dfFoo.toPattern().equals("#0000")) errln("dfFoo.toPattern : " + dfFoo.toPattern()); logln(dfFoo.format(42)); logln(dfFoo.format(-42)); } catch (Exception foo) { errln("Message " + foo.getMessage()); } } /** * NumberFormat.getCurrencyInstance() produces format that uses * decimal separator instead of monetary decimal separator. * * Rewrote this test not to depend on the actual pattern. Pattern should * never contain the monetary separator! Decimal separator in pattern is * interpreted as monetary separator if currency symbol is seen! */ public void Test4087244 () { Locale de = new Locale("pt", "PT"); DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(de); DecimalFormatSymbols sym = df.getDecimalFormatSymbols(); sym.setMonetaryDecimalSeparator('$'); df.setDecimalFormatSymbols(sym); char decSep = sym.getDecimalSeparator(); char monSep = sym.getMonetaryDecimalSeparator(); //char zero = sym.getZeroDigit(); //The variable is never used if (decSep == monSep) { errln("ERROR in test: want decimal sep != monetary sep"); } else { df.setMinimumIntegerDigits(1); df.setMinimumFractionDigits(2); String str = df.format(1.23); String monStr = "1" + monSep + "23"; String decStr = "1" + decSep + "23"; if (str.indexOf(monStr) >= 0 && str.indexOf(decStr) < 0) { logln("OK: 1.23 -> \"" + str + "\" contains \"" + monStr + "\" and not \"" + decStr + '"'); } else { errln("FAIL: 1.23 -> \"" + str + "\", should contain \"" + monStr + "\" and not \"" + decStr + '"'); } } } /** * Number format data rounding errors for locale FR */ public void Test4070798 () { NumberFormat formatter; String tempString; /* User error : String expectedDefault = "-5\u00a0789,987"; String expectedCurrency = "5\u00a0789,98\u00a0F"; String expectedPercent = "-578\u00a0998%"; */ String expectedDefault = "-5\u00a0789,988"; String expectedCurrency = "5\u00a0789,99\u00a0" + EURO; // euro String expectedPercent = "-578\u00a0999\u00a0%"; formatter = NumberFormat.getNumberInstance(Locale.FRANCE); tempString = formatter.format (-5789.9876); if (tempString.equals(expectedDefault)) { logln ("Bug 4070798 default test passed."); } else { errln("Failed:" + " Expected " + expectedDefault + " Received " + tempString ); } formatter = NumberFormat.getCurrencyInstance(Locale.FRANCE); tempString = formatter.format( 5789.9876 ); if (tempString.equals(expectedCurrency) ) { logln ("Bug 4070798 currency test assed."); } else { errln("Failed:" + " Expected " + expectedCurrency + " Received " + tempString ); } formatter = NumberFormat.getPercentInstance(Locale.FRANCE); tempString = formatter.format (-5789.9876); if (tempString.equals(expectedPercent) ) { logln ("Bug 4070798 percentage test passed."); } else { errln("Failed:" + " Expected " + expectedPercent + " Received " + tempString ); } } /** * Data rounding errors for French (Canada) locale */ public void Test4071005 () { NumberFormat formatter; String tempString; /* user error : String expectedDefault = "-5 789,987"; String expectedCurrency = "5 789,98\u00a0$"; String expectedPercent = "-578 998%"; */ String expectedDefault = "-5\u00a0789,988"; String expectedCurrency = "5\u00a0789,99\u00a0$"; String expectedPercent = "-578\u00a0999\u00A0%"; formatter = NumberFormat.getNumberInstance(Locale.CANADA_FRENCH); tempString = formatter.format (-5789.9876); if (tempString.equals(expectedDefault)) { logln ("Bug 4071005 default test passed."); } else { errln("Failed:" + " Expected " + expectedDefault + " Received " + tempString ); } formatter = NumberFormat.getCurrencyInstance(Locale.CANADA_FRENCH); tempString = formatter.format( 5789.9876 ) ; if (tempString.equals(expectedCurrency) ) { logln ("Bug 4071005 currency test passed."); } else { errln("Failed:" + " Expected " + expectedCurrency + " Received " + tempString ); } formatter = NumberFormat.getPercentInstance(Locale.CANADA_FRENCH); tempString = formatter.format (-5789.9876); if (tempString.equals(expectedPercent) ) { logln ("Bug 4071005 percentage test passed."); } else { errln("Failed:" + " Expected " + expectedPercent + " Received " + tempString ); } } /** * Data rounding errors for German (Germany) locale */ public void Test4071014 () { NumberFormat formatter; String tempString; /* user error : String expectedDefault = "-5.789,987"; String expectedCurrency = "5.789,98\u00a0DM"; String expectedPercent = "-578.998%"; */ String expectedDefault = "-5.789,988"; String expectedCurrency = "5.789,99\u00a0" + EURO; String expectedPercent = "-578.999\u00a0%"; formatter = NumberFormat.getNumberInstance(Locale.GERMANY); tempString = formatter.format (-5789.9876); if (tempString.equals(expectedDefault)) { logln ("Bug 4071014 default test passed."); } else { errln("Failed:" + " Expected " + expectedDefault + " Received " + tempString ); } formatter = NumberFormat.getCurrencyInstance(Locale.GERMANY); tempString = formatter.format( 5789.9876 ) ; if (tempString.equals(expectedCurrency) ) { logln ("Bug 4071014 currency test passed."); } else { errln("Failed:" + " Expected " + expectedCurrency + " Received " + tempString ); } formatter = NumberFormat.getPercentInstance(Locale.GERMANY); tempString = formatter.format (-5789.9876); if (tempString.equals(expectedPercent) ) { logln ("Bug 4071014 percentage test passed."); } else { errln("Failed:" + " Expected " + expectedPercent + " Received " + tempString ); } } /** * Data rounding errors for Italian locale number formats * Note- with the Euro, there is no need for currency rounding anymore */ public void Test4071859 () { NumberFormat formatter; String tempString; /* user error : String expectedDefault = "-5.789,987"; String expectedCurrency = "-L.\u00a05.789,98"; String expectedPercent = "-578.998%"; */ String expectedDefault = "-5.789,988"; String expectedCurrency = "-" + EURO + "\u00a05.789,99"; String expectedPercent = "-578.999%"; formatter = NumberFormat.getNumberInstance(Locale.ITALY); tempString = formatter.format (-5789.9876); if (tempString.equals(expectedDefault)) { logln ("Bug 4071859 default test passed."); } else { errln("a) Failed:" + " Expected " + expectedDefault + " Received " + tempString ); } formatter = NumberFormat.getCurrencyInstance(Locale.ITALY); tempString = formatter.format( -5789.9876 ) ; if (tempString.equals(expectedCurrency) ) { logln ("Bug 4071859 currency test passed."); } else { errln("b) Failed:" + " Expected " + expectedCurrency + " Received " + tempString ); } formatter = NumberFormat.getPercentInstance(Locale.ITALY); tempString = formatter.format (-5789.9876); if (tempString.equals(expectedPercent) ) { logln ("Bug 4071859 percentage test passed."); } else { errln("c) Failed:" + " Expected " + expectedPercent + " Received " + tempString ); } } /* bug 4071859 * Test rounding for nearest even. */ public void Test4093610() { DecimalFormat df = new DecimalFormat("#0.#"); roundingTest(df, 12.35, "12.4"); roundingTest(df, 12.45, "12.4"); roundingTest(df, 12.452,"12.5"); roundingTest(df, 12.55, "12.6"); roundingTest(df, 12.65, "12.6"); roundingTest(df, 12.652,"12.7"); roundingTest(df, 12.75, "12.8"); roundingTest(df, 12.752,"12.8"); roundingTest(df, 12.85, "12.8"); roundingTest(df, 12.852,"12.9"); roundingTest(df, 12.95, "13"); roundingTest(df, 12.952,"13"); } void roundingTest(DecimalFormat df, double x, String expected) { String out = df.format(x); logln("" + x + " formats with 1 fractional digits to " + out); if (!out.equals(expected)) errln("FAIL: Expected " + expected); } /** * Tests the setMaximumFractionDigits limit. */ public void Test4098741() { try { NumberFormat fmt = NumberFormat.getPercentInstance(); fmt.setMaximumFractionDigits(20); logln(fmt.format(.001)); } catch (Exception foo) { warnln("Bug 4098471 failed with exception thrown : " + foo.getMessage()); } } /** * Tests illegal pattern exception. * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated. * Part2 has been fixed. */ public void Test4074454() { try { DecimalFormat fmt = new DecimalFormat("#,#00.00;-#.#"); logln("format 3456.78: " + fmt.format(3456.78)); //fix "The variable 'fmt' is never used" logln("Inconsistent negative pattern is fine."); DecimalFormat newFmt = new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces"); String tempString = newFmt.format(3456.78); if (!tempString.equals("3,456.78 p'ieces")) errln("Failed! 3456.78 p'ieces expected, but got : " + tempString); } catch (Exception foo) { warnln("An exception was thrown for any inconsistent negative pattern."); } } /** * Tests all different comments. * Response to some comments : * [1] DecimalFormat.parse API documentation is more than just one line. * This is not a reproducable doc error in 116 source code. * [2] See updated javadoc. * [3] Fixed. * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails, * a null object will be returned. The unchanged parse position also * reflects an error. * NumberFormat.parse(String) : If parsing fails, an ParseException * will be thrown. * See updated javadoc for more details. * [5] See updated javadoc. * [6] See updated javadoc. * [7] This is a correct behavior if the DateFormat object is linient. * Otherwise, an IllegalArgumentException will be thrown when formatting * "January 35". See GregorianCalendar class javadoc for more details. */ public void Test4099404() { try { DecimalFormat fmt = new DecimalFormat("000.0#0"); logln("format 3456.78: " + fmt.format(3456.78)); //fix "The variable 'fmt' is never used" errln("Bug 4099404 failed applying illegal pattern \"000.0#0\""); } catch (Exception foo) { logln("Bug 4099404 pattern \"000.0#0\" passed"); } try { DecimalFormat fmt = new DecimalFormat("0#0.000"); logln("format 3456.78: " + fmt.format(3456.78)); //fix "The variable 'fmt' is never used" errln("Bug 4099404 failed applying illegal pattern \"0#0.000\""); } catch (Exception foo) { logln("Bug 4099404 pattern \"0#0.000\" passed"); } } /** * DecimalFormat.applyPattern doesn't set minimum integer digits */ public void Test4101481() { DecimalFormat sdf = new DecimalFormat("#,##0"); if (sdf.getMinimumIntegerDigits() != 1) errln("Minimum integer digits : " + sdf.getMinimumIntegerDigits()); } /** * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition(). */ public void Test4052223() { try { DecimalFormat fmt = new DecimalFormat("#,#00.00"); Number num = fmt.parse("abc3"); errln("Bug 4052223 failed : can't parse string \"a\". Got " + num); } catch (ParseException foo) { logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset()); } } /** * API tests for API addition request A9. */ public void Test4061302() { DecimalFormatSymbols fmt = new DecimalFormatSymbols(); String currency = fmt.getCurrencySymbol(); String intlCurrency = fmt.getInternationalCurrencySymbol(); char monDecSeparator = fmt.getMonetaryDecimalSeparator(); if (currency.equals("") || intlCurrency.equals("") || monDecSeparator == 0) { errln("getCurrencySymbols failed, got empty string."); } logln("Before set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator); fmt.setCurrencySymbol("XYZ"); fmt.setInternationalCurrencySymbol("ABC"); fmt.setMonetaryDecimalSeparator('*'); currency = fmt.getCurrencySymbol(); intlCurrency = fmt.getInternationalCurrencySymbol(); monDecSeparator = fmt.getMonetaryDecimalSeparator(); if (!currency.equals("XYZ") || !intlCurrency.equals("ABC") || monDecSeparator != '*') { errln("setCurrencySymbols failed."); } logln("After set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator); } /** * API tests for API addition request A23. FieldPosition.getBeginIndex and * FieldPosition.getEndIndex. */ public void Test4062486() { DecimalFormat fmt = new DecimalFormat("#,##0.00"); StringBuffer formatted = new StringBuffer(); FieldPosition field = new FieldPosition(0); Double num = new Double(1234.5); fmt.format(num, formatted, field); if (field.getBeginIndex() != 0 && field.getEndIndex() != 5) errln("Format 1234.5 failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex()); field.setBeginIndex(7); field.setEndIndex(4); if (field.getBeginIndex() != 7 && field.getEndIndex() != 4) errln("Set begin/end field indexes failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex()); } /** * DecimalFormat.parse incorrectly works with a group separator. */ public void Test4108738() { DecimalFormat df = new DecimalFormat("#,##0.###", new DecimalFormatSymbols(java.util.Locale.US)); String text = "1.222,111"; Number num = df.parse(text,new ParsePosition(0)); if (!num.toString().equals("1.222")) errln("\"" + text + "\" is parsed as " + num); text = "1.222x111"; num = df.parse(text,new ParsePosition(0)); if (!num.toString().equals("1.222")) errln("\"" + text + "\" is parsed as " + num); } /** * DecimalFormat.format() incorrectly formats negative doubles. */ public void Test4106658() { Locale savedLocale = Locale.getDefault(); Locale.setDefault(Locale.US); DecimalFormat df = new DecimalFormat(); // Corrected; see 4147706 double d1 = -0.0; double d2 = -0.0001; StringBuffer buffer = new StringBuffer(); logln("pattern: \"" + df.toPattern() + "\""); df.format(d1, buffer, new FieldPosition(0)); if (!buffer.toString().equals("-0")) { // Corrected; see 4147706 errln(d1 + " is formatted as " + buffer); } buffer.setLength(0); df.format(d2, buffer, new FieldPosition(0)); if (!buffer.toString().equals("-0")) { // Corrected; see 4147706 errln(d2 + " is formatted as " + buffer); } Locale.setDefault(savedLocale); } /** * DecimalFormat.parse returns 0 if string parameter is incorrect. */ public void Test4106662() { DecimalFormat df = new DecimalFormat(); String text = "x"; ParsePosition pos1 = new ParsePosition(0), pos2 = new ParsePosition(0); logln("pattern: \"" + df.toPattern() + "\""); Number num = df.parse(text, pos1); if (num != null) { errln("Test Failed: \"" + text + "\" is parsed as " + num); } df = null; df = new DecimalFormat("$###.00"); num = df.parse("$", pos2); if (num != null){ errln("Test Failed: \"$\" is parsed as " + num); } } /** * NumberFormat.parse doesn't return null */ public void Test4114639() { NumberFormat format = NumberFormat.getInstance(); String text = "time 10:x"; ParsePosition pos = new ParsePosition(8); Number result = format.parse(text, pos); if (result != null) errln("Should return null but got : " + result); // Should be null; it isn't } /** * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG. */ public void Test4106664() { DecimalFormat df = new DecimalFormat(); long n = 1234567890123456L; int m = 12345678; BigInteger bigN = BigInteger.valueOf(n); bigN = bigN.multiply(BigInteger.valueOf(m)); df.setMultiplier(m); df.setGroupingUsed(false); logln("formated: " + df.format(n, new StringBuffer(), new FieldPosition(0))); logln("expected: " + bigN.toString()); } /** * DecimalFormat.format incorrectly formats -0.0. */ public void Test4106667() { Locale savedLocale = Locale.getDefault(); Locale.setDefault(Locale.US); DecimalFormat df = new DecimalFormat(); df.setPositivePrefix("+"); double d = -0.0; logln("pattern: \"" + df.toPattern() + "\""); StringBuffer buffer = new StringBuffer(); df.format(d, buffer, new FieldPosition(0)); if (!buffer.toString().equals("-0")) { // Corrected; see 4147706 errln(d + " is formatted as " + buffer); } Locale.setDefault(savedLocale); } /** * DecimalFormat.setMaximumIntegerDigits() works incorrectly. */ public void Test4110936() { NumberFormat nf = NumberFormat.getInstance(); nf.setMaximumIntegerDigits(128); logln("setMaximumIntegerDigits(128)"); if (nf.getMaximumIntegerDigits() != 128) errln("getMaximumIntegerDigits() returns " + nf.getMaximumIntegerDigits()); } /** * Locale data should use generic currency symbol * * 1) Make sure that all currency formats use the generic currency symbol. * 2) Make sure we get the same results using the generic symbol or a * hard-coded one. */ public void Test4122840() { Locale[] locales = NumberFormat.getAvailableLocales(); for (int i = 0; i < locales.length; i++) { UResourceBundle rb = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,locales[i]); // // Get the currency pattern for this locale. We have to fish it // out of the ResourceBundle directly, since DecimalFormat.toPattern // will return the localized symbol, not \00a4 // UResourceBundle numPatterns = rb.get("NumberPatterns"); String pattern = numPatterns.getString(1); if (pattern.indexOf('\u00A4') == -1 ) { // 'x' not "x" -- workaround bug in IBM JDK 1.4.1 errln("Currency format for " + locales[i] + " does not contain generic currency symbol:" + pattern ); } // Create a DecimalFormat using the pattern we got and format a number DecimalFormatSymbols symbols = new DecimalFormatSymbols(locales[i]); DecimalFormat fmt1 = new DecimalFormat(pattern, symbols); String result1 = fmt1.format(1.111); // // Now substitute in the locale's currency symbol and create another // pattern. Replace the decimal separator with the monetary separator. // //char decSep = symbols.getDecimalSeparator(); //The variable is never used char monSep = symbols.getMonetaryDecimalSeparator(); StringBuffer buf = new StringBuffer(pattern); for (int j = 0; j < buf.length(); j++) { if (buf.charAt(j) == '\u00a4') { String cur = "'" + symbols.getCurrencySymbol() + "'"; buf.replace(j, j+1, cur); j += cur.length() - 1; } } symbols.setDecimalSeparator(monSep); DecimalFormat fmt2 = new DecimalFormat(buf.toString(), symbols); String result2 = fmt2.format(1.111); // NOTE: en_IN is a special case (ChoiceFormat currency display name) if (!result1.equals(result2) && !locales[i].toString().equals("en_IN")) { errln("Results for " + locales[i] + " differ: " + result1 + " vs " + result2); } } } /** * DecimalFormat.format() delivers wrong string. */ public void Test4125885() { double rate = 12.34; DecimalFormat formatDec = new DecimalFormat ("000.00"); logln("toPattern: " + formatDec.toPattern()); String rateString= formatDec.format(rate); if (!rateString.equals("012.34")) errln("result : " + rateString + " expected : 012.34"); rate = 0.1234; formatDec = null; formatDec = new DecimalFormat ("+000.00%;-000.00%"); logln("toPattern: " + formatDec.toPattern()); rateString= formatDec.format(rate); if (!rateString.equals("+012.34%")) errln("result : " + rateString + " expected : +012.34%"); } /** ** * DecimalFormat produces extra zeros when formatting numbers. */ public void Test4134034() { DecimalFormat nf = new DecimalFormat("##,###,###.00"); String f = nf.format(9.02); if (f.equals("9.02")) logln(f + " ok"); else errln("9.02 -> " + f + "; want 9.02"); f = nf.format(0); if (f.equals(".00")) logln(f + " ok"); else errln("0 -> " + f + "; want .00"); } /** * CANNOT REPRODUCE - This bug could not be reproduced. It may be * a duplicate of 4134034. * * JDK 1.1.6 Bug, did NOT occur in 1.1.5 * Possibly related to bug 4125885. * * This class demonstrates a regression in version 1.1.6 * of DecimalFormat class. * * 1.1.6 Results * Value 1.2 Format #.00 Result '01.20' !!!wrong * Value 1.2 Format 0.00 Result '001.20' !!!wrong * Value 1.2 Format 00.00 Result '0001.20' !!!wrong * Value 1.2 Format #0.0# Result '1.2' * Value 1.2 Format #0.00 Result '001.20' !!!wrong * * 1.1.5 Results * Value 1.2 Format #.00 Result '1.20' * Value 1.2 Format 0.00 Result '1.20' * Value 1.2 Format 00.00 Result '01.20' * Value 1.2 Format #0.0# Result '1.2' * Value 1.2 Format #0.00 Result '1.20' */ public void Test4134300() { String[] DATA = { // Pattern Expected string "#.00", "1.20", "0.00", "1.20", "00.00", "01.20", "#0.0#", "1.2", "#0.00", "1.20", }; for (int i=0; i.format(" + IN[j] + ")", OUT[j], f.format(IN[j])); } } } //#if defined(FOUNDATION10) //#else /** * BigDecimal numbers get their fractions truncated by NumberFormat. */ public void Test4141750() { try { String str = "12345.67"; java.math.BigDecimal bd = new java.math.BigDecimal(str); String sd = NumberFormat.getInstance(Locale.US).format(bd); if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd); } catch (Exception e) { warnln(e.toString()); //e.printStackTrace(); } } //#endif /** * DecimalFormat toPattern() doesn't quote special characters or handle * single quotes. */ public void Test4145457() { try { DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance(); DecimalFormatSymbols sym = nf.getDecimalFormatSymbols(); sym.setDecimalSeparator('\''); nf.setDecimalFormatSymbols(sym); double pi = 3.14159; String[] PATS = { "#.00 'num''ber'", "''#.00''" }; for (int i=0; i \"" + pat + '"'); if (val == val2 && out.equals(out2)) { logln("Ok " + pi + " x \"" + PATS[i] + "\" -> \"" + out + "\" -> " + val + " -> \"" + out2 + "\" -> " + val2); } else { errln("Fail " + pi + " x \"" + PATS[i] + "\" -> \"" + out + "\" -> " + val + " -> \"" + out2 + "\" -> " + val2); } } } catch (ParseException e) { errln("Fail: " + e); e.printStackTrace(); } } /** * DecimalFormat.applyPattern() sets minimum integer digits incorrectly. * CANNOT REPRODUCE * This bug is a duplicate of 4139344, which is a duplicate of 4134300 */ public void Test4147295() { DecimalFormat sdf = new DecimalFormat(); String pattern = "#,###"; logln("Applying pattern \"" + pattern + "\""); sdf.applyPattern(pattern); int minIntDig = sdf.getMinimumIntegerDigits(); if (minIntDig != 0) { errln("Test failed"); errln(" Minimum integer digits : " + minIntDig); errln(" new pattern: " + sdf.toPattern()); } else { logln("Test passed"); logln(" Minimum integer digits : " + minIntDig); } } /** * DecimalFormat formats -0.0 as +0.0 * See also older related bug 4106658, 4106667 */ public void Test4147706() { DecimalFormat df = new DecimalFormat("#,##0.0##"); df.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.ENGLISH)); double d1 = -0.0; double d2 = -0.0001; StringBuffer f1 = df.format(d1, new StringBuffer(), new FieldPosition(0)); StringBuffer f2 = df.format(d2, new StringBuffer(), new FieldPosition(0)); if (!f1.toString().equals("-0.0")) { errln(d1 + " x \"" + df.toPattern() + "\" is formatted as \"" + f1 + '"'); } if (!f2.toString().equals("-0.0")) { errln(d2 + " x \"" + df.toPattern() + "\" is formatted as \"" + f2 + '"'); } } /** * NumberFormat cannot format Double.MAX_VALUE */ public void Test4162198() { double dbl = Double.MAX_VALUE; NumberFormat f = NumberFormat.getInstance(); f.setMaximumFractionDigits(Integer.MAX_VALUE); f.setMaximumIntegerDigits(Integer.MAX_VALUE); String s = f.format(dbl); logln("The number " + dbl + " formatted to " + s); Number n = null; try { n = f.parse(s); } catch (java.text.ParseException e) { errln("Caught a ParseException:"); e.printStackTrace(); } logln("The string " + s + " parsed as " + n); if (n.doubleValue() != dbl) { errln("Round trip failure"); } } /** * NumberFormat does not parse negative zero. */ public void Test4162852() throws ParseException { for (int i=0; i<2; ++i) { NumberFormat f = (i == 0) ? NumberFormat.getInstance() : NumberFormat.getPercentInstance(); double d = -0.0; String s = f.format(d); double e = f.parse(s).doubleValue(); logln("" + d + " -> " + '"' + s + '"' + " -> " + e); if (e != 0.0 || 1.0/e > 0.0) { logln("Failed to parse negative zero"); } } } /** * NumberFormat truncates data */ public void Test4167494() throws Exception { NumberFormat fmt = NumberFormat.getInstance(Locale.US); double a = Double.MAX_VALUE; String s = fmt.format(a); double b = fmt.parse(s).doubleValue(); boolean match = a == b; if (match) { logln("" + a + " -> \"" + s + "\" -> " + b + " ok"); } else { errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL"); } // We don't test Double.MIN_VALUE because the locale data for the US // currently doesn't specify enough digits to display Double.MIN_VALUE. // This is correct for now; however, we leave this here as a reminder // in case we want to address this later. if (false) { a = Double.MIN_VALUE; s = fmt.format(a); b = fmt.parse(s).doubleValue(); match = a == b; if (match) { logln("" + a + " -> \"" + s + "\" -> " + b + " ok"); } else { errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL"); } } } /** * DecimalFormat.parse() fails when ParseIntegerOnly set to true */ public void Test4170798() { Locale savedLocale = Locale.getDefault(); Locale.setDefault(Locale.US); DecimalFormat df = new DecimalFormat(); df.setParseIntegerOnly(true); Number n = df.parse("-0.0", new ParsePosition(0)); if (!(n instanceof Double) || n.intValue() != 0) { errln("FAIL: parse(\"-0.0\") returns " + n + " (" + n.getClass().getName() + ')'); } Locale.setDefault(savedLocale); } /** * toPattern only puts the first grouping separator in. */ public void Test4176114() { String[] DATA = { "00", "#00", "000", "#000", // No grouping "#000", "#000", // No grouping "#,##0", "#,##0", "#,000", "#,000", "0,000", "#0,000", "00,000", "#00,000", "000,000", "#,000,000", "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported }; for (int i=0; i " + s + ", want " + DATA[i+1]); } } } /** * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2 */ public void Test4179818() { String DATA[] = { // Input Pattern Expected output "1.2511", "#.#", "1.3", "1.2501", "#.#", "1.3", "0.9999", "#", "1", }; DecimalFormat fmt = new DecimalFormat("#", new DecimalFormatSymbols(Locale.US)); for (int i=0; i max. // Numberformat should catch this and throw an exception. for (int i = 0; i < offsets.length; ++i) { bytes[offsets[i]] = (byte)(4 - i); } { ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); try { NumberFormat format = (NumberFormat) ois.readObject(); logln("format: " + format.format(1234.56)); //fix "The variable is never used" errln("FAIL: Deserialized bogus NumberFormat with minXDigits > maxXDigits"); } catch (InvalidObjectException e) { logln("Ok: " + e.getMessage()); } } // Set values so they are too high, but min <= max // Format should pass the min <= max test, and DecimalFormat should reset to current maximum // (for compatibility with versions streamed out before the maximums were imposed). for (int i = 0; i < offsets.length; ++i) { bytes[offsets[i]] = 4; } { ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); NumberFormat format = (NumberFormat) ois.readObject(); //For compatibility with previous version if ((format.getMaximumIntegerDigits() != 309) || format.getMaximumFractionDigits() != 340) { errln("FAIL: Deserialized bogus NumberFormat with values out of range," + " intMin: " + format.getMinimumIntegerDigits() + " intMax: " + format.getMaximumIntegerDigits() + " fracMin: " + format.getMinimumFractionDigits() + " fracMax: " + format.getMaximumFractionDigits()); } else { logln("Ok: Digit count out of range"); } } } /** * Some DecimalFormatSymbols changes are not picked up by DecimalFormat. * This includes the minus sign, currency symbol, international currency * symbol, percent, and permille. This is filed as bugs 4212072 and * 4212073. */ public void Test4212072() throws IOException, ClassNotFoundException { DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US); DecimalFormat fmt = new DecimalFormat("#", sym); sym.setMinusSign('^'); fmt.setDecimalFormatSymbols(sym); if (!fmt.format(-1).equals("^1")) { errln("FAIL: -1 x (minus=^) -> " + fmt.format(-1) + ", exp ^1"); } if (!fmt.getNegativePrefix().equals("^")) { errln("FAIL: (minus=^).getNegativePrefix -> " + fmt.getNegativePrefix() + ", exp ^"); } sym.setMinusSign('-'); fmt.applyPattern("#%"); sym.setPercent('^'); fmt.setDecimalFormatSymbols(sym); if (!fmt.format(0.25).equals("25^")) { errln("FAIL: 0.25 x (percent=^) -> " + fmt.format(0.25) + ", exp 25^"); } if (!fmt.getPositiveSuffix().equals("^")) { errln("FAIL: (percent=^).getPositiveSuffix -> " + fmt.getPositiveSuffix() + ", exp ^"); } sym.setPercent('%'); fmt.applyPattern("#\u2030"); sym.setPerMill('^'); fmt.setDecimalFormatSymbols(sym); if (!fmt.format(0.25).equals("250^")) { errln("FAIL: 0.25 x (permill=^) -> " + fmt.format(0.25) + ", exp 250^"); } if (!fmt.getPositiveSuffix().equals("^")) { errln("FAIL: (permill=^).getPositiveSuffix -> " + fmt.getPositiveSuffix() + ", exp ^"); } sym.setPerMill('\u2030'); fmt.applyPattern("\u00A4#.00"); sym.setCurrencySymbol("usd"); fmt.setDecimalFormatSymbols(sym); if (!fmt.format(12.5).equals("usd12.50")) { errln("FAIL: 12.5 x (currency=usd) -> " + fmt.format(12.5) + ", exp usd12.50"); } if (!fmt.getPositivePrefix().equals("usd")) { errln("FAIL: (currency=usd).getPositivePrefix -> " + fmt.getPositivePrefix() + ", exp usd"); } sym.setCurrencySymbol("$"); fmt.applyPattern("\u00A4\u00A4#.00"); sym.setInternationalCurrencySymbol("DOL"); fmt.setDecimalFormatSymbols(sym); if (!fmt.format(12.5).equals("DOL12.50")) { errln("FAIL: 12.5 x (intlcurrency=DOL) -> " + fmt.format(12.5) + ", exp DOL12.50"); } if (!fmt.getPositivePrefix().equals("DOL")) { errln("FAIL: (intlcurrency=DOL).getPositivePrefix -> " + fmt.getPositivePrefix() + ", exp DOL"); } sym.setInternationalCurrencySymbol("USD"); if (VersionInfo.ICU_VERSION == VersionInfo.getInstance(2,2)) { // bug in 2.2 that fails this test // to be fixed in the later versions System.out.println("\n Test skipped for release 2.2"); return; } // Since the pattern logic has changed, make sure that patterns round // trip properly. Test stream in/out integrity too. Locale[] avail = NumberFormat.getAvailableLocales(); for (int i=0; i \"" + pat + "\" -> \"" + f2.toPattern() + '"'); } // Test toLocalizedPattern/applyLocalizedPattern round trip pat = df.toLocalizedPattern(); try{ f2.applyLocalizedPattern(pat); String s1 = f2.format(123456); String s2 = df.format(123456); if(!s1.equals(s2)){ errln("FAIL: " + avail[i] + " #" + j + " -> localized \"" + s2 + "\" -> \"" + s2 + '"'+ " in locale "+df.getLocale(ULocale.ACTUAL_LOCALE)); } if (!df.equals(f2)) { errln("FAIL: " + avail[i] + " #" + j + " -> localized \"" + pat + "\" -> \"" + f2.toLocalizedPattern() + '"'+ " in locale "+df.getLocale(ULocale.ACTUAL_LOCALE)); errln("s1: "+s1+" s2: "+s2); } }catch(IllegalArgumentException ex){ errln(ex.getMessage()+" for locale "+ df.getLocale(ULocale.ACTUAL_LOCALE)); } // Test writeObject/readObject round trip ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(df); oos.flush(); baos.close(); byte[] bytes = baos.toByteArray(); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); f2 = (DecimalFormat) ois.readObject(); if (!df.equals(f2)) { errln("FAIL: Stream in/out " + avail[i] + " -> \"" + pat + "\" -> " + (f2 != null ? ("\""+f2.toPattern()+'"') : "null")); } } } // @since ICU 2.4 // Make sure that all special characters, when quoted in a suffix or // prefix, lose their special meaning. char[] SPECIALS = { '0', ',', '.', '\u2030', '%', '#', ';', 'E', '*', '+', '-' }; sym = new DecimalFormatSymbols(Locale.US); for (int j=0; j toPattern() => \"" + pat2 + "\""); } String s = fmt.format(123); String exp = "" + special + "123" + special; if (!s.equals(exp)) { errln("FAIL: 123 x \"" + pat + "\" => \"" + s + "\", exp \"" + exp + "\""); } } catch (IllegalArgumentException e) { errln("FAIL: Pattern \"" + pat + "\" => " + e.getMessage()); } } } /** * DecimalFormat.parse() fails for mulipliers 2^n. */ public void Test4216742() throws ParseException { DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance(Locale.US); long[] DATA = { Long.MIN_VALUE, Long.MAX_VALUE, -100000000L, 100000000L}; for (int i=0; i 0 != DATA[i] > 0) { errln("\"" + str + "\" parse(x " + fmt.getMultiplier() + ") => " + n); } } } } /** * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction * digits. */ public void Test4217661() { Object[] DATA = { new Double(0.001), "0", new Double(1.001), "1", new Double(0.006), "0.01", new Double(1.006), "1.01", }; NumberFormat fmt = NumberFormat.getInstance(Locale.US); fmt.setMaximumFractionDigits(2); for (int i=0; i