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