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