Home | History | Annotate | Download | only in text
      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 
     17 package libcore.java.text;
     18 
     19 import java.math.BigDecimal;
     20 import java.math.BigInteger;
     21 import java.math.RoundingMode;
     22 import java.text.DecimalFormat;
     23 import java.text.DecimalFormatSymbols;
     24 import java.text.FieldPosition;
     25 import java.text.NumberFormat;
     26 import java.text.ParsePosition;
     27 import java.util.Currency;
     28 import java.util.Locale;
     29 
     30 public 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