• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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