1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 ********************************************************************** 6 * Copyright (c) 2004-2016, International Business Machines 7 * Corporation and others. All Rights Reserved. 8 ********************************************************************** 9 * Author: Alan Liu 10 * Created: April 6, 2004 11 * Since: ICU 3.0 12 ********************************************************************** 13 */ 14 package ohos.global.icu.dev.test.format; 15 16 import java.text.AttributedCharacterIterator; 17 import java.text.AttributedString; 18 import java.text.ChoiceFormat; 19 import java.text.FieldPosition; 20 import java.text.Format; 21 import java.text.ParseException; 22 import java.text.ParsePosition; 23 import java.util.Date; 24 import java.util.HashMap; 25 import java.util.Iterator; 26 import java.util.Locale; 27 import java.util.Map; 28 import java.util.Set; 29 import java.util.TreeMap; 30 31 import org.junit.Test; 32 import org.junit.runner.RunWith; 33 import org.junit.runners.JUnit4; 34 35 import ohos.global.icu.dev.test.TestFmwk; 36 import ohos.global.icu.text.DateFormat; 37 import ohos.global.icu.text.DecimalFormat; 38 import ohos.global.icu.text.DecimalFormatSymbols; 39 import ohos.global.icu.text.MessageFormat; 40 import ohos.global.icu.text.MessagePattern; 41 import ohos.global.icu.text.NumberFormat; 42 import ohos.global.icu.text.SimpleDateFormat; 43 import ohos.global.icu.text.UFormat; 44 import ohos.global.icu.util.Calendar; 45 import ohos.global.icu.util.GregorianCalendar; 46 import ohos.global.icu.util.TimeZone; 47 import ohos.global.icu.util.ULocale; 48 49 50 51 @RunWith(JUnit4.class) 52 public class TestMessageFormat extends TestFmwk { 53 @Test TestBug3()54 public void TestBug3() 55 { 56 double myNumber = -123456; 57 DecimalFormat form = null; 58 Locale locale[] = { 59 new Locale("ar", "", ""), 60 new Locale("be", "", ""), 61 new Locale("bg", "", ""), 62 new Locale("ca", "", ""), 63 new Locale("cs", "", ""), 64 new Locale("da", "", ""), 65 new Locale("de", "", ""), 66 new Locale("de", "AT", ""), 67 new Locale("de", "CH", ""), 68 new Locale("el", "", ""), // 10 69 new Locale("en", "CA", ""), 70 new Locale("en", "GB", ""), 71 new Locale("en", "IE", ""), 72 new Locale("en", "US", ""), 73 new Locale("es", "", ""), 74 new Locale("et", "", ""), 75 new Locale("fi", "", ""), 76 new Locale("fr", "", ""), 77 new Locale("fr", "BE", ""), 78 new Locale("fr", "CA", ""), // 20 79 new Locale("fr", "CH", ""), 80 new Locale("he", "", ""), 81 new Locale("hr", "", ""), 82 new Locale("hu", "", ""), 83 new Locale("is", "", ""), 84 new Locale("it", "", ""), 85 new Locale("it", "CH", ""), 86 new Locale("ja", "", ""), 87 new Locale("ko", "", ""), 88 new Locale("lt", "", ""), // 30 89 new Locale("lv", "", ""), 90 new Locale("mk", "", ""), 91 new Locale("nl", "", ""), 92 new Locale("nl", "BE", ""), 93 new Locale("no", "", ""), 94 new Locale("pl", "", ""), 95 new Locale("pt", "", ""), 96 new Locale("ro", "", ""), 97 new Locale("ru", "", ""), 98 new Locale("sh", "", ""), // 40 99 new Locale("sk", "", ""), 100 new Locale("sl", "", ""), 101 new Locale("sq", "", ""), 102 new Locale("sr", "", ""), 103 new Locale("sv", "", ""), 104 new Locale("tr", "", ""), 105 new Locale("uk", "", ""), 106 new Locale("zh", "", ""), 107 new Locale("zh", "TW", "") // 49 108 }; 109 StringBuffer buffer = new StringBuffer(); 110 ParsePosition parsePos = new ParsePosition(0); 111 int i; 112 for (i= 0; i < 49; i++) { 113 // form = (DecimalFormat)NumberFormat.getCurrencyInstance(locale[i]); 114 form = (DecimalFormat)NumberFormat.getInstance(locale[i]); 115 if (form == null) { 116 errln("Number format creation failed for " + locale[i].getDisplayName()); 117 continue; 118 } 119 FieldPosition pos = new FieldPosition(FieldPosition_DONT_CARE); 120 buffer.setLength(0); 121 form.format(myNumber, buffer, pos); 122 parsePos.setIndex(0); 123 Object result = form.parse(buffer.toString(), parsePos); 124 logln(locale[i].getDisplayName() + " -> " + result); 125 if (parsePos.getIndex() != buffer.length()) { 126 errln("Number format parse failed."); 127 } 128 } 129 } 130 131 @Test TestBug1()132 public void TestBug1() 133 { 134 final double limit[] = {0.0, 1.0, 2.0}; 135 final String formats[] = {"0.0<=Arg<1.0", 136 "1.0<=Arg<2.0", 137 "2.0<-Arg"}; 138 ChoiceFormat cf = new ChoiceFormat(limit, formats); 139 assertEquals("ChoiceFormat.format", formats[1], cf.format(1)); 140 } 141 142 @Test TestBug2()143 public void TestBug2() 144 { 145 // {sfb} use double format in pattern, so result will match (not strictly necessary) 146 final String pattern = "There {0,choice,0.0#are no files|1.0#is one file|1.0<are {0, number} files} on disk {1}. "; 147 logln("The input pattern : " + pattern); 148 try { 149 MessageFormat fmt = new MessageFormat(pattern); 150 assertEquals("toPattern", pattern, fmt.toPattern()); 151 } catch (IllegalArgumentException e) { 152 errln("MessageFormat pattern creation failed."); 153 } 154 } 155 156 @Test TestPattern()157 public void TestPattern() // aka PatternTest() 158 { 159 Object testArgs[] = { 160 new Double(1), new Double(3456), 161 "Disk", new Date(1000000000L) 162 }; 163 String testCases[] = { 164 "Quotes '', '{', 'a' {0} '{0}'", 165 "Quotes '', '{', 'a' {0,number} '{0}'", 166 "'{'1,number,'#',##} {1,number,'#',##}", 167 "There are {1} files on {2} at {3}.", 168 "On {2}, there are {1} files, with {0,number,currency}.", 169 "'{1,number,percent}', {1,number,percent},", 170 "'{1,date,full}', {1,date,full},", 171 "'{3,date,full}', {3,date,full},", 172 "'{1,number,#,##}' {1,number,#,##}", 173 }; 174 175 // ICU 4.8 returns the original pattern (testCases) 176 // rather than toPattern() reconstituting a new, equivalent pattern string (testResultPatterns). 177 /*String testResultPatterns[] = { 178 "Quotes '', '{', a {0} '{'0}", 179 "Quotes '', '{', a {0,number} '{'0}", 180 "'{'1,number,#,##} {1,number,'#'#,##}", 181 "There are {1} files on {2} at {3}.", 182 "On {2}, there are {1} files, with {0,number,currency}.", 183 "'{'1,number,percent}, {1,number,percent},", 184 "'{'1,date,full}, {1,date,full},", 185 "'{'3,date,full}, {3,date,full},", 186 "'{'1,number,#,##} {1,number,#,##}" 187 };*/ 188 189 String testResultStrings[] = { 190 "Quotes ', {, 'a' 1 {0}", 191 "Quotes ', {, 'a' 1 {0}", 192 "{1,number,'#',##} #34,56", 193 "There are 3,456 files on Disk at 1/12/70, 5:46 AM.", 194 "On Disk, there are 3,456 files, with $1.00.", 195 "{1,number,percent}, 345,600%,", 196 "{1,date,full}, Wednesday, December 31, 1969,", 197 "{3,date,full}, Monday, January 12, 1970,", 198 "{1,number,#,##} 34,56" 199 }; 200 201 for (int i = 0; i < 9; ++i) { 202 //it_out << "\nPat in: " << testCases[i]); 203 204 //String buffer; 205 MessageFormat form = null; 206 try { 207 form = new MessageFormat(testCases[i], Locale.US); 208 } catch (IllegalArgumentException e1) { 209 errln("MessageFormat for " + testCases[i] + " creation failed."); 210 continue; 211 } 212 // ICU 4.8 returns the original pattern (testCases) 213 // rather than toPattern() reconstituting a new, equivalent pattern string (testResultPatterns). 214 // assertEquals("\"" + testCases[i] + "\".toPattern()", testResultPatterns[i], form.toPattern()); 215 assertEquals("\"" + testCases[i] + "\".toPattern()", testCases[i], form.toPattern()); 216 // Note: An alternative test would be to build MessagePattern objects for 217 // both the input and output patterns and compare them, taking SKIP_SYNTAX etc. 218 // into account. 219 // (Too much trouble...) 220 221 //it_out << "Pat out: " << form.toPattern(buffer)); 222 StringBuffer result = new StringBuffer(); 223 FieldPosition fieldpos = new FieldPosition(FieldPosition_DONT_CARE); 224 form.format(testArgs, result, fieldpos); 225 assertEquals("format", testResultStrings[i], result.toString()); 226 227 //it_out << "Result: " << result); 228 // /* TODO: Look at this test and see if this is still a valid test */ 229 // logln("---------------- test parse ----------------"); 230 // 231 // int count = 4; 232 // form.toPattern(buffer); 233 // logln("MSG pattern for parse: " + buffer); 234 // 235 // int parseCount = 0; 236 // Formattable* values = form.parse(result, parseCount, success); 237 // if (U_FAILURE(success)) { 238 // errln("MessageFormat failed test #5"); 239 // logln(String("MessageFormat failed test #5 with error code ")+(int)success); 240 // } else if (parseCount != count) { 241 // errln("MSG count not %d as expected. Got %d", count, parseCount); 242 // } 243 // UBool failed = FALSE; 244 // for (int j = 0; j < parseCount; ++j) { 245 // if (values == 0 || testArgs[j] != values[j]) { 246 // errln(((String)"MSG testargs[") + j + "]: " + toString(testArgs[j])); 247 // errln(((String)"MSG values[") + j + "] : " + toString(values[j])); 248 // failed = TRUE; 249 // } 250 // } 251 // if (failed) 252 // errln("MessageFormat failed test #6"); 253 } 254 } 255 256 @Test TestSample()257 public void TestSample() // aka sample() 258 { 259 MessageFormat form = null; 260 StringBuffer buffer2 = new StringBuffer(); 261 try { 262 form = new MessageFormat("There are {0} files on {1}"); 263 } catch (IllegalArgumentException e1) { 264 errln("Sample message format creation failed."); 265 return; 266 } 267 Object testArgs1[] = { "abc", "def" }; 268 FieldPosition fieldpos = new FieldPosition(FieldPosition_DONT_CARE); 269 assertEquals("format", 270 "There are abc files on def", 271 form.format(testArgs1, buffer2, fieldpos).toString()); 272 } 273 274 @Test TestStaticFormat()275 public void TestStaticFormat() 276 { 277 Object arguments[] = { 278 new Integer(7), 279 new Date(871068000000L), 280 "a disturbance in the Force" 281 }; 282 283 assertEquals("format", 284 "At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7.", 285 MessageFormat.format("At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.", 286 arguments)); 287 } 288 289 static final int FieldPosition_DONT_CARE = -1; 290 291 @Test TestSimpleFormat()292 public void TestSimpleFormat() 293 { 294 Object testArgs1[] = {new Integer(0), "MyDisk"}; 295 Object testArgs2[] = {new Integer(1), "MyDisk"}; 296 Object testArgs3[] = {new Integer(12), "MyDisk"}; 297 298 MessageFormat form = new MessageFormat( 299 "The disk \"{1}\" contains {0} file(s)."); 300 301 StringBuffer string = new StringBuffer(); 302 FieldPosition ignore = new FieldPosition(FieldPosition_DONT_CARE); 303 form.format(testArgs1, string, ignore); 304 assertEquals("format", 305 "The disk \"MyDisk\" contains 0 file(s).", 306 string.toString()); 307 308 string.setLength(0); 309 form.format(testArgs2, string, ignore); 310 assertEquals("format", 311 "The disk \"MyDisk\" contains 1 file(s).", 312 string.toString()); 313 314 string.setLength(0); 315 form.format(testArgs3, string, ignore); 316 assertEquals("format", 317 "The disk \"MyDisk\" contains 12 file(s).", 318 string.toString()); 319 } 320 321 @Test TestMsgFormatChoice()322 public void TestMsgFormatChoice() 323 { 324 MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}."); 325 double filelimits[] = {0,1,2}; 326 String filepart[] = {"no files","one file","{0,number} files"}; 327 ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart); 328 form.setFormat(1, fileform); // NOT zero, see below 329 330 FieldPosition ignore = new FieldPosition(FieldPosition_DONT_CARE); 331 StringBuffer string = new StringBuffer(); 332 Object testArgs1[] = {new Integer(0), "MyDisk"}; 333 form.format(testArgs1, string, ignore); 334 assertEquals("format#1", 335 "The disk \"MyDisk\" contains no files.", 336 string.toString()); 337 338 string.setLength(0); 339 Object testArgs2[] = {new Integer(1), "MyDisk"}; 340 form.format(testArgs2, string, ignore); 341 assertEquals("format#2", 342 "The disk \"MyDisk\" contains one file.", 343 string.toString()); 344 345 string.setLength(0); 346 Object testArgs3[] = {new Integer(1273), "MyDisk"}; 347 form.format(testArgs3, string, ignore); 348 assertEquals("format#3", 349 "The disk \"MyDisk\" contains 1,273 files.", 350 string.toString()); 351 } 352 353 //--------------------------------- 354 // API Tests 355 //--------------------------------- 356 357 @Test TestClone()358 public void TestClone() 359 { 360 MessageFormat x = new MessageFormat("There are {0} files on {1}"); 361 MessageFormat z = new MessageFormat("There are {0} files on {1} created"); 362 MessageFormat y = null; 363 y = (MessageFormat)x.clone(); 364 if (x.equals(y) && 365 !x.equals(z) && 366 !y.equals(z) ) 367 logln("First test (operator ==): Passed!"); 368 else { 369 errln("First test (operator ==): Failed!"); 370 } 371 if ((x.equals(y) && y.equals(x)) && 372 (!x.equals(z) && !z.equals(x)) && 373 (!y.equals(z) && !z.equals(y)) ) 374 logln("Second test (equals): Passed!"); 375 else { 376 errln("Second test (equals): Failed!"); 377 } 378 379 } 380 381 @Test TestEquals()382 public void TestEquals() 383 { 384 MessageFormat x = new MessageFormat("There are {0} files on {1}"); 385 MessageFormat y = new MessageFormat("There are {0} files on {1}"); 386 if (!x.equals(y)) { 387 errln("First test (operator ==): Failed!"); 388 } 389 390 } 391 392 @Test TestNotEquals()393 public void TestNotEquals() 394 { 395 MessageFormat x = new MessageFormat("There are {0} files on {1}"); 396 MessageFormat y = new MessageFormat("There are {0} files on {1}"); 397 y.setLocale(Locale.FRENCH); 398 if (x.equals(y)) { 399 errln("First test (operator !=): Failed!"); 400 } 401 y = new MessageFormat("There are {0} files on {1}"); 402 y.applyPattern("There are {0} files on {1} the disk"); 403 if (x.equals(y)) { 404 errln("Second test (operator !=): Failed!"); 405 } 406 } 407 408 @Test TestHashCode()409 public void TestHashCode() 410 { 411 ULocale save = ULocale.getDefault(); 412 ULocale.setDefault(ULocale.US); 413 414 MessageFormat x = new MessageFormat("There are {0} files on {1}"); 415 MessageFormat z = new MessageFormat("There are {0} files on {1}"); 416 MessageFormat y = null; 417 y = (MessageFormat)x.clone(); 418 if (x.hashCode() != y.hashCode()) 419 errln("FAIL: identical objects have different hashcodes"); 420 if (x.hashCode() != z.hashCode()) 421 errln("FAIL: identical objects have different hashcodes"); 422 423 /* These are not errors 424 y.setLocale(ULocale.FRENCH); 425 if (x.hashCode() == y.hashCode()) 426 errln("FAIL: different objects have same hashcodes. Locale ignored"); 427 428 z.applyPattern("There are {0} files on {1} the disk"); 429 if (x.hashCode() == z.hashCode()) 430 errln("FAIL: different objects have same hashcodes. Pattern ignored"); 431 */ 432 433 ULocale.setDefault(save); 434 } 435 436 @Test TestSetLocale()437 public void TestSetLocale() 438 { 439 Object arguments[] = { 440 new Double(456.83), 441 new Date(871068000000L), 442 "deposit" 443 }; 444 445 StringBuffer result = new StringBuffer(); 446 447 //String formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}."; 448 String formatStr = "At <time> on {1,date}, you made a {2} of {0,number,currency}."; 449 // {sfb} to get $, would need Locale::US, not Locale::ENGLISH 450 // Just use unlocalized currency symbol. 451 // ICU 62: use the unknown currency symbol XXX. 452 //String compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of $456.83."; 453 String compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of "; 454 compareStrEng += "\u00a4"; 455 compareStrEng += "456.83."; 456 // {sfb} to get DM, would need Locale::GERMANY, not Locale::GERMAN 457 // Just use unlocalized currency symbol. 458 //String compareStrGer = "At <time> on 08.08.1997, you made a deposit of 456,83 DM."; 459 String compareStrGer = "At <time> on 08.08.1997, you made a deposit of "; 460 compareStrGer += "456,83\u00a0"; 461 compareStrGer += "XXX"; 462 compareStrGer += "."; 463 464 MessageFormat msg = new MessageFormat(formatStr, Locale.ENGLISH); 465 result.setLength(0); 466 FieldPosition pos = new FieldPosition(FieldPosition_DONT_CARE); 467 result = msg.format( 468 arguments, 469 result, 470 pos); 471 assertEquals("format", compareStrEng, result.toString()); 472 473 msg.setLocale(Locale.ENGLISH); 474 assertEquals("getLocale", Locale.ENGLISH, msg.getLocale()); 475 476 msg.setLocale(Locale.GERMAN); 477 assertEquals("getLocale", Locale.GERMAN, msg.getLocale()); 478 479 msg.applyPattern(formatStr); 480 result.setLength(0); 481 result = msg.format( 482 arguments, 483 result, 484 pos); 485 assertEquals("format", compareStrGer, result.toString()); 486 487 //Cover getULocale() 488 logln("Testing set/get ULocale ..."); 489 msg.setLocale(ULocale.ENGLISH); 490 assertEquals("getULocale", ULocale.ENGLISH, msg.getULocale()); 491 492 msg.setLocale(ULocale.GERMAN); 493 assertEquals("getULocale", ULocale.GERMAN, msg.getULocale()); 494 495 msg.applyPattern(formatStr); 496 result.setLength(0); 497 result = msg.format( 498 arguments, 499 result, 500 pos); 501 assertEquals("format", compareStrGer, result.toString()); 502 } 503 504 @SuppressWarnings("static-access") 505 @Test TestFormat()506 public void TestFormat() 507 { 508 final Object ft_arr[] = 509 { 510 new Date(871068000000L) 511 }; 512 513 StringBuffer result = new StringBuffer(); 514 515 //String formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}."; 516 String formatStr = "On {0,date}, it began."; 517 String compareStr = "On Aug 8, 1997, it began."; 518 519 MessageFormat msg = new MessageFormat(formatStr); 520 FieldPosition fp = new FieldPosition(FieldPosition_DONT_CARE); 521 522 try { 523 msg.format(new Date(871068000000L), 524 result, 525 fp); 526 errln("*** MSG format without expected error code."); 527 } catch (Exception e1) { 528 } 529 530 result.setLength(0); 531 result = msg.format( 532 ft_arr, 533 result, 534 fp); 535 assertEquals("format", compareStr, result.toString()); 536 537 Map<String,Object> map = new HashMap<String,Object>(); 538 try{ 539 msg.format("", map); 540 } catch(Exception e){ 541 errln("MessageFormat.format(String,Map) was not suppose to return " + 542 "an exception."); 543 } 544 } 545 546 @Test TestParse()547 public void TestParse() 548 { 549 String msgFormatString = "{0} =sep= {1}"; 550 MessageFormat msg = new MessageFormat(msgFormatString); 551 String source = "abc =sep= def"; 552 553 try { 554 Object[] fmt_arr = msg.parse(source); 555 if (fmt_arr.length != 2) { 556 errln("*** MSG parse (ustring, count, err) count err."); 557 } else { 558 // TODO: This if statement seems to be redundant. [tschumann] 559 if (fmt_arr.length != 2) { 560 errln("*** MSG parse (ustring, parsepos., count) count err."); 561 } else { 562 assertEquals("parse()[0]", "abc", fmt_arr[0]); 563 assertEquals("parse()[1]", "def", fmt_arr[1]); 564 } 565 } 566 } catch (ParseException e1) { 567 errln("*** MSG parse (ustring, count, err) error."); 568 } 569 570 ParsePosition pp = new ParsePosition(0); 571 572 Object[] fmt_arr = msg.parse(source, pp); 573 if (pp.getIndex()==0 || fmt_arr==null) { 574 errln("*** MSG parse (ustring, parsepos., count) error."); 575 } else { 576 if (fmt_arr.length != 2) { 577 errln("*** MSG parse (ustring, parsepos., count) count err."); 578 } else { 579 assertEquals("parse()[0]", "abc", fmt_arr[0]); 580 assertEquals("parse()[1]", "def", fmt_arr[1]); 581 } 582 } 583 584 pp.setIndex(0); 585 Object[] fmta; 586 587 fmta = (Object[]) msg.parseObject( source, pp ); 588 if (pp.getIndex() == 0) { 589 errln("*** MSG parse (ustring, Object, parsepos ) error."); 590 } else { 591 if (fmta.length != 2) { 592 errln("*** MSG parse (ustring, count, err) count err."); 593 } else { 594 // TODO: Don't we want to check fmta? 595 // In this case this if statement would be redundant, too. 596 // [tschumann] 597 if (fmt_arr.length != 2) { 598 errln("*** MSG parse (ustring, parsepos., count) count err."); 599 } else { 600 // TODO: Don't we want to check fmta? [tschumann] 601 assertEquals("parse()[0]", "abc", fmt_arr[0]); 602 assertEquals("parse()[1]", "def", fmt_arr[1]); 603 } 604 } 605 } 606 } 607 608 /** 609 * Of course, in Java there is no adopt, but we retain the same 610 * method name. [alan] 611 */ 612 @Test TestAdopt()613 public void TestAdopt() 614 { 615 String formatStr = "{0,date},{1},{2,number}"; 616 String formatStrChange = "{0,number},{1,number},{2,date}"; 617 MessageFormat msg = new MessageFormat(formatStr); 618 MessageFormat msgCmp = new MessageFormat(formatStr); 619 Format[] formats = msg.getFormats(); 620 Format[] formatsCmp = msgCmp.getFormats(); 621 Format[] formatsChg = null; 622 Format[] formatsAct = null; 623 Format a = null; 624 Format b = null; 625 Format[] formatsToAdopt = null; 626 627 if (formats==null || formatsCmp==null || (formats.length <= 0) || (formats.length != formatsCmp.length)) { 628 errln("Error getting Formats"); 629 return; 630 } 631 632 int i; 633 634 for (i = 0; i < formats.length; i++) { 635 a = formats[i]; 636 b = formatsCmp[i]; 637 if ((a != null) && (b != null)) { 638 if (!a.equals(b)) { 639 errln("a != b"); 640 return; 641 } 642 } else if ((a != null) || (b != null)) { 643 errln("(a != null) || (b != null)"); 644 return; 645 } 646 } 647 648 msg.applyPattern( formatStrChange ); //set msg formats to something different 649 formatsChg = msg.getFormats(); // tested function 650 if (formatsChg==null || (formatsChg.length != formats.length)) { 651 errln("Error getting Formats"); 652 return; 653 } 654 655 boolean diff; 656 diff = true; 657 for (i = 0; i < formats.length; i++) { 658 a = formatsChg[i]; 659 b = formatsCmp[i]; 660 if ((a != null) && (b != null)) { 661 if (a.equals(b)) { 662 logln("formatsChg == formatsCmp at index " + i); 663 diff = false; 664 } 665 } 666 } 667 if (!diff) { 668 errln("*** MSG getFormats diff err."); 669 return; 670 } 671 672 logln("MSG getFormats tested."); 673 674 msg.setFormats( formatsCmp ); //tested function 675 676 formatsAct = msg.getFormats(); 677 if (formatsAct==null || (formatsAct.length <=0) || (formatsAct.length != formatsCmp.length)) { 678 errln("Error getting Formats"); 679 return; 680 } 681 682 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern()); 683 // ICU 4.8 does not support toPattern() when there are custom formats (from setFormat() etc.). 684 // assertEquals("msg.toPattern()", formatStr, msg.toPattern()); 685 try { 686 msg.toPattern(); 687 errln("msg.setFormat().toPattern() does not throw an IllegalStateException"); 688 } catch(IllegalStateException e) { 689 // ok 690 } 691 692 for (i = 0; i < formatsAct.length; i++) { 693 a = formatsAct[i]; 694 b = formatsCmp[i]; 695 if ((a != null) && (b != null)) { 696 if (!a.equals(b)) { 697 errln("formatsAct != formatsCmp at index " + i); 698 return; 699 } 700 } else if ((a != null) || (b != null)) { 701 errln("(a != null) || (b != null)"); 702 return; 703 } 704 } 705 logln("MSG setFormats tested."); 706 707 //---- 708 709 msg.applyPattern( formatStrChange ); //set msg formats to something different 710 711 formatsToAdopt = new Format[formatsCmp.length]; 712 if (formatsToAdopt==null) { 713 errln("memory allocation error"); 714 return; 715 } 716 717 for (i = 0; i < formatsCmp.length; i++) { 718 if (formatsCmp[i] == null) { 719 formatsToAdopt[i] = null; 720 } else { 721 formatsToAdopt[i] = (Format) formatsCmp[i].clone(); 722 if (formatsToAdopt[i]==null) { 723 errln("Can't clone format at index " + i); 724 return; 725 } 726 } 727 } 728 msg.setFormats( formatsToAdopt ); // function to test 729 730 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern()); 731 // ICU 4.8 does not support toPattern() when there are custom formats (from setFormat() etc.). 732 // assertEquals("msg.toPattern()", formatStr, msg.toPattern()); 733 734 formatsAct = msg.getFormats(); 735 if (formatsAct==null || (formatsAct.length <=0) || (formatsAct.length != formatsCmp.length)) { 736 errln("Error getting Formats"); 737 return; 738 } 739 740 for (i = 0; i < formatsAct.length; i++) { 741 a = formatsAct[i]; 742 b = formatsCmp[i]; 743 if ((a != null) && (b != null)) { 744 if (!a.equals(b)) { 745 errln("a != b"); 746 return; 747 } 748 } else if ((a != null) || (b != null)) { 749 errln("(a != null) || (b != null)"); 750 return; 751 } 752 } 753 logln("MSG adoptFormats tested."); 754 755 //---- adoptFormat 756 757 msg.applyPattern( formatStrChange ); //set msg formats to something different 758 759 formatsToAdopt = new Format[formatsCmp.length]; 760 if (formatsToAdopt==null) { 761 errln("memory allocation error"); 762 return; 763 } 764 765 for (i = 0; i < formatsCmp.length; i++) { 766 if (formatsCmp[i] == null) { 767 formatsToAdopt[i] = null; 768 } else { 769 formatsToAdopt[i] = (Format) formatsCmp[i].clone(); 770 if (formatsToAdopt[i]==null) { 771 errln("Can't clone format at index " + i); 772 return; 773 } 774 } 775 } 776 777 for ( i = 0; i < formatsCmp.length; i++ ) { 778 msg.setFormat( i, formatsToAdopt[i] ); // function to test 779 } 780 781 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern()); 782 // ICU 4.8 does not support toPattern() when there are custom formats (from setFormat() etc.). 783 // assertEquals("msg.toPattern()", formatStr, msg.toPattern()); 784 785 formatsAct = msg.getFormats(); 786 if (formatsAct==null || (formatsAct.length <=0) || (formatsAct.length != formatsCmp.length)) { 787 errln("Error getting Formats"); 788 return; 789 } 790 791 for (i = 0; i < formatsAct.length; i++) { 792 a = formatsAct[i]; 793 b = formatsCmp[i]; 794 if ((a != null) && (b != null)) { 795 if (!a.equals(b)) { 796 errln("a != b"); 797 return; 798 } 799 } else if ((a != null) || (b != null)) { 800 errln("(a != null) || (b != null)"); 801 return; 802 } 803 } 804 logln("MSG adoptFormat tested."); 805 } 806 807 /** 808 * Verify that MessageFormat accomodates more than 10 arguments and 809 * more than 10 subformats. 810 */ 811 @Test TestUnlimitedArgsAndSubformats()812 public void TestUnlimitedArgsAndSubformats() { 813 final String pattern = 814 "On {0,date} (aka {0,date,short}, aka {0,date,long}) "+ 815 "at {0,time} (aka {0,time,short}, aka {0,time,long}) "+ 816 "there were {1,number} werjes "+ 817 "(a {3,number,percent} increase over {2,number}) "+ 818 "despite the {4}''s efforts "+ 819 "and to delight of {5}, {6}, {7}, {8}, {9}, and {10} {11}."; 820 try { 821 MessageFormat msg = new MessageFormat(pattern); 822 823 final Object ARGS[] = { 824 new Date(10000000000000L), 825 new Integer(1303), 826 new Integer(1202), 827 new Double(1303.0/1202 - 1), 828 "Glimmung", 829 "the printers", 830 "Nick", 831 "his father", 832 "his mother", 833 "the spiddles", 834 "of course", 835 "Horace" 836 }; 837 838 String expected = 839 "On Nov 20, 2286 (aka 11/20/86, aka November 20, 2286) "+ 840 "at 9:46:40 AM (aka 9:46 AM, aka 9:46:40 AM PST) "+ 841 "there were 1,303 werjes "+ 842 "(a 8% increase over 1,202) "+ 843 "despite the Glimmung's efforts "+ 844 "and to delight of the printers, Nick, his father, "+ 845 "his mother, the spiddles, and of course Horace."; 846 assertEquals("format", expected, msg.format(ARGS)); 847 } catch (IllegalArgumentException e1) { 848 errln("FAIL: constructor failed"); 849 } 850 } 851 852 // test RBNF extensions to message format 853 @Test TestRBNF()854 public void TestRBNF() { 855 // WARNING: this depends on the RBNF formats for en_US 856 Locale locale = Locale.US; 857 String[] values = { 858 // decimal values do not format completely for ordinal or duration, and 859 // do not always parse, so do not include them 860 "0", "1", "12", "100", "123", "1001", "123,456", "-17", 861 }; 862 String[] formats = { 863 "There are {0,spellout} files to search.", 864 "There are {0,spellout,%simplified} files to search.", 865 "The bogus spellout {0,spellout,%BOGUS} files behaves like the default.", 866 "This is the {0,ordinal} file to search.", // TODO fix bug, ordinal does not parse 867 "Searching this file will take {0,duration} to complete.", 868 "Searching this file will take {0,duration,%with-words} to complete.", 869 }; 870 final NumberFormat numFmt = NumberFormat.getInstance(locale); 871 Object[] args = new Object[1]; 872 Number num = null; 873 for (int i = 0; i < formats.length; ++i) { 874 MessageFormat fmt = new MessageFormat(formats[i], locale); 875 logln("Testing format pattern: '" + formats[i] + "'"); 876 for (int j = 0; j < values.length; ++j) { 877 try { 878 num = numFmt.parse(values[j]); 879 } 880 catch (Exception e) { 881 throw new IllegalStateException("failed to parse test argument"); 882 } 883 args[0] = num; 884 String result = fmt.format(args); 885 logln("value: " + num + " --> " + result); 886 887 if (i != 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3) 888 try { 889 Object[] parsedArgs = fmt.parse(result); 890 if (parsedArgs.length != 1) { 891 errln("parse returned " + parsedArgs.length + " args"); 892 } else if (!parsedArgs[0].equals(num)) { 893 errln("parsed argument " + parsedArgs[0] + " != " + num); 894 } 895 } 896 catch (ParseException e) { 897 errln("parse of '" + result + "' returned exception: " 898 + e.getMessage() + " " + e.getErrorOffset()); 899 } 900 } 901 } 902 } 903 } 904 905 @Test TestSetGetFormats()906 public void TestSetGetFormats() 907 { 908 Object arguments[] = { 909 new Double(456.83), 910 new Date(871068000000L), 911 "deposit" 912 }; 913 914 StringBuffer result = new StringBuffer(); 915 916 String formatStr = "At <time> on {1,date}, you made a {2} of {0,number,currency}."; 917 // original expected format result 918 String compareStr = "At <time> on Aug 8, 1997, you made a deposit of $456.83."; 919 // the date being German-style, but the currency being English-style 920 String compareStr2 = "At <time> on 08.08.1997, you made a deposit of "; 921 compareStr2 += "\u00A4"; 922 compareStr2 += "456.83."; 923 // both date and currency formats are German-style 924 String compareStr3 = "At <time> on 08.08.1997, you made a deposit of "; 925 compareStr3 += "456,83\u00a0"; 926 compareStr3 += "XXX"; 927 compareStr3 += "."; 928 929 MessageFormat msg = new MessageFormat(formatStr, ULocale.US); 930 result.setLength(0); 931 FieldPosition pos = new FieldPosition(FieldPosition_DONT_CARE); 932 result = msg.format( 933 arguments, 934 result, 935 pos); 936 assertEquals("format", compareStr, result.toString()); 937 938 // constructs a Format array with a English-style Currency formatter 939 // and a German-style Date formatter 940 // might not meaningful, just for testing setFormatsByArgIndex 941 Format[] fmts = new Format[] { 942 NumberFormat.getCurrencyInstance(ULocale.ENGLISH), 943 DateFormat.getDateInstance(DateFormat.DEFAULT, ULocale.GERMAN) 944 }; 945 946 msg.setFormatsByArgumentIndex(fmts); 947 result.setLength(0); 948 pos = new FieldPosition(FieldPosition_DONT_CARE); 949 result = msg.format( 950 arguments, 951 result, 952 pos); 953 assertEquals("format", compareStr2, result.toString()); 954 955 // Construct a German-style Currency formatter, replace the corresponding one 956 // Thus both formatters should format objects with German-style 957 Format newFmt = NumberFormat.getCurrencyInstance(ULocale.GERMAN); 958 msg.setFormatByArgumentIndex(0, newFmt); 959 result.setLength(0); 960 pos = new FieldPosition(FieldPosition_DONT_CARE); 961 result = msg.format( 962 arguments, 963 result, 964 pos); 965 assertEquals("format", compareStr3, result.toString()); 966 967 // verify getFormatsByArgumentIndex 968 // you should got three formats by that 969 // - DecimalFormat locale: de 970 // - SimpleDateFormat locale: de 971 // - null 972 Format[] fmts2 = msg.getFormatsByArgumentIndex(); 973 assertEquals("1st subformmater: Format Class", "ohos.global.icu.text.DecimalFormat", fmts2[0].getClass().getName()); 974 assertEquals("1st subformmater: its Locale", ULocale.GERMAN, ((UFormat)fmts2[0]).getLocale(ULocale.VALID_LOCALE)); 975 assertEquals("2nd subformatter: Format Class", "ohos.global.icu.text.SimpleDateFormat", fmts2[1].getClass().getName()); 976 assertEquals("2nd subformmater: its Locale", ULocale.GERMAN, ((UFormat)fmts2[1]).getLocale(ULocale.VALID_LOCALE)); 977 assertTrue("The third subFormatter is null", null == fmts2[2]); 978 } 979 980 // Test the fix pattern api 981 @Test TestAutoQuoteApostrophe()982 public void TestAutoQuoteApostrophe() { 983 final String[] patterns = { // new pattern, expected pattern 984 "'", "''", 985 "''", "''", 986 "'{", "'{'", 987 "' {", "'' {", 988 "'a", "''a", 989 "'{'a", "'{'a", 990 "'{a'", "'{a'", 991 "'{}", "'{}'", 992 "{'", "{'", 993 "{'a", "{'a", 994 "{'a{}'a}'a", "{'a{}'a}''a", 995 "'}'", "'}'", 996 "'} '{'}'", "'} '{'}''", 997 "'} {{{''", "'} {{{'''", 998 }; 999 for (int i = 0; i < patterns.length; i += 2) { 1000 assertEquals("[" + (i/2) + "] \"" + patterns[i] + "\"", patterns[i+1], MessageFormat.autoQuoteApostrophe(patterns[i])); 1001 } 1002 } 1003 1004 // This tests passing named arguments instead of numbers to format(). 1005 @Test testFormatNamedArguments()1006 public void testFormatNamedArguments() { 1007 Map arguments = new HashMap(); 1008 arguments.put("startDate", new Date(871068000000L)); 1009 1010 StringBuffer result = new StringBuffer(); 1011 1012 String formatStr = "On {startDate,date}, it began."; 1013 String compareStr = "On Aug 8, 1997, it began."; 1014 1015 MessageFormat msg = new MessageFormat(formatStr); 1016 FieldPosition fp = new FieldPosition(FieldPosition_DONT_CARE); 1017 1018 try { 1019 msg.format(arguments.get("startDate"), result, fp); 1020 errln("*** MSG format without expected error code."); 1021 } catch (Exception e1) { 1022 } 1023 1024 result.setLength(0); 1025 result = msg.format( 1026 arguments, 1027 result, 1028 fp); 1029 assertEquals("format", compareStr, result.toString()); 1030 } 1031 1032 // This tests parsing formatted messages with named arguments instead of 1033 // numbers. 1034 @Test testParseNamedArguments()1035 public void testParseNamedArguments() { 1036 String msgFormatString = "{foo} =sep= {bar}"; 1037 MessageFormat msg = new MessageFormat(msgFormatString); 1038 String source = "abc =sep= def"; 1039 1040 try { 1041 Map fmt_map = msg.parseToMap(source); 1042 if (fmt_map.keySet().size() != 2) { 1043 errln("*** MSG parse (ustring, count, err) count err."); 1044 } else { 1045 assertEquals("parse()[0]", "abc", fmt_map.get("foo")); 1046 assertEquals("parse()[1]", "def", fmt_map.get("bar")); 1047 } 1048 } catch (ParseException e1) { 1049 errln("*** MSG parse (ustring, count, err) error."); 1050 } 1051 1052 ParsePosition pp = new ParsePosition(0); 1053 Map fmt_map = msg.parseToMap(source, pp); 1054 if (pp.getIndex()==0 || fmt_map==null) { 1055 errln("*** MSG parse (ustring, parsepos., count) error."); 1056 } else { 1057 if (fmt_map.keySet().size() != 2) { 1058 errln("*** MSG parse (ustring, parsepos., count) count err."); 1059 } else { 1060 assertEquals("parse()[0]", "abc", fmt_map.get("foo")); 1061 assertEquals("parse()[1]", "def", fmt_map.get("bar")); 1062 } 1063 } 1064 1065 pp.setIndex(0); 1066 1067 Map fmta = (Map) msg.parseObject( source, pp ); 1068 if (pp.getIndex() == 0) { 1069 errln("*** MSG parse (ustring, Object, parsepos ) error."); 1070 } else { 1071 if (fmta.keySet().size() != 2) { 1072 errln("*** MSG parse (ustring, count, err) count err."); 1073 } else { 1074 assertEquals("parse()[0]", "abc", fmta.get("foo")); 1075 assertEquals("parse()[1]", "def", fmta.get("bar")); 1076 } 1077 } 1078 } 1079 1080 // Ensure that methods designed for numeric arguments only, will throw 1081 // an exception when called on MessageFormat objects created with 1082 // named arguments. 1083 @Test testNumericOnlyMethods()1084 public void testNumericOnlyMethods() { 1085 MessageFormat msg = new MessageFormat("Number of files: {numfiles}"); 1086 boolean gotException = false; 1087 try { 1088 Format fmts[] = {new DecimalFormat()}; 1089 msg.setFormatsByArgumentIndex(fmts); 1090 } catch (IllegalArgumentException e) { 1091 gotException = true; 1092 } 1093 if (!gotException) { 1094 errln("MessageFormat.setFormatsByArgumentIndex() should throw an " + 1095 "IllegalArgumentException when called on formats with " + 1096 "named arguments but did not!"); 1097 } 1098 1099 gotException = false; 1100 try { 1101 msg.setFormatByArgumentIndex(0, new DecimalFormat()); 1102 } catch (IllegalArgumentException e) { 1103 gotException = true; 1104 } 1105 if (!gotException) { 1106 errln("MessageFormat.setFormatByArgumentIndex() should throw an " + 1107 "IllegalArgumentException when called on formats with " + 1108 "named arguments but did not!"); 1109 } 1110 1111 gotException = false; 1112 try { 1113 msg.getFormatsByArgumentIndex(); 1114 } catch (IllegalArgumentException e) { 1115 gotException = true; 1116 } 1117 if (!gotException) { 1118 errln("MessageFormat.getFormatsByArgumentIndex() should throw an " + 1119 "IllegalArgumentException when called on formats with " + 1120 "named arguments but did not!"); 1121 } 1122 1123 gotException = false; 1124 try { 1125 Object args[] = {new Long(42)}; 1126 msg.format(args, new StringBuffer(), new FieldPosition(FieldPosition_DONT_CARE)); 1127 } catch (IllegalArgumentException e) { 1128 gotException = true; 1129 } 1130 if (!gotException) { 1131 errln("MessageFormat.format(Object[], StringBuffer, FieldPosition) " + 1132 "should throw an IllegalArgumentException when called on " + 1133 "formats with named arguments but did not!"); 1134 } 1135 1136 gotException = false; 1137 try { 1138 Object args[] = {new Long(42)}; 1139 msg.format((Object) args, new StringBuffer(), new FieldPosition(FieldPosition_DONT_CARE)); 1140 } catch (IllegalArgumentException e) { 1141 gotException = true; 1142 } 1143 if (!gotException) { 1144 errln("MessageFormat.format(Object, StringBuffer, FieldPosition) " + 1145 "should throw an IllegalArgumentException when called with " + 1146 "non-Map object as argument on formats with named " + 1147 "arguments but did not!"); 1148 } 1149 1150 gotException = false; 1151 try { 1152 msg.parse("Number of files: 5", new ParsePosition(0)); 1153 } catch (IllegalArgumentException e) { 1154 gotException = true; 1155 } 1156 if (!gotException) { 1157 errln("MessageFormat.parse(String, ParsePosition) " + 1158 "should throw an IllegalArgumentException when called with " + 1159 "non-Map object as argument on formats with named " + 1160 "arguments but did not!"); 1161 } 1162 1163 gotException = false; 1164 try { 1165 msg.parse("Number of files: 5"); 1166 } catch (IllegalArgumentException e) { 1167 gotException = true; 1168 } catch (ParseException e) { 1169 errln("Wrong exception thrown."); 1170 } 1171 if (!gotException) { 1172 errln("MessageFormat.parse(String) " + 1173 "should throw an IllegalArgumentException when called with " + 1174 "non-Map object as argument on formats with named " + 1175 "arguments but did not!"); 1176 } 1177 } 1178 1179 @Test testNamedArguments()1180 public void testNamedArguments() { 1181 // ICU 4.8 allows mixing named and numbered arguments. 1182 assertTrue( 1183 "has some named arguments", 1184 new MessageFormat("Number of files in folder {0}: {numfiles}").usesNamedArguments()); 1185 assertTrue( 1186 "has some named arguments", 1187 new MessageFormat("Number of files in folder {folder}: {1}").usesNamedArguments()); 1188 1189 // Test named arguments. 1190 MessageFormat mf = new MessageFormat("Number of files in folder {folder}: {numfiles}"); 1191 if (!mf.usesNamedArguments()) { 1192 errln("message format 1 should have used named arguments"); 1193 } 1194 mf = new MessageFormat("Wavelength: {\u028EValue\uFF14}"); 1195 if (!mf.usesNamedArguments()) { 1196 errln("message format 2 should have used named arguments"); 1197 } 1198 1199 // Test argument names with invalid start characters. 1200 // Modified: ICU 4.8 allows all characters except for Pattern_White_Space and Pattern_Syntax. 1201 try { 1202 new MessageFormat("Wavelength: {^\u028EValue\uFF14}"); 1203 errln("Creating a MessageFormat with invalid argument names " + 1204 "should throw an IllegalArgumentException but did not!"); 1205 } catch (IllegalArgumentException e) {} 1206 1207 try { 1208 new MessageFormat("Wavelength: {\uFE45\u028EValue}"); 1209 errln("Creating a MessageFormat with invalid argument names " + 1210 "should throw an IllegalArgumentException but did not!"); 1211 } catch (IllegalArgumentException e) {} 1212 1213 // Test argument names with invalid continue characters. 1214 // Modified: ICU 4.8 allows all characters except for Pattern_White_Space and Pattern_Syntax. 1215 try { 1216 new MessageFormat("Wavelength: {Value@\uFF14}"); 1217 errln("Creating a MessageFormat with invalid argument names " + 1218 "should throw an IllegalArgumentException but did not!"); 1219 } catch (IllegalArgumentException e) {} 1220 1221 try { 1222 new MessageFormat("Wavelength: {Value(\uFF14)}"); 1223 errln("Creating a MessageFormat with invalid argument names " + 1224 "should throw an IllegalArgumentException but did not!"); 1225 } catch (IllegalArgumentException e) {} 1226 } 1227 1228 @Test testNumericFormatWithMap()1229 public void testNumericFormatWithMap() { 1230 MessageFormat mf = new MessageFormat("X:{2} Y:{1}"); 1231 if (mf.usesNamedArguments()) { 1232 errln("should not use named arguments"); 1233 } 1234 1235 Map map12 = new HashMap(); 1236 map12.put("1", "one"); 1237 map12.put("2", "two"); 1238 1239 String target = "X:two Y:one"; 1240 String result = mf.format(map12); 1241 if (!target.equals(result)) { 1242 errln("expected '" + target + "' but got '" + result + "'"); 1243 } 1244 1245 try { 1246 Map mapResult = mf.parseToMap(target); 1247 if (!map12.equals(mapResult)) { 1248 errln("expected " + map12 + " but got " + mapResult); 1249 } 1250 } catch (ParseException e) { 1251 errln("unexpected exception: " + e.getMessage()); 1252 } 1253 1254 Map map10 = new HashMap(); 1255 map10.put("1", "one"); 1256 map10.put("0", "zero"); 1257 target = "X:{2} Y:one"; 1258 result = mf.format(map10); 1259 if (!target.equals(result)) { 1260 errln("expected '" + target + "' but got '" + result + "'"); 1261 } 1262 1263 DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM); 1264 DateFormat timeFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM); 1265 Map fmtMap = new HashMap(); 1266 fmtMap.put("1", dateFormat); 1267 fmtMap.put("2", timeFormat); 1268 mf.setFormatsByArgumentName(fmtMap); 1269 Date date = new Date(661439820000L); 1270 1271 try { 1272 result = mf.format(map12); // should fail, wrong argument type 1273 fail("expected exception but got '" + result + "'"); 1274 } catch (IllegalArgumentException e) { 1275 // expect this 1276 } 1277 1278 Map argMap = new HashMap(); 1279 argMap.put("1", date); 1280 argMap.put("2", date); 1281 target = "X:5:17:00 AM Y:Dec 17, 1990"; 1282 result = mf.format(argMap); 1283 if (!target.equals(result)) { 1284 errln("expected '" + target + "' but got '" + result + "'"); 1285 } 1286 } 1287 1288 // This tests nested Formats inside PluralFormat. 1289 @Test testNestedFormatsInPluralFormat()1290 public void testNestedFormatsInPluralFormat() { 1291 try { 1292 MessageFormat msgFmt = new MessageFormat( 1293 "{0, plural, one {{0, number,C''est #,##0.0# fichier}} " + 1294 "other {Ce sont # fichiers}} dans la liste.", 1295 new ULocale("fr")); 1296 Object objArray[] = {new Long(0)}; 1297 HashMap objMap = new HashMap(); 1298 objMap.put("argument", objArray[0]); 1299 String result = msgFmt.format(objArray); 1300 if (!result.equals("C'est 0,0 fichier dans la liste.")) { 1301 errln("PluralFormat produced wrong message string."); 1302 } 1303 } catch (Exception e) { 1304 e.printStackTrace(); 1305 throw new RuntimeException(e.getMessage()); 1306 } 1307 } 1308 1309 // This tests PluralFormats used inside MessageFormats. 1310 @Test testPluralFormat()1311 public void testPluralFormat() { 1312 { 1313 MessageFormat mfNum = new MessageFormat( 1314 "{0, plural, one{C''est # fichier} other " + 1315 "{Ce sont # fichiers}} dans la liste.", 1316 new ULocale("fr")); 1317 MessageFormat mfAlpha = new MessageFormat( 1318 "{argument, plural, one{C''est # fichier} other {Ce " + 1319 "sont # fichiers}} dans la liste.", 1320 new ULocale("fr")); 1321 Object objArray[] = {new Long(0)}; 1322 HashMap objMap = new HashMap(); 1323 objMap.put("argument", objArray[0]); 1324 String result = mfNum.format(objArray); 1325 if (!result.equals(mfAlpha.format(objMap))) { 1326 errln("PluralFormat's output differs when using named " + 1327 "arguments instead of numbers!"); 1328 } 1329 if (!result.equals("C'est 0 fichier dans la liste.")) { 1330 errln("PluralFormat produced wrong message string."); 1331 } 1332 } 1333 { 1334 MessageFormat mfNum = new MessageFormat ( 1335 "There {0, plural, one{is # zavod}few{are {0, " + 1336 "number,###.0} zavoda} other{are # zavodov}} in the " + 1337 "directory.", 1338 new ULocale("uk")); 1339 MessageFormat mfAlpha = new MessageFormat ( 1340 "There {argument, plural, one{is # zavod}few{" + 1341 "are {argument, number,###.0} zavoda} other{are # " + 1342 "zavodov}} in the directory.", 1343 new ULocale("uk")); 1344 Object objArray[] = {new Long(4)}; 1345 HashMap objMap = new HashMap(); 1346 objMap.put("argument", objArray[0]); 1347 String result = mfNum.format(objArray); 1348 if (!result.equals(mfAlpha.format(objMap))) { 1349 errln("PluralFormat's output differs when using named " + 1350 "arguments instead of numbers!"); 1351 } 1352 if (!result.equals("There are 4,0 zavoda in the directory.")) { 1353 errln("PluralFormat produced wrong message string."); 1354 } 1355 } 1356 } 1357 1358 @Test testApostropheInPluralAndSelect()1359 public void testApostropheInPluralAndSelect() { 1360 MessageFormat fmt = new MessageFormat( 1361 "abc_{0,plural,other{#'#'#'{'#''}}_def_{1,select,other{sel'}'ect''}}_xyz", 1362 Locale.ENGLISH); 1363 String expected = "abc_3#3{3'_def_sel}ect'_xyz"; 1364 String result = fmt.format(new Object[] { 3, "x" }); 1365 if (!result.equals(expected)) { 1366 errln("MessageFormat with apostrophes in plural/select arguments failed:\n" + 1367 "Expected "+expected+"\n" + 1368 "Got "+result); 1369 } 1370 } 1371 1372 // Test toPattern when there is a PluralFormat 1373 @Test testPluralFormatToPattern()1374 public void testPluralFormatToPattern() { 1375 String[] patterns = { 1376 "Beware of vicious {0, plural, one {hamster} other {hamsters}}.", 1377 "{0, plural, one {{0, number,C''''est #,##0.0# fichier}} other {Ce sont # fichiers}} dans la liste.", 1378 "{0, plural, one {C''est # fichier} other {Ce sont # fichiers}} dans la liste.", 1379 }; 1380 1381 for (int i = 0; i < patterns.length; ++i) { 1382 String pattern = patterns[i]; 1383 MessageFormat mf = new MessageFormat(pattern); 1384 MessageFormat mf2 = new MessageFormat(mf.toPattern()); 1385 if (!mf.equals(mf2)) { 1386 errln("message formats not equal for pattern:\n*** '" + pattern + "'\n*** '" + 1387 mf.toPattern() + "'"); 1388 } 1389 } 1390 } 1391 1392 /** 1393 * This tests SelectFormats used inside MessageFormats. 1394 */ 1395 @Test testSelectFormat()1396 public void testSelectFormat() { 1397 String pattern = null; 1398 MessageFormat msgFmt = null ; 1399 1400 //Create the MessageFormat with simple French pattern 1401 pattern = "{0} est {1, select, female {all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris."; 1402 msgFmt = new MessageFormat(pattern); 1403 assertNotNull( "ERROR:Failure in constructing with simple French pattern", msgFmt); 1404 1405 //Format 1406 Object testArgs[][] ={ 1407 {"Kirti","female"} , 1408 {"Victor","other"} , 1409 {"Ash","unknown"} , 1410 }; 1411 String exp[] = { 1412 "Kirti est all\\u00E9e \\u00E0 Paris." , 1413 "Victor est all\\u00E9 \\u00E0 Paris.", 1414 "Ash est all\\u00E9 \\u00E0 Paris." 1415 }; 1416 for ( int i=0; i< 3; i++){ 1417 assertEquals("ERROR:Failure in format with simple French Pattern" , 1418 exp[i] , msgFmt.format(testArgs[i]) ); 1419 } 1420 1421 //Create the MessageFormat with Quoted French Pattern 1422 pattern = "{0} est {1, select, female {all\\u00E9e c''est} other {all\\u00E9 c''est}} \\u00E0 Paris."; 1423 msgFmt = new MessageFormat(pattern); 1424 assertNotNull( "ERROR:Failure in constructing with quoted French pattern", msgFmt); 1425 1426 //Format 1427 Object testArgs1[][] ={ 1428 {"Kirti","female"} , 1429 {"Victor","other"} , 1430 {"Ash","male"} , 1431 }; 1432 String exp1[] = { 1433 "Kirti est all\\u00E9e c'est \\u00E0 Paris." , 1434 "Victor est all\\u00E9 c'est \\u00E0 Paris.", 1435 "Ash est all\\u00E9 c'est \\u00E0 Paris." 1436 }; 1437 for ( int i=0; i< 3; i++){ 1438 assertEquals("ERROR:Failure in format with quoted French Pattern" , 1439 exp1[i] , msgFmt.format(testArgs1[i]) ); 1440 } 1441 1442 //Nested patterns with plural, number ,choice ,select format etc. 1443 //Select Format with embedded number format 1444 pattern = "{0} est {1, select, female {{2,number,integer} all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris."; 1445 msgFmt = new MessageFormat(pattern); 1446 assertNotNull( "ERROR:Failure in constructing with nested pattern 1", msgFmt); 1447 1448 //Format 1449 Object testArgs3[][] ={ 1450 {"Kirti", "female", 6} , 1451 {"Kirti", "female", 100.100} , 1452 {"Kirti", "other", 6} , 1453 }; 1454 String exp3[] = { 1455 "Kirti est 6 all\\u00E9e \\u00E0 Paris." , 1456 "Kirti est 100 all\\u00E9e \\u00E0 Paris.", 1457 "Kirti est all\\u00E9 \\u00E0 Paris." 1458 }; 1459 1460 for ( int i=0; i< 3; i++){ 1461 assertEquals("ERROR:Failure in format with nested Pattern 1" , 1462 exp3[i] , msgFmt.format(testArgs3[i]) ); 1463 } 1464 1465 //Plural format with embedded select format 1466 pattern = "{0} {1, plural, one {est {2, select, female {all\\u00E9e} other {all\\u00E9}}} other {sont {2, select, female {all\\u00E9es} other {all\\u00E9s}}}} \\u00E0 Paris."; 1467 msgFmt = new MessageFormat(pattern); 1468 assertNotNull( "ERROR:Failure in constructing with nested pattern 2", msgFmt); 1469 1470 //Format 1471 Object testArgs4[][] ={ 1472 {"Kirti",6,"female"}, 1473 {"Kirti",1,"female"}, 1474 {"Ash",1,"other"}, 1475 {"Ash",5,"other"}, 1476 }; 1477 String exp4[] = { 1478 "Kirti sont all\\u00E9es \\u00E0 Paris." , 1479 "Kirti est all\\u00E9e \\u00E0 Paris.", 1480 "Ash est all\\u00E9 \\u00E0 Paris.", 1481 "Ash sont all\\u00E9s \\u00E0 Paris." 1482 }; 1483 for ( int i=0; i< 4; i++){ 1484 assertEquals("ERROR:Failure in format with nested Pattern 2" , 1485 exp4[i] , msgFmt.format(testArgs4[i]) ); 1486 } 1487 1488 //Select, plural, and number formats heavily nested 1489 pattern = "{0} und {1, select, female {{2, plural, one {{3, select, female {ihre Freundin} other {ihr Freund}} } other {ihre {2, number, integer} {3, select, female {Freundinnen} other {Freunde}} } }} other{{2, plural, one {{3, select, female {seine Freundin} other {sein Freund}}} other {seine {2, number, integer} {3, select, female {Freundinnen} other {Freunde}}}}} } gingen nach Paris."; 1490 msgFmt = new MessageFormat(pattern); 1491 assertNotNull( "ERROR:Failure in constructing with nested pattern 3", msgFmt); 1492 1493 //Format 1494 Object testArgs5[][] ={ 1495 {"Kirti","other",1,"other"}, 1496 {"Kirti","other",6,"other"}, 1497 {"Kirti","other",1,"female"}, 1498 {"Kirti","other",3,"female"}, 1499 {"Kirti","female",1,"female"}, 1500 {"Kirti","female",5,"female"}, 1501 {"Kirti","female",1,"other"}, 1502 {"Kirti","female",5,"other"}, 1503 {"Kirti","mixed",1,"mixed"}, 1504 {"Kirti","mixed",1,"other"}, 1505 {"Kirti","female",1,"mixed"}, 1506 {"Kirti","mixed",5,"mixed"}, 1507 {"Kirti","mixed",5,"other"}, 1508 {"Kirti","female",5,"mixed"}, 1509 }; 1510 String exp5[] = { 1511 "Kirti und sein Freund gingen nach Paris." , 1512 "Kirti und seine 6 Freunde gingen nach Paris." , 1513 "Kirti und seine Freundin gingen nach Paris.", 1514 "Kirti und seine 3 Freundinnen gingen nach Paris.", 1515 "Kirti und ihre Freundin gingen nach Paris.", 1516 "Kirti und ihre 5 Freundinnen gingen nach Paris.", 1517 "Kirti und ihr Freund gingen nach Paris.", 1518 "Kirti und ihre 5 Freunde gingen nach Paris.", 1519 "Kirti und sein Freund gingen nach Paris.", 1520 "Kirti und sein Freund gingen nach Paris.", 1521 "Kirti und ihr Freund gingen nach Paris.", 1522 "Kirti und seine 5 Freunde gingen nach Paris." , 1523 "Kirti und seine 5 Freunde gingen nach Paris." , 1524 "Kirti und ihre 5 Freunde gingen nach Paris." 1525 }; 1526 //Format 1527 for ( int i=0; i< 14; i++){ 1528 assertEquals("ERROR:Failure in format with nested Pattern 3" , 1529 exp5[i] , msgFmt.format(testArgs5[i]) ); 1530 } 1531 } 1532 1533 /** 1534 * Test toPattern when there is a SelectFormat 1535 */ 1536 @Test testSelectFormatToPattern()1537 public void testSelectFormatToPattern() { 1538 String[] patterns = { 1539 //Pattern with some text at start and at end 1540 "{0} est {1,select, female {all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.", 1541 //Pattern with some text at start 1542 "{0} est {1,select, female {all\\u00E9e} other {all\\u00E9}}", 1543 //Pattern with some text at end 1544 "{1, select,female {all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.", 1545 //Pattern with no text at any end 1546 "{1, select,female {all\\u00E9e} other {all\\u00E9}}.", 1547 //Quoted French pattern 1548 "{0} est {1,select, female {all\\u00E9e c''est} other {all\\u00E9 c''est}} \\u00E0 Paris.", 1549 }; 1550 1551 for (int i = 0; i < patterns.length; ++i) { 1552 String pattern = patterns[i]; 1553 MessageFormat mf = new MessageFormat(pattern); 1554 MessageFormat mf2 = new MessageFormat(mf.toPattern()); 1555 if (!mf.equals(mf2)) { 1556 errln("message formats not equal for pattern:\n*** '" 1557 + pattern + "'\n*** '" + mf.toPattern() + "'"); 1558 } 1559 } 1560 } 1561 1562 // Test case for null arguments. 1563 // Ticket#6361 1564 @Test TestNullArgs()1565 public void TestNullArgs() { 1566 MessageFormat msgfmt = new MessageFormat("{0} - {1}"); 1567 Object[][] TEST_CASES = { 1568 {null, "{0} - {1}"}, 1569 {new Object[] {null}, "null - {1}"}, 1570 {new Object[] {null, null}, "null - null"}, 1571 {new Object[] {"one"}, "one - {1}"}, 1572 {new Object[] {"one", null}, "one - null"}, 1573 {new Object[] {null, "two"}, "null - two"}, 1574 }; 1575 1576 for (int i = 0; i < TEST_CASES.length; i++) { 1577 String text = msgfmt.format(TEST_CASES[i][0]); 1578 if (!text.equals(TEST_CASES[i][1])) { 1579 errln("FAIL: Returned[" + text + "] Expected[" + TEST_CASES[i][1] + "]"); 1580 } 1581 } 1582 } 1583 1584 @Test TestSetFormat()1585 public void TestSetFormat() { 1586 MessageFormat ms = new MessageFormat("{number} {date}", ULocale.ENGLISH); 1587 final DecimalFormat decimalFormat = new DecimalFormat("000.000", DecimalFormatSymbols.getInstance(ULocale.ENGLISH)); 1588 ms.setFormatByArgumentName("number", decimalFormat); 1589 final SimpleDateFormat dateFormat = new SimpleDateFormat("'year:'yy 'month:'MM 'day:'dd"); 1590 dateFormat.setTimeZone(TimeZone.getTimeZone("Etc/GMT")); 1591 ms.setFormatByArgumentName("date", dateFormat); 1592 Map map = new HashMap(); 1593 map.put("number", new Integer(1234)); 1594 map.put("date", new Date(0,0,0)); 1595 String result = ms.format(map); 1596 assertEquals("setFormatByArgumentName", "1234.000 year:99 month:12 day:31", result); 1597 Set formatNames = ms.getArgumentNames(); 1598 assertEquals("Format Names match", formatNames, map.keySet()); 1599 assertEquals("Decimal", decimalFormat, ms.getFormatByArgumentName("number")); 1600 assertEquals("Date", dateFormat, ms.getFormatByArgumentName("date")); 1601 } 1602 1603 // Test case for formatToCharacterIterator 1604 @Test TestFormatToCharacterIterator()1605 public void TestFormatToCharacterIterator() { 1606 MessageFormat[] msgfmts = { 1607 new MessageFormat( 1608 "The {3,ordinal} folder ''{0}'' contains {2,number} file(s), created at {1,time} on {1,date}."), 1609 new MessageFormat( 1610 "The {arg3,ordinal} folder ''{arg0}'' contains {arg2,number} file(s), created at {arg1,time} on {arg1,date}."), // same 1611 // as 1612 // above, 1613 // but 1614 // named 1615 // args 1616 new MessageFormat("The folder contains {0}.") }; 1617 1618 double filelimits[] = { 0, 1, 2 }; 1619 String filepart[] = { "no files", "one file", "{0,number} files" }; 1620 ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart); 1621 msgfmts[2].setFormat(0, fileform); 1622 1623 Object[] args0 = new Object[] { "tmp", new Date(1184777888000L), new Integer(15), new Integer(2) }; 1624 1625 HashMap args1 = new HashMap(); 1626 args1.put("arg0", "tmp"); 1627 args1.put("arg1", new Date(1184777888000L)); 1628 args1.put("arg2", new Integer(15)); 1629 args1.put("arg3", new Integer(2)); 1630 1631 Object[] args2 = new Object[] { new Integer(34) }; 1632 1633 Object[] args = { args0, args1, args2 }; 1634 1635 String[] expectedStrings = { 1636 "The 2nd folder 'tmp' contains 15 file(s), created at 9:58:08 AM on Jul 18, 2007.", 1637 "The 2nd folder 'tmp' contains 15 file(s), created at 9:58:08 AM on Jul 18, 2007.", 1638 "The folder contains 34 files." }; 1639 1640 AttributedString[] expectedAttributedStrings = { new AttributedString(expectedStrings[0]), 1641 new AttributedString(expectedStrings[1]), new AttributedString(expectedStrings[2]) }; 1642 1643 // Add expected attributes to the expectedAttributedStrings[0] 1644 expectedAttributedStrings[0].addAttribute(MessageFormat.Field.ARGUMENT, new Integer(3), 4, 7); 1645 expectedAttributedStrings[0].addAttribute(MessageFormat.Field.ARGUMENT, new Integer(0), 16, 19); 1646 expectedAttributedStrings[0].addAttribute(MessageFormat.Field.ARGUMENT, new Integer(2), 30, 32); 1647 expectedAttributedStrings[0].addAttribute(NumberFormat.Field.INTEGER, NumberFormat.Field.INTEGER, 30, 32); 1648 expectedAttributedStrings[0].addAttribute(MessageFormat.Field.ARGUMENT, new Integer(1), 53, 63); 1649 expectedAttributedStrings[0].addAttribute(DateFormat.Field.HOUR1, DateFormat.Field.HOUR1, 53, 54); 1650 //expectedAttributedStrings[0].addAttribute(DateFormat.Field.TIME_SEPARATOR, DateFormat.Field.TIME_SEPARATOR, 54, 55); 1651 expectedAttributedStrings[0].addAttribute(DateFormat.Field.MINUTE, DateFormat.Field.MINUTE, 55, 57); 1652 //expectedAttributedStrings[0].addAttribute(DateFormat.Field.TIME_SEPARATOR, DateFormat.Field.TIME_SEPARATOR, 57, 58); 1653 expectedAttributedStrings[0].addAttribute(DateFormat.Field.SECOND, DateFormat.Field.SECOND, 58, 60); 1654 expectedAttributedStrings[0].addAttribute(DateFormat.Field.AM_PM, DateFormat.Field.AM_PM, 61, 63); 1655 expectedAttributedStrings[0].addAttribute(MessageFormat.Field.ARGUMENT, new Integer(1), 67, 79); 1656 expectedAttributedStrings[0].addAttribute(DateFormat.Field.MONTH, DateFormat.Field.MONTH, 67, 70); 1657 expectedAttributedStrings[0].addAttribute(DateFormat.Field.DAY_OF_MONTH, DateFormat.Field.DAY_OF_MONTH, 71, 73); 1658 expectedAttributedStrings[0].addAttribute(DateFormat.Field.YEAR, DateFormat.Field.YEAR, 75, 79); 1659 1660 // Add expected attributes to the expectedAttributedStrings[1] 1661 expectedAttributedStrings[1].addAttribute(MessageFormat.Field.ARGUMENT, "arg3", 4, 7); 1662 expectedAttributedStrings[1].addAttribute(MessageFormat.Field.ARGUMENT, "arg0", 16, 19); 1663 expectedAttributedStrings[1].addAttribute(MessageFormat.Field.ARGUMENT, "arg2", 30, 32); 1664 expectedAttributedStrings[1].addAttribute(NumberFormat.Field.INTEGER, NumberFormat.Field.INTEGER, 30, 32); 1665 expectedAttributedStrings[1].addAttribute(MessageFormat.Field.ARGUMENT, "arg1", 53, 63); 1666 expectedAttributedStrings[1].addAttribute(DateFormat.Field.HOUR1, DateFormat.Field.HOUR1, 53, 54); 1667 //expectedAttributedStrings[1].addAttribute(DateFormat.Field.TIME_SEPARATOR, DateFormat.Field.TIME_SEPARATOR, 54, 55); 1668 expectedAttributedStrings[1].addAttribute(DateFormat.Field.MINUTE, DateFormat.Field.MINUTE, 55, 57); 1669 //expectedAttributedStrings[1].addAttribute(DateFormat.Field.TIME_SEPARATOR, DateFormat.Field.TIME_SEPARATOR, 57, 58); 1670 expectedAttributedStrings[1].addAttribute(DateFormat.Field.SECOND, DateFormat.Field.SECOND, 58, 60); 1671 expectedAttributedStrings[1].addAttribute(DateFormat.Field.AM_PM, DateFormat.Field.AM_PM, 61, 63); 1672 expectedAttributedStrings[1].addAttribute(MessageFormat.Field.ARGUMENT, "arg1", 67, 79); 1673 expectedAttributedStrings[1].addAttribute(DateFormat.Field.MONTH, DateFormat.Field.MONTH, 67, 70); 1674 expectedAttributedStrings[1].addAttribute(DateFormat.Field.DAY_OF_MONTH, DateFormat.Field.DAY_OF_MONTH, 71, 73); 1675 expectedAttributedStrings[1].addAttribute(DateFormat.Field.YEAR, DateFormat.Field.YEAR, 75, 79); 1676 1677 // Add expected attributes to the expectedAttributedStrings[2] 1678 expectedAttributedStrings[2].addAttribute(MessageFormat.Field.ARGUMENT, new Integer(0), 20, 28); 1679 expectedAttributedStrings[2].addAttribute(NumberFormat.Field.INTEGER, NumberFormat.Field.INTEGER, 20, 22); 1680 1681 for (int i = 0; i < msgfmts.length; i++) { 1682 AttributedCharacterIterator acit = msgfmts[i].formatToCharacterIterator(args[i]); 1683 AttributedCharacterIterator expectedAcit = expectedAttributedStrings[i].getIterator(); 1684 1685 // Check available attributes 1686 Set attrSet = acit.getAllAttributeKeys(); 1687 Set expectedAttrSet = expectedAcit.getAllAttributeKeys(); 1688 if (attrSet.size() != expectedAttrSet.size()) { 1689 errln("FAIL: Number of attribute keys is " + attrSet.size() + " expected: " + expectedAttrSet.size()); 1690 } 1691 Iterator attrIterator = attrSet.iterator(); 1692 while (attrIterator.hasNext()) { 1693 AttributedCharacterIterator.Attribute attr = (AttributedCharacterIterator.Attribute) attrIterator 1694 .next(); 1695 if (!expectedAttrSet.contains(attr)) { 1696 errln("FAIL: The attribute " + attr + " is not expected."); 1697 } 1698 } 1699 1700 StringBuffer buf = new StringBuffer(); 1701 int index = acit.getBeginIndex(); 1702 int end = acit.getEndIndex(); 1703 int indexExp = expectedAcit.getBeginIndex(); 1704 int expectedLen = expectedAcit.getEndIndex() - indexExp; 1705 if (end - index != expectedLen) { 1706 errln("FAIL: Length of the result attributed string is " + (end - index) + " expected: " + expectedLen); 1707 } else { 1708 // Check attributes associated with each character 1709 while (index < end) { 1710 char c = acit.setIndex(index); 1711 buf.append(c); 1712 expectedAcit.setIndex(indexExp); 1713 1714 Map attrs = acit.getAttributes(); 1715 Map attrsExp = expectedAcit.getAttributes(); 1716 if (attrs.size() != attrsExp.size()) { 1717 errln("FAIL: Number of attributes associated with index " + index + " is " + attrs.size() 1718 + " expected: " + attrsExp.size()); 1719 } else { 1720 // Check all attributes at the index 1721 Iterator entryIterator = attrsExp.entrySet().iterator(); 1722 while (entryIterator.hasNext()) { 1723 Map.Entry entry = (Map.Entry) entryIterator.next(); 1724 if (attrs.containsKey(entry.getKey())) { 1725 Object value = attrs.get(entry.getKey()); 1726 assertEquals("Attribute value at index " + index, entry.getValue(), value); 1727 } else { 1728 errln("FAIL: Attribute " + entry.getKey() + " is missing at index " + index); 1729 } 1730 } 1731 } 1732 index++; 1733 indexExp++; 1734 } 1735 assertEquals("AttributedString contents", expectedStrings[i], buf.toString()); 1736 } 1737 } 1738 1739 // Tests when "if (arguments == null)" is true 1740 try { 1741 MessageFormat mf = new MessageFormat(""); 1742 mf.formatToCharacterIterator(null); 1743 errln("MessageFormat.formatToCharacterIterator(Object) was suppose " 1744 + "to return an exception when null is passed."); 1745 } catch (Exception e) { 1746 } 1747 } 1748 1749 /* 1750 * Tests the method public Format getFormatByArgumentName(String argumentName) 1751 */ 1752 @Test TestGetFormatByArgumentName()1753 public void TestGetFormatByArgumentName() { 1754 MessageFormat mf = new MessageFormat(""); 1755 if (mf.getFormatByArgumentName("") != null) { 1756 errln("MessageFormat.getFormatByArgumentName(String) was suppose " 1757 + "to return an null if argumentName was not found."); 1758 } 1759 } 1760 getPatternAndSkipSyntax(MessagePattern pattern)1761 public String getPatternAndSkipSyntax(MessagePattern pattern) { 1762 StringBuilder sb = new StringBuilder(pattern.getPatternString()); 1763 int count = pattern.countParts(); 1764 for (int i = count; i > 0;) { 1765 MessagePattern.Part part = pattern.getPart(--i); 1766 if (part.getType() == MessagePattern.Part.Type.SKIP_SYNTAX) { 1767 sb.delete(part.getIndex(), part.getLimit()); 1768 } 1769 } 1770 return sb.toString(); 1771 } 1772 1773 @Test TestApostropheMode()1774 public void TestApostropheMode() { 1775 MessagePattern ado_mp = new MessagePattern(MessagePattern.ApostropheMode.DOUBLE_OPTIONAL); 1776 MessagePattern adr_mp = new MessagePattern(MessagePattern.ApostropheMode.DOUBLE_REQUIRED); 1777 assertEquals("wrong value", 1778 MessagePattern.ApostropheMode.DOUBLE_OPTIONAL, 1779 ado_mp.getApostropheMode()); 1780 assertEquals("wrong value", 1781 MessagePattern.ApostropheMode.DOUBLE_REQUIRED, 1782 adr_mp.getApostropheMode()); 1783 assertNotEquals("MessagePatterns with different ApostropheMode (no pattern)", ado_mp, adr_mp); 1784 assertNotEquals("MessagePatterns with different ApostropheMode (a)", 1785 ado_mp.parse("a"), adr_mp.parse("a")); 1786 1787 String[] tuples = new String[] { 1788 // Desired output 1789 // DOUBLE_OPTIONAL pattern 1790 // DOUBLE_REQUIRED pattern (null=same as DOUBLE_OPTIONAL) 1791 "I see {many}", "I see '{many}'", null, 1792 "I said {'Wow!'}", "I said '{''Wow!''}'", null, 1793 "I dont know", "I dont know", "I don't know", 1794 "I don't know", "I don't know", "I don''t know", 1795 "I don't know", "I don''t know", "I don''t know", 1796 }; 1797 for (int i = 0; i < tuples.length; i += 3) { 1798 String desired = tuples[i]; 1799 String ado_pattern = tuples[i + 1]; 1800 assertEquals("DOUBLE_OPTIONAL failure", desired, 1801 getPatternAndSkipSyntax(ado_mp.parse(ado_pattern))); 1802 String adr_pattern = tuples[i + 2]; 1803 if (adr_pattern == null) { 1804 adr_pattern = ado_pattern; 1805 } 1806 assertEquals("DOUBLE_REQUIRED failure", desired, 1807 getPatternAndSkipSyntax(adr_mp.parse(adr_pattern))); 1808 } 1809 } 1810 1811 // Compare behavior of JDK and ICU's DOUBLE_REQUIRED compatibility mode. 1812 @Test TestCompatibleApostrophe()1813 public void TestCompatibleApostrophe() { 1814 // Message with choice argument which does not contain another argument. 1815 // The JDK performs only one apostrophe-quoting pass on this pattern. 1816 String pattern = "ab{0,choice,0#1'2''3'''4''''.}yz"; 1817 java.text.MessageFormat jdkMsg = 1818 new java.text.MessageFormat(pattern, Locale.ENGLISH); 1819 1820 MessageFormat compMsg = new MessageFormat("", Locale.ENGLISH); 1821 compMsg.applyPattern(pattern, MessagePattern.ApostropheMode.DOUBLE_REQUIRED); 1822 assertEquals("wrong value", 1823 MessagePattern.ApostropheMode.DOUBLE_REQUIRED, 1824 compMsg.getApostropheMode()); 1825 1826 MessageFormat icuMsg = new MessageFormat("", Locale.ENGLISH); 1827 icuMsg.applyPattern(pattern, MessagePattern.ApostropheMode.DOUBLE_OPTIONAL); 1828 assertEquals("wrong value", 1829 MessagePattern.ApostropheMode.DOUBLE_OPTIONAL, 1830 icuMsg.getApostropheMode()); 1831 1832 Object[] zero0 = new Object[] { 0 }; 1833 assertEquals("unexpected JDK MessageFormat apostrophe behavior", 1834 "ab12'3'4''.yz", 1835 jdkMsg.format(zero0)); 1836 assertEquals("incompatible ICU MessageFormat compatibility-apostrophe behavior", 1837 "ab12'3'4''.yz", 1838 compMsg.format(zero0)); 1839 assertEquals("unexpected ICU MessageFormat double-apostrophe-optional behavior", 1840 "ab1'2'3''4''.yz", 1841 icuMsg.format(zero0)); 1842 1843 // Message with choice argument which contains a nested simple argument. 1844 // The JDK performs two apostrophe-quoting passes. 1845 pattern = "ab{0,choice,0#1'2''3'''4''''.{0,number,'#x'}}yz"; 1846 jdkMsg.applyPattern(pattern); 1847 compMsg.applyPattern(pattern); 1848 icuMsg.applyPattern(pattern); 1849 assertEquals("unexpected JDK MessageFormat apostrophe behavior", 1850 "ab1234'.0xyz", 1851 jdkMsg.format(zero0)); 1852 assertEquals("incompatible ICU MessageFormat compatibility-apostrophe behavior", 1853 "ab1234'.0xyz", 1854 compMsg.format(zero0)); 1855 assertEquals("unexpected ICU MessageFormat double-apostrophe-optional behavior", 1856 "ab1'2'3''4''.#x0yz", 1857 icuMsg.format(zero0)); 1858 1859 // Message with choice argument which contains a nested choice argument. 1860 // The JDK fails to parse this pattern. 1861 // jdkMsg.applyPattern("cd{0,choice,0#ef{0,choice,0#1'2''3'''4''''.}uv}wx"); 1862 // For lack of comparison, we do not test ICU with this pattern. 1863 1864 // The JDK ChoiceFormat itself always performs one apostrophe-quoting pass. 1865 ChoiceFormat choice = new ChoiceFormat("0#1'2''3'''4''''."); 1866 assertEquals("unexpected JDK ChoiceFormat apostrophe behavior", 1867 "12'3'4''.", 1868 choice.format(0)); 1869 choice.applyPattern("0#1'2''3'''4''''.{0,number,'#x'}"); 1870 assertEquals("unexpected JDK ChoiceFormat apostrophe behavior", 1871 "12'3'4''.{0,number,#x}", 1872 choice.format(0)); 1873 } 1874 1875 @Test TestTrimArgumentName()1876 public void TestTrimArgumentName() { 1877 // ICU 4.8 allows and ignores white space around argument names and numbers. 1878 MessageFormat m = new MessageFormat("a { 0 , number , '#,#'#.0 } z", Locale.ENGLISH); 1879 assertEquals("trim-numbered-arg format() failed", "a #,#2.0 z", m.format(new Object[] { 2 })); 1880 1881 m.applyPattern("x { _oOo_ , number , integer } y"); 1882 Map<String, Object> map = new HashMap<String, Object>(); 1883 map.put("_oOo_", new Integer(3)); 1884 StringBuffer result = new StringBuffer(); 1885 assertEquals("trim-named-arg format() failed", "x 3 y", 1886 m.format(map, result, new FieldPosition(FieldPosition_DONT_CARE)).toString()); 1887 } 1888 1889 @Test TestSelectOrdinal()1890 public void TestSelectOrdinal() { 1891 // Test plural & ordinal together, 1892 // to make sure that we get the correct cached PluralSelector for each. 1893 MessageFormat m = new MessageFormat( 1894 "{0,plural,one{1 file}other{# files}}, " + 1895 "{0,selectordinal,one{#st file}two{#nd file}few{#rd file}other{#th file}}", 1896 ULocale.ENGLISH); 1897 Object[] args = new Object[] { 21 }; 1898 FieldPosition ignore = null; 1899 StringBuffer result = new StringBuffer(); 1900 assertEquals("plural-and-ordinal format(21)", "21 files, 21st file", 1901 m.format(args, result, ignore).toString()); 1902 1903 args[0] = 2; 1904 result.delete(0, result.length()); 1905 assertEquals("plural-and-ordinal format(2) failed", "2 files, 2nd file", 1906 m.format(args, result, ignore).toString()); 1907 1908 args[0] = 1; 1909 result.delete(0, result.length()); 1910 assertEquals("plural-and-ordinal format(1) failed", "1 file, 1st file", 1911 m.format(args, result, ignore).toString()); 1912 1913 args[0] = 3; 1914 result.delete(0, result.length()); 1915 assertEquals("plural-and-ordinal format(3) failed", "3 files, 3rd file", 1916 m.format(args, result, ignore).toString()); 1917 } 1918 1919 @Test TestDecimals()1920 public void TestDecimals() { 1921 // Simple number replacement. 1922 MessageFormat m = new MessageFormat( 1923 "{0,plural,one{one meter}other{# meters}}", 1924 ULocale.ENGLISH); 1925 Object[] args = new Object[] { 1 }; 1926 FieldPosition ignore = null; 1927 StringBuffer result = new StringBuffer(); 1928 assertEquals("simple format(1)", "one meter", 1929 m.format(args, result, ignore).toString()); 1930 1931 args[0] = 1.5; 1932 result.delete(0, result.length()); 1933 assertEquals("simple format(1.5)", "1.5 meters", 1934 m.format(args, result, ignore).toString()); 1935 1936 // Simple but explicit. 1937 MessageFormat m0 = new MessageFormat( 1938 "{0,plural,one{one meter}other{{0} meters}}", 1939 ULocale.ENGLISH); 1940 args[0] = 1; 1941 result.delete(0, result.length()); 1942 assertEquals("explicit format(1)", "one meter", 1943 m0.format(args, result, ignore).toString()); 1944 1945 args[0] = 1.5; 1946 result.delete(0, result.length()); 1947 assertEquals("explicit format(1.5)", "1.5 meters", 1948 m0.format(args, result, ignore).toString()); 1949 1950 // With offset and specific simple format with optional decimals. 1951 MessageFormat m1 = new MessageFormat( 1952 "{0,plural,offset:1 one{another meter}other{{0,number,00.#} meters}}", 1953 ULocale.ENGLISH); 1954 args[0] = 1; 1955 result.delete(0, result.length()); 1956 assertEquals("offset format(1)", "01 meters", 1957 m1.format(args, result, ignore).toString()); 1958 1959 args[0] = 2; 1960 result.delete(0, result.length()); 1961 assertEquals("offset format(1)", "another meter", 1962 m1.format(args, result, ignore).toString()); 1963 1964 args[0] = 2.5; 1965 result.delete(0, result.length()); 1966 assertEquals("offset format(1)", "02.5 meters", 1967 m1.format(args, result, ignore).toString()); 1968 1969 // With offset and specific simple format with forced decimals. 1970 MessageFormat m2 = new MessageFormat( 1971 "{0,plural,offset:1 one{another meter}other{{0,number,0.0} meters}}", 1972 ULocale.ENGLISH); 1973 args[0] = 1; 1974 result.delete(0, result.length()); 1975 assertEquals("offset-decimals format(1)", "1.0 meters", 1976 m2.format(args, result, ignore).toString()); 1977 1978 args[0] = 2; 1979 result.delete(0, result.length()); 1980 assertEquals("offset-decimals format(1)", "2.0 meters", 1981 m2.format(args, result, ignore).toString()); 1982 1983 args[0] = 2.5; 1984 result.delete(0, result.length()); 1985 assertEquals("offset-decimals format(1)", "2.5 meters", 1986 m2.format(args, result, ignore).toString()); 1987 } 1988 1989 @Test TestArgIsPrefixOfAnother()1990 public void TestArgIsPrefixOfAnother() { 1991 // Ticket #11952 1992 MessageFormat mf1 = new MessageFormat( 1993 "{0,select,a{A}ab{AB}abc{ABC}other{?}}", ULocale.ENGLISH); 1994 assertEquals("a", "A", mf1.format(new Object[] { "a" })); 1995 assertEquals("ab", "AB", mf1.format(new Object[] { "ab" })); 1996 assertEquals("abc", "ABC", mf1.format(new Object[] { "abc" })); 1997 1998 // Ticket #12172 1999 MessageFormat mf2 = new MessageFormat("{a} {aa} {aaa}", ULocale.ENGLISH); 2000 Map<String, Object> args = new TreeMap<String, Object>(); 2001 args.put("a", "A"); 2002 args.put("aa", "AB"); 2003 args.put("aaa", "ABC"); 2004 assertEquals("a aa aaa", "A AB ABC", mf2.format(args, new StringBuffer(), null).toString()); 2005 2006 // Ticket #12172 2007 MessageFormat mf3 = new MessageFormat("{aa} {aaa}", ULocale.ENGLISH); 2008 assertEquals("aa aaa", "AB ABC", mf3.format(args, new StringBuffer(), null).toString()); 2009 } 2010 2011 @Test TestMessagePatternAutoQuoteApostropheDeep()2012 public void TestMessagePatternAutoQuoteApostropheDeep() { 2013 // Example input & output taken from API docs. 2014 MessagePattern pattern = new MessagePattern( 2015 "I don't '{know}' {gender,select,female{h''er}other{h'im}}."); 2016 assertEquals("autoQuoteApostropheDeep()", 2017 "I don''t '{know}' {gender,select,female{h''er}other{h''im}}.", 2018 pattern.autoQuoteApostropheDeep()); 2019 } 2020 2021 @Test TestMessagePatternFreezable()2022 public void TestMessagePatternFreezable() { 2023 MessagePattern pattern = new MessagePattern(); 2024 assertFalse("just constructed, not yet frozen", pattern.isFrozen()); 2025 pattern.parse("fee"); 2026 assertTrue("parsed, not empty", pattern.countParts() > 0); 2027 pattern.freeze(); 2028 assertTrue("just frozen", pattern.isFrozen()); 2029 try { 2030 pattern.parse("fi"); 2031 fail("MessagePattern.freeze().parse() did not fail"); 2032 } catch (Exception expected) { 2033 } 2034 assertEquals("frozen+parse: no change", "fee", pattern.autoQuoteApostropheDeep()); 2035 MessagePattern thawed = pattern.cloneAsThawed(); 2036 assertFalse("thawed", thawed.isFrozen()); 2037 assertTrue("still frozen", pattern.isFrozen()); 2038 assertTrue("frozen!=thawed", pattern != thawed); 2039 thawed.parse("fo"); 2040 assertEquals("thawed+parse", "fo", thawed.autoQuoteApostropheDeep()); 2041 } 2042 2043 @Test TestMessagePatternNamedAndNumberedArguments()2044 public void TestMessagePatternNamedAndNumberedArguments() { 2045 MessagePattern pattern = new MessagePattern(); 2046 pattern.parse("fee"); 2047 assertFalse("fee no named args", pattern.hasNamedArguments()); 2048 assertFalse("fee no numbered args", pattern.hasNumberedArguments()); 2049 pattern.parse("fi {0}"); 2050 assertFalse("fi {0} no named args", pattern.hasNamedArguments()); 2051 assertTrue("fi {0} has numbered args", pattern.hasNumberedArguments()); 2052 pattern.parse("fo {name}"); 2053 assertTrue("fo {name} has named args", pattern.hasNamedArguments()); 2054 assertFalse("fo {name} no numbered args", pattern.hasNumberedArguments()); 2055 pattern.parse("fum {0} {name}"); 2056 assertTrue("fum {0} {name} has named args", pattern.hasNamedArguments()); 2057 assertTrue("fum {0} {name} no numbered args", pattern.hasNumberedArguments()); 2058 } 2059 2060 @Test TestMessagePatternPartCoverage()2061 public void TestMessagePatternPartCoverage() { 2062 MessagePattern pattern = new MessagePattern("ab{17}c"); 2063 assertEquals("msg start { arg number } msg limit", 5, pattern.countParts()); 2064 MessagePattern.Part arg = pattern.getPart(2); 2065 assertEquals("arg number", MessagePattern.Part.Type.ARG_NUMBER, arg.getType()); 2066 assertEquals("arg number start", 3, arg.getIndex()); 2067 assertEquals("arg number length", 2, arg.getLength()); 2068 assertEquals("arg number limit", 5, arg.getLimit()); 2069 assertEquals("arg number 17", 17, arg.getValue()); 2070 } 2071 2072 @Test TestMessagePatternParseChoiceStyle()2073 public void TestMessagePatternParseChoiceStyle() { 2074 // This would be tested by ChoiceFormat if ICU4J had its own version of that, 2075 // like ICU4C does. 2076 // Instead, there is only java.text.ChoiceFormat. 2077 // Most of the implementation gets covered by testing with a MessageFormat 2078 // that contains a nested ChoiceFormat pattern, 2079 // but that does not call this public API method. 2080 MessagePattern pattern = new MessagePattern(); 2081 // Example string from java.text.ChoiceFormat class docs. 2082 pattern.parseChoiceStyle( 2083 "-1#is negative| 0#is zero or fraction | 1#is one |" + 2084 "1.0<is 1+ |2#is two |2<is more than 2."); 2085 // Only simple API coverage. The parser implementation is tested via MessageFormat. 2086 assertTrue("many parts", pattern.countParts() > 10); 2087 } 2088 2089 // This is mostly a code coverage test with verification minimized to what can be plausibly assumed: different 2090 // hash values for distinctly different objects. 2091 @Test TestDateFormatHashCode()2092 public void TestDateFormatHashCode() { 2093 DateFormat testDF1 = DateFormat.getDateInstance(DateFormat.DEFAULT, ULocale.GERMAN); 2094 DateFormat testDF2 = DateFormat.getDateInstance(DateFormat.DEFAULT, ULocale.FRENCH); 2095 2096 int actualHashResult1 = testDF1.hashCode(); 2097 int actualHashResult2 = testDF2.hashCode(); 2098 assertNotEquals("DateFormat hashCode() test: really the same hashcode?", actualHashResult1, actualHashResult2); 2099 } 2100 2101 @Test TestMessageFormatNumberSkeleton()2102 public void TestMessageFormatNumberSkeleton() { 2103 Object[][] cases = new Object[][] { 2104 { "{0,number,::percent}", ULocale.ENGLISH, 50, "50%" }, 2105 { "{0,number,::percent scale/100}", ULocale.ENGLISH, 0.5, "50%" }, 2106 { "{0,number, :: percent scale/100 }", ULocale.ENGLISH, 0.5, "50%" }, 2107 { "{0,number,::currency/USD}", ULocale.ENGLISH, 23, "$23.00" }, 2108 { "{0,number,::precision-integer}", ULocale.ENGLISH, 514.23, "514" }, 2109 { "{0,number,::.000}", ULocale.ENGLISH, 514.23, "514.230" }, 2110 { "{0,number,::.}", ULocale.ENGLISH, 514.23, "514" }, 2111 { "{0,number,::}", ULocale.FRENCH, 514.23, "514,23" }, 2112 { "Cost: {0,number,::currency/EUR}.", ULocale.ENGLISH, 4.3, "Cost: €4.30." }, 2113 { "{0,number,'::'0.00}", ULocale.ENGLISH, 50, "::50.00" }, // pattern literal 2114 }; 2115 2116 for (Object[] cas : cases) { 2117 String messagePattern = (String) cas[0]; 2118 ULocale locale = (ULocale) cas[1]; 2119 Number arg = (Number) cas[2]; 2120 String expected = (String) cas[3]; 2121 2122 MessageFormat msgf = new MessageFormat(messagePattern, locale); 2123 StringBuffer sb = new StringBuffer(); 2124 FieldPosition fpos = new FieldPosition(FieldPosition_DONT_CARE); 2125 msgf.format(new Object[] { arg }, sb, fpos); 2126 2127 assertEquals(messagePattern, expected, sb.toString()); 2128 } 2129 } 2130 doTheRealDateTimeSkeletonTesting(Date date, String messagePattern, ULocale locale, String expected)2131 private static void doTheRealDateTimeSkeletonTesting(Date date, String messagePattern, ULocale locale, String expected) { 2132 2133 MessageFormat msgf = new MessageFormat(messagePattern, locale); 2134 StringBuffer sb = new StringBuffer(); 2135 FieldPosition fpos = new FieldPosition(FieldPosition_DONT_CARE); 2136 msgf.format(new Object[] { date }, sb, fpos); 2137 2138 assertEquals(messagePattern, expected, sb.toString()); 2139 } 2140 2141 @Test TestMessageFormatDateSkeleton()2142 public void TestMessageFormatDateSkeleton() { 2143 Date date = new GregorianCalendar(2021, Calendar.NOVEMBER, 23, 16, 42, 55).getTime(); 2144 2145 doTheRealDateTimeSkeletonTesting(date, "{0,date,::MMMMd}", ULocale.ENGLISH, "November 23"); 2146 doTheRealDateTimeSkeletonTesting(date, "{0,date,::yMMMMdjm}", ULocale.ENGLISH, "November 23, 2021, 4:42 PM"); 2147 doTheRealDateTimeSkeletonTesting(date, "{0,date, :: yMMMMd }", ULocale.ENGLISH, "November 23, 2021"); 2148 doTheRealDateTimeSkeletonTesting(date, "{0,date,::yMMMMd}", ULocale.FRENCH, "23 novembre 2021"); 2149 doTheRealDateTimeSkeletonTesting(date, "Expiration: {0,date,::yMMM}!", ULocale.ENGLISH, "Expiration: Nov 2021!"); 2150 doTheRealDateTimeSkeletonTesting(date, "{0,date,'::'yMMMMd}", ULocale.ENGLISH, "::2021November23"); // pattern literal 2151 } 2152 2153 @Test TestMessageFormatTimeSkeleton()2154 public void TestMessageFormatTimeSkeleton() { 2155 Date date = new GregorianCalendar(2021, Calendar.NOVEMBER, 23, 16, 42, 55).getTime(); 2156 2157 doTheRealDateTimeSkeletonTesting(date, "{0,time,::MMMMd}", ULocale.ENGLISH, "November 23"); 2158 doTheRealDateTimeSkeletonTesting(date, "{0,time,::yMMMMdjm}", ULocale.ENGLISH, "November 23, 2021, 4:42 PM"); 2159 doTheRealDateTimeSkeletonTesting(date, "{0,time, :: yMMMMd }", ULocale.ENGLISH, "November 23, 2021"); 2160 doTheRealDateTimeSkeletonTesting(date, "{0,time,::yMMMMd}", ULocale.FRENCH, "23 novembre 2021"); 2161 doTheRealDateTimeSkeletonTesting(date, "Expiration: {0,time,::yMMM}!", ULocale.ENGLISH, "Expiration: Nov 2021!"); 2162 doTheRealDateTimeSkeletonTesting(date, "{0,time,'::'yMMMMd}", ULocale.ENGLISH, "::2021November23"); // pattern literal 2163 } 2164 } 2165