1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * Copyright (c) 2011-2014, International Business Machines Corporation
5 * and others. All Rights Reserved.
6 ********************************************************************/
7 /* C API TEST FOR PLURAL RULES */
9 #include "unicode/utypes.h"
11 #if !UCONFIG_NO_FORMATTING
13 #include "unicode/upluralrules.h"
14 #include "unicode/ustring.h"
15 #include "unicode/uenum.h"
20 static void TestPluralRules(void);
21 static void TestOrdinalRules(void);
22 static void TestGetKeywords(void);
24 void addPluralRulesTest(TestNode
** root
);
26 #define TESTCASE(x) addTest(root, &x, "tsformat/cpluralrulestest/" #x)
28 void addPluralRulesTest(TestNode
** root
)
30 TESTCASE(TestPluralRules
);
31 TESTCASE(TestOrdinalRules
);
32 TESTCASE(TestGetKeywords
);
38 const char * keywordExpected
;
39 const char * keywordExpectedForDecimals
;
40 } PluralRulesTestItem
;
42 /* Just a small set of tests for now, other functionality is tested in the C++ tests */
43 static const PluralRulesTestItem testItems
[] = {
44 { "en", 0, "other", "other" },
45 { "en", 0.5, "other", "other" },
46 { "en", 1, "one", "other" },
47 { "en", 1.5, "other", "other" },
48 { "en", 2, "other", "other" },
50 { "pt_PT", 0, "other", "other" },
51 { "pt_PT", 0.5, "other", "other" },
52 { "pt_PT", 1, "one", "other" },
53 { "pt_PT", 1.5, "other", "other" },
54 { "pt_PT", 2, "other", "other" },
56 { "pt_BR", 0, "one", "one" },
57 { "pt_BR", 0.5, "one", "one" },
58 { "pt_BR", 1, "one", "one" },
59 { "pt_BR", 1.5, "one", "one" },
60 { "pt_BR", 2, "other", "other" },
62 { "fr", 0, "one", "one" },
63 { "fr", 0.5, "one", "one" },
64 { "fr", 1, "one", "one" },
65 { "fr", 1.5, "one", "one" },
66 { "fr", 2, "other", "other" },
68 { "ru", 0, "many", "other" },
69 { "ru", 0.5, "other", "other" },
70 { "ru", 1, "one", "other" },
71 { "ru", 1.5, "other", "other" },
72 { "ru", 2, "few", "other" },
73 { "ru", 5, "many", "other" },
74 { "ru", 10, "many", "other" },
75 { "ru", 11, "many", "other" },
76 { NULL
, 0, NULL
, NULL
}
79 static const UChar twoDecimalPat
[] = { 0x23,0x30,0x2E,0x30,0x30,0 }; /* "#0.00" */
85 static void TestPluralRules()
87 const PluralRulesTestItem
* testItemPtr
;
88 log_verbose("\nTesting uplrules_open() and uplrules_select() with various parameters\n");
89 for ( testItemPtr
= testItems
; testItemPtr
->locale
!= NULL
; ++testItemPtr
) {
90 UErrorCode status
= U_ZERO_ERROR
;
91 UPluralRules
* uplrules
= uplrules_open(testItemPtr
->locale
, &status
);
92 if ( U_SUCCESS(status
) ) {
93 UNumberFormat
* unumfmt
;
94 UChar keyword
[kKeywordBufLen
];
95 UChar keywordExpected
[kKeywordBufLen
];
96 int32_t keywdLen
= uplrules_select(uplrules
, testItemPtr
->number
, keyword
, kKeywordBufLen
, &status
);
97 if (keywdLen
>= kKeywordBufLen
) {
98 keyword
[kKeywordBufLen
-1] = 0;
100 if ( U_SUCCESS(status
) ) {
101 u_unescape(testItemPtr
->keywordExpected
, keywordExpected
, kKeywordBufLen
);
102 if ( u_strcmp(keyword
, keywordExpected
) != 0 ) {
103 char bcharBuf
[kKeywordBufLen
];
104 log_data_err("ERROR: uplrules_select for locale %s, number %.1f: expect %s, get %s\n",
105 testItemPtr
->locale
, testItemPtr
->number
, testItemPtr
->keywordExpected
, u_austrcpy(bcharBuf
,keyword
) );
108 log_err("FAIL: uplrules_select for locale %s, number %.1f: %s\n",
109 testItemPtr
->locale
, testItemPtr
->number
, myErrorName(status
) );
112 status
= U_ZERO_ERROR
;
113 unumfmt
= unum_open(UNUM_PATTERN_DECIMAL
, twoDecimalPat
, -1, testItemPtr
->locale
, NULL
, &status
);
114 if ( U_SUCCESS(status
) ) {
115 keywdLen
= uplrules_selectWithFormat(uplrules
, testItemPtr
->number
, unumfmt
, keyword
, kKeywordBufLen
, &status
);
116 if (keywdLen
>= kKeywordBufLen
) {
117 keyword
[kKeywordBufLen
-1] = 0;
119 if ( U_SUCCESS(status
) ) {
120 u_unescape(testItemPtr
->keywordExpectedForDecimals
, keywordExpected
, kKeywordBufLen
);
121 if ( u_strcmp(keyword
, keywordExpected
) != 0 ) {
122 char bcharBuf
[kKeywordBufLen
];
123 log_data_err("ERROR: uplrules_selectWithFormat for locale %s, number %.1f: expect %s, get %s\n",
124 testItemPtr
->locale
, testItemPtr
->number
, testItemPtr
->keywordExpectedForDecimals
, u_austrcpy(bcharBuf
,keyword
) );
127 log_err("FAIL: uplrules_selectWithFormat for locale %s, number %.1f: %s\n",
128 testItemPtr
->locale
, testItemPtr
->number
, myErrorName(status
) );
132 log_err("FAIL: unum_open for locale %s: %s\n", testItemPtr
->locale
, myErrorName(status
) );
135 uplrules_close(uplrules
);
137 log_err("FAIL: uplrules_open for locale %s: %s\n", testItemPtr
->locale
, myErrorName(status
) );
142 static void TestOrdinalRules() {
143 U_STRING_DECL(two
, "two", 3);
146 UErrorCode errorCode
= U_ZERO_ERROR
;
147 UPluralRules
* upr
= uplrules_openForType("en", UPLURAL_TYPE_ORDINAL
, &errorCode
);
148 if (U_FAILURE(errorCode
)) {
149 log_err("uplrules_openForType(en, ordinal) failed - %s\n", u_errorName(errorCode
));
152 U_STRING_INIT(two
, "two", 3);
153 length
= uplrules_select(upr
, 2., keyword
, 8, &errorCode
);
154 if (U_FAILURE(errorCode
) || u_strCompare(keyword
, length
, two
, 3, FALSE
) != 0) {
155 log_data_err("uplrules_select(en-ordinal, 2) failed - %s\n", u_errorName(errorCode
));
160 /* items for TestGetKeywords */
162 /* all possible plural keywords, in alphabetical order */
163 static const char* knownKeywords
[] = {
172 kNumKeywords
= UPRV_LENGTHOF(knownKeywords
)
175 /* Return the index of keyword in knownKeywords[], or -1 if not found */
176 static int32_t getKeywordIndex(const char* keyword
) {
178 for (i
= 0; i
< kNumKeywords
&& (compare
= uprv_strcmp(keyword
,knownKeywords
[i
])) >= 0; i
++) {
188 const char* keywords
[kNumKeywords
+ 1];
191 static const KeywordsForLang getKeywordsItems
[] = {
192 { "zh", { "other" } },
193 { "en", { "one", "other" } },
194 { "fr", { "one", "other" } },
195 { "lv", { "zero", "one", "other" } },
196 { "hr", { "one", "few", "other" } },
197 { "sl", { "one", "two", "few", "other" } },
198 { "he", { "one", "two", "many", "other" } },
199 { "cs", { "one", "few", "many", "other" } },
200 { "ar", { "zero", "one", "two", "few", "many" , "other" } },
204 static void TestGetKeywords() {
206 * We don't know the order in which the enumeration will return keywords,
207 * so we have an array with known keywords in a fixed order and then
208 * parallel arrays of flags for expected and actual results that indicate
209 * which keywords are expected to be or actually are found.
211 const KeywordsForLang
* itemPtr
= getKeywordsItems
;
212 for (; itemPtr
->locale
!= NULL
; itemPtr
++) {
213 UPluralRules
* uplrules
;
215 UBool expectKeywords
[kNumKeywords
];
216 UBool getKeywords
[kNumKeywords
];
218 UErrorCode status
= U_ZERO_ERROR
;
220 /* initialize arrays for expected and get results */
221 for (i
= 0; i
< kNumKeywords
; i
++) {
222 expectKeywords
[i
] = FALSE
;
223 getKeywords
[i
] = FALSE
;
225 for (i
= 0; i
< kNumKeywords
&& itemPtr
->keywords
[i
] != NULL
; i
++) {
226 iKnown
= getKeywordIndex(itemPtr
->keywords
[i
]);
228 expectKeywords
[iKnown
] = TRUE
;
232 uplrules
= uplrules_openForType(itemPtr
->locale
, UPLURAL_TYPE_CARDINAL
, &status
);
233 if (U_FAILURE(status
)) {
234 log_err("FAIL: uplrules_openForType for locale %s, UPLURAL_TYPE_CARDINAL: %s\n", itemPtr
->locale
, myErrorName(status
) );
237 uenum
= uplrules_getKeywords(uplrules
, &status
);
238 if (U_FAILURE(status
)) {
239 log_err("FAIL: uplrules_getKeywords for locale %s: %s\n", itemPtr
->locale
, myErrorName(status
) );
242 int32_t keywordLen
, keywordCount
= 0;
243 while ((keyword
= uenum_next(uenum
, &keywordLen
, &status
)) != NULL
&& U_SUCCESS(status
)) {
244 iKnown
= getKeywordIndex(keyword
);
246 log_err("FAIL: uplrules_getKeywords for locale %s, unknown keyword %s\n", itemPtr
->locale
, keyword
);
248 getKeywords
[iKnown
] = TRUE
;
252 if (keywordCount
> kNumKeywords
) {
253 log_err("FAIL: uplrules_getKeywords for locale %s, got too many keywords %d\n", itemPtr
->locale
, keywordCount
);
255 if (uprv_memcmp(expectKeywords
, getKeywords
, kNumKeywords
) != 0) {
256 log_err("FAIL: uplrules_getKeywords for locale %s, got wrong keyword set; with reference to knownKeywords:\n"
257 " expected { %d %d %d %d %d %d },\n"
258 " got { %d %d %d %d %d %d }\n", itemPtr
->locale
,
259 expectKeywords
[0], expectKeywords
[1], expectKeywords
[2], expectKeywords
[3], expectKeywords
[4], expectKeywords
[5],
260 getKeywords
[0], getKeywords
[1], getKeywords
[2], getKeywords
[3], getKeywords
[4], getKeywords
[5] );
265 uplrules_close(uplrules
);
269 #endif /* #if !UCONFIG_NO_FORMATTING */