// © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html /******************************************************************** * COPYRIGHT: * Copyright (c) 1997-2016, International Business Machines Corporation and * others. All Rights Reserved. ******************************************************************** * * File CMSGTST.C * * Modification History: * Name Description * Madhu Katragadda Creation ********************************************************************/ /* C API TEST FOR MESSAGE FORMAT */ #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING #include #include #include #include "unicode/uloc.h" #include "unicode/umsg.h" #include "unicode/udat.h" #include "unicode/umsg.h" #include "unicode/ustring.h" #include "cintltst.h" #include "cmsgtst.h" #include "cformtst.h" #include "cmemory.h" static const char* const txt_testCasePatterns[] = { "Quotes '', '{', a {0,number,integer} '{'0}", "Quotes '', '{', a {0,number,integer} '{'0}", "You deposited {0,number,integer} times an amount of {1,number,currency} on {2,date,short}", "'{'2,time,full}, for {1, number }, {0,number,integer} is {2,time,full} and full date is {2,date,full}", "'{'1,number,percent} for {0,number,integer} is {1,number,percent}", }; static const char* const txt_testResultStrings[] = { "Quotes ', {, a 1 {0}", "Quotes ', {, a 1 {0}", "You deposited 1 times an amount of $3,456.00 on 1/12/70", "{2,time,full}, for 3,456, 1 is 5:46:40 AM Pacific Standard Time and full date is Monday, January 12, 1970", "{1,number,percent} for 1 is 345,600%" }; const int32_t cnt_testCases = 5; static UChar* testCasePatterns[5]; static UChar* testResultStrings[5]; static UBool strings_initialized = FALSE; /* function used to create the test patterns for testing Message formatting */ static void InitStrings( void ) { int32_t i; if (strings_initialized) return; for (i=0; i < cnt_testCases; i++ ) { uint32_t strSize = (uint32_t)strlen(txt_testCasePatterns[i]) + 1; testCasePatterns[i]=(UChar*)malloc(sizeof(UChar) * strSize); u_uastrncpy(testCasePatterns[i], txt_testCasePatterns[i], strSize); } for (i=0; i < cnt_testCases; i++ ) { uint32_t strSize = (uint32_t)strlen(txt_testResultStrings[i]) + 1; testResultStrings[i] = (UChar*)malloc(sizeof(UChar) * strSize); u_uastrncpy(testResultStrings[i], txt_testResultStrings[i], strSize); } strings_initialized = TRUE; } static void FreeStrings( void ) { int32_t i; if (!strings_initialized) return; for (i=0; i < cnt_testCases; i++ ) { free(testCasePatterns[i]); } for (i=0; i < cnt_testCases; i++ ) { free(testResultStrings[i]); } strings_initialized = FALSE; } #if (U_PLATFORM == U_PF_LINUX) /* add platforms here .. */ /* Keep the #if above in sync with the one below that has the same "add platforms here .." comment. */ #else /* Platform dependent test to detect if this type will return NULL when interpreted as a pointer. */ static UBool returnsNullForType(int firstParam, ...) { UBool isNULL; va_list marker; va_start(marker, firstParam); isNULL = (UBool)(va_arg(marker, void*) == NULL); va_end(marker); return isNULL; } #endif /* Test u_formatMessage() with various test patterns() */ static void MessageFormatTest( void ) { UChar *str; UChar* result; int32_t resultLengthOut,resultlength,i, patternlength; UErrorCode status = U_ZERO_ERROR; UDate d1=1000000000.0; ctest_setTimeZone(NULL, &status); str=(UChar*)malloc(sizeof(UChar) * 7); u_uastrncpy(str, "MyDisk", 7); resultlength=1; result=(UChar*)malloc(sizeof(UChar) * 1); log_verbose("Testing u_formatMessage()\n"); InitStrings(); for (i = 0; i < cnt_testCases; i++) { status=U_ZERO_ERROR; patternlength=u_strlen(testCasePatterns[i]); resultLengthOut=u_formatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength, &status, 1, 3456.00, d1); if(status== U_BUFFER_OVERFLOW_ERROR) { status=U_ZERO_ERROR; resultlength=resultLengthOut+1; result=(UChar*)realloc(result,sizeof(UChar) * resultlength); u_formatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength, &status, 1, 3456.00, d1); } if(U_FAILURE(status)){ log_data_err("ERROR: failure in message format on testcase %d: %s (Are you missing data?)\n", i, myErrorName(status) ); continue; } if(u_strcmp(result, testResultStrings[i])==0){ log_verbose("PASS: MessagFormat successful on testcase : %d\n", i); } else{ log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i, austrdup(result), austrdup(testResultStrings[i]) ); } } free(result); result = NULL; free(str); { for (i = 0; i < cnt_testCases; i++) { UParseError parseError; status=U_ZERO_ERROR; patternlength=u_strlen(testCasePatterns[i]); resultlength=0; resultLengthOut=u_formatMessageWithError( "en_US",testCasePatterns[i], patternlength, result, resultlength, &parseError,&status, 1, 3456.00, d1); if(status== U_BUFFER_OVERFLOW_ERROR) { status=U_ZERO_ERROR; resultlength=resultLengthOut+1; result=(UChar*)malloc(sizeof(UChar) * resultlength); u_formatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength, &status, 1, 3456.00, d1); } if(U_FAILURE(status)){ log_data_err("ERROR: failure in message format on testcase %d: %s (Are you missing data?)\n", i, myErrorName(status) ); continue; } if(u_strcmp(result, testResultStrings[i])==0){ log_verbose("PASS: MessagFormat successful on testcase : %d\n", i); } else{ log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i, austrdup(result), austrdup(testResultStrings[i]) ); } free(result); result=NULL; } } { UErrorCode ec = U_ZERO_ERROR; int32_t patternLength = u_strlen(testCasePatterns[0]); UMessageFormat formatter = umsg_open(testCasePatterns[0],patternLength,"en_US",NULL,&ec); if(U_FAILURE(ec)){ log_data_err("umsg_open() failed for testCasePattens[0]. -> %s (Are you missing data?)\n", u_errorName(ec)); umsg_close(formatter); return; } for(i = 0;i %s (Are you missing data?)\n", cresult, EXP, u_errorName(status)); } ctest_resetTimeZone(); } static void OpenMessageFormatTest(void) { UMessageFormat *f1, *f2, *f3; UChar pattern[256]; UChar result[256]; char cresult[256]; UParseError parseError; const char* locale = "hi_IN"; char* retLoc; const char* PAT = "Number {1,number,#0.000}, String {0}, Date {2,date,12:mm:ss.SSS}"; int32_t length=0; UErrorCode status = U_ZERO_ERROR; u_uastrncpy(pattern, PAT, UPRV_LENGTHOF(pattern)); /* Test umsg_open */ f1 = umsg_open(pattern,length,NULL,NULL,&status); if(U_FAILURE(status)) { log_err("umsg_open failed with pattern %s. Error: \n", PAT, u_errorName(status)); return; } /* Test umsg_open with parse error */ status = U_ZERO_ERROR; f2 = umsg_open(pattern,length,NULL,&parseError,&status); if(U_FAILURE(status)) { log_err("umsg_open with parseError failed with pattern %s. Error: %s\n", PAT, u_errorName(status)); return; } /* Test umsg_clone */ status = U_ZERO_ERROR; f3 = umsg_clone(f1,&status); if(U_FAILURE(status)) { log_err("umsg_clone failed. Error %s \n", u_errorName(status)); } /* Test umsg_setLocale */ umsg_setLocale(f1,locale); /* Test umsg_getLocale */ retLoc = (char*)umsg_getLocale(f1); if(strcmp(retLoc,locale)!=0) { log_err("umsg_setLocale and umsg_getLocale methods failed. Expected:%s Got: %s \n", locale, retLoc); } /* Test umsg_applyPattern */ status = U_ZERO_ERROR; umsg_applyPattern(f1,pattern,(int32_t)strlen(PAT),NULL,&status); if(U_FAILURE(status)) { log_data_err("umsg_applyPattern failed. Error %s (Are you missing data?)\n",u_errorName(status)); } /* Test umsg_toPattern */ umsg_toPattern(f1,result,256,&status); if(U_FAILURE(status) ){ log_data_err("umsg_toPattern method failed. Error: %s (Are you missing data?)\n",u_errorName(status)); } else { if(u_strcmp(result,pattern)!=0){ u_UCharsToChars(result,cresult,256); log_err("umsg_toPattern method failed. Expected: %s Got: %s \n",PAT,cresult); } } /* umsg_format umsg_parse */ umsg_close(f1); umsg_close(f2); umsg_close(f3); } static void MessageLength(void) { UErrorCode status = U_ZERO_ERROR; const char patChars[] = {"123{0}456{0}"}; const char expectedChars[] = {"123abc"}; UChar pattern[sizeof(patChars)]; UChar arg[] = {0x61,0x62,0x63,0}; UChar result[128] = {0}; UChar expected[sizeof(expectedChars)]; u_uastrncpy(pattern, patChars, UPRV_LENGTHOF(pattern)); u_uastrncpy(expected, expectedChars, UPRV_LENGTHOF(expected)); u_formatMessage("en_US", pattern, 6, result, UPRV_LENGTHOF(result), &status, arg); if (U_FAILURE(status)) { log_err("u_formatMessage method failed. Error: %s \n",u_errorName(status)); } if (u_strcmp(result, expected) != 0) { log_err("u_formatMessage didn't return expected result\n"); } } static void TestMessageWithUnusedArgNumber(void) { UErrorCode errorCode = U_ZERO_ERROR; U_STRING_DECL(pattern, "abc {1} def", 11); UChar x[2] = { 0x78, 0 }; // "x" UChar y[2] = { 0x79, 0 }; // "y" U_STRING_DECL(expected, "abc y def", 9); UChar result[20]; int32_t length; U_STRING_INIT(pattern, "abc {1} def", 11); U_STRING_INIT(expected, "abc y def", 9); length = u_formatMessage("en", pattern, -1, result, UPRV_LENGTHOF(result), &errorCode, x, y); if (U_FAILURE(errorCode) || length != u_strlen(expected) || u_strcmp(result, expected) != 0) { log_err("u_formatMessage(pattern with only {1}, 2 args) failed: result length %d, UErrorCode %s \n", (int)length, u_errorName(errorCode)); } } static void TestErrorChaining(void) { UErrorCode status = U_USELESS_COLLATOR_ERROR; umsg_open(NULL, 0, NULL, NULL, &status); umsg_applyPattern(NULL, NULL, 0, NULL, &status); umsg_toPattern(NULL, NULL, 0, &status); umsg_clone(NULL, &status); umsg_format(NULL, NULL, 0, &status); umsg_parse(NULL, NULL, 0, NULL, &status); umsg_close(NULL); /* All of this code should have done nothing. */ if (status != U_USELESS_COLLATOR_ERROR) { log_err("Status got changed to %s\n", u_errorName(status)); } status = U_ZERO_ERROR; umsg_open(NULL, 0, NULL, NULL, &status); if (status != U_ILLEGAL_ARGUMENT_ERROR) { log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status)); } status = U_ZERO_ERROR; umsg_applyPattern(NULL, NULL, 0, NULL, &status); if (status != U_ILLEGAL_ARGUMENT_ERROR) { log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status)); } status = U_ZERO_ERROR; umsg_toPattern(NULL, NULL, 0, &status); if (status != U_ILLEGAL_ARGUMENT_ERROR) { log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status)); } status = U_ZERO_ERROR; umsg_clone(NULL, &status); if (status != U_ILLEGAL_ARGUMENT_ERROR) { log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status)); } } void addMsgForTest(TestNode** root); void addMsgForTest(TestNode** root) { addTest(root, &OpenMessageFormatTest, "tsformat/cmsgtst/OpenMessageFormatTest"); addTest(root, &MessageFormatTest, "tsformat/cmsgtst/MessageFormatTest"); addTest(root, &TestSampleMessageFormat, "tsformat/cmsgtst/TestSampleMessageFormat"); addTest(root, &TestSampleFormatAndParse, "tsformat/cmsgtst/TestSampleFormatAndParse"); addTest(root, &TestSampleFormatAndParseWithError, "tsformat/cmsgtst/TestSampleFormatAndParseWithError"); addTest(root, &TestNewFormatAndParseAPI, "tsformat/cmsgtst/TestNewFormatAndParseAPI"); addTest(root, &TestMsgFormatChoice, "tsformat/cmsgtst/TestMsgFormatChoice"); addTest(root, &TestParseMessage, "tsformat/cmsgtst/TestParseMessage"); addTest(root, &TestMessageFormatWithValist, "tsformat/cmsgtst/TestMessageFormatWithValist"); addTest(root, &TestParseMessageWithValist, "tsformat/cmsgtst/TestParseMessageWithValist"); addTest(root, &TestJ904, "tsformat/cmsgtst/TestJ904"); addTest(root, &MessageLength, "tsformat/cmsgtst/MessageLength"); addTest(root, &TestMessageWithUnusedArgNumber, "tsformat/cmsgtst/TestMessageWithUnusedArgNumber"); addTest(root, &TestErrorChaining, "tsformat/cmsgtst/TestErrorChaining"); addTest(root, &TestMsgFormatSelect, "tsformat/cmsgtst/TestMsgFormatSelect"); } #endif /* #if !UCONFIG_NO_FORMATTING */