]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/cintltst/cmsgtst.c
ICU-64252.0.1.tar.gz
[apple/icu.git] / icuSources / test / cintltst / cmsgtst.c
index 0d759105daf940f1e1ff3af595177678bf77434f..167300924d95a52f49b081f14e6303383600bf40 100644 (file)
@@ -1,6 +1,8 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /********************************************************************
  * COPYRIGHT: 
- * Copyright (c) 1997-2010, International Business Machines Corporation and
+ * Copyright (c) 1997-2016, International Business Machines Corporation and
  * others. All Rights Reserved.
  ********************************************************************
  *
@@ -27,6 +29,7 @@
 #include "cintltst.h"
 #include "cmsgtst.h"
 #include "cformtst.h"
+#include "cmemory.h"
 
 static const char* const txt_testCasePatterns[] = {
    "Quotes '', '{', a {0,number,integer} '{'0}",
@@ -87,6 +90,9 @@ static void FreeStrings( void )
     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;
@@ -96,6 +102,7 @@ static UBool returnsNullForType(int firstParam, ...) {
     va_end(marker);
     return isNULL;
 }
+#endif
 
 /* Test u_formatMessage() with various test patterns() */
 static void MessageFormatTest( void ) 
@@ -181,7 +188,7 @@ static void MessageFormatTest( void )
         UMessageFormat formatter = umsg_open(testCasePatterns[0],patternLength,"en_US",NULL,&ec);
 
         if(U_FAILURE(ec)){
-            log_data_err("umsg_open() failed for testCasePattens[%d]. -> %s (Are you missing data?)\n",i, u_errorName(ec));
+            log_data_err("umsg_open() failed for testCasePattens[0]. -> %s (Are you missing data?)\n", u_errorName(ec));
             return;
         }
         for(i = 0;i<cnt_testCases; i++){
@@ -192,8 +199,9 @@ static void MessageFormatTest( void )
             UDate d2=0;
     
             result=NULL;
-            patternLength = u_strlen(testCasePatterns[i]);
-            
+            // Alternate between specifying the length and using NUL-termination.
+            patternLength = ((i & 1) == 0) ? u_strlen(testCasePatterns[i]) : -1;
+
             umsg_applyPattern(formatter,testCasePatterns[i],patternLength,&parseError,&ec);
             if(U_FAILURE(ec)){
                 log_err("umsg_applyPattern() failed for testCasePattens[%d].\n",i);
@@ -219,7 +227,7 @@ static void MessageFormatTest( void )
                         austrdup(result), austrdup(testResultStrings[i]) );
                 }
 
-#if defined (U_DARWIN)  /* add platforms here .. */
+#if (U_PLATFORM == U_PF_LINUX) /* add platforms here .. */
                 log_verbose("Skipping potentially crashing test for mismatched varargs.\n");
 #else
                 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__); 
@@ -367,13 +375,13 @@ static void TestSampleMessageFormat(void)
 static void TestNewFormatAndParseAPI(void)
 {
 
-    UChar *result, tzID[4], str[25];
+    UChar *result = NULL, tzID[4], str[25];
     UChar pattern[100];
     UChar expected[100];
     int32_t resultLengthOut, resultlength;
     UCalendar *cal;
     UDate d1,d;
-    UDateFormat *def1;
+    UDateFormat *def1 = NULL;
     UErrorCode status = U_ZERO_ERROR;
     int32_t value = 0;
     UChar ret[30];
@@ -390,13 +398,12 @@ static void TestNewFormatAndParseAPI(void)
     cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
     if(U_FAILURE(status)){
         log_data_err("error in ucal_open caldef : %s - (Are you missing data?)\n", myErrorName(status) );
-        return;
+        goto cleanup;
     }
     ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status);
     d1=ucal_getMillis(cal, &status);
     if(U_FAILURE(status)){
-            log_err("Error: failure in get millis: %s\n", myErrorName(status) );
-            return;
+        log_err("Error: failure in get millis: %s\n", myErrorName(status) );
     }
     
     log_verbose("\nTesting with pattern test#4");
@@ -406,7 +413,7 @@ static void TestNewFormatAndParseAPI(void)
     fmt = umsg_open(pattern,u_strlen(pattern),"en_US",&parseError,&status);
     if(U_FAILURE(status)){
         log_data_err("error in umsg_open  : %s (Are you missing data?)\n", u_errorName(status) );
-        return;
+        goto cleanup;
     }
     result=(UChar*)malloc(sizeof(UChar) * resultlength);
     
@@ -455,6 +462,7 @@ static void TestNewFormatAndParseAPI(void)
                 austrdup(myDateFormat(def1,d)), austrdup(myDateFormat(def1,d1)) );
         }
     }
+cleanup:
     umsg_close(fmt);
     udat_close(def1);
     ucal_close(cal);
@@ -475,7 +483,7 @@ static void TestSampleFormatAndParseWithError(void)
     int32_t resultLengthOut, resultlength;
     UCalendar *cal;
     UDate d1,d;
-    UDateFormat *def1;
+    UDateFormat *def1 = NULL;
     UErrorCode status = U_ZERO_ERROR;
     int32_t value = 0;
     UChar ret[30];
@@ -515,6 +523,7 @@ static void TestSampleFormatAndParseWithError(void)
     }
     if(U_FAILURE(status)){
         log_data_err("ERROR: failure in message format test#4: %s (Are you missing data?)\n", myErrorName(status));
+        goto cleanup;
     }
     else if(u_strcmp(result, expected)==0)
         log_verbose("PASS: MessagFormat successful on test#4\n");
@@ -549,6 +558,7 @@ static void TestSampleFormatAndParseWithError(void)
                 austrdup(myDateFormat(def1,d)), austrdup(myDateFormat(def1,d1)) );
         }
     }
+cleanup:
     udat_close(def1);
     ucal_close(cal);
 
@@ -585,11 +595,12 @@ static void TestSampleFormatAndParse(void)
     cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
     if(U_FAILURE(status)){
         log_data_err("error in ucal_open caldef : %s - (Are you missing data?)\n", myErrorName(status) );
+        return;
     }
     ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status);
     d1=ucal_getMillis(cal, &status);
     if(U_FAILURE(status)){
-            log_data_err("Error: failure in get millis: %s - (Are you missing data?)\n", myErrorName(status) );
+        log_data_err("Error: failure in get millis: %s - (Are you missing data?)\n", myErrorName(status) );
     }
     
     log_verbose("\nTesting with pattern test#4");
@@ -608,6 +619,7 @@ static void TestSampleFormatAndParse(void)
     }
     if(U_FAILURE(status)){
         log_data_err("ERROR: failure in message format test#4: %s (Are you missing data?)\n", myErrorName(status));
+        return;
     }
     else if(u_strcmp(result, expected)==0)
         log_verbose("PASS: MessagFormat successful on test#4\n");
@@ -707,7 +719,7 @@ static void TestMsgFormatSelect(void)
         status=U_ZERO_ERROR;
         resultlength=resultLengthOut+1;
         result=(UChar*)malloc(sizeof(UChar) * resultlength);
-        u_formatMessage( "fr", pattern, u_strlen(pattern), result, resultlength, &status, str , str1);
+        u_formatMessage( "fr", pattern, u_strlen(pattern), result, resultlength, &status, str , str1, 6);
         if(u_strcmp(result, expected)==0)
             log_verbose("PASS: MessagFormat successful on Select test#2\n");
         else{
@@ -736,8 +748,14 @@ static void TestMsgFormatChoice(void)
     str=(UChar*)malloc(sizeof(UChar) * 25);
     u_uastrcpy(str, "MyDisk");
     log_verbose("Testing message format with choice test #6\n:");
-    /*There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}.*/
-    u_uastrcpy(pattern, "The disk {1} contains {0,choice,0#no files|1#one file|1<{0,number,integer} files}");
+    /*
+     * Before ICU 4.8, umsg_xxx() did not detect conflicting argument types,
+     * and this pattern had {0,number,integer} as the inner argument.
+     * The choice argument has kDouble type while {0,number,integer} has kLong (int32_t).
+     * ICU 4.8 and above detects this as an error.
+     * We changed this pattern to work as intended.
+     */
+    u_uastrcpy(pattern, "The disk {1} contains {0,choice,0#no files|1#one file|1<{0,number} files}");
     u_uastrcpy(expected, "The disk MyDisk contains 100 files");
     resultlength=0;
     resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, 100., str);
@@ -989,6 +1007,7 @@ static void TestJ904(void) {
                              result, 256, &status,
                              string, 1/7.0,
                              789.0+1000*(56+60*(34+60*12)));
+    (void)length;   /* Suppress set but not used warning. */
 
     u_austrncpy(cresult, result, sizeof(cresult));
 
@@ -1019,7 +1038,7 @@ static void OpenMessageFormatTest(void)
     int32_t length=0;
     UErrorCode status = U_ZERO_ERROR;
 
-    u_uastrncpy(pattern, PAT, sizeof(pattern)/sizeof(pattern[0]));
+    u_uastrncpy(pattern, PAT, UPRV_LENGTHOF(pattern));
 
     /* Test umsg_open                   */
     f1 = umsg_open(pattern,length,NULL,NULL,&status);
@@ -1092,10 +1111,10 @@ static void MessageLength(void)
     UChar result[128] = {0};
     UChar expected[sizeof(expectedChars)];
 
-    u_uastrncpy(pattern, patChars, sizeof(pattern)/sizeof(pattern[0]));
-    u_uastrncpy(expected, expectedChars, sizeof(expected)/sizeof(expected[0]));
+    u_uastrncpy(pattern, patChars, UPRV_LENGTHOF(pattern));
+    u_uastrncpy(expected, expectedChars, UPRV_LENGTHOF(expected));
 
-    u_formatMessage("en_US", pattern, 6, result, sizeof(result)/sizeof(result[0]), &status, arg);
+    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));
     }
@@ -1104,6 +1123,24 @@ static void MessageLength(void)
     }
 }
 
+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;
 
@@ -1158,6 +1195,7 @@ void addMsgForTest(TestNode** root)
     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");
 }