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