1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************
11 * Modification History:
13 * Madhu Katragadda Creation
14 ********************************************************************/
15 /* C API TEST FOR MESSAGE FORMAT */
17 #include "unicode/utypes.h"
19 #if !UCONFIG_NO_FORMATTING
24 #include "unicode/uloc.h"
25 #include "unicode/umsg.h"
26 #include "unicode/udat.h"
27 #include "unicode/umsg.h"
28 #include "unicode/ustring.h"
34 static const char* const txt_testCasePatterns
[] = {
35 "Quotes '', '{', a {0,number,integer} '{'0}",
36 "Quotes '', '{', a {0,number,integer} '{'0}",
37 "You deposited {0,number,integer} times an amount of {1,number,currency} on {2,date,short}",
38 "'{'2,time,full}, for {1, number }, {0,number,integer} is {2,time,full} and full date is {2,date,full}",
39 "'{'1,number,percent} for {0,number,integer} is {1,number,percent}",
42 static const char* const txt_testResultStrings
[] = {
43 "Quotes ', {, a 1 {0}",
44 "Quotes ', {, a 1 {0}",
45 "You deposited 1 times an amount of $3,456.00 on 1/12/70",
46 "{2,time,full}, for 3,456, 1 is 5:46:40 AM Pacific Standard Time and full date is Monday, January 12, 1970",
47 "{1,number,percent} for 1 is 345,600%"
50 const int32_t cnt_testCases
= 5;
51 static UChar
* testCasePatterns
[5];
53 static UChar
* testResultStrings
[5];
55 static UBool strings_initialized
= FALSE
;
57 /* function used to create the test patterns for testing Message formatting */
58 static void InitStrings( void )
61 if (strings_initialized
)
64 for (i
=0; i
< cnt_testCases
; i
++ ) {
65 uint32_t strSize
= (uint32_t)strlen(txt_testCasePatterns
[i
]) + 1;
66 testCasePatterns
[i
]=(UChar
*)malloc(sizeof(UChar
) * strSize
);
67 u_uastrncpy(testCasePatterns
[i
], txt_testCasePatterns
[i
], strSize
);
69 for (i
=0; i
< cnt_testCases
; i
++ ) {
70 uint32_t strSize
= (uint32_t)strlen(txt_testResultStrings
[i
]) + 1;
71 testResultStrings
[i
] = (UChar
*)malloc(sizeof(UChar
) * strSize
);
72 u_uastrncpy(testResultStrings
[i
], txt_testResultStrings
[i
], strSize
);
75 strings_initialized
= TRUE
;
78 static void FreeStrings( void )
81 if (!strings_initialized
)
84 for (i
=0; i
< cnt_testCases
; i
++ ) {
85 free(testCasePatterns
[i
]);
87 for (i
=0; i
< cnt_testCases
; i
++ ) {
88 free(testResultStrings
[i
]);
90 strings_initialized
= FALSE
;
93 #if (U_PLATFORM == U_PF_LINUX) /* add platforms here .. */
94 /* Keep the #if above in sync with the one below that has the same "add platforms here .." comment. */
96 /* Platform dependent test to detect if this type will return NULL when interpreted as a pointer. */
97 static UBool
returnsNullForType(int firstParam
, ...) {
100 va_start(marker
, firstParam
);
101 isNULL
= (UBool
)(va_arg(marker
, void*) == NULL
);
107 /* Test u_formatMessage() with various test patterns() */
108 static void MessageFormatTest( void )
112 int32_t resultLengthOut
,resultlength
,i
, patternlength
;
113 UErrorCode status
= U_ZERO_ERROR
;
114 UDate d1
=1000000000.0;
116 ctest_setTimeZone(NULL
, &status
);
118 str
=(UChar
*)malloc(sizeof(UChar
) * 7);
119 u_uastrncpy(str
, "MyDisk", 7);
121 result
=(UChar
*)malloc(sizeof(UChar
) * 1);
122 log_verbose("Testing u_formatMessage()\n");
124 for (i
= 0; i
< cnt_testCases
; i
++) {
126 patternlength
=u_strlen(testCasePatterns
[i
]);
127 resultLengthOut
=u_formatMessage( "en_US",testCasePatterns
[i
], patternlength
, result
, resultlength
,
128 &status
, 1, 3456.00, d1
);
129 if(status
== U_BUFFER_OVERFLOW_ERROR
)
132 resultlength
=resultLengthOut
+1;
133 result
=(UChar
*)realloc(result
,sizeof(UChar
) * resultlength
);
134 u_formatMessage( "en_US",testCasePatterns
[i
], patternlength
, result
, resultlength
,
135 &status
, 1, 3456.00, d1
);
137 if(U_FAILURE(status
)){
138 log_data_err("ERROR: failure in message format on testcase %d: %s (Are you missing data?)\n", i
, myErrorName(status
) );
141 if(u_strcmp(result
, testResultStrings
[i
])==0){
142 log_verbose("PASS: MessagFormat successful on testcase : %d\n", i
);
145 log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i
,
146 austrdup(result
), austrdup(testResultStrings
[i
]) );
154 for (i
= 0; i
< cnt_testCases
; i
++) {
155 UParseError parseError
;
157 patternlength
=u_strlen(testCasePatterns
[i
]);
159 resultLengthOut
=u_formatMessageWithError( "en_US",testCasePatterns
[i
], patternlength
, result
, resultlength
,
160 &parseError
,&status
, 1, 3456.00, d1
);
161 if(status
== U_BUFFER_OVERFLOW_ERROR
)
164 resultlength
=resultLengthOut
+1;
165 result
=(UChar
*)malloc(sizeof(UChar
) * resultlength
);
166 u_formatMessage( "en_US",testCasePatterns
[i
], patternlength
, result
, resultlength
,
167 &status
, 1, 3456.00, d1
);
169 if(U_FAILURE(status
)){
170 log_data_err("ERROR: failure in message format on testcase %d: %s (Are you missing data?)\n", i
, myErrorName(status
) );
173 if(u_strcmp(result
, testResultStrings
[i
])==0){
174 log_verbose("PASS: MessagFormat successful on testcase : %d\n", i
);
177 log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i
,
178 austrdup(result
), austrdup(testResultStrings
[i
]) );
185 UErrorCode ec
= U_ZERO_ERROR
;
186 int32_t patternLength
= u_strlen(testCasePatterns
[0]);
188 UMessageFormat formatter
= umsg_open(testCasePatterns
[0],patternLength
,"en_US",NULL
,&ec
);
191 log_data_err("umsg_open() failed for testCasePattens[0]. -> %s (Are you missing data?)\n", u_errorName(ec
));
194 for(i
= 0;i
<cnt_testCases
; i
++){
195 UParseError parseError
;
196 int32_t resultLength
=0,count
=0;
202 // Alternate between specifying the length and using NUL-termination.
203 patternLength
= ((i
& 1) == 0) ? u_strlen(testCasePatterns
[i
]) : -1;
205 umsg_applyPattern(formatter
,testCasePatterns
[i
],patternLength
,&parseError
,&ec
);
207 log_err("umsg_applyPattern() failed for testCasePattens[%d].\n",i
);
211 resultLength
= umsg_format(formatter
,result
,resultLength
,&ec
,1,3456.00,d1
);
212 if(ec
==U_BUFFER_OVERFLOW_ERROR
){
214 result
= (UChar
*) malloc(U_SIZEOF_UCHAR
*resultLength
+2);
215 resultLength
= umsg_format(formatter
,result
,resultLength
+2,&ec
,1,3456.00,d1
);
217 log_err("ERROR: failure in message format on testcase %d: %s\n", i
, u_errorName(status
) );
222 if(u_strcmp(result
, testResultStrings
[i
])==0){
223 log_verbose("PASS: MessagFormat successful on testcase : %d\n", i
);
226 log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i
,
227 austrdup(result
), austrdup(testResultStrings
[i
]) );
230 #if (U_PLATFORM == U_PF_LINUX) /* add platforms here .. */
231 log_verbose("Skipping potentially crashing test for mismatched varargs.\n");
233 log_verbose("Note: the next is a platform dependent test. If it crashes, add an exclusion for your platform near %s:%d\n", __FILE__
, __LINE__
);
235 if (returnsNullForType(1, (double)2.0)) {
236 /* HP/UX and possibly other platforms don't properly check for this case.
237 We pass in a UDate, but the function expects a UDate *. When va_arg is used,
238 most compilers will return NULL, but HP-UX won't do that and will return 2
239 in this case. This is a platform dependent test. It crashes on some systems.
241 If you get a crash here, see the definition of returnsNullForType.
243 This relies upon "undefined" behavior, as indicated by C99 7.15.1.1 paragraph 2
245 umsg_parse(formatter
,result
,resultLength
,&count
,&ec
,one
,two
,d2
);
246 if(ec
!=U_ILLEGAL_ARGUMENT_ERROR
){
247 log_err("FAIL: Did not get expected error for umsg_parse(). Expected: U_ILLEGAL_ARGUMENT_ERROR Got: %s \n",u_errorName(ec
));
253 log_verbose("Warning: Returning NULL for a mismatched va_arg type isn't supported on this platform.\n", i
);
257 umsg_parse(formatter
,result
,resultLength
,&count
,&ec
,&one
,&two
,&d2
);
259 log_err("umsg_parse could not parse the pattern. Error: %s.\n",u_errorName(ec
));
263 log_err("FAIL: Expected U_BUFFER_OVERFLOW error while preflighting got: %s for testCasePatterns[%d]",u_errorName(ec
),i
);
266 umsg_close(formatter
);
270 ctest_resetTimeZone();
274 /*test u_formatMessage() with sample patterns */
275 static void TestSampleMessageFormat(void)
279 UChar pattern
[100], expected
[100];
280 int32_t resultLengthOut
, resultlength
;
281 UDate d
= 837039928046.0;
282 UErrorCode status
= U_ZERO_ERROR
;
284 ctest_setTimeZone(NULL
, &status
);
286 str
=(UChar
*)malloc(sizeof(UChar
) * 15);
287 u_uastrcpy(str
, "abc");
289 u_uastrcpy(pattern
, "There are {0} files on {1,date}");
290 u_uastrcpy(expected
, "There are abc files on Jul 10, 1996");
291 result
=(UChar
*)malloc(sizeof(UChar
) * 1);
292 log_verbose("\nTesting a sample for Message format test#1\n");
294 resultLengthOut
=u_formatMessage( "en_US", pattern
, u_strlen(pattern
), result
, resultlength
, &status
, str
, d
);
295 if(status
==U_BUFFER_OVERFLOW_ERROR
)
298 resultlength
=resultLengthOut
+1;
299 result
=(UChar
*)realloc(result
, sizeof(UChar
) * resultlength
);
300 u_formatMessage( "en_US", pattern
, u_strlen(pattern
), result
, resultlength
, &status
, str
, d
);
302 if(U_FAILURE(status
)){
303 log_data_err("Error: failure in message format on test#1: %s (Are you missing data?)\n", myErrorName(status
));
305 else if(u_strcmp(result
, expected
)==0)
306 log_verbose("PASS: MessagFormat successful on test#1\n");
308 log_err("FAIL: Error in MessageFormat on test#1 \n GOT: %s EXPECTED: %s\n",
309 austrdup(result
), austrdup(expected
) );
313 log_verbose("\nTesting message format with another pattern test#2\n");
314 u_uastrcpy(pattern
, "The disk \"{0}\" contains {1,number,integer} file(s)");
315 u_uastrcpy(expected
, "The disk \"MyDisk\" contains 23 file(s)");
316 u_uastrcpy(str
, "MyDisk");
318 resultLengthOut
=u_formatMessage( "en_US",
326 if(status
==U_BUFFER_OVERFLOW_ERROR
)
329 resultlength
=resultLengthOut
+1;
330 result
=(UChar
*)realloc(result
, sizeof(UChar
) * (resultlength
+1));
331 u_formatMessage( "en_US", pattern
, u_strlen(pattern
), result
, resultlength
, &status
, str
, 23);
333 if(U_FAILURE(status
)){
334 log_data_err("Error: failure in message format on test#2 : %s (Are you missing data?)\n", myErrorName(status
));
336 else if(u_strcmp(result
, expected
)==0)
337 log_verbose("PASS: MessagFormat successful on test#2\n");
339 log_err("FAIL: Error in MessageFormat on test#2\n GOT: %s EXPECTED: %s\n",
340 austrdup(result
), austrdup(expected
) );
345 log_verbose("\nTesting message format with another pattern test#3\n");
346 u_uastrcpy(pattern
, "You made a {0} of {1,number,currency}");
347 u_uastrcpy(expected
, "You made a deposit of $500.00");
348 u_uastrcpy(str
, "deposit");
350 resultLengthOut
=u_formatMessage( "en_US", pattern
, u_strlen(pattern
), NULL
, resultlength
, &status
, str
, 500.00);
351 if(status
==U_BUFFER_OVERFLOW_ERROR
)
354 resultlength
=resultLengthOut
+1;
355 result
=(UChar
*)realloc(result
, sizeof(UChar
) * resultlength
);
356 u_formatMessage( "en_US", pattern
, u_strlen(pattern
), result
, resultlength
, &status
, str
, 500.00);
358 if(U_FAILURE(status
)){
359 log_data_err("Error: failure in message format on test#3 : %s (Are you missing data?)\n", myErrorName(status
));
361 else if(u_strcmp(result
, expected
)==0)
362 log_verbose("PASS: MessagFormat successful on test#3\n");
364 log_err("FAIL: Error in MessageFormat on test#3\n GOT: %s EXPECTED %s\n", austrdup(result
),
365 austrdup(expected
) );
371 ctest_resetTimeZone();
374 /* Test umsg_format() and umsg_parse() , format and parse sequence and round trip */
375 static void TestNewFormatAndParseAPI(void)
378 UChar
*result
= NULL
, tzID
[4], str
[25];
381 int32_t resultLengthOut
, resultlength
;
384 UDateFormat
*def1
= NULL
;
385 UErrorCode status
= U_ZERO_ERROR
;
388 UParseError parseError
;
389 UMessageFormat
* fmt
= NULL
;
392 ctest_setTimeZone(NULL
, &status
);
394 log_verbose("Testing format and parse with parse error\n");
396 u_uastrcpy(str
, "disturbance in force");
397 u_uastrcpy(tzID
, "PST");
398 cal
=ucal_open(tzID
, u_strlen(tzID
), "en_US", UCAL_TRADITIONAL
, &status
);
399 if(U_FAILURE(status
)){
400 log_data_err("error in ucal_open caldef : %s - (Are you missing data?)\n", myErrorName(status
) );
403 ucal_setDateTime(cal
, 1999, UCAL_MARCH
, 18, 0, 0, 0, &status
);
404 d1
=ucal_getMillis(cal
, &status
);
405 if(U_FAILURE(status
)){
406 log_err("Error: failure in get millis: %s\n", myErrorName(status
) );
409 log_verbose("\nTesting with pattern test#4");
410 u_uastrcpy(pattern
, "On {0, date, long}, there was a {1} on planet {2,number,integer}");
411 u_uastrcpy(expected
, "On March 18, 1999, there was a disturbance in force on planet 7");
413 fmt
= umsg_open(pattern
,u_strlen(pattern
),"en_US",&parseError
,&status
);
414 if(U_FAILURE(status
)){
415 log_data_err("error in umsg_open : %s (Are you missing data?)\n", u_errorName(status
) );
418 result
=(UChar
*)malloc(sizeof(UChar
) * resultlength
);
420 resultLengthOut
=umsg_format(fmt
,result
, resultlength
,&status
, d1
, str
, 7);
421 if(status
==U_BUFFER_OVERFLOW_ERROR
)
424 resultlength
=resultLengthOut
+1;
425 result
=(UChar
*)realloc(result
, sizeof(UChar
) * resultlength
);
426 u_formatMessageWithError( "en_US", pattern
, u_strlen(pattern
), result
, resultlength
,&parseError
, &status
, d1
, str
, 7);
429 if(U_FAILURE(status
)){
430 log_err("ERROR: failure in message format test#4: %s\n", myErrorName(status
));
432 if(u_strcmp(result
, expected
)==0)
433 log_verbose("PASS: MessagFormat successful on test#4\n");
435 log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result
),
436 austrdup(expected
) );
440 /*try to parse this and check*/
441 log_verbose("\nTesting the parse Message test#5\n");
443 umsg_parse(fmt
, result
, u_strlen(result
),&count
,&status
, &d
, ret
, &value
);
444 if(U_FAILURE(status
)){
445 log_err("ERROR: error in parsing: test#5: %s\n", myErrorName(status
));
447 if(value
!=7 && u_strcmp(str
,ret
)!=0)
448 log_err("FAIL: Error in parseMessage on test#5 \n");
450 log_verbose("PASS: parseMessage successful on test#5\n");
452 def1
= udat_open(UDAT_DEFAULT
,UDAT_DEFAULT
,NULL
, NULL
, 0, NULL
,0,&status
);
453 if(U_FAILURE(status
))
455 log_err("error in creating the dateformat using short date and time style:\n %s\n", myErrorName(status
));
458 if(u_strcmp(myDateFormat(def1
, d
), myDateFormat(def1
, d1
))==0)
459 log_verbose("PASS: parseMessage successful test#5\n");
461 log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n",
462 austrdup(myDateFormat(def1
,d
)), austrdup(myDateFormat(def1
,d1
)) );
472 ctest_resetTimeZone();
475 /* Test u_formatMessageWithError() and u_parseMessageWithError() , format and parse sequence and round trip */
476 static void TestSampleFormatAndParseWithError(void)
479 UChar
*result
, *tzID
, *str
;
483 int32_t resultLengthOut
, resultlength
;
486 UDateFormat
*def1
= NULL
;
487 UErrorCode status
= U_ZERO_ERROR
;
490 UParseError parseError
;
492 ctest_setTimeZone(NULL
, &status
);
494 log_verbose("Testing format and parse with parse error\n");
496 str
=(UChar
*)malloc(sizeof(UChar
) * 25);
497 u_uastrcpy(str
, "disturbance in force");
498 tzID
=(UChar
*)malloc(sizeof(UChar
) * 4);
499 u_uastrcpy(tzID
, "PST");
500 cal
=ucal_open(tzID
, u_strlen(tzID
), "en_US", UCAL_TRADITIONAL
, &status
);
501 if(U_FAILURE(status
)){
502 log_data_err("error in ucal_open caldef : %s - (Are you missing data?)\n", myErrorName(status
) );
504 ucal_setDateTime(cal
, 1999, UCAL_MARCH
, 18, 0, 0, 0, &status
);
505 d1
=ucal_getMillis(cal
, &status
);
506 if(U_FAILURE(status
)){
507 log_data_err("Error: failure in get millis: %s - (Are you missing data?)\n", myErrorName(status
) );
510 log_verbose("\nTesting with pattern test#4");
511 u_uastrcpy(pattern
, "On {0, date, long}, there was a {1} on planet {2,number,integer}");
512 u_uastrcpy(expected
, "On March 18, 1999, there was a disturbance in force on planet 7");
514 result
=(UChar
*)malloc(sizeof(UChar
) * resultlength
);
515 resultLengthOut
=u_formatMessageWithError( "en_US", pattern
, u_strlen(pattern
), result
, resultlength
,&parseError
, &status
, d1
, str
, 7);
516 if(status
==U_BUFFER_OVERFLOW_ERROR
)
519 resultlength
=resultLengthOut
+1;
520 result
=(UChar
*)realloc(result
, sizeof(UChar
) * resultlength
);
521 u_formatMessageWithError( "en_US", pattern
, u_strlen(pattern
), result
, resultlength
,&parseError
, &status
, d1
, str
, 7);
524 if(U_FAILURE(status
)){
525 log_data_err("ERROR: failure in message format test#4: %s (Are you missing data?)\n", myErrorName(status
));
528 else if(u_strcmp(result
, expected
)==0)
529 log_verbose("PASS: MessagFormat successful on test#4\n");
531 log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result
),
532 austrdup(expected
) );
536 /*try to parse this and check*/
537 log_verbose("\nTesting the parse Message test#5\n");
539 u_parseMessageWithError("en_US", pattern
, u_strlen(pattern
), result
, u_strlen(result
), &parseError
,&status
, &d
, ret
, &value
);
540 if(U_FAILURE(status
)){
541 log_data_err("ERROR: error in parsing: test#5: %s (Are you missing data?)\n", myErrorName(status
));
543 else if(value
!=7 && u_strcmp(str
,ret
)!=0)
544 log_err("FAIL: Error in parseMessage on test#5 \n");
546 log_verbose("PASS: parseMessage successful on test#5\n");
548 def1
= udat_open(UDAT_DEFAULT
,UDAT_DEFAULT
,NULL
, NULL
, 0, NULL
,0,&status
);
549 if(U_FAILURE(status
))
551 log_data_err("error in creating the dateformat using short date and time style: %s (Are you missing data?)\n", myErrorName(status
));
554 if(u_strcmp(myDateFormat(def1
, d
), myDateFormat(def1
, d1
))==0)
555 log_verbose("PASS: parseMessage successful test#5\n");
557 log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n",
558 austrdup(myDateFormat(def1
,d
)), austrdup(myDateFormat(def1
,d1
)) );
569 ctest_resetTimeZone();
572 /* Test u_formatMessage() and u_parseMessage() , format and parse sequence and round trip */
573 static void TestSampleFormatAndParse(void)
576 UChar
*result
, *tzID
, *str
;
579 int32_t resultLengthOut
, resultlength
;
583 UErrorCode status
= U_ZERO_ERROR
;
587 ctest_setTimeZone(NULL
, &status
);
589 log_verbose("Testing format and parse\n");
591 str
=(UChar
*)malloc(sizeof(UChar
) * 25);
592 u_uastrcpy(str
, "disturbance in force");
593 tzID
=(UChar
*)malloc(sizeof(UChar
) * 4);
594 u_uastrcpy(tzID
, "PST");
595 cal
=ucal_open(tzID
, u_strlen(tzID
), "en_US", UCAL_TRADITIONAL
, &status
);
596 if(U_FAILURE(status
)){
597 log_data_err("error in ucal_open caldef : %s - (Are you missing data?)\n", myErrorName(status
) );
600 ucal_setDateTime(cal
, 1999, UCAL_MARCH
, 18, 0, 0, 0, &status
);
601 d1
=ucal_getMillis(cal
, &status
);
602 if(U_FAILURE(status
)){
603 log_data_err("Error: failure in get millis: %s - (Are you missing data?)\n", myErrorName(status
) );
606 log_verbose("\nTesting with pattern test#4");
607 u_uastrcpy(pattern
, "On {0, date, long}, there was a {1} on planet {2,number,integer}");
608 u_uastrcpy(expected
, "On March 18, 1999, there was a disturbance in force on planet 7");
610 result
=(UChar
*)malloc(sizeof(UChar
) * resultlength
);
611 resultLengthOut
=u_formatMessage( "en_US", pattern
, u_strlen(pattern
), result
, resultlength
, &status
, d1
, str
, 7);
612 if(status
==U_BUFFER_OVERFLOW_ERROR
)
615 resultlength
=resultLengthOut
+1;
616 result
=(UChar
*)realloc(result
, sizeof(UChar
) * resultlength
);
617 u_formatMessage( "en_US", pattern
, u_strlen(pattern
), result
, resultlength
, &status
, d1
, str
, 7);
620 if(U_FAILURE(status
)){
621 log_data_err("ERROR: failure in message format test#4: %s (Are you missing data?)\n", myErrorName(status
));
624 else if(u_strcmp(result
, expected
)==0)
625 log_verbose("PASS: MessagFormat successful on test#4\n");
627 log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result
),
628 austrdup(expected
) );
632 /*try to parse this and check*/
633 log_verbose("\nTesting the parse Message test#5\n");
635 u_parseMessage("en_US", pattern
, u_strlen(pattern
), result
, u_strlen(result
), &status
, &d
, ret
, &value
);
636 if(U_FAILURE(status
)){
637 log_data_err("ERROR: error in parsing: test#5: %s (Are you missing data?)\n", myErrorName(status
));
639 else if(value
!=7 && u_strcmp(str
,ret
)!=0)
640 log_err("FAIL: Error in parseMessage on test#5 \n");
642 log_verbose("PASS: parseMessage successful on test#5\n");
644 def1
= udat_open(UDAT_DEFAULT
,UDAT_DEFAULT
,NULL
, NULL
, 0, NULL
,0,&status
);
645 if(U_FAILURE(status
))
647 log_data_err("error in creating the dateformat using short date and time style: %s (Are you missing data?)\n", myErrorName(status
));
650 if(u_strcmp(myDateFormat(def1
, d
), myDateFormat(def1
, d1
))==0)
651 log_verbose("PASS: parseMessage successful test#5\n");
653 log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n",
654 austrdup(myDateFormat(def1
,d
)), austrdup(myDateFormat(def1
,d1
)) );
664 ctest_resetTimeZone();
667 /* Test message format with a Select option */
668 static void TestMsgFormatSelect(void)
672 UErrorCode status
= U_ZERO_ERROR
;
676 int32_t resultlength
,resultLengthOut
;
678 str
=(UChar
*)malloc(sizeof(UChar
) * 25);
679 u_uastrcpy(str
, "Kirti");
680 str1
=(UChar
*)malloc(sizeof(UChar
) * 25);
681 u_uastrcpy(str1
, "female");
682 log_verbose("Testing message format with Select test #1\n:");
683 u_uastrcpy(pattern
, "{0} est {1, select, female {all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
684 u_uastrcpy(expected
, "Kirti est all\\u00E9e \\u00E0 Paris.");
686 resultLengthOut
=u_formatMessage( "fr", pattern
, u_strlen(pattern
), NULL
, resultlength
, &status
, str
, str1
);
687 if(status
==U_BUFFER_OVERFLOW_ERROR
)
690 resultlength
=resultLengthOut
+1;
691 result
=(UChar
*)malloc(sizeof(UChar
) * resultlength
);
692 u_formatMessage( "fr", pattern
, u_strlen(pattern
), result
, resultlength
, &status
, str
, str1
);
693 if(u_strcmp(result
, expected
)==0)
694 log_verbose("PASS: MessagFormat successful on Select test#1\n");
696 log_err("FAIL: Error in MessageFormat on Select test#1\n GOT %s EXPECTED %s\n", austrdup(result
),
697 austrdup(expected
) );
701 if(U_FAILURE(status
)){
702 log_data_err("ERROR: failure in message format on Select test#1 : %s \n", myErrorName(status
));
707 /*Test a nested pattern*/
708 str
=(UChar
*)malloc(sizeof(UChar
) * 25);
709 u_uastrcpy(str
, "Noname");
710 str1
=(UChar
*)malloc(sizeof(UChar
) * 25);
711 u_uastrcpy(str1
, "other");
712 log_verbose("Testing message format with Select test #2\n:");
713 u_uastrcpy(pattern
, "{0} est {1, select, female {{2,number,integer} all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
714 u_uastrcpy(expected
, "Noname est all\\u00E9 \\u00E0 Paris.");
716 resultLengthOut
=u_formatMessage( "fr", pattern
, u_strlen(pattern
), NULL
, resultlength
, &status
, str
, str1
,6);
717 if(status
==U_BUFFER_OVERFLOW_ERROR
)
720 resultlength
=resultLengthOut
+1;
721 result
=(UChar
*)malloc(sizeof(UChar
) * resultlength
);
722 u_formatMessage( "fr", pattern
, u_strlen(pattern
), result
, resultlength
, &status
, str
, str1
, 6);
723 if(u_strcmp(result
, expected
)==0)
724 log_verbose("PASS: MessagFormat successful on Select test#2\n");
726 log_err("FAIL: Error in MessageFormat on Select test#2\n GOT %s EXPECTED %s\n", austrdup(result
),
727 austrdup(expected
) );
731 if(U_FAILURE(status
)){
732 log_data_err("ERROR: failure in message format on Select test#2 : %s \n", myErrorName(status
));
738 /* test message format with a choice option */
739 static void TestMsgFormatChoice(void)
742 UErrorCode status
= U_ZERO_ERROR
;
746 int32_t resultlength
,resultLengthOut
;
748 str
=(UChar
*)malloc(sizeof(UChar
) * 25);
749 u_uastrcpy(str
, "MyDisk");
750 log_verbose("Testing message format with choice test #6\n:");
752 * Before ICU 4.8, umsg_xxx() did not detect conflicting argument types,
753 * and this pattern had {0,number,integer} as the inner argument.
754 * The choice argument has kDouble type while {0,number,integer} has kLong (int32_t).
755 * ICU 4.8 and above detects this as an error.
756 * We changed this pattern to work as intended.
758 u_uastrcpy(pattern
, "The disk {1} contains {0,choice,0#no files|1#one file|1<{0,number} files}");
759 u_uastrcpy(expected
, "The disk MyDisk contains 100 files");
761 resultLengthOut
=u_formatMessage( "en_US", pattern
, u_strlen(pattern
), NULL
, resultlength
, &status
, 100., str
);
762 if(status
==U_BUFFER_OVERFLOW_ERROR
)
765 resultlength
=resultLengthOut
+1;
766 result
=(UChar
*)malloc(sizeof(UChar
) * resultlength
);
767 u_formatMessage( "en_US", pattern
, u_strlen(pattern
), result
, resultlength
, &status
, 100., str
);
768 if(u_strcmp(result
, expected
)==0)
769 log_verbose("PASS: MessagFormat successful on test#6\n");
771 log_err("FAIL: Error in MessageFormat on test#6\n GOT %s EXPECTED %s\n", austrdup(result
),
772 austrdup(expected
) );
776 if(U_FAILURE(status
)){
777 log_data_err("ERROR: failure in message format on test#6 : %s (Are you missing data?)\n", myErrorName(status
));
780 log_verbose("Testing message format with choice test #7\n:");
781 u_uastrcpy(expected
, "The disk MyDisk contains no files");
783 resultLengthOut
=u_formatMessage( "en_US", pattern
, u_strlen(pattern
), NULL
, resultlength
, &status
, 0., str
);
784 if(status
==U_BUFFER_OVERFLOW_ERROR
)
787 resultlength
=resultLengthOut
+1;
788 result
=(UChar
*)malloc(sizeof(UChar
) * resultlength
);
789 u_formatMessage( "en_US", pattern
, u_strlen(pattern
), result
, resultlength
, &status
, 0., str
);
791 if(u_strcmp(result
, expected
)==0)
792 log_verbose("PASS: MessagFormat successful on test#7\n");
794 log_err("FAIL: Error in MessageFormat on test#7\n GOT: %s EXPECTED %s\n", austrdup(result
),
795 austrdup(expected
) );
799 if(U_FAILURE(status
)){
800 log_data_err("ERROR: failure in message format on test#7 : %s (Are you missing data?)\n", myErrorName(status
));
803 log_verbose("Testing message format with choice test #8\n:");
804 u_uastrcpy(expected
, "The disk MyDisk contains one file");
806 resultLengthOut
=u_formatMessage( "en_US", pattern
, u_strlen(pattern
), NULL
, resultlength
, &status
, 1., str
);
807 if(status
==U_BUFFER_OVERFLOW_ERROR
)
810 resultlength
=resultLengthOut
+1;
811 result
=(UChar
*)malloc(sizeof(UChar
) * resultlength
);
812 u_formatMessage( "en_US", pattern
, u_strlen(pattern
), result
, resultlength
, &status
, 1., str
);
814 if(u_strcmp(result
, expected
)==0)
815 log_verbose("PASS: MessagFormat successful on test#8\n");
817 log_err("FAIL: Error in MessageFormat on test#8\n GOT %s EXPECTED: %s\n", austrdup(result
),
818 austrdup(expected
) );
823 if(U_FAILURE(status
)){
824 log_data_err("ERROR: failure in message format on test#8 : %s (Are you missing data?)\n", myErrorName(status
));
831 /*test u_parseMessage() with various test patterns */
832 static void TestParseMessage(void)
836 UErrorCode status
= U_ZERO_ERROR
;
841 log_verbose("\nTesting a sample for parse Message test#9\n");
843 u_uastrcpy(source
, "You deposited an amount of $500.00");
844 u_uastrcpy(pattern
, "You {0} an amount of {1,number,currency}");
845 u_uastrcpy(res
,"deposited");
847 u_parseMessage( "en_US", pattern
, u_strlen(pattern
), source
, u_strlen(source
), &status
, str
, &value
);
848 if(U_FAILURE(status
)){
849 log_data_err("ERROR: failure in parse Message on test#9: %s (Are you missing data?)\n", myErrorName(status
));
851 else if(value
==500.00 && u_strcmp(str
,res
)==0)
852 log_verbose("PASS: parseMessage successful on test#9\n");
854 log_err("FAIL: Error in parseMessage on test#9 \n");
858 log_verbose("\nTesting a sample for parse Message test#10\n");
860 u_uastrcpy(source
, "There are 123 files on MyDisk created");
861 u_uastrcpy(pattern
, "There are {0,number,integer} files on {1} created");
862 u_uastrcpy(res
,"MyDisk");
864 u_parseMessage( "en_US", pattern
, u_strlen(pattern
), source
, u_strlen(source
), &status
, &value
, str
);
865 if(U_FAILURE(status
)){
866 log_data_err("ERROR: failure in parse Message on test#10: %s (Are you missing data?)\n", myErrorName(status
));
868 else if(value
==123.00 && u_strcmp(str
,res
)==0)
869 log_verbose("PASS: parseMessage successful on test#10\n");
871 log_err("FAIL: Error in parseMessage on test#10 \n");
874 static int32_t CallFormatMessage(const char* locale
, UChar
* testCasePattern
, int32_t patternLength
,
875 UChar
* result
, int32_t resultLength
, UErrorCode
*status
, ...)
879 va_start(ap
, status
);
880 len
= u_vformatMessage(locale
, testCasePattern
, patternLength
, result
, resultLength
, ap
, status
);
885 /* Test u_vformatMessage() with various test patterns. */
886 static void TestMessageFormatWithValist( void )
891 int32_t resultLengthOut
,resultlength
,i
, patternlength
;
892 UErrorCode status
= U_ZERO_ERROR
;
893 UDate d1
=1000000000.0;
895 ctest_setTimeZone(NULL
, &status
);
897 str
=(UChar
*)malloc(sizeof(UChar
) * 7);
898 u_uastrcpy(str
, "MyDisk");
900 result
=(UChar
*)malloc(sizeof(UChar
) * 1);
901 log_verbose("Testing u_formatMessage90\n");
903 for (i
= 0; i
< cnt_testCases
; i
++) {
905 patternlength
=u_strlen(testCasePatterns
[i
]);
906 resultLengthOut
=CallFormatMessage( "en_US",testCasePatterns
[i
], patternlength
, result
, resultlength
,
907 &status
, 1, 3456.00, d1
);
908 if(status
== U_BUFFER_OVERFLOW_ERROR
)
911 resultlength
=resultLengthOut
+1;
912 result
=(UChar
*)realloc(result
,sizeof(UChar
) * resultlength
);
913 CallFormatMessage( "en_US",testCasePatterns
[i
], patternlength
, result
, resultlength
,
914 &status
, 1, 3456.00, d1
);
916 if(U_FAILURE(status
)){
917 log_data_err("ERROR: failure in message format on testcase %d: %s (Are you missing data?)\n", i
, myErrorName(status
) );
919 else if(u_strcmp(result
, testResultStrings
[i
])==0){
920 log_verbose("PASS: MessagFormat successful on testcase : %d\n", i
);
923 log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i
,
924 austrdup(result
), austrdup(testResultStrings
[i
]) );
931 ctest_resetTimeZone();
934 static void CallParseMessage(const char* locale
, UChar
* pattern
, int32_t patternLength
,
935 UChar
* source
, int32_t sourceLength
, UErrorCode
*status
, ...)
938 va_start(ap
, status
);
939 u_vparseMessage(locale
, pattern
, patternLength
, source
, sourceLength
, ap
, status
);
943 /*test u_vparseMessage() with various test patterns */
944 static void TestParseMessageWithValist(void)
948 UErrorCode status
= U_ZERO_ERROR
;
953 log_verbose("\nTesting a sample for parse Message test#9\n");
955 u_uastrcpy(source
, "You deposited an amount of $500.00");
956 u_uastrcpy(pattern
, "You {0} an amount of {1,number,currency}");
957 u_uastrcpy(res
,"deposited");
959 CallParseMessage( "en_US", pattern
, u_strlen(pattern
), source
, u_strlen(source
), &status
, str
, &value
);
960 if(U_FAILURE(status
)){
961 log_data_err("ERROR: failure in parse Message on test#9: %s (Are you missing data?)\n", myErrorName(status
));
963 else if(value
==500.00 && u_strcmp(str
,res
)==0)
964 log_verbose("PASS: parseMessage successful on test#9\n");
966 log_err("FAIL: Error in parseMessage on test#9\n");
969 log_verbose("\nTesting a sample for parse Message test#10\n");
971 u_uastrcpy(source
, "There are 123 files on MyDisk created");
972 u_uastrcpy(pattern
, "There are {0,number,integer} files on {1} created");
973 u_uastrcpy(res
,"MyDisk");
975 CallParseMessage( "en_US", pattern
, u_strlen(pattern
), source
, u_strlen(source
), &status
, &value
, str
);
976 if(U_FAILURE(status
)){
977 log_data_err("ERROR: failure in parse Message on test#10: %s (Are you missing data?)\n", myErrorName(status
));
979 else if(value
==123.00 && u_strcmp(str
,res
)==0)
980 log_verbose("PASS: parseMessage successful on test#10\n");
982 log_err("FAIL: Error in parseMessage on test#10 \n");
986 * Regression test for ICU4C Jitterbug 904
988 static void TestJ904(void) {
994 UErrorCode status
= U_ZERO_ERROR
;
995 const char* PAT
= "Number {1,number,#0.000}, String {0}, Date {2,date,12:mm:ss.SSS}";
996 const char* EXP
= "Number 0,143, String foo, Date 12:34:56.789";
998 ctest_setTimeZone(NULL
, &status
);
1000 u_uastrcpy(string
, "foo");
1001 /* Slight hack here -- instead of date pattern HH:mm:ss.SSS, use
1002 * 12:mm:ss.SSS. Why? So this test generates the same output --
1003 * "12:34:56.789" -- regardless of time zone (as long as we aren't
1004 * in one of the 30 minute offset zones!). */
1005 u_uastrcpy(pattern
, PAT
);
1006 length
= u_formatMessage("nl", pattern
, u_strlen(pattern
),
1007 result
, 256, &status
,
1009 789.0+1000*(56+60*(34+60*12)));
1010 (void)length
; /* Suppress set but not used warning. */
1012 u_austrncpy(cresult
, result
, sizeof(cresult
));
1014 /* This test passes if it DOESN'T CRASH. However, we test the
1015 * output anyway. If the string doesn't match in the date part,
1016 * check to see that the machine doesn't have an unusual time zone
1017 * offset, that is, one with a non-zero minutes/seconds offset
1018 * from GMT -- see above. */
1019 if (strcmp(cresult
, EXP
) == 0) {
1020 log_verbose("Ok: \"%s\"\n", cresult
);
1022 log_data_err("FAIL: got \"%s\", expected \"%s\" -> %s (Are you missing data?)\n", cresult
, EXP
, u_errorName(status
));
1025 ctest_resetTimeZone();
1028 static void OpenMessageFormatTest(void)
1030 UMessageFormat
*f1
, *f2
, *f3
;
1034 UParseError parseError
;
1035 const char* locale
= "hi_IN";
1037 const char* PAT
= "Number {1,number,#0.000}, String {0}, Date {2,date,12:mm:ss.SSS}";
1039 UErrorCode status
= U_ZERO_ERROR
;
1041 u_uastrncpy(pattern
, PAT
, UPRV_LENGTHOF(pattern
));
1043 /* Test umsg_open */
1044 f1
= umsg_open(pattern
,length
,NULL
,NULL
,&status
);
1046 if(U_FAILURE(status
))
1048 log_err("umsg_open failed with pattern %s. Error: \n", PAT
, u_errorName(status
));
1052 /* Test umsg_open with parse error */
1053 status
= U_ZERO_ERROR
;
1054 f2
= umsg_open(pattern
,length
,NULL
,&parseError
,&status
);
1056 if(U_FAILURE(status
))
1058 log_err("umsg_open with parseError failed with pattern %s. Error: %s\n", PAT
, u_errorName(status
));
1062 /* Test umsg_clone */
1063 status
= U_ZERO_ERROR
;
1064 f3
= umsg_clone(f1
,&status
);
1065 if(U_FAILURE(status
))
1067 log_err("umsg_clone failed. Error %s \n", u_errorName(status
));
1070 /* Test umsg_setLocale */
1071 umsg_setLocale(f1
,locale
);
1072 /* Test umsg_getLocale */
1073 retLoc
= (char*)umsg_getLocale(f1
);
1074 if(strcmp(retLoc
,locale
)!=0)
1076 log_err("umsg_setLocale and umsg_getLocale methods failed. Expected:%s Got: %s \n", locale
, retLoc
);
1079 /* Test umsg_applyPattern */
1080 status
= U_ZERO_ERROR
;
1081 umsg_applyPattern(f1
,pattern
,(int32_t)strlen(PAT
),NULL
,&status
);
1082 if(U_FAILURE(status
))
1084 log_data_err("umsg_applyPattern failed. Error %s (Are you missing data?)\n",u_errorName(status
));
1087 /* Test umsg_toPattern */
1088 umsg_toPattern(f1
,result
,256,&status
);
1089 if(U_FAILURE(status
) ){
1090 log_data_err("umsg_toPattern method failed. Error: %s (Are you missing data?)\n",u_errorName(status
));
1092 if(u_strcmp(result
,pattern
)!=0){
1093 u_UCharsToChars(result
,cresult
,256);
1094 log_err("umsg_toPattern method failed. Expected: %s Got: %s \n",PAT
,cresult
);
1097 /* umsg_format umsg_parse */
1104 static void MessageLength(void)
1106 UErrorCode status
= U_ZERO_ERROR
;
1107 const char patChars
[] = {"123{0}456{0}"};
1108 const char expectedChars
[] = {"123abc"};
1109 UChar pattern
[sizeof(patChars
)];
1110 UChar arg
[] = {0x61,0x62,0x63,0};
1111 UChar result
[128] = {0};
1112 UChar expected
[sizeof(expectedChars
)];
1114 u_uastrncpy(pattern
, patChars
, UPRV_LENGTHOF(pattern
));
1115 u_uastrncpy(expected
, expectedChars
, UPRV_LENGTHOF(expected
));
1117 u_formatMessage("en_US", pattern
, 6, result
, UPRV_LENGTHOF(result
), &status
, arg
);
1118 if (U_FAILURE(status
)) {
1119 log_err("u_formatMessage method failed. Error: %s \n",u_errorName(status
));
1121 if (u_strcmp(result
, expected
) != 0) {
1122 log_err("u_formatMessage didn't return expected result\n");
1126 static void TestMessageWithUnusedArgNumber(void) {
1127 UErrorCode errorCode
= U_ZERO_ERROR
;
1128 U_STRING_DECL(pattern
, "abc {1} def", 11);
1129 UChar x
[2] = { 0x78, 0 }; // "x"
1130 UChar y
[2] = { 0x79, 0 }; // "y"
1131 U_STRING_DECL(expected
, "abc y def", 9);
1135 U_STRING_INIT(pattern
, "abc {1} def", 11);
1136 U_STRING_INIT(expected
, "abc y def", 9);
1137 length
= u_formatMessage("en", pattern
, -1, result
, UPRV_LENGTHOF(result
), &errorCode
, x
, y
);
1138 if (U_FAILURE(errorCode
) || length
!= u_strlen(expected
) || u_strcmp(result
, expected
) != 0) {
1139 log_err("u_formatMessage(pattern with only {1}, 2 args) failed: result length %d, UErrorCode %s \n",
1140 (int)length
, u_errorName(errorCode
));
1144 static void TestErrorChaining(void) {
1145 UErrorCode status
= U_USELESS_COLLATOR_ERROR
;
1147 umsg_open(NULL
, 0, NULL
, NULL
, &status
);
1148 umsg_applyPattern(NULL
, NULL
, 0, NULL
, &status
);
1149 umsg_toPattern(NULL
, NULL
, 0, &status
);
1150 umsg_clone(NULL
, &status
);
1151 umsg_format(NULL
, NULL
, 0, &status
);
1152 umsg_parse(NULL
, NULL
, 0, NULL
, &status
);
1155 /* All of this code should have done nothing. */
1156 if (status
!= U_USELESS_COLLATOR_ERROR
) {
1157 log_err("Status got changed to %s\n", u_errorName(status
));
1160 status
= U_ZERO_ERROR
;
1161 umsg_open(NULL
, 0, NULL
, NULL
, &status
);
1162 if (status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
1163 log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status
));
1165 status
= U_ZERO_ERROR
;
1166 umsg_applyPattern(NULL
, NULL
, 0, NULL
, &status
);
1167 if (status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
1168 log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status
));
1170 status
= U_ZERO_ERROR
;
1171 umsg_toPattern(NULL
, NULL
, 0, &status
);
1172 if (status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
1173 log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status
));
1175 status
= U_ZERO_ERROR
;
1176 umsg_clone(NULL
, &status
);
1177 if (status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
1178 log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status
));
1182 void addMsgForTest(TestNode
** root
);
1184 void addMsgForTest(TestNode
** root
)
1186 addTest(root
, &OpenMessageFormatTest
, "tsformat/cmsgtst/OpenMessageFormatTest");
1187 addTest(root
, &MessageFormatTest
, "tsformat/cmsgtst/MessageFormatTest");
1188 addTest(root
, &TestSampleMessageFormat
, "tsformat/cmsgtst/TestSampleMessageFormat");
1189 addTest(root
, &TestSampleFormatAndParse
, "tsformat/cmsgtst/TestSampleFormatAndParse");
1190 addTest(root
, &TestSampleFormatAndParseWithError
, "tsformat/cmsgtst/TestSampleFormatAndParseWithError");
1191 addTest(root
, &TestNewFormatAndParseAPI
, "tsformat/cmsgtst/TestNewFormatAndParseAPI");
1192 addTest(root
, &TestMsgFormatChoice
, "tsformat/cmsgtst/TestMsgFormatChoice");
1193 addTest(root
, &TestParseMessage
, "tsformat/cmsgtst/TestParseMessage");
1194 addTest(root
, &TestMessageFormatWithValist
, "tsformat/cmsgtst/TestMessageFormatWithValist");
1195 addTest(root
, &TestParseMessageWithValist
, "tsformat/cmsgtst/TestParseMessageWithValist");
1196 addTest(root
, &TestJ904
, "tsformat/cmsgtst/TestJ904");
1197 addTest(root
, &MessageLength
, "tsformat/cmsgtst/MessageLength");
1198 addTest(root
, &TestMessageWithUnusedArgNumber
, "tsformat/cmsgtst/TestMessageWithUnusedArgNumber");
1199 addTest(root
, &TestErrorChaining
, "tsformat/cmsgtst/TestErrorChaining");
1200 addTest(root
, &TestMsgFormatSelect
, "tsformat/cmsgtst/TestMsgFormatSelect");
1203 #endif /* #if !UCONFIG_NO_FORMATTING */