1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************
8 *
9 * File CMSGTST.C
10 *
11 * Modification History:
12 *        Name                     Description
13 *     Madhu Katragadda              Creation
14 ********************************************************************/
15/* C API TEST FOR MESSAGE FORMAT */
16
17#include "unicode/utypes.h"
18
19#if !UCONFIG_NO_FORMATTING
20
21#include <stdarg.h>
22#include <stdbool.h>
23#include <stdlib.h>
24#include <string.h>
25#include "unicode/uloc.h"
26#include "unicode/umsg.h"
27#include "unicode/udat.h"
28#include "unicode/umsg.h"
29#include "unicode/ustring.h"
30#include "cintltst.h"
31#include "cmsgtst.h"
32#include "cformtst.h"
33#include "cmemory.h"
34
35static const char* const txt_testCasePatterns[] = {
36   "Quotes '', '{', a {0,number,integer} '{'0}",
37   "Quotes '', '{', a {0,number,integer} '{'0}",
38   "You deposited {0,number,integer} times an amount of {1,number,currency} on {2,date,short}",
39    "'{'2,time,full}, for {1, number }, {0,number,integer} is {2,time,full} and full date is {2,date,full}",
40   "'{'1,number,percent} for {0,number,integer} is {1,number,percent}",
41};
42
43static const char* const txt_testResultStrings[] = {
44    "Quotes ', {, a 1 {0}",
45    "Quotes ', {, a 1 {0}",
46    "You deposited 1 times an amount of $3,456.00 on 1/12/70",
47    "{2,time,full}, for 3,456, 1 is 5:46:40\\u202FAM Pacific Standard Time and full date is Monday, January 12, 1970",
48    "{1,number,percent} for 1 is 345,600%"
49};
50
51const int32_t cnt_testCases = 5;
52static UChar* testCasePatterns[5];
53
54static UChar* testResultStrings[5];
55
56static UBool strings_initialized = false;
57
58/* function used to create the test patterns for testing Message formatting */
59static void InitStrings( void )
60{
61    int32_t i;
62    if (strings_initialized)
63        return;
64
65    for (i=0; i < cnt_testCases; i++ ) {
66        uint32_t strSize = (uint32_t)strlen(txt_testCasePatterns[i]) + 1;
67        testCasePatterns[i]=(UChar*)malloc(sizeof(UChar) * strSize);
68        u_uastrncpy(testCasePatterns[i], txt_testCasePatterns[i], strSize);
69    }
70    for (i=0; i < cnt_testCases; i++ ) {
71        uint32_t strSize = (uint32_t)strlen(txt_testResultStrings[i]) + 1;
72        testResultStrings[i] = (UChar*)malloc(sizeof(UChar) * strSize);
73        u_unescape(txt_testResultStrings[i], testResultStrings[i], strSize);
74    }
75
76    strings_initialized = true;
77}
78
79static void FreeStrings( void )
80{
81    int32_t i;
82    if (!strings_initialized)
83        return;
84
85    for (i=0; i < cnt_testCases; i++ ) {
86        free(testCasePatterns[i]);
87    }
88    for (i=0; i < cnt_testCases; i++ ) {
89        free(testResultStrings[i]);
90    }
91    strings_initialized = false;
92}
93
94#if (U_PLATFORM == U_PF_LINUX) /* add platforms here .. */
95/* Keep the #if above in sync with the one below that has the same "add platforms here .." comment. */
96#else
97/* Platform dependent test to detect if this type will return NULL when interpreted as a pointer. */
98static UBool returnsNullForType(int firstParam, ...) {
99    UBool isNULL;
100    va_list marker;
101    va_start(marker, firstParam);
102    isNULL = (UBool)(va_arg(marker, void*) == NULL);
103    va_end(marker);
104    return isNULL;
105}
106#endif
107
108/* Test u_formatMessage() with various test patterns() */
109static void MessageFormatTest( void )
110{
111    UChar *str;
112    UChar* result;
113    int32_t resultLengthOut,resultlength,i, patternlength;
114    UErrorCode status = U_ZERO_ERROR;
115    UDate d1=1000000000.0;
116
117    ctest_setTimeZone(NULL, &status);
118
119    str=(UChar*)malloc(sizeof(UChar) * 7);
120    u_uastrncpy(str, "MyDisk", 7);
121    resultlength=1;
122    result=(UChar*)malloc(sizeof(UChar) * 1);
123    log_verbose("Testing u_formatMessage()\n");
124    InitStrings();
125    for (i = 0; i < cnt_testCases; i++) {
126        status=U_ZERO_ERROR;
127        patternlength=u_strlen(testCasePatterns[i]);
128        resultLengthOut=u_formatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength,
129            &status, 1, 3456.00, d1);
130        if(status== U_BUFFER_OVERFLOW_ERROR)
131        {
132            status=U_ZERO_ERROR;
133            resultlength=resultLengthOut+1;
134            result=(UChar*)realloc(result,sizeof(UChar) * resultlength);
135            u_formatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength,
136                &status, 1, 3456.00, d1);
137        }
138        if(U_FAILURE(status)){
139            log_data_err("ERROR: failure in message format on testcase %d:  %s (Are you missing data?)\n", i, myErrorName(status) );
140            continue;
141        }
142        if(u_strcmp(result, testResultStrings[i])==0){
143            log_verbose("PASS: MessagFormat successful on testcase : %d\n", i);
144        }
145        else{
146            log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i,
147                austrdup(result), austrdup(testResultStrings[i]) );
148        }
149    }
150    free(result);
151    result = NULL;
152    free(str);
153    {
154
155         for (i = 0; i < cnt_testCases; i++) {
156            UParseError parseError;
157            status=U_ZERO_ERROR;
158            patternlength=u_strlen(testCasePatterns[i]);
159            resultlength=0;
160            resultLengthOut=u_formatMessageWithError( "en_US",testCasePatterns[i], patternlength, result, resultlength,
161                &parseError,&status, 1, 3456.00, d1);
162            if(status== U_BUFFER_OVERFLOW_ERROR)
163            {
164                status=U_ZERO_ERROR;
165                resultlength=resultLengthOut+1;
166                result=(UChar*)malloc(sizeof(UChar) * resultlength);
167                u_formatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength,
168                    &status, 1, 3456.00, d1);
169            }
170            if(U_FAILURE(status)){
171                log_data_err("ERROR: failure in message format on testcase %d:  %s (Are you missing data?)\n", i, myErrorName(status) );
172                continue;
173            }
174            if(u_strcmp(result, testResultStrings[i])==0){
175                log_verbose("PASS: MessagFormat successful on testcase : %d\n", i);
176            }
177            else{
178                log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i,
179                    austrdup(result), austrdup(testResultStrings[i]) );
180            }
181            free(result);
182            result=NULL;
183        }
184    }
185    {
186        UErrorCode ec = U_ZERO_ERROR;
187        int32_t patternLength = u_strlen(testCasePatterns[0]);
188
189        UMessageFormat formatter = umsg_open(testCasePatterns[0],patternLength,"en_US",NULL,&ec);
190
191        if(U_FAILURE(ec)){
192            log_data_err("umsg_open() failed for testCasePattens[0]. -> %s (Are you missing data?)\n", u_errorName(ec));
193            umsg_close(formatter);
194            return;
195        }
196        for(i = 0;i<cnt_testCases; i++){
197            UParseError parseError;
198            int32_t resultLength =0,count=0;
199            int32_t one=0;
200            int32_t two=0;
201            UDate d2=0;
202
203            result=NULL;
204            // Alternate between specifying the length and using NUL-termination.
205            patternLength = ((i & 1) == 0) ? u_strlen(testCasePatterns[i]) : -1;
206
207            umsg_applyPattern(formatter,testCasePatterns[i],patternLength,&parseError,&ec);
208            if(U_FAILURE(ec)){
209                log_err("umsg_applyPattern() failed for testCasePattens[%d].\n",i);
210                umsg_close(formatter);
211                return;
212            }
213            /* pre-flight */
214            resultLength = umsg_format(formatter,result,resultLength,&ec,1,3456.00,d1);
215            if(ec==U_BUFFER_OVERFLOW_ERROR){
216                ec=U_ZERO_ERROR;
217                result = (UChar*) malloc(U_SIZEOF_UCHAR*resultLength+2);
218                resultLength =  umsg_format(formatter,result,resultLength+2,&ec,1,3456.00,d1);
219                if(U_FAILURE(ec)){
220                      log_err("ERROR: failure in message format on testcase %d:  %s\n", i, u_errorName(status) );
221                      free(result);
222                      umsg_close(formatter);
223                      return;
224                }
225
226                if(u_strcmp(result, testResultStrings[i])==0){
227                    log_verbose("PASS: MessagFormat successful on testcase : %d\n", i);
228                }
229                else{
230                    log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i,
231                        austrdup(result), austrdup(testResultStrings[i]) );
232                }
233
234#if (U_PLATFORM == U_PF_LINUX) /* add platforms here .. */
235                log_verbose("Skipping potentially crashing test for mismatched varargs.\n");
236#else
237                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__);
238
239                if (returnsNullForType(1, (double)2.0)) {
240                    /* HP/UX and possibly other platforms don't properly check for this case.
241                    We pass in a UDate, but the function expects a UDate *.  When va_arg is used,
242                    most compilers will return NULL, but HP-UX won't do that and will return 2
243                    in this case.  This is a platform dependent test.  It crashes on some systems.
244
245                    If you get a crash here, see the definition of returnsNullForType.
246
247                    This relies upon "undefined" behavior, as indicated by C99 7.15.1.1 paragraph 2
248                    */
249                    umsg_parse(formatter,result,resultLength,&count,&ec,one,two,d2);
250                    if(ec!=U_ILLEGAL_ARGUMENT_ERROR){
251                        log_err("FAIL: Did not get expected error for umsg_parse(). Expected: U_ILLEGAL_ARGUMENT_ERROR Got: %s \n",u_errorName(ec));
252                    }else{
253                        ec = U_ZERO_ERROR;
254                    }
255                }
256                else {
257                    log_verbose("Warning: Returning NULL for a mismatched va_arg type isn't supported on this platform.\n", i);
258                }
259#endif
260
261                umsg_parse(formatter,result,resultLength,&count,&ec,&one,&two,&d2);
262                if(U_FAILURE(ec)){
263                    log_err("umsg_parse could not parse the pattern. Error: %s.\n",u_errorName(ec));
264                }
265                free(result);
266            }else{
267                log_err("FAIL: Expected U_BUFFER_OVERFLOW error while preflighting got: %s for testCasePatterns[%d]",u_errorName(ec),i);
268            }
269        }
270        umsg_close(formatter);
271    }
272    FreeStrings();
273
274    ctest_resetTimeZone();
275}
276
277
278/*test u_formatMessage() with sample patterns */
279static void TestSampleMessageFormat(void)
280{
281    UChar *str;
282    UChar *result;
283    UChar pattern[100], expected[100];
284    int32_t resultLengthOut, resultlength;
285    UDate d = 837039928046.0;
286    UErrorCode status = U_ZERO_ERROR;
287
288    ctest_setTimeZone(NULL, &status);
289
290    str=(UChar*)malloc(sizeof(UChar) * 15);
291    u_uastrcpy(str, "abc");
292
293    u_uastrcpy(pattern, "There are {0} files on {1,date}");
294    u_uastrcpy(expected, "There are abc files on Jul 10, 1996");
295    result=(UChar*)malloc(sizeof(UChar) * 1);
296    log_verbose("\nTesting a sample for Message format test#1\n");
297    resultlength=1;
298    resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, d);
299    if(status==U_BUFFER_OVERFLOW_ERROR)
300    {
301        status=U_ZERO_ERROR;
302        resultlength=resultLengthOut+1;
303        result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
304        u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, d);
305    }
306    if(U_FAILURE(status)){
307        log_data_err("Error: failure in message format on test#1: %s (Are you missing data?)\n", myErrorName(status));
308    }
309    else if(u_strcmp(result, expected)==0)
310        log_verbose("PASS: MessagFormat successful on test#1\n");
311    else{
312        log_err("FAIL: Error in MessageFormat on test#1 \n GOT: %s EXPECTED: %s\n",
313            austrdup(result), austrdup(expected) );
314    }
315
316
317    log_verbose("\nTesting message format with another pattern test#2\n");
318    u_uastrcpy(pattern, "The disk \"{0}\" contains {1,number,integer} file(s)");
319    u_uastrcpy(expected, "The disk \"MyDisk\" contains 23 file(s)");
320    u_uastrcpy(str, "MyDisk");
321
322    resultLengthOut=u_formatMessage( "en_US",
323        pattern,
324        u_strlen(pattern),
325        result,
326        resultlength,
327        &status,
328        str,
329        235);
330    if(status==U_BUFFER_OVERFLOW_ERROR)
331    {
332        status=U_ZERO_ERROR;
333        resultlength=resultLengthOut+1;
334        result=(UChar*)realloc(result, sizeof(UChar) * (resultlength+1));
335        u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, 23);
336    }
337    if(U_FAILURE(status)){
338        log_data_err("Error: failure in message format on test#2 : %s (Are you missing data?)\n", myErrorName(status));
339    }
340    else if(u_strcmp(result, expected)==0)
341        log_verbose("PASS: MessagFormat successful on test#2\n");
342    else{
343        log_err("FAIL: Error in MessageFormat on test#2\n GOT: %s EXPECTED: %s\n",
344            austrdup(result), austrdup(expected) );
345    }
346
347
348
349    log_verbose("\nTesting message format with another pattern test#3\n");
350    u_uastrcpy(pattern, "You made a {0} of {1,number,currency}");
351    u_uastrcpy(expected, "You made a deposit of $500.00");
352    u_uastrcpy(str, "deposit");
353    resultlength=0;
354    resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, str, 500.00);
355    if(status==U_BUFFER_OVERFLOW_ERROR)
356    {
357        status=U_ZERO_ERROR;
358        resultlength=resultLengthOut+1;
359        result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
360        u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, 500.00);
361    }
362    if(U_FAILURE(status)){
363        log_data_err("Error: failure in message format on test#3 : %s (Are you missing data?)\n", myErrorName(status));
364    }
365    else if(u_strcmp(result, expected)==0)
366        log_verbose("PASS: MessagFormat successful on test#3\n");
367    else{
368        log_err("FAIL: Error in MessageFormat on test#3\n GOT: %s EXPECTED %s\n", austrdup(result),
369            austrdup(expected) );
370    }
371
372    free(result);
373    free(str);
374
375    ctest_resetTimeZone();
376}
377
378/* Test umsg_format() and umsg_parse() , format and parse sequence and round trip */
379static void TestNewFormatAndParseAPI(void)
380{
381
382    UChar *result = NULL, tzID[4], str[25];
383    UChar pattern[100];
384    UChar expected[100];
385    int32_t resultLengthOut, resultlength;
386    UCalendar *cal;
387    UDate d1,d;
388    UDateFormat *def1 = NULL;
389    UErrorCode status = U_ZERO_ERROR;
390    int32_t value = 0;
391    UChar ret[30];
392    UParseError parseError;
393    UMessageFormat* fmt = NULL;
394    int32_t count=0;
395
396    ctest_setTimeZone(NULL, &status);
397
398    log_verbose("Testing format and parse with parse error\n");
399
400    u_uastrcpy(str, "disturbance in force");
401    u_uastrcpy(tzID, "PST");
402    cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
403    if(U_FAILURE(status)){
404        log_data_err("error in ucal_open caldef : %s - (Are you missing data?)\n", myErrorName(status) );
405        goto cleanup;
406    }
407    ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status);
408    d1=ucal_getMillis(cal, &status);
409    if(U_FAILURE(status)){
410        log_err("Error: failure in get millis: %s\n", myErrorName(status) );
411        goto cleanup;
412    }
413
414    log_verbose("\nTesting with pattern test#4");
415    u_uastrcpy(pattern, "On {0, date, long}, there was a {1} on planet {2,number,integer}");
416    u_uastrcpy(expected, "On March 18, 1999, there was a disturbance in force on planet 7");
417    resultlength=1;
418    fmt = umsg_open(pattern,u_strlen(pattern),"en_US",&parseError,&status);
419    if(U_FAILURE(status)){
420        log_data_err("error in umsg_open  : %s (Are you missing data?)\n", u_errorName(status) );
421        goto cleanup;
422    }
423    result=(UChar*)malloc(sizeof(UChar) * resultlength);
424
425    resultLengthOut=umsg_format(fmt ,result, resultlength,&status, d1, str, 7);
426    if(status==U_BUFFER_OVERFLOW_ERROR)
427    {
428        status=U_ZERO_ERROR;
429        resultlength=resultLengthOut+1;
430        result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
431        u_formatMessageWithError( "en_US", pattern, u_strlen(pattern), result, resultlength,&parseError, &status, d1, str, 7);
432
433    }
434    if(U_FAILURE(status)){
435        log_err("ERROR: failure in message format test#4: %s\n", myErrorName(status));
436    }
437    if(u_strcmp(result, expected)==0)
438        log_verbose("PASS: MessagFormat successful on test#4\n");
439    else{
440        log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result),
441            austrdup(expected) );
442    }
443
444
445    /*try to parse this and check*/
446    log_verbose("\nTesting the parse Message test#5\n");
447
448    umsg_parse(fmt, result, u_strlen(result),&count,&status, &d, ret, &value);
449    if(U_FAILURE(status)){
450        log_err("ERROR: error in parsing: test#5: %s\n", myErrorName(status));
451    }
452    if(value!=7 && u_strcmp(str,ret)!=0)
453        log_err("FAIL: Error in parseMessage on test#5 \n");
454    else
455        log_verbose("PASS: parseMessage successful on test#5\n");
456
457    def1 = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, NULL,0,&status);
458    if(U_FAILURE(status))
459    {
460        log_err("error in creating the dateformat using short date and time style:\n %s\n", myErrorName(status));
461    }else{
462
463        if(u_strcmp(myDateFormat(def1, d), myDateFormat(def1, d1))==0)
464            log_verbose("PASS: parseMessage successful test#5\n");
465        else{
466            log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n",
467                austrdup(myDateFormat(def1,d)), austrdup(myDateFormat(def1,d1)) );
468        }
469    }
470cleanup:
471    umsg_close(fmt);
472    udat_close(def1);
473    ucal_close(cal);
474
475    free(result);
476
477    ctest_resetTimeZone();
478}
479
480/* Test u_formatMessageWithError() and u_parseMessageWithError() , format and parse sequence and round trip */
481static void TestSampleFormatAndParseWithError(void)
482{
483
484    UChar *result, *tzID, *str;
485    UChar pattern[100];
486
487    UChar expected[100];
488    int32_t resultLengthOut, resultlength;
489    UCalendar *cal;
490    UDate d1,d;
491    UDateFormat *def1 = NULL;
492    UErrorCode status = U_ZERO_ERROR;
493    int32_t value = 0;
494    UChar ret[30];
495    UParseError parseError;
496
497    ctest_setTimeZone(NULL, &status);
498
499    log_verbose("Testing format and parse with parse error\n");
500
501    str=(UChar*)malloc(sizeof(UChar) * 25);
502    u_uastrcpy(str, "disturbance in force");
503    tzID=(UChar*)malloc(sizeof(UChar) * 4);
504    u_uastrcpy(tzID, "PST");
505    cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
506    if(U_FAILURE(status)){
507        log_data_err("error in ucal_open caldef : %s - (Are you missing data?)\n", myErrorName(status) );
508    }
509    ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status);
510    d1=ucal_getMillis(cal, &status);
511    if(U_FAILURE(status)){
512            log_data_err("Error: failure in get millis: %s - (Are you missing data?)\n", myErrorName(status) );
513    }
514
515    log_verbose("\nTesting with pattern test#4");
516    u_uastrcpy(pattern, "On {0, date, long}, there was a {1} on planet {2,number,integer}");
517    u_uastrcpy(expected, "On March 18, 1999, there was a disturbance in force on planet 7");
518    resultlength=1;
519    result=(UChar*)malloc(sizeof(UChar) * resultlength);
520    resultLengthOut=u_formatMessageWithError( "en_US", pattern, u_strlen(pattern), result, resultlength,&parseError, &status, d1, str, 7);
521    if(status==U_BUFFER_OVERFLOW_ERROR)
522    {
523        status=U_ZERO_ERROR;
524        resultlength=resultLengthOut+1;
525        result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
526        u_formatMessageWithError( "en_US", pattern, u_strlen(pattern), result, resultlength,&parseError, &status, d1, str, 7);
527
528    }
529    if(U_FAILURE(status)){
530        log_data_err("ERROR: failure in message format test#4: %s (Are you missing data?)\n", myErrorName(status));
531        goto cleanup;
532    }
533    else if(u_strcmp(result, expected)==0)
534        log_verbose("PASS: MessagFormat successful on test#4\n");
535    else{
536        log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result),
537            austrdup(expected) );
538    }
539
540
541    /*try to parse this and check*/
542    log_verbose("\nTesting the parse Message test#5\n");
543
544    if (U_SUCCESS(status)) {
545        u_parseMessageWithError("en_US", pattern, u_strlen(pattern), result, u_strlen(result),
546                                &parseError,&status, &d, ret, &value);
547        if(U_FAILURE(status)){
548            log_data_err("ERROR: error in parsing: test#5: %s (Are you missing data?)\n", myErrorName(status));
549        }
550        else if(value!=7 && u_strcmp(str,ret)!=0)
551            log_err("FAIL: Error in parseMessage on test#5 \n");
552        else
553            log_verbose("PASS: parseMessage successful on test#5\n");
554    }
555
556    def1 = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, NULL,0,&status);
557    if(U_FAILURE(status))
558    {
559        log_data_err("error in creating the dateformat using short date and time style: %s (Are you missing data?)\n", myErrorName(status));
560    }else{
561
562        if(u_strcmp(myDateFormat(def1, d), myDateFormat(def1, d1))==0)
563            log_verbose("PASS: parseMessage successful test#5\n");
564        else{
565            log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n",
566                austrdup(myDateFormat(def1,d)), austrdup(myDateFormat(def1,d1)) );
567        }
568    }
569cleanup:
570    udat_close(def1);
571    ucal_close(cal);
572
573    free(result);
574    free(str);
575    free(tzID);
576
577    ctest_resetTimeZone();
578}
579
580/* Test u_formatMessage() and u_parseMessage() , format and parse sequence and round trip */
581static void TestSampleFormatAndParse(void)
582{
583
584    UChar *result, *tzID, *str;
585    UChar pattern[100];
586    UChar expected[100];
587    int32_t resultLengthOut, resultlength;
588    UCalendar *cal;
589    UDate d1,d;
590    UDateFormat *def1;
591    UErrorCode status = U_ZERO_ERROR;
592    int32_t value = 0;
593    UChar ret[30];
594
595    ctest_setTimeZone(NULL, &status);
596
597    log_verbose("Testing format and parse\n");
598
599    str=(UChar*)malloc(sizeof(UChar) * 25);
600    u_uastrcpy(str, "disturbance in force");
601    tzID=(UChar*)malloc(sizeof(UChar) * 4);
602    u_uastrcpy(tzID, "PST");
603    cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
604    if(U_FAILURE(status)){
605        log_data_err("error in ucal_open caldef : %s - (Are you missing data?)\n", myErrorName(status) );
606        return;
607    }
608    ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status);
609    d1=ucal_getMillis(cal, &status);
610    if(U_FAILURE(status)){
611        log_data_err("Error: failure in get millis: %s - (Are you missing data?)\n", myErrorName(status) );
612    }
613
614    log_verbose("\nTesting with pattern test#4");
615    u_uastrcpy(pattern, "On {0, date, long}, there was a {1} on planet {2,number,integer}");
616    u_uastrcpy(expected, "On March 18, 1999, there was a disturbance in force on planet 7");
617    resultlength=1;
618    result=(UChar*)malloc(sizeof(UChar) * resultlength);
619    resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, d1, str, 7);
620    if(status==U_BUFFER_OVERFLOW_ERROR)
621    {
622        status=U_ZERO_ERROR;
623        resultlength=resultLengthOut+1;
624        result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
625        u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, d1, str, 7);
626
627    }
628    if(U_FAILURE(status)){
629        log_data_err("ERROR: failure in message format test#4: %s (Are you missing data?)\n", myErrorName(status));
630        return;
631    }
632    else if(u_strcmp(result, expected)==0)
633        log_verbose("PASS: MessagFormat successful on test#4\n");
634    else{
635        log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result),
636            austrdup(expected) );
637    }
638
639
640    /*try to parse this and check*/
641    log_verbose("\nTesting the parse Message test#5\n");
642
643    if (U_SUCCESS(status)) {
644        u_parseMessage("en_US", pattern, u_strlen(pattern), result, u_strlen(result), &status, &d, ret, &value);
645        if(U_FAILURE(status)){
646            log_data_err("ERROR: error in parsing: test#5: %s (Are you missing data?)\n", myErrorName(status));
647        }
648        else if(value!=7 && u_strcmp(str,ret)!=0)
649            log_err("FAIL: Error in parseMessage on test#5 \n");
650        else
651            log_verbose("PASS: parseMessage successful on test#5\n");
652    }
653
654    def1 = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, NULL,0,&status);
655    if(U_FAILURE(status))
656    {
657        log_data_err("error in creating the dateformat using short date and time style: %s (Are you missing data?)\n", myErrorName(status));
658    }else{
659
660        if(u_strcmp(myDateFormat(def1, d), myDateFormat(def1, d1))==0)
661            log_verbose("PASS: parseMessage successful test#5\n");
662        else{
663            log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n",
664                austrdup(myDateFormat(def1,d)), austrdup(myDateFormat(def1,d1)) );
665        }
666    }
667    udat_close(def1);
668    ucal_close(cal);
669
670    free(result);
671    free(str);
672    free(tzID);
673
674    ctest_resetTimeZone();
675}
676
677/* Test message format with a Select option */
678static void TestMsgFormatSelect(void)
679{
680    UChar* str;
681    UChar* str1;
682    UErrorCode status = U_ZERO_ERROR;
683    UChar *result;
684    UChar pattern[100];
685    UChar expected[100];
686    int32_t resultlength,resultLengthOut;
687
688    str=(UChar*)malloc(sizeof(UChar) * 25);
689    u_uastrcpy(str, "Kirti");
690    str1=(UChar*)malloc(sizeof(UChar) * 25);
691    u_uastrcpy(str1, "female");
692    log_verbose("Testing message format with Select test #1\n:");
693    u_uastrcpy(pattern, "{0} est {1, select, female {all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
694    u_uastrcpy(expected, "Kirti est all\\u00E9e \\u00E0 Paris.");
695    resultlength=0;
696    resultLengthOut=u_formatMessage( "fr", pattern, u_strlen(pattern), NULL, resultlength, &status, str , str1);
697    if(status==U_BUFFER_OVERFLOW_ERROR)
698    {
699        status=U_ZERO_ERROR;
700        resultlength=resultLengthOut+1;
701        result=(UChar*)malloc(sizeof(UChar) * resultlength);
702        u_formatMessage( "fr", pattern, u_strlen(pattern), result, resultlength, &status, str , str1);
703        if(u_strcmp(result, expected)==0)
704            log_verbose("PASS: MessagFormat successful on Select test#1\n");
705        else{
706            log_err("FAIL: Error in MessageFormat on Select test#1\n GOT %s EXPECTED %s\n", austrdup(result),
707                austrdup(expected) );
708        }
709        free(result);
710    }
711    if(U_FAILURE(status)){
712        log_data_err("ERROR: failure in message format on Select test#1 : %s \n", myErrorName(status));
713    }
714    free(str);
715    free(str1);
716
717    /*Test a nested pattern*/
718    str=(UChar*)malloc(sizeof(UChar) * 25);
719    u_uastrcpy(str, "Noname");
720    str1=(UChar*)malloc(sizeof(UChar) * 25);
721    u_uastrcpy(str1, "other");
722    log_verbose("Testing message format with Select test #2\n:");
723    u_uastrcpy(pattern, "{0} est {1, select, female {{2,number,integer} all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
724    u_uastrcpy(expected, "Noname est all\\u00E9 \\u00E0 Paris.");
725    resultlength=0;
726    resultLengthOut=u_formatMessage( "fr", pattern, u_strlen(pattern), NULL, resultlength, &status, str , str1,6);
727    if(status==U_BUFFER_OVERFLOW_ERROR)
728    {
729        status=U_ZERO_ERROR;
730        resultlength=resultLengthOut+1;
731        result=(UChar*)malloc(sizeof(UChar) * resultlength);
732        u_formatMessage( "fr", pattern, u_strlen(pattern), result, resultlength, &status, str , str1, 6);
733        if(u_strcmp(result, expected)==0)
734            log_verbose("PASS: MessagFormat successful on Select test#2\n");
735        else{
736            log_err("FAIL: Error in MessageFormat on Select test#2\n GOT %s EXPECTED %s\n", austrdup(result),
737                austrdup(expected) );
738        }
739        free(result);
740    }
741    if(U_FAILURE(status)){
742        log_data_err("ERROR: failure in message format on Select test#2 : %s \n", myErrorName(status));
743    }
744    free(str);
745    free(str1);
746}
747
748/* test message format with a choice option */
749static void TestMsgFormatChoice(void)
750{
751    UChar* str;
752    UErrorCode status = U_ZERO_ERROR;
753    UChar *result;
754    UChar pattern[100];
755    UChar expected[100];
756    int32_t resultlength,resultLengthOut;
757
758    str=(UChar*)malloc(sizeof(UChar) * 25);
759    u_uastrcpy(str, "MyDisk");
760    log_verbose("Testing message format with choice test #6\n:");
761    /*
762     * Before ICU 4.8, umsg_xxx() did not detect conflicting argument types,
763     * and this pattern had {0,number,integer} as the inner argument.
764     * The choice argument has kDouble type while {0,number,integer} has kLong (int32_t).
765     * ICU 4.8 and above detects this as an error.
766     * We changed this pattern to work as intended.
767     */
768    u_uastrcpy(pattern, "The disk {1} contains {0,choice,0#no files|1#one file|1<{0,number} files}");
769    u_uastrcpy(expected, "The disk MyDisk contains 100 files");
770    resultlength=0;
771    resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, 100., str);
772    if(status==U_BUFFER_OVERFLOW_ERROR)
773    {
774        status=U_ZERO_ERROR;
775        resultlength=resultLengthOut+1;
776        result=(UChar*)malloc(sizeof(UChar) * resultlength);
777        u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, 100., str);
778        if(u_strcmp(result, expected)==0)
779            log_verbose("PASS: MessagFormat successful on test#6\n");
780        else{
781            log_err("FAIL: Error in MessageFormat on test#6\n GOT %s EXPECTED %s\n", austrdup(result),
782                austrdup(expected) );
783        }
784        free(result);
785    }
786    if(U_FAILURE(status)){
787        log_data_err("ERROR: failure in message format on test#6 : %s (Are you missing data?)\n", myErrorName(status));
788    }
789
790    log_verbose("Testing message format with choice test #7\n:");
791    u_uastrcpy(expected, "The disk MyDisk contains no files");
792    resultlength=0;
793    resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, 0., str);
794    if(status==U_BUFFER_OVERFLOW_ERROR)
795    {
796        status=U_ZERO_ERROR;
797        resultlength=resultLengthOut+1;
798        result=(UChar*)malloc(sizeof(UChar) * resultlength);
799        u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, 0., str);
800
801        if(u_strcmp(result, expected)==0)
802            log_verbose("PASS: MessagFormat successful on test#7\n");
803        else{
804            log_err("FAIL: Error in MessageFormat on test#7\n GOT: %s EXPECTED %s\n", austrdup(result),
805                austrdup(expected) );
806        }
807        free(result);
808    }
809    if(U_FAILURE(status)){
810        log_data_err("ERROR: failure in message format on test#7 : %s (Are you missing data?)\n", myErrorName(status));
811    }
812
813    log_verbose("Testing message format with choice test #8\n:");
814    u_uastrcpy(expected, "The disk MyDisk contains one file");
815    resultlength=0;
816    resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, 1., str);
817    if(status==U_BUFFER_OVERFLOW_ERROR)
818    {
819        status=U_ZERO_ERROR;
820        resultlength=resultLengthOut+1;
821        result=(UChar*)malloc(sizeof(UChar) * resultlength);
822        u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, 1., str);
823
824        if(u_strcmp(result, expected)==0)
825            log_verbose("PASS: MessagFormat successful on test#8\n");
826        else{
827            log_err("FAIL: Error in MessageFormat on test#8\n GOT %s EXPECTED: %s\n", austrdup(result),
828                austrdup(expected) );
829        }
830
831        free(result);
832    }
833    if(U_FAILURE(status)){
834        log_data_err("ERROR: failure in message format on test#8 : %s (Are you missing data?)\n", myErrorName(status));
835    }
836
837    free(str);
838
839}
840
841/*test u_parseMessage() with various test patterns */
842static void TestParseMessage(void)
843{
844    UChar pattern[100];
845    UChar source[100];
846    UErrorCode status = U_ZERO_ERROR;
847    int32_t value;
848    UChar str[10];
849    UChar res[10];
850
851    log_verbose("\nTesting a sample for parse Message test#9\n");
852
853    u_uastrcpy(source, "You deposited an amount of $500.00");
854    u_uastrcpy(pattern, "You {0} an amount of {1,number,currency}");
855    u_uastrcpy(res,"deposited");
856
857    u_parseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, str, &value);
858    if(U_FAILURE(status)){
859        log_data_err("ERROR: failure in parse Message on test#9: %s (Are you missing data?)\n", myErrorName(status));
860    }
861    else if(value==500.00  && u_strcmp(str,res)==0)
862        log_verbose("PASS: parseMessage successful on test#9\n");
863    else
864        log_err("FAIL: Error in parseMessage on test#9 \n");
865
866
867
868    log_verbose("\nTesting a sample for parse Message test#10\n");
869
870    u_uastrcpy(source, "There are 123 files on MyDisk created");
871    u_uastrcpy(pattern, "There are {0,number,integer} files on {1} created");
872    u_uastrcpy(res,"MyDisk");
873
874    u_parseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, &value, str);
875    if(U_FAILURE(status)){
876        log_data_err("ERROR: failure in parse Message on test#10: %s (Are you missing data?)\n", myErrorName(status));
877    }
878    else if(value==123.00 && u_strcmp(str,res)==0)
879        log_verbose("PASS: parseMessage successful on test#10\n");
880    else
881        log_err("FAIL: Error in parseMessage on test#10 \n");
882}
883
884static int32_t CallFormatMessage(const char* locale, UChar* testCasePattern, int32_t patternLength,
885                       UChar* result, int32_t resultLength, UErrorCode *status, ...)
886{
887    int32_t len = 0;
888    va_list ap;
889    va_start(ap, status);
890    len = u_vformatMessage(locale, testCasePattern, patternLength, result, resultLength, ap, status);
891    va_end(ap);
892    return len;
893}
894
895/* Test u_vformatMessage() with various test patterns. */
896static void TestMessageFormatWithValist( void )
897{
898
899    UChar *str;
900    UChar* result;
901    int32_t resultLengthOut,resultlength,i, patternlength;
902    UErrorCode status = U_ZERO_ERROR;
903    UDate d1=1000000000.0;
904
905    ctest_setTimeZone(NULL, &status);
906
907    str=(UChar*)malloc(sizeof(UChar) * 7);
908    u_uastrcpy(str, "MyDisk");
909    resultlength=1;
910    result=(UChar*)malloc(sizeof(UChar) * 1);
911    log_verbose("Testing u_formatMessage90\n");
912    InitStrings();
913    for (i = 0; i < cnt_testCases; i++) {
914        status=U_ZERO_ERROR;
915        patternlength=u_strlen(testCasePatterns[i]);
916        resultLengthOut=CallFormatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength,
917            &status, 1, 3456.00, d1);
918        if(status== U_BUFFER_OVERFLOW_ERROR)
919        {
920            status=U_ZERO_ERROR;
921            resultlength=resultLengthOut+1;
922            result=(UChar*)realloc(result,sizeof(UChar) * resultlength);
923            CallFormatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength,
924                &status, 1, 3456.00, d1);
925        }
926        if(U_FAILURE(status)){
927            log_data_err("ERROR: failure in message format on testcase %d:  %s (Are you missing data?)\n", i, myErrorName(status) );
928        }
929        else if(u_strcmp(result, testResultStrings[i])==0){
930            log_verbose("PASS: MessagFormat successful on testcase : %d\n", i);
931        }
932        else{
933            log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i,
934                austrdup(result), austrdup(testResultStrings[i]) );
935        }
936    }
937    free(result);
938    free(str);
939    FreeStrings();
940
941    ctest_resetTimeZone();
942}
943
944static void CallParseMessage(const char* locale, UChar* pattern, int32_t patternLength,
945                       UChar* source, int32_t sourceLength, UErrorCode *status, ...)
946{
947    va_list ap;
948    va_start(ap, status);
949    u_vparseMessage(locale, pattern, patternLength, source, sourceLength, ap, status);
950    va_end(ap);
951}
952
953/*test u_vparseMessage() with various test patterns */
954static void TestParseMessageWithValist(void)
955{
956    UChar pattern[100];
957    UChar source[100];
958    UErrorCode status = U_ZERO_ERROR;
959    int32_t value;
960    UChar str[10];
961    UChar res[10];
962
963    log_verbose("\nTesting a sample for parse Message test#9\n");
964
965    u_uastrcpy(source, "You deposited an amount of $500.00");
966    u_uastrcpy(pattern, "You {0} an amount of {1,number,currency}");
967    u_uastrcpy(res,"deposited");
968
969    CallParseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, str, &value);
970    if(U_FAILURE(status)){
971        log_data_err("ERROR: failure in parse Message on test#9: %s (Are you missing data?)\n", myErrorName(status));
972    }
973    else if(value==500.00  && u_strcmp(str,res)==0)
974        log_verbose("PASS: parseMessage successful on test#9\n");
975    else
976        log_err("FAIL: Error in parseMessage on test#9\n");
977
978
979    log_verbose("\nTesting a sample for parse Message test#10\n");
980
981    u_uastrcpy(source, "There are 123 files on MyDisk created");
982    u_uastrcpy(pattern, "There are {0,number,integer} files on {1} created");
983    u_uastrcpy(res,"MyDisk");
984
985    CallParseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, &value, str);
986    if(U_FAILURE(status)){
987        log_data_err("ERROR: failure in parse Message on test#10: %s (Are you missing data?)\n", myErrorName(status));
988    }
989    else if(value==123.00 && u_strcmp(str,res)==0)
990        log_verbose("PASS: parseMessage successful on test#10\n");
991    else
992        log_err("FAIL: Error in parseMessage on test#10 \n");
993}
994
995/**
996 * Regression test for ICU4C Jitterbug 904
997 */
998static void TestJ904(void) {
999    UChar pattern[256];
1000    UChar result[256];
1001    UChar string[16];
1002    char cresult[256];
1003    int32_t length;
1004    UErrorCode status = U_ZERO_ERROR;
1005    const char* PAT = "Number {1,number,#0.000}, String {0}, Date {2,date,12:mm:ss.SSS}";
1006    const char* EXP = "Number 0,143, String foo, Date 12:34:56.789";
1007
1008    ctest_setTimeZone(NULL, &status);
1009
1010    u_uastrcpy(string, "foo");
1011    /* Slight hack here -- instead of date pattern HH:mm:ss.SSS, use
1012     * 12:mm:ss.SSS.  Why?  So this test generates the same output --
1013     * "12:34:56.789" -- regardless of time zone (as long as we aren't
1014     * in one of the 30 minute offset zones!). */
1015    u_uastrcpy(pattern, PAT);
1016    length = u_formatMessage("nl", pattern, u_strlen(pattern),
1017                             result, 256, &status,
1018                             string, 1/7.0,
1019                             789.0+1000*(56+60*(34+60*12)));
1020    (void)length;   /* Suppress set but not used warning. */
1021
1022    u_austrncpy(cresult, result, sizeof(cresult));
1023
1024    /* This test passes if it DOESN'T CRASH.  However, we test the
1025     * output anyway.  If the string doesn't match in the date part,
1026     * check to see that the machine doesn't have an unusual time zone
1027     * offset, that is, one with a non-zero minutes/seconds offset
1028     * from GMT -- see above. */
1029    if (strcmp(cresult, EXP) == 0) {
1030        log_verbose("Ok: \"%s\"\n", cresult);
1031    } else {
1032        log_data_err("FAIL: got \"%s\", expected \"%s\" -> %s (Are you missing data?)\n", cresult, EXP, u_errorName(status));
1033    }
1034
1035    ctest_resetTimeZone();
1036}
1037
1038static void OpenMessageFormatTest(void)
1039{
1040    UMessageFormat *f1, *f2, *f3;
1041    UChar pattern[256];
1042    UChar result[256];
1043    char cresult[256];
1044    UParseError parseError;
1045    const char* locale = "hi_IN";
1046    char* retLoc;
1047    const char* PAT = "Number {1,number,#0.000}, String {0}, Date {2,date,12:mm:ss.SSS}";
1048    int32_t length=0;
1049    UErrorCode status = U_ZERO_ERROR;
1050
1051    u_uastrncpy(pattern, PAT, UPRV_LENGTHOF(pattern));
1052
1053    /* Test umsg_open                   */
1054    f1 = umsg_open(pattern,length,NULL,NULL,&status);
1055
1056    if(U_FAILURE(status))
1057    {
1058        log_err("umsg_open failed with pattern %s. Error: \n", PAT, u_errorName(status));
1059        return;
1060    }
1061
1062    /* Test umsg_open with parse error  */
1063    status = U_ZERO_ERROR;
1064    f2 = umsg_open(pattern,length,NULL,&parseError,&status);
1065
1066    if(U_FAILURE(status))
1067    {
1068        log_err("umsg_open with parseError failed with pattern %s. Error: %s\n", PAT, u_errorName(status));
1069        return;
1070    }
1071
1072    /* Test umsg_clone                  */
1073    status = U_ZERO_ERROR;
1074    f3 = umsg_clone(f1,&status);
1075    if(U_FAILURE(status))
1076    {
1077        log_err("umsg_clone failed. Error %s \n", u_errorName(status));
1078    }
1079
1080    /* Test umsg_setLocale              */
1081    umsg_setLocale(f1,locale);
1082    /* Test umsg_getLocale              */
1083    retLoc = (char*)umsg_getLocale(f1);
1084    if(strcmp(retLoc,locale)!=0)
1085    {
1086        log_err("umsg_setLocale and umsg_getLocale methods failed. Expected:%s Got: %s \n", locale, retLoc);
1087    }
1088
1089    /* Test umsg_applyPattern           */
1090    status = U_ZERO_ERROR;
1091    umsg_applyPattern(f1,pattern,(int32_t)strlen(PAT),NULL,&status);
1092    if(U_FAILURE(status))
1093    {
1094        log_data_err("umsg_applyPattern failed. Error %s (Are you missing data?)\n",u_errorName(status));
1095    }
1096
1097    /* Test umsg_toPattern              */
1098    umsg_toPattern(f1,result,256,&status);
1099    if(U_FAILURE(status) ){
1100        log_data_err("umsg_toPattern method failed. Error: %s (Are you missing data?)\n",u_errorName(status));
1101    } else {
1102        if(u_strcmp(result,pattern)!=0){
1103            u_UCharsToChars(result,cresult,256);
1104            log_err("umsg_toPattern method failed. Expected: %s Got: %s \n",PAT,cresult);
1105        }
1106    }
1107    /* umsg_format umsg_parse */
1108
1109    umsg_close(f1);
1110    umsg_close(f2);
1111    umsg_close(f3);
1112}
1113
1114static void MessageLength(void)
1115{
1116    UErrorCode status = U_ZERO_ERROR;
1117    const char patChars[] = {"123{0}456{0}"};
1118    const char expectedChars[] = {"123abc"};
1119    UChar pattern[sizeof(patChars)];
1120    UChar arg[] = {0x61,0x62,0x63,0};
1121    UChar result[128] = {0};
1122    UChar expected[sizeof(expectedChars)];
1123
1124    u_uastrncpy(pattern, patChars, UPRV_LENGTHOF(pattern));
1125    u_uastrncpy(expected, expectedChars, UPRV_LENGTHOF(expected));
1126
1127    u_formatMessage("en_US", pattern, 6, result, UPRV_LENGTHOF(result), &status, arg);
1128    if (U_FAILURE(status)) {
1129        log_err("u_formatMessage method failed. Error: %s \n",u_errorName(status));
1130    }
1131    if (u_strcmp(result, expected) != 0) {
1132        log_err("u_formatMessage didn't return expected result\n");
1133    }
1134}
1135
1136static void TestMessageWithUnusedArgNumber(void) {
1137    UErrorCode errorCode = U_ZERO_ERROR;
1138    U_STRING_DECL(pattern, "abc {1} def", 11);
1139    UChar x[2] = { 0x78, 0 };  // "x"
1140    UChar y[2] = { 0x79, 0 };  // "y"
1141    U_STRING_DECL(expected, "abc y def", 9);
1142    UChar result[20];
1143    int32_t length;
1144
1145    U_STRING_INIT(pattern, "abc {1} def", 11);
1146    U_STRING_INIT(expected, "abc y def", 9);
1147    length = u_formatMessage("en", pattern, -1, result, UPRV_LENGTHOF(result), &errorCode, x, y);
1148    if (U_FAILURE(errorCode) || length != u_strlen(expected) || u_strcmp(result, expected) != 0) {
1149        log_err("u_formatMessage(pattern with only {1}, 2 args) failed: result length %d, UErrorCode %s \n",
1150                (int)length, u_errorName(errorCode));
1151    }
1152}
1153
1154static void TestErrorChaining(void) {
1155    UErrorCode status = U_USELESS_COLLATOR_ERROR;
1156
1157    umsg_open(NULL, 0, NULL, NULL, &status);
1158    umsg_applyPattern(NULL, NULL, 0, NULL, &status);
1159    umsg_toPattern(NULL, NULL, 0, &status);
1160    umsg_clone(NULL, &status);
1161    umsg_format(NULL, NULL, 0, &status);
1162    umsg_parse(NULL, NULL, 0, NULL, &status);
1163    umsg_close(NULL);
1164
1165    /* All of this code should have done nothing. */
1166    if (status != U_USELESS_COLLATOR_ERROR) {
1167        log_err("Status got changed to %s\n", u_errorName(status));
1168    }
1169
1170    status = U_ZERO_ERROR;
1171    umsg_open(NULL, 0, NULL, 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));
1174    }
1175    status = U_ZERO_ERROR;
1176    umsg_applyPattern(NULL, NULL, 0, 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));
1179    }
1180    status = U_ZERO_ERROR;
1181    umsg_toPattern(NULL, NULL, 0, &status);
1182    if (status != U_ILLEGAL_ARGUMENT_ERROR) {
1183        log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status));
1184    }
1185    status = U_ZERO_ERROR;
1186    umsg_clone(NULL, &status);
1187    if (status != U_ILLEGAL_ARGUMENT_ERROR) {
1188        log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status));
1189    }
1190}
1191
1192void addMsgForTest(TestNode** root);
1193
1194void addMsgForTest(TestNode** root)
1195{
1196    addTest(root, &OpenMessageFormatTest, "tsformat/cmsgtst/OpenMessageFormatTest");
1197    addTest(root, &MessageFormatTest, "tsformat/cmsgtst/MessageFormatTest");
1198    addTest(root, &TestSampleMessageFormat, "tsformat/cmsgtst/TestSampleMessageFormat");
1199    addTest(root, &TestSampleFormatAndParse, "tsformat/cmsgtst/TestSampleFormatAndParse");
1200    addTest(root, &TestSampleFormatAndParseWithError, "tsformat/cmsgtst/TestSampleFormatAndParseWithError");
1201    addTest(root, &TestNewFormatAndParseAPI, "tsformat/cmsgtst/TestNewFormatAndParseAPI");
1202    addTest(root, &TestMsgFormatChoice, "tsformat/cmsgtst/TestMsgFormatChoice");
1203    addTest(root, &TestParseMessage, "tsformat/cmsgtst/TestParseMessage");
1204    addTest(root, &TestMessageFormatWithValist, "tsformat/cmsgtst/TestMessageFormatWithValist");
1205    addTest(root, &TestParseMessageWithValist, "tsformat/cmsgtst/TestParseMessageWithValist");
1206    addTest(root, &TestJ904, "tsformat/cmsgtst/TestJ904");
1207    addTest(root, &MessageLength, "tsformat/cmsgtst/MessageLength");
1208    addTest(root, &TestMessageWithUnusedArgNumber, "tsformat/cmsgtst/TestMessageWithUnusedArgNumber");
1209    addTest(root, &TestErrorChaining, "tsformat/cmsgtst/TestErrorChaining");
1210    addTest(root, &TestMsgFormatSelect, "tsformat/cmsgtst/TestMsgFormatSelect");
1211}
1212
1213#endif /* #if !UCONFIG_NO_FORMATTING */
1214