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