]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/cintltst/cpluralrulestest.c
ICU-59173.0.1.tar.gz
[apple/icu.git] / icuSources / test / cintltst / cpluralrulestest.c
index 3f33d2347366734f897d8e4060876c906bfe1d44..e1ffcdb1267a01090d2a41afe9adddf6a0482b70 100644 (file)
@@ -1,5 +1,7 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /********************************************************************
- * Copyright (c) 2011-2012, International Business Machines Corporation
+ * Copyright (c) 2011-2014, International Business Machines Corporation
  * and others. All Rights Reserved.
  ********************************************************************/
 /* C API TEST FOR PLURAL RULES */
 
 #include "unicode/upluralrules.h"
 #include "unicode/ustring.h"
+#include "unicode/uenum.h"
 #include "cintltst.h"
 #include "cmemory.h"
+#include "cstring.h"
 
 static void TestPluralRules(void);
 static void TestOrdinalRules(void);
+static void TestGetKeywords(void);
 
 void addPluralRulesTest(TestNode** root);
 
@@ -24,37 +29,55 @@ void addPluralRulesTest(TestNode** root)
 {
     TESTCASE(TestPluralRules);
     TESTCASE(TestOrdinalRules);
+    TESTCASE(TestGetKeywords);
 }
 
 typedef struct {
     const char * locale;
     double       number;
     const char * keywordExpected;
+    const char * keywordExpectedForDecimals;
 } PluralRulesTestItem;
 
 /* Just a small set of tests for now, other functionality is tested in the C++ tests */
 static const PluralRulesTestItem testItems[] = {
-    { "en",   0, "other" },
-    { "en", 0.5, "other" },
-    { "en",   1, "one" },
-    { "en", 1.5, "other" },
-    { "en",   2, "other" },
-    { "fr",   0, "one" },
-    { "fr", 0.5, "one" },
-    { "fr",   1, "one" },
-    { "fr", 1.5, "one" },
-    { "fr",   2, "other" },
-    { "ru",   0, "many" },
-    { "ru", 0.5, "other" },
-    { "ru",   1, "one" },
-    { "ru", 1.5, "other" },
-    { "ru",   2, "few" },
-    { "ru",   5, "many" },
-    { "ru",  10, "many" },
-    { "ru",  11, "many" },
-    { NULL,   0, NULL }
+    { "en",   0, "other", "other" },
+    { "en", 0.5, "other", "other" },
+    { "en",   1, "one",   "other" },
+    { "en", 1.5, "other", "other" },
+    { "en",   2, "other", "other" },
+
+    { "pt_PT",   0, "other", "other" },
+    { "pt_PT", 0.5, "other", "other" },
+    { "pt_PT",   1, "one",   "other" },
+    { "pt_PT", 1.5, "other", "other" },
+    { "pt_PT",   2, "other", "other" },
+
+    { "pt_BR",   0, "one",   "one" },
+    { "pt_BR", 0.5, "one",   "one" },
+    { "pt_BR",   1, "one",   "one" },
+    { "pt_BR", 1.5, "one",   "one" },
+    { "pt_BR",   2, "other", "other" },
+
+    { "fr",   0, "one",   "one" },
+    { "fr", 0.5, "one",   "one" },
+    { "fr",   1, "one",   "one" },
+    { "fr", 1.5, "one",   "one" },
+    { "fr",   2, "other", "other" },
+
+    { "ru",   0, "many",  "other" },
+    { "ru", 0.5, "other", "other" },
+    { "ru",   1, "one",   "other" },
+    { "ru", 1.5, "other", "other" },
+    { "ru",   2, "few",   "other" },
+    { "ru",   5, "many",  "other" },
+    { "ru",  10, "many",  "other" },
+    { "ru",  11, "many",  "other" },
+    { NULL,   0, NULL,    NULL }
 };
 
+static const UChar twoDecimalPat[] = { 0x23,0x30,0x2E,0x30,0x30,0 }; /* "#0.00" */
+
 enum {
     kKeywordBufLen = 32
 };
@@ -67,6 +90,7 @@ static void TestPluralRules()
         UErrorCode status = U_ZERO_ERROR;
         UPluralRules* uplrules = uplrules_open(testItemPtr->locale, &status);
         if ( U_SUCCESS(status) ) {
+            UNumberFormat* unumfmt;
             UChar keyword[kKeywordBufLen];
             UChar keywordExpected[kKeywordBufLen];
             int32_t keywdLen = uplrules_select(uplrules, testItemPtr->number, keyword, kKeywordBufLen, &status);
@@ -84,6 +108,30 @@ static void TestPluralRules()
                 log_err("FAIL: uplrules_select for locale %s, number %.1f: %s\n",
                         testItemPtr->locale, testItemPtr->number, myErrorName(status) );
             }
+
+            status = U_ZERO_ERROR;
+            unumfmt = unum_open(UNUM_PATTERN_DECIMAL, twoDecimalPat, -1, testItemPtr->locale, NULL, &status);
+            if ( U_SUCCESS(status) ) {
+                keywdLen = uplrules_selectWithFormat(uplrules, testItemPtr->number, unumfmt, keyword, kKeywordBufLen, &status);
+                if (keywdLen >= kKeywordBufLen) {
+                    keyword[kKeywordBufLen-1] = 0;
+                }
+                if ( U_SUCCESS(status) ) {
+                    u_unescape(testItemPtr->keywordExpectedForDecimals, keywordExpected, kKeywordBufLen);
+                    if ( u_strcmp(keyword, keywordExpected) != 0 ) {
+                        char bcharBuf[kKeywordBufLen];
+                        log_data_err("ERROR: uplrules_selectWithFormat for locale %s, number %.1f: expect %s, get %s\n",
+                                 testItemPtr->locale, testItemPtr->number, testItemPtr->keywordExpectedForDecimals, u_austrcpy(bcharBuf,keyword) );
+                    }
+                } else {
+                    log_err("FAIL: uplrules_selectWithFormat for locale %s, number %.1f: %s\n",
+                            testItemPtr->locale, testItemPtr->number, myErrorName(status) );
+                }
+                unum_close(unumfmt);
+            } else {
+                log_err("FAIL: unum_open for locale %s: %s\n", testItemPtr->locale, myErrorName(status) );
+            }
+
             uplrules_close(uplrules);
         } else {
             log_err("FAIL: uplrules_open for locale %s: %s\n", testItemPtr->locale, myErrorName(status) );
@@ -109,4 +157,113 @@ static void TestOrdinalRules() {
     uplrules_close(upr);
 }
 
+/* items for TestGetKeywords */
+
+/* all possible plural keywords, in alphabetical order */
+static const char* knownKeywords[] = {
+    "few",
+    "many",
+    "one",
+    "other",
+    "two",
+    "zero"
+};
+enum {
+    kNumKeywords = UPRV_LENGTHOF(knownKeywords)
+};
+
+/* Return the index of keyword in knownKeywords[], or -1 if not found */
+static int32_t getKeywordIndex(const char* keyword) {
+    int32_t i, compare;
+    for (i = 0; i < kNumKeywords && (compare = uprv_strcmp(keyword,knownKeywords[i])) >= 0; i++) {
+        if (compare == 0) {
+               return i;
+        }
+    }
+    return -1;
+}
+
+typedef struct {
+    const char* locale;
+    const char* keywords[kNumKeywords + 1];
+} KeywordsForLang;
+
+static const KeywordsForLang getKeywordsItems[] = {
+    { "zh", { "other" } },
+    { "en", { "one", "other" } },
+    { "fr", { "one", "other" } },
+    { "lv", { "zero", "one", "other" } },
+    { "hr", { "one", "few", "other" } },
+    { "sl", { "one", "two", "few", "other" } },
+    { "he", { "one", "two", "many", "other" } },
+    { "cs", { "one", "few", "many", "other" } },
+    { "ar", { "zero", "one", "two", "few", "many" , "other" } },
+    { NULL, { NULL } }
+};
+
+static void TestGetKeywords() {
+    /*
+     * We don't know the order in which the enumeration will return keywords,
+     * so we have an array with known keywords in a fixed order and then
+     * parallel arrays of flags for expected and actual results that indicate
+     * which keywords are expected to be or actually are found.
+     */
+    const KeywordsForLang* itemPtr = getKeywordsItems;
+    for (; itemPtr->locale != NULL; itemPtr++) {
+        UPluralRules* uplrules;
+        UEnumeration* uenum;
+        UBool expectKeywords[kNumKeywords];
+        UBool getKeywords[kNumKeywords];
+        int32_t i, iKnown;
+        UErrorCode status = U_ZERO_ERROR;
+        
+        /* initialize arrays for expected and get results */
+        for (i = 0; i < kNumKeywords; i++) {
+            expectKeywords[i] = FALSE;
+            getKeywords[i] = FALSE;
+        }
+        for (i = 0; i < kNumKeywords && itemPtr->keywords[i] != NULL; i++) {
+            iKnown = getKeywordIndex(itemPtr->keywords[i]);
+            if (iKnown >= 0) {
+                expectKeywords[iKnown] = TRUE;
+            }
+        }
+        
+        uplrules = uplrules_openForType(itemPtr->locale, UPLURAL_TYPE_CARDINAL, &status);
+        if (U_FAILURE(status)) {
+            log_err("FAIL: uplrules_openForType for locale %s, UPLURAL_TYPE_CARDINAL: %s\n", itemPtr->locale, myErrorName(status) );
+            continue;
+        }
+        uenum = uplrules_getKeywords(uplrules, &status);
+        if (U_FAILURE(status)) {
+            log_err("FAIL: uplrules_getKeywords for locale %s: %s\n", itemPtr->locale, myErrorName(status) );
+        } else {
+            const char* keyword;
+            int32_t keywordLen, keywordCount = 0;
+            while ((keyword = uenum_next(uenum, &keywordLen, &status)) != NULL && U_SUCCESS(status)) {
+                iKnown = getKeywordIndex(keyword);
+                if (iKnown < 0) {
+                    log_err("FAIL: uplrules_getKeywords for locale %s, unknown keyword %s\n", itemPtr->locale, keyword );
+                } else {
+                    getKeywords[iKnown] = TRUE;
+                }
+                keywordCount++;
+            }
+            if (keywordCount > kNumKeywords) {
+                log_err("FAIL: uplrules_getKeywords for locale %s, got too many keywords %d\n", itemPtr->locale, keywordCount );
+            }
+            if (uprv_memcmp(expectKeywords, getKeywords, kNumKeywords) != 0) {
+                log_err("FAIL: uplrules_getKeywords for locale %s, got wrong keyword set; with reference to knownKeywords:\n"
+                        "        expected { %d %d %d %d %d %d },\n"
+                        "        got      { %d %d %d %d %d %d }\n", itemPtr->locale, 
+                        expectKeywords[0], expectKeywords[1], expectKeywords[2], expectKeywords[3], expectKeywords[4], expectKeywords[5],
+                        getKeywords[0], getKeywords[1], getKeywords[2], getKeywords[3], getKeywords[4], getKeywords[5] );
+            }
+            uenum_close(uenum);
+        }
+        
+        uplrules_close(uplrules);
+    }
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */