1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *******************************************************************************
5 * Copyright (C) 1996-2016, 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 "itrbnf.h"
15
16 #include "unicode/umachine.h"
17
18 #include "unicode/tblcoll.h"
19 #include "unicode/coleitr.h"
20 #include "unicode/ures.h"
21 #include "unicode/ustring.h"
22 #include "unicode/decimfmt.h"
23 #include "unicode/udata.h"
24 #include "cmemory.h"
25 #include "putilimp.h"
26 #include "testutil.h"
27
28 #include <string.h>
29
30 // import com.ibm.text.RuleBasedNumberFormat;
31 // import com.ibm.test.TestFmwk;
32
33 // import java.util.Locale;
34 // import java.text.NumberFormat;
35
36 // current macro not in icu1.8.1
37 #define TESTCASE(id,test) \
38 case id: \
39 name = #test; \
40 if (exec) { \
41 logln(#test "---"); \
42 logln(); \
43 test(); \
44 } \
45 break
46
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)47 void IntlTestRBNF::runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par*/)
48 {
49 if (exec) logln("TestSuite RuleBasedNumberFormat");
50 switch (index) {
51 #if U_HAVE_RBNF
52 TESTCASE(0, TestEnglishSpellout);
53 TESTCASE(1, TestOrdinalAbbreviations);
54 TESTCASE(2, TestDurations);
55 TESTCASE(3, TestSpanishSpellout);
56 TESTCASE(4, TestFrenchSpellout);
57 TESTCASE(5, TestSwissFrenchSpellout);
58 TESTCASE(6, TestItalianSpellout);
59 TESTCASE(7, TestGermanSpellout);
60 TESTCASE(8, TestThaiSpellout);
61 TESTCASE(9, TestAPI);
62 TESTCASE(10, TestFractionalRuleSet);
63 TESTCASE(11, TestSwedishSpellout);
64 TESTCASE(12, TestBelgianFrenchSpellout);
65 TESTCASE(13, TestSmallValues);
66 TESTCASE(14, TestLocalizations);
67 TESTCASE(15, TestAllLocales);
68 TESTCASE(16, TestHebrewFraction);
69 TESTCASE(17, TestPortugueseSpellout);
70 TESTCASE(18, TestMultiplierSubstitution);
71 TESTCASE(19, TestSetDecimalFormatSymbols);
72 TESTCASE(20, TestPluralRules);
73 TESTCASE(21, TestMultiplePluralRules);
74 TESTCASE(22, TestInfinityNaN);
75 TESTCASE(23, TestVariableDecimalPoint);
76 #else
77 TESTCASE(0, TestRBNFDisabled);
78 #endif
79 default:
80 name = "";
81 break;
82 }
83 }
84
85 #if U_HAVE_RBNF
86
TestHebrewFraction()87 void IntlTestRBNF::TestHebrewFraction() {
88
89 // this is the expected output for 123.45, with no '<' in it.
90 UChar text1[] = {
91 0x05de, 0x05d0, 0x05d4, 0x0020,
92 0x05e2, 0x05e9, 0x05e8, 0x05d9, 0x05dd, 0x0020,
93 0x05d5, 0x05e9, 0x05dc, 0x05d5, 0x05e9, 0x0020,
94 0x05e0, 0x05e7, 0x05d5, 0x05d3, 0x05d4, 0x0020,
95 0x05d0, 0x05e8, 0x05d1, 0x05e2, 0x0020,
96 0x05d7, 0x05de, 0x05e9, 0x0000,
97 };
98 UChar text2[] = {
99 0x05DE, 0x05D0, 0x05D4, 0x0020,
100 0x05E2, 0x05E9, 0x05E8, 0x05D9, 0x05DD, 0x0020,
101 0x05D5, 0x05E9, 0x05DC, 0x05D5, 0x05E9, 0x0020,
102 0x05E0, 0x05E7, 0x05D5, 0x05D3, 0x05D4, 0x0020,
103 0x05D0, 0x05E4, 0x05E1, 0x0020,
104 0x05D0, 0x05E4, 0x05E1, 0x0020,
105 0x05D0, 0x05E8, 0x05D1, 0x05E2, 0x0020,
106 0x05D7, 0x05DE, 0x05E9, 0x0000,
107 };
108 UErrorCode status = U_ZERO_ERROR;
109 RuleBasedNumberFormat* formatter = new RuleBasedNumberFormat(URBNF_SPELLOUT, "he_IL", status);
110 if (status == U_MISSING_RESOURCE_ERROR || status == U_FILE_ACCESS_ERROR) {
111 errcheckln(status, "Failed in constructing RuleBasedNumberFormat - %s", u_errorName(status));
112 delete formatter;
113 return;
114 }
115 UnicodeString result;
116 Formattable parseResult;
117 ParsePosition pp(0);
118 {
119 UnicodeString expected(text1);
120 formatter->format(123.45, result);
121 if (result != expected) {
122 errln((UnicodeString)"expected '" + TestUtility::hex(expected) + "'\nbut got: '" + TestUtility::hex(result) + "'");
123 } else {
124 // formatter->parse(result, parseResult, pp);
125 // if (parseResult.getDouble() != 123.45) {
126 // errln("expected 123.45 but got: %g", parseResult.getDouble());
127 // }
128 }
129 }
130 {
131 UnicodeString expected(text2);
132 result.remove();
133 formatter->format(123.0045, result);
134 if (result != expected) {
135 errln((UnicodeString)"expected '" + TestUtility::hex(expected) + "'\nbut got: '" + TestUtility::hex(result) + "'");
136 } else {
137 pp.setIndex(0);
138 // formatter->parse(result, parseResult, pp);
139 // if (parseResult.getDouble() != 123.0045) {
140 // errln("expected 123.0045 but got: %g", parseResult.getDouble());
141 // }
142 }
143 }
144 delete formatter;
145 }
146
147 void
TestAPI()148 IntlTestRBNF::TestAPI() {
149 // This test goes through the APIs that were not tested before.
150 // These tests are too small to have separate test classes/functions
151
152 UErrorCode status = U_ZERO_ERROR;
153 RuleBasedNumberFormat* formatter
154 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getUS(), status);
155 if (status == U_MISSING_RESOURCE_ERROR || status == U_FILE_ACCESS_ERROR) {
156 dataerrln("Unable to create formatter. - %s", u_errorName(status));
157 delete formatter;
158 return;
159 }
160
161 logln("RBNF API test starting");
162 // test clone
163 {
164 logln("Testing Clone");
165 RuleBasedNumberFormat* rbnfClone = (RuleBasedNumberFormat *)formatter->clone();
166 if(rbnfClone != NULL) {
167 if(!(*rbnfClone == *formatter)) {
168 errln("Clone should be semantically equivalent to the original!");
169 }
170 delete rbnfClone;
171 } else {
172 errln("Cloning failed!");
173 }
174 }
175
176 // test assignment
177 {
178 logln("Testing assignment operator");
179 RuleBasedNumberFormat assignResult(URBNF_SPELLOUT, Locale("es", "ES", ""), status);
180 assignResult = *formatter;
181 if(!(assignResult == *formatter)) {
182 errln("Assignment result should be semantically equivalent to the original!");
183 }
184 }
185
186 // test rule constructor
187 {
188 logln("Testing rule constructor");
189 LocalUResourceBundlePointer en(ures_open(U_ICUDATA_NAME U_TREE_SEPARATOR_STRING "rbnf", "en", &status));
190 if(U_FAILURE(status)) {
191 errln("Unable to access resource bundle with data!");
192 } else {
193 int32_t ruleLen = 0;
194 int32_t len = 0;
195 LocalUResourceBundlePointer rbnfRules(ures_getByKey(en.getAlias(), "RBNFRules", NULL, &status));
196 LocalUResourceBundlePointer ruleSets(ures_getByKey(rbnfRules.getAlias(), "SpelloutRules", NULL, &status));
197 UnicodeString desc;
198 while (ures_hasNext(ruleSets.getAlias())) {
199 const UChar* currentString = ures_getNextString(ruleSets.getAlias(), &len, NULL, &status);
200 ruleLen += len;
201 desc.append(currentString);
202 }
203
204 const UChar *spelloutRules = desc.getTerminatedBuffer();
205
206 if(U_FAILURE(status) || ruleLen == 0 || spelloutRules == NULL) {
207 errln("Unable to access the rules string!");
208 } else {
209 UParseError perror;
210 RuleBasedNumberFormat ruleCtorResult(spelloutRules, Locale::getUS(), perror, status);
211 if(!(ruleCtorResult == *formatter)) {
212 errln("Formatter constructed from the original rules should be semantically equivalent to the original!");
213 }
214
215 // Jitterbug 4452, for coverage
216 RuleBasedNumberFormat nf(spelloutRules, (UnicodeString)"", Locale::getUS(), perror, status);
217 if(!(nf == *formatter)) {
218 errln("Formatter constructed from the original rules should be semantically equivalent to the original!");
219 }
220 }
221 }
222 }
223
224 // test getRules
225 {
226 logln("Testing getRules function");
227 UnicodeString rules = formatter->getRules();
228 UParseError perror;
229 RuleBasedNumberFormat fromRulesResult(rules, Locale::getUS(), perror, status);
230
231 if(!(fromRulesResult == *formatter)) {
232 errln("Formatter constructed from rules obtained by getRules should be semantically equivalent to the original!");
233 }
234 }
235
236
237 {
238 logln("Testing copy constructor");
239 RuleBasedNumberFormat copyCtorResult(*formatter);
240 if(!(copyCtorResult == *formatter)) {
241 errln("Copy constructor result result should be semantically equivalent to the original!");
242 }
243 }
244
245 #if !UCONFIG_NO_COLLATION
246 // test ruleset names
247 {
248 logln("Testing getNumberOfRuleSetNames, getRuleSetName and format using rule set names");
249 int32_t noOfRuleSetNames = formatter->getNumberOfRuleSetNames();
250 if(noOfRuleSetNames == 0) {
251 errln("Number of rule set names should be more than zero");
252 }
253 UnicodeString ruleSetName;
254 int32_t i = 0;
255 int32_t intFormatNum = 34567;
256 double doubleFormatNum = 893411.234;
257 logln("number of rule set names is %i", noOfRuleSetNames);
258 for(i = 0; i < noOfRuleSetNames; i++) {
259 FieldPosition pos1, pos2;
260 UnicodeString intFormatResult, doubleFormatResult;
261 Formattable intParseResult, doubleParseResult;
262
263 ruleSetName = formatter->getRuleSetName(i);
264 log("Rule set name %i is ", i);
265 log(ruleSetName);
266 logln(". Format results are: ");
267 intFormatResult = formatter->format(intFormatNum, ruleSetName, intFormatResult, pos1, status);
268 doubleFormatResult = formatter->format(doubleFormatNum, ruleSetName, doubleFormatResult, pos2, status);
269 if(U_FAILURE(status)) {
270 errln("Format using a rule set failed");
271 break;
272 }
273 logln(intFormatResult);
274 logln(doubleFormatResult);
275 formatter->setLenient(TRUE);
276 formatter->parse(intFormatResult, intParseResult, status);
277 formatter->parse(doubleFormatResult, doubleParseResult, status);
278
279 logln("Parse results for lenient = TRUE, %i, %f", intParseResult.getLong(), doubleParseResult.getDouble());
280
281 formatter->setLenient(FALSE);
282 formatter->parse(intFormatResult, intParseResult, status);
283 formatter->parse(doubleFormatResult, doubleParseResult, status);
284
285 logln("Parse results for lenient = FALSE, %i, %f", intParseResult.getLong(), doubleParseResult.getDouble());
286
287 if(U_FAILURE(status)) {
288 errln("Error during parsing");
289 }
290
291 intFormatResult = formatter->format(intFormatNum, "BLABLA", intFormatResult, pos1, status);
292 if(U_SUCCESS(status)) {
293 errln("Using invalid rule set name should have failed");
294 break;
295 }
296 status = U_ZERO_ERROR;
297 doubleFormatResult = formatter->format(doubleFormatNum, "TRUC", doubleFormatResult, pos2, status);
298 if(U_SUCCESS(status)) {
299 errln("Using invalid rule set name should have failed");
300 break;
301 }
302 status = U_ZERO_ERROR;
303 }
304 status = U_ZERO_ERROR;
305 }
306 #endif
307
308 // test API
309 UnicodeString expected("four point five","");
310 logln("Testing format(double)");
311 UnicodeString result;
312 formatter->format(4.5,result);
313 if(result != expected) {
314 errln("Formatted 4.5, expected " + expected + " got " + result);
315 } else {
316 logln("Formatted 4.5, expected " + expected + " got " + result);
317 }
318 result.remove();
319 expected = "four";
320 formatter->format((int32_t)4,result);
321 if(result != expected) {
322 errln("Formatted 4, expected " + expected + " got " + result);
323 } else {
324 logln("Formatted 4, expected " + expected + " got " + result);
325 }
326
327 result.remove();
328 FieldPosition pos;
329 formatter->format((int64_t)4, result, pos, status = U_ZERO_ERROR);
330 if(result != expected) {
331 errln("Formatted 4 int64_t, expected " + expected + " got " + result);
332 } else {
333 logln("Formatted 4 int64_t, expected " + expected + " got " + result);
334 }
335
336 //Jitterbug 4452, for coverage
337 result.remove();
338 FieldPosition pos2;
339 formatter->format((int64_t)4, formatter->getRuleSetName(0), result, pos2, status = U_ZERO_ERROR);
340 if(result != expected) {
341 errln("Formatted 4 int64_t, expected " + expected + " got " + result);
342 } else {
343 logln("Formatted 4 int64_t, expected " + expected + " got " + result);
344 }
345
346 // clean up
347 logln("Cleaning up");
348 delete formatter;
349 }
350
351 /**
352 * Perform a simple spot check on the parsing going into an infinite loop for alternate rules.
353 */
TestMultiplePluralRules()354 void IntlTestRBNF::TestMultiplePluralRules() {
355 // This is trying to model the feminine form, but don't worry about the details too much.
356 // We're trying to test the plural rules where there are different prefixes.
357 UnicodeString rules("%spellout-cardinal-feminine-genitive:"
358 "0: zero;"
359 "1: ono;"
360 "2: two;"
361 "1000: << $(cardinal,one{thousand}few{thousanF}other{thousanO})$[ >>];"
362 "%spellout-cardinal-feminine:"
363 "x.x: [<< $(cardinal,one{singleton}other{plurality})$ ]>%%fractions>;"
364 "0: zero;"
365 "1: one;"
366 "2: two;"
367 "1000: << $(cardinal,one{thousand}few{thousanF}other{thousanO})$[ >>];"
368 "%%fractions:"
369 "10: <%spellout-cardinal-feminine< $(cardinal,one{oneth}other{tenth})$;"
370 "100: <%spellout-cardinal-feminine< $(cardinal,one{1hundredth}other{hundredth})$;");
371 UErrorCode status = U_ZERO_ERROR;
372 UParseError pError;
373 RuleBasedNumberFormat formatter(rules, Locale("ru"), pError, status);
374 Formattable result;
375 UnicodeString resultStr;
376 FieldPosition pos;
377
378 if (U_FAILURE(status)) {
379 dataerrln("Unable to create formatter - %s", u_errorName(status));
380 return;
381 }
382
383 formatter.parse(formatter.format(1000.0, resultStr, pos, status), result, status);
384 if (1000 != result.getLong() || resultStr != UNICODE_STRING_SIMPLE("one thousand")) {
385 errln("RuleBasedNumberFormat did not return the correct value. Got: %d", result.getLong());
386 errln(resultStr);
387 }
388 resultStr.remove();
389 formatter.parse(formatter.format(1000.0, UnicodeString("%spellout-cardinal-feminine-genitive"), resultStr, pos, status), result, status);
390 if (1000 != result.getLong() || resultStr != UNICODE_STRING_SIMPLE("ono thousand")) {
391 errln("RuleBasedNumberFormat(cardinal-feminine-genitive) did not return the correct value. Got: %d", result.getLong());
392 errln(resultStr);
393 }
394 resultStr.remove();
395 formatter.parse(formatter.format(1000.0, UnicodeString("%spellout-cardinal-feminine"), resultStr, pos, status), result, status);
396 if (1000 != result.getLong() || resultStr != UNICODE_STRING_SIMPLE("one thousand")) {
397 errln("RuleBasedNumberFormat(spellout-cardinal-feminine) did not return the correct value. Got: %d", result.getLong());
398 errln(resultStr);
399 }
400 static const char* const testData[][2] = {
401 { "0", "zero" },
402 { "1", "one" },
403 { "2", "two" },
404 { "0.1", "one oneth" },
405 { "0.2", "two tenth" },
406 { "1.1", "one singleton one oneth" },
407 { "1.2", "one singleton two tenth" },
408 { "2.1", "two plurality one oneth" },
409 { "2.2", "two plurality two tenth" },
410 { "0.01", "one 1hundredth" },
411 { "0.02", "two hundredth" },
412 { NULL, NULL }
413 };
414 doTest(&formatter, testData, TRUE);
415 }
416
TestFractionalRuleSet()417 void IntlTestRBNF::TestFractionalRuleSet()
418 {
419 UnicodeString fracRules(
420 "%main:\n"
421 // this rule formats the number if it's 1 or more. It formats
422 // the integral part using a DecimalFormat ("#,##0" puts
423 // thousands separators in the right places) and the fractional
424 // part using %%frac. If there is no fractional part, it
425 // just shows the integral part.
426 " x.0: <#,##0<[ >%%frac>];\n"
427 // this rule formats the number if it's between 0 and 1. It
428 // shows only the fractional part (0.5 shows up as "1/2," not
429 // "0 1/2")
430 " 0.x: >%%frac>;\n"
431 // the fraction rule set. This works the same way as the one in the
432 // preceding example: We multiply the fractional part of the number
433 // being formatted by each rule's base value and use the rule that
434 // produces the result closest to 0 (or the first rule that produces 0).
435 // Since we only provide rules for the numbers from 2 to 10, we know
436 // we'll get a fraction with a denominator between 2 and 10.
437 // "<0<" causes the numerator of the fraction to be formatted
438 // using numerals
439 "%%frac:\n"
440 " 2: 1/2;\n"
441 " 3: <0</3;\n"
442 " 4: <0</4;\n"
443 " 5: <0</5;\n"
444 " 6: <0</6;\n"
445 " 7: <0</7;\n"
446 " 8: <0</8;\n"
447 " 9: <0</9;\n"
448 " 10: <0</10;\n");
449
450 // mondo hack
451 int len = fracRules.length();
452 int change = 2;
453 for (int i = 0; i < len; ++i) {
454 UChar ch = fracRules.charAt(i);
455 if (ch == '\n') {
456 change = 2; // change ok
457 } else if (ch == ':') {
458 change = 1; // change, but once we hit a non-space char, don't change
459 } else if (ch == ' ') {
460 if (change != 0) {
461 fracRules.setCharAt(i, (UChar)0x200e);
462 }
463 } else {
464 if (change == 1) {
465 change = 0;
466 }
467 }
468 }
469
470 UErrorCode status = U_ZERO_ERROR;
471 UParseError perror;
472 RuleBasedNumberFormat formatter(fracRules, Locale::getEnglish(), perror, status);
473 if (U_FAILURE(status)) {
474 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
475 } else {
476 static const char* const testData[][2] = {
477 { "0", "0" },
478 { ".1", "1/10" },
479 { ".11", "1/9" },
480 { ".125", "1/8" },
481 { ".1428", "1/7" },
482 { ".1667", "1/6" },
483 { ".2", "1/5" },
484 { ".25", "1/4" },
485 { ".333", "1/3" },
486 { ".5", "1/2" },
487 { "1.1", "1 1/10" },
488 { "2.11", "2 1/9" },
489 { "3.125", "3 1/8" },
490 { "4.1428", "4 1/7" },
491 { "5.1667", "5 1/6" },
492 { "6.2", "6 1/5" },
493 { "7.25", "7 1/4" },
494 { "8.333", "8 1/3" },
495 { "9.5", "9 1/2" },
496 { ".2222", "2/9" },
497 { ".4444", "4/9" },
498 { ".5555", "5/9" },
499 { "1.2856", "1 2/7" },
500 { NULL, NULL }
501 };
502 doTest(&formatter, testData, FALSE); // exact values aren't parsable from fractions
503 }
504 }
505
506 #if 0
507 #define LLAssert(a) \
508 if (!(a)) errln("FAIL: " #a)
509
510 void IntlTestRBNF::TestLLongConstructors()
511 {
512 logln("Testing constructors");
513
514 // constant (shouldn't really be public)
515 LLAssert(llong(llong::kD32).asDouble() == llong::kD32);
516
517 // internal constructor (shouldn't really be public)
518 LLAssert(llong(0, 1).asDouble() == 1);
519 LLAssert(llong(1, 0).asDouble() == llong::kD32);
520 LLAssert(llong((uint32_t)-1, (uint32_t)-1).asDouble() == -1);
521
522 // public empty constructor
523 LLAssert(llong().asDouble() == 0);
524
525 // public int32_t constructor
526 LLAssert(llong((int32_t)0).asInt() == (int32_t)0);
527 LLAssert(llong((int32_t)1).asInt() == (int32_t)1);
528 LLAssert(llong((int32_t)-1).asInt() == (int32_t)-1);
529 LLAssert(llong((int32_t)0x7fffffff).asInt() == (int32_t)0x7fffffff);
530 LLAssert(llong((int32_t)0xffffffff).asInt() == (int32_t)-1);
531 LLAssert(llong((int32_t)0x80000000).asInt() == (int32_t)0x80000000);
532
533 // public int16_t constructor
534 LLAssert(llong((int16_t)0).asInt() == (int16_t)0);
535 LLAssert(llong((int16_t)1).asInt() == (int16_t)1);
536 LLAssert(llong((int16_t)-1).asInt() == (int16_t)-1);
537 LLAssert(llong((int16_t)0x7fff).asInt() == (int16_t)0x7fff);
538 LLAssert(llong((int16_t)0xffff).asInt() == (int16_t)0xffff);
539 LLAssert(llong((int16_t)0x8000).asInt() == (int16_t)0x8000);
540
541 // public int8_t constructor
542 LLAssert(llong((int8_t)0).asInt() == (int8_t)0);
543 LLAssert(llong((int8_t)1).asInt() == (int8_t)1);
544 LLAssert(llong((int8_t)-1).asInt() == (int8_t)-1);
545 LLAssert(llong((int8_t)0x7f).asInt() == (int8_t)0x7f);
546 LLAssert(llong((int8_t)0xff).asInt() == (int8_t)0xff);
547 LLAssert(llong((int8_t)0x80).asInt() == (int8_t)0x80);
548
549 // public uint16_t constructor
550 LLAssert(llong((uint16_t)0).asUInt() == (uint16_t)0);
551 LLAssert(llong((uint16_t)1).asUInt() == (uint16_t)1);
552 LLAssert(llong((uint16_t)-1).asUInt() == (uint16_t)-1);
553 LLAssert(llong((uint16_t)0x7fff).asUInt() == (uint16_t)0x7fff);
554 LLAssert(llong((uint16_t)0xffff).asUInt() == (uint16_t)0xffff);
555 LLAssert(llong((uint16_t)0x8000).asUInt() == (uint16_t)0x8000);
556
557 // public uint32_t constructor
558 LLAssert(llong((uint32_t)0).asUInt() == (uint32_t)0);
559 LLAssert(llong((uint32_t)1).asUInt() == (uint32_t)1);
560 LLAssert(llong((uint32_t)-1).asUInt() == (uint32_t)-1);
561 LLAssert(llong((uint32_t)0x7fffffff).asUInt() == (uint32_t)0x7fffffff);
562 LLAssert(llong((uint32_t)0xffffffff).asUInt() == (uint32_t)-1);
563 LLAssert(llong((uint32_t)0x80000000).asUInt() == (uint32_t)0x80000000);
564
565 // public double constructor
566 LLAssert(llong((double)0).asDouble() == (double)0);
567 LLAssert(llong((double)1).asDouble() == (double)1);
568 LLAssert(llong((double)0x7fffffff).asDouble() == (double)0x7fffffff);
569 LLAssert(llong((double)0x80000000).asDouble() == (double)0x80000000);
570 LLAssert(llong((double)0x80000001).asDouble() == (double)0x80000001);
571
572 // can't access uprv_maxmantissa, so fake it
573 double maxmantissa = (llong((int32_t)1) << 40).asDouble();
574 LLAssert(llong(maxmantissa).asDouble() == maxmantissa);
575 LLAssert(llong(-maxmantissa).asDouble() == -maxmantissa);
576
577 // copy constructor
578 LLAssert(llong(llong(0, 1)).asDouble() == 1);
579 LLAssert(llong(llong(1, 0)).asDouble() == llong::kD32);
580 LLAssert(llong(llong(-1, (uint32_t)-1)).asDouble() == -1);
581
582 // asInt - test unsigned to signed narrowing conversion
583 LLAssert(llong((uint32_t)-1).asInt() == (int32_t)0x7fffffff);
584 LLAssert(llong(-1, 0).asInt() == (int32_t)0x80000000);
585
586 // asUInt - test signed to unsigned narrowing conversion
587 LLAssert(llong((int32_t)-1).asUInt() == (uint32_t)-1);
588 LLAssert(llong((int32_t)0x80000000).asUInt() == (uint32_t)0x80000000);
589
590 // asDouble already tested
591
592 }
593
594 void IntlTestRBNF::TestLLongSimpleOperators()
595 {
596 logln("Testing simple operators");
597
598 // operator==
599 LLAssert(llong() == llong(0, 0));
600 LLAssert(llong(1,0) == llong(1, 0));
601 LLAssert(llong(0,1) == llong(0, 1));
602
603 // operator!=
604 LLAssert(llong(1,0) != llong(1,1));
605 LLAssert(llong(0,1) != llong(1,1));
606 LLAssert(llong(0xffffffff,0xffffffff) != llong(0x7fffffff, 0xffffffff));
607
608 // unsigned >
609 LLAssert(llong((int32_t)-1).ugt(llong(0x7fffffff, 0xffffffff)));
610
611 // unsigned <
612 LLAssert(llong(0x7fffffff, 0xffffffff).ult(llong((int32_t)-1)));
613
614 // unsigned >=
615 LLAssert(llong((int32_t)-1).uge(llong(0x7fffffff, 0xffffffff)));
616 LLAssert(llong((int32_t)-1).uge(llong((int32_t)-1)));
617
618 // unsigned <=
619 LLAssert(llong(0x7fffffff, 0xffffffff).ule(llong((int32_t)-1)));
620 LLAssert(llong((int32_t)-1).ule(llong((int32_t)-1)));
621
622 // operator>
623 LLAssert(llong(1, 1) > llong(1, 0));
624 LLAssert(llong(0, 0x80000000) > llong(0, 0x7fffffff));
625 LLAssert(llong(0x80000000, 1) > llong(0x80000000, 0));
626 LLAssert(llong(1, 0) > llong(0, 0x7fffffff));
627 LLAssert(llong(1, 0) > llong(0, 0xffffffff));
628 LLAssert(llong(0, 0) > llong(0x80000000, 1));
629
630 // operator<
631 LLAssert(llong(1, 0) < llong(1, 1));
632 LLAssert(llong(0, 0x7fffffff) < llong(0, 0x80000000));
633 LLAssert(llong(0x80000000, 0) < llong(0x80000000, 1));
634 LLAssert(llong(0, 0x7fffffff) < llong(1, 0));
635 LLAssert(llong(0, 0xffffffff) < llong(1, 0));
636 LLAssert(llong(0x80000000, 1) < llong(0, 0));
637
638 // operator>=
639 LLAssert(llong(1, 1) >= llong(1, 0));
640 LLAssert(llong(0, 0x80000000) >= llong(0, 0x7fffffff));
641 LLAssert(llong(0x80000000, 1) >= llong(0x80000000, 0));
642 LLAssert(llong(1, 0) >= llong(0, 0x7fffffff));
643 LLAssert(llong(1, 0) >= llong(0, 0xffffffff));
644 LLAssert(llong(0, 0) >= llong(0x80000000, 1));
645 LLAssert(llong() >= llong(0, 0));
646 LLAssert(llong(1,0) >= llong(1, 0));
647 LLAssert(llong(0,1) >= llong(0, 1));
648
649 // operator<=
650 LLAssert(llong(1, 0) <= llong(1, 1));
651 LLAssert(llong(0, 0x7fffffff) <= llong(0, 0x80000000));
652 LLAssert(llong(0x80000000, 0) <= llong(0x80000000, 1));
653 LLAssert(llong(0, 0x7fffffff) <= llong(1, 0));
654 LLAssert(llong(0, 0xffffffff) <= llong(1, 0));
655 LLAssert(llong(0x80000000, 1) <= llong(0, 0));
656 LLAssert(llong() <= llong(0, 0));
657 LLAssert(llong(1,0) <= llong(1, 0));
658 LLAssert(llong(0,1) <= llong(0, 1));
659
660 // operator==(int32)
661 LLAssert(llong() == (int32_t)0);
662 LLAssert(llong(0,1) == (int32_t)1);
663
664 // operator!=(int32)
665 LLAssert(llong(1,0) != (int32_t)0);
666 LLAssert(llong(0,1) != (int32_t)2);
667 LLAssert(llong(0,0xffffffff) != (int32_t)-1);
668
669 llong negOne(0xffffffff, 0xffffffff);
670
671 // operator>(int32)
672 LLAssert(llong(0, 0x80000000) > (int32_t)0x7fffffff);
673 LLAssert(negOne > (int32_t)-2);
674 LLAssert(llong(1, 0) > (int32_t)0x7fffffff);
675 LLAssert(llong(0, 0) > (int32_t)-1);
676
677 // operator<(int32)
678 LLAssert(llong(0, 0x7ffffffe) < (int32_t)0x7fffffff);
679 LLAssert(llong(0xffffffff, 0xfffffffe) < (int32_t)-1);
680
681 // operator>=(int32)
682 LLAssert(llong(0, 0x80000000) >= (int32_t)0x7fffffff);
683 LLAssert(negOne >= (int32_t)-2);
684 LLAssert(llong(1, 0) >= (int32_t)0x7fffffff);
685 LLAssert(llong(0, 0) >= (int32_t)-1);
686 LLAssert(llong() >= (int32_t)0);
687 LLAssert(llong(0,1) >= (int32_t)1);
688
689 // operator<=(int32)
690 LLAssert(llong(0, 0x7ffffffe) <= (int32_t)0x7fffffff);
691 LLAssert(llong(0xffffffff, 0xfffffffe) <= (int32_t)-1);
692 LLAssert(llong() <= (int32_t)0);
693 LLAssert(llong(0,1) <= (int32_t)1);
694
695 // operator=
696 LLAssert((llong(2,3) = llong((uint32_t)-1)).asUInt() == (uint32_t)-1);
697
698 // operator <<=
699 LLAssert((llong(1, 1) <<= 0) == llong(1, 1));
700 LLAssert((llong(1, 1) <<= 31) == llong(0x80000000, 0x80000000));
701 LLAssert((llong(1, 1) <<= 32) == llong(1, 0));
702 LLAssert((llong(1, 1) <<= 63) == llong(0x80000000, 0));
703 LLAssert((llong(1, 1) <<= 64) == llong(1, 1)); // only lower 6 bits are used
704 LLAssert((llong(1, 1) <<= -1) == llong(0x80000000, 0)); // only lower 6 bits are used
705
706 // operator <<
707 LLAssert((llong((int32_t)1) << 5).asUInt() == 32);
708
709 // operator >>= (sign extended)
710 LLAssert((llong(0x7fffa0a0, 0xbcbcdfdf) >>= 16) == llong(0x7fff,0xa0a0bcbc));
711 LLAssert((llong(0x8000789a, 0xbcde0000) >>= 16) == llong(0xffff8000,0x789abcde));
712 LLAssert((llong(0x80000000, 0) >>= 63) == llong(0xffffffff, 0xffffffff));
713 LLAssert((llong(0x80000000, 0) >>= 47) == llong(0xffffffff, 0xffff0000));
714 LLAssert((llong(0x80000000, 0x80000000) >> 64) == llong(0x80000000, 0x80000000)); // only lower 6 bits are used
715 LLAssert((llong(0x80000000, 0) >>= -1) == llong(0xffffffff, 0xffffffff)); // only lower 6 bits are used
716
717 // operator >> sign extended)
718 LLAssert((llong(0x8000789a, 0xbcde0000) >> 16) == llong(0xffff8000,0x789abcde));
719
720 // ushr (right shift without sign extension)
721 LLAssert(llong(0x7fffa0a0, 0xbcbcdfdf).ushr(16) == llong(0x7fff,0xa0a0bcbc));
722 LLAssert(llong(0x8000789a, 0xbcde0000).ushr(16) == llong(0x00008000,0x789abcde));
723 LLAssert(llong(0x80000000, 0).ushr(63) == llong(0, 1));
724 LLAssert(llong(0x80000000, 0).ushr(47) == llong(0, 0x10000));
725 LLAssert(llong(0x80000000, 0x80000000).ushr(64) == llong(0x80000000, 0x80000000)); // only lower 6 bits are used
726 LLAssert(llong(0x80000000, 0).ushr(-1) == llong(0, 1)); // only lower 6 bits are used
727
728 // operator&(llong)
729 LLAssert((llong(0x55555555, 0x55555555) & llong(0xaaaaffff, 0xffffaaaa)) == llong(0x00005555, 0x55550000));
730
731 // operator|(llong)
732 LLAssert((llong(0x55555555, 0x55555555) | llong(0xaaaaffff, 0xffffaaaa)) == llong(0xffffffff, 0xffffffff));
733
734 // operator^(llong)
735 LLAssert((llong(0x55555555, 0x55555555) ^ llong(0xaaaaffff, 0xffffaaaa)) == llong(0xffffaaaa, 0xaaaaffff));
736
737 // operator&(uint32)
738 LLAssert((llong(0x55555555, 0x55555555) & (uint32_t)0xffffaaaa) == llong(0, 0x55550000));
739
740 // operator|(uint32)
741 LLAssert((llong(0x55555555, 0x55555555) | (uint32_t)0xffffaaaa) == llong(0x55555555, 0xffffffff));
742
743 // operator^(uint32)
744 LLAssert((llong(0x55555555, 0x55555555) ^ (uint32_t)0xffffaaaa) == llong(0x55555555, 0xaaaaffff));
745
746 // operator~
747 LLAssert(~llong(0x55555555, 0x55555555) == llong(0xaaaaaaaa, 0xaaaaaaaa));
748
749 // operator&=(llong)
750 LLAssert((llong(0x55555555, 0x55555555) &= llong(0xaaaaffff, 0xffffaaaa)) == llong(0x00005555, 0x55550000));
751
752 // operator|=(llong)
753 LLAssert((llong(0x55555555, 0x55555555) |= llong(0xaaaaffff, 0xffffaaaa)) == llong(0xffffffff, 0xffffffff));
754
755 // operator^=(llong)
756 LLAssert((llong(0x55555555, 0x55555555) ^= llong(0xaaaaffff, 0xffffaaaa)) == llong(0xffffaaaa, 0xaaaaffff));
757
758 // operator&=(uint32)
759 LLAssert((llong(0x55555555, 0x55555555) &= (uint32_t)0xffffaaaa) == llong(0, 0x55550000));
760
761 // operator|=(uint32)
762 LLAssert((llong(0x55555555, 0x55555555) |= (uint32_t)0xffffaaaa) == llong(0x55555555, 0xffffffff));
763
764 // operator^=(uint32)
765 LLAssert((llong(0x55555555, 0x55555555) ^= (uint32_t)0xffffaaaa) == llong(0x55555555, 0xaaaaffff));
766
767 // prefix inc
768 LLAssert(llong(1, 0) == ++llong(0,0xffffffff));
769
770 // prefix dec
771 LLAssert(llong(0,0xffffffff) == --llong(1, 0));
772
773 // postfix inc
774 {
775 llong n(0, 0xffffffff);
776 LLAssert(llong(0, 0xffffffff) == n++);
777 LLAssert(llong(1, 0) == n);
778 }
779
780 // postfix dec
781 {
782 llong n(1, 0);
783 LLAssert(llong(1, 0) == n--);
784 LLAssert(llong(0, 0xffffffff) == n);
785 }
786
787 // unary minus
788 LLAssert(llong(0, 0) == -llong(0, 0));
789 LLAssert(llong(0xffffffff, 0xffffffff) == -llong(0, 1));
790 LLAssert(llong(0, 1) == -llong(0xffffffff, 0xffffffff));
791 LLAssert(llong(0x7fffffff, 0xffffffff) == -llong(0x80000000, 1));
792 LLAssert(llong(0x80000000, 0) == -llong(0x80000000, 0)); // !!! we don't handle overflow
793
794 // operator-=
795 {
796 llong n;
797 LLAssert((n -= llong(0, 1)) == llong(0xffffffff, 0xffffffff));
798 LLAssert(n == llong(0xffffffff, 0xffffffff));
799
800 n = llong(1, 0);
801 LLAssert((n -= llong(0, 1)) == llong(0, 0xffffffff));
802 LLAssert(n == llong(0, 0xffffffff));
803 }
804
805 // operator-
806 {
807 llong n;
808 LLAssert((n - llong(0, 1)) == llong(0xffffffff, 0xffffffff));
809 LLAssert(n == llong(0, 0));
810
811 n = llong(1, 0);
812 LLAssert((n - llong(0, 1)) == llong(0, 0xffffffff));
813 LLAssert(n == llong(1, 0));
814 }
815
816 // operator+=
817 {
818 llong n(0xffffffff, 0xffffffff);
819 LLAssert((n += llong(0, 1)) == llong(0, 0));
820 LLAssert(n == llong(0, 0));
821
822 n = llong(0, 0xffffffff);
823 LLAssert((n += llong(0, 1)) == llong(1, 0));
824 LLAssert(n == llong(1, 0));
825 }
826
827 // operator+
828 {
829 llong n(0xffffffff, 0xffffffff);
830 LLAssert((n + llong(0, 1)) == llong(0, 0));
831 LLAssert(n == llong(0xffffffff, 0xffffffff));
832
833 n = llong(0, 0xffffffff);
834 LLAssert((n + llong(0, 1)) == llong(1, 0));
835 LLAssert(n == llong(0, 0xffffffff));
836 }
837
838 }
839
840 void IntlTestRBNF::TestLLong()
841 {
842 logln("Starting TestLLong");
843
844 TestLLongConstructors();
845
846 TestLLongSimpleOperators();
847
848 logln("Testing operator*=, operator*");
849
850 // operator*=, operator*
851 // small and large values, positive, &NEGative, zero
852 // also test commutivity
853 {
854 const llong ZERO;
855 const llong ONE(0, 1);
856 const llong NEG_ONE((int32_t)-1);
857 const llong THREE(0, 3);
858 const llong NEG_THREE((int32_t)-3);
859 const llong TWO_TO_16(0, 0x10000);
860 const llong NEG_TWO_TO_16 = -TWO_TO_16;
861 const llong TWO_TO_32(1, 0);
862 const llong NEG_TWO_TO_32 = -TWO_TO_32;
863
864 const llong NINE(0, 9);
865 const llong NEG_NINE = -NINE;
866
867 const llong TWO_TO_16X3(0, 0x00030000);
868 const llong NEG_TWO_TO_16X3 = -TWO_TO_16X3;
869
870 const llong TWO_TO_32X3(3, 0);
871 const llong NEG_TWO_TO_32X3 = -TWO_TO_32X3;
872
873 const llong TWO_TO_48(0x10000, 0);
874 const llong NEG_TWO_TO_48 = -TWO_TO_48;
875
876 const int32_t VALUE_WIDTH = 9;
877 const llong* values[VALUE_WIDTH] = {
878 &ZERO, &ONE, &NEG_ONE, &THREE, &NEG_THREE, &TWO_TO_16, &NEG_TWO_TO_16, &TWO_TO_32, &NEG_TWO_TO_32
879 };
880
881 const llong* answers[VALUE_WIDTH*VALUE_WIDTH] = {
882 &ZERO, &ZERO, &ZERO, &ZERO, &ZERO, &ZERO, &ZERO, &ZERO, &ZERO,
883 &ZERO, &ONE, &NEG_ONE, &THREE, &NEG_THREE, &TWO_TO_16, &NEG_TWO_TO_16, &TWO_TO_32, &NEG_TWO_TO_32,
884 &ZERO, &NEG_ONE, &ONE, &NEG_THREE, &THREE, &NEG_TWO_TO_16, &TWO_TO_16, &NEG_TWO_TO_32, &TWO_TO_32,
885 &ZERO, &THREE, &NEG_THREE, &NINE, &NEG_NINE, &TWO_TO_16X3, &NEG_TWO_TO_16X3, &TWO_TO_32X3, &NEG_TWO_TO_32X3,
886 &ZERO, &NEG_THREE, &THREE, &NEG_NINE, &NINE, &NEG_TWO_TO_16X3, &TWO_TO_16X3, &NEG_TWO_TO_32X3, &TWO_TO_32X3,
887 &ZERO, &TWO_TO_16, &NEG_TWO_TO_16, &TWO_TO_16X3, &NEG_TWO_TO_16X3, &TWO_TO_32, &NEG_TWO_TO_32, &TWO_TO_48, &NEG_TWO_TO_48,
888 &ZERO, &NEG_TWO_TO_16, &TWO_TO_16, &NEG_TWO_TO_16X3, &TWO_TO_16X3, &NEG_TWO_TO_32, &TWO_TO_32, &NEG_TWO_TO_48, &TWO_TO_48,
889 &ZERO, &TWO_TO_32, &NEG_TWO_TO_32, &TWO_TO_32X3, &NEG_TWO_TO_32X3, &TWO_TO_48, &NEG_TWO_TO_48, &ZERO, &ZERO,
890 &ZERO, &NEG_TWO_TO_32, &TWO_TO_32, &NEG_TWO_TO_32X3, &TWO_TO_32X3, &NEG_TWO_TO_48, &TWO_TO_48, &ZERO, &ZERO
891 };
892
893 for (int i = 0; i < VALUE_WIDTH; ++i) {
894 for (int j = 0; j < VALUE_WIDTH; ++j) {
895 llong lhs = *values[i];
896 llong rhs = *values[j];
897 llong ans = *answers[i*VALUE_WIDTH + j];
898
899 llong n = lhs;
900
901 LLAssert((n *= rhs) == ans);
902 LLAssert(n == ans);
903
904 n = lhs;
905 LLAssert((n * rhs) == ans);
906 LLAssert(n == lhs);
907 }
908 }
909 }
910
911 logln("Testing operator/=, operator/");
912 // operator/=, operator/
913 // test num = 0, div = 0, pos/neg, > 2^32, div > num
914 {
915 const llong ZERO;
916 const llong ONE(0, 1);
917 const llong NEG_ONE = -ONE;
918 const llong MAX(0x7fffffff, 0xffffffff);
919 const llong MIN(0x80000000, 0);
920 const llong TWO(0, 2);
921 const llong NEG_TWO = -TWO;
922 const llong FIVE(0, 5);
923 const llong NEG_FIVE = -FIVE;
924 const llong TWO_TO_32(1, 0);
925 const llong NEG_TWO_TO_32 = -TWO_TO_32;
926 const llong TWO_TO_32d5 = llong(TWO_TO_32.asDouble()/5.0);
927 const llong NEG_TWO_TO_32d5 = -TWO_TO_32d5;
928 const llong TWO_TO_32X5 = TWO_TO_32 * FIVE;
929 const llong NEG_TWO_TO_32X5 = -TWO_TO_32X5;
930
931 const llong* tuples[] = { // lhs, rhs, ans
932 &ZERO, &ZERO, &ZERO,
933 &ONE, &ZERO,&MAX,
934 &NEG_ONE, &ZERO, &MIN,
935 &ONE, &ONE, &ONE,
936 &ONE, &NEG_ONE, &NEG_ONE,
937 &NEG_ONE, &ONE, &NEG_ONE,
938 &NEG_ONE, &NEG_ONE, &ONE,
939 &FIVE, &TWO, &TWO,
940 &FIVE, &NEG_TWO, &NEG_TWO,
941 &NEG_FIVE, &TWO, &NEG_TWO,
942 &NEG_FIVE, &NEG_TWO, &TWO,
943 &TWO, &FIVE, &ZERO,
944 &TWO, &NEG_FIVE, &ZERO,
945 &NEG_TWO, &FIVE, &ZERO,
946 &NEG_TWO, &NEG_FIVE, &ZERO,
947 &TWO_TO_32, &TWO_TO_32, &ONE,
948 &TWO_TO_32, &NEG_TWO_TO_32, &NEG_ONE,
949 &NEG_TWO_TO_32, &TWO_TO_32, &NEG_ONE,
950 &NEG_TWO_TO_32, &NEG_TWO_TO_32, &ONE,
951 &TWO_TO_32, &FIVE, &TWO_TO_32d5,
952 &TWO_TO_32, &NEG_FIVE, &NEG_TWO_TO_32d5,
953 &NEG_TWO_TO_32, &FIVE, &NEG_TWO_TO_32d5,
954 &NEG_TWO_TO_32, &NEG_FIVE, &TWO_TO_32d5,
955 &TWO_TO_32X5, &FIVE, &TWO_TO_32,
956 &TWO_TO_32X5, &NEG_FIVE, &NEG_TWO_TO_32,
957 &NEG_TWO_TO_32X5, &FIVE, &NEG_TWO_TO_32,
958 &NEG_TWO_TO_32X5, &NEG_FIVE, &TWO_TO_32,
959 &TWO_TO_32X5, &TWO_TO_32, &FIVE,
960 &TWO_TO_32X5, &NEG_TWO_TO_32, &NEG_FIVE,
961 &NEG_TWO_TO_32X5, &NEG_TWO_TO_32, &FIVE,
962 &NEG_TWO_TO_32X5, &TWO_TO_32, &NEG_FIVE
963 };
964 const int TUPLE_WIDTH = 3;
965 const int TUPLE_COUNT = UPRV_LENGTHOF(tuples)/TUPLE_WIDTH;
966 for (int i = 0; i < TUPLE_COUNT; ++i) {
967 const llong lhs = *tuples[i*TUPLE_WIDTH+0];
968 const llong rhs = *tuples[i*TUPLE_WIDTH+1];
969 const llong ans = *tuples[i*TUPLE_WIDTH+2];
970
971 llong n = lhs;
972 if (!((n /= rhs) == ans)) {
973 errln("fail: (n /= rhs) == ans");
974 }
975 LLAssert(n == ans);
976
977 n = lhs;
978 LLAssert((n / rhs) == ans);
979 LLAssert(n == lhs);
980 }
981 }
982
983 logln("Testing operator%%=, operator%%");
984 //operator%=, operator%
985 {
986 const llong ZERO;
987 const llong ONE(0, 1);
988 const llong TWO(0, 2);
989 const llong THREE(0,3);
990 const llong FOUR(0, 4);
991 const llong FIVE(0, 5);
992 const llong SIX(0, 6);
993
994 const llong NEG_ONE = -ONE;
995 const llong NEG_TWO = -TWO;
996 const llong NEG_THREE = -THREE;
997 const llong NEG_FOUR = -FOUR;
998 const llong NEG_FIVE = -FIVE;
999 const llong NEG_SIX = -SIX;
1000
1001 const llong NINETY_NINE(0, 99);
1002 const llong HUNDRED(0, 100);
1003 const llong HUNDRED_ONE(0, 101);
1004
1005 const llong BIG(0x12345678, 0x9abcdef0);
1006 const llong BIG_FIVE(BIG * FIVE);
1007 const llong BIG_FIVEm1 = BIG_FIVE - ONE;
1008 const llong BIG_FIVEp1 = BIG_FIVE + ONE;
1009
1010 const llong* tuples[] = {
1011 &ZERO, &FIVE, &ZERO,
1012 &ONE, &FIVE, &ONE,
1013 &TWO, &FIVE, &TWO,
1014 &THREE, &FIVE, &THREE,
1015 &FOUR, &FIVE, &FOUR,
1016 &FIVE, &FIVE, &ZERO,
1017 &SIX, &FIVE, &ONE,
1018 &ZERO, &NEG_FIVE, &ZERO,
1019 &ONE, &NEG_FIVE, &ONE,
1020 &TWO, &NEG_FIVE, &TWO,
1021 &THREE, &NEG_FIVE, &THREE,
1022 &FOUR, &NEG_FIVE, &FOUR,
1023 &FIVE, &NEG_FIVE, &ZERO,
1024 &SIX, &NEG_FIVE, &ONE,
1025 &NEG_ONE, &FIVE, &NEG_ONE,
1026 &NEG_TWO, &FIVE, &NEG_TWO,
1027 &NEG_THREE, &FIVE, &NEG_THREE,
1028 &NEG_FOUR, &FIVE, &NEG_FOUR,
1029 &NEG_FIVE, &FIVE, &ZERO,
1030 &NEG_SIX, &FIVE, &NEG_ONE,
1031 &NEG_ONE, &NEG_FIVE, &NEG_ONE,
1032 &NEG_TWO, &NEG_FIVE, &NEG_TWO,
1033 &NEG_THREE, &NEG_FIVE, &NEG_THREE,
1034 &NEG_FOUR, &NEG_FIVE, &NEG_FOUR,
1035 &NEG_FIVE, &NEG_FIVE, &ZERO,
1036 &NEG_SIX, &NEG_FIVE, &NEG_ONE,
1037 &NINETY_NINE, &FIVE, &FOUR,
1038 &HUNDRED, &FIVE, &ZERO,
1039 &HUNDRED_ONE, &FIVE, &ONE,
1040 &BIG_FIVEm1, &FIVE, &FOUR,
1041 &BIG_FIVE, &FIVE, &ZERO,
1042 &BIG_FIVEp1, &FIVE, &ONE
1043 };
1044 const int TUPLE_WIDTH = 3;
1045 const int TUPLE_COUNT = UPRV_LENGTHOF(tuples)/TUPLE_WIDTH;
1046 for (int i = 0; i < TUPLE_COUNT; ++i) {
1047 const llong lhs = *tuples[i*TUPLE_WIDTH+0];
1048 const llong rhs = *tuples[i*TUPLE_WIDTH+1];
1049 const llong ans = *tuples[i*TUPLE_WIDTH+2];
1050
1051 llong n = lhs;
1052 if (!((n %= rhs) == ans)) {
1053 errln("fail: (n %= rhs) == ans");
1054 }
1055 LLAssert(n == ans);
1056
1057 n = lhs;
1058 LLAssert((n % rhs) == ans);
1059 LLAssert(n == lhs);
1060 }
1061 }
1062
1063 logln("Testing pow");
1064 // pow
1065 LLAssert(llong(0, 0).pow(0) == llong(0, 0));
1066 LLAssert(llong(0, 0).pow(2) == llong(0, 0));
1067 LLAssert(llong(0, 2).pow(0) == llong(0, 1));
1068 LLAssert(llong(0, 2).pow(2) == llong(0, 4));
1069 LLAssert(llong(0, 2).pow(32) == llong(1, 0));
1070 LLAssert(llong(0, 5).pow(10) == llong((double)5.0 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5));
1071
1072 // absolute value
1073 {
1074 const llong n(0xffffffff,0xffffffff);
1075 LLAssert(n.abs() == llong(0, 1));
1076 }
1077
1078 #ifdef RBNF_DEBUG
1079 logln("Testing atoll");
1080 // atoll
1081 const char empty[] = "";
1082 const char zero[] = "0";
1083 const char neg_one[] = "-1";
1084 const char neg_12345[] = "-12345";
1085 const char big1[] = "123456789abcdef0";
1086 const char big2[] = "fFfFfFfFfFfFfFfF";
1087 LLAssert(llong::atoll(empty) == llong(0, 0));
1088 LLAssert(llong::atoll(zero) == llong(0, 0));
1089 LLAssert(llong::atoll(neg_one) == llong(0xffffffff, 0xffffffff));
1090 LLAssert(llong::atoll(neg_12345) == -llong(0, 12345));
1091 LLAssert(llong::atoll(big1, 16) == llong(0x12345678, 0x9abcdef0));
1092 LLAssert(llong::atoll(big2, 16) == llong(0xffffffff, 0xffffffff));
1093 #endif
1094
1095 // u_atoll
1096 const UChar uempty[] = { 0 };
1097 const UChar uzero[] = { 0x30, 0 };
1098 const UChar uneg_one[] = { 0x2d, 0x31, 0 };
1099 const UChar uneg_12345[] = { 0x2d, 0x31, 0x32, 0x33, 0x34, 0x35, 0 };
1100 const UChar ubig1[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x30, 0 };
1101 const UChar ubig2[] = { 0x66, 0x46, 0x66, 0x46, 0x66, 0x46, 0x66, 0x46, 0x66, 0x46, 0x66, 0x46, 0x66, 0x46, 0x66, 0x46, 0 };
1102 LLAssert(llong::utoll(uempty) == llong(0, 0));
1103 LLAssert(llong::utoll(uzero) == llong(0, 0));
1104 LLAssert(llong::utoll(uneg_one) == llong(0xffffffff, 0xffffffff));
1105 LLAssert(llong::utoll(uneg_12345) == -llong(0, 12345));
1106 LLAssert(llong::utoll(ubig1, 16) == llong(0x12345678, 0x9abcdef0));
1107 LLAssert(llong::utoll(ubig2, 16) == llong(0xffffffff, 0xffffffff));
1108
1109 #ifdef RBNF_DEBUG
1110 logln("Testing lltoa");
1111 // lltoa
1112 {
1113 char buf[64]; // ascii
1114 LLAssert((llong(0, 0).lltoa(buf, (uint32_t)sizeof(buf)) == 1) && (strcmp(buf, zero) == 0));
1115 LLAssert((llong(0xffffffff, 0xffffffff).lltoa(buf, (uint32_t)sizeof(buf)) == 2) && (strcmp(buf, neg_one) == 0));
1116 LLAssert(((-llong(0, 12345)).lltoa(buf, (uint32_t)sizeof(buf)) == 6) && (strcmp(buf, neg_12345) == 0));
1117 LLAssert((llong(0x12345678, 0x9abcdef0).lltoa(buf, (uint32_t)sizeof(buf), 16) == 16) && (strcmp(buf, big1) == 0));
1118 }
1119 #endif
1120
1121 logln("Testing u_lltoa");
1122 // u_lltoa
1123 {
1124 UChar buf[64];
1125 LLAssert((llong(0, 0).lltou(buf, (uint32_t)sizeof(buf)) == 1) && (u_strcmp(buf, uzero) == 0));
1126 LLAssert((llong(0xffffffff, 0xffffffff).lltou(buf, (uint32_t)sizeof(buf)) == 2) && (u_strcmp(buf, uneg_one) == 0));
1127 LLAssert(((-llong(0, 12345)).lltou(buf, (uint32_t)sizeof(buf)) == 6) && (u_strcmp(buf, uneg_12345) == 0));
1128 LLAssert((llong(0x12345678, 0x9abcdef0).lltou(buf, (uint32_t)sizeof(buf), 16) == 16) && (u_strcmp(buf, ubig1) == 0));
1129 }
1130 }
1131
1132 /* if 0 */
1133 #endif
1134
1135 void
TestEnglishSpellout()1136 IntlTestRBNF::TestEnglishSpellout()
1137 {
1138 UErrorCode status = U_ZERO_ERROR;
1139 RuleBasedNumberFormat* formatter
1140 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getUS(), status);
1141 if (U_FAILURE(status)) {
1142 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1143 } else {
1144 static const char* const testData[][2] = {
1145 { "1", "one" },
1146 { "2", "two" },
1147 { "15", "fifteen" },
1148 { "20", "twenty" },
1149 { "23", "twenty-three" },
1150 { "73", "seventy-three" },
1151 { "88", "eighty-eight" },
1152 { "100", "one hundred" },
1153 { "106", "one hundred six" },
1154 { "127", "one hundred twenty-seven" },
1155 { "200", "two hundred" },
1156 { "579", "five hundred seventy-nine" },
1157 { "1,000", "one thousand" },
1158 { "2,000", "two thousand" },
1159 { "3,004", "three thousand four" },
1160 { "4,567", "four thousand five hundred sixty-seven" },
1161 { "15,943", "fifteen thousand nine hundred forty-three" },
1162 { "2,345,678", "two million three hundred forty-five thousand six hundred seventy-eight" },
1163 { "-36", "minus thirty-six" },
1164 { "234.567", "two hundred thirty-four point five six seven" },
1165 { NULL, NULL}
1166 };
1167
1168 doTest(formatter, testData, TRUE);
1169
1170 #if !UCONFIG_NO_COLLATION
1171 formatter->setLenient(TRUE);
1172 static const char* lpTestData[][2] = {
1173 { "fifty-7", "57" },
1174 { " fifty-7", "57" },
1175 { " fifty-7", "57" },
1176 { "2 thousand six HUNDRED fifty-7", "2,657" },
1177 { "fifteen hundred and zero", "1,500" },
1178 { "FOurhundred thiRTY six", "436" },
1179 { NULL, NULL}
1180 };
1181 doLenientParseTest(formatter, lpTestData);
1182 #endif
1183 }
1184 delete formatter;
1185 }
1186
1187 void
TestOrdinalAbbreviations()1188 IntlTestRBNF::TestOrdinalAbbreviations()
1189 {
1190 UErrorCode status = U_ZERO_ERROR;
1191 RuleBasedNumberFormat* formatter
1192 = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale::getUS(), status);
1193
1194 if (U_FAILURE(status)) {
1195 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1196 } else {
1197 static const char* const testData[][2] = {
1198 { "1", "1st" },
1199 { "2", "2nd" },
1200 { "3", "3rd" },
1201 { "4", "4th" },
1202 { "7", "7th" },
1203 { "10", "10th" },
1204 { "11", "11th" },
1205 { "13", "13th" },
1206 { "20", "20th" },
1207 { "21", "21st" },
1208 { "22", "22nd" },
1209 { "23", "23rd" },
1210 { "24", "24th" },
1211 { "33", "33rd" },
1212 { "102", "102nd" },
1213 { "312", "312th" },
1214 { "12,345", "12,345th" },
1215 { NULL, NULL}
1216 };
1217
1218 doTest(formatter, testData, FALSE);
1219 }
1220 delete formatter;
1221 }
1222
1223 void
TestDurations()1224 IntlTestRBNF::TestDurations()
1225 {
1226 UErrorCode status = U_ZERO_ERROR;
1227 RuleBasedNumberFormat* formatter
1228 = new RuleBasedNumberFormat(URBNF_DURATION, Locale::getUS(), status);
1229
1230 if (U_FAILURE(status)) {
1231 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1232 } else {
1233 static const char* const testData[][2] = {
1234 { "3,600", "1:00:00" }, //move me and I fail
1235 { "0", "0 sec." },
1236 { "1", "1 sec." },
1237 { "24", "24 sec." },
1238 { "60", "1:00" },
1239 { "73", "1:13" },
1240 { "145", "2:25" },
1241 { "666", "11:06" },
1242 // { "3,600", "1:00:00" },
1243 { "3,740", "1:02:20" },
1244 { "10,293", "2:51:33" },
1245 { NULL, NULL}
1246 };
1247
1248 doTest(formatter, testData, TRUE);
1249
1250 #if !UCONFIG_NO_COLLATION
1251 formatter->setLenient(TRUE);
1252 static const char* lpTestData[][2] = {
1253 { "2-51-33", "10,293" },
1254 { NULL, NULL}
1255 };
1256 doLenientParseTest(formatter, lpTestData);
1257 #endif
1258 }
1259 delete formatter;
1260 }
1261
1262 void
TestSpanishSpellout()1263 IntlTestRBNF::TestSpanishSpellout()
1264 {
1265 UErrorCode status = U_ZERO_ERROR;
1266 RuleBasedNumberFormat* formatter
1267 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("es", "ES", ""), status);
1268
1269 if (U_FAILURE(status)) {
1270 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1271 } else {
1272 static const char* const testData[][2] = {
1273 { "1", "uno" },
1274 { "6", "seis" },
1275 { "16", "diecis\\u00e9is" },
1276 { "20", "veinte" },
1277 { "24", "veinticuatro" },
1278 { "26", "veintis\\u00e9is" },
1279 { "73", "setenta y tres" },
1280 { "88", "ochenta y ocho" },
1281 { "100", "cien" },
1282 { "106", "ciento seis" },
1283 { "127", "ciento veintisiete" },
1284 { "200", "doscientos" },
1285 { "579", "quinientos setenta y nueve" },
1286 { "1,000", "mil" },
1287 { "2,000", "dos mil" },
1288 { "3,004", "tres mil cuatro" },
1289 { "4,567", "cuatro mil quinientos sesenta y siete" },
1290 { "15,943", "quince mil novecientos cuarenta y tres" },
1291 { "2,345,678", "dos millones trescientos cuarenta y cinco mil seiscientos setenta y ocho"},
1292 { "-36", "menos treinta y seis" },
1293 { "234.567", "doscientos treinta y cuatro coma cinco seis siete" },
1294 { NULL, NULL}
1295 };
1296
1297 doTest(formatter, testData, TRUE);
1298 }
1299 delete formatter;
1300 }
1301
1302 void
TestFrenchSpellout()1303 IntlTestRBNF::TestFrenchSpellout()
1304 {
1305 UErrorCode status = U_ZERO_ERROR;
1306 RuleBasedNumberFormat* formatter
1307 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getFrance(), status);
1308
1309 if (U_FAILURE(status)) {
1310 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1311 } else {
1312 static const char* const testData[][2] = {
1313 { "1", "un" },
1314 { "15", "quinze" },
1315 { "20", "vingt" },
1316 { "21", "vingt-et-un" },
1317 { "23", "vingt-trois" },
1318 { "62", "soixante-deux" },
1319 { "70", "soixante-dix" },
1320 { "71", "soixante-et-onze" },
1321 { "73", "soixante-treize" },
1322 { "80", "quatre-vingts" },
1323 { "88", "quatre-vingt-huit" },
1324 { "100", "cent" },
1325 { "106", "cent six" },
1326 { "127", "cent vingt-sept" },
1327 { "200", "deux cents" },
1328 { "579", "cinq cent soixante-dix-neuf" },
1329 { "1,000", "mille" },
1330 { "1,123", "mille cent vingt-trois" },
1331 { "1,594", "mille cinq cent quatre-vingt-quatorze" },
1332 { "2,000", "deux mille" },
1333 { "3,004", "trois mille quatre" },
1334 { "4,567", "quatre mille cinq cent soixante-sept" },
1335 { "15,943", "quinze mille neuf cent quarante-trois" },
1336 { "2,345,678", "deux millions trois cent quarante-cinq mille six cent soixante-dix-huit" },
1337 { "-36", "moins trente-six" },
1338 { "234.567", "deux cent trente-quatre virgule cinq six sept" },
1339 { NULL, NULL}
1340 };
1341
1342 doTest(formatter, testData, TRUE);
1343
1344 #if !UCONFIG_NO_COLLATION
1345 formatter->setLenient(TRUE);
1346 static const char* lpTestData[][2] = {
1347 { "trente-et-un", "31" },
1348 { "un cent quatre vingt dix huit", "198" },
1349 { NULL, NULL}
1350 };
1351 doLenientParseTest(formatter, lpTestData);
1352 #endif
1353 }
1354 delete formatter;
1355 }
1356
1357 static const char* const swissFrenchTestData[][2] = {
1358 { "1", "un" },
1359 { "15", "quinze" },
1360 { "20", "vingt" },
1361 { "21", "vingt-et-un" },
1362 { "23", "vingt-trois" },
1363 { "62", "soixante-deux" },
1364 { "70", "septante" },
1365 { "71", "septante-et-un" },
1366 { "73", "septante-trois" },
1367 { "80", "huitante" },
1368 { "88", "huitante-huit" },
1369 { "100", "cent" },
1370 { "106", "cent six" },
1371 { "127", "cent vingt-sept" },
1372 { "200", "deux cents" },
1373 { "579", "cinq cent septante-neuf" },
1374 { "1,000", "mille" },
1375 { "1,123", "mille cent vingt-trois" },
1376 { "1,594", "mille cinq cent nonante-quatre" },
1377 { "2,000", "deux mille" },
1378 { "3,004", "trois mille quatre" },
1379 { "4,567", "quatre mille cinq cent soixante-sept" },
1380 { "15,943", "quinze mille neuf cent quarante-trois" },
1381 { "2,345,678", "deux millions trois cent quarante-cinq mille six cent septante-huit" },
1382 { "-36", "moins trente-six" },
1383 { "234.567", "deux cent trente-quatre virgule cinq six sept" },
1384 { NULL, NULL}
1385 };
1386
1387 void
TestSwissFrenchSpellout()1388 IntlTestRBNF::TestSwissFrenchSpellout()
1389 {
1390 UErrorCode status = U_ZERO_ERROR;
1391 RuleBasedNumberFormat* formatter
1392 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("fr", "CH", ""), status);
1393
1394 if (U_FAILURE(status)) {
1395 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1396 } else {
1397 doTest(formatter, swissFrenchTestData, TRUE);
1398 }
1399 delete formatter;
1400 }
1401
1402 static const char* const belgianFrenchTestData[][2] = {
1403 { "1", "un" },
1404 { "15", "quinze" },
1405 { "20", "vingt" },
1406 { "21", "vingt-et-un" },
1407 { "23", "vingt-trois" },
1408 { "62", "soixante-deux" },
1409 { "70", "septante" },
1410 { "71", "septante-et-un" },
1411 { "73", "septante-trois" },
1412 { "80", "quatre-vingts" },
1413 { "88", "quatre-vingt huit" },
1414 { "90", "nonante" },
1415 { "91", "nonante-et-un" },
1416 { "95", "nonante-cinq" },
1417 { "100", "cent" },
1418 { "106", "cent six" },
1419 { "127", "cent vingt-sept" },
1420 { "200", "deux cents" },
1421 { "579", "cinq cent septante-neuf" },
1422 { "1,000", "mille" },
1423 { "1,123", "mille cent vingt-trois" },
1424 { "1,594", "mille cinq cent nonante-quatre" },
1425 { "2,000", "deux mille" },
1426 { "3,004", "trois mille quatre" },
1427 { "4,567", "quatre mille cinq cent soixante-sept" },
1428 { "15,943", "quinze mille neuf cent quarante-trois" },
1429 { "2,345,678", "deux millions trois cent quarante-cinq mille six cent septante-huit" },
1430 { "-36", "moins trente-six" },
1431 { "234.567", "deux cent trente-quatre virgule cinq six sept" },
1432 { NULL, NULL}
1433 };
1434
1435
1436 void
TestBelgianFrenchSpellout()1437 IntlTestRBNF::TestBelgianFrenchSpellout()
1438 {
1439 UErrorCode status = U_ZERO_ERROR;
1440 RuleBasedNumberFormat* formatter
1441 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("fr", "BE", ""), status);
1442
1443 if (U_FAILURE(status)) {
1444 errcheckln(status, "rbnf status: 0x%x (%s)\n", status, u_errorName(status));
1445 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1446 } else {
1447 // Belgian french should match Swiss french.
1448 doTest(formatter, belgianFrenchTestData, TRUE);
1449 }
1450 delete formatter;
1451 }
1452
1453 void
TestItalianSpellout()1454 IntlTestRBNF::TestItalianSpellout()
1455 {
1456 UErrorCode status = U_ZERO_ERROR;
1457 RuleBasedNumberFormat* formatter
1458 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getItalian(), status);
1459
1460 if (U_FAILURE(status)) {
1461 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1462 } else {
1463 static const char* const testData[][2] = {
1464 { "1", "uno" },
1465 { "15", "quindici" },
1466 { "20", "venti" },
1467 { "23", "venti\\u00ADtr\\u00E9" },
1468 { "73", "settanta\\u00ADtr\\u00E9" },
1469 { "88", "ottant\\u00ADotto" },
1470 { "100", "cento" },
1471 { "101", "cento\\u00ADuno" },
1472 { "103", "cento\\u00ADtr\\u00E9" },
1473 { "106", "cento\\u00ADsei" },
1474 { "108", "cent\\u00ADotto" },
1475 { "127", "cento\\u00ADventi\\u00ADsette" },
1476 { "181", "cent\\u00ADottant\\u00ADuno" },
1477 { "200", "due\\u00ADcento" },
1478 { "579", "cinque\\u00ADcento\\u00ADsettanta\\u00ADnove" },
1479 { "1,000", "mille" },
1480 { "2,000", "due\\u00ADmila" },
1481 { "3,004", "tre\\u00ADmila\\u00ADquattro" },
1482 { "4,567", "quattro\\u00ADmila\\u00ADcinque\\u00ADcento\\u00ADsessanta\\u00ADsette" },
1483 { "15,943", "quindici\\u00ADmila\\u00ADnove\\u00ADcento\\u00ADquaranta\\u00ADtr\\u00E9" },
1484 { "-36", "meno trenta\\u00ADsei" },
1485 { "234.567", "due\\u00ADcento\\u00ADtrenta\\u00ADquattro virgola cinque sei sette" },
1486 { NULL, NULL}
1487 };
1488
1489 doTest(formatter, testData, TRUE);
1490 }
1491 delete formatter;
1492 }
1493
1494 void
TestPortugueseSpellout()1495 IntlTestRBNF::TestPortugueseSpellout()
1496 {
1497 UErrorCode status = U_ZERO_ERROR;
1498 RuleBasedNumberFormat* formatter
1499 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("pt","BR",""), status);
1500
1501 if (U_FAILURE(status)) {
1502 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1503 } else {
1504 static const char* const testData[][2] = {
1505 { "1", "um" },
1506 { "15", "quinze" },
1507 { "20", "vinte" },
1508 { "23", "vinte e tr\\u00EAs" },
1509 { "73", "setenta e tr\\u00EAs" },
1510 { "88", "oitenta e oito" },
1511 { "100", "cem" },
1512 { "106", "cento e seis" },
1513 { "108", "cento e oito" },
1514 { "127", "cento e vinte e sete" },
1515 { "181", "cento e oitenta e um" },
1516 { "200", "duzentos" },
1517 { "579", "quinhentos e setenta e nove" },
1518 { "1,000", "mil" },
1519 { "2,000", "dois mil" },
1520 { "3,004", "tr\\u00EAs mil e quatro" },
1521 { "4,567", "quatro mil e quinhentos e sessenta e sete" },
1522 { "15,943", "quinze mil e novecentos e quarenta e tr\\u00EAs" },
1523 { "-36", "menos trinta e seis" },
1524 { "234.567", "duzentos e trinta e quatro v\\u00EDrgula cinco seis sete" },
1525 { NULL, NULL}
1526 };
1527
1528 doTest(formatter, testData, TRUE);
1529 }
1530 delete formatter;
1531 }
1532 void
TestGermanSpellout()1533 IntlTestRBNF::TestGermanSpellout()
1534 {
1535 UErrorCode status = U_ZERO_ERROR;
1536 RuleBasedNumberFormat* formatter
1537 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getGermany(), status);
1538
1539 if (U_FAILURE(status)) {
1540 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1541 } else {
1542 static const char* const testData[][2] = {
1543 { "1", "eins" },
1544 { "15", "f\\u00fcnfzehn" },
1545 { "20", "zwanzig" },
1546 { "23", "drei\\u00ADund\\u00ADzwanzig" },
1547 { "73", "drei\\u00ADund\\u00ADsiebzig" },
1548 { "88", "acht\\u00ADund\\u00ADachtzig" },
1549 { "100", "ein\\u00ADhundert" },
1550 { "106", "ein\\u00ADhundert\\u00ADsechs" },
1551 { "127", "ein\\u00ADhundert\\u00ADsieben\\u00ADund\\u00ADzwanzig" },
1552 { "200", "zwei\\u00ADhundert" },
1553 { "579", "f\\u00fcnf\\u00ADhundert\\u00ADneun\\u00ADund\\u00ADsiebzig" },
1554 { "1,000", "ein\\u00ADtausend" },
1555 { "2,000", "zwei\\u00ADtausend" },
1556 { "3,004", "drei\\u00ADtausend\\u00ADvier" },
1557 { "4,567", "vier\\u00ADtausend\\u00ADf\\u00fcnf\\u00ADhundert\\u00ADsieben\\u00ADund\\u00ADsechzig" },
1558 { "15,943", "f\\u00fcnfzehn\\u00ADtausend\\u00ADneun\\u00ADhundert\\u00ADdrei\\u00ADund\\u00ADvierzig" },
1559 { "2,345,678", "zwei Millionen drei\\u00ADhundert\\u00ADf\\u00fcnf\\u00ADund\\u00ADvierzig\\u00ADtausend\\u00ADsechs\\u00ADhundert\\u00ADacht\\u00ADund\\u00ADsiebzig" },
1560 { NULL, NULL}
1561 };
1562
1563 doTest(formatter, testData, TRUE);
1564
1565 #if !UCONFIG_NO_COLLATION
1566 formatter->setLenient(TRUE);
1567 static const char* lpTestData[][2] = {
1568 { "ein Tausend sechs Hundert fuenfunddreissig", "1,635" },
1569 { NULL, NULL}
1570 };
1571 doLenientParseTest(formatter, lpTestData);
1572 #endif
1573 }
1574 delete formatter;
1575 }
1576
1577 void
TestThaiSpellout()1578 IntlTestRBNF::TestThaiSpellout()
1579 {
1580 UErrorCode status = U_ZERO_ERROR;
1581 RuleBasedNumberFormat* formatter
1582 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("th"), status);
1583
1584 if (U_FAILURE(status)) {
1585 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1586 } else {
1587 static const char* const testData[][2] = {
1588 { "0", "\\u0e28\\u0e39\\u0e19\\u0e22\\u0e4c" },
1589 { "1", "\\u0e2b\\u0e19\\u0e36\\u0e48\\u0e07" },
1590 { "10", "\\u0e2a\\u0e34\\u0e1a" },
1591 { "11", "\\u0e2a\\u0e34\\u0e1a\\u200b\\u0e40\\u0e2d\\u0e47\\u0e14" },
1592 { "21", "\\u0e22\\u0e35\\u0e48\\u200b\\u0e2a\\u0e34\\u0e1a\\u200b\\u0e40\\u0e2d\\u0e47\\u0e14" },
1593 { "101", "\\u0e2b\\u0e19\\u0e36\\u0e48\\u0e07\\u200b\\u0e23\\u0e49\\u0e2d\\u0e22\\u200b\\u0e2b\\u0e19\\u0e36\\u0e48\\u0e07" },
1594 { "1.234", "\\u0e2b\\u0e19\\u0e36\\u0e48\\u0e07\\u200b\\u0e08\\u0e38\\u0e14\\u200b\\u0e2a\\u0e2d\\u0e07\\u0e2a\\u0e32\\u0e21\\u0e2a\\u0e35\\u0e48" },
1595 { NULL, NULL}
1596 };
1597
1598 doTest(formatter, testData, TRUE);
1599 }
1600 delete formatter;
1601 }
1602
1603 void
TestSwedishSpellout()1604 IntlTestRBNF::TestSwedishSpellout()
1605 {
1606 UErrorCode status = U_ZERO_ERROR;
1607 RuleBasedNumberFormat* formatter
1608 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("sv"), status);
1609
1610 if (U_FAILURE(status)) {
1611 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1612 } else {
1613 static const char* testDataDefault[][2] = {
1614 { "101", "ett\\u00adhundra\\u00adett" },
1615 { "123", "ett\\u00adhundra\\u00adtjugo\\u00adtre" },
1616 { "1,001", "et\\u00adtusen ett" },
1617 { "1,100", "et\\u00adtusen ett\\u00adhundra" },
1618 { "1,101", "et\\u00adtusen ett\\u00adhundra\\u00adett" },
1619 { "1,234", "et\\u00adtusen tv\\u00e5\\u00adhundra\\u00adtrettio\\u00adfyra" },
1620 { "10,001", "tio\\u00adtusen ett" },
1621 { "11,000", "elva\\u00adtusen" },
1622 { "12,000", "tolv\\u00adtusen" },
1623 { "20,000", "tjugo\\u00adtusen" },
1624 { "21,000", "tjugo\\u00adet\\u00adtusen" },
1625 { "21,001", "tjugo\\u00adet\\u00adtusen ett" },
1626 { "200,000", "tv\\u00e5\\u00adhundra\\u00adtusen" },
1627 { "201,000", "tv\\u00e5\\u00adhundra\\u00adet\\u00adtusen" },
1628 { "200,200", "tv\\u00e5\\u00adhundra\\u00adtusen tv\\u00e5\\u00adhundra" },
1629 { "2,002,000", "tv\\u00e5 miljoner tv\\u00e5\\u00adtusen" },
1630 { "12,345,678", "tolv miljoner tre\\u00adhundra\\u00adfyrtio\\u00adfem\\u00adtusen sex\\u00adhundra\\u00adsjuttio\\u00ad\\u00e5tta" },
1631 { "123,456.789", "ett\\u00adhundra\\u00adtjugo\\u00adtre\\u00adtusen fyra\\u00adhundra\\u00adfemtio\\u00adsex komma sju \\u00e5tta nio" },
1632 { "-12,345.678", "minus tolv\\u00adtusen tre\\u00adhundra\\u00adfyrtio\\u00adfem komma sex sju \\u00e5tta" },
1633 { NULL, NULL }
1634 };
1635 doTest(formatter, testDataDefault, TRUE);
1636
1637 static const char* testDataNeutrum[][2] = {
1638 { "101", "ett\\u00adhundra\\u00adett" },
1639 { "1,001", "et\\u00adtusen ett" },
1640 { "1,101", "et\\u00adtusen ett\\u00adhundra\\u00adett" },
1641 { "10,001", "tio\\u00adtusen ett" },
1642 { "21,001", "tjugo\\u00adet\\u00adtusen ett" },
1643 { NULL, NULL }
1644 };
1645
1646 formatter->setDefaultRuleSet("%spellout-cardinal-neuter", status);
1647 if (U_SUCCESS(status)) {
1648 logln(" testing spellout-cardinal-neuter rules");
1649 doTest(formatter, testDataNeutrum, TRUE);
1650 }
1651 else {
1652 errln("Can't test spellout-cardinal-neuter rules");
1653 }
1654
1655 static const char* testDataYear[][2] = {
1656 { "101", "ett\\u00adhundra\\u00adett" },
1657 { "900", "nio\\u00adhundra" },
1658 { "1,001", "et\\u00adtusen ett" },
1659 { "1,100", "elva\\u00adhundra" },
1660 { "1,101", "elva\\u00adhundra\\u00adett" },
1661 { "1,234", "tolv\\u00adhundra\\u00adtrettio\\u00adfyra" },
1662 { "2,001", "tjugo\\u00adhundra\\u00adett" },
1663 { "10,001", "tio\\u00adtusen ett" },
1664 { NULL, NULL }
1665 };
1666
1667 status = U_ZERO_ERROR;
1668 formatter->setDefaultRuleSet("%spellout-numbering-year", status);
1669 if (U_SUCCESS(status)) {
1670 logln("testing year rules");
1671 doTest(formatter, testDataYear, TRUE);
1672 }
1673 else {
1674 errln("Can't test year rules");
1675 }
1676
1677 }
1678 delete formatter;
1679 }
1680
1681 void
TestSmallValues()1682 IntlTestRBNF::TestSmallValues()
1683 {
1684 UErrorCode status = U_ZERO_ERROR;
1685 RuleBasedNumberFormat* formatter
1686 = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("en_US"), status);
1687
1688 if (U_FAILURE(status)) {
1689 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1690 } else {
1691 static const char* const testDataDefault[][2] = {
1692 { "0.001", "zero point zero zero one" },
1693 { "0.0001", "zero point zero zero zero one" },
1694 { "0.00001", "zero point zero zero zero zero one" },
1695 { "0.000001", "zero point zero zero zero zero zero one" },
1696 { "0.0000001", "zero point zero zero zero zero zero zero one" },
1697 { "0.00000001", "zero point zero zero zero zero zero zero zero one" },
1698 { "0.000000001", "zero point zero zero zero zero zero zero zero zero one" },
1699 { "0.0000000001", "zero point zero zero zero zero zero zero zero zero zero one" },
1700 { "0.00000000001", "zero point zero zero zero zero zero zero zero zero zero zero one" },
1701 { "0.000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero one" },
1702 { "0.0000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero one" },
1703 { "0.00000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero one" },
1704 { "0.000000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero zero one" },
1705 { "10,000,000.001", "ten million point zero zero one" },
1706 { "10,000,000.0001", "ten million point zero zero zero one" },
1707 { "10,000,000.00001", "ten million point zero zero zero zero one" },
1708 { "10,000,000.000001", "ten million point zero zero zero zero zero one" },
1709 { "10,000,000.0000001", "ten million point zero zero zero zero zero zero one" },
1710 // { "10,000,000.00000001", "ten million point zero zero zero zero zero zero zero one" },
1711 // { "10,000,000.000000002", "ten million point zero zero zero zero zero zero zero zero two" },
1712 { "10,000,000", "ten million" },
1713 // { "1,234,567,890.0987654", "one billion, two hundred and thirty-four million, five hundred and sixty-seven thousand, eight hundred and ninety point zero nine eight seven six five four" },
1714 // { "123,456,789.9876543", "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine point nine eight seven six five four three" },
1715 // { "12,345,678.87654321", "twelve million, three hundred and forty-five thousand, six hundred and seventy-eight point eight seven six five four three two one" },
1716 { "1,234,567.7654321", "one million two hundred thirty-four thousand five hundred sixty-seven point seven six five four three two one" },
1717 { "123,456.654321", "one hundred twenty-three thousand four hundred fifty-six point six five four three two one" },
1718 { "12,345.54321", "twelve thousand three hundred forty-five point five four three two one" },
1719 { "1,234.4321", "one thousand two hundred thirty-four point four three two one" },
1720 { "123.321", "one hundred twenty-three point three two one" },
1721 { "0.0000000011754944", "zero point zero zero zero zero zero zero zero zero one one seven five four nine four four" },
1722 { "0.000001175494351", "zero point zero zero zero zero zero one one seven five four nine four three five one" },
1723 { NULL, NULL }
1724 };
1725
1726 doTest(formatter, testDataDefault, TRUE);
1727
1728 delete formatter;
1729 }
1730 }
1731
1732 void
TestLocalizations(void)1733 IntlTestRBNF::TestLocalizations(void)
1734 {
1735 int i;
1736 UnicodeString rules("%main:0:no;1:some;100:a lot;1000:tons;\n"
1737 "%other:0:nada;1:yah, some;100:plenty;1000:more'n you'll ever need");
1738
1739 UErrorCode status = U_ZERO_ERROR;
1740 UParseError perror;
1741 RuleBasedNumberFormat formatter(rules, perror, status);
1742 if (U_FAILURE(status)) {
1743 errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1744 } else {
1745 {
1746 static const char* const testData[][2] = {
1747 { "0", "nada" },
1748 { "5", "yah, some" },
1749 { "423", "plenty" },
1750 { "12345", "more'n you'll ever need" },
1751 { NULL, NULL }
1752 };
1753 doTest(&formatter, testData, FALSE);
1754 }
1755
1756 {
1757 UnicodeString loc("<<%main, %other>,<en, Main, Other>,<fr, leMain, leOther>,<de, 'das Main', 'etwas anderes'>>");
1758 static const char* const testData[][2] = {
1759 { "0", "no" },
1760 { "5", "some" },
1761 { "423", "a lot" },
1762 { "12345", "tons" },
1763 { NULL, NULL }
1764 };
1765 RuleBasedNumberFormat formatter0(rules, loc, perror, status);
1766 if (U_FAILURE(status)) {
1767 errln("failed to build second formatter");
1768 } else {
1769 doTest(&formatter0, testData, FALSE);
1770
1771 {
1772 // exercise localization info
1773 Locale locale0("en__VALLEY@turkey=gobblegobble");
1774 Locale locale1("de_DE_FOO");
1775 Locale locale2("ja_JP");
1776 UnicodeString name = formatter0.getRuleSetName(0);
1777 if ( formatter0.getRuleSetDisplayName(0, locale0) == "Main"
1778 && formatter0.getRuleSetDisplayName(0, locale1) == "das Main"
1779 && formatter0.getRuleSetDisplayName(0, locale2) == "%main"
1780 && formatter0.getRuleSetDisplayName(name, locale0) == "Main"
1781 && formatter0.getRuleSetDisplayName(name, locale1) == "das Main"
1782 && formatter0.getRuleSetDisplayName(name, locale2) == "%main"){
1783 logln("getRuleSetDisplayName tested");
1784 }else {
1785 errln("failed to getRuleSetDisplayName");
1786 }
1787 }
1788
1789 for (i = 0; i < formatter0.getNumberOfRuleSetDisplayNameLocales(); ++i) {
1790 Locale locale = formatter0.getRuleSetDisplayNameLocale(i, status);
1791 if (U_SUCCESS(status)) {
1792 for (int j = 0; j < formatter0.getNumberOfRuleSetNames(); ++j) {
1793 UnicodeString name = formatter0.getRuleSetName(j);
1794 UnicodeString lname = formatter0.getRuleSetDisplayName(j, locale);
1795 UnicodeString msg = locale.getName();
1796 msg.append(": ");
1797 msg.append(name);
1798 msg.append(" = ");
1799 msg.append(lname);
1800 logln(msg);
1801 }
1802 }
1803 }
1804 }
1805 }
1806
1807 {
1808 static const char* goodLocs[] = {
1809 "", // zero-length ok, same as providing no localization data
1810 "<<>>", // no public rule sets ok
1811 "<<%main>>", // no localizations ok
1812 "<<%main,>,<en, Main,>>", // comma before close angle ok
1813 "<<%main>,<en, ',<>\" '>>", // quotes everything until next quote
1814 "<<%main>,<'en', \"it's ok\">>", // double quotes work too
1815 " \n <\n <\n %main\n >\n , \t <\t en\t , \tfoo \t\t > \n\n > \n ", // Pattern_White_Space ok
1816 };
1817 int32_t goodLocsLen = UPRV_LENGTHOF(goodLocs);
1818
1819 static const char* badLocs[] = {
1820 " ", // non-zero length
1821 "<>", // empty array
1822 "<", // unclosed outer array
1823 "<<", // unclosed inner array
1824 "<<,>>", // unexpected comma
1825 "<<''>>", // empty string
1826 " x<<%main>>", // first non space char not open angle bracket
1827 "<%main>", // missing inner array
1828 "<<%main %other>>", // elements missing separating commma (spaces must be quoted)
1829 "<<%main><en, Main>>", // arrays missing separating comma
1830 "<<%main>,<en, main, foo>>", // too many elements in locale data
1831 "<<%main>,<en>>", // too few elements in locale data
1832 "<<<%main>>>", // unexpected open angle
1833 "<<%main<>>>", // unexpected open angle
1834 "<<%main, %other>,<en,,>>", // implicit empty strings
1835 "<<%main>,<en,''>>", // empty string
1836 "<<%main>, < en, '>>", // unterminated quote
1837 "<<%main>, < en, \"<>>", // unterminated quote
1838 "<<%main\">>", // quote in string
1839 "<<%main'>>", // quote in string
1840 "<<%main<>>", // open angle in string
1841 "<<%main>> x", // extra non-space text at end
1842
1843 };
1844 int32_t badLocsLen = UPRV_LENGTHOF(badLocs);
1845
1846 for (i = 0; i < goodLocsLen; ++i) {
1847 logln("[%d] '%s'", i, goodLocs[i]);
1848 UErrorCode status = U_ZERO_ERROR;
1849 UnicodeString loc(goodLocs[i]);
1850 RuleBasedNumberFormat fmt(rules, loc, perror, status);
1851 if (U_FAILURE(status)) {
1852 errln("Failed parse of good localization string: '%s'", goodLocs[i]);
1853 }
1854 }
1855
1856 for (i = 0; i < badLocsLen; ++i) {
1857 logln("[%d] '%s'", i, badLocs[i]);
1858 UErrorCode status = U_ZERO_ERROR;
1859 UnicodeString loc(badLocs[i]);
1860 RuleBasedNumberFormat fmt(rules, loc, perror, status);
1861 if (U_SUCCESS(status)) {
1862 errln("Successful parse of bad localization string: '%s'", badLocs[i]);
1863 }
1864 }
1865 }
1866 }
1867 }
1868
1869 void
TestAllLocales()1870 IntlTestRBNF::TestAllLocales()
1871 {
1872 const char* names[] = {
1873 " (spellout) ",
1874 " (ordinal) "
1875 // " (duration) " // This is English only, and it's not really supported in CLDR anymore.
1876 };
1877 double numbers[] = {45.678, 1, 2, 10, 11, 100, 110, 200, 1000, 1111, -1111};
1878
1879 int32_t count = 0;
1880 const Locale* locales = Locale::getAvailableLocales(count);
1881 for (int i = 0; i < count; ++i) {
1882 const Locale* loc = &locales[i];
1883
1884 for (int j = 0; j < 2; ++j) {
1885 UErrorCode status = U_ZERO_ERROR;
1886 RuleBasedNumberFormat* f = new RuleBasedNumberFormat((URBNFRuleSetTag)j, *loc, status);
1887
1888 if (status == U_USING_DEFAULT_WARNING || status == U_USING_FALLBACK_WARNING) {
1889 // Skip it.
1890 delete f;
1891 break;
1892 }
1893 if (U_FAILURE(status)) {
1894 errln(UnicodeString(loc->getName()) + names[j]
1895 + "ERROR could not instantiate -> " + u_errorName(status));
1896 continue;
1897 }
1898 #if !UCONFIG_NO_COLLATION
1899 for (unsigned int numidx = 0; numidx < UPRV_LENGTHOF(numbers); numidx++) {
1900 double n = numbers[numidx];
1901 UnicodeString str;
1902 f->format(n, str);
1903
1904 if (verbose) {
1905 logln(UnicodeString(loc->getName()) + names[j]
1906 + "success: " + n + " -> " + str);
1907 }
1908
1909 // We do not validate the result in this test case,
1910 // because there are cases which do not round trip by design.
1911 Formattable num;
1912
1913 // regular parse
1914 status = U_ZERO_ERROR;
1915 f->setLenient(FALSE);
1916 f->parse(str, num, status);
1917 if (U_FAILURE(status)) {
1918 errln(UnicodeString(loc->getName()) + names[j]
1919 + "ERROR could not parse '" + str + "' -> " + u_errorName(status));
1920 }
1921 // We only check the spellout. The behavior is undefined for numbers < 1 and fractional numbers.
1922 if (j == 0) {
1923 if (num.getType() == Formattable::kLong && num.getLong() != n) {
1924 errln(UnicodeString(loc->getName()) + names[j]
1925 + UnicodeString("ERROR could not roundtrip ") + n
1926 + UnicodeString(" -> ") + str + UnicodeString(" -> ") + num.getLong());
1927 }
1928 else if (num.getType() == Formattable::kDouble && (int64_t)(num.getDouble() * 1000) != (int64_t)(n*1000)) {
1929 // The epsilon difference is too high.
1930 errln(UnicodeString(loc->getName()) + names[j]
1931 + UnicodeString("ERROR could not roundtrip ") + n
1932 + UnicodeString(" -> ") + str + UnicodeString(" -> ") + num.getDouble());
1933 }
1934 }
1935 if (!quick && !logKnownIssue("9503") ) {
1936 // lenient parse
1937 status = U_ZERO_ERROR;
1938 f->setLenient(TRUE);
1939 f->parse(str, num, status);
1940 if (U_FAILURE(status)) {
1941 errln(UnicodeString(loc->getName()) + names[j]
1942 + "ERROR could not parse(lenient) '" + str + "' -> " + u_errorName(status));
1943 }
1944 // We only check the spellout. The behavior is undefined for numbers < 1 and fractional numbers.
1945 if (j == 0) {
1946 if (num.getType() == Formattable::kLong && num.getLong() != n) {
1947 errln(UnicodeString(loc->getName()) + names[j]
1948 + UnicodeString("ERROR could not roundtrip ") + n
1949 + UnicodeString(" -> ") + str + UnicodeString(" -> ") + num.getLong());
1950 }
1951 else if (num.getType() == Formattable::kDouble && (int64_t)(num.getDouble() * 1000) != (int64_t)(n*1000)) {
1952 // The epsilon difference is too high.
1953 errln(UnicodeString(loc->getName()) + names[j]
1954 + UnicodeString("ERROR could not roundtrip ") + n
1955 + UnicodeString(" -> ") + str + UnicodeString(" -> ") + num.getDouble());
1956 }
1957 }
1958 }
1959 }
1960 #endif
1961 delete f;
1962 }
1963 }
1964 }
1965
1966 void
TestMultiplierSubstitution(void)1967 IntlTestRBNF::TestMultiplierSubstitution(void) {
1968 UnicodeString rules("=#,##0=;1,000,000: <##0.###< million;");
1969 UErrorCode status = U_ZERO_ERROR;
1970 UParseError parse_error;
1971 RuleBasedNumberFormat *rbnf =
1972 new RuleBasedNumberFormat(rules, Locale::getUS(), parse_error, status);
1973 if (U_SUCCESS(status)) {
1974 UnicodeString res;
1975 FieldPosition pos;
1976 double n = 1234000.0;
1977 rbnf->format(n, res, pos);
1978 delete rbnf;
1979
1980 UnicodeString expected(UNICODE_STRING_SIMPLE("1.234 million"));
1981 if (expected != res) {
1982 UnicodeString msg = "Expected: ";
1983 msg.append(expected);
1984 msg.append(" but got ");
1985 msg.append(res);
1986 errln(msg);
1987 }
1988 }
1989 }
1990
1991 void
TestSetDecimalFormatSymbols()1992 IntlTestRBNF::TestSetDecimalFormatSymbols() {
1993 UErrorCode status = U_ZERO_ERROR;
1994
1995 RuleBasedNumberFormat rbnf(URBNF_ORDINAL, Locale::getEnglish(), status);
1996 if (U_FAILURE(status)) {
1997 dataerrln("Unable to create RuleBasedNumberFormat - " + UnicodeString(u_errorName(status)));
1998 return;
1999 }
2000
2001 DecimalFormatSymbols dfs(Locale::getEnglish(), status);
2002 if (U_FAILURE(status)) {
2003 errln("Unable to create DecimalFormatSymbols - " + UnicodeString(u_errorName(status)));
2004 return;
2005 }
2006
2007 UnicodeString expected[] = {
2008 UnicodeString("1,001st"),
2009 UnicodeString("1&001st")
2010 };
2011
2012 double number = 1001;
2013
2014 UnicodeString result;
2015
2016 rbnf.format(number, result);
2017 if (result != expected[0]) {
2018 errln("Format Error - Got: " + result + " Expected: " + expected[0]);
2019 }
2020
2021 result.remove();
2022
2023 /* Set new symbol for testing */
2024 dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, UnicodeString("&"), TRUE);
2025 rbnf.setDecimalFormatSymbols(dfs);
2026
2027 rbnf.format(number, result);
2028 if (result != expected[1]) {
2029 errln("Format Error - Got: " + result + " Expected: " + expected[1]);
2030 }
2031 }
2032
TestPluralRules()2033 void IntlTestRBNF::TestPluralRules() {
2034 UErrorCode status = U_ZERO_ERROR;
2035 UnicodeString enRules("%digits-ordinal:-x: ->>;0: =#,##0=$(ordinal,one{st}two{nd}few{rd}other{th})$;");
2036 UParseError parseError;
2037 RuleBasedNumberFormat enFormatter(enRules, Locale::getEnglish(), parseError, status);
2038 if (U_FAILURE(status)) {
2039 dataerrln("Unable to create RuleBasedNumberFormat - " + UnicodeString(u_errorName(status)));
2040 return;
2041 }
2042 const char* const enTestData[][2] = {
2043 { "1", "1st" },
2044 { "2", "2nd" },
2045 { "3", "3rd" },
2046 { "4", "4th" },
2047 { "11", "11th" },
2048 { "12", "12th" },
2049 { "13", "13th" },
2050 { "14", "14th" },
2051 { "21", "21st" },
2052 { "22", "22nd" },
2053 { "23", "23rd" },
2054 { "24", "24th" },
2055 { NULL, NULL }
2056 };
2057
2058 doTest(&enFormatter, enTestData, TRUE);
2059
2060 // This is trying to model the feminine form, but don't worry about the details too much.
2061 // We're trying to test the plural rules.
2062 UnicodeString ruRules("%spellout-numbering:"
2063 "-x: minus >>;"
2064 "x.x: << point >>;"
2065 "0: zero;"
2066 "1: one;"
2067 "2: two;"
2068 "3: three;"
2069 "4: four;"
2070 "5: five;"
2071 "6: six;"
2072 "7: seven;"
2073 "8: eight;"
2074 "9: nine;"
2075 "10: ten;"
2076 "11: eleven;"
2077 "12: twelve;"
2078 "13: thirteen;"
2079 "14: fourteen;"
2080 "15: fifteen;"
2081 "16: sixteen;"
2082 "17: seventeen;"
2083 "18: eighteen;"
2084 "19: nineteen;"
2085 "20: twenty[->>];"
2086 "30: thirty[->>];"
2087 "40: forty[->>];"
2088 "50: fifty[->>];"
2089 "60: sixty[->>];"
2090 "70: seventy[->>];"
2091 "80: eighty[->>];"
2092 "90: ninety[->>];"
2093 "100: hundred[ >>];"
2094 "200: << hundred[ >>];"
2095 "300: << hundreds[ >>];"
2096 "500: << hundredss[ >>];"
2097 "1000: << $(cardinal,one{thousand}few{thousands}other{thousandss})$[ >>];"
2098 "1000000: << $(cardinal,one{million}few{millions}other{millionss})$[ >>];");
2099 RuleBasedNumberFormat ruFormatter(ruRules, Locale("ru"), parseError, status);
2100 const char* const ruTestData[][2] = {
2101 { "1", "one" },
2102 { "100", "hundred" },
2103 { "125", "hundred twenty-five" },
2104 { "399", "three hundreds ninety-nine" },
2105 { "1,000", "one thousand" },
2106 { "1,001", "one thousand one" },
2107 { "2,000", "two thousands" },
2108 { "2,001", "two thousands one" },
2109 { "2,002", "two thousands two" },
2110 { "3,333", "three thousands three hundreds thirty-three" },
2111 { "5,000", "five thousandss" },
2112 { "11,000", "eleven thousandss" },
2113 { "21,000", "twenty-one thousand" },
2114 { "22,000", "twenty-two thousands" },
2115 { "25,001", "twenty-five thousandss one" },
2116 { NULL, NULL }
2117 };
2118
2119 if (U_FAILURE(status)) {
2120 errln("Unable to create RuleBasedNumberFormat - " + UnicodeString(u_errorName(status)));
2121 return;
2122 }
2123 doTest(&ruFormatter, ruTestData, TRUE);
2124
2125 // Make sure there are no divide by 0 errors.
2126 UnicodeString result;
2127 RuleBasedNumberFormat(ruRules, Locale("ru"), parseError, status).format((int32_t)21000, result);
2128 if (result.compare(UNICODE_STRING_SIMPLE("twenty-one thousand")) != 0) {
2129 errln("Got " + result + " for 21000");
2130 }
2131
2132 }
2133
TestInfinityNaN()2134 void IntlTestRBNF::TestInfinityNaN() {
2135 UErrorCode status = U_ZERO_ERROR;
2136 UParseError parseError;
2137 UnicodeString enRules("%default:"
2138 "-x: minus >>;"
2139 "Inf: infinite;"
2140 "NaN: not a number;"
2141 "0: =#,##0=;");
2142 RuleBasedNumberFormat enFormatter(enRules, Locale::getEnglish(), parseError, status);
2143 const char * const enTestData[][2] = {
2144 {"1", "1"},
2145 {"\\u221E", "infinite"},
2146 {"-\\u221E", "minus infinite"},
2147 {"NaN", "not a number"},
2148 { NULL, NULL }
2149 };
2150 if (U_FAILURE(status)) {
2151 dataerrln("Unable to create RuleBasedNumberFormat - " + UnicodeString(u_errorName(status)));
2152 return;
2153 }
2154
2155 doTest(&enFormatter, enTestData, true);
2156
2157 // Test the default behavior when the rules are undefined.
2158 UnicodeString enRules2("%default:"
2159 "-x: ->>;"
2160 "0: =#,##0=;");
2161 RuleBasedNumberFormat enFormatter2(enRules2, Locale::getEnglish(), parseError, status);
2162 if (U_FAILURE(status)) {
2163 errln("Unable to create RuleBasedNumberFormat - " + UnicodeString(u_errorName(status)));
2164 return;
2165 }
2166 const char * const enDefaultTestData[][2] = {
2167 {"1", "1"},
2168 {"\\u221E", "\\u221E"},
2169 {"-\\u221E", "-\\u221E"},
2170 {"NaN", "NaN"},
2171 { NULL, NULL }
2172 };
2173
2174 doTest(&enFormatter2, enDefaultTestData, true);
2175 }
2176
TestVariableDecimalPoint()2177 void IntlTestRBNF::TestVariableDecimalPoint() {
2178 UErrorCode status = U_ZERO_ERROR;
2179 UParseError parseError;
2180 UnicodeString enRules("%spellout-numbering:"
2181 "-x: minus >>;"
2182 "x.x: << point >>;"
2183 "x,x: << comma >>;"
2184 "0.x: xpoint >>;"
2185 "0,x: xcomma >>;"
2186 "0: zero;"
2187 "1: one;"
2188 "2: two;"
2189 "3: three;"
2190 "4: four;"
2191 "5: five;"
2192 "6: six;"
2193 "7: seven;"
2194 "8: eight;"
2195 "9: nine;");
2196 RuleBasedNumberFormat enFormatter(enRules, Locale::getEnglish(), parseError, status);
2197 const char * const enTestPointData[][2] = {
2198 {"1.1", "one point one"},
2199 {"1.23", "one point two three"},
2200 {"0.4", "xpoint four"},
2201 { NULL, NULL }
2202 };
2203 if (U_FAILURE(status)) {
2204 dataerrln("Unable to create RuleBasedNumberFormat - " + UnicodeString(u_errorName(status)));
2205 return;
2206 }
2207 doTest(&enFormatter, enTestPointData, true);
2208
2209 DecimalFormatSymbols decimalFormatSymbols(Locale::getEnglish(), status);
2210 decimalFormatSymbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, UNICODE_STRING_SIMPLE(","));
2211 enFormatter.setDecimalFormatSymbols(decimalFormatSymbols);
2212 const char * const enTestCommaData[][2] = {
2213 {"1.1", "one comma one"},
2214 {"1.23", "one comma two three"},
2215 {"0.4", "xcomma four"},
2216 { NULL, NULL }
2217 };
2218 doTest(&enFormatter, enTestCommaData, true);
2219 }
2220
2221 void
doTest(RuleBasedNumberFormat * formatter,const char * const testData[][2],UBool testParsing)2222 IntlTestRBNF::doTest(RuleBasedNumberFormat* formatter, const char* const testData[][2], UBool testParsing)
2223 {
2224 // man, error reporting would be easier with printf-style syntax for unicode string and formattable
2225
2226 UErrorCode status = U_ZERO_ERROR;
2227 DecimalFormatSymbols dfs("en", status);
2228 // NumberFormat* decFmt = NumberFormat::createInstance(Locale::getUS(), status);
2229 DecimalFormat decFmt("#,###.################", dfs, status);
2230 if (U_FAILURE(status)) {
2231 errcheckln(status, "FAIL: could not create NumberFormat - %s", u_errorName(status));
2232 } else {
2233 for (int i = 0; testData[i][0]; ++i) {
2234 const char* numString = testData[i][0];
2235 const char* expectedWords = testData[i][1];
2236
2237 log("[%i] %s = ", i, numString);
2238 Formattable expectedNumber;
2239 UnicodeString escapedNumString = UnicodeString(numString, -1, US_INV).unescape();
2240 decFmt.parse(escapedNumString, expectedNumber, status);
2241 if (U_FAILURE(status)) {
2242 errln("FAIL: decFmt could not parse %s", numString);
2243 break;
2244 } else {
2245 UnicodeString actualString;
2246 FieldPosition pos;
2247 formatter->format(expectedNumber, actualString/* , pos*/, status);
2248 if (U_FAILURE(status)) {
2249 UnicodeString msg = "Fail: formatter could not format ";
2250 decFmt.format(expectedNumber, msg, status);
2251 errln(msg);
2252 break;
2253 } else {
2254 UnicodeString expectedString = UnicodeString(expectedWords, -1, US_INV).unescape();
2255 if (actualString != expectedString) {
2256 UnicodeString msg = "FAIL: check failed for ";
2257 decFmt.format(expectedNumber, msg, status);
2258 msg.append(", expected ");
2259 msg.append(expectedString);
2260 msg.append(" but got ");
2261 msg.append(actualString);
2262 errln(msg);
2263 break;
2264 } else {
2265 logln(actualString);
2266 if (testParsing) {
2267 Formattable parsedNumber;
2268 formatter->parse(actualString, parsedNumber, status);
2269 if (U_FAILURE(status)) {
2270 UnicodeString msg = "FAIL: formatter could not parse ";
2271 msg.append(actualString);
2272 msg.append(" status code: " );
2273 msg.append(u_errorName(status));
2274 errln(msg);
2275 break;
2276 } else {
2277 if (parsedNumber != expectedNumber
2278 && (!uprv_isNaN(parsedNumber.getDouble()) || !uprv_isNaN(expectedNumber.getDouble())))
2279 {
2280 UnicodeString msg = "FAIL: parse failed for ";
2281 msg.append(actualString);
2282 msg.append(", expected ");
2283 decFmt.format(expectedNumber, msg, status);
2284 msg.append(", but got ");
2285 decFmt.format(parsedNumber, msg, status);
2286 errln(msg);
2287 break;
2288 }
2289 }
2290 }
2291 }
2292 }
2293 }
2294 }
2295 }
2296 }
2297
2298 void
doLenientParseTest(RuleBasedNumberFormat * formatter,const char * testData[][2])2299 IntlTestRBNF::doLenientParseTest(RuleBasedNumberFormat* formatter, const char* testData[][2])
2300 {
2301 UErrorCode status = U_ZERO_ERROR;
2302 NumberFormat* decFmt = NumberFormat::createInstance(Locale::getUS(), status);
2303 if (U_FAILURE(status)) {
2304 errcheckln(status, "FAIL: could not create NumberFormat - %s", u_errorName(status));
2305 } else {
2306 for (int i = 0; testData[i][0]; ++i) {
2307 const char* spelledNumber = testData[i][0]; // spelled-out number
2308 const char* asciiUSNumber = testData[i][1]; // number as ascii digits formatted for US locale
2309
2310 UnicodeString spelledNumberString = UnicodeString(spelledNumber).unescape();
2311 Formattable actualNumber;
2312 formatter->parse(spelledNumberString, actualNumber, status);
2313 if (U_FAILURE(status)) {
2314 UnicodeString msg = "FAIL: formatter could not parse ";
2315 msg.append(spelledNumberString);
2316 errln(msg);
2317 break;
2318 } else {
2319 // I changed the logic of this test somewhat from Java-- instead of comparing the
2320 // strings, I compare the Formattables. Hmmm, but the Formattables don't compare,
2321 // so change it back.
2322
2323 UnicodeString asciiUSNumberString = asciiUSNumber;
2324 Formattable expectedNumber;
2325 decFmt->parse(asciiUSNumberString, expectedNumber, status);
2326 if (U_FAILURE(status)) {
2327 UnicodeString msg = "FAIL: decFmt could not parse ";
2328 msg.append(asciiUSNumberString);
2329 errln(msg);
2330 break;
2331 } else {
2332 UnicodeString actualNumberString;
2333 UnicodeString expectedNumberString;
2334 decFmt->format(actualNumber, actualNumberString, status);
2335 decFmt->format(expectedNumber, expectedNumberString, status);
2336 if (actualNumberString != expectedNumberString) {
2337 UnicodeString msg = "FAIL: parsing";
2338 msg.append(asciiUSNumberString);
2339 msg.append("\n");
2340 msg.append(" lenient parse failed for ");
2341 msg.append(spelledNumberString);
2342 msg.append(", expected ");
2343 msg.append(expectedNumberString);
2344 msg.append(", but got ");
2345 msg.append(actualNumberString);
2346 errln(msg);
2347 break;
2348 }
2349 }
2350 }
2351 }
2352 delete decFmt;
2353 }
2354 }
2355
2356 /* U_HAVE_RBNF */
2357 #else
2358
2359 void
TestRBNFDisabled()2360 IntlTestRBNF::TestRBNFDisabled() {
2361 errln("*** RBNF currently disabled on this platform ***\n");
2362 }
2363
2364 /* U_HAVE_RBNF */
2365 #endif
2366
2367 #endif /* #if !UCONFIG_NO_FORMATTING */
2368