1 /* 2 ******************************************************************************* 3 * Copyright (C) 2007-2008, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ******************************************************************************** 6 7 * File PLURRULTS.cpp 8 * 9 ******************************************************************************** 10 */ 11 12 #include "unicode/utypes.h" 13 14 #if !UCONFIG_NO_FORMATTING 15 16 #include "plurults.h" 17 #include "unicode/plurrule.h" 18 19 20 21 void setupResult(const int32_t testSource[], char result[], int32_t* max); 22 UBool checkEqual(PluralRules *test, char *result, int32_t max); 23 UBool testEquality(PluralRules *test); 24 25 // This is an API test, not a unit test. It doesn't test very many cases, and doesn't 26 // try to test the full functionality. It just calls each function in the class and 27 // verifies that it works on a basic level. 28 29 void PluralRulesTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) 30 { 31 if (exec) logln("TestSuite PluralRulesAPI"); 32 switch (index) { 33 TESTCASE(0, testAPI); 34 default: name = ""; break; 35 } 36 } 37 38 #define PLURAL_TEST_NUM 18 39 /** 40 * Test various generic API methods of PluralRules for API coverage. 41 */ 42 void PluralRulesTest::testAPI(/*char *par*/) 43 { 44 UnicodeString pluralTestData[PLURAL_TEST_NUM] = { 45 UNICODE_STRING_SIMPLE("a: n is 1"), 46 UNICODE_STRING_SIMPLE("a: n mod 10 is 2"), 47 UNICODE_STRING_SIMPLE("a: n is not 1"), 48 UNICODE_STRING_SIMPLE("a: n mod 3 is not 1"), 49 UNICODE_STRING_SIMPLE("a: n in 2..5"), 50 UNICODE_STRING_SIMPLE("a: n within 2..5"), 51 UNICODE_STRING_SIMPLE("a: n not in 2..5"), 52 UNICODE_STRING_SIMPLE("a: n not within 2..5"), 53 UNICODE_STRING_SIMPLE("a: n mod 10 in 2..5"), 54 UNICODE_STRING_SIMPLE("a: n mod 10 within 2..5"), 55 UNICODE_STRING_SIMPLE("a: n mod 10 is 2 and n is not 12"), 56 UNICODE_STRING_SIMPLE("a: n mod 10 in 2..3 or n mod 10 is 5"), 57 UNICODE_STRING_SIMPLE("a: n mod 10 within 2..3 or n mod 10 is 5"), 58 UNICODE_STRING_SIMPLE("a: n is 1 or n is 4 or n is 23"), 59 UNICODE_STRING_SIMPLE("a: n mod 2 is 1 and n is not 3 and n in 1..11"), 60 UNICODE_STRING_SIMPLE("a: n mod 2 is 1 and n is not 3 and n within 1..11"), 61 UNICODE_STRING_SIMPLE("a: n mod 2 is 1 or n mod 5 is 1 and n is not 6"), 62 "", 63 }; 64 static const int32_t pluralTestResult[PLURAL_TEST_NUM][30] = { 65 {1, 0}, 66 {2,12,22, 0}, 67 {0,2,3,4,5,0}, 68 {0,2,3,5,6,8,9,0}, 69 {2,3,4,5,0}, 70 {2,3,4,5,0}, 71 {0,1,6,7,8, 0}, 72 {0,1,6,7,8, 0}, 73 {2,3,4,5,12,13,14,15,22,23,24,25,0}, 74 {2,3,4,5,12,13,14,15,22,23,24,25,0}, 75 {2,22,32,42,0}, 76 {2,3,5,12,13,15,22,23,25,0}, 77 {2,3,5,12,13,15,22,23,25,0}, 78 {1,4,23,0}, 79 {1,5,7,9,11,0}, 80 {1,5,7,9,11,0}, 81 {1,3,5,7,9,11,13,15,16,0}, 82 }; 83 UErrorCode status = U_ZERO_ERROR; 84 85 // ======= Test constructors 86 logln("Testing PluralRules constructors"); 87 88 89 logln("\n start default locale test case ..\n"); 90 91 PluralRules defRule(status); 92 PluralRules* test=new PluralRules(status); 93 PluralRules* newEnPlural= test->forLocale(Locale::getEnglish(), status); 94 if(U_FAILURE(status)) { 95 dataerrln("ERROR: Could not create PluralRules (default) - exitting"); 96 delete test; 97 return; 98 } 99 100 // ======= Test clone, assignment operator && == operator. 101 PluralRules *dupRule = defRule.clone(); 102 if (dupRule!=NULL) { 103 if ( *dupRule != defRule ) { 104 errln("ERROR: clone plural rules test failed!"); 105 } 106 } 107 *dupRule = *newEnPlural; 108 if (dupRule!=NULL) { 109 if ( *dupRule != *newEnPlural ) { 110 errln("ERROR: clone plural rules test failed!"); 111 } 112 delete dupRule; 113 } 114 115 delete newEnPlural; 116 117 // ======= Test empty plural rules 118 logln("Testing Simple PluralRules"); 119 120 PluralRules* empRule = test->createRules(UNICODE_STRING_SIMPLE("a:n"), status); 121 UnicodeString key; 122 for (int32_t i=0; i<10; ++i) { 123 key = empRule->select(i); 124 if ( key.charAt(0)!= 0x61 ) { // 'a' 125 errln("ERROR: empty plural rules test failed! - exitting"); 126 } 127 } 128 if (empRule!=NULL) { 129 delete empRule; 130 } 131 132 // ======= Test simple plural rules 133 logln("Testing Simple PluralRules"); 134 135 char result[100]; 136 int32_t max; 137 138 for (int32_t i=0; i<PLURAL_TEST_NUM-1; ++i) { 139 PluralRules *newRules = test->createRules(pluralTestData[i], status); 140 setupResult(pluralTestResult[i], result, &max); 141 if ( !checkEqual(newRules, result, max) ) { 142 errln("ERROR: simple plural rules failed! - exitting"); 143 delete test; 144 return; 145 } 146 if (newRules!=NULL) { 147 delete newRules; 148 } 149 } 150 151 152 // ======= Test complex plural rules 153 logln("Testing Complex PluralRules"); 154 // TODO: the complex test data is hard coded. It's better to implement 155 // a parser to parse the test data. 156 UnicodeString complexRule = UNICODE_STRING_SIMPLE("a: n in 2..5; b: n in 5..8; c: n mod 2 is 1"); 157 UnicodeString complexRule2 = UNICODE_STRING_SIMPLE("a: n within 2..5; b: n within 5..8; c: n mod 2 is 1"); 158 char cRuleResult[] = 159 { 160 0x6F, // 'o' 161 0x63, // 'c' 162 0x61, // 'a' 163 0x61, // 'a' 164 0x61, // 'a' 165 0x61, // 'a' 166 0x62, // 'b' 167 0x62, // 'b' 168 0x62, // 'b' 169 0x63, // 'c' 170 0x6F, // 'o' 171 0x63 // 'c' 172 }; 173 PluralRules *newRules = test->createRules(complexRule, status); 174 if ( !checkEqual(newRules, cRuleResult, 12) ) { 175 errln("ERROR: complex plural rules failed! - exitting"); 176 delete test; 177 return; 178 } 179 if (newRules!=NULL) { 180 delete newRules; 181 newRules=NULL; 182 } 183 newRules = test->createRules(complexRule2, status); 184 if ( !checkEqual(newRules, cRuleResult, 12) ) { 185 errln("ERROR: complex plural rules failed! - exitting"); 186 delete test; 187 return; 188 } 189 if (newRules!=NULL) { 190 delete newRules; 191 newRules=NULL; 192 } 193 194 // ======= Test decimal fractions plural rules 195 UnicodeString decimalRule= UNICODE_STRING_SIMPLE("a: n not in 0..100;"); 196 UnicodeString KEYWORD_A = UNICODE_STRING_SIMPLE("a"); 197 status = U_ZERO_ERROR; 198 newRules = test->createRules(decimalRule, status); 199 if (U_FAILURE(status)) { 200 dataerrln("ERROR: Could not create PluralRules for testing fractions - exitting"); 201 delete test; 202 return; 203 } 204 double fData[10] = {-100, -1, -0.0, 0, 0.1, 1, 1.999, 2.0, 100, 100.001 }; 205 UBool isKeywordA[10] = { 206 TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE }; 207 for (int32_t i=0; i<10; i++) { 208 if ((newRules->select(fData[i])== KEYWORD_A) != isKeywordA[i]) { 209 errln("ERROR: plural rules for decimal fractions test failed!"); 210 } 211 } 212 if (newRules!=NULL) { 213 delete newRules; 214 newRules=NULL; 215 } 216 217 218 219 // ======= Test Equality 220 logln("Testing Equality of PluralRules"); 221 222 223 if ( !testEquality(test) ) { 224 errln("ERROR: complex plural rules failed! - exitting"); 225 delete test; 226 return; 227 } 228 229 230 // ======= Test getStaticClassID() 231 logln("Testing getStaticClassID()"); 232 233 if(test->getDynamicClassID() != PluralRules::getStaticClassID()) { 234 errln("ERROR: getDynamicClassID() didn't return the expected value"); 235 } 236 // ====== Test fallback to parent locale 237 PluralRules *en_UK = test->forLocale(Locale::getUK(), status); 238 PluralRules *en = test->forLocale(Locale::getEnglish(), status); 239 if (en_UK != NULL && en != NULL) { 240 if ( *en_UK != *en ) { 241 errln("ERROR: test locale fallback failed!"); 242 } 243 } 244 delete en; 245 delete en_UK; 246 247 PluralRules *zh_Hant = test->forLocale(Locale::getTaiwan(), status); 248 PluralRules *zh = test->forLocale(Locale::getChinese(), status); 249 if (zh_Hant != NULL && zh != NULL) { 250 if ( *zh_Hant != *zh ) { 251 errln("ERROR: test locale fallback failed!"); 252 } 253 } 254 delete zh_Hant; 255 delete zh; 256 delete test; 257 } 258 259 void setupResult(const int32_t testSource[], char result[], int32_t* max) { 260 int32_t i=0; 261 int32_t curIndex=0; 262 263 do { 264 while (curIndex < testSource[i]) { 265 result[curIndex++]=0x6F; //'o' other 266 } 267 result[curIndex++]=0x61; // 'a' 268 269 } while(testSource[++i]>0); 270 *max=curIndex; 271 } 272 273 274 UBool checkEqual(PluralRules *test, char *result, int32_t max) { 275 UnicodeString key; 276 UBool isEqual = TRUE; 277 for (int32_t i=0; i<max; ++i) { 278 key= test->select(i); 279 if ( key.charAt(0)!=result[i] ) { 280 isEqual = FALSE; 281 } 282 } 283 return isEqual; 284 } 285 286 #define MAX_EQ_ROW 2 287 #define MAX_EQ_COL 5 288 UBool testEquality(PluralRules *test) { 289 UnicodeString testEquRules[MAX_EQ_ROW][MAX_EQ_COL] = { 290 { UNICODE_STRING_SIMPLE("a: n in 2..3"), 291 UNICODE_STRING_SIMPLE("a: n is 2 or n is 3"), 292 UNICODE_STRING_SIMPLE( "a:n is 3 and n in 2..5 or n is 2"), 293 "", 294 }, 295 { UNICODE_STRING_SIMPLE("a: n is 12; b:n mod 10 in 2..3"), 296 UNICODE_STRING_SIMPLE("b: n mod 10 in 2..3 and n is not 12; a: n in 12..12"), 297 UNICODE_STRING_SIMPLE("b: n is 13; a: n in 12..13; b: n mod 10 is 2 or n mod 10 is 3"), 298 "", 299 } 300 }; 301 UErrorCode status = U_ZERO_ERROR; 302 UnicodeString key[MAX_EQ_COL]; 303 UBool ret=TRUE; 304 for (int32_t i=0; i<MAX_EQ_ROW; ++i) { 305 PluralRules* rules[MAX_EQ_COL]; 306 307 for (int32_t j=0; j<MAX_EQ_COL; ++j) { 308 rules[j]=NULL; 309 } 310 int32_t totalRules=0; 311 while((totalRules<MAX_EQ_COL) && (testEquRules[i][totalRules].length()>0) ) { 312 rules[totalRules]=test->createRules(testEquRules[i][totalRules], status); 313 totalRules++; 314 } 315 for (int32_t n=0; n<300 && ret ; ++n) { 316 for(int32_t j=0; j<totalRules;++j) { 317 key[j] = rules[j]->select(n); 318 } 319 for(int32_t j=0; j<totalRules-1;++j) { 320 if (key[j]!=key[j+1]) { 321 ret= FALSE; 322 break; 323 } 324 } 325 326 } 327 for (int32_t j=0; j<MAX_EQ_COL; ++j) { 328 if (rules[j]!=NULL) { 329 delete rules[j]; 330 } 331 } 332 } 333 334 return ret; 335 } 336 #endif /* #if !UCONFIG_NO_FORMATTING */ 337 338