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