+// © 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);
{
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
};
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);
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) );
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 */