]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/cintltst/cpluralrulestest.c
ICU-64232.0.1.tar.gz
[apple/icu.git] / icuSources / test / cintltst / cpluralrulestest.c
CommitLineData
f3c0d7a5
A
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
4388f060 3/********************************************************************
57a6839d 4 * Copyright (c) 2011-2014, International Business Machines Corporation
4388f060
A
5 * and others. All Rights Reserved.
6 ********************************************************************/
7/* C API TEST FOR PLURAL RULES */
8
9#include "unicode/utypes.h"
10
11#if !UCONFIG_NO_FORMATTING
12
13#include "unicode/upluralrules.h"
14#include "unicode/ustring.h"
f3c0d7a5 15#include "unicode/uenum.h"
3d1f044b 16#include "unicode/unumberformatter.h"
4388f060
A
17#include "cintltst.h"
18#include "cmemory.h"
f3c0d7a5 19#include "cstring.h"
4388f060
A
20
21static void TestPluralRules(void);
51004dcb 22static void TestOrdinalRules(void);
f3c0d7a5 23static void TestGetKeywords(void);
3d1f044b 24static void TestFormatted(void);
4388f060
A
25
26void addPluralRulesTest(TestNode** root);
27
28#define TESTCASE(x) addTest(root, &x, "tsformat/cpluralrulestest/" #x)
29
30void addPluralRulesTest(TestNode** root)
31{
32 TESTCASE(TestPluralRules);
51004dcb 33 TESTCASE(TestOrdinalRules);
f3c0d7a5 34 TESTCASE(TestGetKeywords);
3d1f044b 35 TESTCASE(TestFormatted);
4388f060
A
36}
37
38typedef struct {
39 const char * locale;
40 double number;
41 const char * keywordExpected;
f3c0d7a5 42 const char * keywordExpectedForDecimals;
4388f060
A
43} PluralRulesTestItem;
44
45/* Just a small set of tests for now, other functionality is tested in the C++ tests */
46static const PluralRulesTestItem testItems[] = {
f3c0d7a5
A
47 { "en", 0, "other", "other" },
48 { "en", 0.5, "other", "other" },
49 { "en", 1, "one", "other" },
50 { "en", 1.5, "other", "other" },
51 { "en", 2, "other", "other" },
52
53 { "pt_PT", 0, "other", "other" },
54 { "pt_PT", 0.5, "other", "other" },
55 { "pt_PT", 1, "one", "other" },
56 { "pt_PT", 1.5, "other", "other" },
57 { "pt_PT", 2, "other", "other" },
58
59 { "pt_BR", 0, "one", "one" },
60 { "pt_BR", 0.5, "one", "one" },
61 { "pt_BR", 1, "one", "one" },
62 { "pt_BR", 1.5, "one", "one" },
63 { "pt_BR", 2, "other", "other" },
64
65 { "fr", 0, "one", "one" },
66 { "fr", 0.5, "one", "one" },
67 { "fr", 1, "one", "one" },
68 { "fr", 1.5, "one", "one" },
69 { "fr", 2, "other", "other" },
70
71 { "ru", 0, "many", "other" },
72 { "ru", 0.5, "other", "other" },
73 { "ru", 1, "one", "other" },
74 { "ru", 1.5, "other", "other" },
75 { "ru", 2, "few", "other" },
76 { "ru", 5, "many", "other" },
77 { "ru", 10, "many", "other" },
78 { "ru", 11, "many", "other" },
3d1f044b
A
79
80 // ru rules should not be affected by script/lang/keywords <rdar://problem/49268649>
81 { "ru_Cyrl_RU", 0, "many", "other" },
82 { "ru_Cyrl_RU", 0.5, "other", "other" },
83 { "ru_Cyrl_RU", 1, "one", "other" },
84 { "ru_Cyrl_RU", 1.5, "other", "other" },
85 { "ru_Cyrl_RU", 2, "few", "other" },
86 { "ru_Cyrl_RU", 5, "many", "other" },
87 { "ru_Cyrl_RU", 10, "many", "other" },
88 { "ru_Cyrl_RU", 11, "many", "other" },
89
90 { "ru@numbers=latn", 0, "many", "other" },
91 { "ru@numbers=latn", 0.5, "other", "other" },
92 { "ru@numbers=latn", 1, "one", "other" },
93 { "ru@numbers=latn", 1.5, "other", "other" },
94 { "ru@numbers=latn", 2, "few", "other" },
95 { "ru@numbers=latn", 5, "many", "other" },
96 { "ru@numbers=latn", 10, "many", "other" },
97 { "ru@numbers=latn", 11, "many", "other" },
98
99 { "ru_Cyrl_RU@numbers=latn", 0, "many", "other" },
100 { "ru_Cyrl_RU@numbers=latn", 0.5, "other", "other" },
101 { "ru_Cyrl_RU@numbers=latn", 1, "one", "other" },
102 { "ru_Cyrl_RU@numbers=latn", 1.5, "other", "other" },
103 { "ru_Cyrl_RU@numbers=latn", 2, "few", "other" },
104 { "ru_Cyrl_RU@numbers=latn", 5, "many", "other" },
105 { "ru_Cyrl_RU@numbers=latn", 10, "many", "other" },
106 { "ru_Cyrl_RU@numbers=latn", 11, "many", "other" },
107
f3c0d7a5 108 { NULL, 0, NULL, NULL }
4388f060
A
109};
110
f3c0d7a5
A
111static const UChar twoDecimalPat[] = { 0x23,0x30,0x2E,0x30,0x30,0 }; /* "#0.00" */
112
4388f060
A
113enum {
114 kKeywordBufLen = 32
115};
116
117static void TestPluralRules()
118{
119 const PluralRulesTestItem * testItemPtr;
120 log_verbose("\nTesting uplrules_open() and uplrules_select() with various parameters\n");
121 for ( testItemPtr = testItems; testItemPtr->locale != NULL; ++testItemPtr ) {
122 UErrorCode status = U_ZERO_ERROR;
123 UPluralRules* uplrules = uplrules_open(testItemPtr->locale, &status);
124 if ( U_SUCCESS(status) ) {
f3c0d7a5 125 UNumberFormat* unumfmt;
4388f060
A
126 UChar keyword[kKeywordBufLen];
127 UChar keywordExpected[kKeywordBufLen];
128 int32_t keywdLen = uplrules_select(uplrules, testItemPtr->number, keyword, kKeywordBufLen, &status);
129 if (keywdLen >= kKeywordBufLen) {
130 keyword[kKeywordBufLen-1] = 0;
131 }
132 if ( U_SUCCESS(status) ) {
133 u_unescape(testItemPtr->keywordExpected, keywordExpected, kKeywordBufLen);
134 if ( u_strcmp(keyword, keywordExpected) != 0 ) {
135 char bcharBuf[kKeywordBufLen];
136 log_data_err("ERROR: uplrules_select for locale %s, number %.1f: expect %s, get %s\n",
137 testItemPtr->locale, testItemPtr->number, testItemPtr->keywordExpected, u_austrcpy(bcharBuf,keyword) );
138 }
139 } else {
140 log_err("FAIL: uplrules_select for locale %s, number %.1f: %s\n",
141 testItemPtr->locale, testItemPtr->number, myErrorName(status) );
142 }
f3c0d7a5
A
143
144 status = U_ZERO_ERROR;
145 unumfmt = unum_open(UNUM_PATTERN_DECIMAL, twoDecimalPat, -1, testItemPtr->locale, NULL, &status);
146 if ( U_SUCCESS(status) ) {
147 keywdLen = uplrules_selectWithFormat(uplrules, testItemPtr->number, unumfmt, keyword, kKeywordBufLen, &status);
148 if (keywdLen >= kKeywordBufLen) {
149 keyword[kKeywordBufLen-1] = 0;
150 }
151 if ( U_SUCCESS(status) ) {
152 u_unescape(testItemPtr->keywordExpectedForDecimals, keywordExpected, kKeywordBufLen);
153 if ( u_strcmp(keyword, keywordExpected) != 0 ) {
154 char bcharBuf[kKeywordBufLen];
155 log_data_err("ERROR: uplrules_selectWithFormat for locale %s, number %.1f: expect %s, get %s\n",
156 testItemPtr->locale, testItemPtr->number, testItemPtr->keywordExpectedForDecimals, u_austrcpy(bcharBuf,keyword) );
157 }
158 } else {
159 log_err("FAIL: uplrules_selectWithFormat for locale %s, number %.1f: %s\n",
160 testItemPtr->locale, testItemPtr->number, myErrorName(status) );
161 }
162 unum_close(unumfmt);
163 } else {
164 log_err("FAIL: unum_open for locale %s: %s\n", testItemPtr->locale, myErrorName(status) );
165 }
166
4388f060
A
167 uplrules_close(uplrules);
168 } else {
169 log_err("FAIL: uplrules_open for locale %s: %s\n", testItemPtr->locale, myErrorName(status) );
170 }
171 }
172}
173
51004dcb
A
174static void TestOrdinalRules() {
175 U_STRING_DECL(two, "two", 3);
176 UChar keyword[8];
177 int32_t length;
178 UErrorCode errorCode = U_ZERO_ERROR;
179 UPluralRules* upr = uplrules_openForType("en", UPLURAL_TYPE_ORDINAL, &errorCode);
180 if (U_FAILURE(errorCode)) {
181 log_err("uplrules_openForType(en, ordinal) failed - %s\n", u_errorName(errorCode));
182 return;
183 }
184 U_STRING_INIT(two, "two", 3);
185 length = uplrules_select(upr, 2., keyword, 8, &errorCode);
186 if (U_FAILURE(errorCode) || u_strCompare(keyword, length, two, 3, FALSE) != 0) {
187 log_data_err("uplrules_select(en-ordinal, 2) failed - %s\n", u_errorName(errorCode));
188 }
189 uplrules_close(upr);
190}
191
f3c0d7a5
A
192/* items for TestGetKeywords */
193
194/* all possible plural keywords, in alphabetical order */
195static const char* knownKeywords[] = {
196 "few",
197 "many",
198 "one",
199 "other",
200 "two",
201 "zero"
202};
203enum {
204 kNumKeywords = UPRV_LENGTHOF(knownKeywords)
205};
206
207/* Return the index of keyword in knownKeywords[], or -1 if not found */
208static int32_t getKeywordIndex(const char* keyword) {
209 int32_t i, compare;
210 for (i = 0; i < kNumKeywords && (compare = uprv_strcmp(keyword,knownKeywords[i])) >= 0; i++) {
211 if (compare == 0) {
212 return i;
213 }
214 }
215 return -1;
216}
217
218typedef struct {
219 const char* locale;
220 const char* keywords[kNumKeywords + 1];
221} KeywordsForLang;
222
223static const KeywordsForLang getKeywordsItems[] = {
224 { "zh", { "other" } },
225 { "en", { "one", "other" } },
226 { "fr", { "one", "other" } },
227 { "lv", { "zero", "one", "other" } },
228 { "hr", { "one", "few", "other" } },
229 { "sl", { "one", "two", "few", "other" } },
230 { "he", { "one", "two", "many", "other" } },
231 { "cs", { "one", "few", "many", "other" } },
232 { "ar", { "zero", "one", "two", "few", "many" , "other" } },
233 { NULL, { NULL } }
234};
235
236static void TestGetKeywords() {
237 /*
238 * We don't know the order in which the enumeration will return keywords,
239 * so we have an array with known keywords in a fixed order and then
240 * parallel arrays of flags for expected and actual results that indicate
241 * which keywords are expected to be or actually are found.
242 */
243 const KeywordsForLang* itemPtr = getKeywordsItems;
244 for (; itemPtr->locale != NULL; itemPtr++) {
245 UPluralRules* uplrules;
246 UEnumeration* uenum;
247 UBool expectKeywords[kNumKeywords];
248 UBool getKeywords[kNumKeywords];
249 int32_t i, iKnown;
250 UErrorCode status = U_ZERO_ERROR;
251
252 /* initialize arrays for expected and get results */
253 for (i = 0; i < kNumKeywords; i++) {
254 expectKeywords[i] = FALSE;
255 getKeywords[i] = FALSE;
256 }
257 for (i = 0; i < kNumKeywords && itemPtr->keywords[i] != NULL; i++) {
258 iKnown = getKeywordIndex(itemPtr->keywords[i]);
259 if (iKnown >= 0) {
260 expectKeywords[iKnown] = TRUE;
261 }
262 }
263
264 uplrules = uplrules_openForType(itemPtr->locale, UPLURAL_TYPE_CARDINAL, &status);
265 if (U_FAILURE(status)) {
266 log_err("FAIL: uplrules_openForType for locale %s, UPLURAL_TYPE_CARDINAL: %s\n", itemPtr->locale, myErrorName(status) );
267 continue;
268 }
269 uenum = uplrules_getKeywords(uplrules, &status);
270 if (U_FAILURE(status)) {
271 log_err("FAIL: uplrules_getKeywords for locale %s: %s\n", itemPtr->locale, myErrorName(status) );
272 } else {
273 const char* keyword;
274 int32_t keywordLen, keywordCount = 0;
275 while ((keyword = uenum_next(uenum, &keywordLen, &status)) != NULL && U_SUCCESS(status)) {
276 iKnown = getKeywordIndex(keyword);
277 if (iKnown < 0) {
278 log_err("FAIL: uplrules_getKeywords for locale %s, unknown keyword %s\n", itemPtr->locale, keyword );
279 } else {
280 getKeywords[iKnown] = TRUE;
281 }
282 keywordCount++;
283 }
284 if (keywordCount > kNumKeywords) {
285 log_err("FAIL: uplrules_getKeywords for locale %s, got too many keywords %d\n", itemPtr->locale, keywordCount );
286 }
287 if (uprv_memcmp(expectKeywords, getKeywords, kNumKeywords) != 0) {
288 log_err("FAIL: uplrules_getKeywords for locale %s, got wrong keyword set; with reference to knownKeywords:\n"
289 " expected { %d %d %d %d %d %d },\n"
290 " got { %d %d %d %d %d %d }\n", itemPtr->locale,
291 expectKeywords[0], expectKeywords[1], expectKeywords[2], expectKeywords[3], expectKeywords[4], expectKeywords[5],
292 getKeywords[0], getKeywords[1], getKeywords[2], getKeywords[3], getKeywords[4], getKeywords[5] );
293 }
294 uenum_close(uenum);
295 }
296
297 uplrules_close(uplrules);
298 }
299}
300
3d1f044b
A
301static void TestFormatted() {
302 UErrorCode ec = U_ZERO_ERROR;
303 UNumberFormatter* unumf = NULL;
304 UFormattedNumber* uresult = NULL;
305 UPluralRules* uplrules = NULL;
306
307 uplrules = uplrules_open("hr", &ec);
308 if (!assertSuccess("open plural rules", &ec)) {
309 goto cleanup;
310 }
311
312 unumf = unumf_openForSkeletonAndLocale(u".00", -1, "hr", &ec);
313 if (!assertSuccess("open unumf", &ec)) {
314 goto cleanup;
315 }
316
317 uresult = unumf_openResult(&ec);
318 if (!assertSuccess("open result", &ec)) {
319 goto cleanup;
320 }
321
322 unumf_formatDouble(unumf, 100.2, uresult, &ec);
323 if (!assertSuccess("format", &ec)) {
324 goto cleanup;
325 }
326
327 UChar buffer[40];
328 uplrules_selectFormatted(uplrules, uresult, buffer, 40, &ec);
329 if (!assertSuccess("select", &ec)) {
330 goto cleanup;
331 }
332
333 assertUEquals("0.20 is plural category 'other' in hr", u"other", buffer);
334
335cleanup:
336 uplrules_close(uplrules);
337 unumf_close(unumf);
338 unumf_closeResult(uresult);
339}
340
4388f060 341#endif /* #if !UCONFIG_NO_FORMATTING */