1 // Copyright (C) 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[%d]. -> %s (Are you missing data?)\n",i, u_errorName(ec));
194 for(i = 0;i<cnt_testCases; i++){
195 UParseError parseError;
196 int32_t resultLength =0,count=0;
202 patternLength = u_strlen(testCasePatterns[i]);
204 umsg_applyPattern(formatter,testCasePatterns[i],patternLength,&parseError,&ec);
206 log_err("umsg_applyPattern() failed for testCasePattens[%d].\n",i);
210 resultLength = umsg_format(formatter,result,resultLength,&ec,1,3456.00,d1);
211 if(ec==U_BUFFER_OVERFLOW_ERROR){
213 result = (UChar*) malloc(U_SIZEOF_UCHAR*resultLength+2);
214 resultLength = umsg_format(formatter,result,resultLength+2,&ec,1,3456.00,d1);
216 log_err("ERROR: failure in message format on testcase %d: %s\n", i, u_errorName(status) );
221 if(u_strcmp(result, testResultStrings[i])==0){
222 log_verbose("PASS: MessagFormat successful on testcase : %d\n", i);
225 log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i,
226 austrdup(result), austrdup(testResultStrings[i]) );
229 #if (U_PLATFORM == U_PF_LINUX) /* add platforms here .. */
230 log_verbose("Skipping potentially crashing test for mismatched varargs.\n");
232 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__);
234 if (returnsNullForType(1, (double)2.0)) {
235 /* HP/UX and possibly other platforms don't properly check for this case.
236 We pass in a UDate, but the function expects a UDate *. When va_arg is used,
237 most compilers will return NULL, but HP-UX won't do that and will return 2
238 in this case. This is a platform dependent test. It crashes on some systems.
240 If you get a crash here, see the definition of returnsNullForType.
242 This relies upon "undefined" behavior, as indicated by C99 7.15.1.1 paragraph 2
244 umsg_parse(formatter,result,resultLength,&count,&ec,one,two,d2);
245 if(ec!=U_ILLEGAL_ARGUMENT_ERROR){
246 log_err("FAIL: Did not get expected error for umsg_parse(). Expected: U_ILLEGAL_ARGUMENT_ERROR Got: %s \n",u_errorName(ec));
252 log_verbose("Warning: Returning NULL for a mismatched va_arg type isn't supported on this platform.\n", i);
256 umsg_parse(formatter,result,resultLength,&count,&ec,&one,&two,&d2);
258 log_err("umsg_parse could not parse the pattern. Error: %s.\n",u_errorName(ec));
262 log_err("FAIL: Expected U_BUFFER_OVERFLOW error while preflighting got: %s for testCasePatterns[%d]",u_errorName(ec),i);
265 umsg_close(formatter);
269 ctest_resetTimeZone();
273 /*test u_formatMessage() with sample patterns */
274 static void TestSampleMessageFormat(void)
278 UChar pattern[100], expected[100];
279 int32_t resultLengthOut, resultlength;
280 UDate d = 837039928046.0;
281 UErrorCode status = U_ZERO_ERROR;
283 ctest_setTimeZone(NULL, &status);
285 str=(UChar*)malloc(sizeof(UChar) * 15);
286 u_uastrcpy(str, "abc");
288 u_uastrcpy(pattern, "There are {0} files on {1,date}");
289 u_uastrcpy(expected, "There are abc files on Jul 10, 1996");
290 result=(UChar*)malloc(sizeof(UChar) * 1);
291 log_verbose("\nTesting a sample for Message format test#1\n");
293 resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, d);
294 if(status==U_BUFFER_OVERFLOW_ERROR)
297 resultlength=resultLengthOut+1;
298 result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
299 u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, d);
301 if(U_FAILURE(status)){
302 log_data_err("Error: failure in message format on test#1: %s (Are you missing data?)\n", myErrorName(status));
304 else if(u_strcmp(result, expected)==0)
305 log_verbose("PASS: MessagFormat successful on test#1\n");
307 log_err("FAIL: Error in MessageFormat on test#1 \n GOT: %s EXPECTED: %s\n",
308 austrdup(result), austrdup(expected) );
312 log_verbose("\nTesting message format with another pattern test#2\n");
313 u_uastrcpy(pattern, "The disk \"{0}\" contains {1,number,integer} file(s)");
314 u_uastrcpy(expected, "The disk \"MyDisk\" contains 23 file(s)");
315 u_uastrcpy(str, "MyDisk");
317 resultLengthOut=u_formatMessage( "en_US",
325 if(status==U_BUFFER_OVERFLOW_ERROR)
328 resultlength=resultLengthOut+1;
329 result=(UChar*)realloc(result, sizeof(UChar) * (resultlength+1));
330 u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, 23);
332 if(U_FAILURE(status)){
333 log_data_err("Error: failure in message format on test#2 : %s (Are you missing data?)\n", myErrorName(status));
335 else if(u_strcmp(result, expected)==0)
336 log_verbose("PASS: MessagFormat successful on test#2\n");
338 log_err("FAIL: Error in MessageFormat on test#2\n GOT: %s EXPECTED: %s\n",
339 austrdup(result), austrdup(expected) );
344 log_verbose("\nTesting message format with another pattern test#3\n");
345 u_uastrcpy(pattern, "You made a {0} of {1,number,currency}");
346 u_uastrcpy(expected, "You made a deposit of $500.00");
347 u_uastrcpy(str, "deposit");
349 resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, str, 500.00);
350 if(status==U_BUFFER_OVERFLOW_ERROR)
353 resultlength=resultLengthOut+1;
354 result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
355 u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, 500.00);
357 if(U_FAILURE(status)){
358 log_data_err("Error: failure in message format on test#3 : %s (Are you missing data?)\n", myErrorName(status));
360 else if(u_strcmp(result, expected)==0)
361 log_verbose("PASS: MessagFormat successful on test#3\n");
363 log_err("FAIL: Error in MessageFormat on test#3\n GOT: %s EXPECTED %s\n", austrdup(result),
364 austrdup(expected) );
370 ctest_resetTimeZone();
373 /* Test umsg_format() and umsg_parse() , format and parse sequence and round trip */
374 static void TestNewFormatAndParseAPI(void)
377 UChar *result, tzID[4], str[25];
380 int32_t resultLengthOut, resultlength;
384 UErrorCode status = U_ZERO_ERROR;
387 UParseError parseError;
388 UMessageFormat* fmt = NULL;
391 ctest_setTimeZone(NULL, &status);
393 log_verbose("Testing format and parse with parse error\n");
395 u_uastrcpy(str, "disturbance in force");
396 u_uastrcpy(tzID, "PST");
397 cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
398 if(U_FAILURE(status)){
399 log_data_err("error in ucal_open caldef : %s - (Are you missing data?)\n", myErrorName(status) );
402 ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status);
403 d1=ucal_getMillis(cal, &status);
404 if(U_FAILURE(status)){
405 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)) );
471 ctest_resetTimeZone();
474 /* Test u_formatMessageWithError() and u_parseMessageWithError() , format and parse sequence and round trip */
475 static void TestSampleFormatAndParseWithError(void)
478 UChar *result, *tzID, *str;
482 int32_t resultLengthOut, resultlength;
486 UErrorCode status = U_ZERO_ERROR;
489 UParseError parseError;
491 ctest_setTimeZone(NULL, &status);
493 log_verbose("Testing format and parse with parse error\n");
495 str=(UChar*)malloc(sizeof(UChar) * 25);
496 u_uastrcpy(str, "disturbance in force");
497 tzID=(UChar*)malloc(sizeof(UChar) * 4);
498 u_uastrcpy(tzID, "PST");
499 cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
500 if(U_FAILURE(status)){
501 log_data_err("error in ucal_open caldef : %s - (Are you missing data?)\n", myErrorName(status) );
503 ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status);
504 d1=ucal_getMillis(cal, &status);
505 if(U_FAILURE(status)){
506 log_data_err("Error: failure in get millis: %s - (Are you missing data?)\n", myErrorName(status) );
509 log_verbose("\nTesting with pattern test#4");
510 u_uastrcpy(pattern, "On {0, date, long}, there was a {1} on planet {2,number,integer}");
511 u_uastrcpy(expected, "On March 18, 1999, there was a disturbance in force on planet 7");
513 result=(UChar*)malloc(sizeof(UChar) * resultlength);
514 resultLengthOut=u_formatMessageWithError( "en_US", pattern, u_strlen(pattern), result, resultlength,&parseError, &status, d1, str, 7);
515 if(status==U_BUFFER_OVERFLOW_ERROR)
518 resultlength=resultLengthOut+1;
519 result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
520 u_formatMessageWithError( "en_US", pattern, u_strlen(pattern), result, resultlength,&parseError, &status, d1, str, 7);
523 if(U_FAILURE(status)){
524 log_data_err("ERROR: failure in message format test#4: %s (Are you missing data?)\n", myErrorName(status));
526 else if(u_strcmp(result, expected)==0)
527 log_verbose("PASS: MessagFormat successful on test#4\n");
529 log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result),
530 austrdup(expected) );
534 /*try to parse this and check*/
535 log_verbose("\nTesting the parse Message test#5\n");
537 u_parseMessageWithError("en_US", pattern, u_strlen(pattern), result, u_strlen(result), &parseError,&status, &d, ret, &value);
538 if(U_FAILURE(status)){
539 log_data_err("ERROR: error in parsing: test#5: %s (Are you missing data?)\n", myErrorName(status));
541 else if(value!=7 && u_strcmp(str,ret)!=0)
542 log_err("FAIL: Error in parseMessage on test#5 \n");
544 log_verbose("PASS: parseMessage successful on test#5\n");
546 def1 = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, NULL,0,&status);
547 if(U_FAILURE(status))
549 log_data_err("error in creating the dateformat using short date and time style: %s (Are you missing data?)\n", myErrorName(status));
552 if(u_strcmp(myDateFormat(def1, d), myDateFormat(def1, d1))==0)
553 log_verbose("PASS: parseMessage successful test#5\n");
555 log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n",
556 austrdup(myDateFormat(def1,d)), austrdup(myDateFormat(def1,d1)) );
566 ctest_resetTimeZone();
569 /* Test u_formatMessage() and u_parseMessage() , format and parse sequence and round trip */
570 static void TestSampleFormatAndParse(void)
573 UChar *result, *tzID, *str;
576 int32_t resultLengthOut, resultlength;
580 UErrorCode status = U_ZERO_ERROR;
584 ctest_setTimeZone(NULL, &status);
586 log_verbose("Testing format and parse\n");
588 str=(UChar*)malloc(sizeof(UChar) * 25);
589 u_uastrcpy(str, "disturbance in force");
590 tzID=(UChar*)malloc(sizeof(UChar) * 4);
591 u_uastrcpy(tzID, "PST");
592 cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
593 if(U_FAILURE(status)){
594 log_data_err("error in ucal_open caldef : %s - (Are you missing data?)\n", myErrorName(status) );
596 ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status);
597 d1=ucal_getMillis(cal, &status);
598 if(U_FAILURE(status)){
599 log_data_err("Error: failure in get millis: %s - (Are you missing data?)\n", myErrorName(status) );
602 log_verbose("\nTesting with pattern test#4");
603 u_uastrcpy(pattern, "On {0, date, long}, there was a {1} on planet {2,number,integer}");
604 u_uastrcpy(expected, "On March 18, 1999, there was a disturbance in force on planet 7");
606 result=(UChar*)malloc(sizeof(UChar) * resultlength);
607 resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, d1, str, 7);
608 if(status==U_BUFFER_OVERFLOW_ERROR)
611 resultlength=resultLengthOut+1;
612 result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
613 u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, d1, str, 7);
616 if(U_FAILURE(status)){
617 log_data_err("ERROR: failure in message format test#4: %s (Are you missing data?)\n", myErrorName(status));
619 else if(u_strcmp(result, expected)==0)
620 log_verbose("PASS: MessagFormat successful on test#4\n");
622 log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result),
623 austrdup(expected) );
627 /*try to parse this and check*/
628 log_verbose("\nTesting the parse Message test#5\n");
630 u_parseMessage("en_US", pattern, u_strlen(pattern), result, u_strlen(result), &status, &d, ret, &value);
631 if(U_FAILURE(status)){
632 log_data_err("ERROR: error in parsing: test#5: %s (Are you missing data?)\n", myErrorName(status));
634 else if(value!=7 && u_strcmp(str,ret)!=0)
635 log_err("FAIL: Error in parseMessage on test#5 \n");
637 log_verbose("PASS: parseMessage successful on test#5\n");
639 def1 = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, NULL,0,&status);
640 if(U_FAILURE(status))
642 log_data_err("error in creating the dateformat using short date and time style: %s (Are you missing data?)\n", myErrorName(status));
645 if(u_strcmp(myDateFormat(def1, d), myDateFormat(def1, d1))==0)
646 log_verbose("PASS: parseMessage successful test#5\n");
648 log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n",
649 austrdup(myDateFormat(def1,d)), austrdup(myDateFormat(def1,d1)) );
659 ctest_resetTimeZone();
662 /* Test message format with a Select option */
663 static void TestMsgFormatSelect(void)
667 UErrorCode status = U_ZERO_ERROR;
671 int32_t resultlength,resultLengthOut;
673 str=(UChar*)malloc(sizeof(UChar) * 25);
674 u_uastrcpy(str, "Kirti");
675 str1=(UChar*)malloc(sizeof(UChar) * 25);
676 u_uastrcpy(str1, "female");
677 log_verbose("Testing message format with Select test #1\n:");
678 u_uastrcpy(pattern, "{0} est {1, select, female {all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
679 u_uastrcpy(expected, "Kirti est all\\u00E9e \\u00E0 Paris.");
681 resultLengthOut=u_formatMessage( "fr", pattern, u_strlen(pattern), NULL, resultlength, &status, str , str1);
682 if(status==U_BUFFER_OVERFLOW_ERROR)
685 resultlength=resultLengthOut+1;
686 result=(UChar*)malloc(sizeof(UChar) * resultlength);
687 u_formatMessage( "fr", pattern, u_strlen(pattern), result, resultlength, &status, str , str1);
688 if(u_strcmp(result, expected)==0)
689 log_verbose("PASS: MessagFormat successful on Select test#1\n");
691 log_err("FAIL: Error in MessageFormat on Select test#1\n GOT %s EXPECTED %s\n", austrdup(result),
692 austrdup(expected) );
696 if(U_FAILURE(status)){
697 log_data_err("ERROR: failure in message format on Select test#1 : %s \n", myErrorName(status));
702 /*Test a nested pattern*/
703 str=(UChar*)malloc(sizeof(UChar) * 25);
704 u_uastrcpy(str, "Noname");
705 str1=(UChar*)malloc(sizeof(UChar) * 25);
706 u_uastrcpy(str1, "other");
707 log_verbose("Testing message format with Select test #2\n:");
708 u_uastrcpy(pattern, "{0} est {1, select, female {{2,number,integer} all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
709 u_uastrcpy(expected, "Noname est all\\u00E9 \\u00E0 Paris.");
711 resultLengthOut=u_formatMessage( "fr", pattern, u_strlen(pattern), NULL, resultlength, &status, str , str1,6);
712 if(status==U_BUFFER_OVERFLOW_ERROR)
715 resultlength=resultLengthOut+1;
716 result=(UChar*)malloc(sizeof(UChar) * resultlength);
717 u_formatMessage( "fr", pattern, u_strlen(pattern), result, resultlength, &status, str , str1);
718 if(u_strcmp(result, expected)==0)
719 log_verbose("PASS: MessagFormat successful on Select test#2\n");
721 log_err("FAIL: Error in MessageFormat on Select test#2\n GOT %s EXPECTED %s\n", austrdup(result),
722 austrdup(expected) );
726 if(U_FAILURE(status)){
727 log_data_err("ERROR: failure in message format on Select test#2 : %s \n", myErrorName(status));
733 /* test message format with a choice option */
734 static void TestMsgFormatChoice(void)
737 UErrorCode status = U_ZERO_ERROR;
741 int32_t resultlength,resultLengthOut;
743 str=(UChar*)malloc(sizeof(UChar) * 25);
744 u_uastrcpy(str, "MyDisk");
745 log_verbose("Testing message format with choice test #6\n:");
747 * Before ICU 4.8, umsg_xxx() did not detect conflicting argument types,
748 * and this pattern had {0,number,integer} as the inner argument.
749 * The choice argument has kDouble type while {0,number,integer} has kLong (int32_t).
750 * ICU 4.8 and above detects this as an error.
751 * We changed this pattern to work as intended.
753 u_uastrcpy(pattern, "The disk {1} contains {0,choice,0#no files|1#one file|1<{0,number} files}");
754 u_uastrcpy(expected, "The disk MyDisk contains 100 files");
756 resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, 100., str);
757 if(status==U_BUFFER_OVERFLOW_ERROR)
760 resultlength=resultLengthOut+1;
761 result=(UChar*)malloc(sizeof(UChar) * resultlength);
762 u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, 100., str);
763 if(u_strcmp(result, expected)==0)
764 log_verbose("PASS: MessagFormat successful on test#6\n");
766 log_err("FAIL: Error in MessageFormat on test#6\n GOT %s EXPECTED %s\n", austrdup(result),
767 austrdup(expected) );
771 if(U_FAILURE(status)){
772 log_data_err("ERROR: failure in message format on test#6 : %s (Are you missing data?)\n", myErrorName(status));
775 log_verbose("Testing message format with choice test #7\n:");
776 u_uastrcpy(expected, "The disk MyDisk contains no files");
778 resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, 0., str);
779 if(status==U_BUFFER_OVERFLOW_ERROR)
782 resultlength=resultLengthOut+1;
783 result=(UChar*)malloc(sizeof(UChar) * resultlength);
784 u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, 0., str);
786 if(u_strcmp(result, expected)==0)
787 log_verbose("PASS: MessagFormat successful on test#7\n");
789 log_err("FAIL: Error in MessageFormat on test#7\n GOT: %s EXPECTED %s\n", austrdup(result),
790 austrdup(expected) );
794 if(U_FAILURE(status)){
795 log_data_err("ERROR: failure in message format on test#7 : %s (Are you missing data?)\n", myErrorName(status));
798 log_verbose("Testing message format with choice test #8\n:");
799 u_uastrcpy(expected, "The disk MyDisk contains one file");
801 resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, 1., str);
802 if(status==U_BUFFER_OVERFLOW_ERROR)
805 resultlength=resultLengthOut+1;
806 result=(UChar*)malloc(sizeof(UChar) * resultlength);
807 u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, 1., str);
809 if(u_strcmp(result, expected)==0)
810 log_verbose("PASS: MessagFormat successful on test#8\n");
812 log_err("FAIL: Error in MessageFormat on test#8\n GOT %s EXPECTED: %s\n", austrdup(result),
813 austrdup(expected) );
818 if(U_FAILURE(status)){
819 log_data_err("ERROR: failure in message format on test#8 : %s (Are you missing data?)\n", myErrorName(status));
826 /*test u_parseMessage() with various test patterns */
827 static void TestParseMessage(void)
831 UErrorCode status = U_ZERO_ERROR;
836 log_verbose("\nTesting a sample for parse Message test#9\n");
838 u_uastrcpy(source, "You deposited an amount of $500.00");
839 u_uastrcpy(pattern, "You {0} an amount of {1,number,currency}");
840 u_uastrcpy(res,"deposited");
842 u_parseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, str, &value);
843 if(U_FAILURE(status)){
844 log_data_err("ERROR: failure in parse Message on test#9: %s (Are you missing data?)\n", myErrorName(status));
846 else if(value==500.00 && u_strcmp(str,res)==0)
847 log_verbose("PASS: parseMessage successful on test#9\n");
849 log_err("FAIL: Error in parseMessage on test#9 \n");
853 log_verbose("\nTesting a sample for parse Message test#10\n");
855 u_uastrcpy(source, "There are 123 files on MyDisk created");
856 u_uastrcpy(pattern, "There are {0,number,integer} files on {1} created");
857 u_uastrcpy(res,"MyDisk");
859 u_parseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, &value, str);
860 if(U_FAILURE(status)){
861 log_data_err("ERROR: failure in parse Message on test#10: %s (Are you missing data?)\n", myErrorName(status));
863 else if(value==123.00 && u_strcmp(str,res)==0)
864 log_verbose("PASS: parseMessage successful on test#10\n");
866 log_err("FAIL: Error in parseMessage on test#10 \n");
869 static int32_t CallFormatMessage(const char* locale, UChar* testCasePattern, int32_t patternLength,
870 UChar* result, int32_t resultLength, UErrorCode *status, ...)
874 va_start(ap, status);
875 len = u_vformatMessage(locale, testCasePattern, patternLength, result, resultLength, ap, status);
880 /* Test u_vformatMessage() with various test patterns. */
881 static void TestMessageFormatWithValist( void )
886 int32_t resultLengthOut,resultlength,i, patternlength;
887 UErrorCode status = U_ZERO_ERROR;
888 UDate d1=1000000000.0;
890 ctest_setTimeZone(NULL, &status);
892 str=(UChar*)malloc(sizeof(UChar) * 7);
893 u_uastrcpy(str, "MyDisk");
895 result=(UChar*)malloc(sizeof(UChar) * 1);
896 log_verbose("Testing u_formatMessage90\n");
898 for (i = 0; i < cnt_testCases; i++) {
900 patternlength=u_strlen(testCasePatterns[i]);
901 resultLengthOut=CallFormatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength,
902 &status, 1, 3456.00, d1);
903 if(status== U_BUFFER_OVERFLOW_ERROR)
906 resultlength=resultLengthOut+1;
907 result=(UChar*)realloc(result,sizeof(UChar) * resultlength);
908 CallFormatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength,
909 &status, 1, 3456.00, d1);
911 if(U_FAILURE(status)){
912 log_data_err("ERROR: failure in message format on testcase %d: %s (Are you missing data?)\n", i, myErrorName(status) );
914 else if(u_strcmp(result, testResultStrings[i])==0){
915 log_verbose("PASS: MessagFormat successful on testcase : %d\n", i);
918 log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i,
919 austrdup(result), austrdup(testResultStrings[i]) );
926 ctest_resetTimeZone();
929 static void CallParseMessage(const char* locale, UChar* pattern, int32_t patternLength,
930 UChar* source, int32_t sourceLength, UErrorCode *status, ...)
933 va_start(ap, status);
934 u_vparseMessage(locale, pattern, patternLength, source, sourceLength, ap, status);
938 /*test u_vparseMessage() with various test patterns */
939 static void TestParseMessageWithValist(void)
943 UErrorCode status = U_ZERO_ERROR;
948 log_verbose("\nTesting a sample for parse Message test#9\n");
950 u_uastrcpy(source, "You deposited an amount of $500.00");
951 u_uastrcpy(pattern, "You {0} an amount of {1,number,currency}");
952 u_uastrcpy(res,"deposited");
954 CallParseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, str, &value);
955 if(U_FAILURE(status)){
956 log_data_err("ERROR: failure in parse Message on test#9: %s (Are you missing data?)\n", myErrorName(status));
958 else if(value==500.00 && u_strcmp(str,res)==0)
959 log_verbose("PASS: parseMessage successful on test#9\n");
961 log_err("FAIL: Error in parseMessage on test#9\n");
964 log_verbose("\nTesting a sample for parse Message test#10\n");
966 u_uastrcpy(source, "There are 123 files on MyDisk created");
967 u_uastrcpy(pattern, "There are {0,number,integer} files on {1} created");
968 u_uastrcpy(res,"MyDisk");
970 CallParseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, &value, str);
971 if(U_FAILURE(status)){
972 log_data_err("ERROR: failure in parse Message on test#10: %s (Are you missing data?)\n", myErrorName(status));
974 else if(value==123.00 && u_strcmp(str,res)==0)
975 log_verbose("PASS: parseMessage successful on test#10\n");
977 log_err("FAIL: Error in parseMessage on test#10 \n");
981 * Regression test for ICU4C Jitterbug 904
983 static void TestJ904(void) {
989 UErrorCode status = U_ZERO_ERROR;
990 const char* PAT = "Number {1,number,#0.000}, String {0}, Date {2,date,12:mm:ss.SSS}";
991 const char* EXP = "Number 0,143, String foo, Date 12:34:56.789";
993 ctest_setTimeZone(NULL, &status);
995 u_uastrcpy(string, "foo");
996 /* Slight hack here -- instead of date pattern HH:mm:ss.SSS, use
997 * 12:mm:ss.SSS. Why? So this test generates the same output --
998 * "12:34:56.789" -- regardless of time zone (as long as we aren't
999 * in one of the 30 minute offset zones!). */
1000 u_uastrcpy(pattern, PAT);
1001 length = u_formatMessage("nl", pattern, u_strlen(pattern),
1002 result, 256, &status,
1004 789.0+1000*(56+60*(34+60*12)));
1005 (void)length; /* Suppress set but not used warning. */
1007 u_austrncpy(cresult, result, sizeof(cresult));
1009 /* This test passes if it DOESN'T CRASH. However, we test the
1010 * output anyway. If the string doesn't match in the date part,
1011 * check to see that the machine doesn't have an unusual time zone
1012 * offset, that is, one with a non-zero minutes/seconds offset
1013 * from GMT -- see above. */
1014 if (strcmp(cresult, EXP) == 0) {
1015 log_verbose("Ok: \"%s\"\n", cresult);
1017 log_data_err("FAIL: got \"%s\", expected \"%s\" -> %s (Are you missing data?)\n", cresult, EXP, u_errorName(status));
1020 ctest_resetTimeZone();
1023 static void OpenMessageFormatTest(void)
1025 UMessageFormat *f1, *f2, *f3;
1029 UParseError parseError;
1030 const char* locale = "hi_IN";
1032 const char* PAT = "Number {1,number,#0.000}, String {0}, Date {2,date,12:mm:ss.SSS}";
1034 UErrorCode status = U_ZERO_ERROR;
1036 u_uastrncpy(pattern, PAT, UPRV_LENGTHOF(pattern));
1038 /* Test umsg_open */
1039 f1 = umsg_open(pattern,length,NULL,NULL,&status);
1041 if(U_FAILURE(status))
1043 log_err("umsg_open failed with pattern %s. Error: \n", PAT, u_errorName(status));
1047 /* Test umsg_open with parse error */
1048 status = U_ZERO_ERROR;
1049 f2 = umsg_open(pattern,length,NULL,&parseError,&status);
1051 if(U_FAILURE(status))
1053 log_err("umsg_open with parseError failed with pattern %s. Error: %s\n", PAT, u_errorName(status));
1057 /* Test umsg_clone */
1058 status = U_ZERO_ERROR;
1059 f3 = umsg_clone(f1,&status);
1060 if(U_FAILURE(status))
1062 log_err("umsg_clone failed. Error %s \n", u_errorName(status));
1065 /* Test umsg_setLocale */
1066 umsg_setLocale(f1,locale);
1067 /* Test umsg_getLocale */
1068 retLoc = (char*)umsg_getLocale(f1);
1069 if(strcmp(retLoc,locale)!=0)
1071 log_err("umsg_setLocale and umsg_getLocale methods failed. Expected:%s Got: %s \n", locale, retLoc);
1074 /* Test umsg_applyPattern */
1075 status = U_ZERO_ERROR;
1076 umsg_applyPattern(f1,pattern,(int32_t)strlen(PAT),NULL,&status);
1077 if(U_FAILURE(status))
1079 log_data_err("umsg_applyPattern failed. Error %s (Are you missing data?)\n",u_errorName(status));
1082 /* Test umsg_toPattern */
1083 umsg_toPattern(f1,result,256,&status);
1084 if(U_FAILURE(status) ){
1085 log_data_err("umsg_toPattern method failed. Error: %s (Are you missing data?)\n",u_errorName(status));
1087 if(u_strcmp(result,pattern)!=0){
1088 u_UCharsToChars(result,cresult,256);
1089 log_err("umsg_toPattern method failed. Expected: %s Got: %s \n",PAT,cresult);
1092 /* umsg_format umsg_parse */
1099 static void MessageLength(void)
1101 UErrorCode status = U_ZERO_ERROR;
1102 const char patChars[] = {"123{0}456{0}"};
1103 const char expectedChars[] = {"123abc"};
1104 UChar pattern[sizeof(patChars)];
1105 UChar arg[] = {0x61,0x62,0x63,0};
1106 UChar result[128] = {0};
1107 UChar expected[sizeof(expectedChars)];
1109 u_uastrncpy(pattern, patChars, UPRV_LENGTHOF(pattern));
1110 u_uastrncpy(expected, expectedChars, UPRV_LENGTHOF(expected));
1112 u_formatMessage("en_US", pattern, 6, result, UPRV_LENGTHOF(result), &status, arg);
1113 if (U_FAILURE(status)) {
1114 log_err("u_formatMessage method failed. Error: %s \n",u_errorName(status));
1116 if (u_strcmp(result, expected) != 0) {
1117 log_err("u_formatMessage didn't return expected result\n");
1121 static void TestMessageWithUnusedArgNumber() {
1122 UErrorCode errorCode = U_ZERO_ERROR;
1123 U_STRING_DECL(pattern, "abc {1} def", 11);
1124 UChar x[2] = { 0x78, 0 }; // "x"
1125 UChar y[2] = { 0x79, 0 }; // "y"
1126 U_STRING_DECL(expected, "abc y def", 9);
1130 U_STRING_INIT(pattern, "abc {1} def", 11);
1131 U_STRING_INIT(expected, "abc y def", 9);
1132 length = u_formatMessage("en", pattern, -1, result, UPRV_LENGTHOF(result), &errorCode, x, y);
1133 if (U_FAILURE(errorCode) || length != u_strlen(expected) || u_strcmp(result, expected) != 0) {
1134 log_err("u_formatMessage(pattern with only {1}, 2 args) failed: result length %d, UErrorCode %s \n",
1135 (int)length, u_errorName(errorCode));
1139 static void TestErrorChaining(void) {
1140 UErrorCode status = U_USELESS_COLLATOR_ERROR;
1142 umsg_open(NULL, 0, NULL, NULL, &status);
1143 umsg_applyPattern(NULL, NULL, 0, NULL, &status);
1144 umsg_toPattern(NULL, NULL, 0, &status);
1145 umsg_clone(NULL, &status);
1146 umsg_format(NULL, NULL, 0, &status);
1147 umsg_parse(NULL, NULL, 0, NULL, &status);
1150 /* All of this code should have done nothing. */
1151 if (status != U_USELESS_COLLATOR_ERROR) {
1152 log_err("Status got changed to %s\n", u_errorName(status));
1155 status = U_ZERO_ERROR;
1156 umsg_open(NULL, 0, NULL, NULL, &status);
1157 if (status != U_ILLEGAL_ARGUMENT_ERROR) {
1158 log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status));
1160 status = U_ZERO_ERROR;
1161 umsg_applyPattern(NULL, NULL, 0, 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_toPattern(NULL, NULL, 0, &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_clone(NULL, &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));
1177 void addMsgForTest(TestNode** root);
1179 void addMsgForTest(TestNode** root)
1181 addTest(root, &OpenMessageFormatTest, "tsformat/cmsgtst/OpenMessageFormatTest");
1182 addTest(root, &MessageFormatTest, "tsformat/cmsgtst/MessageFormatTest");
1183 addTest(root, &TestSampleMessageFormat, "tsformat/cmsgtst/TestSampleMessageFormat");
1184 addTest(root, &TestSampleFormatAndParse, "tsformat/cmsgtst/TestSampleFormatAndParse");
1185 addTest(root, &TestSampleFormatAndParseWithError, "tsformat/cmsgtst/TestSampleFormatAndParseWithError");
1186 addTest(root, &TestNewFormatAndParseAPI, "tsformat/cmsgtst/TestNewFormatAndParseAPI");
1187 addTest(root, &TestMsgFormatChoice, "tsformat/cmsgtst/TestMsgFormatChoice");
1188 addTest(root, &TestParseMessage, "tsformat/cmsgtst/TestParseMessage");
1189 addTest(root, &TestMessageFormatWithValist, "tsformat/cmsgtst/TestMessageFormatWithValist");
1190 addTest(root, &TestParseMessageWithValist, "tsformat/cmsgtst/TestParseMessageWithValist");
1191 addTest(root, &TestJ904, "tsformat/cmsgtst/TestJ904");
1192 addTest(root, &MessageLength, "tsformat/cmsgtst/MessageLength");
1193 addTest(root, &TestMessageWithUnusedArgNumber, "tsformat/cmsgtst/TestMessageWithUnusedArgNumber");
1194 addTest(root, &TestErrorChaining, "tsformat/cmsgtst/TestErrorChaining");
1195 addTest(root, &TestMsgFormatSelect, "tsformat/cmsgtst/TestMsgFormatSelect");
1198 #endif /* #if !UCONFIG_NO_FORMATTING */