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