]>
Commit | Line | Data |
---|---|---|
b75a7d8f | 1 | /******************************************************************** |
729e4ab9 | 2 | * COPYRIGHT: |
51004dcb | 3 | * Copyright (c) 1997-2012, 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" | |
21 | ||
22 | #include "unicode/format.h" | |
23 | #include "unicode/decimfmt.h" | |
51004dcb | 24 | #include "unicode/localpointer.h" |
b75a7d8f A |
25 | #include "unicode/locid.h" |
26 | #include "unicode/msgfmt.h" | |
27 | #include "unicode/numfmt.h" | |
28 | #include "unicode/choicfmt.h" | |
4388f060 | 29 | #include "unicode/messagepattern.h" |
729e4ab9 | 30 | #include "unicode/selfmt.h" |
b75a7d8f | 31 | #include "unicode/gregocal.h" |
73c04bcf | 32 | #include <stdio.h> |
b75a7d8f | 33 | |
4388f060 | 34 | #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) |
729e4ab9 | 35 | |
b75a7d8f A |
36 | void |
37 | TestMessageFormat::runIndexedTest(int32_t index, UBool exec, | |
38 | const char* &name, char* /*par*/) { | |
4388f060 A |
39 | TESTCASE_AUTO_BEGIN; |
40 | TESTCASE_AUTO(testBug1); | |
41 | TESTCASE_AUTO(testBug2); | |
42 | TESTCASE_AUTO(sample); | |
43 | TESTCASE_AUTO(PatternTest); | |
44 | TESTCASE_AUTO(testStaticFormat); | |
45 | TESTCASE_AUTO(testSimpleFormat); | |
46 | TESTCASE_AUTO(testMsgFormatChoice); | |
47 | TESTCASE_AUTO(testCopyConstructor); | |
48 | TESTCASE_AUTO(testAssignment); | |
49 | TESTCASE_AUTO(testClone); | |
50 | TESTCASE_AUTO(testEquals); | |
51 | TESTCASE_AUTO(testNotEquals); | |
52 | TESTCASE_AUTO(testSetLocale); | |
53 | TESTCASE_AUTO(testFormat); | |
54 | TESTCASE_AUTO(testParse); | |
55 | TESTCASE_AUTO(testAdopt); | |
56 | TESTCASE_AUTO(testCopyConstructor2); | |
57 | TESTCASE_AUTO(TestUnlimitedArgsAndSubformats); | |
58 | TESTCASE_AUTO(TestRBNF); | |
59 | TESTCASE_AUTO(TestTurkishCasing); | |
60 | TESTCASE_AUTO(testAutoQuoteApostrophe); | |
61 | TESTCASE_AUTO(testMsgFormatPlural); | |
62 | TESTCASE_AUTO(testMsgFormatSelect); | |
63 | TESTCASE_AUTO(testApostropheInPluralAndSelect); | |
64 | TESTCASE_AUTO(TestApostropheMode); | |
65 | TESTCASE_AUTO(TestCompatibleApostrophe); | |
66 | TESTCASE_AUTO(testCoverage); | |
51004dcb | 67 | TESTCASE_AUTO(testGetFormatNames); |
4388f060 | 68 | TESTCASE_AUTO(TestTrimArgumentName); |
51004dcb | 69 | TESTCASE_AUTO(TestSelectOrdinal); |
4388f060 | 70 | TESTCASE_AUTO_END; |
b75a7d8f A |
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); | |
374ca955 | 147 | logln(UnicodeString(" -> ") /* + << dec*/ + toString(result) + UnicodeString("[supposed output for result]")); |
b75a7d8f A |
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 necessary) | |
46f4442e | 178 | const UnicodeString pattern = "There {0,choice,0#are no files|1#is one file|1<are {0, number} files} on disk {1}. "; |
b75a7d8f A |
179 | logln("The input pattern : " + pattern); |
180 | MessageFormat *fmt = new MessageFormat(pattern, status); | |
181 | if (U_FAILURE(status)) { | |
4388f060 | 182 | dataerrln("MessageFormat pattern creation failed. - %s", u_errorName(status)); |
b75a7d8f A |
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 | |
4388f060 | 193 | #if defined(_DEBUG) && U_IOSTREAM_SOURCE >= 199711 |
b75a7d8f A |
194 | //---------------------------------------------------- |
195 | // console I/O | |
196 | //---------------------------------------------------- | |
197 | ||
4388f060 A |
198 | #include <iostream> |
199 | std::ostream& operator<<(std::ostream& stream, const Formattable& obj); | |
b75a7d8f A |
200 | |
201 | #include "unicode/datefmt.h" | |
202 | #include <stdlib.h> | |
b75a7d8f A |
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 | } | |
4388f060 | 244 | #endif /* defined(_DEBUG) && U_IOSTREAM_SOURCE >= 199711 */ |
b75a7d8f A |
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), Formattable::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 | ||
4388f060 A |
265 | // ICU 4.8 returns the original pattern (testCases), |
266 | // rather than toPattern() reconstituting a new, equivalent pattern string (testResultPatterns). | |
267 | /*UnicodeString testResultPatterns[] = { | |
b75a7d8f A |
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,#,##}" | |
4388f060 | 277 | };*/ |
b75a7d8f A |
278 | |
279 | UnicodeString testResultStrings[] = { | |
4388f060 A |
280 | "Quotes ', {, 'a' 1 {0}", |
281 | "Quotes ', {, 'a' 1 {0}", | |
282 | "{1,number,'#',##} #34,56", | |
51004dcb | 283 | "There are 3,456 files on Disk at 1/12/70, 5:46 AM.", |
b75a7d8f A |
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)) { | |
729e4ab9 | 300 | dataerrln("MessageFormat creation failed.#1 - %s", u_errorName(success)); |
b75a7d8f A |
301 | logln(((UnicodeString)"MessageFormat for ") + testCases[i] + " creation failed.\n"); |
302 | continue; | |
303 | } | |
4388f060 A |
304 | // ICU 4.8 returns the original pattern (testCases), |
305 | // rather than toPattern() reconstituting a new, equivalent pattern string (testResultPatterns). | |
306 | if (form->toPattern(buffer) != testCases[i]) { | |
307 | // Note: An alternative test would be to build MessagePattern objects for | |
308 | // both the input and output patterns and compare them, taking SKIP_SYNTAX etc. | |
309 | // into account. | |
310 | // (Too much trouble...) | |
b75a7d8f A |
311 | errln(UnicodeString("TestMessageFormat::PatternTest failed test #2, i = ") + i); |
312 | //form->toPattern(buffer); | |
313 | errln(((UnicodeString)" Orig: ") + testCases[i]); | |
4388f060 | 314 | errln(((UnicodeString)" Exp: ") + testCases[i]); |
b75a7d8f A |
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)) { | |
729e4ab9 | 324 | dataerrln("MessageFormat failed test #3 - %s", u_errorName(success)); |
b75a7d8f A |
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 | } | |
4388f060 | 334 | |
b75a7d8f A |
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(testArgs[j])); | |
356 | errln(((UnicodeString)"MSG values[") + j + "] : " + toString(values[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); | |
374ca955 A |
382 | assertEquals("format", |
383 | "There are abc files on def", | |
384 | form->format(testArgs1, 2, buffer2, fieldpos, success)); | |
385 | assertSuccess("format", success); | |
b75a7d8f A |
386 | delete form; |
387 | } | |
388 | ||
374ca955 | 389 | void TestMessageFormat::testStaticFormat() |
b75a7d8f | 390 | { |
b75a7d8f | 391 | UErrorCode err = U_ZERO_ERROR; |
b75a7d8f A |
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)) { | |
729e4ab9 | 407 | dataerrln("TestMessageFormat::testStaticFormat #1 - %s", u_errorName(err)); |
b75a7d8f A |
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 | ||
73c04bcf A |
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,INTEGER}.", | |
437 | arguments, | |
438 | 3, | |
439 | result, | |
440 | err); | |
441 | ||
442 | if (U_FAILURE(err)) { | |
729e4ab9 | 443 | dataerrln("TestTurkishCasing #1 with error code %s", u_errorName(err)); |
73c04bcf A |
444 | return; |
445 | } | |
446 | ||
447 | const UnicodeString expected( | |
51004dcb | 448 | "At 12:20:00 on 8.08.1997, there was a disturbance in the Force on planet 7.", ""); |
73c04bcf A |
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 | } | |
b75a7d8f A |
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).") { | |
729e4ab9 | 474 | dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #1 - ") + u_errorName(err)); |
b75a7d8f A |
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); | |
729e4ab9 | 482 | dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #2")+string + " - " + u_errorName(err)); |
b75a7d8f A |
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).") { | |
729e4ab9 | 489 | dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #3")+string + " - " + u_errorName(err)); |
b75a7d8f A |
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}.", err); | |
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.") { | |
729e4ab9 | 529 | dataerrln("TestMessageFormat::testMsgFormatChoice failed on test #3 - %s", u_errorName(err)); |
b75a7d8f A |
530 | } |
531 | ||
532 | delete form; | |
533 | delete fileform; | |
534 | } | |
535 | ||
536 | ||
46f4442e A |
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."); | |
4388f060 | 546 | UnicodeString t5("{0, plural, one {{0, number,C''est #,##0.0# fichier}} other {Ce sont # fichiers}} dans la liste."); |
46f4442e A |
547 | MessageFormat* mfNum = new MessageFormat(t1, Locale("fr"), err); |
548 | if (U_FAILURE(err)) { | |
729e4ab9 | 549 | dataerrln("TestMessageFormat::testMsgFormatPlural #1 - argumentIndex - %s", u_errorName(err)); |
46f4442e A |
550 | logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error 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)) { | |
4388f060 | 563 | dataerrln("TestMessageFormat::testMsgFormatPlural #1 - argumentName - %s", u_errorName(err)); |
46f4442e A |
564 | logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error 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 not 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 not the same.")); | |
575 | } | |
576 | err = U_ZERO_ERROR; | |
577 | ||
578 | delete mfNum; | |
579 | delete mfAlpha; | |
580 | ||
581 | MessageFormat* mfNum2 = new MessageFormat(t3, Locale("ru"), 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("ru"), 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 error 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 not 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 not 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 error 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.")) { | |
4388f060 | 623 | errln(UnicodeString("TestMessageFormat::test nested named PluralFormat: ") + argNameResult); |
46f4442e A |
624 | logln(UnicodeString("The unexpected nested named PluralFormat.")); |
625 | } | |
626 | delete msgFmt; | |
627 | } | |
628 | ||
4388f060 A |
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 | ||
729e4ab9 A |
646 | void TestMessageFormat::internalFormat(MessageFormat* msgFmt , |
647 | Formattable* args , int32_t numOfArgs , | |
4388f060 | 648 | UnicodeString expected, const char* errMsg) |
729e4ab9 A |
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( "%serror 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( "%serror while constructing with ErrorCode as %s" ,errMsg, u_errorName(status) ); | |
674 | logln(UnicodeString("TestMessageFormat::testMsgFormatSelect #1 with error 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,(char*)"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,(char*)"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 company} 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 TestMessageFormat::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 TestMessageFormat::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 | //Create the MessageFormat with Select Format with embedded number format (nested pattern) | |
756 | MessageFormat* msgFmt4 = internalCreate(t4.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t4"); | |
757 | if (!U_FAILURE(err)) { | |
758 | //Arguments | |
759 | Formattable testArgs10[] = {"Kirti","female",(int32_t)6}; | |
760 | Formattable testArgs11[] = {"Kirti","female",100.100}; | |
761 | Formattable testArgs12[] = {"Kirti","other",(int32_t)6}; | |
762 | Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12}; | |
763 | UnicodeString exp[] = { | |
764 | "Kirti est 6 all\\u00E9e \\u00E0 Paris." , | |
765 | "Kirti est 100 all\\u00E9e \\u00E0 Paris.", | |
766 | "Kirti est all\\u00E9 \\u00E0 Paris."}; | |
767 | //Format | |
768 | for( int i=0; i< 3; i++){ | |
769 | internalFormat( msgFmt4 , testArgs[i], 3, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t4"); | |
770 | } | |
771 | } | |
772 | delete msgFmt4; | |
773 | ||
774 | err = U_ZERO_ERROR; | |
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\\u00E9s}}}} \\u00E0 Paris."); | |
777 | err = U_ZERO_ERROR; | |
778 | //Create the MessageFormat with Plural format with embedded select format(nested pattern) | |
779 | MessageFormat* msgFmt5 = internalCreate(t5.unescape(), Locale("fr"),err,(char*)"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, 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."); | |
802 | //Create the MessageFormat with Select, plural, and number formats heavily nested | |
803 | MessageFormat* msgFmt6 = internalCreate(t6, Locale("de"),err,(char*)"From TestMessageFormat::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 TestMessageFormat::testSelectFormat format t6"); | |
843 | } | |
844 | } | |
845 | delete msgFmt6; | |
846 | } | |
46f4442e | 847 | |
b75a7d8f A |
848 | //--------------------------------- |
849 | // API Tests | |
850 | //--------------------------------- | |
851 | ||
852 | void TestMessageFormat::testCopyConstructor() | |
853 | { | |
b75a7d8f A |
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", success); | |
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 | { | |
b75a7d8f A |
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", success); | |
887 | MessageFormat *y = new MessageFormat("There are {0} files on {1} created", success); | |
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 | { | |
b75a7d8f A |
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", success); | |
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 | { | |
b75a7d8f A |
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"); | |
374ca955 | 966 | logln("Second test (operator !=): Failed!"); |
b75a7d8f A |
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,number,currency}."; | |
984 | UnicodeString formatStr = "At <time> on {1,date}, you made a {2} of {0,number,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 deposit 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 of "; | |
46f4442e A |
995 | compareStrGer += "456,83"; |
996 | compareStrGer += (UChar) 0x00a0; | |
b75a7d8f | 997 | compareStrGer += (UChar) 0x00a4; |
46f4442e | 998 | compareStrGer += "."; |
b75a7d8f A |
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) { | |
729e4ab9 | 1012 | dataerrln("*** MSG format err. - %s", u_errorName(err)); |
b75a7d8f A |
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{ | |
729e4ab9 | 1044 | dataerrln( "*** MSG setLocale err. - %s", u_errorName(err)); |
b75a7d8f A |
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,number,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) { | |
729e4ab9 | 1086 | dataerrln("*** MSG format without expected error code. - %s", u_errorName(err)); |
b75a7d8f A |
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) { | |
729e4ab9 | 1102 | dataerrln("*** MSG format( Formattable&, .... ) err. - %s", u_errorName(err)); |
b75a7d8f A |
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 err."); | |
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); | |
4388f060 A |
1196 | if (U_FAILURE(err)) { |
1197 | dataerrln("Unable to instantiate MessageFormat - %s", u_errorName(err)); | |
1198 | return; | |
1199 | } | |
b75a7d8f A |
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)) { | |
729e4ab9 | 1213 | dataerrln("Error getting Formats"); |
b75a7d8f A |
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 different | |
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) { | |
374ca955 | 1248 | logln("formatsChg == formatsCmp at index %d", i); |
b75a7d8f A |
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 | ||
374ca955 | 1268 | assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove())); |
4388f060 A |
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 | } | |
b75a7d8f A |
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 | ||
b75a7d8f A |
1292 | //---- |
1293 | ||
1294 | msg.applyPattern( formatStrChange, err ); //set msg formats to something different | |
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 | ||
374ca955 | 1316 | assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove())); |
4388f060 A |
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())); | |
b75a7d8f A |
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 different | |
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 | ||
374ca955 | 1368 | assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove())); |
4388f060 A |
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())); | |
b75a7d8f A |
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 depends on memory values. | |
1396 | // (At least before the bug was fixed, whether it showed up or not depended on memory contents, | |
1397 | // which is probably why it didn't show up in the regular test for the copy constructor.) | |
1398 | // For this reason, the test isn't changed even though it contains function calls 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 ); | |
4388f060 A |
1411 | MessageFormat* fmt2 = NULL; |
1412 | MessageFormat* fmt3 = NULL; | |
1413 | MessageFormat* fmt4 = NULL; | |
b75a7d8f | 1414 | |
4388f060 A |
1415 | if (fmt1 == NULL) { |
1416 | it_err("testCopyConstructor2: (fmt1 != NULL)"); | |
1417 | goto cleanup; | |
1418 | } | |
b75a7d8f | 1419 | |
4388f060 | 1420 | fmt2 = new MessageFormat( *fmt1 ); |
b75a7d8f A |
1421 | result = fmt1->format( &fargs, 1, resultStr, fp, status ); |
1422 | ||
4388f060 A |
1423 | if (fmt2 == NULL) { |
1424 | it_err("testCopyConstructor2: (fmt2 != NULL)"); | |
1425 | goto cleanup; | |
1426 | } | |
b75a7d8f A |
1427 | |
1428 | fmt3 = (MessageFormat*) fmt1->clone(); | |
1429 | fmt4 = (MessageFormat*) fmt2->clone(); | |
1430 | ||
4388f060 A |
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 | } | |
b75a7d8f A |
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 ); | |
4388f060 A |
1444 | |
1445 | cleanup: | |
b75a7d8f A |
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)) { | |
729e4ab9 | 1471 | dataerrln("FAIL: constructor failed - %s", u_errorName(ec)); |
b75a7d8f A |
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 | ||
374ca955 A |
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.", // TODO fix bug, ordinal does not parse | |
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); | |
73c04bcf A |
1537 | if (U_FAILURE(ec)) { |
1538 | dataerrln("Error calling NumberFormat::createInstance()"); | |
1539 | return; | |
1540 | } | |
1541 | ||
374ca955 A |
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] + "'"); | |
73c04bcf | 1545 | |
374ca955 A |
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]) + " --> " + result + UnicodeString(" ec: ") + u_errorName(ec)); | |
1556 | ||
1557 | if (i != 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3) | |
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])); | |
1564 | } | |
1565 | delete []parseResult; | |
1566 | } | |
1567 | } | |
1568 | } | |
1569 | delete fmt; | |
1570 | } | |
1571 | delete numFmt; | |
1572 | } | |
1573 | ||
4388f060 A |
1574 | UnicodeString TestMessageFormat::GetPatternAndSkipSyntax(const MessagePattern& pattern) { |
1575 | UnicodeString us(pattern.getPatternString()); | |
1576 | int count = pattern.countParts(); | |
1577 | for (int i = count; i > 0;) { | |
1578 | const MessagePattern::Part& part = pattern.getPart(--i); | |
1579 | if (part.getType() == UMSGPAT_PART_TYPE_SKIP_SYNTAX) { | |
1580 | us.remove(part.getIndex(), part.getLimit() - part.getIndex()); | |
1581 | } | |
1582 | } | |
1583 | return us; | |
1584 | } | |
1585 | ||
1586 | void TestMessageFormat::TestApostropheMode() { | |
1587 | UErrorCode status = U_ZERO_ERROR; | |
1588 | MessagePattern *ado_mp = new MessagePattern(UMSGPAT_APOS_DOUBLE_OPTIONAL, status); | |
1589 | MessagePattern *adr_mp = new MessagePattern(UMSGPAT_APOS_DOUBLE_REQUIRED, status); | |
1590 | if (ado_mp->getApostropheMode() != UMSGPAT_APOS_DOUBLE_OPTIONAL) { | |
1591 | errln("wrong value from ado_mp->getApostropheMode()."); | |
1592 | } | |
1593 | if (adr_mp->getApostropheMode() != UMSGPAT_APOS_DOUBLE_REQUIRED) { | |
1594 | errln("wrong value from adr_mp->getApostropheMode()."); | |
1595 | } | |
1596 | ||
1597 | ||
1598 | UnicodeString tuples[] = { | |
1599 | // Desired output | |
1600 | // DOUBLE_OPTIONAL pattern | |
1601 | // DOUBLE_REQUIRED pattern (empty=same as DOUBLE_OPTIONAL) | |
1602 | "I see {many}", "I see '{many}'", "", | |
1603 | "I said {'Wow!'}", "I said '{''Wow!''}'", "", | |
1604 | "I dont know", "I dont know", "I don't know", | |
1605 | "I don't know", "I don't know", "I don''t know", | |
1606 | "I don't know", "I don''t know", "I don''t know" | |
1607 | }; | |
1608 | int32_t tuples_count = LENGTHOF(tuples); | |
1609 | ||
1610 | for (int i = 0; i < tuples_count; i += 3) { | |
1611 | UnicodeString& desired = tuples[i]; | |
1612 | UnicodeString& ado_pattern = tuples[i + 1]; | |
1613 | UErrorCode status = U_ZERO_ERROR; | |
1614 | assertEquals("DOUBLE_OPTIONAL failure", | |
1615 | desired, | |
1616 | GetPatternAndSkipSyntax(ado_mp->parse(ado_pattern, NULL, status))); | |
1617 | UnicodeString& adr_pattern = tuples[i + 2].isEmpty() ? ado_pattern : tuples[i + 2]; | |
1618 | assertEquals("DOUBLE_REQUIRED failure", desired, | |
1619 | GetPatternAndSkipSyntax(adr_mp->parse(adr_pattern, NULL, status))); | |
1620 | } | |
1621 | delete adr_mp; | |
1622 | delete ado_mp; | |
1623 | } | |
1624 | ||
1625 | ||
1626 | // Compare behavior of DOUBLE_OPTIONAL (new default) and DOUBLE_REQUIRED JDK-compatibility mode. | |
1627 | void TestMessageFormat::TestCompatibleApostrophe() { | |
1628 | // Message with choice argument which does not contain another argument. | |
1629 | // The JDK performs only one apostrophe-quoting pass on this pattern. | |
1630 | UnicodeString pattern = "ab{0,choice,0#1'2''3'''4''''.}yz"; | |
1631 | ||
1632 | UErrorCode ec = U_ZERO_ERROR; | |
1633 | MessageFormat compMsg("", Locale::getUS(), ec); | |
1634 | compMsg.applyPattern(pattern, UMSGPAT_APOS_DOUBLE_REQUIRED, NULL, ec); | |
1635 | if (compMsg.getApostropheMode() != UMSGPAT_APOS_DOUBLE_REQUIRED) { | |
1636 | errln("wrong value from compMsg.getApostropheMode()."); | |
1637 | } | |
1638 | ||
1639 | MessageFormat icuMsg("", Locale::getUS(), ec); | |
1640 | icuMsg.applyPattern(pattern, UMSGPAT_APOS_DOUBLE_OPTIONAL, NULL, ec); | |
1641 | if (icuMsg.getApostropheMode() != UMSGPAT_APOS_DOUBLE_OPTIONAL) { | |
1642 | errln("wrong value from icuMsg.getApostropheMode()."); | |
1643 | } | |
1644 | ||
1645 | Formattable zero0[] = { (int32_t)0 }; | |
1646 | FieldPosition fieldpos(0); | |
1647 | UnicodeString buffer1, buffer2; | |
1648 | assertEquals("incompatible ICU MessageFormat compatibility-apostrophe behavior", | |
1649 | "ab12'3'4''.yz", | |
1650 | compMsg.format(zero0, 1, buffer1, fieldpos, ec)); | |
1651 | assertEquals("unexpected ICU MessageFormat double-apostrophe-optional behavior", | |
1652 | "ab1'2'3''4''.yz", | |
1653 | icuMsg.format(zero0, 1, buffer2, fieldpos, ec)); | |
1654 | ||
1655 | // Message with choice argument which contains a nested simple argument. | |
1656 | // The DOUBLE_REQUIRED version performs two apostrophe-quoting passes. | |
1657 | buffer1.remove(); | |
1658 | buffer2.remove(); | |
1659 | pattern = "ab{0,choice,0#1'2''3'''4''''.{0,number,'#x'}}yz"; | |
1660 | compMsg.applyPattern(pattern, ec); | |
1661 | icuMsg.applyPattern(pattern, ec); | |
1662 | if (U_FAILURE(ec)) { | |
1663 | dataerrln("Unable to applyPattern - %s", u_errorName(ec)); | |
1664 | } else { | |
1665 | assertEquals("incompatible ICU MessageFormat compatibility-apostrophe behavior", | |
1666 | "ab1234'.0xyz", | |
1667 | compMsg.format(zero0, 1, buffer1, fieldpos, ec)); | |
1668 | assertEquals("unexpected ICU MessageFormat double-apostrophe-optional behavior", | |
1669 | "ab1'2'3''4''.#x0yz", | |
1670 | icuMsg.format(zero0, 1, buffer2, fieldpos, ec)); | |
1671 | } | |
1672 | ||
1673 | // This part is copied over from Java tests but cannot be properly tested here | |
1674 | // because we do not have a live reference implementation with JDK behavior. | |
1675 | // The JDK ChoiceFormat itself always performs one apostrophe-quoting pass. | |
1676 | /* | |
1677 | ChoiceFormat choice = new ChoiceFormat("0#1'2''3'''4''''."); | |
1678 | assertEquals("unexpected JDK ChoiceFormat apostrophe behavior", | |
1679 | "12'3'4''.", | |
1680 | choice.format(0)); | |
1681 | choice.applyPattern("0#1'2''3'''4''''.{0,number,'#x'}"); | |
1682 | assertEquals("unexpected JDK ChoiceFormat apostrophe behavior", | |
1683 | "12'3'4''.{0,number,#x}", | |
1684 | choice.format(0)); | |
1685 | */ | |
1686 | } | |
1687 | ||
73c04bcf A |
1688 | void TestMessageFormat::testAutoQuoteApostrophe(void) { |
1689 | const char* patterns[] = { // pattern, expected pattern | |
1690 | "'", "''", | |
1691 | "''", "''", | |
1692 | "'{", "'{'", | |
1693 | "' {", "'' {", | |
1694 | "'a", "''a", | |
1695 | "'{'a", "'{'a", | |
1696 | "'{a'", "'{a'", | |
1697 | "'{}", "'{}'", | |
1698 | "{'", "{'", | |
1699 | "{'a", "{'a", | |
1700 | "{'a{}'a}'a", "{'a{}'a}''a", | |
1701 | "'}'", "'}'", | |
1702 | "'} '{'}'", "'} '{'}''", | |
1703 | "'} {{{''", "'} {{{'''", | |
1704 | }; | |
1705 | int32_t pattern_count = sizeof(patterns)/sizeof(patterns[0]); | |
1706 | ||
1707 | for (int i = 0; i < pattern_count; i += 2) { | |
1708 | UErrorCode status = U_ZERO_ERROR; | |
1709 | UnicodeString result = MessageFormat::autoQuoteApostrophe(patterns[i], status); | |
1710 | UnicodeString target(patterns[i+1]); | |
1711 | if (target != result) { | |
1712 | const int BUF2_LEN = 64; | |
1713 | char buf[256]; | |
1714 | char buf2[BUF2_LEN]; | |
1715 | int32_t len = result.extract(0, result.length(), buf2, BUF2_LEN); | |
1716 | if (len >= BUF2_LEN) { | |
1717 | buf2[BUF2_LEN-1] = 0; | |
1718 | } | |
1719 | sprintf(buf, "[%2d] test \"%s\": target (\"%s\") != result (\"%s\")\n", i/2, patterns[i], patterns[i+1], buf2); | |
1720 | errln(buf); | |
1721 | } | |
1722 | } | |
1723 | } | |
1724 | ||
729e4ab9 A |
1725 | void TestMessageFormat::testCoverage(void) { |
1726 | UErrorCode status = U_ZERO_ERROR; | |
1727 | UnicodeString testformat("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste."); | |
1728 | MessageFormat *msgfmt = new MessageFormat(testformat, Locale("fr"), status); | |
1729 | if (msgfmt == NULL || U_FAILURE(status)) { | |
1730 | dataerrln("FAIL: Unable to create MessageFormat.: %s", u_errorName(status)); | |
1731 | return; | |
1732 | } | |
1733 | if (!msgfmt->usesNamedArguments()) { | |
1734 | errln("FAIL: Unable to detect usage of named arguments."); | |
1735 | } | |
1736 | const double limit[] = {0.0, 1.0, 2.0}; | |
1737 | const UnicodeString formats[] = {"0.0<=Arg<1.0", | |
1738 | "1.0<=Arg<2.0", | |
1739 | "2.0<-Arg"}; | |
1740 | ChoiceFormat cf(limit, formats, 3); | |
1741 | ||
1742 | msgfmt->setFormat("set", cf, status); | |
1743 | ||
1744 | StringEnumeration *en = msgfmt->getFormatNames(status); | |
1745 | if (en == NULL || U_FAILURE(status)) { | |
1746 | errln("FAIL: Unable to get format names enumeration."); | |
1747 | } else { | |
1748 | int32_t count = 0; | |
1749 | en->reset(status); | |
1750 | count = en->count(status); | |
1751 | if (U_FAILURE(status)) { | |
1752 | errln("FAIL: Unable to get format name enumeration count."); | |
1753 | } else { | |
1754 | for (int32_t i = 0; i < count; i++) { | |
1755 | en->snext(status); | |
1756 | if (U_FAILURE(status)) { | |
1757 | errln("FAIL: Error enumerating through names."); | |
1758 | break; | |
1759 | } | |
1760 | } | |
1761 | } | |
1762 | } | |
1763 | ||
4388f060 A |
1764 | // adoptFormat() takes ownership of the input Format object. |
1765 | // We need to clone the stack-allocated cf so that we do not attempt to delete cf. | |
1766 | Format *cfClone = cf.clone(); | |
1767 | msgfmt->adoptFormat("adopt", cfClone, status); | |
729e4ab9 A |
1768 | |
1769 | delete en; | |
1770 | delete msgfmt; | |
1771 | ||
1772 | msgfmt = new MessageFormat("'", status); | |
1773 | if (msgfmt == NULL || U_FAILURE(status)) { | |
1774 | errln("FAIL: Unable to create MessageFormat."); | |
1775 | return; | |
1776 | } | |
1777 | if (msgfmt->usesNamedArguments()) { | |
1778 | errln("FAIL: Unable to detect usage of named arguments."); | |
1779 | } | |
1780 | ||
4388f060 A |
1781 | // Starting with ICU 4.8, we support setFormat(name, ...) and getFormatNames() |
1782 | // on a MessageFormat without named arguments. | |
729e4ab9 | 1783 | msgfmt->setFormat("formatName", cf, status); |
4388f060 A |
1784 | if (U_FAILURE(status)) { |
1785 | errln("FAIL: Should work to setFormat(name, ...) regardless of pattern."); | |
729e4ab9 A |
1786 | } |
1787 | status = U_ZERO_ERROR; | |
1788 | en = msgfmt->getFormatNames(status); | |
4388f060 A |
1789 | if (U_FAILURE(status)) { |
1790 | errln("FAIL: Should work to get format names enumeration regardless of pattern."); | |
729e4ab9 A |
1791 | } |
1792 | ||
1793 | delete en; | |
1794 | delete msgfmt; | |
1795 | } | |
1796 | ||
51004dcb A |
1797 | void TestMessageFormat::testGetFormatNames() { |
1798 | IcuTestErrorCode errorCode(*this, "testGetFormatNames"); | |
1799 | MessageFormat msgfmt("Hello, {alice,number} {oops,date,full} {zip,spellout} World.", Locale::getRoot(), errorCode); | |
1800 | if(errorCode.logDataIfFailureAndReset("MessageFormat() failed")) { | |
1801 | return; | |
1802 | } | |
1803 | LocalPointer<StringEnumeration> names(msgfmt.getFormatNames(errorCode)); | |
1804 | if(errorCode.logIfFailureAndReset("msgfmt.getFormatNames() failed")) { | |
1805 | return; | |
1806 | } | |
1807 | const UnicodeString *name; | |
1808 | name = names->snext(errorCode); | |
1809 | if (name == NULL || errorCode.isFailure()) { | |
1810 | errln("msgfmt.getFormatNames()[0] failed: %s", errorCode.errorName()); | |
1811 | errorCode.reset(); | |
1812 | return; | |
1813 | } | |
1814 | if (!assertEquals("msgfmt.getFormatNames()[0]", UNICODE_STRING_SIMPLE("alice"), *name)) { | |
1815 | return; | |
1816 | } | |
1817 | name = names->snext(errorCode); | |
1818 | if (name == NULL || errorCode.isFailure()) { | |
1819 | errln("msgfmt.getFormatNames()[1] failed: %s", errorCode.errorName()); | |
1820 | errorCode.reset(); | |
1821 | return; | |
1822 | } | |
1823 | if (!assertEquals("msgfmt.getFormatNames()[1]", UNICODE_STRING_SIMPLE("oops"), *name)) { | |
1824 | return; | |
1825 | } | |
1826 | name = names->snext(errorCode); | |
1827 | if (name == NULL || errorCode.isFailure()) { | |
1828 | errln("msgfmt.getFormatNames()[2] failed: %s", errorCode.errorName()); | |
1829 | errorCode.reset(); | |
1830 | return; | |
1831 | } | |
1832 | if (!assertEquals("msgfmt.getFormatNames()[2]", UNICODE_STRING_SIMPLE("zip"), *name)) { | |
1833 | return; | |
1834 | } | |
1835 | name = names->snext(errorCode); | |
1836 | if (name != NULL) { | |
1837 | errln(UnicodeString("msgfmt.getFormatNames()[3] should be NULL but is: ") + *name); | |
1838 | return; | |
1839 | } | |
1840 | } | |
1841 | ||
4388f060 A |
1842 | void TestMessageFormat::TestTrimArgumentName() { |
1843 | // ICU 4.8 allows and ignores white space around argument names and numbers. | |
1844 | IcuTestErrorCode errorCode(*this, "TestTrimArgumentName"); | |
1845 | MessageFormat m("a { 0 , number , '#,#'#.0 } z", Locale::getEnglish(), errorCode); | |
1846 | if (errorCode.logDataIfFailureAndReset("Unable to instantiate MessageFormat")) { | |
1847 | return; | |
1848 | } | |
1849 | Formattable args[1] = { (int32_t)2 }; | |
1850 | FieldPosition ignore(0); | |
1851 | UnicodeString result; | |
1852 | assertEquals("trim-numbered-arg format() failed", "a #,#2.0 z", | |
1853 | m.format(args, 1, result, ignore, errorCode)); | |
1854 | ||
1855 | m.applyPattern("x { _oOo_ , number , integer } y", errorCode); | |
1856 | UnicodeString argName = UNICODE_STRING_SIMPLE("_oOo_"); | |
1857 | args[0].setLong(3); | |
1858 | result.remove(); | |
1859 | assertEquals("trim-named-arg format() failed", "x 3 y", | |
1860 | m.format(&argName, args, 1, result, errorCode)); | |
1861 | } | |
1862 | ||
51004dcb A |
1863 | void TestMessageFormat::TestSelectOrdinal() { |
1864 | IcuTestErrorCode errorCode(*this, "TestSelectOrdinal"); | |
1865 | // Test plural & ordinal together, | |
1866 | // to make sure that we get the correct cached PluralSelector for each. | |
1867 | MessageFormat m( | |
1868 | "{0,plural,one{1 file}other{# files}}, " | |
1869 | "{0,selectordinal,one{#st file}two{#nd file}few{#rd file}other{#th file}}", | |
1870 | Locale::getEnglish(), errorCode); | |
1871 | if (errorCode.logDataIfFailureAndReset("Unable to instantiate MessageFormat")) { | |
1872 | return; | |
1873 | } | |
1874 | Formattable args[1] = { (int32_t)21 }; | |
1875 | FieldPosition ignore(0); | |
1876 | UnicodeString result; | |
1877 | assertEquals("plural-and-ordinal format(21) failed", "21 files, 21st file", | |
1878 | m.format(args, 1, result, ignore, errorCode), TRUE); | |
1879 | ||
1880 | args[0].setLong(2); | |
1881 | assertEquals("plural-and-ordinal format(2) failed", "2 files, 2nd file", | |
1882 | m.format(args, 1, result.remove(), ignore, errorCode), TRUE); | |
1883 | ||
1884 | args[0].setLong(1); | |
1885 | assertEquals("plural-and-ordinal format(1) failed", "1 file, 1st file", | |
1886 | m.format(args, 1, result.remove(), ignore, errorCode), TRUE); | |
1887 | ||
1888 | args[0].setLong(3); | |
1889 | assertEquals("plural-and-ordinal format(3) failed", "3 files, 3rd file", | |
1890 | m.format(args, 1, result.remove(), ignore, errorCode), TRUE); | |
1891 | ||
1892 | errorCode.logDataIfFailureAndReset(""); | |
1893 | } | |
1894 | ||
b75a7d8f | 1895 | #endif /* #if !UCONFIG_NO_FORMATTING */ |