1 /* 2 * Copyright (c) 1997, 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 4052223 4059870 4061302 4062486 4066646 4068693 4070798 4071005 4071014 27 * 4071492 4071859 4074454 4074620 4075713 4083018 4086575 4087244 4087245 28 * 4087251 4087535 4088161 4088503 4090489 4090504 4092480 4092561 4095713 29 * 4098741 4099404 4101481 4106658 4106662 4106664 4108738 4110936 4122840 30 * 4125885 4134034 4134300 4140009 4141750 4145457 4147295 4147706 4162198 31 * 4162852 4167494 4170798 4176114 4179818 4185761 4212072 4212073 4216742 32 * 4217661 4243011 4243108 4330377 4233840 4241880 4833877 8008577 33 * @summary Regression tests for NumberFormat and associated classes 34 * @library /java/text/testlib 35 * @build IntlTest HexDumpReader TestUtils 36 * @modules java.base/sun.util.resources 37 * @compile -XDignore.symbol.file NumberRegression.java 38 * @run main/othervm -Djava.locale.providers=COMPAT,SPI NumberRegression 39 */ 40 41 /* 42 (C) Copyright Taligent, Inc. 1996 - All Rights Reserved 43 (C) Copyright IBM Corp. 1996 - All Rights Reserved 44 45 The original version of this source code and documentation is copyrighted and 46 owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are 47 provided under terms of a License Agreement between Taligent and Sun. This 48 technology is protected by multiple US and International patents. This notice and 49 attribution to Taligent may not be removed. 50 Taligent is a registered trademark of Taligent, Inc. 51 */ 52 53 import java.text.*; 54 import java.util.*; 55 import java.math.BigDecimal; 56 import java.io.*; 57 import java.math.BigInteger; 58 import sun.util.resources.LocaleData; 59 60 public class NumberRegression extends IntlTest { 61 62 public static void main(String[] args) throws Exception { 63 new NumberRegression().run(args); 64 } 65 66 /** 67 * NumberFormat.equals comparing with null should always return false. 68 */ 69 public void Test4075713(){ 70 71 try { 72 MyNumberFormatTest tmp = new MyNumberFormatTest(); 73 if (!tmp.equals(null)) 74 logln("NumberFormat.equals passed"); 75 } catch (NullPointerException e) { 76 errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception"); 77 } 78 } 79 80 /** 81 * NumberFormat.equals comparing two obj equal even the setGroupingUsed 82 * flag is different. 83 */ 84 public void Test4074620() { 85 86 MyNumberFormatTest nf1 = new MyNumberFormatTest(); 87 MyNumberFormatTest nf2 = new MyNumberFormatTest(); 88 89 nf1.setGroupingUsed(false); 90 nf2.setGroupingUsed(true); 91 92 if (nf1.equals(nf2)) errln("Test for bug 4074620 failed"); 93 else logln("Test for bug 4074620 passed."); 94 return; 95 } 96 97 98 /** 99 * DecimalFormat.format() incorrectly uses maxFractionDigits setting. 100 */ 101 102 public void Test4088161 (){ 103 Locale locale = Locale.getDefault(); 104 if (!TestUtils.usesAsciiDigits(locale)) { 105 logln("Skipping this test because locale is " + locale); 106 return; 107 } 108 109 DecimalFormat df = new DecimalFormat(); 110 double d = 100; 111 df.setMinimumFractionDigits(0); 112 df.setMaximumFractionDigits(16); 113 StringBuffer sBuf1 = new StringBuffer(""); 114 FieldPosition fp1 = new FieldPosition(0); 115 logln("d = " + d); 116 logln("maxFractionDigits = " + df.getMaximumFractionDigits()); 117 logln(" format(d) = '" + df.format(d, sBuf1, fp1) + "'"); 118 df.setMaximumFractionDigits(17); 119 StringBuffer sBuf2 = new StringBuffer(""); 120 FieldPosition fp2 = new FieldPosition(0); 121 logln("maxFractionDigits = " + df.getMaximumFractionDigits()); 122 df.format(d, sBuf2, fp2); 123 String expected = "100"; 124 if (!sBuf2.toString().equals(expected)) 125 errln(" format(d) = '" + sBuf2 + "'"); 126 } 127 /** 128 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat. 129 * DecimalFormat(String, DecimalFormatSymbols). 130 */ 131 public void Test4087245 (){ 132 DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(); 133 DecimalFormat df = new DecimalFormat("#,##0.0", symbols); 134 long n = 123; 135 StringBuffer buf1 = new StringBuffer(); 136 StringBuffer buf2 = new StringBuffer(); 137 logln("format(" + n + ") = " + 138 df.format(n, buf1, new FieldPosition(0))); 139 symbols.setDecimalSeparator('p'); // change value of field 140 logln("format(" + n + ") = " + 141 df.format(n, buf2, new FieldPosition(0))); 142 if (!buf1.toString().equals(buf2.toString())) 143 errln("Test for bug 4087245 failed"); 144 } 145 /** 146 * DecimalFormat.format() incorrectly formats 0.0 147 */ 148 public void Test4087535 () 149 { 150 DecimalFormat df = new DecimalFormat(); 151 df.setMinimumIntegerDigits(0); 152 153 double n = 0; 154 String buffer = new String(); 155 buffer = df.format(n); 156 if (buffer.length() == 0) 157 errln(n + ": '" + buffer + "'"); 158 n = 0.1; 159 buffer = df.format(n); 160 if (buffer.length() == 0) 161 errln(n + ": '" + buffer + "'"); 162 } 163 164 /** 165 * DecimalFormat.format fails when groupingSize is set to 0. 166 */ 167 public void Test4088503 (){ 168 DecimalFormat df = new DecimalFormat(); 169 df.setGroupingSize(0); 170 StringBuffer sBuf = new StringBuffer(""); 171 FieldPosition fp = new FieldPosition(0); 172 try { 173 logln(df.format(123, sBuf, fp).toString()); 174 } catch (Exception foo) { 175 errln("Test for bug 4088503 failed."); 176 } 177 178 } 179 /** 180 * NumberFormat.getCurrencyInstance is wrong. 181 */ 182 public void Test4066646 () { 183 float returnfloat = 0.0f; 184 assignFloatValue(2.04f); 185 assignFloatValue(2.03f); 186 assignFloatValue(2.02f); 187 assignFloatValue(0.0f); 188 } 189 190 public float assignFloatValue(float returnfloat) 191 { 192 logln(" VALUE " + returnfloat); 193 NumberFormat nfcommon = NumberFormat.getCurrencyInstance(Locale.US); 194 nfcommon.setGroupingUsed(false); 195 196 String stringValue = nfcommon.format(returnfloat).substring(1); 197 if (Float.valueOf(stringValue).floatValue() != returnfloat) 198 errln(" DISPLAYVALUE " + stringValue); 199 return returnfloat; 200 } // End Of assignFloatValue() 201 202 /** 203 * DecimalFormat throws exception when parsing "0" 204 */ 205 public void Test4059870() { 206 DecimalFormat format = new DecimalFormat("00"); 207 try { 208 logln(format.parse("0").toString()); 209 } catch (Exception e) { errln("Test for bug 4059870 failed : " + e); } 210 } 211 /** 212 * DecimalFormatSymbol.equals should always return false when 213 * comparing with null. 214 */ 215 216 public void Test4083018 (){ 217 DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(); 218 try { 219 if (!dfs.equals(null)) 220 logln("Test Passed!"); 221 } catch (Exception foo) { 222 errln("Test for bug 4083018 failed => Message : " + foo.getMessage()); 223 } 224 } 225 /** 226 * DecimalFormat does not round up correctly. 227 */ 228 public void Test4071492 (){ 229 Locale savedLocale = Locale.getDefault(); 230 Locale.setDefault(Locale.US); 231 double x = 0.00159999; 232 NumberFormat nf = NumberFormat.getInstance(); 233 nf.setMaximumFractionDigits(4); 234 String out = nf.format(x); 235 logln("0.00159999 formats with 4 fractional digits to " + out); 236 String expected = "0.0016"; 237 if (!out.equals(expected)) 238 errln("FAIL: Expected " + expected); 239 Locale.setDefault(savedLocale); 240 } 241 242 /** 243 * A space as a group separator for localized pattern causes 244 * wrong format. WorkAround : use non-breaking space. 245 */ 246 public void Test4086575() { 247 248 NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE); 249 logln("nf toPattern1: " + ((DecimalFormat)nf).toPattern()); 250 logln("nf toLocPattern1: " + ((DecimalFormat)nf).toLocalizedPattern()); 251 252 // No group separator 253 logln("...applyLocalizedPattern ###,00;(###,00) "); 254 ((DecimalFormat)nf).applyLocalizedPattern("###,00;(###,00)"); 255 logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern()); 256 logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern()); 257 258 logln("nf: " + nf.format(1234)); // 1234,00 259 logln("nf: " + nf.format(-1234)); // (1234,00) 260 261 // Space as group separator 262 263 logln("...applyLocalizedPattern # ###,00;(# ###,00) "); 264 ((DecimalFormat)nf).applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)"); 265 logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern()); 266 logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern()); 267 String buffer = nf.format(1234); 268 if (!buffer.equals("1\u00a0234,00")) 269 errln("nf : " + buffer); // Expect 1 234,00 270 buffer = nf.format(-1234); 271 if (!buffer.equals("(1\u00a0234,00)")) 272 errln("nf : " + buffer); // Expect (1 234,00) 273 274 // Erroneously prints: 275 // 1234,00 , 276 // (1234,00 ,) 277 278 } 279 /** 280 * DecimalFormat.parse returns wrong value 281 */ 282 public void Test4068693() 283 { 284 Locale savedLocale = Locale.getDefault(); 285 Locale.setDefault(Locale.US); 286 logln("----- Test Application -----"); 287 ParsePosition pos; 288 DecimalFormat df = new DecimalFormat(); 289 Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0)); 290 if (!d.toString().equals("123.55456")) { 291 errln("Result -> " + d.doubleValue()); 292 } 293 Locale.setDefault(savedLocale); 294 } 295 296 /* bugs 4069754, 4067878 297 * null pointer thrown when accessing a deserialized DecimalFormat 298 * object. 299 */ 300 public void Test4069754() 301 { 302 try { 303 myformat it = new myformat(); 304 logln(it.Now()); 305 FileOutputStream ostream = new FileOutputStream("t.tmp"); 306 ObjectOutputStream p = new ObjectOutputStream(ostream); 307 p.writeObject(it); 308 ostream.close(); 309 logln("Saved ok."); 310 311 FileInputStream istream = new FileInputStream("t.tmp"); 312 ObjectInputStream p2 = new ObjectInputStream(istream); 313 myformat it2 = (myformat)p2.readObject(); 314 logln(it2.Now()); 315 istream.close(); 316 logln("Loaded ok."); 317 } catch (Exception foo) { 318 errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage()); 319 } 320 } 321 322 /** 323 * DecimalFormat.applyPattern(String) allows illegal patterns 324 */ 325 public void Test4087251 (){ 326 DecimalFormat df = new DecimalFormat(); 327 try { 328 df.applyPattern("#.#.#"); 329 logln("toPattern() returns \"" + df.toPattern() + "\""); 330 errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException"); 331 } catch (IllegalArgumentException e) { 332 logln("Caught Illegal Argument Error !"); 333 } 334 // Second test; added 5/11/98 when reported to fail on 1.2b3 335 try { 336 df.applyPattern("#0.0#0#0"); 337 logln("toPattern() returns \"" + df.toPattern() + "\""); 338 errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException"); 339 } catch (IllegalArgumentException e) { 340 logln("Ok - IllegalArgumentException for #0.0#0#0"); 341 } 342 } 343 344 /** 345 * DecimalFormat.format() loses precision 346 */ 347 public void Test4090489 (){ 348 Locale savedLocale = Locale.getDefault(); 349 Locale.setDefault(Locale.US); 350 DecimalFormat df = new DecimalFormat(); 351 df.setMinimumFractionDigits(10); 352 df.setGroupingUsed(false); 353 double d = 1.000000000000001E7; 354 BigDecimal bd = new BigDecimal(d); 355 StringBuffer sb = new StringBuffer(""); 356 FieldPosition fp = new FieldPosition(0); 357 logln("d = " + d); 358 logln("BigDecimal.toString(): " + bd.toString()); 359 df.format(d, sb, fp); 360 if (!sb.toString().equals("10000000.0000000100")) { 361 errln("DecimalFormat.format(): " + sb.toString()); 362 } 363 Locale.setDefault(savedLocale); 364 } 365 366 /** 367 * DecimalFormat.format() loses precision 368 */ 369 public void Test4090504 () 370 { 371 double d = 1; 372 logln("d = " + d); 373 DecimalFormat df = new DecimalFormat(); 374 StringBuffer sb; 375 FieldPosition fp; 376 try { 377 for (int i = 17; i <= 20; i++) { 378 df.setMaximumFractionDigits(i); 379 sb = new StringBuffer(""); 380 fp = new FieldPosition(0); 381 logln(" getMaximumFractionDigits() = " + i); 382 logln(" formated: " + df.format(d, sb, fp)); 383 } 384 } catch (Exception foo) { 385 errln("Bug 4090504 regression test failed. Message : " + foo.getMessage()); 386 } 387 } 388 /** 389 * DecimalFormat.parse(String str, ParsePosition pp) loses precision 390 */ 391 public void Test4095713 () 392 { 393 Locale savedLocale = Locale.getDefault(); 394 Locale.setDefault(Locale.US); 395 DecimalFormat df = new DecimalFormat(); 396 String str = "0.1234"; 397 Double d1 = new Double(str); 398 Double d2 = (Double) df.parse(str, new ParsePosition(0)); 399 logln(d1.toString()); 400 if (d2.doubleValue() != d1.doubleValue()) 401 errln("Bug 4095713 test failed, new double value : " + d2.doubleValue()); 402 Locale.setDefault(savedLocale); 403 } 404 405 /** 406 * DecimalFormat.parse() fails when multiplier is not set to 1 407 */ 408 public void Test4092561 () 409 { 410 Locale savedLocale = Locale.getDefault(); 411 Locale.setDefault(Locale.US); 412 DecimalFormat df = new DecimalFormat(); 413 414 String str = Long.toString(Long.MIN_VALUE); 415 logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString()); 416 df.setMultiplier(100); 417 Number num = df.parse(str, new ParsePosition(0)); 418 if (num.doubleValue() != -9.223372036854776E16) { 419 errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: -9.223372036854776E16, got: " + num.doubleValue()); 420 } 421 422 df.setMultiplier(-100); 423 num = df.parse(str, new ParsePosition(0)); 424 if (num.doubleValue() != 9.223372036854776E16) { 425 errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: 9.223372036854776E16, got: " + num.doubleValue()); 426 } 427 428 str = Long.toString(Long.MAX_VALUE); 429 logln("Long.MAX_VALUE : " + df.parse(str, new ParsePosition(0)).toString()); 430 431 df.setMultiplier(100); 432 num = df.parse(str, new ParsePosition(0)); 433 if (num.doubleValue() != 9.223372036854776E16) { 434 errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: 9.223372036854776E16, got: " + num.doubleValue()); 435 } 436 437 df.setMultiplier(-100); 438 num = df.parse(str, new ParsePosition(0)); 439 if (num.doubleValue() != -9.223372036854776E16) { 440 errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: -9.223372036854776E16, got: " + num.doubleValue()); 441 } 442 443 Locale.setDefault(savedLocale); 444 } 445 446 /** 447 * DecimalFormat: Negative format ignored. 448 */ 449 public void Test4092480 () 450 { 451 DecimalFormat dfFoo = new DecimalFormat("000"); 452 453 try { 454 dfFoo.applyPattern("0000;-000"); 455 if (!dfFoo.toPattern().equals("#0000")) 456 errln("dfFoo.toPattern : " + dfFoo.toPattern()); 457 logln(dfFoo.format(42)); 458 logln(dfFoo.format(-42)); 459 dfFoo.applyPattern("000;-000"); 460 if (!dfFoo.toPattern().equals("#000")) 461 errln("dfFoo.toPattern : " + dfFoo.toPattern()); 462 logln(dfFoo.format(42)); 463 logln(dfFoo.format(-42)); 464 465 dfFoo.applyPattern("000;-0000"); 466 if (!dfFoo.toPattern().equals("#000")) 467 errln("dfFoo.toPattern : " + dfFoo.toPattern()); 468 logln(dfFoo.format(42)); 469 logln(dfFoo.format(-42)); 470 471 dfFoo.applyPattern("0000;-000"); 472 if (!dfFoo.toPattern().equals("#0000")) 473 errln("dfFoo.toPattern : " + dfFoo.toPattern()); 474 logln(dfFoo.format(42)); 475 logln(dfFoo.format(-42)); 476 } catch (Exception foo) { 477 errln("Message " + foo.getMessage()); 478 } 479 } 480 /** 481 * NumberFormat.getCurrencyInstance() produces format that uses 482 * decimal separator instead of monetary decimal separator. 483 * 484 * Rewrote this test not to depend on the actual pattern. Pattern should 485 * never contain the monetary separator! Decimal separator in pattern is 486 * interpreted as monetary separator if currency symbol is seen! 487 */ 488 public void Test4087244 () { 489 Locale de = new Locale("pt", "PT"); 490 DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(de); 491 DecimalFormatSymbols sym = df.getDecimalFormatSymbols(); 492 sym.setMonetaryDecimalSeparator('$'); 493 df.setDecimalFormatSymbols(sym); 494 char decSep = sym.getDecimalSeparator(); 495 char monSep = sym.getMonetaryDecimalSeparator(); 496 char zero = sym.getZeroDigit(); 497 if (decSep == monSep) { 498 errln("ERROR in test: want decimal sep != monetary sep"); 499 } else { 500 df.setMinimumIntegerDigits(1); 501 df.setMinimumFractionDigits(2); 502 String str = df.format(1.23); 503 String monStr = "1" + monSep + "23"; 504 String decStr = "1" + decSep + "23"; 505 if (str.indexOf(monStr) >= 0 && str.indexOf(decStr) < 0) { 506 logln("OK: 1.23 -> \"" + str + "\" contains \"" + 507 monStr + "\" and not \"" + decStr + '"'); 508 } else { 509 errln("FAIL: 1.23 -> \"" + str + "\", should contain \"" + 510 monStr + 511 "\" and not \"" + decStr + '"'); 512 } 513 } 514 } 515 /** 516 * Number format data rounding errors for locale FR 517 */ 518 public void Test4070798 () { 519 NumberFormat formatter; 520 String tempString; 521 /* User error : 522 String expectedDefault = "-5\u00a0789,987"; 523 String expectedCurrency = "5\u00a0789,98 F"; 524 String expectedPercent = "-578\u00a0998%"; 525 */ 526 String expectedDefault = "-5\u00a0789,988"; 527 String expectedCurrency = "5\u00a0789,99 \u20AC"; 528 // changed for bug 6547501 529 String expectedPercent = "-578\u00a0999 %"; 530 531 formatter = NumberFormat.getNumberInstance(Locale.FRANCE); 532 tempString = formatter.format (-5789.9876); 533 534 if (tempString.equals(expectedDefault)) { 535 logln ("Bug 4070798 default test passed."); 536 } else { 537 errln("Failed:" + 538 " Expected " + expectedDefault + 539 " Received " + tempString ); 540 } 541 542 543 formatter = NumberFormat.getCurrencyInstance(Locale.FRANCE); 544 tempString = formatter.format( 5789.9876 ); 545 546 if (tempString.equals(expectedCurrency) ) { 547 logln ("Bug 4070798 currency test assed."); 548 } else { 549 errln("Failed:" + 550 " Expected " + expectedCurrency + 551 " Received " + tempString ); 552 } 553 554 555 formatter = NumberFormat.getPercentInstance(Locale.FRANCE); 556 tempString = formatter.format (-5789.9876); 557 558 if (tempString.equals(expectedPercent) ) { 559 logln ("Bug 4070798 percentage test passed."); 560 } else { 561 errln("Failed:" + 562 " Expected " + expectedPercent + 563 " Received " + tempString ); 564 } 565 } 566 /** 567 * Data rounding errors for French (Canada) locale 568 */ 569 public void Test4071005 () { 570 571 NumberFormat formatter; 572 String tempString; 573 /* user error : 574 String expectedDefault = "-5 789,987"; 575 String expectedCurrency = "5 789,98 $"; 576 String expectedPercent = "-578 998%"; 577 */ 578 String expectedDefault = "-5\u00a0789,988"; 579 String expectedCurrency = "5\u00a0789,99 $"; 580 // changed for bug 6547501 581 String expectedPercent = "-578\u00a0999 %"; 582 583 formatter = NumberFormat.getNumberInstance(Locale.CANADA_FRENCH); 584 tempString = formatter.format (-5789.9876); 585 if (tempString.equals(expectedDefault)) { 586 logln ("Bug 4071005 default test passed."); 587 } else { 588 errln("Failed:" + 589 " Expected " + expectedDefault + 590 " Received " + tempString ); 591 } 592 593 formatter = NumberFormat.getCurrencyInstance(Locale.CANADA_FRENCH); 594 tempString = formatter.format( 5789.9876 ) ; 595 596 if (tempString.equals(expectedCurrency) ) { 597 logln ("Bug 4071005 currency test passed."); 598 } else { 599 errln("Failed:" + 600 " Expected " + expectedCurrency + 601 " Received " + tempString ); 602 } 603 formatter = NumberFormat.getPercentInstance(Locale.CANADA_FRENCH); 604 tempString = formatter.format (-5789.9876); 605 606 if (tempString.equals(expectedPercent) ) { 607 logln ("Bug 4071005 percentage test passed."); 608 } else { 609 errln("Failed:" + 610 " Expected " + expectedPercent + 611 " Received " + tempString ); 612 } 613 } 614 615 /** 616 * Data rounding errors for German (Germany) locale 617 */ 618 public void Test4071014 () { 619 NumberFormat formatter; 620 String tempString; 621 /* user error : 622 String expectedDefault = "-5.789,987"; 623 String expectedCurrency = "5.789,98 DM"; 624 String expectedPercent = "-578.998%"; 625 */ 626 String expectedDefault = "-5.789,988"; 627 String expectedCurrency = "5.789,99 \u20AC"; 628 String expectedPercent = "-578.999%"; 629 630 formatter = NumberFormat.getNumberInstance(Locale.GERMANY); 631 tempString = formatter.format (-5789.9876); 632 633 if (tempString.equals(expectedDefault)) { 634 logln ("Bug 4071014 default test passed."); 635 } else { 636 errln("Failed:" + 637 " Expected " + expectedDefault + 638 " Received " + tempString ); 639 } 640 641 formatter = NumberFormat.getCurrencyInstance(Locale.GERMANY); 642 tempString = formatter.format( 5789.9876 ) ; 643 644 if (tempString.equals(expectedCurrency) ) { 645 logln ("Bug 4071014 currency test passed."); 646 } else { 647 errln("Failed:" + 648 " Expected " + expectedCurrency + 649 " Received " + tempString ); 650 } 651 652 formatter = NumberFormat.getPercentInstance(Locale.GERMANY); 653 tempString = formatter.format (-5789.9876); 654 655 if (tempString.equals(expectedPercent) ) { 656 logln ("Bug 4071014 percentage test passed."); 657 } else { 658 errln("Failed:" + 659 " Expected " + expectedPercent + 660 " Received " + tempString ); 661 } 662 663 } 664 /** 665 * Data rounding errors for Italian locale number formats 666 */ 667 public void Test4071859 () { 668 NumberFormat formatter; 669 String tempString; 670 /* user error : 671 String expectedDefault = "-5.789,987"; 672 String expectedCurrency = "-L. 5.789,98"; 673 String expectedPercent = "-578.998%"; 674 */ 675 String expectedDefault = "-5.789,988"; 676 String expectedCurrency = "-\u20AC 5.789,99"; 677 String expectedPercent = "-578.999%"; 678 679 formatter = NumberFormat.getNumberInstance(Locale.ITALY); 680 tempString = formatter.format (-5789.9876); 681 682 if (tempString.equals(expectedDefault)) { 683 logln ("Bug 4071859 default test passed."); 684 } else { 685 errln("Failed:" + 686 " Expected " + expectedDefault + 687 " Received " + tempString ); 688 } 689 690 formatter = NumberFormat.getCurrencyInstance(Locale.ITALY); 691 tempString = formatter.format( -5789.9876 ) ; 692 693 if (tempString.equals(expectedCurrency) ) { 694 logln ("Bug 4071859 currency test passed."); 695 } else { 696 errln("Failed:" + 697 " Expected " + expectedCurrency + 698 " Received " + tempString ); 699 } 700 701 formatter = NumberFormat.getPercentInstance(Locale.ITALY); 702 tempString = formatter.format (-5789.9876); 703 704 if (tempString.equals(expectedPercent) ) { 705 logln ("Bug 4071859 percentage test passed."); 706 } else { 707 errln("Failed:" + 708 " Expected " + expectedPercent + 709 " Received " + tempString ); 710 } 711 712 } 713 714 /* bug 4071859 715 * Test rounding for nearest even. 716 */ 717 public void Test4093610() 718 { 719 Locale savedLocale = Locale.getDefault(); 720 Locale.setDefault(Locale.US); 721 DecimalFormat df = new DecimalFormat("#0.#"); 722 723 roundingTest(df, 12.15, "12.2"); // Rounding-up. Above tie (12.150..) 724 roundingTest(df, 12.25, "12.2"); // No round-up. Exact + half-even rule. 725 roundingTest(df, 12.45, "12.4"); // No round-up. Below tie (12.449..) 726 roundingTest(df, 12.450000001,"12.5"); // Rounding-up. Above tie. 727 roundingTest(df, 12.55, "12.6"); // Rounding-up. Above tie (12.550..) 728 roundingTest(df, 12.650000001,"12.7"); // Rounding-up. Above tie. 729 roundingTest(df, 12.75, "12.8"); // Rounding-up. Exact + half-even rule. 730 roundingTest(df, 12.750000001,"12.8"); // Rounding-up. Above tie. 731 roundingTest(df, 12.85, "12.8"); // No round-up. Below tie (12.849..) 732 roundingTest(df, 12.850000001,"12.9"); // Rounding-up. Above tie. 733 roundingTest(df, 12.950000001,"13"); // Rounding-up. Above tie. 734 735 Locale.setDefault(savedLocale); 736 } 737 738 void roundingTest(DecimalFormat df, double x, String expected) 739 { 740 String out = df.format(x); 741 logln("" + x + " formats with 1 fractional digits to " + out); 742 if (!out.equals(expected)) errln("FAIL: Expected " + expected); 743 } 744 /** 745 * Tests the setMaximumFractionDigits limit. 746 */ 747 public void Test4098741() 748 { 749 try { 750 NumberFormat fmt = NumberFormat.getPercentInstance(); 751 fmt.setMaximumFractionDigits(20); 752 logln(fmt.format(.001)); 753 } catch (Exception foo) { 754 errln("Bug 4098471 failed with exception thrown : " + foo.getMessage()); 755 } 756 } 757 /** 758 * Tests illegal pattern exception. 759 * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated. 760 * Part2 has been fixed. 761 */ 762 public void Test4074454() 763 { 764 Locale savedLocale = Locale.getDefault(); 765 Locale.setDefault(Locale.US); 766 try { 767 DecimalFormat fmt = new DecimalFormat("#,#00.00;-#.#"); 768 logln("Inconsistent negative pattern is fine."); 769 DecimalFormat newFmt = new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces"); 770 String tempString = newFmt.format(3456.78); 771 if (!tempString.equals("3,456.78 p'ieces")) 772 errln("Failed! 3,456.78 p'ieces expected, but got : " + tempString); 773 } catch (Exception foo) { 774 errln("An exception was thrown for any inconsistent negative pattern."); 775 } 776 Locale.setDefault(savedLocale); 777 } 778 779 /** 780 * Tests all different comments. 781 * Response to some comments : 782 * [1] DecimalFormat.parse API documentation is more than just one line. 783 * This is not a reproducable doc error in 116 source code. 784 * [2] See updated javadoc. 785 * [3] Fixed. 786 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails, 787 * a null object will be returned. The unchanged parse position also 788 * reflects an error. 789 * NumberFormat.parse(String) : If parsing fails, an ParseException 790 * will be thrown. 791 * See updated javadoc for more details. 792 * [5] See updated javadoc. 793 * [6] See updated javadoc. 794 * [7] This is a correct behavior if the DateFormat object is linient. 795 * Otherwise, an IllegalArgumentException will be thrown when formatting 796 * "January 35". See GregorianCalendar class javadoc for more details. 797 */ 798 public void Test4099404() 799 { 800 try { 801 DecimalFormat fmt = new DecimalFormat("000.0#0"); 802 errln("Bug 4099404 failed applying illegal pattern \"000.0#0\""); 803 } catch (Exception foo) { 804 logln("Bug 4099404 pattern \"000.0#0\" passed"); 805 } 806 try { 807 DecimalFormat fmt = new DecimalFormat("0#0.000"); 808 errln("Bug 4099404 failed applying illegal pattern \"0#0.000\""); 809 } catch (Exception foo) { 810 logln("Bug 4099404 pattern \"0#0.000\" passed"); 811 } 812 } 813 /** 814 * DecimalFormat.applyPattern doesn't set minimum integer digits 815 */ 816 public void Test4101481() 817 { 818 DecimalFormat sdf = new DecimalFormat("#,##0"); 819 if (sdf.getMinimumIntegerDigits() != 1) 820 errln("Minimum integer digits : " + sdf.getMinimumIntegerDigits()); 821 } 822 /** 823 * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition(). 824 */ 825 public void Test4052223() 826 { 827 try { 828 DecimalFormat fmt = new DecimalFormat("#,#00.00"); 829 Number num = fmt.parse("abc3"); 830 errln("Bug 4052223 failed : can't parse string \"a\". Got " + num); 831 } catch (ParseException foo) { 832 logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset()); 833 } 834 } 835 /** 836 * API tests for API addition request A9. 837 */ 838 public void Test4061302() 839 { 840 DecimalFormatSymbols fmt = DecimalFormatSymbols.getInstance(); 841 String currency = fmt.getCurrencySymbol(); 842 String intlCurrency = fmt.getInternationalCurrencySymbol(); 843 char monDecSeparator = fmt.getMonetaryDecimalSeparator(); 844 if (currency.equals("") || 845 intlCurrency.equals("") || 846 monDecSeparator == 0) { 847 errln("getCurrencySymbols failed, got empty string."); 848 } 849 logln("Before set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator); 850 fmt.setCurrencySymbol("XYZ"); 851 fmt.setInternationalCurrencySymbol("ABC"); 852 fmt.setMonetaryDecimalSeparator('*'); 853 currency = fmt.getCurrencySymbol(); 854 intlCurrency = fmt.getInternationalCurrencySymbol(); 855 monDecSeparator = fmt.getMonetaryDecimalSeparator(); 856 if (!currency.equals("XYZ") || 857 !intlCurrency.equals("ABC") || 858 monDecSeparator != '*') { 859 errln("setCurrencySymbols failed."); 860 } 861 logln("After set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator); 862 } 863 /** 864 * API tests for API addition request A23. FieldPosition.getBeginIndex and 865 * FieldPosition.getEndIndex. 866 */ 867 public void Test4062486() 868 { 869 DecimalFormat fmt = new DecimalFormat("#,##0.00"); 870 StringBuffer formatted = new StringBuffer(); 871 FieldPosition field = new FieldPosition(0); 872 Double num = new Double(1234.5); 873 fmt.format(num, formatted, field); 874 if (field.getBeginIndex() != 0 && field.getEndIndex() != 5) 875 errln("Format 1234.5 failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex()); 876 field.setBeginIndex(7); 877 field.setEndIndex(4); 878 if (field.getBeginIndex() != 7 && field.getEndIndex() != 4) 879 errln("Set begin/end field indexes failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex()); 880 } 881 882 /** 883 * DecimalFormat.parse incorrectly works with a group separator. 884 */ 885 public void Test4108738() 886 { 887 888 DecimalFormat df = new DecimalFormat("#,##0.###", 889 DecimalFormatSymbols.getInstance(java.util.Locale.US)); 890 String text = "1.222,111"; 891 Number num = df.parse(text,new ParsePosition(0)); 892 if (!num.toString().equals("1.222")) 893 errln("\"" + text + "\" is parsed as " + num); 894 text = "1.222x111"; 895 num = df.parse(text,new ParsePosition(0)); 896 if (!num.toString().equals("1.222")) 897 errln("\"" + text + "\" is parsed as " + num); 898 } 899 900 /** 901 * DecimalFormat.format() incorrectly formats negative doubles. 902 */ 903 public void Test4106658() 904 { 905 Locale savedLocale = Locale.getDefault(); 906 Locale.setDefault(Locale.US); 907 DecimalFormat df = new DecimalFormat(); // Corrected; see 4147706 908 double d1 = -0.0; 909 double d2 = -0.0001; 910 StringBuffer buffer = new StringBuffer(); 911 logln("pattern: \"" + df.toPattern() + "\""); 912 df.format(d1, buffer, new FieldPosition(0)); 913 if (!buffer.toString().equals("-0")) { // Corrected; see 4147706 914 errln(d1 + " is formatted as " + buffer); 915 } 916 buffer.setLength(0); 917 df.format(d2, buffer, new FieldPosition(0)); 918 if (!buffer.toString().equals("-0")) { // Corrected; see 4147706 919 errln(d2 + " is formatted as " + buffer); 920 } 921 Locale.setDefault(savedLocale); 922 } 923 924 /** 925 * DecimalFormat.parse returns 0 if string parameter is incorrect. 926 */ 927 public void Test4106662() 928 { 929 DecimalFormat df = new DecimalFormat(); 930 String text = "x"; 931 ParsePosition pos1 = new ParsePosition(0), pos2 = new ParsePosition(0); 932 933 logln("pattern: \"" + df.toPattern() + "\""); 934 Number num = df.parse(text, pos1); 935 if (num != null) { 936 errln("Test Failed: \"" + text + "\" is parsed as " + num); 937 } 938 df = null; 939 df = new DecimalFormat("$###.00"); 940 num = df.parse("$", pos2); 941 if (num != null){ 942 errln("Test Failed: \"$\" is parsed as " + num); 943 } 944 } 945 946 /** 947 * NumberFormat.parse doesn't return null 948 */ 949 public void Test4114639() 950 { 951 NumberFormat format = NumberFormat.getInstance(); 952 String text = "time 10:x"; 953 ParsePosition pos = new ParsePosition(8); 954 Number result = format.parse(text, pos); 955 if (result != null) errln("Should return null but got : " + result); // Should be null; it isn't 956 } 957 958 /** 959 * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG. 960 */ 961 public void Test4106664() 962 { 963 DecimalFormat df = new DecimalFormat(); 964 long n = 1234567890123456L; 965 int m = 12345678; 966 BigInteger bigN = BigInteger.valueOf(n); 967 bigN = bigN.multiply(BigInteger.valueOf(m)); 968 df.setMultiplier(m); 969 df.setGroupingUsed(false); 970 logln("formated: " + 971 df.format(n, new StringBuffer(), new FieldPosition(0))); 972 logln("expected: " + bigN.toString()); 973 } 974 /** 975 * DecimalFormat.format incorrectly formats -0.0. 976 */ 977 public void Test4106667() 978 { 979 Locale savedLocale = Locale.getDefault(); 980 Locale.setDefault(Locale.US); 981 DecimalFormat df = new DecimalFormat(); 982 df.setPositivePrefix("+"); 983 double d = -0.0; 984 logln("pattern: \"" + df.toPattern() + "\""); 985 StringBuffer buffer = new StringBuffer(); 986 df.format(d, buffer, new FieldPosition(0)); 987 if (!buffer.toString().equals("-0")) { // Corrected; see 4147706 988 errln(d + " is formatted as " + buffer); 989 } 990 Locale.setDefault(savedLocale); 991 } 992 993 /** 994 * DecimalFormat.setMaximumIntegerDigits() works incorrectly. 995 */ 996 public void Test4110936() 997 { 998 NumberFormat nf = NumberFormat.getInstance(); 999 nf.setMaximumIntegerDigits(128); 1000 logln("setMaximumIntegerDigits(128)"); 1001 if (nf.getMaximumIntegerDigits() != 128) 1002 errln("getMaximumIntegerDigits() returns " + 1003 nf.getMaximumIntegerDigits()); 1004 } 1005 1006 /** 1007 * Locale data should use generic currency symbol 1008 * 1009 * 1) Make sure that all currency formats use the generic currency symbol. 1010 * 2) Make sure we get the same results using the generic symbol or a 1011 * hard-coded one. 1012 */ 1013 public void Test4122840() 1014 { 1015 Locale[] locales = NumberFormat.getAvailableLocales(); 1016 1017 for (int i = 0; i < locales.length; i++) { 1018 ResourceBundle rb = LocaleData.getBundle("sun.text.resources.FormatData", 1019 locales[i]); 1020 // 1021 // Get the currency pattern for this locale. We have to fish it 1022 // out of the ResourceBundle directly, since DecimalFormat.toPattern 1023 // will return the localized symbol, not \00a4 1024 // 1025 String[] numPatterns = (String[])rb.getObject("NumberPatterns"); 1026 String pattern = numPatterns[1]; 1027 1028 if (pattern.indexOf("\u00A4") == -1 ) { 1029 errln("Currency format for " + locales[i] + 1030 " does not contain generic currency symbol:" + 1031 pattern ); 1032 } 1033 1034 // Create a DecimalFormat using the pattern we got and format a number 1035 DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locales[i]); 1036 DecimalFormat fmt1 = new DecimalFormat(pattern, symbols); 1037 1038 String result1 = fmt1.format(1.111); 1039 1040 // 1041 // Now substitute in the locale's currency symbol and create another 1042 // pattern. Replace the decimal separator with the monetary separator. 1043 // 1044 char decSep = symbols.getDecimalSeparator(); 1045 char monSep = symbols.getMonetaryDecimalSeparator(); 1046 StringBuffer buf = new StringBuffer(pattern); 1047 for (int j = 0; j < buf.length(); j++) { 1048 if (buf.charAt(j) == '\u00a4') { 1049 String cur = "'" + symbols.getCurrencySymbol() + "'"; 1050 buf.replace(j, j+1, cur); 1051 j += cur.length() - 1; 1052 } 1053 } 1054 symbols.setDecimalSeparator(monSep); 1055 DecimalFormat fmt2 = new DecimalFormat(buf.toString(), symbols); 1056 1057 String result2 = fmt2.format(1.111); 1058 1059 if (!result1.equals(result2)) { 1060 errln("Results for " + locales[i] + " differ: " + 1061 result1 + " vs " + result2); 1062 } 1063 } 1064 } 1065 1066 /** 1067 * DecimalFormat.format() delivers wrong string. 1068 */ 1069 public void Test4125885() 1070 { 1071 Locale savedLocale = Locale.getDefault(); 1072 Locale.setDefault(Locale.US); 1073 double rate = 12.34; 1074 DecimalFormat formatDec = new DecimalFormat ("000.00"); 1075 logln("toPattern: " + formatDec.toPattern()); 1076 String rateString= formatDec.format(rate); 1077 if (!rateString.equals("012.34")) 1078 errln("result : " + rateString + " expected : 012.34"); 1079 rate = 0.1234; 1080 formatDec = null; 1081 formatDec = new DecimalFormat ("+000.00%;-000.00%"); 1082 logln("toPattern: " + formatDec.toPattern()); 1083 rateString= formatDec.format(rate); 1084 if (!rateString.equals("+012.34%")) 1085 errln("result : " + rateString + " expected : +012.34%"); 1086 Locale.setDefault(savedLocale); 1087 } 1088 1089 /** 1090 ** 1091 * DecimalFormat produces extra zeros when formatting numbers. 1092 */ 1093 public void Test4134034() { 1094 Locale savedLocale = Locale.getDefault(); 1095 Locale.setDefault(Locale.US); 1096 DecimalFormat nf = new DecimalFormat("##,###,###.00"); 1097 1098 String f = nf.format(9.02); 1099 if (f.equals("9.02")) logln(f + " ok"); else errln("9.02 -> " + f + "; want 9.02"); 1100 1101 f = nf.format(0); 1102 if (f.equals(".00")) logln(f + " ok"); else errln("0 -> " + f + "; want .00"); 1103 Locale.setDefault(savedLocale); 1104 } 1105 1106 /** 1107 * CANNOT REPRODUCE - This bug could not be reproduced. It may be 1108 * a duplicate of 4134034. 1109 * 1110 * JDK 1.1.6 Bug, did NOT occur in 1.1.5 1111 * Possibly related to bug 4125885. 1112 * 1113 * This class demonstrates a regression in version 1.1.6 1114 * of DecimalFormat class. 1115 * 1116 * 1.1.6 Results 1117 * Value 1.2 Format #.00 Result '01.20' !!!wrong 1118 * Value 1.2 Format 0.00 Result '001.20' !!!wrong 1119 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong 1120 * Value 1.2 Format #0.0# Result '1.2' 1121 * Value 1.2 Format #0.00 Result '001.20' !!!wrong 1122 * 1123 * 1.1.5 Results 1124 * Value 1.2 Format #.00 Result '1.20' 1125 * Value 1.2 Format 0.00 Result '1.20' 1126 * Value 1.2 Format 00.00 Result '01.20' 1127 * Value 1.2 Format #0.0# Result '1.2' 1128 * Value 1.2 Format #0.00 Result '1.20' 1129 */ 1130 public void Test4134300() { 1131 Locale savedLocale = Locale.getDefault(); 1132 Locale.setDefault(Locale.US); 1133 String[] DATA = { 1134 // Pattern Expected string 1135 "#.00", "1.20", 1136 "0.00", "1.20", 1137 "00.00", "01.20", 1138 "#0.0#", "1.2", 1139 "#0.00", "1.20", 1140 }; 1141 for (int i=0; i<DATA.length; i+=2) { 1142 String result = new DecimalFormat(DATA[i]).format(1.2); 1143 if (!result.equals(DATA[i+1])) { 1144 errln("Fail: 1.2 x " + DATA[i] + " = " + result + 1145 "; want " + DATA[i+1]); 1146 } 1147 else { 1148 logln("Ok: 1.2 x " + DATA[i] + " = " + result); 1149 } 1150 } 1151 Locale.setDefault(savedLocale); 1152 } 1153 1154 /** 1155 * Empty pattern produces double negative prefix. 1156 */ 1157 public void Test4140009() { 1158 for (int i=0; i<2; ++i) { 1159 DecimalFormat f = null; 1160 switch (i) { 1161 case 0: 1162 f = new DecimalFormat("", 1163 DecimalFormatSymbols.getInstance(Locale.ENGLISH)); 1164 break; 1165 case 1: 1166 f = new DecimalFormat("#.#", 1167 DecimalFormatSymbols.getInstance(Locale.ENGLISH)); 1168 f.applyPattern(""); 1169 break; 1170 } 1171 String s = f.format(123.456); 1172 if (!s.equals("123.456")) 1173 errln("Fail: Format empty pattern x 123.456 => " + s); 1174 s = f.format(-123.456); 1175 if (!s.equals("-123.456")) 1176 errln("Fail: Format empty pattern x -123.456 => " + s); 1177 } 1178 } 1179 1180 /** 1181 * BigDecimal numbers get their fractions truncated by NumberFormat. 1182 */ 1183 public void Test4141750() { 1184 try { 1185 String str = "12345.67"; 1186 BigDecimal bd = new BigDecimal(str); 1187 NumberFormat nf = NumberFormat.getInstance(Locale.US); 1188 String sd = nf.format(bd); 1189 if (!sd.endsWith("67")) { 1190 errln("Fail: " + str + " x format -> " + sd); 1191 } 1192 } 1193 catch (Exception e) { 1194 errln(e.toString()); 1195 e.printStackTrace(); 1196 } 1197 } 1198 1199 /** 1200 * DecimalFormat toPattern() doesn't quote special characters or handle 1201 * single quotes. 1202 */ 1203 public void Test4145457() { 1204 try { 1205 DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance(); 1206 DecimalFormatSymbols sym = nf.getDecimalFormatSymbols(); 1207 sym.setDecimalSeparator('\''); 1208 nf.setDecimalFormatSymbols(sym); 1209 double pi = 3.14159; 1210 1211 String[] PATS = { "#.00 'num''ber'", "''#.00''" }; 1212 1213 for (int i=0; i<PATS.length; ++i) { 1214 nf.applyPattern(PATS[i]); 1215 String out = nf.format(pi); 1216 String pat = nf.toPattern(); 1217 double val = nf.parse(out).doubleValue(); 1218 1219 nf.applyPattern(pat); 1220 String out2 = nf.format(pi); 1221 String pat2 = nf.toPattern(); 1222 double val2 = nf.parse(out2).doubleValue(); 1223 1224 if (!pat.equals(pat2)) 1225 errln("Fail with \"" + PATS[i] + "\": Patterns should concur, \"" + 1226 pat + "\" vs. \"" + pat2 + "\""); 1227 else 1228 logln("Ok \"" + PATS[i] + "\" toPattern() -> \"" + pat + '"'); 1229 1230 if (val == val2 && out.equals(out2)) { 1231 logln("Ok " + pi + " x \"" + PATS[i] + "\" -> \"" + 1232 out + "\" -> " + val + " -> \"" + 1233 out2 + "\" -> " + val2); 1234 } 1235 else { 1236 errln("Fail " + pi + " x \"" + PATS[i] + "\" -> \"" + 1237 out + "\" -> " + val + " -> \"" + 1238 out2 + "\" -> " + val2); 1239 } 1240 } 1241 } 1242 catch (ParseException e) { 1243 errln("Fail: " + e); 1244 e.printStackTrace(); 1245 } 1246 } 1247 1248 /** 1249 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly. 1250 * CANNOT REPRODUCE 1251 * This bug is a duplicate of 4139344, which is a duplicate of 4134300 1252 */ 1253 public void Test4147295() { 1254 DecimalFormat sdf = new DecimalFormat(); 1255 String pattern = "#,###"; 1256 logln("Applying pattern \"" + pattern + "\""); 1257 sdf.applyPattern(pattern); 1258 int minIntDig = sdf.getMinimumIntegerDigits(); 1259 if (minIntDig != 0) { 1260 errln("Test failed"); 1261 errln(" Minimum integer digits : " + minIntDig); 1262 errln(" new pattern: " + sdf.toPattern()); 1263 } else { 1264 logln("Test passed"); 1265 logln(" Minimum integer digits : " + minIntDig); 1266 } 1267 } 1268 1269 /** 1270 * DecimalFormat formats -0.0 as +0.0 1271 * See also older related bug 4106658, 4106667 1272 */ 1273 public void Test4147706() { 1274 DecimalFormat df = new DecimalFormat("#,##0.0##"); 1275 df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH)); 1276 double d1 = -0.0; 1277 double d2 = -0.0001; 1278 StringBuffer f1 = df.format(d1, new StringBuffer(), new FieldPosition(0)); 1279 StringBuffer f2 = df.format(d2, new StringBuffer(), new FieldPosition(0)); 1280 if (!f1.toString().equals("-0.0")) { 1281 errln(d1 + " x \"" + df.toPattern() + "\" is formatted as \"" + f1 + '"'); 1282 } 1283 if (!f2.toString().equals("-0.0")) { 1284 errln(d2 + " x \"" + df.toPattern() + "\" is formatted as \"" + f2 + '"'); 1285 } 1286 } 1287 1288 /** 1289 * NumberFormat cannot format Double.MAX_VALUE 1290 */ 1291 public void Test4162198() { 1292 double dbl = Double.MAX_VALUE; 1293 NumberFormat f = NumberFormat.getInstance(); 1294 f.setMaximumFractionDigits(Integer.MAX_VALUE); 1295 f.setMaximumIntegerDigits(Integer.MAX_VALUE); 1296 String s = f.format(dbl); 1297 logln("The number " + dbl + " formatted to " + s); 1298 Number n = null; 1299 try { 1300 n = f.parse(s); 1301 } catch (java.text.ParseException e) { 1302 errln("Caught a ParseException:"); 1303 e.printStackTrace(); 1304 } 1305 logln("The string " + s + " parsed as " + n); 1306 if (n.doubleValue() != dbl) { 1307 errln("Round trip failure"); 1308 } 1309 } 1310 1311 /** 1312 * NumberFormat does not parse negative zero. 1313 */ 1314 public void Test4162852() throws ParseException { 1315 for (int i=0; i<2; ++i) { 1316 NumberFormat f = (i == 0) ? NumberFormat.getInstance() 1317 : NumberFormat.getPercentInstance(); 1318 double d = -0.0; 1319 String s = f.format(d); 1320 double e = f.parse(s).doubleValue(); 1321 logln("" + 1322 d + " -> " + 1323 '"' + s + '"' + " -> " + 1324 e); 1325 if (e != 0.0 || 1.0/e > 0.0) { 1326 logln("Failed to parse negative zero"); 1327 } 1328 } 1329 } 1330 1331 /** 1332 * NumberFormat truncates data 1333 */ 1334 public void Test4167494() throws Exception { 1335 NumberFormat fmt = NumberFormat.getInstance(Locale.US); 1336 1337 double a = Double.MAX_VALUE; 1338 String s = fmt.format(a); 1339 double b = fmt.parse(s).doubleValue(); 1340 boolean match = a == b; 1341 if (match) { 1342 logln("" + a + " -> \"" + s + "\" -> " + b + " ok"); 1343 } else { 1344 errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL"); 1345 } 1346 1347 // We don't test Double.MIN_VALUE because the locale data for the US 1348 // currently doesn't specify enough digits to display Double.MIN_VALUE. 1349 // This is correct for now; however, we leave this here as a reminder 1350 // in case we want to address this later. 1351 if (false) { 1352 a = Double.MIN_VALUE; 1353 s = fmt.format(a); 1354 b = fmt.parse(s).doubleValue(); 1355 match = a == b; 1356 if (match) { 1357 logln("" + a + " -> \"" + s + "\" -> " + b + " ok"); 1358 } else { 1359 errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL"); 1360 } 1361 } 1362 } 1363 1364 /** 1365 * DecimalFormat.parse() fails when ParseIntegerOnly set to true 1366 */ 1367 public void Test4170798() { 1368 Locale savedLocale = Locale.getDefault(); 1369 Locale.setDefault(Locale.US); 1370 DecimalFormat df = new DecimalFormat(); 1371 df.setParseIntegerOnly(true); 1372 Number n = df.parse("-0.0", new ParsePosition(0)); 1373 if (!(n instanceof Long || n instanceof Integer) 1374 || n.intValue() != 0) { 1375 errln("FAIL: parse(\"-0.0\") returns " + 1376 n + " (" + n.getClass().getName() + ')'); 1377 } 1378 Locale.setDefault(savedLocale); 1379 } 1380 1381 /** 1382 * toPattern only puts the first grouping separator in. 1383 */ 1384 public void Test4176114() { 1385 String[] DATA = { 1386 "00", "#00", 1387 "000", "#000", // No grouping 1388 "#000", "#000", // No grouping 1389 "#,##0", "#,##0", 1390 "#,000", "#,000", 1391 "0,000", "#0,000", 1392 "00,000", "#00,000", 1393 "000,000", "#,000,000", 1394 "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported 1395 }; 1396 for (int i=0; i<DATA.length; i+=2) { 1397 DecimalFormat df = new DecimalFormat(DATA[i]); 1398 String s = df.toPattern(); 1399 if (!s.equals(DATA[i+1])) { 1400 errln("FAIL: " + DATA[i] + " -> " + s + ", want " + DATA[i+1]); 1401 } 1402 } 1403 } 1404 1405 /** 1406 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2 1407 */ 1408 public void Test4179818() { 1409 String DATA[] = { 1410 // Input Pattern Expected output 1411 "1.2511", "#.#", "1.3", 1412 "1.2501", "#.#", "1.3", 1413 "0.9999", "#", "1", 1414 }; 1415 DecimalFormat fmt = new DecimalFormat("#", 1416 DecimalFormatSymbols.getInstance(Locale.US)); 1417 for (int i=0; i<DATA.length; i+=3) { 1418 double in = Double.valueOf(DATA[i]).doubleValue(); 1419 String pat = DATA[i+1]; 1420 String exp = DATA[i+2]; 1421 fmt.applyPattern(pat); 1422 String out = fmt.format(in); 1423 if (out.equals(exp)) { 1424 logln("Ok: " + in + " x " + pat + " = " + out); 1425 } else { 1426 errln("FAIL: " + in + " x " + pat + " = " + out + 1427 ", expected " + exp); 1428 } 1429 } 1430 } 1431 1432 public void Test4185761() throws IOException, ClassNotFoundException { 1433 /* Code used to write out the initial files, which are 1434 * then edited manually: 1435 NumberFormat nf = NumberFormat.getInstance(Locale.US); 1436 nf.setMinimumIntegerDigits(0x111); // Keep under 309 1437 nf.setMaximumIntegerDigits(0x112); // Keep under 309 1438 nf.setMinimumFractionDigits(0x113); // Keep under 340 1439 nf.setMaximumFractionDigits(0x114); // Keep under 340 1440 FileOutputStream ostream = 1441 new FileOutputStream("NumberFormat4185761"); 1442 ObjectOutputStream p = new ObjectOutputStream(ostream); 1443 p.writeObject(nf); 1444 ostream.close(); 1445 */ 1446 1447 // File minint maxint minfrac maxfrac 1448 // NumberFormat4185761a 0x122 0x121 0x124 0x123 1449 // NumberFormat4185761b 0x311 0x312 0x313 0x314 1450 // File a is bad because the mins are smaller than the maxes. 1451 // File b is bad because the values are too big for a DecimalFormat. 1452 // These files have a sufix ".ser.txt". 1453 1454 InputStream istream = HexDumpReader.getStreamFromHexDump("NumberFormat4185761a.ser.txt"); 1455 ObjectInputStream p = new ObjectInputStream(istream); 1456 try { 1457 NumberFormat nf = (NumberFormat) p.readObject(); 1458 errln("FAIL: Deserialized bogus NumberFormat int:" + 1459 nf.getMinimumIntegerDigits() + ".." + 1460 nf.getMaximumIntegerDigits() + " frac:" + 1461 nf.getMinimumFractionDigits() + ".." + 1462 nf.getMaximumFractionDigits()); 1463 } catch (InvalidObjectException e) { 1464 logln("Ok: " + e.getMessage()); 1465 } 1466 istream.close(); 1467 1468 istream = HexDumpReader.getStreamFromHexDump("NumberFormat4185761b.ser.txt"); 1469 p = new ObjectInputStream(istream); 1470 try { 1471 NumberFormat nf = (NumberFormat) p.readObject(); 1472 errln("FAIL: Deserialized bogus DecimalFormat int:" + 1473 nf.getMinimumIntegerDigits() + ".." + 1474 nf.getMaximumIntegerDigits() + " frac:" + 1475 nf.getMinimumFractionDigits() + ".." + 1476 nf.getMaximumFractionDigits()); 1477 } catch (InvalidObjectException e) { 1478 logln("Ok: " + e.getMessage()); 1479 } 1480 istream.close(); 1481 } 1482 1483 1484 /** 1485 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat. 1486 * This includes the minus sign, currency symbol, international currency 1487 * symbol, percent, and permille. This is filed as bugs 4212072 and 1488 * 4212073. 1489 */ 1490 public void Test4212072() throws IOException, ClassNotFoundException { 1491 DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US); 1492 DecimalFormat fmt = new DecimalFormat("#", sym); 1493 1494 sym.setMinusSign('^'); 1495 fmt.setDecimalFormatSymbols(sym); 1496 if (!fmt.format(-1).equals("^1")) { 1497 errln("FAIL: -1 x (minus=^) -> " + fmt.format(-1) + 1498 ", exp ^1"); 1499 } 1500 if (!fmt.getNegativePrefix().equals("^")) { 1501 errln("FAIL: (minus=^).getNegativePrefix -> " + 1502 fmt.getNegativePrefix() + ", exp ^"); 1503 } 1504 sym.setMinusSign('-'); 1505 1506 fmt.applyPattern("#%"); 1507 sym.setPercent('^'); 1508 fmt.setDecimalFormatSymbols(sym); 1509 if (!fmt.format(0.25).equals("25^")) { 1510 errln("FAIL: 0.25 x (percent=^) -> " + fmt.format(0.25) + 1511 ", exp 25^"); 1512 } 1513 if (!fmt.getPositiveSuffix().equals("^")) { 1514 errln("FAIL: (percent=^).getPositiveSuffix -> " + 1515 fmt.getPositiveSuffix() + ", exp ^"); 1516 } 1517 sym.setPercent('%'); 1518 1519 fmt.applyPattern("#\u2030"); 1520 sym.setPerMill('^'); 1521 fmt.setDecimalFormatSymbols(sym); 1522 if (!fmt.format(0.25).equals("250^")) { 1523 errln("FAIL: 0.25 x (permill=^) -> " + fmt.format(0.25) + 1524 ", exp 250^"); 1525 } 1526 if (!fmt.getPositiveSuffix().equals("^")) { 1527 errln("FAIL: (permill=^).getPositiveSuffix -> " + 1528 fmt.getPositiveSuffix() + ", exp ^"); 1529 } 1530 sym.setPerMill('\u2030'); 1531 1532 fmt.applyPattern("\u00A4#.00"); 1533 sym.setCurrencySymbol("usd"); 1534 fmt.setDecimalFormatSymbols(sym); 1535 if (!fmt.format(12.5).equals("usd12.50")) { 1536 errln("FAIL: 12.5 x (currency=usd) -> " + fmt.format(12.5) + 1537 ", exp usd12.50"); 1538 } 1539 if (!fmt.getPositivePrefix().equals("usd")) { 1540 errln("FAIL: (currency=usd).getPositivePrefix -> " + 1541 fmt.getPositivePrefix() + ", exp usd"); 1542 } 1543 sym.setCurrencySymbol("$"); 1544 1545 fmt.applyPattern("\u00A4\u00A4#.00"); 1546 sym.setInternationalCurrencySymbol("DOL"); 1547 fmt.setDecimalFormatSymbols(sym); 1548 if (!fmt.format(12.5).equals("DOL12.50")) { 1549 errln("FAIL: 12.5 x (intlcurrency=DOL) -> " + fmt.format(12.5) + 1550 ", exp DOL12.50"); 1551 } 1552 if (!fmt.getPositivePrefix().equals("DOL")) { 1553 errln("FAIL: (intlcurrency=DOL).getPositivePrefix -> " + 1554 fmt.getPositivePrefix() + ", exp DOL"); 1555 } 1556 sym.setInternationalCurrencySymbol("USD"); 1557 1558 // Since the pattern logic has changed, make sure that patterns round 1559 // trip properly. Test stream in/out integrity too. 1560 Locale[] avail = NumberFormat.getAvailableLocales(); 1561 for (int i=0; i<avail.length; ++i) { 1562 for (int j=0; j<3; ++j) { 1563 NumberFormat nf; 1564 switch (j) { 1565 case 0: 1566 nf = NumberFormat.getInstance(avail[i]); 1567 break; 1568 case 1: 1569 nf = NumberFormat.getCurrencyInstance(avail[i]); 1570 break; 1571 default: 1572 nf = NumberFormat.getPercentInstance(avail[i]); 1573 break; 1574 } 1575 DecimalFormat df = (DecimalFormat) nf; 1576 1577 // Test toPattern/applyPattern round trip 1578 String pat = df.toPattern(); 1579 DecimalFormatSymbols symb = DecimalFormatSymbols.getInstance(avail[i]); 1580 DecimalFormat f2 = new DecimalFormat(pat, symb); 1581 if (!df.equals(f2)) { 1582 errln("FAIL: " + avail[i] + " -> \"" + pat + 1583 "\" -> \"" + f2.toPattern() + '"'); 1584 } 1585 1586 // Test toLocalizedPattern/applyLocalizedPattern round trip 1587 pat = df.toLocalizedPattern(); 1588 f2.applyLocalizedPattern(pat); 1589 if (!df.equals(f2)) { 1590 errln("FAIL: " + avail[i] + " -> localized \"" + pat + 1591 "\" -> \"" + f2.toPattern() + '"'); 1592 } 1593 1594 // Test writeObject/readObject round trip 1595 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 1596 ObjectOutputStream oos = new ObjectOutputStream(baos); 1597 oos.writeObject(df); 1598 oos.flush(); 1599 baos.close(); 1600 byte[] bytes = baos.toByteArray(); 1601 ObjectInputStream ois = 1602 new ObjectInputStream(new ByteArrayInputStream(bytes)); 1603 f2 = (DecimalFormat) ois.readObject(); 1604 if (!df.equals(f2)) { 1605 errln("FAIL: Stream in/out " + avail[i] + " -> \"" + pat + 1606 "\" -> " + 1607 (f2 != null ? ("\""+f2.toPattern()+'"') : "null")); 1608 } 1609 1610 } 1611 } 1612 } 1613 1614 /** 1615 * DecimalFormat.parse() fails for mulipliers 2^n. 1616 */ 1617 public void Test4216742() throws ParseException { 1618 DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance(Locale.US); 1619 long[] DATA = { Long.MIN_VALUE, Long.MAX_VALUE, -100000000L, 100000000L}; 1620 for (int i=0; i<DATA.length; ++i) { 1621 String str = Long.toString(DATA[i]); 1622 for (int m = 1; m <= 100; m++) { 1623 fmt.setMultiplier(m); 1624 long n = ((Number) fmt.parse(str)).longValue(); 1625 if (n > 0 != DATA[i] > 0) { 1626 errln("\"" + str + "\" parse(x " + fmt.getMultiplier() + 1627 ") => " + n); 1628 } 1629 } 1630 } 1631 } 1632 1633 /** 1634 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction 1635 * digits. 1636 */ 1637 public void Test4217661() { 1638 Object[] DATA = { 1639 new Double(0.001), "0", 1640 new Double(1.001), "1", 1641 new Double(0.006), "0.01", 1642 new Double(1.006), "1.01", 1643 }; 1644 NumberFormat fmt = NumberFormat.getInstance(Locale.US); 1645 fmt.setMaximumFractionDigits(2); 1646 for (int i=0; i<DATA.length; i+=2) { 1647 String s = fmt.format(((Double) DATA[i]).doubleValue()); 1648 if (!s.equals(DATA[i+1])) { 1649 errln("FAIL: Got " + s + ", exp " + DATA[i+1]); 1650 } 1651 } 1652 } 1653 1654 /** 1655 * 4243011: Formatting .5 rounds to "1" instead of "0" 1656 */ 1657 public void Test4243011() { 1658 Locale savedLocale = Locale.getDefault(); 1659 Locale.setDefault(Locale.US); 1660 double DATA[] = {0.5, 1.5, 2.5, 3.5, 4.5}; 1661 String EXPECTED[] = {"0.", "2.", "2.", "4.", "4."}; 1662 1663 DecimalFormat format = new DecimalFormat("0."); 1664 for (int i = 0; i < DATA.length; i++) { 1665 String result = format.format(DATA[i]); 1666 if (result.equals(EXPECTED[i])) { 1667 logln("OK: got " + result); 1668 } else { 1669 errln("FAIL: got " + result); 1670 } 1671 } 1672 Locale.setDefault(savedLocale); 1673 } 1674 1675 /** 1676 * 4243108: format(0.0) gives "0.1" if preceded by parse("99.99") 1677 */ 1678 public void Test4243108() { 1679 Locale savedLocale = Locale.getDefault(); 1680 Locale.setDefault(Locale.US); 1681 DecimalFormat f = new DecimalFormat("#.#"); 1682 String result = f.format(0.0); 1683 if (result.equals("0")) { 1684 logln("OK: got " + result); 1685 } else { 1686 errln("FAIL: got " + result); 1687 } 1688 try { 1689 double dResult = f.parse("99.99").doubleValue(); 1690 if (dResult == 99.99) { 1691 logln("OK: got " + dResult); 1692 } else { 1693 errln("FAIL: got " + dResult); 1694 } 1695 } catch (ParseException e) { 1696 errln("Caught a ParseException:"); 1697 e.printStackTrace(); 1698 } 1699 result = f.format(0.0); 1700 if (result.equals("0")) { 1701 logln("OK: got " + result); 1702 } else { 1703 errln("FAIL: got " + result); 1704 } 1705 Locale.setDefault(savedLocale); 1706 } 1707 1708 /** 1709 * 4330377: DecimalFormat engineering notation gives incorrect results 1710 */ 1711 public void test4330377() { 1712 Locale savedLocale = Locale.getDefault(); 1713 Locale.setDefault(Locale.US); 1714 double[] input = {5000.0, 500.0, 50.0, 5.0, 0.5, 0.05, 0.005, 0.0005, 1715 5050.0, 505.0, 50.5, 5.05, 0.505, 0.0505, 0.00505, 0.000505}; 1716 String[] pattern = {"000.#E0", "##0.#E0", "#00.#E0"}; 1717 String[][] expected = { 1718 // it's questionable whether "#00.#E0" should result in post-decimal 1719 // zeroes, i.e., whether "5.0E3", "5.0E0", "5.0E-3" are really good 1720 {"500E1", "5E3", "5.0E3"}, 1721 {"500E0", "500E0", "500E0"}, 1722 {"500E-1", "50E0", "50E0"}, 1723 {"500E-2", "5E0", "5.0E0"}, 1724 {"500E-3", "500E-3", "500E-3"}, 1725 {"500E-4", "50E-3", "50E-3"}, 1726 {"500E-5", "5E-3", "5.0E-3"}, 1727 {"500E-6", "500E-6", "500E-6"}, 1728 {"505E1", "5.05E3", "5.05E3"}, 1729 {"505E0", "505E0", "505E0"}, 1730 {"505E-1", "50.5E0", "50.5E0"}, 1731 {"505E-2", "5.05E0", "5.05E0"}, 1732 {"505E-3", "505E-3", "505E-3"}, 1733 {"505E-4", "50.5E-3", "50.5E-3"}, 1734 {"505E-5", "5.05E-3", "5.05E-3"}, 1735 {"505E-6", "505E-6", "505E-6"} 1736 }; 1737 for (int i = 0; i < input.length; i++) { 1738 for (int j = 0; j < pattern.length; j++) { 1739 DecimalFormat format = new DecimalFormat(pattern[j]); 1740 String result = format.format(input[i]); 1741 if (!result.equals(expected[i][j])) { 1742 errln("FAIL: input: " + input[i] + 1743 ", pattern: " + pattern[j] + 1744 ", expected: " + expected[i][j] + 1745 ", got: " + result); 1746 } 1747 } 1748 } 1749 Locale.setDefault(savedLocale); 1750 } 1751 1752 /** 1753 * 4233840: NumberFormat does not round correctly 1754 */ 1755 public void test4233840() { 1756 float f = 0.0099f; 1757 1758 NumberFormat nf = new DecimalFormat("0.##", DecimalFormatSymbols.getInstance(Locale.US)); 1759 nf.setMinimumFractionDigits(2); 1760 1761 String result = nf.format(f); 1762 1763 if (!result.equals("0.01")) { 1764 errln("FAIL: input: " + f + ", expected: 0.01, got: " + result); 1765 } 1766 } 1767 1768 /** 1769 * 4241880: Decimal format doesnt round a double properly when the number is less than 1 1770 */ 1771 public void test4241880() { 1772 Locale savedLocale = Locale.getDefault(); 1773 Locale.setDefault(Locale.US); 1774 double[] input = { 1775 .019, .009, .015, .016, .014, 1776 .004, .005, .006, .007, .008, 1777 .5, 1.5, .25, .55, .045, 1778 .035, .0005, .0015, 1779 }; 1780 String[] pattern = { 1781 "##0%", "##0%", "##0%", "##0%", "##0%", 1782 "##0%", "##0%", "##0%", "##0%", "##0%", 1783 "#,##0", "#,##0", "#,##0.0", "#,##0.0", "#,##0.00", 1784 "#,##0.00", "#,##0.000", "#,##0.000", 1785 }; 1786 String[] expected = { 1787 "2%", "1%", "2%", "2%", "1%", 1788 "0%", "0%", "1%", "1%", "1%", 1789 "0", "2", "0.2", "0.6", "0.04", 1790 "0.04", "0.000", "0.002", 1791 }; 1792 for (int i = 0; i < input.length; i++) { 1793 DecimalFormat format = new DecimalFormat(pattern[i]); 1794 String result = format.format(input[i]); 1795 if (!result.equals(expected[i])) { 1796 errln("FAIL: input: " + input[i] + 1797 ", pattern: " + pattern[i] + 1798 ", expected: " + expected[i] + 1799 ", got: " + result); 1800 } 1801 } 1802 Locale.setDefault(savedLocale); 1803 } 1804 } 1805 1806 class myformat implements Serializable 1807 { 1808 DateFormat _dateFormat = DateFormat.getDateInstance(); 1809 1810 public String Now() 1811 { 1812 GregorianCalendar calendar = new GregorianCalendar(); 1813 Date t = calendar.getTime(); 1814 String nowStr = _dateFormat.format(t); 1815 return nowStr; 1816 } 1817 } 1818 1819 class MyNumberFormatTest extends NumberFormat { 1820 public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) { 1821 return new StringBuffer(""); 1822 } 1823 public StringBuffer format(long number,StringBuffer toAppendTo, FieldPosition pos) { 1824 return new StringBuffer(""); 1825 } 1826 public Number parse(String text, ParsePosition parsePosition) { 1827 return new Integer(0); 1828 } 1829 }