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