Bug4838107.java revision 14630:29af931514f5
1/*
2 * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @bug 4838107 8008577
27 * @summary Confirm that DecimalFormat can format a number with negative exponent number correctly.
28 * @library /java/text/testlib
29 * @run main/othervm -Djava.locale.providers=COMPAT,SPI Bug4838107
30 */
31
32import java.math.*;
33import java.util.*;
34import java.text.*;
35
36public class Bug4838107 extends IntlTest {
37
38    static DecimalFormat df;
39    static DecimalFormatSymbols dfs;
40    static boolean err = false;
41
42    static public void main(String[] args) {
43        Locale defaultLoc = Locale.getDefault();
44        Locale.setDefault(Locale.US);
45
46        /**
47         * This bug is about exponential formatting. But I added test cases for:
48         *   - Double and BigDecimal numbers which don't have exponent parts.
49         *   - Long and BigInteger numbers which don't support exponential
50         *     notation.
51         * because there are few test cases for suffix and prefix.
52         * And also, I added test cases to guarantee further formatting and
53         * parsing using the same DecimalFormat instance will not change the
54         * Number's value anymore.
55         */
56
57        test_double();
58        test_long();
59        test_BigDecimal();
60        test_BigInteger();
61
62        Locale.setDefault(defaultLoc);
63
64        if (err) {
65            throw new RuntimeException("Wrong format with DecimalFormat");
66        }
67    }
68
69    static void test_double() {
70        df = new DecimalFormat();
71        dfs = df.getDecimalFormatSymbols();
72
73        /* Test with default pattern */
74        test(new Double(1234),    "1,234");
75        test(new Double(0.1234),  "0.123");     // rounded
76        test(new Double(-1234),   "-1,234");
77        test(new Double(-0.1234), "-0.123");    // rounded
78
79        test(new Double(Double.POSITIVE_INFINITY), "\u221e");
80        test(new Double(Double.NEGATIVE_INFINITY), "-\u221e");
81        test(new Double(Double.NaN), "\ufffd"); // without prefix and suffix
82        test(new Double(0.0),  "0");
83        test(new Double(-0.0), "-0");   // with the minus sign
84
85        /* Specify a pattern and the minus sign. */
86        prepareFormatter("<P>#.###E00<S>", 'm');
87        test(new Double(1234),    "<P>1.234E03<S>");
88        test(new Double(0.1234),  "<P>1.234Em01<S>");
89        test(new Double(-1234),   "m<P>1.234E03<S>");
90        test(new Double(-0.1234), "m<P>1.234Em01<S>");
91
92        prepareFormatter("<P>#.###E00<S>;#.###E00", 'm');
93        test(new Double(1234),    "<P>1.234E03<S>");
94        test(new Double(0.1234),  "<P>1.234Em01<S>");
95        test(new Double(-1234),   "1.234E03");
96        test(new Double(-0.1234), "1.234Em01");
97
98        prepareFormatter("#.###E00;<P>#.###E00<S>", 'm');
99        test(new Double(1234),    "1.234E03");
100        test(new Double(0.1234),  "1.234Em01");
101        test(new Double(-1234),   "<P>1.234E03<S>");
102        test(new Double(-0.1234), "<P>1.234Em01<S>");
103
104        prepareFormatter("<P>#.###E00<S>;<p>-#.###E00<s>", 'm');
105        test(new Double(1234),    "<P>1.234E03<S>");
106        test(new Double(0.1234),  "<P>1.234Em01<S>");
107        test(new Double(-1234),   "<p>m1.234E03<s>");
108        test(new Double(-0.1234), "<p>m1.234Em01<s>");
109
110        test(new Double(Double.POSITIVE_INFINITY), "<P>\u221e<S>");
111        test(new Double(Double.NEGATIVE_INFINITY), "<p>m\u221e<s>");
112        test(new Double(Double.NaN), "\ufffd"); // without prefix and suffix
113        test(new Double(0.0),  "<P>0E00<S>");
114        test(new Double(-0.0), "<p>m0E00<s>");  // with the minus sign
115    }
116
117    static void test_BigDecimal() {
118        df = new DecimalFormat();
119        dfs = df.getDecimalFormatSymbols();
120
121        /* Test with default pattern */
122        test(new BigDecimal("123456789012345678901234567890"),
123             "123,456,789,012,345,678,901,234,567,890");
124        test(new BigDecimal("0.000000000123456789012345678901234567890"),
125             "0");
126        test(new BigDecimal("-123456789012345678901234567890"),
127             "-123,456,789,012,345,678,901,234,567,890");
128        test(new BigDecimal("-0.000000000123456789012345678901234567890"),
129              "-0");
130
131        test(new BigDecimal("0"), "0");
132        test(new BigDecimal("-0"), "0");
133
134        /* Specify a pattern and the minus sign. */
135        prepareFormatter("<P>#.####################E00<S>;<p>-#.####################E00<s>", 'm');
136        test(new BigDecimal("123456789012345678901234567890"),
137             "<P>1.23456789012345678901E29<S>");
138        test(new BigDecimal("0.000000000123456789012345678901234567890"),
139             "<P>1.23456789012345678901Em10<S>");
140        test(new BigDecimal("-123456789012345678901234567890"),
141             "<p>m1.23456789012345678901E29<s>");
142        test(new BigDecimal("-0.000000000123456789012345678901234567890"),
143              "<p>m1.23456789012345678901Em10<s>");
144
145        test(new BigDecimal("0"), "<P>0E00<S>");
146        test(new BigDecimal("-0"), "<P>0E00<S>");
147    }
148
149    static void test_long() {
150        df = new DecimalFormat();
151        dfs = df.getDecimalFormatSymbols();
152
153        /* Test with default pattern */
154        test(new Long(123456789),  "123,456,789");
155        test(new Long(-123456789), "-123,456,789");
156
157        test(new Long(0), "0");
158        test(new Long(-0), "0");
159
160        /* Specify a pattern and the minus sign. */
161        prepareFormatter("<P>#,###<S>;<p>-#,###<s>", 'm');
162        test(new Long(123456789),  "<P>123,456,789<S>");
163        test(new Long(-123456789), "<p>m123,456,789<s>");
164
165        test(new Long(0), "<P>0<S>");
166        test(new Long(-0), "<P>0<S>");
167    }
168
169    static void test_BigInteger() {
170        df = new DecimalFormat();
171        dfs = df.getDecimalFormatSymbols();
172
173        /* Test with default pattern */
174        test(new BigInteger("123456789012345678901234567890"),
175             "123,456,789,012,345,678,901,234,567,890");
176        test(new BigInteger("-123456789012345678901234567890"),
177             "-123,456,789,012,345,678,901,234,567,890");
178
179        test(new BigInteger("0"), "0");
180        test(new BigInteger("-0"), "0");
181
182        /* Specify a pattern and the minus sign. */
183        prepareFormatter("<P>#,###<S>;<p>-#,###<s>", 'm');
184        test(new BigInteger("123456789012345678901234567890"),
185             "<P>123,456,789,012,345,678,901,234,567,890<S>");
186        test(new BigInteger("-123456789012345678901234567890"),
187             "<p>m123,456,789,012,345,678,901,234,567,890<s>");
188
189        test(new BigInteger("0"), "<P>0<S>");
190        test(new BigInteger("-0"), "<P>0<S>");
191    }
192
193    static void prepareFormatter(String pattern, char minusSign) {
194        dfs = df.getDecimalFormatSymbols();
195        df.applyPattern(pattern);
196        dfs.setMinusSign(minusSign);
197        df.setDecimalFormatSymbols(dfs);
198    }
199
200    static void test(Number num, String str) {
201        String formatted = df.format(num);
202        if (!formatted.equals(str)) {
203            err = true;
204            System.err.println("    DecimalFormat format(" +
205                               num.getClass().getName() +
206                               ") error: \n\tnumber: " + num +
207                               "\n\tminus sign: " + dfs.getMinusSign() +
208                               "\n\tgot:        " + formatted +
209                               "\n\texpected:   " + str);
210            return;
211        }
212
213        if (num instanceof BigDecimal || num instanceof BigInteger) {
214            df.setParseBigDecimal(true);
215        }
216        Number parsed1 = null, parsed2 = null;
217        try {
218            parsed1 = df.parse(formatted);
219            formatted = df.format(parsed1);
220            parsed2 = df.parse(formatted);
221            if (!parsed1.equals(parsed2)) {
222                err = true;
223                System.err.println("    DecimalFormat roundtrip parse(" +
224                                   num.getClass().getName() +
225                                   ") error: \n\toriginal number:  " + str +
226                                   "\n\tparsed number:    " + parsed1 +
227                                   "  (" + parsed1.getClass().getName() + ")" +
228                                   "\n\tformatted number: " + formatted +
229                                   "\n\tre-parsed number: " + parsed2 +
230                                   "  (" + parsed2.getClass().getName() + ")" +
231                                   "\n\tminus sign: " + dfs.getMinusSign());
232            }
233        }
234        catch (Exception e) {
235            err = true;
236            System.err.println("    DecimalFormat parse(" +
237                               num.getClass().getName() +
238                               ") threw an Exception:  " + e.getMessage() +
239                               "\n\toriginal number:  " + str +
240                               "\n\tparsed number   : " + parsed1 +
241                               "  (" + parsed1.getClass().getName() + ")" +
242                               "\n\tformatted number: " + formatted +
243                               "\n\tre-parsed number: " + parsed2 +
244                               "  (" + parsed2.getClass().getName() + ")" +
245                               "\n\tminus sign: " + dfs.getMinusSign());
246        }
247    }
248}
249