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