1 // 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ******************************************************************************* 5 * Copyright (C) 1996-2009, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 */ 9 10 #include "unicode/utypes.h" 11 12 #if !UCONFIG_NO_FORMATTING 13 14 #include "itrbnfrt.h" 15 16 #include "unicode/fmtable.h" 17 #include <math.h> // fabs 18 #include <stdio.h> 19 20 // current macro not in icu1.8.1 21 #define TESTCASE(id,test) \ 22 case id: \ 23 name = #test; \ 24 if (exec) { \ 25 logln(#test "---"); \ 26 logln(); \ 27 test(); \ 28 } \ 29 break 30 31 void RbnfRoundTripTest::runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par*/) 32 { 33 if (exec) logln("TestSuite RuleBasedNumberFormatRT"); 34 switch (index) { 35 #if U_HAVE_RBNF 36 TESTCASE(0, TestEnglishSpelloutRT); 37 TESTCASE(1, TestDurationsRT); 38 TESTCASE(2, TestSpanishSpelloutRT); 39 TESTCASE(3, TestFrenchSpelloutRT); 40 TESTCASE(4, TestSwissFrenchSpelloutRT); 41 TESTCASE(5, TestItalianSpelloutRT); 42 TESTCASE(6, TestGermanSpelloutRT); 43 TESTCASE(7, TestSwedishSpelloutRT); 44 TESTCASE(8, TestDutchSpelloutRT); 45 TESTCASE(9, TestJapaneseSpelloutRT); 46 TESTCASE(10, TestRussianSpelloutRT); 47 TESTCASE(11, TestPortugueseSpelloutRT); 48 #else 49 TESTCASE(0, TestRBNFDisabled); 50 #endif 51 default: 52 name = ""; 53 break; 54 } 55 } 56 57 #if U_HAVE_RBNF 58 59 /** 60 * Perform an exhaustive round-trip test on the English spellout rules 61 */ 62 void 63 RbnfRoundTripTest::TestEnglishSpelloutRT() 64 { 65 UErrorCode status = U_ZERO_ERROR; 66 RuleBasedNumberFormat* formatter 67 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getUS(), status); 68 69 if (U_FAILURE(status)) { 70 errcheckln(status, "failed to construct formatter - %s", u_errorName(status)); 71 } else { 72 doTest(formatter, -12345678, 12345678); 73 } 74 delete formatter; 75 } 76 77 /** 78 * Perform an exhaustive round-trip test on the duration-formatting rules 79 */ 80 void 81 RbnfRoundTripTest::TestDurationsRT() 82 { 83 UErrorCode status = U_ZERO_ERROR; 84 RuleBasedNumberFormat* formatter 85 = new RuleBasedNumberFormat(URBNF_DURATION, Locale::getUS(), status); 86 87 if (U_FAILURE(status)) { 88 errcheckln(status, "failed to construct formatter - %s", u_errorName(status)); 89 } else { 90 doTest(formatter, 0, 12345678); 91 } 92 delete formatter; 93 } 94 95 /** 96 * Perform an exhaustive round-trip test on the Spanish spellout rules 97 */ 98 void 99 RbnfRoundTripTest::TestSpanishSpelloutRT() 100 { 101 UErrorCode status = U_ZERO_ERROR; 102 RuleBasedNumberFormat* formatter 103 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("es", "es"), status); 104 105 if (U_FAILURE(status)) { 106 errcheckln(status, "failed to construct formatter - %s", u_errorName(status)); 107 } else { 108 doTest(formatter, -12345678, 12345678); 109 } 110 delete formatter; 111 } 112 113 /** 114 * Perform an exhaustive round-trip test on the French spellout rules 115 */ 116 void 117 RbnfRoundTripTest::TestFrenchSpelloutRT() 118 { 119 UErrorCode status = U_ZERO_ERROR; 120 RuleBasedNumberFormat* formatter 121 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getFrance(), status); 122 123 if (U_FAILURE(status)) { 124 errcheckln(status, "failed to construct formatter - %s", u_errorName(status)); 125 } else { 126 doTest(formatter, -12345678, 12345678); 127 } 128 delete formatter; 129 } 130 131 /** 132 * Perform an exhaustive round-trip test on the Swiss French spellout rules 133 */ 134 void 135 RbnfRoundTripTest::TestSwissFrenchSpelloutRT() 136 { 137 UErrorCode status = U_ZERO_ERROR; 138 RuleBasedNumberFormat* formatter 139 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("fr", "CH"), status); 140 141 if (U_FAILURE(status)) { 142 errcheckln(status, "failed to construct formatter - %s", u_errorName(status)); 143 } else { 144 doTest(formatter, -12345678, 12345678); 145 } 146 delete formatter; 147 } 148 149 /** 150 * Perform an exhaustive round-trip test on the Italian spellout rules 151 */ 152 void 153 RbnfRoundTripTest::TestItalianSpelloutRT() 154 { 155 UErrorCode status = U_ZERO_ERROR; 156 RuleBasedNumberFormat* formatter 157 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getItalian(), status); 158 159 if (U_FAILURE(status)) { 160 errcheckln(status, "failed to construct formatter - %s", u_errorName(status)); 161 } else { 162 doTest(formatter, -999999, 999999); 163 } 164 delete formatter; 165 } 166 167 /** 168 * Perform an exhaustive round-trip test on the German spellout rules 169 */ 170 void 171 RbnfRoundTripTest::TestGermanSpelloutRT() 172 { 173 UErrorCode status = U_ZERO_ERROR; 174 RuleBasedNumberFormat* formatter 175 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getGermany(), status); 176 177 if (U_FAILURE(status)) { 178 errcheckln(status, "failed to construct formatter - %s", u_errorName(status)); 179 } else { 180 doTest(formatter, 0, 12345678); 181 } 182 delete formatter; 183 } 184 185 /** 186 * Perform an exhaustive round-trip test on the Swedish spellout rules 187 */ 188 void 189 RbnfRoundTripTest::TestSwedishSpelloutRT() 190 { 191 UErrorCode status = U_ZERO_ERROR; 192 RuleBasedNumberFormat* formatter 193 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("sv", "SE"), status); 194 195 if (U_FAILURE(status)) { 196 errcheckln(status, "failed to construct formatter - %s", u_errorName(status)); 197 } else { 198 doTest(formatter, 0, 12345678); 199 } 200 delete formatter; 201 } 202 203 /** 204 * Perform an exhaustive round-trip test on the Dutch spellout rules 205 */ 206 void 207 RbnfRoundTripTest::TestDutchSpelloutRT() 208 { 209 UErrorCode status = U_ZERO_ERROR; 210 RuleBasedNumberFormat* formatter 211 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("nl", "NL"), status); 212 213 if (U_FAILURE(status)) { 214 errcheckln(status, "failed to construct formatter - %s", u_errorName(status)); 215 } else { 216 doTest(formatter, -12345678, 12345678); 217 } 218 delete formatter; 219 } 220 221 /** 222 * Perform an exhaustive round-trip test on the Japanese spellout rules 223 */ 224 void 225 RbnfRoundTripTest::TestJapaneseSpelloutRT() 226 { 227 UErrorCode status = U_ZERO_ERROR; 228 RuleBasedNumberFormat* formatter 229 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getJapan(), status); 230 231 if (U_FAILURE(status)) { 232 errcheckln(status, "failed to construct formatter - %s", u_errorName(status)); 233 } else { 234 doTest(formatter, 0, 12345678); 235 } 236 delete formatter; 237 } 238 239 /** 240 * Perform an exhaustive round-trip test on the Russian spellout rules 241 */ 242 void 243 RbnfRoundTripTest::TestRussianSpelloutRT() 244 { 245 UErrorCode status = U_ZERO_ERROR; 246 RuleBasedNumberFormat* formatter 247 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("ru", "RU"), status); 248 249 if (U_FAILURE(status)) { 250 errcheckln(status, "failed to construct formatter - %s", u_errorName(status)); 251 } else { 252 doTest(formatter, 0, 12345678); 253 } 254 delete formatter; 255 } 256 257 /** 258 * Perform an exhaustive round-trip test on the Portuguese spellout rules 259 */ 260 void 261 RbnfRoundTripTest::TestPortugueseSpelloutRT() 262 { 263 UErrorCode status = U_ZERO_ERROR; 264 RuleBasedNumberFormat* formatter 265 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("pt", "BR"), status); 266 267 if (U_FAILURE(status)) { 268 errcheckln(status, "failed to construct formatter - %s", u_errorName(status)); 269 } else { 270 doTest(formatter, -12345678, 12345678); 271 } 272 delete formatter; 273 } 274 275 void 276 RbnfRoundTripTest::doTest(const RuleBasedNumberFormat* formatter, 277 double lowLimit, 278 double highLimit) 279 { 280 char buf[128]; 281 282 uint32_t count = 0; 283 double increment = 1; 284 for (double i = lowLimit; i <= highLimit; i += increment) { 285 if (count % 1000 == 0) { 286 sprintf(buf, "%.12g", i); 287 logln(buf); 288 } 289 290 if (fabs(i) < 5000) 291 increment = 1; 292 else if (fabs(i) < 500000) 293 increment = 2737; 294 else 295 increment = 267437; 296 297 UnicodeString formatResult; 298 formatter->format(i, formatResult); 299 UErrorCode status = U_ZERO_ERROR; 300 Formattable parseResult; 301 formatter->parse(formatResult, parseResult, status); 302 if (U_FAILURE(status)) { 303 sprintf(buf, "Round-trip status failure: %.12g, status: %d", i, status); 304 errln(buf); 305 return; 306 } else { 307 double rt = (parseResult.getType() == Formattable::kDouble) ? 308 parseResult.getDouble() : 309 (double)parseResult.getLong(); 310 311 if (rt != i) { 312 sprintf(buf, "Round-trip failed: %.12g -> %.12g", i, rt); 313 errln(buf); 314 return; 315 } 316 } 317 318 ++count; 319 } 320 321 if (lowLimit < 0) { 322 double d = 1.234; 323 while (d < 1000) { 324 UnicodeString formatResult; 325 formatter->format(d, formatResult); 326 UErrorCode status = U_ZERO_ERROR; 327 Formattable parseResult; 328 formatter->parse(formatResult, parseResult, status); 329 if (U_FAILURE(status)) { 330 sprintf(buf, "Round-trip status failure: %.12g, status: %d", d, status); 331 errln(buf); 332 return; 333 } else { 334 double rt = (parseResult.getType() == Formattable::kDouble) ? 335 parseResult.getDouble() : 336 (double)parseResult.getLong(); 337 338 if (rt != d) { 339 UnicodeString msg; 340 sprintf(buf, "Round-trip failed: %.12g -> ", d); 341 msg.append(buf); 342 msg.append(formatResult); 343 sprintf(buf, " -> %.12g", rt); 344 msg.append(buf); 345 errln(msg); 346 return; 347 } 348 } 349 350 d *= 10; 351 } 352 } 353 } 354 355 /* U_HAVE_RBNF */ 356 #else 357 358 void 359 RbnfRoundTripTest::TestRBNFDisabled() { 360 errln("*** RBNF currently disabled on this platform ***\n"); 361 } 362 363 /* U_HAVE_RBNF */ 364 #endif 365 366 #endif /* #if !UCONFIG_NO_FORMATTING */ 367