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