1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package libcore.java.text; 18 19import java.math.BigDecimal; 20import java.math.BigInteger; 21import java.math.RoundingMode; 22import java.text.DecimalFormat; 23import java.text.DecimalFormatSymbols; 24import java.text.FieldPosition; 25import java.text.NumberFormat; 26import java.text.ParsePosition; 27import java.util.Currency; 28import java.util.Locale; 29 30public class DecimalFormatTest extends junit.framework.TestCase { 31 public void test_exponentSeparator() throws Exception { 32 DecimalFormat df = new DecimalFormat("0E0"); 33 assertEquals("1E4", df.format(12345.)); 34 35 DecimalFormatSymbols dfs = df.getDecimalFormatSymbols(); 36 dfs.setExponentSeparator("-useless-api-"); 37 df.setDecimalFormatSymbols(dfs); 38 assertEquals("1-useless-api-4", df.format(12345.)); 39 } 40 41 public void test_setMaximumFractionDigitsAffectsRoundingMode() throws Exception { 42 DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance(Locale.US); 43 df.setMaximumFractionDigits(0); 44 df.setRoundingMode(RoundingMode.HALF_UP); 45 assertEquals("-0", df.format(-0.2)); 46 df.setMaximumFractionDigits(1); 47 assertEquals("-0.2", df.format(-0.2)); 48 } 49 50 // Android fails this test, truncating to 127 digits. 51 public void test_setMaximumIntegerDigits() throws Exception { 52 NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US); 53 numberFormat.setGroupingUsed(false); 54 numberFormat.setMinimumIntegerDigits(400); 55 // The RI's documentation suggests that the int should be formatted to 309 characters -- 56 // a magic number they don't explain -- but the BigInteger should be formatted to the 400 57 // characters we asked for. In practice, the RI uses 309 in both cases. 58 assertEquals(309, numberFormat.format(123).length()); 59 assertEquals(309, numberFormat.format(BigInteger.valueOf(123)).length()); 60 } 61 62 // Regression test for http://b/1897917: BigDecimal does not take into account multiplier. 63 public void testBigDecimalBug1897917() { 64 // For example. the BigDecimal 0.17 formatted in PercentInstance is 0% instead of 17%: 65 NumberFormat pf = NumberFormat.getPercentInstance(); 66 assertEquals("17%", pf.format(BigDecimal.valueOf(0.17))); 67 68 // Test long decimal formatted in PercentInstance with various fractions. 69 String longDec = "11.2345678901234567890123456789012345678901234567890"; 70 BigDecimal bd = new BigDecimal(longDec); 71 assertBigDecimalWithFraction(bd, "1,123.46%", 2); 72 assertBigDecimalWithFraction(bd, "1,123.45678901%", 8); 73 assertBigDecimalWithFraction(bd, "1,123.4567890123%", 10); 74 assertBigDecimalWithFraction(bd, "1,123.45678901234567890123%", 20); 75 assertBigDecimalWithFraction(bd, "1,123.456789012345678901234567890123%", 30); 76 77 // Test trailing zeros. 78 assertDecFmtWithMultiplierAndFraction("3333.33333333", 3, 4, "10,000"); 79 assertDecFmtWithMultiplierAndFraction("3333.33333333", -3, 4, "-10,000"); 80 assertDecFmtWithMultiplierAndFraction("0.00333333", 3, 4, "0.01"); 81 82 assertDecFmtWithMultiplierAndFractionByLocale("3330000000000000000000000000000000", 3, 4, 83 Locale.US, "9,990,000,000,000,000,000,000,000,000,000,000"); 84 85 Locale en_IN = new Locale("en", "IN"); 86 assertDecFmtWithMultiplierAndFractionByLocale("3330000000000000000000000000000000", 3, 4, 87 en_IN, "9,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,000"); 88 } 89 90 public void testBigDecimalTestBigIntWithMultiplier() { 91 // Big integer tests. 92 assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", 10, 0, 93 Locale.US, "1,234,567,890,123,450"); 94 assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", 10, 0, 95 Locale.US, "123,456,789,012,345,678,900"); 96 assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", 10, 0, 97 Locale.US, "987,654,321,098,765,432,109,876,543,210"); 98 99 assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", -10, 0, 100 Locale.US, "-1,234,567,890,123,450"); 101 assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", -10, 0, 102 Locale.US, "-123,456,789,012,345,678,900"); 103 assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", -10, 0, 104 Locale.US, "-987,654,321,098,765,432,109,876,543,210"); 105 106 Locale en_IN = new Locale("en", "IN"); 107 assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", 10, 0, 108 en_IN, "1,23,45,67,89,01,23,450"); 109 assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", 10, 0, 110 en_IN, "12,34,56,78,90,12,34,56,78,900"); 111 assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", 10, 0, 112 en_IN, "9,87,65,43,21,09,87,65,43,21,09,87,65,43,210"); 113 114 assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", -10, 0, 115 en_IN, "-1,23,45,67,89,01,23,450"); 116 assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", -10, 0, 117 en_IN, "-12,34,56,78,90,12,34,56,78,900"); 118 assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", -10, 0, 119 en_IN, "-9,87,65,43,21,09,87,65,43,21,09,87,65,43,210"); 120 } 121 122 public void testBigDecimalICUConsistency() { 123 DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(); 124 df.setMaximumFractionDigits(2); 125 df.setMultiplier(2); 126 assertEquals(df.format(BigDecimal.valueOf(0.16)), 127 df.format(BigDecimal.valueOf(0.16).doubleValue())); 128 assertEquals(df.format(BigDecimal.valueOf(0.0293)), 129 df.format(BigDecimal.valueOf(0.0293).doubleValue())); 130 assertEquals(df.format(BigDecimal.valueOf(0.006)), 131 df.format(BigDecimal.valueOf(0.006).doubleValue())); 132 assertEquals(df.format(BigDecimal.valueOf(0.00283)), 133 df.format(BigDecimal.valueOf(0.00283).doubleValue())); 134 assertEquals(df.format(BigDecimal.valueOf(1.60)), 135 df.format(BigDecimal.valueOf(1.60).doubleValue())); 136 assertEquals(df.format(BigDecimal.valueOf(15)), 137 df.format(BigDecimal.valueOf(15).doubleValue())); 138 assertEquals(df.format(BigDecimal.valueOf(170)), 139 df.format(BigDecimal.valueOf(170).doubleValue())); 140 assertEquals(df.format(BigDecimal.valueOf(234.56)), 141 df.format(BigDecimal.valueOf(234.56).doubleValue())); 142 assertEquals(df.format(BigDecimal.valueOf(0)), 143 df.format(BigDecimal.valueOf(0).doubleValue())); 144 assertEquals(df.format(BigDecimal.valueOf(-1)), 145 df.format(BigDecimal.valueOf(-1).doubleValue())); 146 assertEquals(df.format(BigDecimal.valueOf(-10000)), 147 df.format(BigDecimal.valueOf(-10000).doubleValue())); 148 assertEquals(df.format(BigDecimal.valueOf(-0.001)), 149 df.format(BigDecimal.valueOf(-0.001).doubleValue())); 150 assertEquals(df.format(BigDecimal.valueOf(1234567890.1234567)), 151 df.format(BigDecimal.valueOf(1234567890.1234567).doubleValue())); 152 assertEquals(df.format(BigDecimal.valueOf(1.234567E100)), 153 df.format(BigDecimal.valueOf(1.234567E100).doubleValue())); 154 } 155 156 private void assertBigDecimalWithFraction(BigDecimal bd, String expectedResult, int fraction) { 157 NumberFormat pf = NumberFormat.getPercentInstance(); 158 pf.setMaximumFractionDigits(fraction); 159 assertEquals(expectedResult, pf.format(bd)); 160 } 161 162 private void assertDecFmtWithMultiplierAndFraction(String value, int multiplier, int fraction, String expectedResult) { 163 DecimalFormat df = (DecimalFormat)NumberFormat.getInstance(); 164 df.setMultiplier(multiplier); 165 df.setMaximumFractionDigits(fraction); 166 BigDecimal d = new BigDecimal(value); 167 assertEquals(expectedResult, df.format(d)); 168 } 169 170 private void assertDecFmtWithMultiplierAndFractionByLocale(String value, int multiplier, int fraction, Locale locale, String expectedResult) { 171 DecimalFormat df = (DecimalFormat)NumberFormat.getIntegerInstance(locale); 172 df.setMultiplier(multiplier); 173 df.setMaximumFractionDigits(fraction); 174 BigDecimal d = new BigDecimal(value); 175 assertEquals(expectedResult, df.format(d)); 176 } 177 178 public void testSetZeroDigitForPattern() { 179 DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(); 180 decimalFormatSymbols.setZeroDigit('a'); 181 DecimalFormat formatter = new DecimalFormat(); 182 formatter.setDecimalFormatSymbols(decimalFormatSymbols); 183 formatter.applyLocalizedPattern("#.aa"); 184 assertEquals("e.fa", formatter.format(4.50)); 185 } 186 187 public void testSetZeroDigitForFormatting() { 188 DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(); 189 decimalFormatSymbols.setZeroDigit('a'); 190 DecimalFormat formatter = new DecimalFormat(); 191 formatter.setDecimalFormatSymbols(decimalFormatSymbols); 192 formatter.applyLocalizedPattern("#"); 193 assertEquals("eadacab", formatter.format(4030201)); 194 } 195 196 public void testBug9087737() throws Exception { 197 DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(Locale.US); 198 // These shouldn't make valgrind unhappy. 199 df.setCurrency(Currency.getInstance("CHF")); 200 df.setCurrency(Currency.getInstance("GBP")); 201 } 202 203 // Check we don't crash on null inputs. 204 public void testBug15081434() throws Exception { 205 DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(Locale.US); 206 try { 207 df.parse(null); 208 fail(); 209 } catch (NullPointerException expected) { 210 } 211 212 try { 213 df.applyLocalizedPattern(null); 214 fail(); 215 } catch (NullPointerException expected) { 216 } 217 218 try { 219 df.applyPattern(null); 220 fail(); 221 } catch (NullPointerException expected) { 222 } 223 224 try { 225 df.applyPattern(null); 226 fail(); 227 } catch (NullPointerException expected) { 228 } 229 230 try { 231 df.format(null, new StringBuffer(), new FieldPosition(0)); 232 fail(); 233 } catch (IllegalArgumentException expected) { 234 } 235 236 try { 237 df.parse(null, new ParsePosition(0)); 238 fail(); 239 } catch (NullPointerException expected) { 240 } 241 242 // This just ignores null. 243 df.setDecimalFormatSymbols(null); 244 245 try { 246 df.setCurrency(null); 247 fail(); 248 } catch (NullPointerException expected) { 249 } 250 251 // These just ignore null. 252 df.setNegativePrefix(null); 253 df.setNegativeSuffix(null); 254 df.setPositivePrefix(null); 255 df.setPositiveSuffix(null); 256 257 try { 258 df.setRoundingMode(null); 259 fail(); 260 } catch (NullPointerException expected) { 261 } 262 } 263 264 // Confirm the fraction digits do not change when the currency is changed. 265 public void testBug71369() { 266 final String nonBreakingSpace = "\u00A0"; 267 268 NumberFormat numberFormat = NumberFormat.getCurrencyInstance(Locale.GERMAN); 269 numberFormat.setCurrency(Currency.getInstance("USD")); 270 271 assertEquals("2,01" + nonBreakingSpace + "$", numberFormat.format(2.01)); 272 273 numberFormat.setMinimumFractionDigits(0); 274 numberFormat.setMaximumFractionDigits(0); 275 276 String expected = "2" + nonBreakingSpace + "$"; 277 assertEquals(expected, numberFormat.format(2.01)); 278 279 // Changing the currency must not reset the digits. 280 numberFormat.setCurrency(Currency.getInstance("EUR")); 281 numberFormat.setCurrency(Currency.getInstance("USD")); 282 283 assertEquals(expected, numberFormat.format(2.01)); 284 } 285 286 // Confirm the currency symbol used by a format is determined by the locale of the format 287 // not the current default Locale. 288 public void testSetCurrency_symbolOrigin() { 289 Currency currency = Currency.getInstance("CNY"); 290 Locale locale1 = Locale.CHINA; 291 Locale locale2 = Locale.US; 292 String locale1Symbol = currency.getSymbol(locale1); 293 String locale2Symbol = currency.getSymbol(locale2); 294 // This test only works if we can tell where the symbol came from, which requires they are 295 // different across the two locales chosen. 296 assertFalse(locale1Symbol.equals(locale2Symbol)); 297 298 Locale originalLocale = Locale.getDefault(); 299 try { 300 Locale.setDefault(locale1); 301 String amountDefaultLocale1 = 302 formatArbitraryCurrencyAmountInLocale(currency, locale2); 303 304 Locale.setDefault(locale2); 305 String amountDefaultLocale2 = 306 formatArbitraryCurrencyAmountInLocale(currency, locale2); 307 308 // This used to fail because Currency.getSymbol() was used without providing the 309 // format's locale. 310 assertEquals(amountDefaultLocale1, amountDefaultLocale2); 311 } finally { 312 Locale.setDefault(originalLocale); 313 } 314 } 315 316 private String formatArbitraryCurrencyAmountInLocale(Currency currency, Locale locale) { 317 NumberFormat localeCurrencyFormat = NumberFormat.getCurrencyInstance(locale); 318 localeCurrencyFormat.setCurrency(currency); 319 return localeCurrencyFormat.format(1000); 320 } 321} 322