1f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes/*
2f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes * Copyright (C) 2010 The Android Open Source Project
3f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
4f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes * you may not use this file except in compliance with the License.
6f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes * You may obtain a copy of the License at
7f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
8f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
10f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes * Unless required by applicable law or agreed to in writing, software
11f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes * See the License for the specific language governing permissions and
14f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes * limitations under the License.
15f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes */
16f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes
174557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonpackage libcore.java.text;
18f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes
1942db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughesimport java.math.BigDecimal;
20f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughesimport java.math.BigInteger;
2142db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughesimport java.math.RoundingMode;
224557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport java.text.DecimalFormat;
2334eb0408ff03c10b8f5842d328457aeeabac17a7Elliott Hughesimport java.text.DecimalFormatSymbols;
247f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughesimport java.text.FieldPosition;
254557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport java.text.NumberFormat;
267f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughesimport java.text.ParsePosition;
278c8fdca4a5c764fa7a6990dc44252736e5f44846Elliott Hughesimport java.util.Currency;
28f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughesimport java.util.Locale;
29f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes
30f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughespublic class DecimalFormatTest extends junit.framework.TestCase {
3134eb0408ff03c10b8f5842d328457aeeabac17a7Elliott Hughes    public void test_exponentSeparator() throws Exception {
3234eb0408ff03c10b8f5842d328457aeeabac17a7Elliott Hughes        DecimalFormat df = new DecimalFormat("0E0");
3334eb0408ff03c10b8f5842d328457aeeabac17a7Elliott Hughes        assertEquals("1E4", df.format(12345.));
3434eb0408ff03c10b8f5842d328457aeeabac17a7Elliott Hughes
3534eb0408ff03c10b8f5842d328457aeeabac17a7Elliott Hughes        DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();
3634eb0408ff03c10b8f5842d328457aeeabac17a7Elliott Hughes        dfs.setExponentSeparator("-useless-api-");
3734eb0408ff03c10b8f5842d328457aeeabac17a7Elliott Hughes        df.setDecimalFormatSymbols(dfs);
3834eb0408ff03c10b8f5842d328457aeeabac17a7Elliott Hughes        assertEquals("1-useless-api-4", df.format(12345.));
3934eb0408ff03c10b8f5842d328457aeeabac17a7Elliott Hughes    }
4034eb0408ff03c10b8f5842d328457aeeabac17a7Elliott Hughes
4142db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes    public void test_setMaximumFractionDigitsAffectsRoundingMode() throws Exception {
4242db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance(Locale.US);
4342db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        df.setMaximumFractionDigits(0);
4442db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        df.setRoundingMode(RoundingMode.HALF_UP);
4542db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals("-0", df.format(-0.2));
4642db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        df.setMaximumFractionDigits(1);
4742db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals("-0.2", df.format(-0.2));
4842db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes    }
49f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
50f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes    // Android fails this test, truncating to 127 digits.
51f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes    public void test_setMaximumIntegerDigits() throws Exception {
52f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes        NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US);
53f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes        numberFormat.setGroupingUsed(false);
54f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes        numberFormat.setMinimumIntegerDigits(400);
55f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes        // The RI's documentation suggests that the int should be formatted to 309 characters --
56f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes        // a magic number they don't explain -- but the BigInteger should be formatted to the 400
57f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes        // characters we asked for. In practice, the RI uses 309 in both cases.
58f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes        assertEquals(309, numberFormat.format(123).length());
59f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes        assertEquals(309, numberFormat.format(BigInteger.valueOf(123)).length());
60f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes    }
61f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
6242db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes    // Regression test for http://b/1897917: BigDecimal does not take into account multiplier.
6342db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes    public void testBigDecimalBug1897917() {
6442db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        // For example. the BigDecimal 0.17 formatted in PercentInstance is 0% instead of 17%:
6542db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        NumberFormat pf = NumberFormat.getPercentInstance();
6642db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals("17%", pf.format(BigDecimal.valueOf(0.17)));
67f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
6842db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        // Test long decimal formatted in PercentInstance with various fractions.
6942db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        String longDec = "11.2345678901234567890123456789012345678901234567890";
7042db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        BigDecimal bd = new BigDecimal(longDec);
7142db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertBigDecimalWithFraction(bd, "1,123.46%", 2);
7242db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertBigDecimalWithFraction(bd, "1,123.45678901%", 8);
7342db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertBigDecimalWithFraction(bd, "1,123.4567890123%", 10);
7442db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertBigDecimalWithFraction(bd, "1,123.45678901234567890123%", 20);
7542db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertBigDecimalWithFraction(bd, "1,123.456789012345678901234567890123%", 30);
76f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
7742db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        // Test trailing zeros.
7842db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertDecFmtWithMultiplierAndFraction("3333.33333333", 3, 4, "10,000");
7942db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertDecFmtWithMultiplierAndFraction("3333.33333333", -3, 4, "-10,000");
8042db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertDecFmtWithMultiplierAndFraction("0.00333333", 3, 4, "0.01");
813d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute
823d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute        assertDecFmtWithMultiplierAndFractionByLocale("3330000000000000000000000000000000", 3, 4,
833d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute                    Locale.US, "9,990,000,000,000,000,000,000,000,000,000,000");
843d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute
85dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes        Locale en_IN = new Locale("en", "IN");
86dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes        assertDecFmtWithMultiplierAndFractionByLocale("3330000000000000000000000000000000", 3, 4,
87dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes                en_IN, "9,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,000");
8842db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes    }
89f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
9042db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes    public void testBigDecimalTestBigIntWithMultiplier() {
9142db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        // Big integer tests.
923d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute        assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", 10, 0,
933d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute                Locale.US, "1,234,567,890,123,450");
943d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute        assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", 10, 0,
953d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute                Locale.US, "123,456,789,012,345,678,900");
963d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute        assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", 10, 0,
973d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute                Locale.US, "987,654,321,098,765,432,109,876,543,210");
983d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute
993d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute        assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", -10, 0,
1003d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute                Locale.US, "-1,234,567,890,123,450");
1013d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute        assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", -10, 0,
1023d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute                Locale.US, "-123,456,789,012,345,678,900");
1033d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute        assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", -10, 0,
1043d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute                Locale.US, "-987,654,321,098,765,432,109,876,543,210");
1053d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute
106dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes        Locale en_IN = new Locale("en", "IN");
107dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes        assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", 10, 0,
108dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes                en_IN, "1,23,45,67,89,01,23,450");
109dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes        assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", 10, 0,
110dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes                en_IN, "12,34,56,78,90,12,34,56,78,900");
111dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes        assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", 10, 0,
112dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes                en_IN, "9,87,65,43,21,09,87,65,43,21,09,87,65,43,210");
113dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes
114dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes        assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", -10, 0,
115dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes                en_IN, "-1,23,45,67,89,01,23,450");
116dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes        assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", -10, 0,
117dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes                en_IN, "-12,34,56,78,90,12,34,56,78,900");
118dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes        assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", -10, 0,
119dd9b761d3b32bf02de354cb228f83cf7697032efElliott Hughes                en_IN, "-9,87,65,43,21,09,87,65,43,21,09,87,65,43,210");
12042db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes    }
121f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
12242db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes    public void testBigDecimalICUConsistency() {
12342db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
12442db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        df.setMaximumFractionDigits(2);
12542db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        df.setMultiplier(2);
12642db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(0.16)),
1278d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller                df.format(BigDecimal.valueOf(0.16).doubleValue()));
12842db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(0.0293)),
1298d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller                df.format(BigDecimal.valueOf(0.0293).doubleValue()));
13042db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(0.006)),
1318d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller                df.format(BigDecimal.valueOf(0.006).doubleValue()));
13242db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(0.00283)),
1338d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller                df.format(BigDecimal.valueOf(0.00283).doubleValue()));
13442db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(1.60)),
13542db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        df.format(BigDecimal.valueOf(1.60).doubleValue()));
13642db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(15)),
1378d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller                df.format(BigDecimal.valueOf(15).doubleValue()));
13842db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(170)),
1398d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller                df.format(BigDecimal.valueOf(170).doubleValue()));
14042db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(234.56)),
1418d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller                df.format(BigDecimal.valueOf(234.56).doubleValue()));
14242db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(0)),
14342db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        df.format(BigDecimal.valueOf(0).doubleValue()));
14442db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(-1)),
14542db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        df.format(BigDecimal.valueOf(-1).doubleValue()));
14642db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(-10000)),
14742db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        df.format(BigDecimal.valueOf(-10000).doubleValue()));
14842db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(-0.001)),
1498d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller                df.format(BigDecimal.valueOf(-0.001).doubleValue()));
15042db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(1234567890.1234567)),
1518d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller                df.format(BigDecimal.valueOf(1234567890.1234567).doubleValue()));
15242db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(df.format(BigDecimal.valueOf(1.234567E100)),
1538d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller                df.format(BigDecimal.valueOf(1.234567E100).doubleValue()));
15442db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes    }
155f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
15642db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes    private void assertBigDecimalWithFraction(BigDecimal bd, String expectedResult, int fraction) {
15742db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        NumberFormat pf = NumberFormat.getPercentInstance();
15842db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        pf.setMaximumFractionDigits(fraction);
15942db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(expectedResult, pf.format(bd));
16042db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes    }
161f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
16242db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes    private void assertDecFmtWithMultiplierAndFraction(String value, int multiplier, int fraction, String expectedResult) {
16342db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        DecimalFormat df = (DecimalFormat)NumberFormat.getInstance();
16442db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        df.setMultiplier(multiplier);
16542db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        df.setMaximumFractionDigits(fraction);
16642db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        BigDecimal d = new BigDecimal(value);
16742db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes        assertEquals(expectedResult, df.format(d));
16842db7d138547e3bba75cf6ed02b6a319e30004aeElliott Hughes    }
1693d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute
1703d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute    private void assertDecFmtWithMultiplierAndFractionByLocale(String value, int multiplier, int fraction, Locale locale, String expectedResult) {
1713d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute        DecimalFormat df = (DecimalFormat)NumberFormat.getIntegerInstance(locale);
1723d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute        df.setMultiplier(multiplier);
1733d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute        df.setMaximumFractionDigits(fraction);
1743d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute        BigDecimal d = new BigDecimal(value);
1753d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute        assertEquals(expectedResult, df.format(d));
1763d8e4eadf05cdd726164e19114989818ff9794f8android-htc-contribute    }
1778c8fdca4a5c764fa7a6990dc44252736e5f44846Elliott Hughes
17823bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes    public void testSetZeroDigitForPattern() {
17923bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes        DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols();
18023bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes        decimalFormatSymbols.setZeroDigit('a');
18123bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes        DecimalFormat formatter = new DecimalFormat();
18223bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes        formatter.setDecimalFormatSymbols(decimalFormatSymbols);
18323bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes        formatter.applyLocalizedPattern("#.aa");
18423bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes        assertEquals("e.fa", formatter.format(4.50));
18523bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes    }
18623bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes
18723bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes    public void testSetZeroDigitForFormatting() {
18823bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes        DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols();
18923bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes        decimalFormatSymbols.setZeroDigit('a');
19023bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes        DecimalFormat formatter = new DecimalFormat();
19123bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes        formatter.setDecimalFormatSymbols(decimalFormatSymbols);
19223bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes        formatter.applyLocalizedPattern("#");
19323bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes        assertEquals("eadacab", formatter.format(4030201));
19423bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes    }
19523bd0dfb8a4b16942c6e09096082729b9d3d7db7Elliott Hughes
1968c8fdca4a5c764fa7a6990dc44252736e5f44846Elliott Hughes    public void testBug9087737() throws Exception {
1978c8fdca4a5c764fa7a6990dc44252736e5f44846Elliott Hughes        DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(Locale.US);
1988c8fdca4a5c764fa7a6990dc44252736e5f44846Elliott Hughes        // These shouldn't make valgrind unhappy.
1998c8fdca4a5c764fa7a6990dc44252736e5f44846Elliott Hughes        df.setCurrency(Currency.getInstance("CHF"));
2008c8fdca4a5c764fa7a6990dc44252736e5f44846Elliott Hughes        df.setCurrency(Currency.getInstance("GBP"));
2018c8fdca4a5c764fa7a6990dc44252736e5f44846Elliott Hughes    }
2027f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes
2037f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes    // Check we don't crash on null inputs.
2047f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes    public void testBug15081434() throws Exception {
2057f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(Locale.US);
2067f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      try {
2077f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        df.parse(null);
2087f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        fail();
2097f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      } catch (NullPointerException expected) {
2107f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      }
2117f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes
2127f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      try {
2137f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        df.applyLocalizedPattern(null);
2147f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        fail();
2157f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      } catch (NullPointerException expected) {
2167f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      }
2177f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes
2187f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      try {
2197f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        df.applyPattern(null);
2207f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        fail();
2217f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      } catch (NullPointerException expected) {
2227f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      }
2237f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes
2247f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      try {
2257f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        df.applyPattern(null);
2267f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        fail();
2277f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      } catch (NullPointerException expected) {
2287f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      }
2297f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes
2307f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      try {
2317f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        df.format(null, new StringBuffer(), new FieldPosition(0));
2327f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        fail();
2337f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      } catch (IllegalArgumentException expected) {
2347f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      }
2357f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes
2367f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      try {
2377f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        df.parse(null, new ParsePosition(0));
2387f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        fail();
2397f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      } catch (NullPointerException expected) {
2407f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      }
2417f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes
2427f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      // This just ignores null.
2437f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      df.setDecimalFormatSymbols(null);
2447f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes
2457f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      try {
2467f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        df.setCurrency(null);
2477f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        fail();
2487f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      } catch (NullPointerException expected) {
2497f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      }
2507f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes
251a5a851ef18cf45152fc0901a07e2f6aa303ef702Joachim Sauer      // These just ignore null.
252a5a851ef18cf45152fc0901a07e2f6aa303ef702Joachim Sauer      df.setNegativePrefix(null);
253a5a851ef18cf45152fc0901a07e2f6aa303ef702Joachim Sauer      df.setNegativeSuffix(null);
254a5a851ef18cf45152fc0901a07e2f6aa303ef702Joachim Sauer      df.setPositivePrefix(null);
255a5a851ef18cf45152fc0901a07e2f6aa303ef702Joachim Sauer      df.setPositiveSuffix(null);
2567f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes
2577f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      try {
2587f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        df.setRoundingMode(null);
2597f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes        fail();
2607f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      } catch (NullPointerException expected) {
2617f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes      }
2627f0856090f176550fb3b8834afa46eb5813ee329Elliott Hughes    }
263ba0592bae1be38bd29f5240c218ff5775f2cd933Neil Fuller
264219af6ef9b40a39728f204ca20ebffdaa0a24ff7Neil Fuller    // Confirm the fraction digits do not change when the currency is changed.
265ba0592bae1be38bd29f5240c218ff5775f2cd933Neil Fuller    public void testBug71369() {
266ba0592bae1be38bd29f5240c218ff5775f2cd933Neil Fuller        final String nonBreakingSpace = "\u00A0";
267ba0592bae1be38bd29f5240c218ff5775f2cd933Neil Fuller
268ba0592bae1be38bd29f5240c218ff5775f2cd933Neil Fuller        NumberFormat numberFormat = NumberFormat.getCurrencyInstance(Locale.GERMAN);
269ba0592bae1be38bd29f5240c218ff5775f2cd933Neil Fuller        numberFormat.setCurrency(Currency.getInstance("USD"));
270ba0592bae1be38bd29f5240c218ff5775f2cd933Neil Fuller
271ba0592bae1be38bd29f5240c218ff5775f2cd933Neil Fuller        assertEquals("2,01" + nonBreakingSpace + "$", numberFormat.format(2.01));
272ba0592bae1be38bd29f5240c218ff5775f2cd933Neil Fuller
273ba0592bae1be38bd29f5240c218ff5775f2cd933Neil Fuller        numberFormat.setMinimumFractionDigits(0);
274ba0592bae1be38bd29f5240c218ff5775f2cd933Neil Fuller        numberFormat.setMaximumFractionDigits(0);
275219af6ef9b40a39728f204ca20ebffdaa0a24ff7Neil Fuller
276219af6ef9b40a39728f204ca20ebffdaa0a24ff7Neil Fuller        String expected = "2" + nonBreakingSpace + "$";
277219af6ef9b40a39728f204ca20ebffdaa0a24ff7Neil Fuller        assertEquals(expected, numberFormat.format(2.01));
278219af6ef9b40a39728f204ca20ebffdaa0a24ff7Neil Fuller
279219af6ef9b40a39728f204ca20ebffdaa0a24ff7Neil Fuller        // Changing the currency must not reset the digits.
280219af6ef9b40a39728f204ca20ebffdaa0a24ff7Neil Fuller        numberFormat.setCurrency(Currency.getInstance("EUR"));
281219af6ef9b40a39728f204ca20ebffdaa0a24ff7Neil Fuller        numberFormat.setCurrency(Currency.getInstance("USD"));
282219af6ef9b40a39728f204ca20ebffdaa0a24ff7Neil Fuller
283219af6ef9b40a39728f204ca20ebffdaa0a24ff7Neil Fuller        assertEquals(expected, numberFormat.format(2.01));
284ba0592bae1be38bd29f5240c218ff5775f2cd933Neil Fuller    }
2858d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller
28643379e19f9b8cb88936d0c1be69070c7c8fbd083Joachim Sauer    // http://b/27855939
28743379e19f9b8cb88936d0c1be69070c7c8fbd083Joachim Sauer    public void testBug27855939() {
28843379e19f9b8cb88936d0c1be69070c7c8fbd083Joachim Sauer        DecimalFormat df = new DecimalFormat("00");
28943379e19f9b8cb88936d0c1be69070c7c8fbd083Joachim Sauer        assertEquals("01", df.format(BigDecimal.ONE));
29043379e19f9b8cb88936d0c1be69070c7c8fbd083Joachim Sauer        assertEquals("00", df.format(BigDecimal.ZERO));
29143379e19f9b8cb88936d0c1be69070c7c8fbd083Joachim Sauer    }
29243379e19f9b8cb88936d0c1be69070c7c8fbd083Joachim Sauer
2938d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller    // Confirm the currency symbol used by a format is determined by the locale of the format
2948d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller    // not the current default Locale.
2958d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller    public void testSetCurrency_symbolOrigin() {
2968d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        Currency currency = Currency.getInstance("CNY");
2978d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        Locale locale1 = Locale.CHINA;
2988d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        Locale locale2 = Locale.US;
2998d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        String locale1Symbol = currency.getSymbol(locale1);
3008d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        String locale2Symbol = currency.getSymbol(locale2);
3018d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        // This test only works if we can tell where the symbol came from, which requires they are
3028d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        // different across the two locales chosen.
3038d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        assertFalse(locale1Symbol.equals(locale2Symbol));
3048d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller
3058d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        Locale originalLocale = Locale.getDefault();
3068d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        try {
3078d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller            Locale.setDefault(locale1);
3088d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller            String amountDefaultLocale1 =
3098d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller                    formatArbitraryCurrencyAmountInLocale(currency, locale2);
3108d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller
3118d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller            Locale.setDefault(locale2);
3128d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller            String amountDefaultLocale2 =
3138d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller                    formatArbitraryCurrencyAmountInLocale(currency, locale2);
3148d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller
3158d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller            // This used to fail because Currency.getSymbol() was used without providing the
3168d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller            // format's locale.
3178d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller            assertEquals(amountDefaultLocale1, amountDefaultLocale2);
3188d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        } finally {
3198d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller            Locale.setDefault(originalLocale);
3208d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        }
3218d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller    }
3228d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller
323d7f14d4672ba2d07fd7dfa7a74fb31879cd14369Raph Levien    // Test that overriding the currency symbol survives a roundrip through the
324d7f14d4672ba2d07fd7dfa7a74fb31879cd14369Raph Levien    // DecimalFormat constructor.
325d7f14d4672ba2d07fd7dfa7a74fb31879cd14369Raph Levien    // http://b/28732330
326d7f14d4672ba2d07fd7dfa7a74fb31879cd14369Raph Levien    public void testSetCurrencySymbol() {
327d7f14d4672ba2d07fd7dfa7a74fb31879cd14369Raph Levien        DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(Locale.US);
328d7f14d4672ba2d07fd7dfa7a74fb31879cd14369Raph Levien        decimalFormatSymbols.setCurrencySymbol("¥");
329d7f14d4672ba2d07fd7dfa7a74fb31879cd14369Raph Levien        DecimalFormat decimalFormat = new DecimalFormat("¤#,##0.00", decimalFormatSymbols);
330d7f14d4672ba2d07fd7dfa7a74fb31879cd14369Raph Levien        assertEquals("¥", decimalFormat.getDecimalFormatSymbols().getCurrencySymbol());
331d7f14d4672ba2d07fd7dfa7a74fb31879cd14369Raph Levien    }
332d7f14d4672ba2d07fd7dfa7a74fb31879cd14369Raph Levien
3338d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller    private String formatArbitraryCurrencyAmountInLocale(Currency currency, Locale locale) {
3348d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        NumberFormat localeCurrencyFormat = NumberFormat.getCurrencyInstance(locale);
3358d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        localeCurrencyFormat.setCurrency(currency);
3368d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller        return localeCurrencyFormat.format(1000);
3378d07b07a3ed315c2e1c469d3769cf1df3f49e58bNeil Fuller    }
33824d7719948d565617351a6135454893bdd9b8b21Victor Chang
33924d7719948d565617351a6135454893bdd9b8b21Victor Chang    /**
34024d7719948d565617351a6135454893bdd9b8b21Victor Chang     * DecimalFormat doesn't support different group separator for currency and non-currency
34124d7719948d565617351a6135454893bdd9b8b21Victor Chang     * number formats. Ensure normal group separator is used, and ignore monetary group separator
34224d7719948d565617351a6135454893bdd9b8b21Victor Chang     * when formatting currency. http://b/37135768
34324d7719948d565617351a6135454893bdd9b8b21Victor Chang     */
34424d7719948d565617351a6135454893bdd9b8b21Victor Chang    public void testLocaleGroupingSeparator() {
345311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // CLDR uses '.' for currency and U+00a0 for non-currency number formats in de_AT
34624d7719948d565617351a6135454893bdd9b8b21Victor Chang        // Assert ICU is using these characters
34724d7719948d565617351a6135454893bdd9b8b21Victor Chang        Locale locale = new Locale("de", "AT");
34824d7719948d565617351a6135454893bdd9b8b21Victor Chang        android.icu.text.DecimalFormatSymbols icuDfs =
34924d7719948d565617351a6135454893bdd9b8b21Victor Chang                new android.icu.text.DecimalFormatSymbols(locale);
35024d7719948d565617351a6135454893bdd9b8b21Victor Chang        assertEquals(icuDfs.getGroupingSeparator(), '\u00a0');
35124d7719948d565617351a6135454893bdd9b8b21Victor Chang        assertEquals(icuDfs.getMonetaryGroupingSeparator(), '.');
35224d7719948d565617351a6135454893bdd9b8b21Victor Chang
353311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // In this class, only U+00a0 should be used for both cases.
35424d7719948d565617351a6135454893bdd9b8b21Victor Chang        DecimalFormatSymbols dfs = new DecimalFormatSymbols(locale);
355311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // Assert CLDR uses U+00a0 as grouping separator
35624d7719948d565617351a6135454893bdd9b8b21Victor Chang        assertEquals(dfs.getGroupingSeparator(), '\u00a0');
35724d7719948d565617351a6135454893bdd9b8b21Victor Chang
35824d7719948d565617351a6135454893bdd9b8b21Victor Chang        // Test non-currency number formats
35924d7719948d565617351a6135454893bdd9b8b21Victor Chang        assertEquals("1\u00a0234,00", new DecimalFormat("#,##0.00", dfs).format(1234));
36024d7719948d565617351a6135454893bdd9b8b21Victor Chang        // Test currency format
36124d7719948d565617351a6135454893bdd9b8b21Victor Chang        assertEquals("\u20ac1\u00a0234,00", new DecimalFormat("¤#,##0.00", dfs).format(1234));
36224d7719948d565617351a6135454893bdd9b8b21Victor Chang    }
36324d7719948d565617351a6135454893bdd9b8b21Victor Chang
36424d7719948d565617351a6135454893bdd9b8b21Victor Chang    /**
36524d7719948d565617351a6135454893bdd9b8b21Victor Chang     * Test {@link DecimalFormatSymbols#setGroupingSeparator(char)} for currency and non-currency
36624d7719948d565617351a6135454893bdd9b8b21Victor Chang     * number formats. http://b/37135768
36724d7719948d565617351a6135454893bdd9b8b21Victor Chang     */
36824d7719948d565617351a6135454893bdd9b8b21Victor Chang    public void testSetGroupingSeparator() {
36924d7719948d565617351a6135454893bdd9b8b21Victor Chang        DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US);
37024d7719948d565617351a6135454893bdd9b8b21Victor Chang        dfs.setGroupingSeparator(' ');
37124d7719948d565617351a6135454893bdd9b8b21Victor Chang        // Test non-currency number formats
37224d7719948d565617351a6135454893bdd9b8b21Victor Chang        assertEquals("1 234.00", new DecimalFormat("#,##0.00", dfs).format(1234));
37324d7719948d565617351a6135454893bdd9b8b21Victor Chang        // Test currency format
37424d7719948d565617351a6135454893bdd9b8b21Victor Chang        assertEquals("$1 234.00", new DecimalFormat("¤#,##0.00", dfs).format(1234));
37524d7719948d565617351a6135454893bdd9b8b21Victor Chang    }
376311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
377311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    /**
378311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * PerMill should be truncated into one char. http://b/67034519
379311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     */
380311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    public void testPerMill() {
381311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        String pattern = "0\u2030";
382311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        double number = 0.1;
383311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        Locale locale;
384311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
385311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // Test US locale behavior: java.text perMill char is expected to be \u2030.
386311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        locale = Locale.US;
387311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        {
388311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            android.icu.text.DecimalFormat df = new android.icu.text.DecimalFormat(pattern,
389311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang                    new android.icu.text.DecimalFormatSymbols(locale));
390311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("100\u2030", df.format(number));
391311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
392311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        for (DecimalFormat df : createDecimalFormatInstances(locale, pattern)) {
393311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("100\u2030", df.format(number));
394311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
395311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
396311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // Test setPerMill() works
397311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        DecimalFormatSymbols dfs = new DecimalFormatSymbols(locale);
398311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        dfs.setPerMill(';');
399311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        assertEquals("100;", new DecimalFormat(pattern, dfs).format(number));
400311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
401311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // Confirm ICU and java.text agree. Test PerMill is localized.
402311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        locale = new Locale("ar");
403311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        {
404311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            android.icu.text.DecimalFormat df = new android.icu.text.DecimalFormat(pattern,
405311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang                    new android.icu.text.DecimalFormatSymbols(locale));
406311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // Confirm the "correct" perMill sign uses a single non-ascii char.
407311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // ICU's perMill string for ar is known to use single non-ascii char U+0609
408311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u0609", df.getDecimalFormatSymbols().getPerMillString());
409311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u0661\u0660\u0660\u0609", df.format(number));
410311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
411311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        for (DecimalFormat df : createDecimalFormatInstances(locale, pattern)) {
412311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals('\u0609', df.getDecimalFormatSymbols().getPerMill());
413311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u0661\u0660\u0660\u0609", df.format(number));
414311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
415311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
416311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // Confirm ICU and java.text disagree.
417311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // java.text doesn't localize PerMill and fallback to default char U+2030
418311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // when PerMill in that locale has more than one visible characters.
419a2c4fca4140bb6466f1060bc9026312b7d254198Victor Chang        locale = Locale.forLanguageTag("en-US-POSIX");
420311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        {
421311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            android.icu.text.DecimalFormat df = new android.icu.text.DecimalFormat(pattern,
422311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang                    new android.icu.text.DecimalFormatSymbols(locale));
423311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // Confirm the "correct" perMill sign requires more than one char.
424311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // ICU's perMill string for en_US_POSIX is known to have more than one visible chars.
425311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("0/00", df.getDecimalFormatSymbols().getPerMillString());
426311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("1000/00", df.format(number));
427311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
428311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        for (DecimalFormat df : createDecimalFormatInstances(locale, pattern)) {
429311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals('\u2030', df.getDecimalFormatSymbols().getPerMill());
430311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("100\u2030", df.format(number));
431311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
432311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    }
433311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
434311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    /**
435311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * Percent should be truncated into one char.
436311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     */
437311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    public void testPercent() {
438311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        String pattern = "0%";
439311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        double number = 0.1;
440311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        Locale locale;
441311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
442311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // Test US locale behavior: java.text percent char is expected to be '%'.
443311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        locale = Locale.US;
444311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        {
445311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            android.icu.text.DecimalFormat df = new android.icu.text.DecimalFormat(pattern,
446311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang                    new android.icu.text.DecimalFormatSymbols(locale));
447311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("10%", df.format(number));
448311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
449311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        for (DecimalFormat df : createDecimalFormatInstances(locale, pattern)) {
450311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("10%", df.format(number));
451311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
452311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
453311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // Test setPercent() works
454311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        DecimalFormatSymbols dfs = new DecimalFormatSymbols(locale);
455311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        dfs.setPercent(';');
456311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        assertEquals("10;", new DecimalFormat(pattern, dfs).format(number));
457311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
458311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // Confirm ICU and java.text disagree because java.text strips out bidi marker
459311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        locale = new Locale("ar");
460311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        {
461311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            android.icu.text.DecimalFormat df = new android.icu.text.DecimalFormat(pattern,
462311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang                    new android.icu.text.DecimalFormatSymbols(locale));
463311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // Confirm the "correct" percent sign requires more than one char.
464311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // ICU's percent string for ar is known to have a bidi marker.
465311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u066a\u061c", df.getDecimalFormatSymbols().getPercentString());
466311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u0661\u0660\u066a\u061c", df.format(number));
467311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
468311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        for (DecimalFormat df : createDecimalFormatInstances(locale, pattern)) {
469311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // Confirm that java.text.DecimalFormat strips bidi marker characters.
470311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // so the ar percent can fit in a single char.
471311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals('\u066a', df.getDecimalFormatSymbols().getPercent());
472311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u0661\u0660\u066a", df.format(number));
473311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
474311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    }
475311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
476311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    /**
477311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * Minus sign should be truncated into one char.
478311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     */
479311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    public void testMinusSign() {
480311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        String pattern = "0;-0";
481311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        double number = -123;
482311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        Locale locale;
483311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
484311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // Test US locale behavior: java.text percent char is expected to be '-'.
485311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        locale = Locale.US;
486311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        assertEquals("-123", new DecimalFormat(pattern, new DecimalFormatSymbols(locale))
487311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang                .format(number));
488311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        assertEquals("-123", new android.icu.text.DecimalFormat(pattern,
489311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang                new android.icu.text.DecimalFormatSymbols(locale)).format(number));
490311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
491311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // Confirm ICU and java.text agree. Minus sign is localized
492311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        locale = new Locale("lt");
493311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        {
494311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            android.icu.text.DecimalFormat df = new android.icu.text.DecimalFormat(pattern,
495311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang                    new android.icu.text.DecimalFormatSymbols(locale));
496311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // Confirm the "correct" minus sign uses a single non-ascii char.
497311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // ICU's minus string for ar is known to use single non-ascii char U+2212
498311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u2212", df.getDecimalFormatSymbols().getMinusSignString());
499311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u2212123", df.format(number));
500311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
501311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        for (DecimalFormat df : createDecimalFormatInstances(locale, pattern)) {
502311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals('\u2212', df.getDecimalFormatSymbols().getMinusSign());
503311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u2212123", df.format(number));
504311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
505311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
506311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // Confirm ICU and java.text disagree because java.text strips out bidi marker
507311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        locale = new Locale("ar");
508311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        {
509311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            android.icu.text.DecimalFormat df = new android.icu.text.DecimalFormat(pattern,
510311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang                    new android.icu.text.DecimalFormatSymbols(locale));
511311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // Confirm the "correct" minus sign requires more than one char.
512311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // ICU's minus string for ar is known to have a bidi marker.
513311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u061c\u002d", df.getDecimalFormatSymbols().getMinusSignString());
514311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u061c\u002d\u0661\u0662\u0663", df.format(number));
515311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
516311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        for (DecimalFormat df : createDecimalFormatInstances(locale, pattern)) {
517311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals('\u002d', df.getDecimalFormatSymbols().getMinusSign());
518311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u002d\u0661\u0662\u0663", df.format(number));
519311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
520311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    }
521311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
522311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    /**
523311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * Plus sign should not be localized. http://b/67034519
524311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     */
525311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    public void testPlusSign() {
526311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // Test US Locale
527311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        String pattern = "+0;-0";
528311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        assertEquals("+123", new DecimalFormat(pattern, new DecimalFormatSymbols(Locale.US))
529311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang                .format(123));
530311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
531311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        // Confirm ICU and java.text disagree because java.text doesn't localize plus sign.
532311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        Locale locale = new Locale("ar");
533311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        {
534311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            android.icu.text.DecimalFormat df = new android.icu.text.DecimalFormat(pattern,
535311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang                    new android.icu.text.DecimalFormatSymbols(locale));
536311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // Confirm the "correct" plus sign requires more than one char.
537311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            // ICU's plus string for ar is known to have a bidi marker.
538311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u061c\u002b", df.getDecimalFormatSymbols().getPlusSignString());
539311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u061c\u002b\u0661\u0662\u0663", df.format(123));
540311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
541311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        for (DecimalFormat df : createDecimalFormatInstances(locale, pattern)) {
542311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang            assertEquals("\u002b\u0661\u0662\u0663", df.format(123));
543311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        }
544311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    }
545311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang
546311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    /**
547311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * Returns DecimalFormat instances created in different ways:
548311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * <ol>
549311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * <li>Using an implicit DecimalFormatSymbols created using the default locale.</li>
550311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * <li>Using an explicit DecimalFormatSymbols object.
551311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * </ol>
552311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * This is to confirm the behavior is currently the same. In future we may choose to improve the
553311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * behavior when the caller doesn't provide an explicit DecimalFormatSymbols:
554311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * in that case we wouldn't have to pretend that some symbols fit into single char; because the
555311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * caller hasn't explicitly specified the symbols they want us to use and we'd be under no
556311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     * obligation to use the limited char-based public API on DecimalFormatSymbols.
557311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang     */
558311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    private static DecimalFormat[] createDecimalFormatInstances(Locale locale, String pattern) {
559311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        Locale originalLocale = Locale.getDefault();
560311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        Locale.setDefault(locale);
561311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        DecimalFormat[] instances = new DecimalFormat[] {
562311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang                new DecimalFormat(pattern),
563311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang                new DecimalFormat(pattern, new DecimalFormatSymbols(locale))
564311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        };
565311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        Locale.setDefault(originalLocale);
566311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang        return instances;
567311862196723a8d0dc51f276a1a22947e70a2d06Victor Chang    }
5680e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer
5690e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer    // http://b/68143370
5700e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer    public void testWhitespaceTolerated() {
5710e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Trailing space is tolerated, but not consumed.
5720e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParsed("0", "1 ", 1, 1);
5730e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Digits after trailing space are ignored.
5740e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParsed("0", "1 2", 1, 1);
5750e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Space after decimal point is treated as end of input.
5760e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParsed("0", "1. 1", 1, 2);
5770e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Space before decimal point is treated as end of input.
5780e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParsed("0", "1 .1", 1, 1);
5790e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Space after decimal digit is treated as end of input.
5800e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParsed("0", "1.2 3", 1.2d, 3);
5810e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Leading space treated as part of negative prefix
5820e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParsed("0; 0", " 1 ", -1, 2);
5830e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Leading space in prefix is accepted.
5840e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParsed(" 0", " 1 ", 1, 2);
5850e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Extra space after prefix with space is accepted.
5860e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParsed(" 0", "  1 ", 1, 3);
5870e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer    }
5880e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer
5890e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer    // http://b/68143370
5900e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer    public void testWhitespaceError() {
5910e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Space before currency symbol is not tolerated.
5920e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParseError("¤0", " $1");
5930e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Space after currency symbol is not tolerated.
5940e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParseError("¤0", "$ 1");
5950e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Space before positive prefix is not tolerated.
5960e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParseError("+0", " +1");
5970e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Space after positive prefix is not tolerated.
5980e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParseError("+0", "+ 1");
5990e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Leading space is not tolerated.
6000e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParseError("0", " 1");
6010e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        // Space in prefix is expected to be present.
6020e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertParseError(" 0", "1");
6030e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer    }
6040e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer
6050e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer
6060e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer    private void assertParseError(String pattern, String input) {
6070e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        ParsePosition pos = new ParsePosition(0);
6080e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        DecimalFormat df = new DecimalFormat(pattern, DecimalFormatSymbols.getInstance(Locale.US));
6090e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        Number result = df.parse(input, pos);
6100e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        if (result != null) {
6110e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer            fail(String.format("Parsed <%s> using <%s>, should have failed: %s",
6120e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer                    input, pattern, describeParseResult(result, pos)));
6130e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        }
6140e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer    }
6150e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer
6160e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer    private static void assertParsed(String pattern, String input, Number expected,
6170e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer            int expectedIndex) {
6180e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        ParsePosition expectedPos = new ParsePosition(expectedIndex);
6190e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        ParsePosition pos = new ParsePosition(0);
6200e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        DecimalFormat df = new DecimalFormat(pattern, DecimalFormatSymbols.getInstance(Locale.US));
6210e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        Number result = df.parse(input, pos);
6220e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        assertEquals("Parse <" + input + "> using <" + pattern + ">.",
6230e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer                describeParseResult(expected, expectedPos), describeParseResult(result, pos));
6240e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer    }
6250e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer
6260e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer    private static String describeParseResult(Number result, ParsePosition pos) {
6270e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer        return String.format("%s, index=%d, errorIndex=%d",
6280e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer                result, pos.getIndex(), pos.getErrorIndex());
6290e881ce44223bd7712e6ece982a5198ff21fdaefJoachim Sauer    }
630f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes}
631