3 **********************************************************************
4 * Copyright (c) 2004-2009, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 **********************************************************************
8 * Created: April 6, 2004
10 **********************************************************************
12 package com.ibm.icu.dev.test.format;
14 import java.text.AttributedCharacterIterator;
15 import java.text.AttributedString;
16 import java.text.ChoiceFormat;
17 import java.text.FieldPosition;
18 import java.text.Format;
19 import java.text.ParseException;
20 import java.text.ParsePosition;
21 import java.util.Date;
22 import java.util.Iterator;
23 import java.util.Locale;
24 import java.util.HashMap;
28 import com.ibm.icu.text.DateFormat;
29 import com.ibm.icu.text.DecimalFormat;
30 import com.ibm.icu.text.DecimalFormatSymbols;
31 import com.ibm.icu.text.MessageFormat;
32 import com.ibm.icu.text.NumberFormat;
33 import com.ibm.icu.text.SimpleDateFormat;
34 import com.ibm.icu.text.UFormat;
35 import com.ibm.icu.util.TimeZone;
36 import com.ibm.icu.util.ULocale;
38 public class TestMessageFormat extends com.ibm.icu.dev.test.TestFmwk {
40 public static void main(String[] args) throws Exception {
41 new TestMessageFormat().run(args);
44 public void TestBug3()
46 double myNumber = -123456;
47 DecimalFormat form = null;
49 new Locale("ar", "", ""),
50 new Locale("be", "", ""),
51 new Locale("bg", "", ""),
52 new Locale("ca", "", ""),
53 new Locale("cs", "", ""),
54 new Locale("da", "", ""),
55 new Locale("de", "", ""),
56 new Locale("de", "AT", ""),
57 new Locale("de", "CH", ""),
58 new Locale("el", "", ""), // 10
59 new Locale("en", "CA", ""),
60 new Locale("en", "GB", ""),
61 new Locale("en", "IE", ""),
62 new Locale("en", "US", ""),
63 new Locale("es", "", ""),
64 new Locale("et", "", ""),
65 new Locale("fi", "", ""),
66 new Locale("fr", "", ""),
67 new Locale("fr", "BE", ""),
68 new Locale("fr", "CA", ""), // 20
69 new Locale("fr", "CH", ""),
70 new Locale("he", "", ""),
71 new Locale("hr", "", ""),
72 new Locale("hu", "", ""),
73 new Locale("is", "", ""),
74 new Locale("it", "", ""),
75 new Locale("it", "CH", ""),
76 new Locale("ja", "", ""),
77 new Locale("ko", "", ""),
78 new Locale("lt", "", ""), // 30
79 new Locale("lv", "", ""),
80 new Locale("mk", "", ""),
81 new Locale("nl", "", ""),
82 new Locale("nl", "BE", ""),
83 new Locale("no", "", ""),
84 new Locale("pl", "", ""),
85 new Locale("pt", "", ""),
86 new Locale("ro", "", ""),
87 new Locale("ru", "", ""),
88 new Locale("sh", "", ""), // 40
89 new Locale("sk", "", ""),
90 new Locale("sl", "", ""),
91 new Locale("sq", "", ""),
92 new Locale("sr", "", ""),
93 new Locale("sv", "", ""),
94 new Locale("tr", "", ""),
95 new Locale("uk", "", ""),
96 new Locale("zh", "", ""),
97 new Locale("zh", "TW", "") // 49
99 StringBuffer buffer = new StringBuffer();
100 ParsePosition parsePos = new ParsePosition(0);
102 for (i= 0; i < 49; i++) {
103 // form = (DecimalFormat)NumberFormat.getCurrencyInstance(locale[i]);
104 form = (DecimalFormat)NumberFormat.getInstance(locale[i]);
106 errln("Number format creation failed for " + locale[i].getDisplayName());
109 FieldPosition pos = new FieldPosition(0);
111 form.format(myNumber, buffer, pos);
112 parsePos.setIndex(0);
113 Object result = form.parse(buffer.toString(), parsePos);
114 logln(locale[i].getDisplayName() + " -> " + result);
115 if (parsePos.getIndex() != buffer.length()) {
116 errln("Number format parse failed.");
121 public void TestBug1()
123 final double limit[] = {0.0, 1.0, 2.0};
124 final String formats[] = {"0.0<=Arg<1.0",
127 ChoiceFormat cf = new ChoiceFormat(limit, formats);
128 assertEquals("ChoiceFormat.format", formats[1], cf.format(1));
131 public void TestBug2()
133 // {sfb} use double format in pattern, so result will match (not strictly necessary)
134 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}. ";
135 logln("The input pattern : " + pattern);
137 MessageFormat fmt = new MessageFormat(pattern);
138 assertEquals("toPattern", pattern, fmt.toPattern());
139 } catch (IllegalArgumentException e) {
140 errln("MessageFormat pattern creation failed.");
144 public void TestPattern() // aka PatternTest()
146 Object testArgs[] = {
147 new Double(1), new Double(3456),
148 "Disk", new Date(1000000000L)
150 String testCases[] = {
151 "Quotes '', '{', 'a' {0} '{0}'",
152 "Quotes '', '{', 'a' {0,number} '{0}'",
153 "'{'1,number,'#',##} {1,number,'#',##}",
154 "There are {1} files on {2} at {3}.",
155 "On {2}, there are {1} files, with {0,number,currency}.",
156 "'{1,number,percent}', {1,number,percent},",
157 "'{1,date,full}', {1,date,full},",
158 "'{3,date,full}', {3,date,full},",
159 "'{1,number,#,##}' {1,number,#,##}",
162 String testResultPatterns[] = {
163 "Quotes '', '{', a {0} '{'0}",
164 "Quotes '', '{', a {0,number} '{'0}",
165 "'{'1,number,#,##} {1,number,'#'#,##}",
166 "There are {1} files on {2} at {3}.",
167 "On {2}, there are {1} files, with {0,number,currency}.",
168 "'{'1,number,percent}, {1,number,percent},",
169 "'{'1,date,full}, {1,date,full},",
170 "'{'3,date,full}, {3,date,full},",
171 "'{'1,number,#,##} {1,number,#,##}"
174 String testResultStrings[] = {
175 "Quotes ', {, a 1 {0}",
176 "Quotes ', {, a 1 {0}",
177 "{1,number,#,##} #34,56",
178 "There are 3,456 files on Disk at 1/12/70 5:46 AM.",
179 "On Disk, there are 3,456 files, with $1.00.",
180 "{1,number,percent}, 345,600%,",
181 "{1,date,full}, Wednesday, December 31, 1969,",
182 "{3,date,full}, Monday, January 12, 1970,",
183 "{1,number,#,##} 34,56"
186 for (int i = 0; i < 9; ++i) {
187 //it_out << "\nPat in: " << testCases[i]);
190 MessageFormat form = null;
192 form = new MessageFormat(testCases[i], Locale.US);
193 } catch (IllegalArgumentException e1) {
194 errln("MessageFormat for " + testCases[i] + " creation failed.");
197 assertEquals("\"" + testCases[i] + "\".toPattern()", testResultPatterns[i], form.toPattern());
199 //it_out << "Pat out: " << form.toPattern(buffer));
200 StringBuffer result = new StringBuffer();
201 FieldPosition fieldpos = new FieldPosition(0);
202 form.format(testArgs, result, fieldpos);
203 assertEquals("format", testResultStrings[i], result.toString());
205 //it_out << "Result: " << result);
206 // /* TODO: Look at this test and see if this is still a valid test */
207 // logln("---------------- test parse ----------------");
210 // form.toPattern(buffer);
211 // logln("MSG pattern for parse: " + buffer);
213 // int parseCount = 0;
214 // Formattable* values = form.parse(result, parseCount, success);
215 // if (U_FAILURE(success)) {
216 // errln("MessageFormat failed test #5");
217 // logln(String("MessageFormat failed test #5 with error code ")+(int)success);
218 // } else if (parseCount != count) {
219 // errln("MSG count not %d as expected. Got %d", count, parseCount);
221 // UBool failed = FALSE;
222 // for (int j = 0; j < parseCount; ++j) {
223 // if (values == 0 || testArgs[j] != values[j]) {
224 // errln(((String)"MSG testargs[") + j + "]: " + toString(testArgs[j]));
225 // errln(((String)"MSG values[") + j + "] : " + toString(values[j]));
230 // errln("MessageFormat failed test #6");
234 public void TestSample() // aka sample()
236 MessageFormat form = null;
237 StringBuffer buffer2 = new StringBuffer();
239 form = new MessageFormat("There are {0} files on {1}");
240 } catch (IllegalArgumentException e1) {
241 errln("Sample message format creation failed.");
244 Object testArgs1[] = { "abc", "def" };
245 FieldPosition fieldpos = new FieldPosition(0);
246 assertEquals("format",
247 "There are abc files on def",
248 form.format(testArgs1, buffer2, fieldpos).toString());
251 public void TestStaticFormat()
253 Object arguments[] = {
255 new Date(871068000000L),
256 "a disturbance in the Force"
259 assertEquals("format",
260 "At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7.",
261 MessageFormat.format("At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
265 static final int FieldPosition_DONT_CARE = -1;
267 public void TestSimpleFormat()
269 Object testArgs1[] = {new Integer(0), "MyDisk"};
270 Object testArgs2[] = {new Integer(1), "MyDisk"};
271 Object testArgs3[] = {new Integer(12), "MyDisk"};
273 MessageFormat form = new MessageFormat(
274 "The disk \"{1}\" contains {0} file(s).");
276 StringBuffer string = new StringBuffer();
277 FieldPosition ignore = new FieldPosition(FieldPosition_DONT_CARE);
278 form.format(testArgs1, string, ignore);
279 assertEquals("format",
280 "The disk \"MyDisk\" contains 0 file(s).",
284 form.format(testArgs2, string, ignore);
285 assertEquals("format",
286 "The disk \"MyDisk\" contains 1 file(s).",
290 form.format(testArgs3, string, ignore);
291 assertEquals("format",
292 "The disk \"MyDisk\" contains 12 file(s).",
296 public void TestMsgFormatChoice()
298 MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}.");
299 double filelimits[] = {0,1,2};
300 String filepart[] = {"no files","one file","{0,number} files"};
301 ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
302 form.setFormat(1, fileform); // NOT zero, see below
304 FieldPosition ignore = new FieldPosition(FieldPosition_DONT_CARE);
305 StringBuffer string = new StringBuffer();
306 Object testArgs1[] = {new Integer(0), "MyDisk"};
307 form.format(testArgs1, string, ignore);
308 assertEquals("format#1",
309 "The disk \"MyDisk\" contains no files.",
313 Object testArgs2[] = {new Integer(1), "MyDisk"};
314 form.format(testArgs2, string, ignore);
315 assertEquals("format#2",
316 "The disk \"MyDisk\" contains one file.",
320 Object testArgs3[] = {new Integer(1273), "MyDisk"};
321 form.format(testArgs3, string, ignore);
322 assertEquals("format#3",
323 "The disk \"MyDisk\" contains 1,273 files.",
327 //---------------------------------
329 //---------------------------------
331 public void TestClone()
333 MessageFormat x = new MessageFormat("There are {0} files on {1}");
334 MessageFormat z = new MessageFormat("There are {0} files on {1} created");
335 MessageFormat y = null;
336 y = (MessageFormat)x.clone();
340 logln("First test (operator ==): Passed!");
342 errln("First test (operator ==): Failed!");
344 if ((x.equals(y) && y.equals(x)) &&
345 (!x.equals(z) && !z.equals(x)) &&
346 (!y.equals(z) && !z.equals(y)) )
347 logln("Second test (equals): Passed!");
349 errln("Second test (equals): Failed!");
354 public void TestEquals()
356 MessageFormat x = new MessageFormat("There are {0} files on {1}");
357 MessageFormat y = new MessageFormat("There are {0} files on {1}");
359 errln("First test (operator ==): Failed!");
364 public void TestNotEquals()
366 MessageFormat x = new MessageFormat("There are {0} files on {1}");
367 MessageFormat y = new MessageFormat("There are {0} files on {1}");
368 y.setLocale(Locale.FRENCH);
370 errln("First test (operator !=): Failed!");
372 y = new MessageFormat("There are {0} files on {1}");
373 y.applyPattern("There are {0} files on {1} the disk");
375 errln("Second test (operator !=): Failed!");
379 public void TestHashCode()
381 ULocale save = ULocale.getDefault();
382 ULocale.setDefault(ULocale.US);
384 MessageFormat x = new MessageFormat("There are {0} files on {1}");
385 MessageFormat z = new MessageFormat("There are {0} files on {1}");
386 MessageFormat y = null;
387 y = (MessageFormat)x.clone();
388 if (x.hashCode() != y.hashCode())
389 errln("FAIL: identical objects have different hashcodes");
390 if (x.hashCode() != z.hashCode())
391 errln("FAIL: identical objects have different hashcodes");
393 /* These are not errors
394 y.setLocale(ULocale.FRENCH);
395 if (x.hashCode() == y.hashCode())
396 errln("FAIL: different objects have same hashcodes. Locale ignored");
398 z.applyPattern("There are {0} files on {1} the disk");
399 if (x.hashCode() == z.hashCode())
400 errln("FAIL: different objects have same hashcodes. Pattern ignored");
403 ULocale.setDefault(save);
406 public void TestSetLocale()
408 Object arguments[] = {
410 new Date(871068000000L),
414 StringBuffer result = new StringBuffer();
416 //String formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
417 String formatStr = "At <time> on {1,date}, you made a {2} of {0,number,currency}.";
418 // {sfb} to get $, would need Locale::US, not Locale::ENGLISH
419 // Just use unlocalized currency symbol.
420 //String compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of $456.83.";
421 String compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of ";
422 compareStrEng += '\u00a4';
423 compareStrEng += "456.83.";
424 // {sfb} to get DM, would need Locale::GERMANY, not Locale::GERMAN
425 // Just use unlocalized currency symbol.
426 //String compareStrGer = "At <time> on 08.08.1997, you made a deposit of 456,83 DM.";
427 String compareStrGer = "At <time> on 08.08.1997, you made a deposit of ";
428 compareStrGer += "456,83\u00a0";
429 compareStrGer += '\u00a4';
430 compareStrGer += ".";
432 MessageFormat msg = new MessageFormat(formatStr, Locale.ENGLISH);
434 FieldPosition pos = new FieldPosition(0);
439 assertEquals("format", compareStrEng, result.toString());
441 msg.setLocale(Locale.ENGLISH);
442 assertEquals("getLocale", Locale.ENGLISH, msg.getLocale());
444 msg.setLocale(Locale.GERMAN);
445 assertEquals("getLocale", Locale.GERMAN, msg.getLocale());
447 msg.applyPattern(formatStr);
453 assertEquals("format", compareStrGer, result.toString());
456 logln("Testing set/get ULocale ...");
457 msg.setLocale(ULocale.ENGLISH);
458 assertEquals("getULocale", ULocale.ENGLISH, msg.getULocale());
460 msg.setLocale(ULocale.GERMAN);
461 assertEquals("getULocale", ULocale.GERMAN, msg.getULocale());
463 msg.applyPattern(formatStr);
469 assertEquals("format", compareStrGer, result.toString());
472 public void TestFormat()
474 final Object ft_arr[] =
476 new Date(871068000000L)
479 StringBuffer result = new StringBuffer();
481 //String formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
482 String formatStr = "On {0,date}, it began.";
483 String compareStr = "On Aug 8, 1997, it began.";
485 MessageFormat msg = new MessageFormat(formatStr);
486 FieldPosition fp = new FieldPosition(0);
489 msg.format(new Date(871068000000L),
492 errln("*** MSG format without expected error code.");
493 } catch (Exception e1) {
501 assertEquals("format", compareStr, result.toString());
504 public void TestParse()
506 String msgFormatString = "{0} =sep= {1}";
507 MessageFormat msg = new MessageFormat(msgFormatString);
508 String source = "abc =sep= def";
511 Object[] fmt_arr = msg.parse(source);
512 if (fmt_arr.length != 2) {
513 errln("*** MSG parse (ustring, count, err) count err.");
515 // TODO: This if statement seems to be redundant. [tschumann]
516 if (fmt_arr.length != 2) {
517 errln("*** MSG parse (ustring, parsepos., count) count err.");
519 assertEquals("parse()[0]", "abc", fmt_arr[0]);
520 assertEquals("parse()[1]", "def", fmt_arr[1]);
523 } catch (ParseException e1) {
524 errln("*** MSG parse (ustring, count, err) error.");
527 ParsePosition pp = new ParsePosition(0);
529 Object[] fmt_arr = msg.parse(source, pp);
530 if (pp.getIndex()==0 || fmt_arr==null) {
531 errln("*** MSG parse (ustring, parsepos., count) error.");
533 if (fmt_arr.length != 2) {
534 errln("*** MSG parse (ustring, parsepos., count) count err.");
536 assertEquals("parse()[0]", "abc", fmt_arr[0]);
537 assertEquals("parse()[1]", "def", fmt_arr[1]);
544 fmta = (Object[]) msg.parseObject( source, pp );
545 if (pp.getIndex() == 0) {
546 errln("*** MSG parse (ustring, Object, parsepos ) error.");
548 if (fmta.length != 2) {
549 errln("*** MSG parse (ustring, count, err) count err.");
551 // TODO: Don't we want to check fmta?
552 // In this case this if statement would be redundant, too.
554 if (fmt_arr.length != 2) {
555 errln("*** MSG parse (ustring, parsepos., count) count err.");
557 // TODO: Don't we want to check fmta? [tschumann]
558 assertEquals("parse()[0]", "abc", fmt_arr[0]);
559 assertEquals("parse()[1]", "def", fmt_arr[1]);
566 * Of course, in Java there is no adopt, but we retain the same
567 * method name. [alan]
569 public void TestAdopt()
571 String formatStr = "{0,date},{1},{2,number}";
572 String formatStrChange = "{0,number},{1,number},{2,date}";
573 MessageFormat msg = new MessageFormat(formatStr);
574 MessageFormat msgCmp = new MessageFormat(formatStr);
575 Format[] formats = msg.getFormats();
576 Format[] formatsCmp = msgCmp.getFormats();
577 Format[] formatsChg = null;
578 Format[] formatsAct = null;
581 Format[] formatsToAdopt = null;
583 if (formats==null || formatsCmp==null || (formats.length <= 0) || (formats.length != formatsCmp.length)) {
584 errln("Error getting Formats");
590 for (i = 0; i < formats.length; i++) {
593 if ((a != null) && (b != null)) {
598 } else if ((a != null) || (b != null)) {
599 errln("(a != null) || (b != null)");
604 msg.applyPattern( formatStrChange ); //set msg formats to something different
605 formatsChg = msg.getFormats(); // tested function
606 if (formatsChg==null || (formatsChg.length != formats.length)) {
607 errln("Error getting Formats");
613 for (i = 0; i < formats.length; i++) {
616 if ((a != null) && (b != null)) {
618 logln("formatsChg == formatsCmp at index " + i);
624 errln("*** MSG getFormats diff err.");
628 logln("MSG getFormats tested.");
630 msg.setFormats( formatsCmp ); //tested function
632 formatsAct = msg.getFormats();
633 if (formatsAct==null || (formatsAct.length <=0) || (formatsAct.length != formatsCmp.length)) {
634 errln("Error getting Formats");
638 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern());
639 assertEquals("msg.toPattern()", formatStr, msg.toPattern());
641 for (i = 0; i < formatsAct.length; i++) {
644 if ((a != null) && (b != null)) {
646 errln("formatsAct != formatsCmp at index " + i);
649 } else if ((a != null) || (b != null)) {
650 errln("(a != null) || (b != null)");
654 logln("MSG setFormats tested.");
658 msg.applyPattern( formatStrChange ); //set msg formats to something different
660 formatsToAdopt = new Format[formatsCmp.length];
661 if (formatsToAdopt==null) {
662 errln("memory allocation error");
666 for (i = 0; i < formatsCmp.length; i++) {
667 if (formatsCmp[i] == null) {
668 formatsToAdopt[i] = null;
670 formatsToAdopt[i] = (Format) formatsCmp[i].clone();
671 if (formatsToAdopt[i]==null) {
672 errln("Can't clone format at index " + i);
677 msg.setFormats( formatsToAdopt ); // function to test
679 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern());
680 assertEquals("msg.toPattern()", formatStr, msg.toPattern());
682 formatsAct = msg.getFormats();
683 if (formatsAct==null || (formatsAct.length <=0) || (formatsAct.length != formatsCmp.length)) {
684 errln("Error getting Formats");
688 for (i = 0; i < formatsAct.length; i++) {
691 if ((a != null) && (b != null)) {
696 } else if ((a != null) || (b != null)) {
697 errln("(a != null) || (b != null)");
701 logln("MSG adoptFormats tested.");
705 msg.applyPattern( formatStrChange ); //set msg formats to something different
707 formatsToAdopt = new Format[formatsCmp.length];
708 if (formatsToAdopt==null) {
709 errln("memory allocation error");
713 for (i = 0; i < formatsCmp.length; i++) {
714 if (formatsCmp[i] == null) {
715 formatsToAdopt[i] = null;
717 formatsToAdopt[i] = (Format) formatsCmp[i].clone();
718 if (formatsToAdopt[i]==null) {
719 errln("Can't clone format at index " + i);
725 for ( i = 0; i < formatsCmp.length; i++ ) {
726 msg.setFormat( i, formatsToAdopt[i] ); // function to test
729 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern());
730 assertEquals("msg.toPattern()", formatStr, msg.toPattern());
732 formatsAct = msg.getFormats();
733 if (formatsAct==null || (formatsAct.length <=0) || (formatsAct.length != formatsCmp.length)) {
734 errln("Error getting Formats");
738 for (i = 0; i < formatsAct.length; i++) {
741 if ((a != null) && (b != null)) {
746 } else if ((a != null) || (b != null)) {
747 errln("(a != null) || (b != null)");
751 logln("MSG adoptFormat tested.");
755 * Verify that MessageFormat accomodates more than 10 arguments and
756 * more than 10 subformats.
758 public void TestUnlimitedArgsAndSubformats() {
759 final String pattern =
760 "On {0,date} (aka {0,date,short}, aka {0,date,long}) "+
761 "at {0,time} (aka {0,time,short}, aka {0,time,long}) "+
762 "there were {1,number} werjes "+
763 "(a {3,number,percent} increase over {2,number}) "+
764 "despite the {4}''s efforts "+
765 "and to delight of {5}, {6}, {7}, {8}, {9}, and {10} {11}.";
767 MessageFormat msg = new MessageFormat(pattern);
769 final Object ARGS[] = {
770 new Date(10000000000000L),
773 new Double(1303.0/1202 - 1),
785 "On Nov 20, 2286 (aka 11/20/86, aka November 20, 2286) "+
786 "at 9:46:40 AM (aka 9:46 AM, aka 9:46:40 AM PST) "+
787 "there were 1,303 werjes "+
788 "(a 8% increase over 1,202) "+
789 "despite the Glimmung's efforts "+
790 "and to delight of the printers, Nick, his father, "+
791 "his mother, the spiddles, and of course Horace.";
792 assertEquals("format", expected, msg.format(ARGS));
793 } catch (IllegalArgumentException e1) {
794 errln("FAIL: constructor failed");
798 // test RBNF extensions to message format
799 public void TestRBNF() {
800 // WARNING: this depends on the RBNF formats for en_US
801 Locale locale = Locale.US;
803 // decimal values do not format completely for ordinal or duration, and
804 // do not always parse, so do not include them
805 "0", "1", "12", "100", "123", "1001", "123,456", "-17",
808 "There are {0,spellout} files to search.",
809 "There are {0,spellout,%simplified} files to search.",
810 "The bogus spellout {0,spellout,%BOGUS} files behaves like the default.",
811 "This is the {0,ordinal} file to search.", // TODO fix bug, ordinal does not parse
812 "Searching this file will take {0,duration} to complete.",
813 "Searching this file will take {0,duration,%with-words} to complete.",
815 final NumberFormat numFmt = NumberFormat.getInstance(locale);
816 Object[] args = new Object[1];
818 for (int i = 0; i < formats.length; ++i) {
819 MessageFormat fmt = new MessageFormat(formats[i], locale);
820 logln("Testing format pattern: '" + formats[i] + "'");
821 for (int j = 0; j < values.length; ++j) {
823 num = numFmt.parse(values[j]);
825 catch (Exception e) {
826 throw new IllegalStateException("failed to parse test argument");
829 String result = fmt.format(args);
830 logln("value: " + num + " --> " + result);
832 if (i != 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3)
834 Object[] parsedArgs = fmt.parse(result);
835 if (parsedArgs.length != 1) {
836 errln("parse returned " + parsedArgs.length + " args");
837 } else if (!parsedArgs[0].equals(num)) {
838 errln("parsed argument " + parsedArgs[0] + " != " + num);
841 catch (Exception e) {
842 errln("parse of '" + result + " returned exception: " + e.getMessage());
849 public void TestSetGetFormats()
851 Object arguments[] = {
853 new Date(871068000000L),
857 StringBuffer result = new StringBuffer();
859 String formatStr = "At <time> on {1,date}, you made a {2} of {0,number,currency}.";
860 // original expected format result
861 String compareStr = "At <time> on Aug 8, 1997, you made a deposit of $456.83.";
862 // the date being German-style, but the currency being English-style
863 String compareStr2 = "At <time> on 08.08.1997, you made a deposit of ";
864 compareStr2 += '\u00a4';
865 compareStr2 += "456.83.";
866 // both date and currency formats are German-style
867 String compareStr3 = "At <time> on 08.08.1997, you made a deposit of ";
868 compareStr3 += "456,83\u00a0";
869 compareStr3 += '\u00a4';
872 MessageFormat msg = new MessageFormat(formatStr, ULocale.US);
874 FieldPosition pos = new FieldPosition(0);
879 assertEquals("format", compareStr, result.toString());
881 // constructs a Format array with a English-style Currency formatter
882 // and a German-style Date formatter
883 // might not meaningful, just for testing setFormatsByArgIndex
884 Format[] fmts = new Format[] {
885 NumberFormat.getCurrencyInstance(ULocale.ENGLISH),
886 DateFormat.getDateInstance(DateFormat.DEFAULT, ULocale.GERMAN)
889 msg.setFormatsByArgumentIndex(fmts);
891 pos = new FieldPosition(0);
896 assertEquals("format", compareStr2, result.toString());
898 // Construct a German-style Currency formatter, replace the corresponding one
899 // Thus both formatters should format objects with German-style
900 Format newFmt = NumberFormat.getCurrencyInstance(ULocale.GERMAN);
901 msg.setFormatByArgumentIndex(0, newFmt);
903 pos = new FieldPosition(0);
908 assertEquals("format", compareStr3, result.toString());
910 // verify getFormatsByArgumentIndex
911 // you should got three formats by that
912 // - DecimalFormat locale: de
913 // - SimpleDateFormat locale: de
915 Format[] fmts2 = msg.getFormatsByArgumentIndex();
916 assertEquals("1st subformmater: Format Class", "com.ibm.icu.text.DecimalFormat", fmts2[0].getClass().getName());
917 assertEquals("1st subformmater: its Locale", ULocale.GERMAN, ((UFormat)fmts2[0]).getLocale(ULocale.VALID_LOCALE));
918 assertEquals("2nd subformatter: Format Class", "com.ibm.icu.text.SimpleDateFormat", fmts2[1].getClass().getName());
919 assertEquals("2nd subformmater: its Locale", ULocale.GERMAN, ((UFormat)fmts2[1]).getLocale(ULocale.VALID_LOCALE));
920 assertTrue("The third subFormatter is null", null == fmts2[2]);
923 // Test the fix pattern api
924 public void TestAutoQuoteApostrophe() {
925 final String[] patterns = { // new pattern, expected pattern
936 "{'a{}'a}'a", "{'a{}'a}''a",
938 "'} '{'}'", "'} '{'}''",
939 "'} {{{''", "'} {{{'''",
941 for (int i = 0; i < patterns.length; i += 2) {
942 assertEquals("[" + (i/2) + "] \"" + patterns[i] + "\"", patterns[i+1], MessageFormat.autoQuoteApostrophe(patterns[i]));
946 // This tests passing named arguments instead of numbers to format().
947 public void testFormatNamedArguments() {
948 Map arguments = new HashMap();
949 arguments.put("startDate", new Date(871068000000L));
951 StringBuffer result = new StringBuffer();
953 String formatStr = "On {startDate,date}, it began.";
954 String compareStr = "On Aug 8, 1997, it began.";
956 MessageFormat msg = new MessageFormat(formatStr);
957 FieldPosition fp = new FieldPosition(0);
960 msg.format(arguments.get("startDate"), result, fp);
961 errln("*** MSG format without expected error code.");
962 } catch (Exception e1) {
970 assertEquals("format", compareStr, result.toString());
973 // This tests parsing formatted messages with named arguments instead of
975 public void testParseNamedArguments() {
976 String msgFormatString = "{foo} =sep= {bar}";
977 MessageFormat msg = new MessageFormat(msgFormatString);
978 String source = "abc =sep= def";
981 Map fmt_map = msg.parseToMap(source);
982 if (fmt_map.keySet().size() != 2) {
983 errln("*** MSG parse (ustring, count, err) count err.");
985 assertEquals("parse()[0]", "abc", fmt_map.get("foo"));
986 assertEquals("parse()[1]", "def", fmt_map.get("bar"));
988 } catch (ParseException e1) {
989 errln("*** MSG parse (ustring, count, err) error.");
992 ParsePosition pp = new ParsePosition(0);
993 Map fmt_map = msg.parseToMap(source, pp);
994 if (pp.getIndex()==0 || fmt_map==null) {
995 errln("*** MSG parse (ustring, parsepos., count) error.");
997 if (fmt_map.keySet().size() != 2) {
998 errln("*** MSG parse (ustring, parsepos., count) count err.");
1000 assertEquals("parse()[0]", "abc", fmt_map.get("foo"));
1001 assertEquals("parse()[1]", "def", fmt_map.get("bar"));
1007 Map fmta = (Map) msg.parseObject( source, pp );
1008 if (pp.getIndex() == 0) {
1009 errln("*** MSG parse (ustring, Object, parsepos ) error.");
1011 if (fmta.keySet().size() != 2) {
1012 errln("*** MSG parse (ustring, count, err) count err.");
1014 assertEquals("parse()[0]", "abc", fmta.get("foo"));
1015 assertEquals("parse()[1]", "def", fmta.get("bar"));
1020 // Ensure that methods designed for numeric arguments only, will throw
1021 // an exception when called on MessageFormat objects created with
1023 public void testNumericOnlyMethods() {
1024 MessageFormat msg = new MessageFormat("Number of files: {numfiles}");
1025 boolean gotException = false;
1027 Format fmts[] = {new DecimalFormat()};
1028 msg.setFormatsByArgumentIndex(fmts);
1029 } catch (IllegalArgumentException e) {
1030 gotException = true;
1032 if (!gotException) {
1033 errln("MessageFormat.setFormatsByArgumentIndex() should throw an " +
1034 "IllegalArgumentException when called on formats with " +
1035 "named arguments but did not!");
1038 gotException = false;
1040 msg.setFormatByArgumentIndex(0, new DecimalFormat());
1041 } catch (IllegalArgumentException e) {
1042 gotException = true;
1044 if (!gotException) {
1045 errln("MessageFormat.setFormatByArgumentIndex() should throw an " +
1046 "IllegalArgumentException when called on formats with " +
1047 "named arguments but did not!");
1050 gotException = false;
1052 msg.getFormatsByArgumentIndex();
1053 } catch (IllegalArgumentException e) {
1054 gotException = true;
1056 if (!gotException) {
1057 errln("MessageFormat.getFormatsByArgumentIndex() should throw an " +
1058 "IllegalArgumentException when called on formats with " +
1059 "named arguments but did not!");
1062 gotException = false;
1064 Object args[] = {new Long(42)};
1065 msg.format(args, new StringBuffer(), new FieldPosition(0));
1066 } catch (IllegalArgumentException e) {
1067 gotException = true;
1069 if (!gotException) {
1070 errln("MessageFormat.format(Object[], StringBuffer, FieldPosition) " +
1071 "should throw an IllegalArgumentException when called on " +
1072 "formats with named arguments but did not!");
1075 gotException = false;
1077 Object args[] = {new Long(42)};
1078 msg.format((Object) args, new StringBuffer(), new FieldPosition(0));
1079 } catch (IllegalArgumentException e) {
1080 gotException = true;
1082 if (!gotException) {
1083 errln("MessageFormat.format(Object, StringBuffer, FieldPosition) " +
1084 "should throw an IllegalArgumentException when called with " +
1085 "non-Map object as argument on formats with named " +
1086 "arguments but did not!");
1089 gotException = false;
1091 msg.parse("Number of files: 5", new ParsePosition(0));
1092 } catch (IllegalArgumentException e) {
1093 gotException = true;
1095 if (!gotException) {
1096 errln("MessageFormat.parse(String, ParsePosition) " +
1097 "should throw an IllegalArgumentException when called with " +
1098 "non-Map object as argument on formats with named " +
1099 "arguments but did not!");
1102 gotException = false;
1104 msg.parse("Number of files: 5");
1105 } catch (IllegalArgumentException e) {
1106 gotException = true;
1107 } catch (ParseException e) {
1108 errln("Wrong exception thrown.");
1110 if (!gotException) {
1111 errln("MessageFormat.parse(String) " +
1112 "should throw an IllegalArgumentException when called with " +
1113 "non-Map object as argument on formats with named " +
1114 "arguments but did not!");
1118 public void testNamedArguments() {
1119 // Ensure that mixed argument types are not allowed.
1120 // Either all arguments have to be numeric or valid identifiers.
1122 new MessageFormat("Number of files in folder {0}: {numfiles}");
1123 errln("Creating a MessageFormat with mixed argument types " +
1124 "(named and numeric) should throw an " +
1125 "IllegalArgumentException but did not!");
1126 } catch (IllegalArgumentException e) {}
1129 new MessageFormat("Number of files in folder {folder}: {1}");
1130 errln("Creating a MessageFormat with mixed argument types " +
1131 "(named and numeric) should throw an " +
1132 "IllegalArgumentException but did not!");
1133 } catch (IllegalArgumentException e) {}
1135 // Test named arguments.
1136 MessageFormat mf = new MessageFormat("Number of files in folder {folder}: {numfiles}");
1137 if (!mf.usesNamedArguments()) {
1138 errln("message format 1 should have used named arguments");
1140 mf = new MessageFormat("Wavelength: {\u028EValue\uFF14}");
1141 if (!mf.usesNamedArguments()) {
1142 errln("message format 2 should have used named arguments");
1145 // Test argument names with invalid start characters.
1147 new MessageFormat("Wavelength: {_\u028EValue\uFF14}");
1148 errln("Creating a MessageFormat with invalid argument names " +
1149 "should throw an IllegalArgumentException but did not!");
1150 } catch (IllegalArgumentException e) {}
1153 new MessageFormat("Wavelength: {\uFF14\u028EValue}");
1154 errln("Creating a MessageFormat with invalid argument names " +
1155 "should throw an IllegalArgumentException but did not!");
1156 } catch (IllegalArgumentException e) {}
1158 // Test argument names with invalid continue characters.
1160 new MessageFormat("Wavelength: {Value@\uFF14}");
1161 errln("Creating a MessageFormat with invalid argument names " +
1162 "should throw an IllegalArgumentException but did not!");
1163 } catch (IllegalArgumentException e) {}
1166 new MessageFormat("Wavelength: {Value(\uFF14)}");
1167 errln("Creating a MessageFormat with invalid argument names " +
1168 "should throw an IllegalArgumentException but did not!");
1169 } catch (IllegalArgumentException e) {}
1172 public void testNumericFormatWithMap() {
1173 MessageFormat mf = new MessageFormat("X:{2} Y:{1}");
1174 if (mf.usesNamedArguments()) {
1175 errln("should not use named arguments");
1178 Map map12 = new HashMap();
1179 map12.put("1", "one");
1180 map12.put("2", "two");
1182 String target = "X:two Y:one";
1183 String result = mf.format(map12);
1184 if (!target.equals(result)) {
1185 errln("expected '" + target + "' but got '" + result + "'");
1189 Map mapResult = mf.parseToMap(target);
1190 if (!map12.equals(mapResult)) {
1191 errln("expected " + map12 + " but got " + mapResult);
1193 } catch (ParseException e) {
1194 errln("unexpected exception: " + e.getMessage());
1197 Map map10 = new HashMap();
1198 map10.put("1", "one");
1199 map10.put("0", "zero");
1200 target = "X:{2} Y:one";
1201 result = mf.format(map10);
1202 if (!target.equals(result)) {
1203 errln("expected '" + target + "' but got '" + result + "'");
1206 DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM);
1207 DateFormat timeFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM);
1208 Map fmtMap = new HashMap();
1209 fmtMap.put("1", dateFormat);
1210 fmtMap.put("2", timeFormat);
1211 mf.setFormatsByArgumentName(fmtMap);
1212 Date date = new Date(661439820000L);
1215 result = mf.format(map12); // should fail, wrong argument type
1216 fail("expected exception but got '" + result + "'");
1217 } catch (IllegalArgumentException e) {
1221 Map argMap = new HashMap();
1222 argMap.put("1", date);
1223 argMap.put("2", date);
1224 target = "X:5:17:00 AM Y:Dec 17, 1990";
1225 result = mf.format(argMap);
1226 if (!target.equals(result)) {
1227 errln("expected '" + target + "' but got '" + result + "'");
1231 // This tests nested Formats inside PluralFormat.
1232 public void testNestedFormatsInPluralFormat() {
1234 MessageFormat msgFmt = new MessageFormat(
1235 "{0, plural, one {{0, number,C''''est #,##0.0# fichier}} " +
1236 "other {Ce sont # fichiers}} dans la liste.",
1238 Object objArray[] = {new Long(0)};
1239 HashMap objMap = new HashMap();
1240 objMap.put("argument", objArray[0]);
1241 String result = msgFmt.format(objArray);
1242 if (!result.equals("C'est 0,0 fichier dans la liste.")) {
1243 errln("PluralFormat produced wrong message string.");
1245 } catch (Exception e) {
1246 e.printStackTrace();
1247 throw new RuntimeException(e.getMessage());
1251 // This tests PluralFormats used inside MessageFormats.
1252 public void testPluralFormat() {
1254 MessageFormat mfNum = new MessageFormat(
1255 "{0, plural, one{C''est # fichier} other " +
1256 "{Ce sont # fichiers}} dans la liste.",
1258 MessageFormat mfAlpha = new MessageFormat(
1259 "{argument, plural, one{C''est # fichier} other {Ce " +
1260 "sont # fichiers}} dans la liste.",
1262 Object objArray[] = {new Long(0)};
1263 HashMap objMap = new HashMap();
1264 objMap.put("argument", objArray[0]);
1265 String result = mfNum.format(objArray);
1266 if (!result.equals(mfAlpha.format(objMap))) {
1267 errln("PluralFormat's output differs when using named " +
1268 "arguments instead of numbers!");
1270 if (!result.equals("C'est 0 fichier dans la liste.")) {
1271 errln("PluralFormat produced wrong message string.");
1275 MessageFormat mfNum = new MessageFormat (
1276 "There {0, plural, one{is # zavod}few{are {0, " +
1277 "number,###.0} zavoda} other{are # zavodov}} in the " +
1280 MessageFormat mfAlpha = new MessageFormat (
1281 "There {argument, plural, one{is # zavod}few{" +
1282 "are {argument, number,###.0} zavoda} other{are # " +
1283 "zavodov}} in the directory.",
1285 Object objArray[] = {new Long(4)};
1286 HashMap objMap = new HashMap();
1287 objMap.put("argument", objArray[0]);
1288 String result = mfNum.format(objArray);
1289 if (!result.equals(mfAlpha.format(objMap))) {
1290 errln("PluralFormat's output differs when using named " +
1291 "arguments instead of numbers!");
1293 if (!result.equals("There are 4,0 zavoda in the directory.")) {
1294 errln("PluralFormat produced wrong message string.");
1299 // Test toPattern when there is a PluralFormat
1300 public void testPluralFormatToPattern() {
1301 String[] patterns = {
1302 "Beware of vicious {0, plural, one {hamster} other {hamsters}}.",
1303 "{0, plural, one {{0, number,C''''est #,##0.0# fichier}} other {Ce sont # fichiers}} dans la liste.",
1304 "{0, plural, one {C''est # fichier} other {Ce sont # fichiers}} dans la liste.",
1307 for (int i = 0; i < patterns.length; ++i) {
1308 String pattern = patterns[i];
1309 MessageFormat mf = new MessageFormat(pattern);
1310 MessageFormat mf2 = new MessageFormat(mf.toPattern());
1311 if (!mf.equals(mf2)) {
1312 errln("message formats not equal for pattern:\n*** '" + pattern + "'\n*** '" +
1313 mf.toPattern() + "'");
1318 // Test case for null arguments.
1320 public void TestNullArgs() {
1321 MessageFormat msgfmt = new MessageFormat("{0} - {1}");
1322 Object[][] TEST_CASES = {
1323 {null, "{0} - {1}"},
1324 {new Object[] {null}, "null - {1}"},
1325 {new Object[] {null, null}, "null - null"},
1326 {new Object[] {"one"}, "one - {1}"},
1327 {new Object[] {"one", null}, "one - null"},
1328 {new Object[] {null, "two"}, "null - two"},
1331 for (int i = 0; i < TEST_CASES.length; i++) {
1332 String text = msgfmt.format(TEST_CASES[i][0]);
1333 if (!text.equals(TEST_CASES[i][1])) {
1334 errln("FAIL: Returned[" + text + "] Expected[" + TEST_CASES[i][1] + "]");
1339 public void TestSetFormat() {
1340 MessageFormat ms = new MessageFormat("{number} {date}", ULocale.ENGLISH);
1341 final DecimalFormat decimalFormat = new DecimalFormat("000.000", DecimalFormatSymbols.getInstance(ULocale.ENGLISH));
1342 ms.setFormatByArgumentName("number", decimalFormat);
1343 final SimpleDateFormat dateFormat = new SimpleDateFormat("'year:'yy 'month:'MM 'day:'dd");
1344 dateFormat.setTimeZone(TimeZone.getTimeZone("Etc/GMT"));
1345 ms.setFormatByArgumentName("date", dateFormat);
1346 Map map = new HashMap();
1347 map.put("number", new Integer(1234));
1348 map.put("date", new Date(0,0,0));
1349 String result = ms.format(map);
1350 assertEquals("setFormatByArgumentName", "1234.000 year:99 month:12 day:31", result);
1351 Set formatNames = ms.getFormatArgumentNames();
1352 assertEquals("Format Names match", formatNames, map.keySet());
1353 assertEquals("Decimal", decimalFormat, ms.getFormatByArgumentName("number"));
1354 assertEquals("Date", dateFormat, ms.getFormatByArgumentName("date"));
1357 //#if defined(FOUNDATION10) || defined(J2SE13)
1359 // Test case for formatToCharacterIterator
1360 public void TestFormatToCharacterIterator() {
1361 MessageFormat[] msgfmts = {
1362 new MessageFormat("The {3,ordinal} folder ''{0}'' contains {2,number} file(s), created at {1,time} on {1,date}."),
1363 new MessageFormat("The {arg3,ordinal} folder ''{arg0}'' contains {arg2,number} file(s), created at {arg1,time} on {arg1,date}."), // same as above, but named args
1364 new MessageFormat("The folder contains {0}.")
1367 double filelimits[] = {0,1,2};
1368 String filepart[] = {"no files","one file","{0,number} files"};
1369 ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
1370 msgfmts[2].setFormat(0, fileform);
1373 Object[] args0 = new Object[] {"tmp", new Date(1184777888000L), new Integer(15), new Integer(2)};
1375 HashMap args1 = new HashMap();
1376 args1.put("arg0", "tmp");
1377 args1.put("arg1", new Date(1184777888000L));
1378 args1.put("arg2", new Integer(15));
1379 args1.put("arg3", new Integer(2));
1381 Object[] args2 = new Object[] {new Integer(34)};
1389 String[] expectedStrings = {
1390 "The 2\u207f\u1d48 folder 'tmp' contains 15 file(s), created at 9:58:08 AM on Jul 18, 2007.",
1391 "The 2\u207f\u1d48 folder 'tmp' contains 15 file(s), created at 9:58:08 AM on Jul 18, 2007.",
1392 "The folder contains 34 files."
1395 AttributedString[] expectedAttributedStrings = {
1396 new AttributedString(expectedStrings[0]),
1397 new AttributedString(expectedStrings[1]),
1398 new AttributedString(expectedStrings[2])
1401 // Add expected attributes to the expectedAttributedStrings[0]
1402 expectedAttributedStrings[0].addAttribute(MessageFormat.Field.ARGUMENT, new Integer(3), 4, 7);
1403 expectedAttributedStrings[0].addAttribute(MessageFormat.Field.ARGUMENT, new Integer(0), 16, 19);
1404 expectedAttributedStrings[0].addAttribute(MessageFormat.Field.ARGUMENT, new Integer(2), 30, 32);
1405 expectedAttributedStrings[0].addAttribute(NumberFormat.Field.INTEGER, NumberFormat.Field.INTEGER, 30, 32);
1406 expectedAttributedStrings[0].addAttribute(MessageFormat.Field.ARGUMENT, new Integer(1), 53, 63);
1407 expectedAttributedStrings[0].addAttribute(DateFormat.Field.HOUR1, DateFormat.Field.HOUR1, 53, 54);
1408 expectedAttributedStrings[0].addAttribute(DateFormat.Field.MINUTE, DateFormat.Field.MINUTE, 55, 57);
1409 expectedAttributedStrings[0].addAttribute(DateFormat.Field.SECOND, DateFormat.Field.SECOND, 58, 60);
1410 expectedAttributedStrings[0].addAttribute(DateFormat.Field.AM_PM, DateFormat.Field.AM_PM, 61, 63);
1411 expectedAttributedStrings[0].addAttribute(MessageFormat.Field.ARGUMENT, new Integer(1), 67, 79);
1412 expectedAttributedStrings[0].addAttribute(DateFormat.Field.MONTH, DateFormat.Field.MONTH, 67, 70);
1413 expectedAttributedStrings[0].addAttribute(DateFormat.Field.DAY_OF_MONTH, DateFormat.Field.DAY_OF_MONTH, 71, 73);
1414 expectedAttributedStrings[0].addAttribute(DateFormat.Field.YEAR, DateFormat.Field.YEAR, 75, 79);
1416 // Add expected attributes to the expectedAttributedStrings[1]
1417 expectedAttributedStrings[1].addAttribute(MessageFormat.Field.ARGUMENT, "arg3", 4, 7);
1418 expectedAttributedStrings[1].addAttribute(MessageFormat.Field.ARGUMENT, "arg0", 16, 19);
1419 expectedAttributedStrings[1].addAttribute(MessageFormat.Field.ARGUMENT, "arg2", 30, 32);
1420 expectedAttributedStrings[1].addAttribute(NumberFormat.Field.INTEGER, NumberFormat.Field.INTEGER, 30, 32);
1421 expectedAttributedStrings[1].addAttribute(MessageFormat.Field.ARGUMENT, "arg1", 53, 63);
1422 expectedAttributedStrings[1].addAttribute(DateFormat.Field.HOUR1, DateFormat.Field.HOUR1, 53, 54);
1423 expectedAttributedStrings[1].addAttribute(DateFormat.Field.MINUTE, DateFormat.Field.MINUTE, 55, 57);
1424 expectedAttributedStrings[1].addAttribute(DateFormat.Field.SECOND, DateFormat.Field.SECOND, 58, 60);
1425 expectedAttributedStrings[1].addAttribute(DateFormat.Field.AM_PM, DateFormat.Field.AM_PM, 61, 63);
1426 expectedAttributedStrings[1].addAttribute(MessageFormat.Field.ARGUMENT, "arg1", 67, 79);
1427 expectedAttributedStrings[1].addAttribute(DateFormat.Field.MONTH, DateFormat.Field.MONTH, 67, 70);
1428 expectedAttributedStrings[1].addAttribute(DateFormat.Field.DAY_OF_MONTH, DateFormat.Field.DAY_OF_MONTH, 71, 73);
1429 expectedAttributedStrings[1].addAttribute(DateFormat.Field.YEAR, DateFormat.Field.YEAR, 75, 79);
1431 // Add expected attributes to the expectedAttributedStrings[2]
1432 expectedAttributedStrings[2].addAttribute(MessageFormat.Field.ARGUMENT, new Integer(0), 20, 28);
1433 expectedAttributedStrings[2].addAttribute(NumberFormat.Field.INTEGER, NumberFormat.Field.INTEGER, 20, 22);
1435 for (int i = 0; i < msgfmts.length; i++) {
1436 AttributedCharacterIterator acit = msgfmts[i].formatToCharacterIterator(args[i]);
1437 AttributedCharacterIterator expectedAcit = expectedAttributedStrings[i].getIterator();
1439 // Check available attributes
1440 Set attrSet = acit.getAllAttributeKeys();
1441 Set expectedAttrSet = expectedAcit.getAllAttributeKeys();
1442 if (attrSet.size() != expectedAttrSet.size()) {
1443 errln("FAIL: Number of attribute keys is " + attrSet.size() + " expected: " + expectedAttrSet.size());
1445 Iterator attrIterator = attrSet.iterator();
1446 while (attrIterator.hasNext()) {
1447 AttributedCharacterIterator.Attribute attr = (AttributedCharacterIterator.Attribute)attrIterator.next();
1448 if (!expectedAttrSet.contains(attr)) {
1449 errln("FAIL: The attribute " + attr + " is not expected.");
1453 StringBuffer buf = new StringBuffer();
1454 int index = acit.getBeginIndex();
1455 int end = acit.getEndIndex();
1456 int indexExp = expectedAcit.getBeginIndex();
1457 int expectedLen = expectedAcit.getEndIndex() - indexExp;
1458 if (end - index != expectedLen) {
1459 errln("FAIL: Length of the result attributed string is " + (end - index) + " expected: " + expectedLen);
1461 // Check attributes associated with each character
1462 while (index < end) {
1463 char c = acit.setIndex(index);
1465 expectedAcit.setIndex(indexExp);
1467 Map attrs = acit.getAttributes();
1468 Map attrsExp = expectedAcit.getAttributes();
1469 if (attrs.size() != attrsExp.size()) {
1470 errln("FAIL: Number of attributes associated with index " + index + " is " + attrs.size()
1471 + " expected: " + attrsExp.size());
1473 // Check all attributes at the index
1474 Iterator entryIterator = attrsExp.entrySet().iterator();
1475 while (entryIterator.hasNext()) {
1476 Map.Entry entry = (Map.Entry)entryIterator.next();
1477 if (attrs.containsKey(entry.getKey())) {
1478 Object value = attrs.get(entry.getKey());
1479 assertEquals("Attribute value at index " + index, entry.getValue(), value);
1481 errln("FAIL: Attribute " + entry.getKey() + " is missing at index " + index);
1488 assertEquals("AttributedString contents", expectedStrings[i], buf.toString());