]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/tmsgfmt.cpp
ICU-491.11.2.tar.gz
[apple/icu.git] / icuSources / test / intltest / tmsgfmt.cpp
1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2011, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************
6 * File TMSGFMT.CPP
7 *
8 * Modification History:
9 *
10 * Date Name Description
11 * 03/24/97 helena Converted from Java.
12 * 07/11/97 helena Updated to work on AIX.
13 * 08/04/97 jfitz Updated to intltest
14 *******************************************************************/
15
16 #include "unicode/utypes.h"
17
18 #if !UCONFIG_NO_FORMATTING
19
20 #include "tmsgfmt.h"
21
22 #include "unicode/format.h"
23 #include "unicode/decimfmt.h"
24 #include "unicode/locid.h"
25 #include "unicode/msgfmt.h"
26 #include "unicode/numfmt.h"
27 #include "unicode/choicfmt.h"
28 #include "unicode/messagepattern.h"
29 #include "unicode/selfmt.h"
30 #include "unicode/gregocal.h"
31 #include <stdio.h>
32
33 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
34
35 void
36 TestMessageFormat::runIndexedTest(int32_t index, UBool exec,
37 const char* &name, char* /*par*/) {
38 TESTCASE_AUTO_BEGIN;
39 TESTCASE_AUTO(testBug1);
40 TESTCASE_AUTO(testBug2);
41 TESTCASE_AUTO(sample);
42 TESTCASE_AUTO(PatternTest);
43 TESTCASE_AUTO(testStaticFormat);
44 TESTCASE_AUTO(testSimpleFormat);
45 TESTCASE_AUTO(testMsgFormatChoice);
46 TESTCASE_AUTO(testCopyConstructor);
47 TESTCASE_AUTO(testAssignment);
48 TESTCASE_AUTO(testClone);
49 TESTCASE_AUTO(testEquals);
50 TESTCASE_AUTO(testNotEquals);
51 TESTCASE_AUTO(testSetLocale);
52 TESTCASE_AUTO(testFormat);
53 TESTCASE_AUTO(testParse);
54 TESTCASE_AUTO(testAdopt);
55 TESTCASE_AUTO(testCopyConstructor2);
56 TESTCASE_AUTO(TestUnlimitedArgsAndSubformats);
57 TESTCASE_AUTO(TestRBNF);
58 TESTCASE_AUTO(TestTurkishCasing);
59 TESTCASE_AUTO(testAutoQuoteApostrophe);
60 TESTCASE_AUTO(testMsgFormatPlural);
61 TESTCASE_AUTO(testMsgFormatSelect);
62 TESTCASE_AUTO(testApostropheInPluralAndSelect);
63 TESTCASE_AUTO(TestApostropheMode);
64 TESTCASE_AUTO(TestCompatibleApostrophe);
65 TESTCASE_AUTO(testCoverage);
66 TESTCASE_AUTO(TestTrimArgumentName);
67 TESTCASE_AUTO_END;
68 }
69
70 void TestMessageFormat::testBug3()
71 {
72 double myNumber = -123456;
73 DecimalFormat *form = 0;
74 Locale locale[] = {
75 Locale("ar", "", ""),
76 Locale("be", "", ""),
77 Locale("bg", "", ""),
78 Locale("ca", "", ""),
79 Locale("cs", "", ""),
80 Locale("da", "", ""),
81 Locale("de", "", ""),
82 Locale("de", "AT", ""),
83 Locale("de", "CH", ""),
84 Locale("el", "", ""), // 10
85 Locale("en", "CA", ""),
86 Locale("en", "GB", ""),
87 Locale("en", "IE", ""),
88 Locale("en", "US", ""),
89 Locale("es", "", ""),
90 Locale("et", "", ""),
91 Locale("fi", "", ""),
92 Locale("fr", "", ""),
93 Locale("fr", "BE", ""),
94 Locale("fr", "CA", ""), // 20
95 Locale("fr", "CH", ""),
96 Locale("he", "", ""),
97 Locale("hr", "", ""),
98 Locale("hu", "", ""),
99 Locale("is", "", ""),
100 Locale("it", "", ""),
101 Locale("it", "CH", ""),
102 Locale("ja", "", ""),
103 Locale("ko", "", ""),
104 Locale("lt", "", ""), // 30
105 Locale("lv", "", ""),
106 Locale("mk", "", ""),
107 Locale("nl", "", ""),
108 Locale("nl", "BE", ""),
109 Locale("no", "", ""),
110 Locale("pl", "", ""),
111 Locale("pt", "", ""),
112 Locale("ro", "", ""),
113 Locale("ru", "", ""),
114 Locale("sh", "", ""), // 40
115 Locale("sk", "", ""),
116 Locale("sl", "", ""),
117 Locale("sq", "", ""),
118 Locale("sr", "", ""),
119 Locale("sv", "", ""),
120 Locale("tr", "", ""),
121 Locale("uk", "", ""),
122 Locale("zh", "", ""),
123 Locale("zh", "TW", "") // 49
124 };
125 int32_t i;
126 for (i= 0; i < 49; i++) {
127 UnicodeString buffer;
128 logln(locale[i].getDisplayName(buffer));
129 UErrorCode success = U_ZERO_ERROR;
130 // form = (DecimalFormat*)NumberFormat::createCurrencyInstance(locale[i], success);
131 form = (DecimalFormat*)NumberFormat::createInstance(locale[i], success);
132 if (U_FAILURE(success)) {
133 errln("Err: Number Format ");
134 logln("Number format creation failed.");
135 continue;
136 }
137 Formattable result;
138 FieldPosition pos(0);
139 buffer.remove();
140 form->format(myNumber, buffer, pos);
141 success = U_ZERO_ERROR;
142 ParsePosition parsePos;
143 form->parse(buffer, result, parsePos);
144 logln(UnicodeString(" -> ") /* + << dec*/ + toString(result) + UnicodeString("[supposed output for result]"));
145 if (U_FAILURE(success)) {
146 errln("Err: Number Format parse");
147 logln("Number format parse failed.");
148 }
149 delete form;
150 }
151 }
152
153 void TestMessageFormat::testBug1()
154 {
155 const double limit[] = {0.0, 1.0, 2.0};
156 const UnicodeString formats[] = {"0.0<=Arg<1.0",
157 "1.0<=Arg<2.0",
158 "2.0<-Arg"};
159 ChoiceFormat *cf = new ChoiceFormat(limit, formats, 3);
160 FieldPosition status(0);
161 UnicodeString toAppendTo;
162 cf->format((int32_t)1, toAppendTo, status);
163 if (toAppendTo != "1.0<=Arg<2.0") {
164 errln("ChoiceFormat cmp in testBug1");
165 }
166 logln(toAppendTo);
167 delete cf;
168 }
169
170 void TestMessageFormat::testBug2()
171 {
172 UErrorCode status = U_ZERO_ERROR;
173 UnicodeString result;
174 // {sfb} use double format in pattern, so result will match (not strictly necessary)
175 const UnicodeString pattern = "There {0,choice,0#are no files|1#is one file|1<are {0, number} files} on disk {1}. ";
176 logln("The input pattern : " + pattern);
177 MessageFormat *fmt = new MessageFormat(pattern, status);
178 if (U_FAILURE(status)) {
179 dataerrln("MessageFormat pattern creation failed. - %s", u_errorName(status));
180 return;
181 }
182 logln("The output pattern is : " + fmt->toPattern(result));
183 if (pattern != result) {
184 errln("MessageFormat::toPattern() failed.");
185 }
186 delete fmt;
187 }
188
189 #if 0
190 #if defined(_DEBUG) && U_IOSTREAM_SOURCE >= 199711
191 //----------------------------------------------------
192 // console I/O
193 //----------------------------------------------------
194
195 #include <iostream>
196 std::ostream& operator<<(std::ostream& stream, const Formattable& obj);
197
198 #include "unicode/datefmt.h"
199 #include <stdlib.h>
200 #include <string.h>
201
202 IntlTest&
203 operator<<( IntlTest& stream,
204 const Formattable& obj)
205 {
206 static DateFormat *defDateFormat = 0;
207
208 UnicodeString buffer;
209 switch(obj.getType()) {
210 case Formattable::kDate :
211 if (defDateFormat == 0) {
212 defDateFormat = DateFormat::createInstance();
213 }
214 defDateFormat->format(obj.getDate(), buffer);
215 stream << buffer;
216 break;
217 case Formattable::kDouble :
218 char convert[20];
219 sprintf( convert, "%lf", obj.getDouble() );
220 stream << convert << "D";
221 break;
222 case Formattable::kLong :
223 stream << obj.getLong() << "L";
224 break;
225 case Formattable::kString:
226 stream << "\"" << obj.getString(buffer) << "\"";
227 break;
228 case Formattable::kArray:
229 int32_t i, count;
230 const Formattable* array;
231 array = obj.getArray(count);
232 stream << "[";
233 for (i=0; i<count; ++i) stream << array[i] << ( (i==(count-1)) ? "" : ", " );
234 stream << "]";
235 break;
236 default:
237 stream << "INVALID_Formattable";
238 }
239 return stream;
240 }
241 #endif /* defined(_DEBUG) && U_IOSTREAM_SOURCE >= 199711 */
242 #endif
243
244 void TestMessageFormat::PatternTest()
245 {
246 Formattable testArgs[] = {
247 Formattable(double(1)), Formattable(double(3456)),
248 Formattable("Disk"), Formattable(UDate((int32_t)1000000000L), Formattable::kIsDate)
249 };
250 UnicodeString testCases[] = {
251 "Quotes '', '{', 'a' {0} '{0}'",
252 "Quotes '', '{', 'a' {0,number} '{0}'",
253 "'{'1,number,'#',##} {1,number,'#',##}",
254 "There are {1} files on {2} at {3}.",
255 "On {2}, there are {1} files, with {0,number,currency}.",
256 "'{1,number,percent}', {1,number,percent},",
257 "'{1,date,full}', {1,date,full},",
258 "'{3,date,full}', {3,date,full},",
259 "'{1,number,#,##}' {1,number,#,##}",
260 };
261
262 // ICU 4.8 returns the original pattern (testCases),
263 // rather than toPattern() reconstituting a new, equivalent pattern string (testResultPatterns).
264 /*UnicodeString testResultPatterns[] = {
265 "Quotes '', '{', a {0} '{'0}",
266 "Quotes '', '{', a {0,number} '{'0}",
267 "'{'1,number,#,##} {1,number,'#'#,##}",
268 "There are {1} files on {2} at {3}.",
269 "On {2}, there are {1} files, with {0,number,currency}.",
270 "'{'1,number,percent}, {1,number,percent},",
271 "'{'1,date,full}, {1,date,full},",
272 "'{'3,date,full}, {3,date,full},",
273 "'{'1,number,#,##} {1,number,#,##}"
274 };*/
275
276 UnicodeString testResultStrings[] = {
277 "Quotes ', {, 'a' 1 {0}",
278 "Quotes ', {, 'a' 1 {0}",
279 "{1,number,'#',##} #34,56",
280 "There are 3,456 files on Disk at 1/12/70 5:46 AM.",
281 "On Disk, there are 3,456 files, with $1.00.",
282 "{1,number,percent}, 345,600%,",
283 "{1,date,full}, Wednesday, December 31, 1969,",
284 "{3,date,full}, Monday, January 12, 1970,",
285 "{1,number,#,##} 34,56"
286 };
287
288
289 for (int32_t i = 0; i < 9; ++i) {
290 //it_out << "\nPat in: " << testCases[i]);
291
292 MessageFormat *form = 0;
293 UErrorCode success = U_ZERO_ERROR;
294 UnicodeString buffer;
295 form = new MessageFormat(testCases[i], Locale::getUS(), success);
296 if (U_FAILURE(success)) {
297 dataerrln("MessageFormat creation failed.#1 - %s", u_errorName(success));
298 logln(((UnicodeString)"MessageFormat for ") + testCases[i] + " creation failed.\n");
299 continue;
300 }
301 // ICU 4.8 returns the original pattern (testCases),
302 // rather than toPattern() reconstituting a new, equivalent pattern string (testResultPatterns).
303 if (form->toPattern(buffer) != testCases[i]) {
304 // Note: An alternative test would be to build MessagePattern objects for
305 // both the input and output patterns and compare them, taking SKIP_SYNTAX etc.
306 // into account.
307 // (Too much trouble...)
308 errln(UnicodeString("TestMessageFormat::PatternTest failed test #2, i = ") + i);
309 //form->toPattern(buffer);
310 errln(((UnicodeString)" Orig: ") + testCases[i]);
311 errln(((UnicodeString)" Exp: ") + testCases[i]);
312 errln(((UnicodeString)" Got: ") + buffer);
313 }
314
315 //it_out << "Pat out: " << form->toPattern(buffer));
316 UnicodeString result;
317 int32_t count = 4;
318 FieldPosition fieldpos(0);
319 form->format(testArgs, count, result, fieldpos, success);
320 if (U_FAILURE(success)) {
321 dataerrln("MessageFormat failed test #3 - %s", u_errorName(success));
322 logln("TestMessageFormat::PatternTest failed test #3");
323 continue;
324 }
325 if (result != testResultStrings[i]) {
326 errln("TestMessageFormat::PatternTest failed test #4");
327 logln("TestMessageFormat::PatternTest failed #4.");
328 logln(UnicodeString(" Result: ") + result );
329 logln(UnicodeString(" Expected: ") + testResultStrings[i] );
330 }
331
332
333 //it_out << "Result: " << result);
334 #if 0
335 /* TODO: Look at this test and see if this is still a valid test */
336 logln("---------------- test parse ----------------");
337
338 form->toPattern(buffer);
339 logln("MSG pattern for parse: " + buffer);
340
341 int32_t parseCount = 0;
342 Formattable* values = form->parse(result, parseCount, success);
343 if (U_FAILURE(success)) {
344 errln("MessageFormat failed test #5");
345 logln(UnicodeString("MessageFormat failed test #5 with error code ")+(int32_t)success);
346 } else if (parseCount != count) {
347 errln("MSG count not %d as expected. Got %d", count, parseCount);
348 }
349 UBool failed = FALSE;
350 for (int32_t j = 0; j < parseCount; ++j) {
351 if (values == 0 || testArgs[j] != values[j]) {
352 errln(((UnicodeString)"MSG testargs[") + j + "]: " + toString(testArgs[j]));
353 errln(((UnicodeString)"MSG values[") + j + "] : " + toString(values[j]));
354 failed = TRUE;
355 }
356 }
357 if (failed)
358 errln("MessageFormat failed test #6");
359 #endif
360 delete form;
361 }
362 }
363
364 void TestMessageFormat::sample()
365 {
366 MessageFormat *form = 0;
367 UnicodeString buffer1, buffer2;
368 UErrorCode success = U_ZERO_ERROR;
369 form = new MessageFormat("There are {0} files on {1}", success);
370 if (U_FAILURE(success)) {
371 errln("Err: Message format creation failed");
372 logln("Sample message format creation failed.");
373 return;
374 }
375 UnicodeString abc("abc");
376 UnicodeString def("def");
377 Formattable testArgs1[] = { abc, def };
378 FieldPosition fieldpos(0);
379 assertEquals("format",
380 "There are abc files on def",
381 form->format(testArgs1, 2, buffer2, fieldpos, success));
382 assertSuccess("format", success);
383 delete form;
384 }
385
386 void TestMessageFormat::testStaticFormat()
387 {
388 UErrorCode err = U_ZERO_ERROR;
389 Formattable arguments[] = {
390 (int32_t)7,
391 Formattable(UDate(8.71068e+011), Formattable::kIsDate),
392 "a disturbance in the Force"
393 };
394
395 UnicodeString result;
396 result = MessageFormat::format(
397 "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
398 arguments,
399 3,
400 result,
401 err);
402
403 if (U_FAILURE(err)) {
404 dataerrln("TestMessageFormat::testStaticFormat #1 - %s", u_errorName(err));
405 logln(UnicodeString("TestMessageFormat::testStaticFormat failed test #1 with error code ")+(int32_t)err);
406 return;
407 }
408
409 const UnicodeString expected(
410 "At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7.", "");
411 if (result != expected) {
412 errln("TestMessageFormat::testStaticFormat failed on test");
413 logln( UnicodeString(" Result: ") + result );
414 logln( UnicodeString(" Expected: ") + expected );
415 }
416 }
417
418 /* When the default locale is tr, make sure that the pattern can still be parsed. */
419 void TestMessageFormat::TestTurkishCasing()
420 {
421 UErrorCode err = U_ZERO_ERROR;
422 Locale saveDefaultLocale;
423 Locale::setDefault( Locale("tr"), err );
424
425 Formattable arguments[] = {
426 (int32_t)7,
427 Formattable(UDate(8.71068e+011), Formattable::kIsDate),
428 "a disturbance in the Force"
429 };
430
431 UnicodeString result;
432 result = MessageFormat::format(
433 "At {1,TIME} on {1,DATE,SHORT}, there was {2} on planet {0,NUMBER,INTEGER}.",
434 arguments,
435 3,
436 result,
437 err);
438
439 if (U_FAILURE(err)) {
440 dataerrln("TestTurkishCasing #1 with error code %s", u_errorName(err));
441 return;
442 }
443
444 const UnicodeString expected(
445 "At 12:20:00 on 08.08.1997, there was a disturbance in the Force on planet 7.", "");
446 if (result != expected) {
447 errln("TestTurkishCasing failed on test");
448 errln( UnicodeString(" Result: ") + result );
449 errln( UnicodeString(" Expected: ") + expected );
450 }
451 Locale::setDefault( saveDefaultLocale, err );
452 }
453
454 void TestMessageFormat::testSimpleFormat(/* char* par */)
455 {
456 logln("running TestMessageFormat::testSimpleFormat");
457
458 UErrorCode err = U_ZERO_ERROR;
459
460 Formattable testArgs1[] = {(int32_t)0, "MyDisk"};
461 Formattable testArgs2[] = {(int32_t)1, "MyDisk"};
462 Formattable testArgs3[] = {(int32_t)12, "MyDisk"};
463
464 MessageFormat* form = new MessageFormat(
465 "The disk \"{1}\" contains {0} file(s).", err);
466
467 UnicodeString string;
468 FieldPosition ignore(FieldPosition::DONT_CARE);
469 form->format(testArgs1, 2, string, ignore, err);
470 if (U_FAILURE(err) || string != "The disk \"MyDisk\" contains 0 file(s).") {
471 dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #1 - ") + u_errorName(err));
472 }
473
474 ignore.setField(FieldPosition::DONT_CARE);
475 string.remove();
476 form->format(testArgs2, 2, string, ignore, err);
477 if (U_FAILURE(err) || string != "The disk \"MyDisk\" contains 1 file(s).") {
478 logln(string);
479 dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #2")+string + " - " + u_errorName(err));
480 }
481
482 ignore.setField(FieldPosition::DONT_CARE);
483 string.remove();
484 form->format(testArgs3, 2, string, ignore, err);
485 if (U_FAILURE(err) || string != "The disk \"MyDisk\" contains 12 file(s).") {
486 dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #3")+string + " - " + u_errorName(err));
487 }
488
489 delete form;
490 }
491
492 void TestMessageFormat::testMsgFormatChoice(/* char* par */)
493 {
494 logln("running TestMessageFormat::testMsgFormatChoice");
495
496 UErrorCode err = U_ZERO_ERROR;
497
498 MessageFormat* form = new MessageFormat("The disk \"{1}\" contains {0}.", err);
499 double filelimits[] = {0,1,2};
500 UnicodeString filepart[] = {"no files","one file","{0,number} files"};
501 ChoiceFormat* fileform = new ChoiceFormat(filelimits, filepart, 3);
502 form->setFormat(1,*fileform); // NOT zero, see below
503 //is the format adopted?
504
505 FieldPosition ignore(FieldPosition::DONT_CARE);
506 UnicodeString string;
507 Formattable testArgs1[] = {(int32_t)0, "MyDisk"};
508 form->format(testArgs1, 2, string, ignore, err);
509 if (string != "The disk \"MyDisk\" contains no files.") {
510 errln("TestMessageFormat::testMsgFormatChoice failed on test #1");
511 }
512
513 ignore.setField(FieldPosition::DONT_CARE);
514 string.remove();
515 Formattable testArgs2[] = {(int32_t)1, "MyDisk"};
516 form->format(testArgs2, 2, string, ignore, err);
517 if (string != "The disk \"MyDisk\" contains one file.") {
518 errln("TestMessageFormat::testMsgFormatChoice failed on test #2");
519 }
520
521 ignore.setField(FieldPosition::DONT_CARE);
522 string.remove();
523 Formattable testArgs3[] = {(int32_t)1273, "MyDisk"};
524 form->format(testArgs3, 2, string, ignore, err);
525 if (string != "The disk \"MyDisk\" contains 1,273 files.") {
526 dataerrln("TestMessageFormat::testMsgFormatChoice failed on test #3 - %s", u_errorName(err));
527 }
528
529 delete form;
530 delete fileform;
531 }
532
533
534 void TestMessageFormat::testMsgFormatPlural(/* char* par */)
535 {
536 logln("running TestMessageFormat::testMsgFormatPlural");
537
538 UErrorCode err = U_ZERO_ERROR;
539 UnicodeString t1("{0, plural, one{C''est # fichier} other{Ce sont # fichiers}} dans la liste.");
540 UnicodeString t2("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste.");
541 UnicodeString t3("There {0, plural, one{is # zavod}few{are {0, number,###.0} zavoda} other{are # zavodov}} in the directory.");
542 UnicodeString t4("There {argument, plural, one{is # zavod}few{are {argument, number,###.0} zavoda} other{are #zavodov}} in the directory.");
543 UnicodeString t5("{0, plural, one {{0, number,C''est #,##0.0# fichier}} other {Ce sont # fichiers}} dans la liste.");
544 MessageFormat* mfNum = new MessageFormat(t1, Locale("fr"), err);
545 if (U_FAILURE(err)) {
546 dataerrln("TestMessageFormat::testMsgFormatPlural #1 - argumentIndex - %s", u_errorName(err));
547 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err);
548 return;
549 }
550 Formattable testArgs1((int32_t)0);
551 FieldPosition ignore(FieldPosition::DONT_CARE);
552 UnicodeString numResult1;
553 mfNum->format(&testArgs1, 1, numResult1, ignore, err);
554
555 MessageFormat* mfAlpha = new MessageFormat(t2, Locale("fr"), err);
556 UnicodeString argName[] = {UnicodeString("argument")};
557 UnicodeString argNameResult;
558 mfAlpha->format(argName, &testArgs1, 1, argNameResult, err);
559 if (U_FAILURE(err)) {
560 dataerrln("TestMessageFormat::testMsgFormatPlural #1 - argumentName - %s", u_errorName(err));
561 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err);
562 delete mfNum;
563 return;
564 }
565 if ( numResult1 != argNameResult){
566 errln("TestMessageFormat::testMsgFormatPlural #1");
567 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
568 }
569 if ( numResult1 != UnicodeString("C\'est 0 fichier dans la liste.")) {
570 errln("TestMessageFormat::testMsgFormatPlural #1");
571 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
572 }
573 err = U_ZERO_ERROR;
574
575 delete mfNum;
576 delete mfAlpha;
577
578 MessageFormat* mfNum2 = new MessageFormat(t3, Locale("ru"), err);
579 numResult1.remove();
580 Formattable testArgs2((int32_t)4);
581 mfNum2->format(&testArgs2, 1, numResult1, ignore, err);
582 MessageFormat* mfAlpha2 = new MessageFormat(t4, Locale("ru"), err);
583 argNameResult.remove();
584 mfAlpha2->format(argName, &testArgs2, 1, argNameResult, err);
585
586 if (U_FAILURE(err)) {
587 errln("TestMessageFormat::testMsgFormatPlural #2 - argumentName");
588 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #2 with error code ")+(int32_t)err);
589 delete mfNum2;
590 return;
591 }
592 if ( numResult1 != argNameResult){
593 errln("TestMessageFormat::testMsgFormatPlural #2");
594 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
595 }
596 if ( numResult1 != UnicodeString("There are 4,0 zavoda in the directory.")) {
597 errln("TestMessageFormat::testMsgFormatPlural #2");
598 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
599 }
600
601 delete mfNum2;
602 delete mfAlpha2;
603
604 // nested formats
605 err = U_ZERO_ERROR;
606 MessageFormat* msgFmt = new MessageFormat(t5, Locale("fr"), err);
607 if (U_FAILURE(err)) {
608 errln("TestMessageFormat::test nested PluralFormat with argumentName");
609 logln(UnicodeString("TestMessageFormat::test nested PluralFormat with error code ")+(int32_t)err);
610 delete msgFmt;
611 return;
612 }
613 Formattable testArgs3((int32_t)0);
614 argNameResult.remove();
615 msgFmt->format(&testArgs3, 1, argNameResult, ignore, err);
616 if (U_FAILURE(err)) {
617 errln("TestMessageFormat::test nested PluralFormat with argumentName");
618 }
619 if ( argNameResult!= UnicodeString("C'est 0,0 fichier dans la liste.")) {
620 errln(UnicodeString("TestMessageFormat::test nested named PluralFormat: ") + argNameResult);
621 logln(UnicodeString("The unexpected nested named PluralFormat."));
622 }
623 delete msgFmt;
624 }
625
626 void TestMessageFormat::testApostropheInPluralAndSelect() {
627 UErrorCode errorCode = U_ZERO_ERROR;
628 MessageFormat msgFmt(UNICODE_STRING_SIMPLE(
629 "abc_{0,plural,other{#'#'#'{'#''}}_def_{1,select,other{sel'}'ect''}}_xyz"),
630 Locale::getEnglish(),
631 errorCode);
632 if (U_FAILURE(errorCode)) {
633 errln("MessageFormat constructor failed - %s\n", u_errorName(errorCode));
634 return;
635 }
636 UnicodeString expected = UNICODE_STRING_SIMPLE("abc_3#3{3'_def_sel}ect'_xyz");
637 Formattable args[] = { (int32_t)3, UNICODE_STRING_SIMPLE("x") };
638 internalFormat(
639 &msgFmt, args, 2, expected,
640 "MessageFormat with apostrophes in plural/select arguments failed:\n");
641 }
642
643 void TestMessageFormat::internalFormat(MessageFormat* msgFmt ,
644 Formattable* args , int32_t numOfArgs ,
645 UnicodeString expected, const char* errMsg)
646 {
647 UnicodeString result;
648 FieldPosition ignore(FieldPosition::DONT_CARE);
649 UErrorCode status = U_ZERO_ERROR;
650
651 //Format with passed arguments
652 msgFmt->format( args , numOfArgs , result, ignore, status);
653 if (U_FAILURE(status)) {
654 dataerrln( "%serror while formatting with ErrorCode as %s" ,errMsg, u_errorName(status) );
655 }
656 //Compare expected with obtained result
657 if ( result!= expected ) {
658 UnicodeString err = UnicodeString(errMsg);
659 err+= UnicodeString(":Unexpected Result \n Expected: " + expected + "\n Obtained: " + result + "\n");
660 dataerrln(err);
661 }
662 }
663
664 MessageFormat* TestMessageFormat::internalCreate(
665 UnicodeString pattern ,Locale locale ,UErrorCode &status , char* errMsg)
666 {
667 //Create the MessageFormat with simple SelectFormat
668 MessageFormat* msgFmt = new MessageFormat(pattern, locale, status);
669 if (U_FAILURE(status)) {
670 dataerrln( "%serror while constructing with ErrorCode as %s" ,errMsg, u_errorName(status) );
671 logln(UnicodeString("TestMessageFormat::testMsgFormatSelect #1 with error code ")+(int32_t)status);
672 return NULL;
673 }
674 return msgFmt;
675 }
676
677 void TestMessageFormat::testMsgFormatSelect(/* char* par */)
678 {
679 logln("running TestMessageFormat::testMsgFormatSelect");
680
681 UErrorCode err = U_ZERO_ERROR;
682 //French Pattern
683 UnicodeString t1("{0} est {1, select, female {all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
684
685 err = U_ZERO_ERROR;
686 //Create the MessageFormat with simple French pattern
687 MessageFormat* msgFmt1 = internalCreate(t1.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t1");
688 if (!U_FAILURE(err)) {
689 //Arguments
690 Formattable testArgs10[] = {"Kirti","female"};
691 Formattable testArgs11[] = {"Victor","other"};
692 Formattable testArgs12[] = {"Ash","unknown"};
693 Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
694 UnicodeString exp[] = {
695 "Kirti est all\\u00E9e \\u00E0 Paris." ,
696 "Victor est all\\u00E9 \\u00E0 Paris.",
697 "Ash est all\\u00E9 \\u00E0 Paris."};
698 //Format
699 for( int i=0; i< 3; i++){
700 internalFormat( msgFmt1 , testArgs[i], 2, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t1");
701 }
702 }
703 delete msgFmt1;
704
705 //Quoted French Pattern
706 UnicodeString t2("{0} est {1, select, female {all\\u00E9e c''est} other {all\\u00E9 c''est}} \\u00E0 Paris.");
707 err = U_ZERO_ERROR;
708 //Create the MessageFormat with Quoted French pattern
709 MessageFormat* msgFmt2 = internalCreate(t2.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t2");
710 if (!U_FAILURE(err)) {
711 //Arguments
712 Formattable testArgs10[] = {"Kirti","female"};
713 Formattable testArgs11[] = {"Victor","other"};
714 Formattable testArgs12[] = {"Ash","male"};
715 Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
716 UnicodeString exp[] = {
717 "Kirti est all\\u00E9e c'est \\u00E0 Paris." ,
718 "Victor est all\\u00E9 c'est \\u00E0 Paris.",
719 "Ash est all\\u00E9 c'est \\u00E0 Paris."};
720 //Format
721 for( int i=0; i< 3; i++){
722 internalFormat( msgFmt2 , testArgs[i], 2, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t2");
723 }
724 }
725 delete msgFmt2;
726
727 //English Pattern
728 UnicodeString t3("{0, select , male {MALE FR company} female {FEMALE FR company} other {FR otherValue}} published new books.");
729 err = U_ZERO_ERROR;
730 //Create the MessageFormat with English pattern
731 MessageFormat* msgFmt3 = internalCreate(t3, Locale("en"),err,(char*)"From TestMessageFormat::TestSelectFormat create t3");
732 if (!U_FAILURE(err)) {
733 //Arguments
734 Formattable testArgs10[] = {"female"};
735 Formattable testArgs11[] = {"other"};
736 Formattable testArgs12[] = {"male"};
737 Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
738 UnicodeString exp[] = {
739 "FEMALE FR company published new books." ,
740 "FR otherValue published new books.",
741 "MALE FR company published new books."};
742 //Format
743 for( int i=0; i< 3; i++){
744 internalFormat( msgFmt3 , testArgs[i], 1, exp[i] ,(char*)"From TestMessageFormat::testSelectFormat format t3");
745 }
746 }
747 delete msgFmt3;
748
749 //Nested patterns with plural, number ,choice ,select format etc.
750 //Select Format with embedded number format
751 UnicodeString t4("{0} est {1, select, female {{2,number,integer} all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
752 //Create the MessageFormat with Select Format with embedded number format (nested pattern)
753 MessageFormat* msgFmt4 = internalCreate(t4.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t4");
754 if (!U_FAILURE(err)) {
755 //Arguments
756 Formattable testArgs10[] = {"Kirti","female",(int32_t)6};
757 Formattable testArgs11[] = {"Kirti","female",100.100};
758 Formattable testArgs12[] = {"Kirti","other",(int32_t)6};
759 Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
760 UnicodeString exp[] = {
761 "Kirti est 6 all\\u00E9e \\u00E0 Paris." ,
762 "Kirti est 100 all\\u00E9e \\u00E0 Paris.",
763 "Kirti est all\\u00E9 \\u00E0 Paris."};
764 //Format
765 for( int i=0; i< 3; i++){
766 internalFormat( msgFmt4 , testArgs[i], 3, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t4");
767 }
768 }
769 delete msgFmt4;
770
771 err = U_ZERO_ERROR;
772 //Plural format with embedded select format
773 UnicodeString t5("{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.");
774 err = U_ZERO_ERROR;
775 //Create the MessageFormat with Plural format with embedded select format(nested pattern)
776 MessageFormat* msgFmt5 = internalCreate(t5.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t5");
777 if (!U_FAILURE(err)) {
778 //Arguments
779 Formattable testArgs10[] = {"Kirti",(int32_t)6,"female"};
780 Formattable testArgs11[] = {"Kirti",(int32_t)1,"female"};
781 Formattable testArgs12[] = {"Ash",(int32_t)1,"other"};
782 Formattable testArgs13[] = {"Ash",(int32_t)5,"other"};
783 Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12,testArgs13};
784 UnicodeString exp[] = {
785 "Kirti sont all\\u00E9es \\u00E0 Paris." ,
786 "Kirti est all\\u00E9e \\u00E0 Paris.",
787 "Ash est all\\u00E9 \\u00E0 Paris.",
788 "Ash sont all\\u00E9s \\u00E0 Paris."};
789 //Format
790 for( int i=0; i< 4; i++){
791 internalFormat( msgFmt5 , testArgs[i], 3, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t5");
792 }
793 }
794 delete msgFmt5;
795
796 err = U_ZERO_ERROR;
797 //Select, plural, and number formats heavily nested
798 UnicodeString t6("{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.");
799 //Create the MessageFormat with Select, plural, and number formats heavily nested
800 MessageFormat* msgFmt6 = internalCreate(t6, Locale("de"),err,(char*)"From TestMessageFormat::TestSelectFormat create t6");
801 if (!U_FAILURE(err)) {
802 //Arguments
803 Formattable testArgs10[] = {"Kirti","other",(int32_t)1,"other"};
804 Formattable testArgs11[] = {"Kirti","other",(int32_t)6,"other"};
805 Formattable testArgs12[] = {"Kirti","other",(int32_t)1,"female"};
806 Formattable testArgs13[] = {"Kirti","other",(int32_t)3,"female"};
807 Formattable testArgs14[] = {"Kirti","female",(int32_t)1,"female"};
808 Formattable testArgs15[] = {"Kirti","female",(int32_t)5,"female"};
809 Formattable testArgs16[] = {"Kirti","female",(int32_t)1,"other"};
810 Formattable testArgs17[] = {"Kirti","female",(int32_t)5,"other"};
811 Formattable testArgs18[] = {"Kirti","mixed",(int32_t)1,"mixed"};
812 Formattable testArgs19[] = {"Kirti","mixed",(int32_t)1,"other"};
813 Formattable testArgs20[] = {"Kirti","female",(int32_t)1,"mixed"};
814 Formattable testArgs21[] = {"Kirti","mixed",(int32_t)5,"mixed"};
815 Formattable testArgs22[] = {"Kirti","mixed",(int32_t)5,"other"};
816 Formattable testArgs23[] = {"Kirti","female",(int32_t)5,"mixed"};
817 Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12,testArgs13,
818 testArgs14,testArgs15,testArgs16,testArgs17,
819 testArgs18,testArgs19,testArgs20,testArgs21,
820 testArgs22,testArgs23 };
821 UnicodeString exp[] = {
822 "Kirti und sein Freund gingen nach Paris." ,
823 "Kirti und seine 6 Freunde gingen nach Paris." ,
824 "Kirti und seine Freundin gingen nach Paris.",
825 "Kirti und seine 3 Freundinnen gingen nach Paris.",
826 "Kirti und ihre Freundin gingen nach Paris.",
827 "Kirti und ihre 5 Freundinnen gingen nach Paris.",
828 "Kirti und ihr Freund gingen nach Paris.",
829 "Kirti und ihre 5 Freunde gingen nach Paris.",
830 "Kirti und sein Freund gingen nach Paris.",
831 "Kirti und sein Freund gingen nach Paris.",
832 "Kirti und ihr Freund gingen nach Paris.",
833 "Kirti und seine 5 Freunde gingen nach Paris." ,
834 "Kirti und seine 5 Freunde gingen nach Paris." ,
835 "Kirti und ihre 5 Freunde gingen nach Paris."
836 };
837 //Format
838 for( int i=0; i< 14; i++){
839 internalFormat( msgFmt6 , testArgs[i], 4, exp[i] ,(char*)"From TestMessageFormat::testSelectFormat format t6");
840 }
841 }
842 delete msgFmt6;
843 }
844
845 //---------------------------------
846 // API Tests
847 //---------------------------------
848
849 void TestMessageFormat::testCopyConstructor()
850 {
851 UErrorCode success = U_ZERO_ERROR;
852 MessageFormat *x = new MessageFormat("There are {0} files on {1}", success);
853 MessageFormat *z = new MessageFormat("There are {0} files on {1} created", success);
854 MessageFormat *y = 0;
855 y = new MessageFormat(*x);
856 if ( (*x == *y) &&
857 (*x != *z) &&
858 (*y != *z) )
859 logln("First test (operator ==): Passed!");
860 else {
861 errln("TestMessageFormat::testCopyConstructor failed #1");
862 logln("First test (operator ==): Failed!");
863 }
864 if ( ((*x == *y) && (*y == *x)) &&
865 ((*x != *z) && (*z != *x)) &&
866 ((*y != *z) && (*z != *y)) )
867 logln("Second test (equals): Passed!");
868 else {
869 errln("TestMessageFormat::testCopyConstructor failed #2");
870 logln("Second test (equals): Failed!");
871 }
872
873 delete x;
874 delete y;
875 delete z;
876 }
877
878
879 void TestMessageFormat::testAssignment()
880 {
881 UErrorCode success = U_ZERO_ERROR;
882 MessageFormat *x = new MessageFormat("There are {0} files on {1}", success);
883 MessageFormat *z = new MessageFormat("There are {0} files on {1} created", success);
884 MessageFormat *y = new MessageFormat("There are {0} files on {1} created", success);
885 *y = *x;
886 if ( (*x == *y) &&
887 (*x != *z) &&
888 (*y != *z) )
889 logln("First test (operator ==): Passed!");
890 else {
891 errln( "TestMessageFormat::testAssignment failed #1");
892 logln("First test (operator ==): Failed!");
893 }
894 if ( ((*x == *y) && (*y == *x)) &&
895 ((*x != *z) && (*z != *x)) &&
896 ((*y != *z) && (*z != *y)) )
897 logln("Second test (equals): Passed!");
898 else {
899 errln("TestMessageFormat::testAssignment failed #2");
900 logln("Second test (equals): Failed!");
901 }
902
903 delete x;
904 delete y;
905 delete z;
906 }
907
908 void TestMessageFormat::testClone()
909 {
910 UErrorCode success = U_ZERO_ERROR;
911 MessageFormat *x = new MessageFormat("There are {0} files on {1}", success);
912 MessageFormat *z = new MessageFormat("There are {0} files on {1} created", success);
913 MessageFormat *y = 0;
914 y = (MessageFormat*)x->clone();
915 if ( (*x == *y) &&
916 (*x != *z) &&
917 (*y != *z) )
918 logln("First test (operator ==): Passed!");
919 else {
920 errln("TestMessageFormat::testClone failed #1");
921 logln("First test (operator ==): Failed!");
922 }
923 if ( ((*x == *y) && (*y == *x)) &&
924 ((*x != *z) && (*z != *x)) &&
925 ((*y != *z) && (*z != *y)) )
926 logln("Second test (equals): Passed!");
927 else {
928 errln("TestMessageFormat::testClone failed #2");
929 logln("Second test (equals): Failed!");
930 }
931
932 delete x;
933 delete y;
934 delete z;
935 }
936
937 void TestMessageFormat::testEquals()
938 {
939 UErrorCode success = U_ZERO_ERROR;
940 MessageFormat x("There are {0} files on {1}", success);
941 MessageFormat y("There are {0} files on {1}", success);
942 if (!(x == y)) {
943 errln( "TestMessageFormat::testEquals failed #1");
944 logln("First test (operator ==): Failed!");
945 }
946
947 }
948
949 void TestMessageFormat::testNotEquals()
950 {
951 UErrorCode success = U_ZERO_ERROR;
952 MessageFormat x("There are {0} files on {1}", success);
953 MessageFormat y(x);
954 y.setLocale(Locale("fr"));
955 if (!(x != y)) {
956 errln( "TestMessageFormat::testEquals failed #1");
957 logln("First test (operator !=): Failed!");
958 }
959 y = x;
960 y.applyPattern("There are {0} files on {1} the disk", success);
961 if (!(x != y)) {
962 errln( "TestMessageFormat::testEquals failed #1");
963 logln("Second test (operator !=): Failed!");
964 }
965 }
966
967
968 void TestMessageFormat::testSetLocale()
969 {
970 UErrorCode err = U_ZERO_ERROR;
971 GregorianCalendar cal(err);
972 Formattable arguments[] = {
973 456.83,
974 Formattable(UDate(8.71068e+011), Formattable::kIsDate),
975 "deposit"
976 };
977
978 UnicodeString result;
979
980 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
981 UnicodeString formatStr = "At <time> on {1,date}, you made a {2} of {0,number,currency}.";
982 // {sfb} to get $, would need Locale::US, not Locale::ENGLISH
983 // Just use unlocalized currency symbol.
984 //UnicodeString compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of $456.83.";
985 UnicodeString compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of ";
986 compareStrEng += (UChar) 0x00a4;
987 compareStrEng += "456.83.";
988 // {sfb} to get DM, would need Locale::GERMANY, not Locale::GERMAN
989 // Just use unlocalized currency symbol.
990 //UnicodeString compareStrGer = "At <time> on 08.08.1997, you made a deposit of 456,83 DM.";
991 UnicodeString compareStrGer = "At <time> on 08.08.1997, you made a deposit of ";
992 compareStrGer += "456,83";
993 compareStrGer += (UChar) 0x00a0;
994 compareStrGer += (UChar) 0x00a4;
995 compareStrGer += ".";
996
997 MessageFormat msg( formatStr, err);
998 result = "";
999 FieldPosition pos(0);
1000 result = msg.format(
1001 arguments,
1002 3,
1003 result,
1004 pos,
1005 err);
1006
1007 logln(result);
1008 if (result != compareStrEng) {
1009 dataerrln("*** MSG format err. - %s", u_errorName(err));
1010 }
1011
1012 msg.setLocale(Locale::getEnglish());
1013 UBool getLocale_ok = TRUE;
1014 if (msg.getLocale() != Locale::getEnglish()) {
1015 errln("*** MSG getLocal err.");
1016 getLocale_ok = FALSE;
1017 }
1018
1019 msg.setLocale(Locale::getGerman());
1020
1021 if (msg.getLocale() != Locale::getGerman()) {
1022 errln("*** MSG getLocal err.");
1023 getLocale_ok = FALSE;
1024 }
1025
1026 msg.applyPattern( formatStr, err);
1027
1028 pos.setField(0);
1029 result = "";
1030 result = msg.format(
1031 arguments,
1032 3,
1033 result,
1034 pos,
1035 err);
1036
1037 logln(result);
1038 if (result == compareStrGer) {
1039 logln("MSG setLocale tested.");
1040 }else{
1041 dataerrln( "*** MSG setLocale err. - %s", u_errorName(err));
1042 }
1043
1044 if (getLocale_ok) {
1045 logln("MSG getLocale tested.");
1046 }
1047 }
1048
1049 void TestMessageFormat::testFormat()
1050 {
1051 UErrorCode err = U_ZERO_ERROR;
1052 GregorianCalendar cal(err);
1053
1054 const Formattable ftarray[] =
1055 {
1056 Formattable( UDate(8.71068e+011), Formattable::kIsDate )
1057 };
1058 const int32_t ft_cnt = sizeof(ftarray) / sizeof(Formattable);
1059 Formattable ft_arr( ftarray, ft_cnt );
1060
1061 Formattable* fmt = new Formattable(UDate(8.71068e+011), Formattable::kIsDate);
1062
1063 UnicodeString result;
1064
1065 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
1066 UnicodeString formatStr = "On {0,date}, it began.";
1067 UnicodeString compareStr = "On Aug 8, 1997, it began.";
1068
1069 err = U_ZERO_ERROR;
1070 MessageFormat msg( formatStr, err);
1071 FieldPosition fp(0);
1072
1073 result = "";
1074 fp = 0;
1075 result = msg.format(
1076 *fmt,
1077 result,
1078 //FieldPosition(0),
1079 fp,
1080 err);
1081
1082 if (err != U_ILLEGAL_ARGUMENT_ERROR) {
1083 dataerrln("*** MSG format without expected error code. - %s", u_errorName(err));
1084 }
1085 err = U_ZERO_ERROR;
1086
1087 result = "";
1088 fp = 0;
1089 result = msg.format(
1090 ft_arr,
1091 result,
1092 //FieldPosition(0),
1093 fp,
1094 err);
1095
1096 logln("MSG format( Formattable&, ... ) expected:" + compareStr);
1097 logln("MSG format( Formattable&, ... ) result:" + result);
1098 if (result != compareStr) {
1099 dataerrln("*** MSG format( Formattable&, .... ) err. - %s", u_errorName(err));
1100 }else{
1101 logln("MSG format( Formattable&, ... ) tested.");
1102 }
1103
1104 delete fmt;
1105
1106 }
1107
1108 void TestMessageFormat::testParse()
1109 {
1110 UErrorCode err = U_ZERO_ERROR;
1111 int32_t count;
1112 UnicodeString msgFormatString = "{0} =sep= {1}";
1113 MessageFormat msg( msgFormatString, err);
1114 UnicodeString source = "abc =sep= def";
1115 UnicodeString tmp1, tmp2;
1116
1117 Formattable* fmt_arr = msg.parse( source, count, err );
1118 if (U_FAILURE(err) || (!fmt_arr)) {
1119 errln("*** MSG parse (ustring, count, err) error.");
1120 }else{
1121 logln("MSG parse -- count: %d", count);
1122 if (count != 2) {
1123 errln("*** MSG parse (ustring, count, err) count err.");
1124 }else{
1125 if ((fmt_arr[0].getType() == Formattable::kString)
1126 && (fmt_arr[1].getType() == Formattable::kString)
1127 && (fmt_arr[0].getString(tmp1) == "abc")
1128 && (fmt_arr[1].getString(tmp2) == "def")) {
1129 logln("MSG parse (ustring, count, err) tested.");
1130 }else{
1131 errln("*** MSG parse (ustring, count, err) result err.");
1132 }
1133 }
1134 }
1135 delete[] fmt_arr;
1136
1137 ParsePosition pp(0);
1138
1139 fmt_arr = msg.parse( source, pp, count );
1140 if ((pp == 0) || (!fmt_arr)) {
1141 errln("*** MSG parse (ustring, parsepos., count) error.");
1142 }else{
1143 logln("MSG parse -- count: %d", count);
1144 if (count != 2) {
1145 errln("*** MSG parse (ustring, parsepos., count) count err.");
1146 }else{
1147 if ((fmt_arr[0].getType() == Formattable::kString)
1148 && (fmt_arr[1].getType() == Formattable::kString)
1149 && (fmt_arr[0].getString(tmp1) == "abc")
1150 && (fmt_arr[1].getString(tmp2) == "def")) {
1151 logln("MSG parse (ustring, parsepos., count) tested.");
1152 }else{
1153 errln("*** MSG parse (ustring, parsepos., count) result err.");
1154 }
1155 }
1156 }
1157 delete[] fmt_arr;
1158
1159 pp = 0;
1160 Formattable fmta;
1161
1162 msg.parseObject( source, fmta, pp );
1163 if (pp == 0) {
1164 errln("*** MSG parse (ustring, Formattable, parsepos ) error.");
1165 }else{
1166 logln("MSG parse -- count: %d", count);
1167 fmta.getArray(count);
1168 if (count != 2) {
1169 errln("*** MSG parse (ustring, Formattable, parsepos ) count err.");
1170 }else{
1171 if ((fmta[0].getType() == Formattable::kString)
1172 && (fmta[1].getType() == Formattable::kString)
1173 && (fmta[0].getString(tmp1) == "abc")
1174 && (fmta[1].getString(tmp2) == "def")) {
1175 logln("MSG parse (ustring, Formattable, parsepos ) tested.");
1176 }else{
1177 errln("*** MSG parse (ustring, Formattable, parsepos ) result err.");
1178 }
1179 }
1180 }
1181 }
1182
1183
1184 void TestMessageFormat::testAdopt()
1185 {
1186 UErrorCode err = U_ZERO_ERROR;
1187
1188 UnicodeString formatStr("{0,date},{1},{2,number}", "");
1189 UnicodeString formatStrChange("{0,number},{1,number},{2,date}", "");
1190 err = U_ZERO_ERROR;
1191 MessageFormat msg( formatStr, err);
1192 MessageFormat msgCmp( formatStr, err);
1193 if (U_FAILURE(err)) {
1194 dataerrln("Unable to instantiate MessageFormat - %s", u_errorName(err));
1195 return;
1196 }
1197 int32_t count, countCmp;
1198 const Format** formats = msg.getFormats(count);
1199 const Format** formatsCmp = msgCmp.getFormats(countCmp);
1200 const Format** formatsChg = 0;
1201 const Format** formatsAct = 0;
1202 int32_t countAct;
1203 const Format* a;
1204 const Format* b;
1205 UnicodeString patCmp;
1206 UnicodeString patAct;
1207 Format** formatsToAdopt;
1208
1209 if (!formats || !formatsCmp || (count <= 0) || (count != countCmp)) {
1210 dataerrln("Error getting Formats");
1211 return;
1212 }
1213
1214 int32_t i;
1215
1216 for (i = 0; i < count; i++) {
1217 a = formats[i];
1218 b = formatsCmp[i];
1219 if ((a != NULL) && (b != NULL)) {
1220 if (*a != *b) {
1221 errln("a != b");
1222 return;
1223 }
1224 }else if ((a != NULL) || (b != NULL)) {
1225 errln("(a != NULL) || (b != NULL)");
1226 return;
1227 }
1228 }
1229
1230 msg.applyPattern( formatStrChange, err ); //set msg formats to something different
1231 int32_t countChg;
1232 formatsChg = msg.getFormats(countChg); // tested function
1233 if (!formatsChg || (countChg != count)) {
1234 errln("Error getting Formats");
1235 return;
1236 }
1237
1238 UBool diff;
1239 diff = TRUE;
1240 for (i = 0; i < count; i++) {
1241 a = formatsChg[i];
1242 b = formatsCmp[i];
1243 if ((a != NULL) && (b != NULL)) {
1244 if (*a == *b) {
1245 logln("formatsChg == formatsCmp at index %d", i);
1246 diff = FALSE;
1247 }
1248 }
1249 }
1250 if (!diff) {
1251 errln("*** MSG getFormats diff err.");
1252 return;
1253 }
1254
1255 logln("MSG getFormats tested.");
1256
1257 msg.setFormats( formatsCmp, countCmp ); //tested function
1258
1259 formatsAct = msg.getFormats(countAct);
1260 if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
1261 errln("Error getting Formats");
1262 return;
1263 }
1264
1265 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
1266 // ICU 4.8 does not support toPattern() when there are custom formats (from setFormat() etc.).
1267 // assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
1268 msg.toPattern(patCmp.remove());
1269 if (!patCmp.isBogus()) {
1270 errln("msg.setFormat().toPattern() succeeds.");
1271 }
1272
1273 for (i = 0; i < countAct; i++) {
1274 a = formatsAct[i];
1275 b = formatsCmp[i];
1276 if ((a != NULL) && (b != NULL)) {
1277 if (*a != *b) {
1278 logln("formatsAct != formatsCmp at index %d", i);
1279 errln("a != b");
1280 return;
1281 }
1282 }else if ((a != NULL) || (b != NULL)) {
1283 errln("(a != NULL) || (b != NULL)");
1284 return;
1285 }
1286 }
1287 logln("MSG setFormats tested.");
1288
1289 //----
1290
1291 msg.applyPattern( formatStrChange, err ); //set msg formats to something different
1292
1293 formatsToAdopt = new Format* [countCmp];
1294 if (!formatsToAdopt) {
1295 errln("memory allocation error");
1296 return;
1297 }
1298
1299 for (i = 0; i < countCmp; i++) {
1300 if (formatsCmp[i] == NULL) {
1301 formatsToAdopt[i] = NULL;
1302 }else{
1303 formatsToAdopt[i] = formatsCmp[i]->clone();
1304 if (!formatsToAdopt[i]) {
1305 errln("Can't clone format at index %d", i);
1306 return;
1307 }
1308 }
1309 }
1310 msg.adoptFormats( formatsToAdopt, countCmp ); // function to test
1311 delete[] formatsToAdopt;
1312
1313 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
1314 // ICU 4.8 does not support toPattern() when there are custom formats (from setFormat() etc.).
1315 // assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
1316
1317 formatsAct = msg.getFormats(countAct);
1318 if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
1319 errln("Error getting Formats");
1320 return;
1321 }
1322
1323 for (i = 0; i < countAct; i++) {
1324 a = formatsAct[i];
1325 b = formatsCmp[i];
1326 if ((a != NULL) && (b != NULL)) {
1327 if (*a != *b) {
1328 errln("a != b");
1329 return;
1330 }
1331 }else if ((a != NULL) || (b != NULL)) {
1332 errln("(a != NULL) || (b != NULL)");
1333 return;
1334 }
1335 }
1336 logln("MSG adoptFormats tested.");
1337
1338 //---- adoptFormat
1339
1340 msg.applyPattern( formatStrChange, err ); //set msg formats to something different
1341
1342 formatsToAdopt = new Format* [countCmp];
1343 if (!formatsToAdopt) {
1344 errln("memory allocation error");
1345 return;
1346 }
1347
1348 for (i = 0; i < countCmp; i++) {
1349 if (formatsCmp[i] == NULL) {
1350 formatsToAdopt[i] = NULL;
1351 }else{
1352 formatsToAdopt[i] = formatsCmp[i]->clone();
1353 if (!formatsToAdopt[i]) {
1354 errln("Can't clone format at index %d", i);
1355 return;
1356 }
1357 }
1358 }
1359
1360 for ( i = 0; i < countCmp; i++ ) {
1361 msg.adoptFormat( i, formatsToAdopt[i] ); // function to test
1362 }
1363 delete[] formatsToAdopt; // array itself not needed in this case;
1364
1365 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
1366 // ICU 4.8 does not support toPattern() when there are custom formats (from setFormat() etc.).
1367 // assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
1368
1369 formatsAct = msg.getFormats(countAct);
1370 if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
1371 errln("Error getting Formats");
1372 return;
1373 }
1374
1375 for (i = 0; i < countAct; i++) {
1376 a = formatsAct[i];
1377 b = formatsCmp[i];
1378 if ((a != NULL) && (b != NULL)) {
1379 if (*a != *b) {
1380 errln("a != b");
1381 return;
1382 }
1383 }else if ((a != NULL) || (b != NULL)) {
1384 errln("(a != NULL) || (b != NULL)");
1385 return;
1386 }
1387 }
1388 logln("MSG adoptFormat tested.");
1389 }
1390
1391 // This test is a regression test for a fixed bug in the copy constructor.
1392 // It is kept as a global function rather than as a method since the test depends on memory values.
1393 // (At least before the bug was fixed, whether it showed up or not depended on memory contents,
1394 // which is probably why it didn't show up in the regular test for the copy constructor.)
1395 // For this reason, the test isn't changed even though it contains function calls whose results are
1396 // not tested and had no problems. Actually, the test failed by *crashing*.
1397 static void _testCopyConstructor2()
1398 {
1399 UErrorCode status = U_ZERO_ERROR;
1400 UnicodeString formatStr("Hello World on {0,date,full}", "");
1401 UnicodeString resultStr(" ", "");
1402 UnicodeString result;
1403 FieldPosition fp(0);
1404 UDate d = Calendar::getNow();
1405 const Formattable fargs( d, Formattable::kIsDate );
1406
1407 MessageFormat* fmt1 = new MessageFormat( formatStr, status );
1408 MessageFormat* fmt2 = NULL;
1409 MessageFormat* fmt3 = NULL;
1410 MessageFormat* fmt4 = NULL;
1411
1412 if (fmt1 == NULL) {
1413 it_err("testCopyConstructor2: (fmt1 != NULL)");
1414 goto cleanup;
1415 }
1416
1417 fmt2 = new MessageFormat( *fmt1 );
1418 result = fmt1->format( &fargs, 1, resultStr, fp, status );
1419
1420 if (fmt2 == NULL) {
1421 it_err("testCopyConstructor2: (fmt2 != NULL)");
1422 goto cleanup;
1423 }
1424
1425 fmt3 = (MessageFormat*) fmt1->clone();
1426 fmt4 = (MessageFormat*) fmt2->clone();
1427
1428 if (fmt3 == NULL) {
1429 it_err("testCopyConstructor2: (fmt3 != NULL)");
1430 goto cleanup;
1431 }
1432 if (fmt4 == NULL) {
1433 it_err("testCopyConstructor2: (fmt4 != NULL)");
1434 goto cleanup;
1435 }
1436
1437 result = fmt1->format( &fargs, 1, resultStr, fp, status );
1438 result = fmt2->format( &fargs, 1, resultStr, fp, status );
1439 result = fmt3->format( &fargs, 1, resultStr, fp, status );
1440 result = fmt4->format( &fargs, 1, resultStr, fp, status );
1441
1442 cleanup:
1443 delete fmt1;
1444 delete fmt2;
1445 delete fmt3;
1446 delete fmt4;
1447 }
1448
1449 void TestMessageFormat::testCopyConstructor2() {
1450 _testCopyConstructor2();
1451 }
1452
1453 /**
1454 * Verify that MessageFormat accomodates more than 10 arguments and
1455 * more than 10 subformats.
1456 */
1457 void TestMessageFormat::TestUnlimitedArgsAndSubformats() {
1458 UErrorCode ec = U_ZERO_ERROR;
1459 const UnicodeString pattern =
1460 "On {0,date} (aka {0,date,short}, aka {0,date,long}) "
1461 "at {0,time} (aka {0,time,short}, aka {0,time,long}) "
1462 "there were {1,number} werjes "
1463 "(a {3,number,percent} increase over {2,number}) "
1464 "despite the {4}''s efforts "
1465 "and to delight of {5}, {6}, {7}, {8}, {9}, and {10} {11}.";
1466 MessageFormat msg(pattern, ec);
1467 if (U_FAILURE(ec)) {
1468 dataerrln("FAIL: constructor failed - %s", u_errorName(ec));
1469 return;
1470 }
1471
1472 const Formattable ARGS[] = {
1473 Formattable(UDate(1e13), Formattable::kIsDate),
1474 Formattable((int32_t)1303),
1475 Formattable((int32_t)1202),
1476 Formattable(1303.0/1202 - 1),
1477 Formattable("Glimmung"),
1478 Formattable("the printers"),
1479 Formattable("Nick"),
1480 Formattable("his father"),
1481 Formattable("his mother"),
1482 Formattable("the spiddles"),
1483 Formattable("of course"),
1484 Formattable("Horace"),
1485 };
1486 const int32_t ARGS_LENGTH = sizeof(ARGS) / sizeof(ARGS[0]);
1487 Formattable ARGS_OBJ(ARGS, ARGS_LENGTH);
1488
1489 UnicodeString expected =
1490 "On Nov 20, 2286 (aka 11/20/86, aka November 20, 2286) "
1491 "at 9:46:40 AM (aka 9:46 AM, aka 9:46:40 AM PST) "
1492 "there were 1,303 werjes "
1493 "(a 8% increase over 1,202) "
1494 "despite the Glimmung's efforts "
1495 "and to delight of the printers, Nick, his father, "
1496 "his mother, the spiddles, and of course Horace.";
1497 UnicodeString result;
1498 msg.format(ARGS_OBJ, result, ec);
1499 if (result == expected) {
1500 logln(result);
1501 } else {
1502 errln((UnicodeString)"FAIL: Got " + result +
1503 ", expected " + expected);
1504 }
1505 }
1506
1507 // test RBNF extensions to message format
1508 void TestMessageFormat::TestRBNF(void) {
1509 // WARNING: this depends on the RBNF formats for en_US
1510 Locale locale("en", "US", "");
1511
1512 UErrorCode ec = U_ZERO_ERROR;
1513
1514 UnicodeString values[] = {
1515 // decimal values do not format completely for ordinal or duration, and
1516 // do not always parse, so do not include them
1517 "0", "1", "12", "100", "123", "1001", "123,456", "-17",
1518 };
1519 int32_t values_count = sizeof(values)/sizeof(values[0]);
1520
1521 UnicodeString formats[] = {
1522 "There are {0,spellout} files to search.",
1523 "There are {0,spellout,%simplified} files to search.",
1524 "The bogus spellout {0,spellout,%BOGUS} files behaves like the default.",
1525 "This is the {0,ordinal} file to search.", // TODO fix bug, ordinal does not parse
1526 "Searching this file will take {0,duration} to complete.",
1527 "Searching this file will take {0,duration,%with-words} to complete.",
1528 };
1529 int32_t formats_count = sizeof(formats)/sizeof(formats[0]);
1530
1531 Formattable args[1];
1532
1533 NumberFormat* numFmt = NumberFormat::createInstance(locale, ec);
1534 if (U_FAILURE(ec)) {
1535 dataerrln("Error calling NumberFormat::createInstance()");
1536 return;
1537 }
1538
1539 for (int i = 0; i < formats_count; ++i) {
1540 MessageFormat* fmt = new MessageFormat(formats[i], locale, ec);
1541 logln((UnicodeString)"Testing format pattern: '" + formats[i] + "'");
1542
1543 for (int j = 0; j < values_count; ++j) {
1544 ec = U_ZERO_ERROR;
1545 numFmt->parse(values[j], args[0], ec);
1546 if (U_FAILURE(ec)) {
1547 errln((UnicodeString)"Failed to parse test argument " + values[j]);
1548 } else {
1549 FieldPosition fp(0);
1550 UnicodeString result;
1551 fmt->format(args, 1, result, fp, ec);
1552 logln((UnicodeString)"value: " + toString(args[0]) + " --> " + result + UnicodeString(" ec: ") + u_errorName(ec));
1553
1554 if (i != 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3)
1555 int32_t count = 0;
1556 Formattable* parseResult = fmt->parse(result, count, ec);
1557 if (count != 1) {
1558 errln((UnicodeString)"parse returned " + count + " args");
1559 } else if (parseResult[0] != args[0]) {
1560 errln((UnicodeString)"parsed argument " + toString(parseResult[0]) + " != " + toString(args[0]));
1561 }
1562 delete []parseResult;
1563 }
1564 }
1565 }
1566 delete fmt;
1567 }
1568 delete numFmt;
1569 }
1570
1571 UnicodeString TestMessageFormat::GetPatternAndSkipSyntax(const MessagePattern& pattern) {
1572 UnicodeString us(pattern.getPatternString());
1573 int count = pattern.countParts();
1574 for (int i = count; i > 0;) {
1575 const MessagePattern::Part& part = pattern.getPart(--i);
1576 if (part.getType() == UMSGPAT_PART_TYPE_SKIP_SYNTAX) {
1577 us.remove(part.getIndex(), part.getLimit() - part.getIndex());
1578 }
1579 }
1580 return us;
1581 }
1582
1583 void TestMessageFormat::TestApostropheMode() {
1584 UErrorCode status = U_ZERO_ERROR;
1585 MessagePattern *ado_mp = new MessagePattern(UMSGPAT_APOS_DOUBLE_OPTIONAL, status);
1586 MessagePattern *adr_mp = new MessagePattern(UMSGPAT_APOS_DOUBLE_REQUIRED, status);
1587 if (ado_mp->getApostropheMode() != UMSGPAT_APOS_DOUBLE_OPTIONAL) {
1588 errln("wrong value from ado_mp->getApostropheMode().");
1589 }
1590 if (adr_mp->getApostropheMode() != UMSGPAT_APOS_DOUBLE_REQUIRED) {
1591 errln("wrong value from adr_mp->getApostropheMode().");
1592 }
1593
1594
1595 UnicodeString tuples[] = {
1596 // Desired output
1597 // DOUBLE_OPTIONAL pattern
1598 // DOUBLE_REQUIRED pattern (empty=same as DOUBLE_OPTIONAL)
1599 "I see {many}", "I see '{many}'", "",
1600 "I said {'Wow!'}", "I said '{''Wow!''}'", "",
1601 "I dont know", "I dont know", "I don't know",
1602 "I don't know", "I don't know", "I don''t know",
1603 "I don't know", "I don''t know", "I don''t know"
1604 };
1605 int32_t tuples_count = LENGTHOF(tuples);
1606
1607 for (int i = 0; i < tuples_count; i += 3) {
1608 UnicodeString& desired = tuples[i];
1609 UnicodeString& ado_pattern = tuples[i + 1];
1610 UErrorCode status = U_ZERO_ERROR;
1611 assertEquals("DOUBLE_OPTIONAL failure",
1612 desired,
1613 GetPatternAndSkipSyntax(ado_mp->parse(ado_pattern, NULL, status)));
1614 UnicodeString& adr_pattern = tuples[i + 2].isEmpty() ? ado_pattern : tuples[i + 2];
1615 assertEquals("DOUBLE_REQUIRED failure", desired,
1616 GetPatternAndSkipSyntax(adr_mp->parse(adr_pattern, NULL, status)));
1617 }
1618 delete adr_mp;
1619 delete ado_mp;
1620 }
1621
1622
1623 // Compare behavior of DOUBLE_OPTIONAL (new default) and DOUBLE_REQUIRED JDK-compatibility mode.
1624 void TestMessageFormat::TestCompatibleApostrophe() {
1625 // Message with choice argument which does not contain another argument.
1626 // The JDK performs only one apostrophe-quoting pass on this pattern.
1627 UnicodeString pattern = "ab{0,choice,0#1'2''3'''4''''.}yz";
1628
1629 UErrorCode ec = U_ZERO_ERROR;
1630 MessageFormat compMsg("", Locale::getUS(), ec);
1631 compMsg.applyPattern(pattern, UMSGPAT_APOS_DOUBLE_REQUIRED, NULL, ec);
1632 if (compMsg.getApostropheMode() != UMSGPAT_APOS_DOUBLE_REQUIRED) {
1633 errln("wrong value from compMsg.getApostropheMode().");
1634 }
1635
1636 MessageFormat icuMsg("", Locale::getUS(), ec);
1637 icuMsg.applyPattern(pattern, UMSGPAT_APOS_DOUBLE_OPTIONAL, NULL, ec);
1638 if (icuMsg.getApostropheMode() != UMSGPAT_APOS_DOUBLE_OPTIONAL) {
1639 errln("wrong value from icuMsg.getApostropheMode().");
1640 }
1641
1642 Formattable zero0[] = { (int32_t)0 };
1643 FieldPosition fieldpos(0);
1644 UnicodeString buffer1, buffer2;
1645 assertEquals("incompatible ICU MessageFormat compatibility-apostrophe behavior",
1646 "ab12'3'4''.yz",
1647 compMsg.format(zero0, 1, buffer1, fieldpos, ec));
1648 assertEquals("unexpected ICU MessageFormat double-apostrophe-optional behavior",
1649 "ab1'2'3''4''.yz",
1650 icuMsg.format(zero0, 1, buffer2, fieldpos, ec));
1651
1652 // Message with choice argument which contains a nested simple argument.
1653 // The DOUBLE_REQUIRED version performs two apostrophe-quoting passes.
1654 buffer1.remove();
1655 buffer2.remove();
1656 pattern = "ab{0,choice,0#1'2''3'''4''''.{0,number,'#x'}}yz";
1657 compMsg.applyPattern(pattern, ec);
1658 icuMsg.applyPattern(pattern, ec);
1659 if (U_FAILURE(ec)) {
1660 dataerrln("Unable to applyPattern - %s", u_errorName(ec));
1661 } else {
1662 assertEquals("incompatible ICU MessageFormat compatibility-apostrophe behavior",
1663 "ab1234'.0xyz",
1664 compMsg.format(zero0, 1, buffer1, fieldpos, ec));
1665 assertEquals("unexpected ICU MessageFormat double-apostrophe-optional behavior",
1666 "ab1'2'3''4''.#x0yz",
1667 icuMsg.format(zero0, 1, buffer2, fieldpos, ec));
1668 }
1669
1670 // This part is copied over from Java tests but cannot be properly tested here
1671 // because we do not have a live reference implementation with JDK behavior.
1672 // The JDK ChoiceFormat itself always performs one apostrophe-quoting pass.
1673 /*
1674 ChoiceFormat choice = new ChoiceFormat("0#1'2''3'''4''''.");
1675 assertEquals("unexpected JDK ChoiceFormat apostrophe behavior",
1676 "12'3'4''.",
1677 choice.format(0));
1678 choice.applyPattern("0#1'2''3'''4''''.{0,number,'#x'}");
1679 assertEquals("unexpected JDK ChoiceFormat apostrophe behavior",
1680 "12'3'4''.{0,number,#x}",
1681 choice.format(0));
1682 */
1683 }
1684
1685 void TestMessageFormat::testAutoQuoteApostrophe(void) {
1686 const char* patterns[] = { // pattern, expected pattern
1687 "'", "''",
1688 "''", "''",
1689 "'{", "'{'",
1690 "' {", "'' {",
1691 "'a", "''a",
1692 "'{'a", "'{'a",
1693 "'{a'", "'{a'",
1694 "'{}", "'{}'",
1695 "{'", "{'",
1696 "{'a", "{'a",
1697 "{'a{}'a}'a", "{'a{}'a}''a",
1698 "'}'", "'}'",
1699 "'} '{'}'", "'} '{'}''",
1700 "'} {{{''", "'} {{{'''",
1701 };
1702 int32_t pattern_count = sizeof(patterns)/sizeof(patterns[0]);
1703
1704 for (int i = 0; i < pattern_count; i += 2) {
1705 UErrorCode status = U_ZERO_ERROR;
1706 UnicodeString result = MessageFormat::autoQuoteApostrophe(patterns[i], status);
1707 UnicodeString target(patterns[i+1]);
1708 if (target != result) {
1709 const int BUF2_LEN = 64;
1710 char buf[256];
1711 char buf2[BUF2_LEN];
1712 int32_t len = result.extract(0, result.length(), buf2, BUF2_LEN);
1713 if (len >= BUF2_LEN) {
1714 buf2[BUF2_LEN-1] = 0;
1715 }
1716 sprintf(buf, "[%2d] test \"%s\": target (\"%s\") != result (\"%s\")\n", i/2, patterns[i], patterns[i+1], buf2);
1717 errln(buf);
1718 }
1719 }
1720 }
1721
1722 void TestMessageFormat::testCoverage(void) {
1723 UErrorCode status = U_ZERO_ERROR;
1724 UnicodeString testformat("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste.");
1725 MessageFormat *msgfmt = new MessageFormat(testformat, Locale("fr"), status);
1726 if (msgfmt == NULL || U_FAILURE(status)) {
1727 dataerrln("FAIL: Unable to create MessageFormat.: %s", u_errorName(status));
1728 return;
1729 }
1730 if (!msgfmt->usesNamedArguments()) {
1731 errln("FAIL: Unable to detect usage of named arguments.");
1732 }
1733 const double limit[] = {0.0, 1.0, 2.0};
1734 const UnicodeString formats[] = {"0.0<=Arg<1.0",
1735 "1.0<=Arg<2.0",
1736 "2.0<-Arg"};
1737 ChoiceFormat cf(limit, formats, 3);
1738
1739 msgfmt->setFormat("set", cf, status);
1740
1741 StringEnumeration *en = msgfmt->getFormatNames(status);
1742 if (en == NULL || U_FAILURE(status)) {
1743 errln("FAIL: Unable to get format names enumeration.");
1744 } else {
1745 int32_t count = 0;
1746 en->reset(status);
1747 count = en->count(status);
1748 if (U_FAILURE(status)) {
1749 errln("FAIL: Unable to get format name enumeration count.");
1750 } else {
1751 for (int32_t i = 0; i < count; i++) {
1752 en->snext(status);
1753 if (U_FAILURE(status)) {
1754 errln("FAIL: Error enumerating through names.");
1755 break;
1756 }
1757 }
1758 }
1759 }
1760
1761 // adoptFormat() takes ownership of the input Format object.
1762 // We need to clone the stack-allocated cf so that we do not attempt to delete cf.
1763 Format *cfClone = cf.clone();
1764 msgfmt->adoptFormat("adopt", cfClone, status);
1765
1766 delete en;
1767 delete msgfmt;
1768
1769 msgfmt = new MessageFormat("'", status);
1770 if (msgfmt == NULL || U_FAILURE(status)) {
1771 errln("FAIL: Unable to create MessageFormat.");
1772 return;
1773 }
1774 if (msgfmt->usesNamedArguments()) {
1775 errln("FAIL: Unable to detect usage of named arguments.");
1776 }
1777
1778 // Starting with ICU 4.8, we support setFormat(name, ...) and getFormatNames()
1779 // on a MessageFormat without named arguments.
1780 msgfmt->setFormat("formatName", cf, status);
1781 if (U_FAILURE(status)) {
1782 errln("FAIL: Should work to setFormat(name, ...) regardless of pattern.");
1783 }
1784 status = U_ZERO_ERROR;
1785 en = msgfmt->getFormatNames(status);
1786 if (U_FAILURE(status)) {
1787 errln("FAIL: Should work to get format names enumeration regardless of pattern.");
1788 }
1789
1790 delete en;
1791 delete msgfmt;
1792 }
1793
1794 void TestMessageFormat::TestTrimArgumentName() {
1795 // ICU 4.8 allows and ignores white space around argument names and numbers.
1796 IcuTestErrorCode errorCode(*this, "TestTrimArgumentName");
1797 MessageFormat m("a { 0 , number , '#,#'#.0 } z", Locale::getEnglish(), errorCode);
1798 if (errorCode.logDataIfFailureAndReset("Unable to instantiate MessageFormat")) {
1799 return;
1800 }
1801 Formattable args[1] = { (int32_t)2 };
1802 FieldPosition ignore(0);
1803 UnicodeString result;
1804 assertEquals("trim-numbered-arg format() failed", "a #,#2.0 z",
1805 m.format(args, 1, result, ignore, errorCode));
1806
1807 m.applyPattern("x { _oOo_ , number , integer } y", errorCode);
1808 UnicodeString argName = UNICODE_STRING_SIMPLE("_oOo_");
1809 args[0].setLong(3);
1810 result.remove();
1811 assertEquals("trim-named-arg format() failed", "x 3 y",
1812 m.format(&argName, args, 1, result, errorCode));
1813 }
1814
1815 #endif /* #if !UCONFIG_NO_FORMATTING */