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