1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2017 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 package ohos.global.icu.dev.test.format; 5 6 import java.math.BigDecimal; 7 import java.math.RoundingMode; 8 import java.text.ParsePosition; 9 10 import org.junit.Test; 11 12 import ohos.global.icu.dev.test.TestUtil; 13 import ohos.global.icu.impl.number.DecimalFormatProperties; 14 import ohos.global.icu.impl.number.DecimalFormatProperties.ParseMode; 15 import ohos.global.icu.impl.number.Padder.PadPosition; 16 import ohos.global.icu.impl.number.PatternStringParser; 17 import ohos.global.icu.impl.number.PatternStringUtils; 18 import ohos.global.icu.impl.number.parse.NumberParserImpl; 19 import ohos.global.icu.number.LocalizedNumberFormatter; 20 import ohos.global.icu.number.NumberFormatter; 21 import ohos.global.icu.text.DecimalFormat; 22 import ohos.global.icu.text.DecimalFormat.PropertySetter; 23 import ohos.global.icu.text.DecimalFormatSymbols; 24 import ohos.global.icu.util.CurrencyAmount; 25 import ohos.global.icu.util.ULocale; 26 27 28 29 public class NumberFormatDataDrivenTest { 30 31 private static ULocale EN = new ULocale("en"); 32 toNumber(String s)33 private static Number toNumber(String s) { 34 if (s.equals("NaN")) { 35 return Double.NaN; 36 } else if (s.equals("-Inf")) { 37 return Double.NEGATIVE_INFINITY; 38 } else if (s.equals("Inf")) { 39 return Double.POSITIVE_INFINITY; 40 } 41 return new BigDecimal(s); 42 } 43 44 /** 45 * Standard function for comparing expected and actual parse results. Handles NaN, Infinity, and 46 * failure cases. 47 */ compareParseResult(String expected, Number actual, ParsePosition ppos)48 private static String compareParseResult(String expected, Number actual, ParsePosition ppos) { 49 if (actual == null && ppos.getIndex() != 0) { 50 throw new AssertionError("Error: value is null but parse position is not zero"); 51 } 52 if (ppos.getIndex() == 0) { 53 return "Parse failed; got " + actual + ", but expected " + expected; 54 } 55 if (expected.equals("NaN")) { 56 if (!Double.isNaN(actual.doubleValue())) { 57 return "Expected NaN, but got: " + actual; 58 } 59 return null; 60 } else if (expected.equals("Inf")) { 61 if (!Double.isInfinite(actual.doubleValue()) 62 || Double.compare(actual.doubleValue(), 0.0) < 0) { 63 return "Expected Inf, but got: " + actual; 64 } 65 return null; 66 } else if (expected.equals("-Inf")) { 67 if (!Double.isInfinite(actual.doubleValue()) 68 || Double.compare(actual.doubleValue(), 0.0) > 0) { 69 return "Expected -Inf, but got: " + actual; 70 } 71 return null; 72 } else if (expected.equals("fail")) { 73 return null; 74 } else if (actual.toString().equals("Infinity")) { 75 return "Expected " + expected + ", but got Infinity"; 76 } else { 77 BigDecimal expectedDecimal = new BigDecimal(expected); 78 BigDecimal actualDecimal; 79 try { 80 actualDecimal = new BigDecimal(actual.toString()); 81 } catch (NumberFormatException e) { 82 throw new AssertionError("Could not convert to BigDecimal: " + actual.toString() + " - " + e.getMessage()); 83 } 84 if (expectedDecimal.compareTo(actualDecimal) != 0) { 85 return "Expected: " + expected + ", got: " + actual; 86 } else { 87 return null; 88 } 89 } 90 } 91 92 /** 93 * Standard function for comparing expected and actual parse-currency results. Handles failure cases. 94 * Does not currently handle NaN or Infinity because there are no parse-currency cases with NaN or 95 * Infinity. 96 */ compareParseCurrencyResult( String expected, String expectedCurrency, CurrencyAmount actual, ParsePosition ppos)97 private static String compareParseCurrencyResult( 98 String expected, 99 String expectedCurrency, 100 CurrencyAmount actual, 101 ParsePosition ppos) { 102 if (ppos.getIndex() == 0 || actual.getCurrency().getCurrencyCode().equals("XXX")) { 103 return "Parse failed; got " + actual + ", but expected " + expected; 104 } 105 if (expected.equals("fail")) { 106 return null; 107 } 108 BigDecimal expectedNumber = new BigDecimal(expected); 109 if (expectedNumber.compareTo(new BigDecimal(actual.getNumber().toString())) != 0) { 110 return "Wrong number: Expected: " + expectedNumber + ", got: " + actual; 111 } 112 if (!expectedCurrency.equals(actual.getCurrency().toString())) { 113 return "Wrong currency: Expected: " + expectedCurrency + ", got: " + actual; 114 } 115 return null; 116 } 117 118 /** 119 * Main ICU4J DecimalFormat data-driven test. 120 */ 121 private DataDrivenNumberFormatTestUtility.CodeUnderTest ICU4J = new DataDrivenNumberFormatTestUtility.CodeUnderTest() { 122 @Override 123 public Character Id() { 124 return 'J'; 125 } 126 127 @Override 128 public String format(DataDrivenNumberFormatTestData tuple) { 129 DecimalFormat fmt = createDecimalFormat(tuple); 130 String actual = fmt.format(toNumber(tuple.format)); 131 String expected = tuple.output; 132 if (!expected.equals(actual)) { 133 return "Expected " + expected + ", got " + actual; 134 } 135 return null; 136 } 137 138 @Override 139 public String toPattern(DataDrivenNumberFormatTestData tuple) { 140 DecimalFormat fmt = createDecimalFormat(tuple); 141 StringBuilder result = new StringBuilder(); 142 if (tuple.toPattern != null) { 143 String expected = tuple.toPattern; 144 String actual = fmt.toPattern(); 145 if (!expected.equals(actual)) { 146 result.append("Expected toPattern=" + expected + ", got " + actual); 147 } 148 } 149 if (tuple.toLocalizedPattern != null) { 150 String expected = tuple.toLocalizedPattern; 151 String actual = fmt.toLocalizedPattern(); 152 if (!expected.equals(actual)) { 153 result.append("Expected toLocalizedPattern=" + expected + ", got " + actual); 154 } 155 } 156 return result.length() == 0 ? null : result.toString(); 157 } 158 159 @Override 160 public String parse(DataDrivenNumberFormatTestData tuple) { 161 DecimalFormat fmt = createDecimalFormat(tuple); 162 ParsePosition ppos = new ParsePosition(0); 163 Number actual = fmt.parse(tuple.parse, ppos); 164 return compareParseResult(tuple.output, actual, ppos); 165 } 166 167 @Override 168 public String parseCurrency(DataDrivenNumberFormatTestData tuple) { 169 DecimalFormat fmt = createDecimalFormat(tuple); 170 ParsePosition ppos = new ParsePosition(0); 171 CurrencyAmount actual = fmt.parseCurrency(tuple.parse, ppos); 172 return compareParseCurrencyResult(tuple.output, tuple.outputCurrency, actual, ppos); 173 } 174 175 /** 176 * @param tuple 177 * @return 178 */ 179 private DecimalFormat createDecimalFormat(DataDrivenNumberFormatTestData tuple) { 180 DecimalFormat fmt = new DecimalFormat(tuple.pattern == null ? "0" : tuple.pattern, 181 new DecimalFormatSymbols(tuple.locale == null ? EN : tuple.locale)); 182 adjustDecimalFormat(tuple, fmt); 183 return fmt; 184 } 185 186 /** 187 * @param tuple 188 * @param fmt 189 */ 190 private void adjustDecimalFormat(DataDrivenNumberFormatTestData tuple, DecimalFormat fmt) { 191 if (tuple.minIntegerDigits != null) { 192 fmt.setMinimumIntegerDigits(tuple.minIntegerDigits); 193 } 194 if (tuple.maxIntegerDigits != null) { 195 fmt.setMaximumIntegerDigits(tuple.maxIntegerDigits); 196 } 197 if (tuple.minFractionDigits != null) { 198 fmt.setMinimumFractionDigits(tuple.minFractionDigits); 199 } 200 if (tuple.maxFractionDigits != null) { 201 fmt.setMaximumFractionDigits(tuple.maxFractionDigits); 202 } 203 if (tuple.currency != null) { 204 fmt.setCurrency(tuple.currency); 205 } 206 if (tuple.minGroupingDigits != null) { 207 fmt.setMinimumGroupingDigits(tuple.minGroupingDigits); 208 } 209 if (tuple.useSigDigits != null) { 210 fmt.setSignificantDigitsUsed(tuple.useSigDigits != 0); 211 } 212 if (tuple.minSigDigits != null) { 213 fmt.setMinimumSignificantDigits(tuple.minSigDigits); 214 } 215 if (tuple.maxSigDigits != null) { 216 fmt.setMaximumSignificantDigits(tuple.maxSigDigits); 217 } 218 if (tuple.useGrouping != null) { 219 fmt.setGroupingUsed(tuple.useGrouping != 0); 220 } 221 if (tuple.multiplier != null) { 222 fmt.setMultiplier(tuple.multiplier); 223 } 224 if (tuple.roundingIncrement != null) { 225 fmt.setRoundingIncrement(tuple.roundingIncrement.doubleValue()); 226 } 227 if (tuple.formatWidth != null) { 228 fmt.setFormatWidth(tuple.formatWidth); 229 } 230 if (tuple.padCharacter != null && tuple.padCharacter.length() > 0) { 231 fmt.setPadCharacter(tuple.padCharacter.charAt(0)); 232 } 233 if (tuple.useScientific != null) { 234 fmt.setScientificNotation(tuple.useScientific != 0); 235 } 236 if (tuple.grouping != null) { 237 fmt.setGroupingSize(tuple.grouping); 238 } 239 if (tuple.grouping2 != null) { 240 fmt.setSecondaryGroupingSize(tuple.grouping2); 241 } 242 if (tuple.roundingMode != null) { 243 fmt.setRoundingMode(tuple.roundingMode); 244 } 245 if (tuple.currencyUsage != null) { 246 fmt.setCurrencyUsage(tuple.currencyUsage); 247 } 248 if (tuple.minimumExponentDigits != null) { 249 fmt.setMinimumExponentDigits(tuple.minimumExponentDigits.byteValue()); 250 } 251 if (tuple.exponentSignAlwaysShown != null) { 252 fmt.setExponentSignAlwaysShown(tuple.exponentSignAlwaysShown != 0); 253 } 254 if (tuple.decimalSeparatorAlwaysShown != null) { 255 fmt.setDecimalSeparatorAlwaysShown(tuple.decimalSeparatorAlwaysShown != 0); 256 } 257 if (tuple.padPosition != null) { 258 fmt.setPadPosition(tuple.padPosition); 259 } 260 if (tuple.positivePrefix != null) { 261 fmt.setPositivePrefix(tuple.positivePrefix); 262 } 263 if (tuple.positiveSuffix != null) { 264 fmt.setPositiveSuffix(tuple.positiveSuffix); 265 } 266 if (tuple.negativePrefix != null) { 267 fmt.setNegativePrefix(tuple.negativePrefix); 268 } 269 if (tuple.negativeSuffix != null) { 270 fmt.setNegativeSuffix(tuple.negativeSuffix); 271 } 272 if (tuple.signAlwaysShown != null) { 273 fmt.setSignAlwaysShown(tuple.signAlwaysShown != 0); 274 } 275 if (tuple.localizedPattern != null) { 276 fmt.applyLocalizedPattern(tuple.localizedPattern); 277 } 278 int lenient = tuple.lenient == null ? 1 : tuple.lenient.intValue(); 279 fmt.setParseStrict(lenient == 0); 280 if (tuple.parseIntegerOnly != null) { 281 fmt.setParseIntegerOnly(tuple.parseIntegerOnly != 0); 282 } 283 if (tuple.parseCaseSensitive != null) { 284 fmt.setParseCaseSensitive(tuple.parseCaseSensitive != 0); 285 } 286 if (tuple.decimalPatternMatchRequired != null) { 287 fmt.setDecimalPatternMatchRequired(tuple.decimalPatternMatchRequired != 0); 288 } 289 if (tuple.parseNoExponent != null) { 290 fmt.setParseNoExponent(tuple.parseNoExponent != 0); 291 } 292 } 293 }; 294 295 /** 296 * Test of available JDK APIs. 297 */ 298 private DataDrivenNumberFormatTestUtility.CodeUnderTest JDK = new DataDrivenNumberFormatTestUtility.CodeUnderTest() { 299 @Override 300 public Character Id() { 301 return 'K'; 302 } 303 304 @Override 305 public String format(DataDrivenNumberFormatTestData tuple) { 306 java.text.DecimalFormat fmt = createDecimalFormat(tuple); 307 String actual = fmt.format(toNumber(tuple.format)); 308 String expected = tuple.output; 309 if (!expected.equals(actual)) { 310 return "Expected " + expected + ", got " + actual; 311 } 312 return null; 313 } 314 315 @Override 316 public String toPattern(DataDrivenNumberFormatTestData tuple) { 317 java.text.DecimalFormat fmt = createDecimalFormat(tuple); 318 StringBuilder result = new StringBuilder(); 319 if (tuple.toPattern != null) { 320 String expected = tuple.toPattern; 321 String actual = fmt.toPattern(); 322 if (!expected.equals(actual)) { 323 result.append("Expected toPattern=" + expected + ", got " + actual); 324 } 325 } 326 if (tuple.toLocalizedPattern != null) { 327 String expected = tuple.toLocalizedPattern; 328 String actual = fmt.toLocalizedPattern(); 329 if (!expected.equals(actual)) { 330 result.append("Expected toLocalizedPattern=" + expected + ", got " + actual); 331 } 332 } 333 return result.length() == 0 ? null : result.toString(); 334 } 335 336 @Override 337 public String parse(DataDrivenNumberFormatTestData tuple) { 338 java.text.DecimalFormat fmt = createDecimalFormat(tuple); 339 ParsePosition ppos = new ParsePosition(0); 340 Number actual = fmt.parse(tuple.parse, ppos); 341 return compareParseResult(tuple.output, actual, ppos); 342 } 343 344 /** 345 * @param tuple 346 * @return 347 */ 348 private java.text.DecimalFormat createDecimalFormat(DataDrivenNumberFormatTestData tuple) { 349 java.text.DecimalFormat fmt = new java.text.DecimalFormat( 350 tuple.pattern == null ? "0" : tuple.pattern, 351 new java.text.DecimalFormatSymbols( 352 (tuple.locale == null ? EN : tuple.locale).toLocale())); 353 adjustDecimalFormat(tuple, fmt); 354 return fmt; 355 } 356 357 /** 358 * @param tuple 359 * @param fmt 360 */ 361 private void adjustDecimalFormat( 362 DataDrivenNumberFormatTestData tuple, 363 java.text.DecimalFormat fmt) { 364 if (tuple.minIntegerDigits != null) { 365 fmt.setMinimumIntegerDigits(tuple.minIntegerDigits); 366 } 367 if (tuple.maxIntegerDigits != null) { 368 fmt.setMaximumIntegerDigits(tuple.maxIntegerDigits); 369 } 370 if (tuple.minFractionDigits != null) { 371 fmt.setMinimumFractionDigits(tuple.minFractionDigits); 372 } 373 if (tuple.maxFractionDigits != null) { 374 fmt.setMaximumFractionDigits(tuple.maxFractionDigits); 375 } 376 if (tuple.currency != null) { 377 fmt.setCurrency(java.util.Currency.getInstance(tuple.currency.toString())); 378 } 379 if (tuple.minGroupingDigits != null) { 380 // Oops we don't support this. 381 } 382 if (tuple.useSigDigits != null) { 383 // Oops we don't support this 384 } 385 if (tuple.minSigDigits != null) { 386 // Oops we don't support this 387 } 388 if (tuple.maxSigDigits != null) { 389 // Oops we don't support this 390 } 391 if (tuple.useGrouping != null) { 392 fmt.setGroupingUsed(tuple.useGrouping != 0); 393 } 394 if (tuple.multiplier != null) { 395 fmt.setMultiplier(tuple.multiplier); 396 } 397 if (tuple.roundingIncrement != null) { 398 // Not supported 399 } 400 if (tuple.formatWidth != null) { 401 // Not supported 402 } 403 if (tuple.padCharacter != null && tuple.padCharacter.length() > 0) { 404 // Not supported 405 } 406 if (tuple.useScientific != null) { 407 // Not supported 408 } 409 if (tuple.grouping != null) { 410 fmt.setGroupingSize(tuple.grouping); 411 } 412 if (tuple.grouping2 != null) { 413 // Not supported 414 } 415 if (tuple.roundingMode != null) { 416 // Not supported 417 } 418 if (tuple.currencyUsage != null) { 419 // Not supported 420 } 421 if (tuple.minimumExponentDigits != null) { 422 // Not supported 423 } 424 if (tuple.exponentSignAlwaysShown != null) { 425 // Not supported 426 } 427 if (tuple.decimalSeparatorAlwaysShown != null) { 428 fmt.setDecimalSeparatorAlwaysShown(tuple.decimalSeparatorAlwaysShown != 0); 429 } 430 if (tuple.padPosition != null) { 431 // Not supported 432 } 433 if (tuple.positivePrefix != null) { 434 fmt.setPositivePrefix(tuple.positivePrefix); 435 } 436 if (tuple.positiveSuffix != null) { 437 fmt.setPositiveSuffix(tuple.positiveSuffix); 438 } 439 if (tuple.negativePrefix != null) { 440 fmt.setNegativePrefix(tuple.negativePrefix); 441 } 442 if (tuple.negativeSuffix != null) { 443 fmt.setNegativeSuffix(tuple.negativeSuffix); 444 } 445 if (tuple.signAlwaysShown != null) { 446 // Not supported. 447 } 448 if (tuple.localizedPattern != null) { 449 fmt.applyLocalizedPattern(tuple.localizedPattern); 450 } 451 452 // lenient parsing not supported by JDK 453 if (tuple.parseIntegerOnly != null) { 454 fmt.setParseIntegerOnly(tuple.parseIntegerOnly != 0); 455 } 456 if (tuple.parseCaseSensitive != null) { 457 // Not supported. 458 } 459 if (tuple.decimalPatternMatchRequired != null) { 460 // Oops, not supported 461 } 462 if (tuple.parseNoExponent != null) { 463 // Oops, not supported for now 464 } 465 } 466 }; 467 propertiesFromTuple( DataDrivenNumberFormatTestData tuple, DecimalFormatProperties properties)468 static void propertiesFromTuple( 469 DataDrivenNumberFormatTestData tuple, 470 DecimalFormatProperties properties) { 471 if (tuple.minIntegerDigits != null) { 472 properties.setMinimumIntegerDigits(tuple.minIntegerDigits); 473 } 474 if (tuple.maxIntegerDigits != null) { 475 properties.setMaximumIntegerDigits(tuple.maxIntegerDigits); 476 } 477 if (tuple.minFractionDigits != null) { 478 properties.setMinimumFractionDigits(tuple.minFractionDigits); 479 } 480 if (tuple.maxFractionDigits != null) { 481 properties.setMaximumFractionDigits(tuple.maxFractionDigits); 482 } 483 if (tuple.currency != null) { 484 properties.setCurrency(tuple.currency); 485 } 486 if (tuple.minGroupingDigits != null) { 487 properties.setMinimumGroupingDigits(tuple.minGroupingDigits); 488 } 489 if (tuple.useSigDigits != null) { 490 // TODO 491 } 492 if (tuple.minSigDigits != null) { 493 properties.setMinimumSignificantDigits(tuple.minSigDigits); 494 } 495 if (tuple.maxSigDigits != null) { 496 properties.setMaximumSignificantDigits(tuple.maxSigDigits); 497 } 498 if (tuple.useGrouping != null) { 499 properties.setGroupingUsed(tuple.useGrouping > 0); 500 } 501 if (tuple.multiplier != null) { 502 properties.setMultiplier(new BigDecimal(tuple.multiplier)); 503 } 504 if (tuple.roundingIncrement != null) { 505 properties.setRoundingIncrement(new BigDecimal(tuple.roundingIncrement.toString())); 506 } 507 if (tuple.formatWidth != null) { 508 properties.setFormatWidth(tuple.formatWidth); 509 } 510 if (tuple.padCharacter != null && tuple.padCharacter.length() > 0) { 511 properties.setPadString(tuple.padCharacter.toString()); 512 } 513 if (tuple.useScientific != null) { 514 properties.setMinimumExponentDigits(tuple.useScientific != 0 ? 1 : -1); 515 } 516 if (tuple.grouping != null) { 517 properties.setGroupingSize(tuple.grouping); 518 } 519 if (tuple.grouping2 != null) { 520 properties.setSecondaryGroupingSize(tuple.grouping2); 521 } 522 if (tuple.roundingMode != null) { 523 properties.setRoundingMode(RoundingMode.valueOf(tuple.roundingMode)); 524 } 525 if (tuple.currencyUsage != null) { 526 properties.setCurrencyUsage(tuple.currencyUsage); 527 } 528 if (tuple.minimumExponentDigits != null) { 529 properties.setMinimumExponentDigits(tuple.minimumExponentDigits.byteValue()); 530 } 531 if (tuple.exponentSignAlwaysShown != null) { 532 properties.setExponentSignAlwaysShown(tuple.exponentSignAlwaysShown != 0); 533 } 534 if (tuple.decimalSeparatorAlwaysShown != null) { 535 properties.setDecimalSeparatorAlwaysShown(tuple.decimalSeparatorAlwaysShown != 0); 536 } 537 if (tuple.padPosition != null) { 538 properties.setPadPosition(PadPosition.fromOld(tuple.padPosition)); 539 } 540 if (tuple.positivePrefix != null) { 541 properties.setPositivePrefix(tuple.positivePrefix); 542 } 543 if (tuple.positiveSuffix != null) { 544 properties.setPositiveSuffix(tuple.positiveSuffix); 545 } 546 if (tuple.negativePrefix != null) { 547 properties.setNegativePrefix(tuple.negativePrefix); 548 } 549 if (tuple.negativeSuffix != null) { 550 properties.setNegativeSuffix(tuple.negativeSuffix); 551 } 552 if (tuple.signAlwaysShown != null) { 553 properties.setSignAlwaysShown(tuple.signAlwaysShown != 0); 554 } 555 if (tuple.localizedPattern != null) { 556 DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(tuple.locale); 557 String converted = PatternStringUtils 558 .convertLocalized(tuple.localizedPattern, symbols, false); 559 PatternStringParser.parseToExistingProperties(converted, properties); 560 } 561 if (tuple.lenient != null) { 562 properties.setParseMode(tuple.lenient == 0 ? ParseMode.STRICT : ParseMode.LENIENT); 563 } 564 if (tuple.parseIntegerOnly != null) { 565 properties.setParseIntegerOnly(tuple.parseIntegerOnly != 0); 566 } 567 if (tuple.parseCaseSensitive != null) { 568 properties.setParseCaseSensitive(tuple.parseCaseSensitive != 0); 569 } 570 if (tuple.decimalPatternMatchRequired != null) { 571 properties.setDecimalPatternMatchRequired(tuple.decimalPatternMatchRequired != 0); 572 } 573 if (tuple.parseNoExponent != null) { 574 properties.setParseNoExponent(tuple.parseNoExponent != 0); 575 } 576 } 577 578 /** 579 * Same as ICU4J, but bypasses the DecimalFormat wrapper and goes directly to the 580 * DecimalFormatProperties. 581 */ 582 private DataDrivenNumberFormatTestUtility.CodeUnderTest ICU4J_Properties = new DataDrivenNumberFormatTestUtility.CodeUnderTest() { 583 584 @Override 585 public Character Id() { 586 return 'P'; 587 } 588 589 /** 590 * Runs a single formatting test. On success, returns null. On failure, returns the error. This 591 * implementation just returns null. Subclasses should override. 592 * 593 * @param tuple 594 * contains the parameters of the format test. 595 */ 596 @Override 597 public String format(DataDrivenNumberFormatTestData tuple) { 598 String pattern = (tuple.pattern == null) ? "0" : tuple.pattern; 599 ULocale locale = (tuple.locale == null) ? ULocale.ENGLISH : tuple.locale; 600 DecimalFormatProperties properties = PatternStringParser.parseToProperties(pattern, 601 tuple.currency != null ? PatternStringParser.IGNORE_ROUNDING_ALWAYS 602 : PatternStringParser.IGNORE_ROUNDING_NEVER); 603 propertiesFromTuple(tuple, properties); 604 DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale); 605 LocalizedNumberFormatter fmt = NumberFormatter.fromDecimalFormat(properties, symbols, null) 606 .locale(locale); 607 Number number = toNumber(tuple.format); 608 String expected = tuple.output; 609 String actual = fmt.format(number).toString(); 610 if (!expected.equals(actual)) { 611 return "Expected \"" + expected + "\", got \"" + actual + "\""; 612 } 613 return null; 614 } 615 616 /** 617 * Runs a single toPattern test. On success, returns null. On failure, returns the error. This 618 * implementation just returns null. Subclasses should override. 619 * 620 * @param tuple 621 * contains the parameters of the format test. 622 */ 623 @Override 624 public String toPattern(DataDrivenNumberFormatTestData tuple) { 625 String pattern = (tuple.pattern == null) ? "0" : tuple.pattern; 626 final DecimalFormatProperties properties; 627 DecimalFormat df; 628 try { 629 properties = PatternStringParser.parseToProperties(pattern, 630 tuple.currency != null ? PatternStringParser.IGNORE_ROUNDING_ALWAYS 631 : PatternStringParser.IGNORE_ROUNDING_NEVER); 632 propertiesFromTuple(tuple, properties); 633 // TODO: Use PatternString.propertiesToString() directly. (How to deal with 634 // CurrencyUsage?) 635 df = new DecimalFormat(); 636 df.setProperties(new PropertySetter() { 637 @Override 638 public void set(DecimalFormatProperties props) { 639 props.copyFrom(properties); 640 } 641 }); 642 } catch (IllegalArgumentException e) { 643 e.printStackTrace(); 644 return e.getLocalizedMessage(); 645 } 646 647 if (tuple.toPattern != null) { 648 String expected = tuple.toPattern; 649 String actual = df.toPattern(); 650 if (!expected.equals(actual)) { 651 return "Expected toPattern='" + expected + "'; got '" + actual + "'"; 652 } 653 } 654 if (tuple.toLocalizedPattern != null) { 655 String expected = tuple.toLocalizedPattern; 656 String actual = PatternStringUtils.propertiesToPatternString(properties); 657 if (!expected.equals(actual)) { 658 return "Expected toLocalizedPattern='" + expected + "'; got '" + actual + "'"; 659 } 660 } 661 return null; 662 } 663 664 @Override 665 public String parse(DataDrivenNumberFormatTestData tuple) { 666 String pattern = (tuple.pattern == null) ? "0" : tuple.pattern; 667 DecimalFormatProperties properties; 668 ParsePosition ppos = new ParsePosition(0); 669 Number actual; 670 try { 671 properties = PatternStringParser.parseToProperties(pattern, 672 tuple.currency != null ? PatternStringParser.IGNORE_ROUNDING_ALWAYS 673 : PatternStringParser.IGNORE_ROUNDING_NEVER); 674 propertiesFromTuple(tuple, properties); 675 actual = NumberParserImpl.parseStatic(tuple.parse, 676 ppos, 677 properties, 678 DecimalFormatSymbols.getInstance(tuple.locale)); 679 } catch (IllegalArgumentException e) { 680 return "parse exception: " + e.getMessage(); 681 } 682 return compareParseResult(tuple.output, actual, ppos); 683 } 684 685 @Override 686 public String parseCurrency(DataDrivenNumberFormatTestData tuple) { 687 String pattern = (tuple.pattern == null) ? "0" : tuple.pattern; 688 DecimalFormatProperties properties; 689 ParsePosition ppos = new ParsePosition(0); 690 CurrencyAmount actual; 691 try { 692 properties = PatternStringParser.parseToProperties(pattern, 693 tuple.currency != null ? PatternStringParser.IGNORE_ROUNDING_ALWAYS 694 : PatternStringParser.IGNORE_ROUNDING_NEVER); 695 propertiesFromTuple(tuple, properties); 696 actual = NumberParserImpl.parseStaticCurrency(tuple.parse, 697 ppos, 698 properties, 699 DecimalFormatSymbols.getInstance(tuple.locale)); 700 } catch (IllegalArgumentException e) { 701 e.printStackTrace(); 702 return "parse exception: " + e.getMessage(); 703 } 704 return compareParseCurrencyResult(tuple.output, tuple.outputCurrency, actual, ppos); 705 } 706 }; 707 708 @Test TestNoUnknownIDs()709 public void TestNoUnknownIDs() { 710 DataDrivenNumberFormatTestUtility.checkNoUnknownIDs("numberformattestspecification.txt", "CHJKP"); 711 } 712 713 @Test TestDataDrivenICU4J()714 public void TestDataDrivenICU4J() { 715 DataDrivenNumberFormatTestUtility 716 .runFormatSuiteIncludingKnownFailures("numberformattestspecification.txt", ICU4J); 717 } 718 719 @Test TestDataDrivenJDK()720 public void TestDataDrivenJDK() { 721 // #13373: Since not all JDK implementations are the same, test only whitelisted JDKs 722 // with known behavior. The JDK version should be occasionally updated. 723 org.junit.Assume.assumeTrue(TestUtil.getJavaRuntimeName() == TestUtil.JavaRuntimeName.OpenJDK 724 && TestUtil.getJavaVersion() == 8); 725 726 DataDrivenNumberFormatTestUtility 727 .runFormatSuiteIncludingKnownFailures("numberformattestspecification.txt", JDK); 728 } 729 730 @Test TestDataDrivenICU4JProperties()731 public void TestDataDrivenICU4JProperties() { 732 DataDrivenNumberFormatTestUtility 733 .runFormatSuiteIncludingKnownFailures("numberformattestspecification.txt", ICU4J_Properties); 734 } 735 } 736