IntlTestDecimalFormatAPI.java revision 2d2bb24f747c65578da13d5b13b82f0669690461
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html#License
3/*****************************************************************************************
4 *
5 *   Copyright (C) 1996-2012, International Business Machines
6 *   Corporation and others.  All Rights Reserved.
7 **/
8
9/**
10 * Port From:   JDK 1.4b1 : java.text.Format.IntlTestDecimalFormatAPI
11 * Source File: java/text/format/IntlTestDecimalFormatAPI.java
12 **/
13
14/*
15    @test 1.4 98/03/06
16    @summary test International Decimal Format API
17*/
18
19package com.ibm.icu.dev.test.format;
20
21import java.text.FieldPosition;
22import java.text.Format;
23import java.text.ParseException;
24import java.text.ParsePosition;
25import java.util.Locale;
26
27import org.junit.Test;
28
29import com.ibm.icu.math.BigDecimal;
30import com.ibm.icu.math.MathContext;
31import com.ibm.icu.text.DecimalFormat;
32import com.ibm.icu.text.DecimalFormatSymbols;
33import com.ibm.icu.text.NumberFormat;
34
35public class IntlTestDecimalFormatAPI extends com.ibm.icu.dev.test.TestFmwk
36{
37    /**
38     * Problem 1: simply running
39     * decF4.setRoundingMode(java.math.BigDecimal.ROUND_HALF_UP) does not work
40     * as decF4.setRoundingIncrement(.0001) must also be run.
41     * Problem 2: decF4.format(8.88885) does not return 8.8889 as expected.
42     * You must run decF4.format(new BigDecimal(Double.valueOf(8.88885))) in
43     * order for this to work as expected.
44     * Problem 3: There seems to be no way to set half up to be the default
45     * rounding mode.
46     * We solved the problem with the code at the bottom of this page however
47     * this is not quite general purpose enough to include in icu4j. A static
48     * setDefaultRoundingMode function would solve the problem nicely. Also
49     * decimal places past 20 are not handled properly. A small ammount of work
50     * would make bring this up to snuff.
51     */
52    @Test
53    public void testJB1871()
54    {
55        // problem 2
56        double number = 8.88885;
57        String expected = "8.8889";
58
59        String pat = ",##0.0000";
60        DecimalFormat dec = new DecimalFormat(pat);
61        dec.setRoundingMode(BigDecimal.ROUND_HALF_UP);
62        double roundinginc = 0.0001;
63        dec.setRoundingIncrement(roundinginc);
64        String str = dec.format(number);
65        if (!str.equals(expected)) {
66            errln("Fail: " + number + " x \"" + pat + "\" = \"" +
67                  str + "\", expected \"" + expected + "\"");
68        }
69
70        pat = ",##0.0001";
71        dec = new DecimalFormat(pat);
72        dec.setRoundingMode(BigDecimal.ROUND_HALF_UP);
73        str = dec.format(number);
74        if (!str.equals(expected)) {
75            errln("Fail: " + number + " x \"" + pat + "\" = \"" +
76                  str + "\", expected \"" + expected + "\"");
77        }
78
79        // testing 20 decimal places
80        pat = ",##0.00000000000000000001";
81        dec = new DecimalFormat(pat);
82        BigDecimal bignumber = new BigDecimal("8.888888888888888888885");
83        expected = "8.88888888888888888889";
84
85        dec.setRoundingMode(BigDecimal.ROUND_HALF_UP);
86        str = dec.format(bignumber);
87        if (!str.equals(expected)) {
88            errln("Fail: " + bignumber + " x \"" + pat + "\" = \"" +
89                  str + "\", expected \"" + expected + "\"");
90        }
91
92    }
93
94    /**
95     * This test checks various generic API methods in DecimalFormat to achieve
96     * 100% API coverage.
97     */
98    @Test
99    public void TestAPI()
100    {
101        logln("DecimalFormat API test---"); logln("");
102        Locale.setDefault(Locale.ENGLISH);
103
104        // ======= Test constructors
105
106        logln("Testing DecimalFormat constructors");
107
108        DecimalFormat def = new DecimalFormat();
109
110        final String pattern = new String("#,##0.# FF");
111        DecimalFormat pat = null;
112        try {
113            pat = new DecimalFormat(pattern);
114        }
115        catch (IllegalArgumentException e) {
116            errln("ERROR: Could not create DecimalFormat (pattern)");
117        }
118
119        DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.FRENCH);
120
121        DecimalFormat cust1 = new DecimalFormat(pattern, symbols);
122
123        // ======= Test clone(), assignment, and equality
124
125        logln("Testing clone() and equality operators");
126
127        Format clone = (Format) def.clone();
128        if( ! def.equals(clone)) {
129            errln("ERROR: Clone() failed");
130        }
131
132        // ======= Test various format() methods
133
134        logln("Testing various format() methods");
135
136//        final double d = -10456.0037; // this appears as -10456.003700000001 on NT
137//        final double d = -1.04560037e-4; // this appears as -1.0456003700000002E-4 on NT
138        final double d = -10456.00370000000000; // this works!
139        final long l = 100000000;
140        logln("" + d + " is the double value");
141
142        StringBuffer res1 = new StringBuffer();
143        StringBuffer res2 = new StringBuffer();
144        StringBuffer res3 = new StringBuffer();
145        StringBuffer res4 = new StringBuffer();
146        FieldPosition pos1 = new FieldPosition(0);
147        FieldPosition pos2 = new FieldPosition(0);
148        FieldPosition pos3 = new FieldPosition(0);
149        FieldPosition pos4 = new FieldPosition(0);
150
151        res1 = def.format(d, res1, pos1);
152        logln("" + d + " formatted to " + res1);
153
154        res2 = pat.format(l, res2, pos2);
155        logln("" + l + " formatted to " + res2);
156
157        res3 = cust1.format(d, res3, pos3);
158        logln("" + d + " formatted to " + res3);
159
160        res4 = cust1.format(l, res4, pos4);
161        logln("" + l + " formatted to " + res4);
162
163        // ======= Test parse()
164
165        logln("Testing parse()");
166
167        String text = new String("-10,456.0037");
168        ParsePosition pos = new ParsePosition(0);
169        String patt = new String("#,##0.#");
170        pat.applyPattern(patt);
171        double d2 = pat.parse(text, pos).doubleValue();
172        if(d2 != d) {
173            errln("ERROR: Roundtrip failed (via parse(" + d2 + " != " + d + ")) for " + text);
174        }
175        logln(text + " parsed into " + (long) d2);
176
177        // ======= Test getters and setters
178
179        logln("Testing getters and setters");
180
181        final DecimalFormatSymbols syms = pat.getDecimalFormatSymbols();
182        def.setDecimalFormatSymbols(syms);
183        if( ! pat.getDecimalFormatSymbols().equals(def.getDecimalFormatSymbols())) {
184            errln("ERROR: set DecimalFormatSymbols() failed");
185        }
186
187        String posPrefix;
188        pat.setPositivePrefix("+");
189        posPrefix = pat.getPositivePrefix();
190        logln("Positive prefix (should be +): " + posPrefix);
191        if(posPrefix != "+") {
192            errln("ERROR: setPositivePrefix() failed");
193        }
194
195        String negPrefix;
196        pat.setNegativePrefix("-");
197        negPrefix = pat.getNegativePrefix();
198        logln("Negative prefix (should be -): " + negPrefix);
199        if(negPrefix != "-") {
200            errln("ERROR: setNegativePrefix() failed");
201        }
202
203        String posSuffix;
204        pat.setPositiveSuffix("_");
205        posSuffix = pat.getPositiveSuffix();
206        logln("Positive suffix (should be _): " + posSuffix);
207        if(posSuffix != "_") {
208            errln("ERROR: setPositiveSuffix() failed");
209        }
210
211        String negSuffix;
212        pat.setNegativeSuffix("~");
213        negSuffix = pat.getNegativeSuffix();
214        logln("Negative suffix (should be ~): " + negSuffix);
215        if(negSuffix != "~") {
216            errln("ERROR: setNegativeSuffix() failed");
217        }
218
219        long multiplier = 0;
220        pat.setMultiplier(8);
221        multiplier = pat.getMultiplier();
222        logln("Multiplier (should be 8): " + multiplier);
223        if(multiplier != 8) {
224            errln("ERROR: setMultiplier() failed");
225        }
226
227        int groupingSize = 0;
228        pat.setGroupingSize(2);
229        groupingSize = pat.getGroupingSize();
230        logln("Grouping size (should be 2): " + (long) groupingSize);
231        if(groupingSize != 2) {
232            errln("ERROR: setGroupingSize() failed");
233        }
234
235        pat.setDecimalSeparatorAlwaysShown(true);
236        boolean tf = pat.isDecimalSeparatorAlwaysShown();
237        logln("DecimalSeparatorIsAlwaysShown (should be true) is " +  (tf ? "true" : "false"));
238        if(tf != true) {
239            errln("ERROR: setDecimalSeparatorAlwaysShown() failed");
240        }
241
242        String funkyPat;
243        funkyPat = pat.toPattern();
244        logln("Pattern is " + funkyPat);
245
246        String locPat;
247        locPat = pat.toLocalizedPattern();
248        logln("Localized pattern is " + locPat);
249
250        // ======= Test applyPattern()
251
252        logln("Testing applyPattern()");
253
254        String p1 = new String("#,##0.0#;(#,##0.0#)");
255        logln("Applying pattern " + p1);
256        pat.applyPattern(p1);
257        String s2;
258        s2 = pat.toPattern();
259        logln("Extracted pattern is " + s2);
260        if( ! s2.equals(p1) ) {
261            errln("ERROR: toPattern() result did not match pattern applied");
262        }
263
264        String p2 = new String("#,##0.0# FF;(#,##0.0# FF)");
265        logln("Applying pattern " + p2);
266        pat.applyLocalizedPattern(p2);
267        String s3;
268        s3 = pat.toLocalizedPattern();
269        logln("Extracted pattern is " + s3);
270        if( ! s3.equals(p2) ) {
271            errln("ERROR: toLocalizedPattern() result did not match pattern applied");
272        }
273    }
274
275    @Test
276    public void testJB6134()
277    {
278        DecimalFormat decfmt = new DecimalFormat();
279        StringBuffer buf = new StringBuffer();
280
281        FieldPosition fposByInt = new FieldPosition(NumberFormat.INTEGER_FIELD);
282        decfmt.format(123, buf, fposByInt);
283
284        buf.setLength(0);
285        FieldPosition fposByField = new FieldPosition(NumberFormat.Field.INTEGER);
286        decfmt.format(123, buf, fposByField);
287
288        if (fposByInt.getEndIndex() != fposByField.getEndIndex())
289        {
290            errln("ERROR: End index for integer field - fposByInt:" + fposByInt.getEndIndex() +
291                " / fposByField: " + fposByField.getEndIndex());
292        }
293    }
294
295    @Test
296    public void testJB4971()
297    {
298        DecimalFormat decfmt = new DecimalFormat();
299        MathContext resultICU;
300
301        MathContext comp1 = new MathContext(0, MathContext.PLAIN);
302        resultICU = decfmt.getMathContextICU();
303        if ((comp1.getDigits() != resultICU.getDigits()) ||
304            (comp1.getForm() != resultICU.getForm()) ||
305            (comp1.getLostDigits() != resultICU.getLostDigits()) ||
306            (comp1.getRoundingMode() != resultICU.getRoundingMode()))
307        {
308            errln("ERROR: Math context 1 not equal - result: " + resultICU.toString() +
309                " / expected: " + comp1.toString());
310        }
311
312        MathContext comp2 = new MathContext(5, MathContext.ENGINEERING);
313        decfmt.setMathContextICU(comp2);
314        resultICU = decfmt.getMathContextICU();
315        if ((comp2.getDigits() != resultICU.getDigits()) ||
316            (comp2.getForm() != resultICU.getForm()) ||
317            (comp2.getLostDigits() != resultICU.getLostDigits()) ||
318            (comp2.getRoundingMode() != resultICU.getRoundingMode()))
319        {
320            errln("ERROR: Math context 2 not equal - result: " + resultICU.toString() +
321                " / expected: " + comp2.toString());
322        }
323
324        java.math.MathContext result;
325
326        java.math.MathContext comp3 = new java.math.MathContext(3, java.math.RoundingMode.DOWN);
327        decfmt.setMathContext(comp3);
328        result = decfmt.getMathContext();
329        if ((comp3.getPrecision() != result.getPrecision()) ||
330            (comp3.getRoundingMode() != result.getRoundingMode()))
331        {
332            errln("ERROR: Math context 3 not equal - result: " + result.toString() +
333                " / expected: " + comp3.toString());
334        }
335
336    }
337
338    @Test
339    public void testJB6354()
340    {
341        DecimalFormat pat = new DecimalFormat("#,##0.00");
342        java.math.BigDecimal r1, r2;
343
344        // get default rounding increment
345        r1 = pat.getRoundingIncrement();
346
347        // set rounding mode with zero increment.  Rounding
348        // increment should be set by this operation
349        pat.setRoundingMode(BigDecimal.ROUND_UP);
350        r2 = pat.getRoundingIncrement();
351
352        // check for different values
353        if ((r1 != null) && (r2 != null))
354        {
355            if (r1.compareTo(r2) == 0)
356            {
357                errln("ERROR: Rounding increment did not change");
358            }
359        }
360    }
361
362    @Test
363    public void testJB6648()
364    {
365        DecimalFormat df = new DecimalFormat();
366        df.setParseStrict(true);
367
368        String numstr = new String();
369
370        String[] patterns = {
371            "0",
372            "00",
373            "000",
374            "0,000",
375            "0.0",
376            "#000.0"
377        };
378
379        for(int i=0; i < patterns.length; i++) {
380            df.applyPattern(patterns[i]);
381            numstr = df.format(5);
382            try {
383                Number n = df.parse(numstr);
384                logln("INFO: Parsed " + numstr + " -> " + n);
385            } catch (ParseException pe) {
386                errln("ERROR: Failed round trip with strict parsing.");
387            }
388        }
389
390        df.applyPattern(patterns[1]);
391        numstr = "005";
392        try {
393            Number n = df.parse(numstr);
394            logln("INFO: Successful parse for " + numstr + " with strict parse enabled. Number is " + n);
395        } catch (ParseException pe) {
396            errln("ERROR: Parse Exception encountered in strict mode: numstr -> " + numstr);
397        }
398
399    }
400}
401