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