]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/cintltst/cpluralrulestest.c
ICU-62107.0.1.tar.gz
[apple/icu.git] / icuSources / test / cintltst / cpluralrulestest.c
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 */
8
9 #include "unicode/utypes.h"
10
11 #if !UCONFIG_NO_FORMATTING
12
13 #include "unicode/upluralrules.h"
14 #include "unicode/ustring.h"
15 #include "unicode/uenum.h"
16 #include "cintltst.h"
17 #include "cmemory.h"
18 #include "cstring.h"
19
20 static void TestPluralRules(void);
21 static void TestOrdinalRules(void);
22 static void TestGetKeywords(void);
23
24 void addPluralRulesTest(TestNode** root);
25
26 #define TESTCASE(x) addTest(root, &x, "tsformat/cpluralrulestest/" #x)
27
28 void addPluralRulesTest(TestNode** root)
29 {
30 TESTCASE(TestPluralRules);
31 TESTCASE(TestOrdinalRules);
32 TESTCASE(TestGetKeywords);
33 }
34
35 typedef struct {
36 const char * locale;
37 double number;
38 const char * keywordExpected;
39 const char * keywordExpectedForDecimals;
40 } PluralRulesTestItem;
41
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" },
49
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" },
55
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" },
61
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" },
67
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 }
77 };
78
79 static const UChar twoDecimalPat[] = { 0x23,0x30,0x2E,0x30,0x30,0 }; /* "#0.00" */
80
81 enum {
82 kKeywordBufLen = 32
83 };
84
85 static void TestPluralRules()
86 {
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;
99 }
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) );
106 }
107 } else {
108 log_err("FAIL: uplrules_select for locale %s, number %.1f: %s\n",
109 testItemPtr->locale, testItemPtr->number, myErrorName(status) );
110 }
111
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;
118 }
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) );
125 }
126 } else {
127 log_err("FAIL: uplrules_selectWithFormat for locale %s, number %.1f: %s\n",
128 testItemPtr->locale, testItemPtr->number, myErrorName(status) );
129 }
130 unum_close(unumfmt);
131 } else {
132 log_err("FAIL: unum_open for locale %s: %s\n", testItemPtr->locale, myErrorName(status) );
133 }
134
135 uplrules_close(uplrules);
136 } else {
137 log_err("FAIL: uplrules_open for locale %s: %s\n", testItemPtr->locale, myErrorName(status) );
138 }
139 }
140 }
141
142 static void TestOrdinalRules() {
143 U_STRING_DECL(two, "two", 3);
144 UChar keyword[8];
145 int32_t length;
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));
150 return;
151 }
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));
156 }
157 uplrules_close(upr);
158 }
159
160 /* items for TestGetKeywords */
161
162 /* all possible plural keywords, in alphabetical order */
163 static const char* knownKeywords[] = {
164 "few",
165 "many",
166 "one",
167 "other",
168 "two",
169 "zero"
170 };
171 enum {
172 kNumKeywords = UPRV_LENGTHOF(knownKeywords)
173 };
174
175 /* Return the index of keyword in knownKeywords[], or -1 if not found */
176 static int32_t getKeywordIndex(const char* keyword) {
177 int32_t i, compare;
178 for (i = 0; i < kNumKeywords && (compare = uprv_strcmp(keyword,knownKeywords[i])) >= 0; i++) {
179 if (compare == 0) {
180 return i;
181 }
182 }
183 return -1;
184 }
185
186 typedef struct {
187 const char* locale;
188 const char* keywords[kNumKeywords + 1];
189 } KeywordsForLang;
190
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" } },
201 { NULL, { NULL } }
202 };
203
204 static void TestGetKeywords() {
205 /*
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.
210 */
211 const KeywordsForLang* itemPtr = getKeywordsItems;
212 for (; itemPtr->locale != NULL; itemPtr++) {
213 UPluralRules* uplrules;
214 UEnumeration* uenum;
215 UBool expectKeywords[kNumKeywords];
216 UBool getKeywords[kNumKeywords];
217 int32_t i, iKnown;
218 UErrorCode status = U_ZERO_ERROR;
219
220 /* initialize arrays for expected and get results */
221 for (i = 0; i < kNumKeywords; i++) {
222 expectKeywords[i] = FALSE;
223 getKeywords[i] = FALSE;
224 }
225 for (i = 0; i < kNumKeywords && itemPtr->keywords[i] != NULL; i++) {
226 iKnown = getKeywordIndex(itemPtr->keywords[i]);
227 if (iKnown >= 0) {
228 expectKeywords[iKnown] = TRUE;
229 }
230 }
231
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) );
235 continue;
236 }
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) );
240 } else {
241 const char* keyword;
242 int32_t keywordLen, keywordCount = 0;
243 while ((keyword = uenum_next(uenum, &keywordLen, &status)) != NULL && U_SUCCESS(status)) {
244 iKnown = getKeywordIndex(keyword);
245 if (iKnown < 0) {
246 log_err("FAIL: uplrules_getKeywords for locale %s, unknown keyword %s\n", itemPtr->locale, keyword );
247 } else {
248 getKeywords[iKnown] = TRUE;
249 }
250 keywordCount++;
251 }
252 if (keywordCount > kNumKeywords) {
253 log_err("FAIL: uplrules_getKeywords for locale %s, got too many keywords %d\n", itemPtr->locale, keywordCount );
254 }
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] );
261 }
262 uenum_close(uenum);
263 }
264
265 uplrules_close(uplrules);
266 }
267 }
268
269 #endif /* #if !UCONFIG_NO_FORMATTING */