1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4  * COPYRIGHT:
5  * Copyright (c) 1997-2016, International Business Machines Corporation and
6  * others. All Rights Reserved.
7  ********************************************************************/
8 /* Modification History:
9 *   Date        Name        Description
10 *   07/15/99    helena      Ported to HPUX 10/11 CC.
11 */
12 
13 #include "unicode/utypes.h"
14 
15 #if !UCONFIG_NO_FORMATTING
16 
17 #include "numfmtst.h"
18 #include "unicode/currpinf.h"
19 #include "unicode/dcfmtsym.h"
20 #include "unicode/decimfmt.h"
21 #include "unicode/localpointer.h"
22 #include "unicode/ucurr.h"
23 #include "unicode/ustring.h"
24 #include "unicode/measfmt.h"
25 #include "unicode/curramt.h"
26 #include "unicode/strenum.h"
27 #include "textfile.h"
28 #include "tokiter.h"
29 #include "charstr.h"
30 #include "cstr.h"
31 #include "putilimp.h"
32 #include "winnmtst.h"
33 #include <cmath>
34 #include <float.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include "cmemory.h"
38 #include "cstring.h"
39 #include "unicode/numsys.h"
40 #include "fmtableimp.h"
41 #include "numberformattesttuple.h"
42 #include "unicode/msgfmt.h"
43 #include "number_decimalquantity.h"
44 #include "unicode/numberformatter.h"
45 
46 #if (U_PLATFORM == U_PF_AIX) || (U_PLATFORM == U_PF_OS390)
47 // These should not be macros. If they are,
48 // replace them with std::isnan and std::isinf
49 #if defined(isnan)
50 #undef isnan
51 namespace std {
isnan(double x)52  bool isnan(double x) {
53    return _isnan(x);
54  }
55 }
56 #endif
57 #if defined(isinf)
58 #undef isinf
59 namespace std {
isinf(double x)60  bool isinf(double x) {
61    return _isinf(x);
62  }
63 }
64 #endif
65 #endif
66 
67 using icu::number::impl::DecimalQuantity;
68 using namespace icu::number;
69 
70 //#define NUMFMTST_CACHE_DEBUG 1
71 #include "stdio.h" /* for sprintf */
72 // #include "iostream"   // for cout
73 
74 //#define NUMFMTST_DEBUG 1
75 
76 static const UChar EUR[] = {69,85,82,0}; // "EUR"
77 static const UChar ISO_CURRENCY_USD[] = {0x55, 0x53, 0x44, 0}; // "USD"
78 
79 
80 // *****************************************************************************
81 // class NumberFormatTest
82 // *****************************************************************************
83 
84 #define CHECK(status,str) UPRV_BLOCK_MACRO_BEGIN { \
85     if (U_FAILURE(status)) { \
86         errcheckln(status, UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \
87         return; \
88     } \
89 } UPRV_BLOCK_MACRO_END
90 #define CHECK_DATA(status,str) UPRV_BLOCK_MACRO_BEGIN { \
91     if (U_FAILURE(status)) { \
92         dataerrln(UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \
93         return; \
94     } \
95 } UPRV_BLOCK_MACRO_END
96 
runIndexedTest( int32_t index, UBool exec, const char* &name, char* )97 void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
98 {
99   TESTCASE_AUTO_BEGIN;
100   TESTCASE_AUTO(TestCurrencySign);
101   TESTCASE_AUTO(TestCurrency);
102   TESTCASE_AUTO(TestParse);
103   TESTCASE_AUTO(TestRounding487);
104   TESTCASE_AUTO(TestQuotes);
105   TESTCASE_AUTO(TestExponential);
106   TESTCASE_AUTO(TestPatterns);
107   TESTCASE_AUTO(Test20186_SpacesAroundSemicolon);
108 
109   // Upgrade to alphaWorks - liu 5/99
110   TESTCASE_AUTO(TestExponent);
111   TESTCASE_AUTO(TestScientific);
112   TESTCASE_AUTO(TestPad);
113   TESTCASE_AUTO(TestPatterns2);
114   TESTCASE_AUTO(TestSecondaryGrouping);
115   TESTCASE_AUTO(TestSurrogateSupport);
116   TESTCASE_AUTO(TestAPI);
117 
118   TESTCASE_AUTO(TestCurrencyObject);
119   TESTCASE_AUTO(TestCurrencyPatterns);
120   //TESTCASE_AUTO(TestDigitList);
121   TESTCASE_AUTO(TestWhiteSpaceParsing);
122   TESTCASE_AUTO(TestComplexCurrency);  // This test removed because CLDR no longer uses choice formats in currency symbols.
123   TESTCASE_AUTO(TestRegCurrency);
124   TESTCASE_AUTO(TestSymbolsWithBadLocale);
125   TESTCASE_AUTO(TestAdoptDecimalFormatSymbols);
126 
127   TESTCASE_AUTO(TestScientific2);
128   TESTCASE_AUTO(TestScientificGrouping);
129   TESTCASE_AUTO(TestInt64);
130 
131   TESTCASE_AUTO(TestPerMill);
132   TESTCASE_AUTO(TestIllegalPatterns);
133   TESTCASE_AUTO(TestCases);
134 
135   TESTCASE_AUTO(TestCurrencyNames);
136   TESTCASE_AUTO(TestCurrencyVariants);
137   TESTCASE_AUTO(TestCurrencyAmount);
138   TESTCASE_AUTO(TestCurrencyUnit);
139   TESTCASE_AUTO(TestCoverage);
140   TESTCASE_AUTO(TestLocalizedPatternSymbolCoverage);
141   TESTCASE_AUTO(TestJB3832);
142   TESTCASE_AUTO(TestHost);
143   TESTCASE_AUTO(TestHostClone);
144   TESTCASE_AUTO(TestCurrencyFormat);
145   TESTCASE_AUTO(TestRounding);
146   TESTCASE_AUTO(TestNonpositiveMultiplier);
147   TESTCASE_AUTO(TestNumberingSystems);
148   TESTCASE_AUTO(TestSpaceParsing);
149   TESTCASE_AUTO(TestMultiCurrencySign);
150   TESTCASE_AUTO(TestCurrencyFormatForMixParsing);
151   TESTCASE_AUTO(TestMismatchedCurrencyFormatFail);
152   TESTCASE_AUTO(TestDecimalFormatCurrencyParse);
153   TESTCASE_AUTO(TestCurrencyIsoPluralFormat);
154   TESTCASE_AUTO(TestCurrencyParsing);
155   TESTCASE_AUTO(TestParseCurrencyInUCurr);
156   TESTCASE_AUTO(TestFormatAttributes);
157   TESTCASE_AUTO(TestFieldPositionIterator);
158   TESTCASE_AUTO(TestDecimal);
159   TESTCASE_AUTO(TestCurrencyFractionDigits);
160   TESTCASE_AUTO(TestExponentParse);
161   TESTCASE_AUTO(TestExplicitParents);
162   TESTCASE_AUTO(TestLenientParse);
163   TESTCASE_AUTO(TestAvailableNumberingSystems);
164   TESTCASE_AUTO(TestRoundingPattern);
165   TESTCASE_AUTO(Test9087);
166   TESTCASE_AUTO(TestFormatFastpaths);
167   TESTCASE_AUTO(TestFormattableSize);
168   TESTCASE_AUTO(TestUFormattable);
169   TESTCASE_AUTO(TestSignificantDigits);
170   TESTCASE_AUTO(TestShowZero);
171   TESTCASE_AUTO(TestCompatibleCurrencies);
172   TESTCASE_AUTO(TestBug9936);
173   TESTCASE_AUTO(TestParseNegativeWithFaLocale);
174   TESTCASE_AUTO(TestParseNegativeWithAlternateMinusSign);
175   TESTCASE_AUTO(TestCustomCurrencySignAndSeparator);
176   TESTCASE_AUTO(TestParseSignsAndMarks);
177   TESTCASE_AUTO(Test10419RoundingWith0FractionDigits);
178   TESTCASE_AUTO(Test10468ApplyPattern);
179   TESTCASE_AUTO(TestRoundingScientific10542);
180   TESTCASE_AUTO(TestZeroScientific10547);
181   TESTCASE_AUTO(TestAccountingCurrency);
182   TESTCASE_AUTO(TestCurrencyFormatForMissingLocale);
183   TESTCASE_AUTO(TestEquality);
184   TESTCASE_AUTO(TestCurrencyUsage);
185   TESTCASE_AUTO(TestDoubleLimit11439);
186   TESTCASE_AUTO(TestGetAffixes);
187   TESTCASE_AUTO(TestToPatternScientific11648);
188   TESTCASE_AUTO(TestBenchmark);
189   TESTCASE_AUTO(TestCtorApplyPatternDifference);
190   TESTCASE_AUTO(TestFractionalDigitsForCurrency);
191   TESTCASE_AUTO(TestFormatCurrencyPlural);
192   TESTCASE_AUTO(Test11868);
193   TESTCASE_AUTO(Test11739_ParseLongCurrency);
194   TESTCASE_AUTO(Test13035_MultiCodePointPaddingInPattern);
195   TESTCASE_AUTO(Test13737_ParseScientificStrict);
196   TESTCASE_AUTO(Test10727_RoundingZero);
197   TESTCASE_AUTO(Test11376_getAndSetPositivePrefix);
198   TESTCASE_AUTO(Test11475_signRecognition);
199   TESTCASE_AUTO(Test11640_getAffixes);
200   TESTCASE_AUTO(Test11649_toPatternWithMultiCurrency);
201   TESTCASE_AUTO(Test13327_numberingSystemBufferOverflow);
202   TESTCASE_AUTO(Test13391_chakmaParsing);
203   TESTCASE_AUTO(Test11735_ExceptionIssue);
204   TESTCASE_AUTO(Test11035_FormatCurrencyAmount);
205   TESTCASE_AUTO(Test11318_DoubleConversion);
206   TESTCASE_AUTO(TestParsePercentRegression);
207   TESTCASE_AUTO(TestMultiplierWithScale);
208   TESTCASE_AUTO(TestFastFormatInt32);
209   TESTCASE_AUTO(Test11646_Equality);
210   TESTCASE_AUTO(TestParseNaN);
211   TESTCASE_AUTO(TestFormatFailIfMoreThanMaxDigits);
212   TESTCASE_AUTO(TestParseCaseSensitive);
213   TESTCASE_AUTO(TestParseNoExponent);
214   TESTCASE_AUTO(TestSignAlwaysShown);
215   TESTCASE_AUTO(TestMinimumGroupingDigits);
216   TESTCASE_AUTO(Test11897_LocalizedPatternSeparator);
217   TESTCASE_AUTO(Test13055_PercentageRounding);
218   TESTCASE_AUTO(Test11839);
219   TESTCASE_AUTO(Test10354);
220   TESTCASE_AUTO(Test11645_ApplyPatternEquality);
221   TESTCASE_AUTO(Test12567);
222   TESTCASE_AUTO(Test11626_CustomizeCurrencyPluralInfo);
223   TESTCASE_AUTO(Test20073_StrictPercentParseErrorIndex);
224   TESTCASE_AUTO(Test13056_GroupingSize);
225   TESTCASE_AUTO(Test11025_CurrencyPadding);
226   TESTCASE_AUTO(Test11648_ExpDecFormatMalPattern);
227   TESTCASE_AUTO(Test11649_DecFmtCurrencies);
228   TESTCASE_AUTO(Test13148_ParseGroupingSeparators);
229   TESTCASE_AUTO(Test12753_PatternDecimalPoint);
230   TESTCASE_AUTO(Test11647_PatternCurrencySymbols);
231   TESTCASE_AUTO(Test11913_BigDecimal);
232   TESTCASE_AUTO(Test11020_RoundingInScientificNotation);
233   TESTCASE_AUTO(Test11640_TripleCurrencySymbol);
234   TESTCASE_AUTO(Test13763_FieldPositionIteratorOffset);
235   TESTCASE_AUTO(Test13777_ParseLongNameNonCurrencyMode);
236   TESTCASE_AUTO(Test13804_EmptyStringsWhenParsing);
237   TESTCASE_AUTO(Test20037_ScientificIntegerOverflow);
238   TESTCASE_AUTO(Test13840_ParseLongStringCrash);
239   TESTCASE_AUTO(Test13850_EmptyStringCurrency);
240   TESTCASE_AUTO(Test20348_CurrencyPrefixOverride);
241   TESTCASE_AUTO(Test20956_MonetarySymbolGetters);
242   TESTCASE_AUTO(Test20358_GroupingInPattern);
243   TESTCASE_AUTO(Test13731_DefaultCurrency);
244   TESTCASE_AUTO(Test20499_CurrencyVisibleDigitsPlural);
245   TESTCASE_AUTO(Test13735_GroupingSizeGetter);
246   TESTCASE_AUTO(Test13734_StrictFlexibleWhitespace);
247   TESTCASE_AUTO(Test20961_CurrencyPluralPattern);
248   TESTCASE_AUTO(Test21134_ToNumberFormatter);
249   TESTCASE_AUTO(Test13733_StrictAndLenient);
250   TESTCASE_AUTO(Test20425_IntegerIncrement);
251   TESTCASE_AUTO(Test20425_FractionWithIntegerIncrement);
252   TESTCASE_AUTO(Test21232_ParseTimeout);
253   TESTCASE_AUTO(Test10997_FormatCurrency);
254   TESTCASE_AUTO(Test21556_CurrencyAsDecimal);
255   TESTCASE_AUTO(Test22088_Ethiopic);
256   TESTCASE_AUTO_END;
257 }
258 
259 // -------------------------------------
260 
261 // Test API (increase code coverage)
262 void
TestAPI(void)263 NumberFormatTest::TestAPI(void)
264 {
265   logln("Test API");
266   UErrorCode status = U_ZERO_ERROR;
267   NumberFormat *test = NumberFormat::createInstance("root", status);
268   if(U_FAILURE(status)) {
269     dataerrln("unable to create format object - %s", u_errorName(status));
270   }
271   if(test != NULL) {
272     test->setMinimumIntegerDigits(10);
273     test->setMaximumIntegerDigits(1);
274 
275     test->setMinimumFractionDigits(10);
276     test->setMaximumFractionDigits(1);
277 
278     UnicodeString result;
279     FieldPosition pos;
280     Formattable bla("Paja Patak"); // Donald Duck for non Serbian speakers
281     test->format(bla, result, pos, status);
282     if(U_SUCCESS(status)) {
283       errln("Yuck... Formatted a duck... As a number!");
284     } else {
285       status = U_ZERO_ERROR;
286     }
287 
288     result.remove();
289     int64_t ll = 12;
290     test->format(ll, result);
291     assertEquals("format int64_t error", u"2.0", result);
292 
293     test->setMinimumIntegerDigits(4);
294     test->setMinimumFractionDigits(4);
295 
296     result.remove();
297     test->format(ll, result);
298     assertEquals("format int64_t error", u"0,012.0000", result);
299 
300     ParsePosition ppos;
301     LocalPointer<CurrencyAmount> currAmt(test->parseCurrency("",ppos));
302     // old test for (U_FAILURE(status)) was bogus here, method does not set status!
303     if (ppos.getIndex()) {
304         errln("Parsed empty string as currency");
305     }
306 
307     delete test;
308   }
309 }
310 
311 class StubNumberFormat :public NumberFormat{
312 public:
StubNumberFormat()313     StubNumberFormat(){}
314     virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const override {
315         return appendTo;
316     }
317     virtual UnicodeString& format(int32_t ,UnicodeString& appendTo,FieldPosition& ) const override {
318         return appendTo.append((UChar)0x0033);
319     }
320     virtual UnicodeString& format(int64_t number,UnicodeString& appendTo,FieldPosition& pos) const override {
321         return NumberFormat::format(number, appendTo, pos);
322     }
323     virtual UnicodeString& format(const Formattable& , UnicodeString& appendTo, FieldPosition& , UErrorCode& ) const override {
324         return appendTo;
325     }
326     virtual void parse(const UnicodeString& ,
327                     Formattable& ,
328                     ParsePosition& ) const override {}
329     virtual void parse( const UnicodeString& ,
330                         Formattable& ,
331                         UErrorCode& ) const override {}
332     virtual UClassID getDynamicClassID(void) const override {
333         static char classID = 0;
334         return (UClassID)&classID;
335     }
336     virtual StubNumberFormat* clone() const override {return NULL;}
337 };
338 
339 void
TestCoverage(void)340 NumberFormatTest::TestCoverage(void){
341     StubNumberFormat stub;
342     UnicodeString agent("agent");
343     FieldPosition pos;
344     int64_t num = 4;
345     if (stub.format(num, agent, pos) != UnicodeString("agent3")){
346         errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)");
347     }
348 }
349 
TestLocalizedPatternSymbolCoverage()350 void NumberFormatTest::TestLocalizedPatternSymbolCoverage() {
351     IcuTestErrorCode errorCode(*this, "TestLocalizedPatternSymbolCoverage");
352     // Ticket #12961: DecimalFormat::toLocalizedPattern() is not working as designed.
353     DecimalFormatSymbols dfs(errorCode);
354     dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u'⁖');
355     dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'⁘');
356     dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u'⁙');
357     dfs.setSymbol(DecimalFormatSymbols::kDigitSymbol, u'▰');
358     dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u'໐');
359     dfs.setSymbol(DecimalFormatSymbols::kSignificantDigitSymbol, u'⁕');
360     dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u'†');
361     dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u'‡');
362     dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u'⁜');
363     dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u'‱');
364     dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"⁑⁑"); // tests multi-char sequence
365     dfs.setSymbol(DecimalFormatSymbols::kPadEscapeSymbol, u'⁂');
366 
367     {
368         UnicodeString standardPattern(u"#,##0.05+%;#,##0.05-%");
369         UnicodeString localizedPattern(u"▰⁖▰▰໐⁘໐໕†⁜⁙▰⁖▰▰໐⁘໐໕‡⁜");
370 
371         DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
372         df1.applyPattern(standardPattern, errorCode);
373         DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
374         df2.applyLocalizedPattern(localizedPattern, errorCode);
375         assertTrue("DecimalFormat instances should be equal", df1 == df2);
376         UnicodeString p2;
377         assertEquals("toPattern should match on localizedPattern instance",
378                 standardPattern, df2.toPattern(p2));
379         UnicodeString lp1;
380         assertEquals("toLocalizedPattern should match on standardPattern instance",
381                 localizedPattern, df1.toLocalizedPattern(lp1));
382     }
383 
384     {
385         UnicodeString standardPattern(u"* @@@E0‰");
386         UnicodeString localizedPattern(u"⁂ ⁕⁕⁕⁑⁑໐‱");
387 
388         DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
389         df1.applyPattern(standardPattern, errorCode);
390         DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
391         df2.applyLocalizedPattern(localizedPattern, errorCode);
392         assertTrue("DecimalFormat instances should be equal", df1 == df2);
393         UnicodeString p2;
394         assertEquals("toPattern should match on localizedPattern instance",
395                 standardPattern, df2.toPattern(p2));
396         UnicodeString lp1;
397         assertEquals("toLocalizedPattern should match on standardPattern instance",
398                 localizedPattern, df1.toLocalizedPattern(lp1));
399     }
400 }
401 
402 // Test various patterns
403 void
TestPatterns(void)404 NumberFormatTest::TestPatterns(void)
405 {
406     UErrorCode status = U_ZERO_ERROR;
407     DecimalFormatSymbols sym(Locale::getUS(), status);
408     if (U_FAILURE(status)) { errcheckln(status, "FAIL: Could not construct DecimalFormatSymbols - %s", u_errorName(status)); return; }
409 
410     const char* pat[]    = { "#.#", "#.", ".#", "#" };
411     int32_t pat_length = UPRV_LENGTHOF(pat);
412     const char* newpat[] = { "0.#", "0.", "#.0", "0" };
413     const char* num[]    = { "0",   "0.", ".0", "0" };
414     for (int32_t i=0; i<pat_length; ++i)
415     {
416         status = U_ZERO_ERROR;
417         DecimalFormat fmt(pat[i], sym, status);
418         if (U_FAILURE(status)) { errln((UnicodeString)"FAIL: DecimalFormat constructor failed for " + pat[i]); continue; }
419         UnicodeString newp; fmt.toPattern(newp);
420         if (!(newp == newpat[i]))
421             errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
422                   "; " + newp + " seen instead");
423 
424         UnicodeString s; (*(NumberFormat*)&fmt).format((int32_t)0, s);
425         if (!(s == num[i]))
426         {
427             errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
428                   "; " + s + " seen instead");
429             logln((UnicodeString)"Min integer digits = " + fmt.getMinimumIntegerDigits());
430         }
431     }
432 }
433 
Test20186_SpacesAroundSemicolon()434 void NumberFormatTest::Test20186_SpacesAroundSemicolon() {
435     IcuTestErrorCode status(*this, "Test20186_SpacesAroundSemicolon");
436     DecimalFormat df(u"0.00 ; -0.00", {"en-us", status}, status);
437     expect2(df, 1, u"1.00 ");
438     expect2(df, -1, u" -1.00");
439 
440     df = DecimalFormat(u"0.00;", {"en-us", status}, status);
441     expect2(df, 1, u"1.00");
442     expect2(df, -1, u"-1.00");
443 
444     df = DecimalFormat(u"0.00;0.00", {"en-us", status}, status);
445     expect2(df, 1, u"1.00");
446     expect(df, -1, u"1.00");  // parses as 1, not -1
447 
448     df = DecimalFormat(u" 0.00 ; -0.00 ", {"en-us", status}, status);
449     expect2(df, 1, u" 1.00 ");
450     expect2(df, -1, u" -1.00 ");
451 }
452 
453 /*
454 icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
455 icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
456 icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
457 */
458 /*
459 void
460 NumberFormatTest::TestDigitList(void)
461 {
462   // API coverage for DigitList
463   DigitList list1;
464   list1.append('1');
465   list1.fDecimalAt = 1;
466   DigitList list2;
467   list2.set((int32_t)1);
468   if (list1 != list2) {
469     errln("digitlist append, operator!= or set failed ");
470   }
471   if (!(list1 == list2)) {
472     errln("digitlist append, operator== or set failed ");
473   }
474 }
475 */
476 
477 // -------------------------------------
478 
479 // Test exponential pattern
480 void
TestExponential(void)481 NumberFormatTest::TestExponential(void)
482 {
483     UErrorCode status = U_ZERO_ERROR;
484     DecimalFormatSymbols sym(Locale::getUS(), status);
485     if (U_FAILURE(status)) { errcheckln(status, "FAIL: Bad status returned by DecimalFormatSymbols ct - %s", u_errorName(status)); return; }
486     const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]"  };
487     int32_t pat_length = UPRV_LENGTHOF(pat);
488 
489 // The following #if statements allow this test to be built and run on
490 // platforms that do not have standard IEEE numerics.  For example,
491 // S/390 doubles have an exponent range of -78 to +75.  For the
492 // following #if statements to work, float.h must define
493 // DBL_MAX_10_EXP to be a compile-time constant.
494 
495 // This section may be expanded as needed.
496 
497 #if DBL_MAX_10_EXP > 300
498     double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
499     int32_t val_length = UPRV_LENGTHOF(val);
500     const char* valFormat[] =
501     {
502         // 0.####E0
503         "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
504         // 00.000E00
505         "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
506         // ##0.######E000
507         "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
508         // 0.###E0;[0.###E0]
509         "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
510     };
511     double valParse[] =
512     {
513         0.01234, 123460000, 1.23E300, -3.1416E-271,
514         0.01234, 123460000, 1.23E300, -3.1416E-271,
515         0.01234, 123456800, 1.23E300, -3.141593E-271,
516         0.01234, 123500000, 1.23E300, -3.142E-271,
517     };
518 #elif DBL_MAX_10_EXP > 70
519     double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
520     int32_t val_length = UPRV_LENGTHOF(val);
521     char* valFormat[] =
522     {
523         // 0.####E0
524         "1.234E-2", "1.2346E8", "1.23E70", "-3.1416E-71",
525         // 00.000E00
526         "12.340E-03", "12.346E07", "12.300E69", "-31.416E-72",
527         // ##0.######E000
528         "12.34E-003", "123.4568E006", "12.3E069", "-31.41593E-072",
529         // 0.###E0;[0.###E0]
530         "1.234E-2", "1.235E8", "1.23E70", "[3.142E-71]"
531     };
532     double valParse[] =
533     {
534         0.01234, 123460000, 1.23E70, -3.1416E-71,
535         0.01234, 123460000, 1.23E70, -3.1416E-71,
536         0.01234, 123456800, 1.23E70, -3.141593E-71,
537         0.01234, 123500000, 1.23E70, -3.142E-71,
538     };
539 #else
540     // Don't test double conversion
541     double* val = 0;
542     int32_t val_length = 0;
543     char** valFormat = 0;
544     double* valParse = 0;
545     logln("Warning: Skipping double conversion tests");
546 #endif
547 
548     int32_t lval[] = { 0, -1, 1, 123456789 };
549     int32_t lval_length = UPRV_LENGTHOF(lval);
550     const char* lvalFormat[] =
551     {
552         // 0.####E0
553         "0E0", "-1E0", "1E0", "1.2346E8",
554         // 00.000E00
555         "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
556         // ##0.######E000
557         "0E000", "-1E000", "1E000", "123.4568E006",
558         // 0.###E0;[0.###E0]
559         "0E0", "[1E0]", "1E0", "1.235E8"
560     };
561     int32_t lvalParse[] =
562     {
563         0, -1, 1, 123460000,
564         0, -1, 1, 123460000,
565         0, -1, 1, 123456800,
566         0, -1, 1, 123500000,
567     };
568     int32_t ival = 0, ilval = 0;
569     for (int32_t p=0; p<pat_length; ++p)
570     {
571         DecimalFormat fmt(pat[p], sym, status);
572         if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormat ct"); continue; }
573         UnicodeString pattern;
574         logln((UnicodeString)"Pattern \"" + pat[p] + "\" -toPattern-> \"" +
575           fmt.toPattern(pattern) + "\"");
576         int32_t v;
577         for (v=0; v<val_length; ++v)
578         {
579             UnicodeString s; (*(NumberFormat*)&fmt).format(val[v], s);
580             logln((UnicodeString)" " + val[v] + " -format-> " + s);
581             if (s != valFormat[v+ival])
582                 errln((UnicodeString)"FAIL: Expected " + valFormat[v+ival]);
583 
584             ParsePosition pos(0);
585             Formattable af;
586             fmt.parse(s, af, pos);
587             double a;
588             UBool useEpsilon = false;
589             if (af.getType() == Formattable::kLong)
590                 a = af.getLong();
591             else if (af.getType() == Formattable::kDouble) {
592                 a = af.getDouble();
593 #if U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400
594                 // S/390 will show a failure like this:
595                 //| -3.141592652999999e-271 -format-> -3.1416E-271
596                 //|                          -parse-> -3.1416e-271
597                 //| FAIL: Expected -3.141599999999999e-271
598                 // To compensate, we use an epsilon-based equality
599                 // test on S/390 only.  We don't want to do this in
600                 // general because it's less exacting.
601                 useEpsilon = true;
602 #endif
603             }
604             else {
605                 errln(UnicodeString("FAIL: Non-numeric Formattable returned: ") + pattern + " " + s);
606                 continue;
607             }
608             if (pos.getIndex() == s.length())
609             {
610                 logln((UnicodeString)"  -parse-> " + a);
611                 // Use epsilon comparison as necessary
612                 if ((useEpsilon &&
613                     (uprv_fabs(a - valParse[v+ival]) / a > (2*DBL_EPSILON))) ||
614                     (!useEpsilon && a != valParse[v+ival]))
615                 {
616                     errln((UnicodeString)"FAIL: Expected " + valParse[v+ival] + " but got " + a
617                         + " on input " + s);
618                 }
619             }
620             else {
621                 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
622                 errln((UnicodeString)"  should be (" + s.length() + " chars) -> " + valParse[v+ival]);
623             }
624         }
625         for (v=0; v<lval_length; ++v)
626         {
627             UnicodeString s;
628             (*(NumberFormat*)&fmt).format(lval[v], s);
629             logln((UnicodeString)" " + lval[v] + "L -format-> " + s);
630             if (s != lvalFormat[v+ilval])
631                 errln((UnicodeString)"ERROR: Expected " + lvalFormat[v+ilval] + " Got: " + s);
632 
633             ParsePosition pos(0);
634             Formattable af;
635             fmt.parse(s, af, pos);
636             if (af.getType() == Formattable::kLong ||
637                 af.getType() == Formattable::kInt64) {
638                 UErrorCode status = U_ZERO_ERROR;
639                 int32_t a = af.getLong(status);
640                 if (pos.getIndex() == s.length())
641                 {
642                     logln((UnicodeString)"  -parse-> " + a);
643                     if (a != lvalParse[v+ilval])
644                         errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval] + " but got " + a);
645                 }
646                 else
647                     errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
648             }
649             else
650                 errln((UnicodeString)"FAIL: Non-long Formattable returned for " + s
651                     + " Double: " + af.getDouble()
652                     + ", Long: " + af.getLong());
653         }
654         ival += val_length;
655         ilval += lval_length;
656     }
657 }
658 
659 void
TestScientific2()660 NumberFormatTest::TestScientific2() {
661     // jb 2552
662     UErrorCode status = U_ZERO_ERROR;
663     DecimalFormat* fmt = (DecimalFormat*)NumberFormat::createCurrencyInstance("en_US", status);
664     if (U_SUCCESS(status)) {
665         double num = 12.34;
666         expect(*fmt, num, "$12.34");
667         fmt->setScientificNotation(true);
668         expect(*fmt, num, "$1.23E1");
669         fmt->setScientificNotation(false);
670         expect(*fmt, num, "$12.34");
671     }
672     delete fmt;
673 }
674 
675 void
TestScientificGrouping()676 NumberFormatTest::TestScientificGrouping() {
677     // jb 2552
678     UErrorCode status = U_ZERO_ERROR;
679     DecimalFormat fmt("##0.00E0",status);
680     if (assertSuccess("", status, true, __FILE__, __LINE__)) {
681         expect(fmt, .01234, "12.3E-3");
682         expect(fmt, .1234, "123E-3");
683         expect(fmt, 1.234, "1.23E0");
684         expect(fmt, 12.34, "12.3E0");
685         expect(fmt, 123.4, "123E0");
686         expect(fmt, 1234., "1.23E3");
687     }
688 }
689 
690 /*static void setFromString(DigitList& dl, const char* str) {
691     char c;
692     UBool decimalSet = false;
693     dl.clear();
694     while ((c = *str++)) {
695         if (c == '-') {
696             dl.fIsPositive = false;
697         } else if (c == '+') {
698             dl.fIsPositive = true;
699         } else if (c == '.') {
700             dl.fDecimalAt = dl.fCount;
701             decimalSet = true;
702         } else {
703             dl.append(c);
704         }
705     }
706     if (!decimalSet) {
707         dl.fDecimalAt = dl.fCount;
708     }
709 }*/
710 
711 void
TestInt64()712 NumberFormatTest::TestInt64() {
713     UErrorCode status = U_ZERO_ERROR;
714     DecimalFormat fmt("#.#E0",status);
715     if (U_FAILURE(status)) {
716         dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
717         return;
718     }
719     fmt.setMaximumFractionDigits(20);
720     if (U_SUCCESS(status)) {
721         expect(fmt, (Formattable)(int64_t)0, "0E0");
722         expect(fmt, (Formattable)(int64_t)-1, "-1E0");
723         expect(fmt, (Formattable)(int64_t)1, "1E0");
724         expect(fmt, (Formattable)(int64_t)2147483647, "2.147483647E9");
725         expect(fmt, (Formattable)((int64_t)-2147483647-1), "-2.147483648E9");
726         expect(fmt, (Formattable)(int64_t)U_INT64_MAX, "9.223372036854775807E18");
727         expect(fmt, (Formattable)(int64_t)U_INT64_MIN, "-9.223372036854775808E18");
728     }
729 
730     // also test digitlist
731 /*    int64_t int64max = U_INT64_MAX;
732     int64_t int64min = U_INT64_MIN;
733     const char* int64maxstr = "9223372036854775807";
734     const char* int64minstr = "-9223372036854775808";
735     UnicodeString fail("fail: ");
736 
737     // test max int64 value
738     DigitList dl;
739     setFromString(dl, int64maxstr);
740     {
741         if (!dl.fitsIntoInt64(false)) {
742             errln(fail + int64maxstr + " didn't fit");
743         }
744         int64_t int64Value = dl.getInt64();
745         if (int64Value != int64max) {
746             errln(fail + int64maxstr);
747         }
748         dl.set(int64Value);
749         int64Value = dl.getInt64();
750         if (int64Value != int64max) {
751             errln(fail + int64maxstr);
752         }
753     }
754     // test negative of max int64 value (1 shy of min int64 value)
755     dl.fIsPositive = false;
756     {
757         if (!dl.fitsIntoInt64(false)) {
758             errln(fail + "-" + int64maxstr + " didn't fit");
759         }
760         int64_t int64Value = dl.getInt64();
761         if (int64Value != -int64max) {
762             errln(fail + "-" + int64maxstr);
763         }
764         dl.set(int64Value);
765         int64Value = dl.getInt64();
766         if (int64Value != -int64max) {
767             errln(fail + "-" + int64maxstr);
768         }
769     }
770     // test min int64 value
771     setFromString(dl, int64minstr);
772     {
773         if (!dl.fitsIntoInt64(false)) {
774             errln(fail + "-" + int64minstr + " didn't fit");
775         }
776         int64_t int64Value = dl.getInt64();
777         if (int64Value != int64min) {
778             errln(fail + int64minstr);
779         }
780         dl.set(int64Value);
781         int64Value = dl.getInt64();
782         if (int64Value != int64min) {
783             errln(fail + int64minstr);
784         }
785     }
786     // test negative of min int 64 value (1 more than max int64 value)
787     dl.fIsPositive = true; // won't fit
788     {
789         if (dl.fitsIntoInt64(false)) {
790             errln(fail + "-(" + int64minstr + ") didn't fit");
791         }
792     }*/
793 }
794 
795 // -------------------------------------
796 
797 // Test the handling of quotes
798 void
TestQuotes(void)799 NumberFormatTest::TestQuotes(void)
800 {
801     UErrorCode status = U_ZERO_ERROR;
802     UnicodeString *pat;
803     DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), status);
804     if (U_FAILURE(status)) {
805         errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
806         delete sym;
807         return;
808     }
809     pat = new UnicodeString("a'fo''o'b#");
810     DecimalFormat *fmt = new DecimalFormat(*pat, *sym, status);
811     UnicodeString s;
812     ((NumberFormat*)fmt)->format((int32_t)123, s);
813     logln((UnicodeString)"Pattern \"" + *pat + "\"");
814     logln((UnicodeString)" Format 123 -> " + escape(s));
815     if (!(s=="afo'ob123"))
816         errln((UnicodeString)"FAIL: Expected afo'ob123");
817 
818     s.truncate(0);
819     delete fmt;
820     delete pat;
821 
822     pat = new UnicodeString("a''b#");
823     fmt = new DecimalFormat(*pat, *sym, status);
824     ((NumberFormat*)fmt)->format((int32_t)123, s);
825     logln((UnicodeString)"Pattern \"" + *pat + "\"");
826     logln((UnicodeString)" Format 123 -> " + escape(s));
827     if (!(s=="a'b123"))
828         errln((UnicodeString)"FAIL: Expected a'b123");
829     delete fmt;
830     delete pat;
831     delete sym;
832 }
833 
834 /**
835  * Test the handling of the currency symbol in patterns.
836  */
837 void
TestCurrencySign(void)838 NumberFormatTest::TestCurrencySign(void)
839 {
840     UErrorCode status = U_ZERO_ERROR;
841     DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale::getUS(), status);
842     UnicodeString pat;
843     UChar currency = 0x00A4;
844     if (U_FAILURE(status)) {
845         errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
846         delete sym;
847         return;
848     }
849     // "\xA4#,##0.00;-\xA4#,##0.00"
850     pat.append(currency).append("#,##0.00;-").
851         append(currency).append("#,##0.00");
852     DecimalFormat *fmt = new DecimalFormat(pat, *sym, status);
853     UnicodeString s; ((NumberFormat*)fmt)->format(1234.56, s);
854     pat.truncate(0);
855     logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
856     logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
857     if (s != "$1,234.56") dataerrln((UnicodeString)"FAIL: Expected $1,234.56");
858     s.truncate(0);
859     ((NumberFormat*)fmt)->format(- 1234.56, s);
860     logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
861     if (s != "-$1,234.56") dataerrln((UnicodeString)"FAIL: Expected -$1,234.56");
862     delete fmt;
863     pat.truncate(0);
864     // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
865     pat.append(currency).append(currency).
866         append(" #,##0.00;").
867         append(currency).append(currency).
868         append(" -#,##0.00");
869     fmt = new DecimalFormat(pat, *sym, status);
870     s.truncate(0);
871     ((NumberFormat*)fmt)->format(1234.56, s);
872     logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
873     logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
874     if (s != "USD 1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD 1,234.56");
875     s.truncate(0);
876     ((NumberFormat*)fmt)->format(-1234.56, s);
877     logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
878     if (s != "USD -1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD -1,234.56");
879     delete fmt;
880     delete sym;
881     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + u_errorName(status));
882 }
883 
884 // -------------------------------------
885 
toHexString(int32_t i)886 static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
887 
888 UnicodeString&
escape(UnicodeString& s)889 NumberFormatTest::escape(UnicodeString& s)
890 {
891     UnicodeString buf;
892     for (int32_t i=0; i<s.length(); ++i)
893     {
894         UChar c = s[(int32_t)i];
895         if (c <= (UChar)0x7F) buf += c;
896         else {
897             buf += (UChar)0x5c; buf += (UChar)0x55;
898             buf += toHexString((c & 0xF000) >> 12);
899             buf += toHexString((c & 0x0F00) >> 8);
900             buf += toHexString((c & 0x00F0) >> 4);
901             buf += toHexString(c & 0x000F);
902         }
903     }
904     return (s = buf);
905 }
906 
907 
908 // -------------------------------------
909 static const char* testCases[][2]= {
910      /* locale ID */  /* expected */
911     {"ca_ES@currency=ESP", "\\u20A7\\u00A01.150" },
912     {"de_LU@currency=LUF", "1,150\\u00A0F" },
913     {"el_GR@currency=GRD", "1.150,50\\u00A0\\u0394\\u03C1\\u03C7" },
914     {"en_BE@currency=BEF", "1.150,50\\u00A0BEF" },
915     {"es_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
916     {"eu_ES@currency=ESP", "\\u20A7\\u00A01.150" },
917     {"gl_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
918     {"it_IT@currency=ITL", "ITL\\u00A01.150" },
919     {"pt_PT@currency=PTE", "1,150$50\\u00A0\\u200B"}, // per cldrbug 7670
920     {"en_US@currency=JPY", "\\u00A51,150"},
921     {"en_US@currency=jpy", "\\u00A51,150"},
922     {"en-US-u-cu-jpy", "\\u00A51,150"}
923 };
924 /**
925  * Test localized currency patterns.
926  */
927 void
TestCurrency(void)928 NumberFormatTest::TestCurrency(void)
929 {
930     UErrorCode status = U_ZERO_ERROR;
931     NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
932     if (U_FAILURE(status)) {
933         dataerrln("Error calling NumberFormat::createCurrencyInstance()");
934         return;
935     }
936 
937     UnicodeString s; currencyFmt->format(1.50, s);
938     logln((UnicodeString)"Un pauvre ici a..........." + s);
939     if (!(s==CharsToUnicodeString("1,50\\u00A0$")))
940         errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$ but got " + s);
941     delete currencyFmt;
942     s.truncate(0);
943     char loc[256]={0};
944     int len = uloc_canonicalize("de_DE@currency=DEM", loc, 256, &status);
945     (void)len;  // Suppress unused variable warning.
946     currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
947     currencyFmt->format(1.50, s);
948     logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
949     if (!(s==CharsToUnicodeString("1,50\\u00A0DM")))
950         errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM but got " + s);
951     delete currencyFmt;
952     s.truncate(0);
953     len = uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status);
954     currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
955     currencyFmt->format(1.50, s);
956     logln((UnicodeString)"Un pauvre en France a....." + s);
957     if (!(s==CharsToUnicodeString("1,50\\u00A0F")))
958         errln((UnicodeString)"FAIL: Expected 1,50<nbsp>F");
959     delete currencyFmt;
960     if (U_FAILURE(status))
961         errln((UnicodeString)"FAIL: Status " + (int32_t)status);
962 
963     for(int i=0; i < UPRV_LENGTHOF(testCases); i++){
964         status = U_ZERO_ERROR;
965         const char *localeID = testCases[i][0];
966         UnicodeString expected(testCases[i][1], -1, US_INV);
967         expected = expected.unescape();
968         s.truncate(0);
969         char loc[256]={0};
970         uloc_canonicalize(localeID, loc, 256, &status);
971         currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
972         if(U_FAILURE(status)){
973             errln("Could not create currency formatter for locale %s",localeID);
974             continue;
975         }
976         currencyFmt->format(1150.50, s);
977         if(s!=expected){
978             errln(UnicodeString("FAIL: Expected: ")+expected
979                     + UnicodeString(" Got: ") + s
980                     + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
981         }
982         if (U_FAILURE(status)){
983             errln((UnicodeString)"FAIL: Status " + (int32_t)status);
984         }
985         delete currencyFmt;
986     }
987 }
988 
989 // -------------------------------------
990 
991 /**
992  * Test the Currency object handling, new as of ICU 2.2.
993  */
TestCurrencyObject()994 void NumberFormatTest::TestCurrencyObject() {
995     UErrorCode ec = U_ZERO_ERROR;
996     NumberFormat* fmt =
997         NumberFormat::createCurrencyInstance(Locale::getUS(), ec);
998 
999     if (U_FAILURE(ec)) {
1000         dataerrln("FAIL: getCurrencyInstance(US) - %s", u_errorName(ec));
1001         delete fmt;
1002         return;
1003     }
1004 
1005     Locale null("", "", "");
1006 
1007     expectCurrency(*fmt, null, 1234.56, "$1,234.56");
1008 
1009     expectCurrency(*fmt, Locale::getFrance(),
1010                    1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro
1011 
1012     expectCurrency(*fmt, Locale::getJapan(),
1013                    1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
1014 
1015     expectCurrency(*fmt, Locale("fr", "CH", ""),
1016                    1234.56, "CHF 1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
1017 
1018     expectCurrency(*fmt, Locale::getUS(),
1019                    1234.56, "$1,234.56");
1020 
1021     delete fmt;
1022     fmt = NumberFormat::createCurrencyInstance(Locale::getFrance(), ec);
1023 
1024     if (U_FAILURE(ec)) {
1025         errln("FAIL: getCurrencyInstance(FRANCE)");
1026         delete fmt;
1027         return;
1028     }
1029 
1030     expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC"));
1031 
1032     expectCurrency(*fmt, Locale::getJapan(),
1033                    1234.56, CharsToUnicodeString("1\\u202F235 JPY")); // Yen
1034 
1035     expectCurrency(*fmt, Locale("fr", "CH", ""),
1036                    1234.56, CharsToUnicodeString("1\\u202F234,56 CHF")); // no more 0.05 rounding here, see cldrbug 5548
1037 
1038     expectCurrency(*fmt, Locale::getUS(),
1039                    1234.56, CharsToUnicodeString("1\\u202F234,56 $US"));
1040 
1041     expectCurrency(*fmt, Locale::getFrance(),
1042                    1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC")); // Euro
1043 
1044     delete fmt;
1045 }
1046 
1047 // -------------------------------------
1048 
1049 /**
1050  * Do rudimentary testing of parsing.
1051  */
1052 void
TestParse(void)1053 NumberFormatTest::TestParse(void)
1054 {
1055     UErrorCode status = U_ZERO_ERROR;
1056     UnicodeString arg("0");
1057     DecimalFormat* format = new DecimalFormat("00", status);
1058     //try {
1059         Formattable n; format->parse(arg, n, status);
1060         logln((UnicodeString)"parse(" + arg + ") = " + n.getLong());
1061         if (n.getType() != Formattable::kLong ||
1062             n.getLong() != 0) errln((UnicodeString)"FAIL: Expected 0");
1063     delete format;
1064     if (U_FAILURE(status)) errcheckln(status, (UnicodeString)"FAIL: Status " + u_errorName(status));
1065     //}
1066     //catch(Exception e) {
1067     //    errln((UnicodeString)"Exception caught: " + e);
1068     //}
1069 }
1070 
1071 // -------------------------------------
1072 
1073 static const char *lenientAffixTestCases[] = {
1074         "(1)",
1075         "( 1)",
1076         "(1 )",
1077         "( 1 )"
1078 };
1079 
1080 static const char *lenientMinusTestCases[] = {
1081     "-5",
1082     "\\u22125",
1083     "\\u27965"
1084 };
1085 
1086 static const char *lenientCurrencyTestCases[] = {
1087         "$1,000",
1088         "$ 1,000",
1089         "$1000",
1090         "$ 1000",
1091         "$1 000.00",
1092         "$ 1 000.00",
1093         "$ 1\\u00A0000.00",
1094         "1000.00"
1095 };
1096 
1097 // changed from () to - per cldrbug 5674
1098 static const char *lenientNegativeCurrencyTestCases[] = {
1099         "-$1,000",
1100         "-$ 1,000",
1101         "-$1000",
1102         "-$ 1000",
1103         "-$1 000.00",
1104         "-$ 1 000.00",
1105         "- $ 1,000.00 ",
1106         "-$ 1\\u00A0000.00",
1107         "-1000.00"
1108 };
1109 
1110 static const char *lenientPercentTestCases[] = {
1111         "25%",
1112         " 25%",
1113         " 25 %",
1114     	"25 %",
1115 		"25\\u00A0%",
1116 		"25"
1117 };
1118 
1119 static const char *lenientNegativePercentTestCases[] = {
1120 		"-25%",
1121 		" -25%",
1122 		" - 25%",
1123 		"- 25 %",
1124 		" - 25 %",
1125 		"-25 %",
1126 		"-25\\u00A0%",
1127 		"-25",
1128 		"- 25"
1129 };
1130 
1131 static const char *strictFailureTestCases[] = {
1132 		" 1000",
1133 		"10,00",
1134 		"1,000,.0"
1135 };
1136 
1137 /**
1138  * Test lenient parsing.
1139  */
1140 void
TestLenientParse(void)1141 NumberFormatTest::TestLenientParse(void)
1142 {
1143     UErrorCode status = U_ZERO_ERROR;
1144     DecimalFormat *format = new DecimalFormat("(#,##0)", status);
1145     Formattable n;
1146 
1147     if (format == NULL || U_FAILURE(status)) {
1148         dataerrln("Unable to create DecimalFormat (#,##0) - %s", u_errorName(status));
1149     } else {
1150         format->setLenient(true);
1151         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientAffixTestCases); t += 1) {
1152         	UnicodeString testCase = ctou(lenientAffixTestCases[t]);
1153 
1154             format->parse(testCase, n, status);
1155             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1156 
1157             if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
1158             	n.getLong() != 1) {
1159             	dataerrln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t]
1160                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1161             	status = U_ZERO_ERROR;
1162             }
1163        }
1164        delete format;
1165     }
1166 
1167     Locale en_US("en_US");
1168     Locale sv_SE("sv_SE");
1169 
1170     NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, UNUM_DECIMAL, status);
1171 
1172     if (mFormat == NULL || U_FAILURE(status)) {
1173         dataerrln("Unable to create NumberFormat (sv_SE, UNUM_DECIMAL) - %s", u_errorName(status));
1174     } else {
1175         mFormat->setLenient(true);
1176         for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1177             UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1178 
1179             mFormat->parse(testCase, n, status);
1180             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1181 
1182             if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1183                 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1184                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1185                 status = U_ZERO_ERROR;
1186             }
1187         }
1188         delete mFormat;
1189     }
1190 
1191     mFormat = NumberFormat::createInstance(en_US, UNUM_DECIMAL, status);
1192 
1193     if (mFormat == NULL || U_FAILURE(status)) {
1194         dataerrln("Unable to create NumberFormat (en_US, UNUM_DECIMAL) - %s", u_errorName(status));
1195     } else {
1196         mFormat->setLenient(true);
1197         for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1198             UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1199 
1200             mFormat->parse(testCase, n, status);
1201             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1202 
1203             if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1204                 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1205                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1206                 status = U_ZERO_ERROR;
1207             }
1208         }
1209         delete mFormat;
1210     }
1211 
1212     NumberFormat *cFormat = NumberFormat::createInstance(en_US, UNUM_CURRENCY, status);
1213 
1214     if (cFormat == NULL || U_FAILURE(status)) {
1215         dataerrln("Unable to create NumberFormat (en_US, UNUM_CURRENCY) - %s", u_errorName(status));
1216     } else {
1217         cFormat->setLenient(true);
1218         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientCurrencyTestCases); t += 1) {
1219         	UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
1220 
1221             cFormat->parse(testCase, n, status);
1222             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1223 
1224             if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1225             	n.getLong() != 1000) {
1226             	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t]
1227                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1228             	status = U_ZERO_ERROR;
1229             }
1230         }
1231 
1232         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativeCurrencyTestCases); t += 1) {
1233         	UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
1234 
1235             cFormat->parse(testCase, n, status);
1236             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1237 
1238             if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1239             	n.getLong() != -1000) {
1240             	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t]
1241                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1242             	status = U_ZERO_ERROR;
1243             }
1244         }
1245 
1246         delete cFormat;
1247     }
1248 
1249     NumberFormat *pFormat = NumberFormat::createPercentInstance(en_US, status);
1250 
1251     if (pFormat == NULL || U_FAILURE(status)) {
1252         dataerrln("Unable to create NumberFormat::createPercentInstance (en_US) - %s", u_errorName(status));
1253     } else {
1254         pFormat->setLenient(true);
1255         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientPercentTestCases); t += 1) {
1256         	UnicodeString testCase = ctou(lenientPercentTestCases[t]);
1257 
1258         	pFormat->parse(testCase, n, status);
1259             logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1260 
1261             if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1262             	n.getDouble() != 0.25) {
1263             	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t]
1264                       + (UnicodeString) "\"; error code = " + u_errorName(status)
1265                       + "; got: " + n.getDouble(status));
1266             	status = U_ZERO_ERROR;
1267             }
1268         }
1269 
1270         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativePercentTestCases); t += 1) {
1271         	UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
1272 
1273         	pFormat->parse(testCase, n, status);
1274             logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1275 
1276             if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1277             	n.getDouble() != -0.25) {
1278             	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t]
1279                       + (UnicodeString) "\"; error code = " + u_errorName(status)
1280                       + "; got: " + n.getDouble(status));
1281             	status = U_ZERO_ERROR;
1282             }
1283         }
1284 
1285         delete pFormat;
1286     }
1287 
1288    // Test cases that should fail with a strict parse and pass with a
1289    // lenient parse.
1290    NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);
1291 
1292    if (nFormat == NULL || U_FAILURE(status)) {
1293        dataerrln("Unable to create NumberFormat (en_US) - %s", u_errorName(status));
1294    } else {
1295        // first, make sure that they fail with a strict parse
1296        for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1297 	       UnicodeString testCase = ctou(strictFailureTestCases[t]);
1298 
1299 	       nFormat->parse(testCase, n, status);
1300 	       logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1301 
1302 	       if (! U_FAILURE(status)) {
1303 		       errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t]
1304                      + (UnicodeString) "\"; error code = " + u_errorName(status));
1305 	       }
1306 
1307 	       status = U_ZERO_ERROR;
1308        }
1309 
1310        // then, make sure that they pass with a lenient parse
1311        nFormat->setLenient(true);
1312        for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1313 	       UnicodeString testCase = ctou(strictFailureTestCases[t]);
1314 
1315 	       nFormat->parse(testCase, n, status);
1316 	       logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1317 
1318 	       if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1319 	            	n.getLong() != 1000) {
1320 		       errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t]
1321                      + (UnicodeString) "\"; error code = " + u_errorName(status));
1322 		       status = U_ZERO_ERROR;
1323 	       }
1324        }
1325 
1326        delete nFormat;
1327    }
1328 }
1329 
1330 // -------------------------------------
1331 
1332 /**
1333  * Test proper rounding by the format method.
1334  */
1335 void
TestRounding487(void)1336 NumberFormatTest::TestRounding487(void)
1337 {
1338     UErrorCode status = U_ZERO_ERROR;
1339     NumberFormat *nf = NumberFormat::createInstance(status);
1340     if (U_FAILURE(status)) {
1341         dataerrln("Error calling NumberFormat::createInstance()");
1342         return;
1343     }
1344 
1345     roundingTest(*nf, 0.00159999, 4, "0.0016");
1346     roundingTest(*nf, 0.00995, 4, "0.01");
1347 
1348     roundingTest(*nf, 12.3995, 3, "12.4");
1349 
1350     roundingTest(*nf, 12.4999, 0, "12");
1351     roundingTest(*nf, - 19.5, 0, "-20");
1352     delete nf;
1353     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
1354 }
1355 
1356 /**
1357  * Test the functioning of the secondary grouping value.
1358  */
TestSecondaryGrouping(void)1359 void NumberFormatTest::TestSecondaryGrouping(void) {
1360     UErrorCode status = U_ZERO_ERROR;
1361     DecimalFormatSymbols US(Locale::getUS(), status);
1362     CHECK(status, "DecimalFormatSymbols ct");
1363 
1364     DecimalFormat f("#,##,###", US, status);
1365     CHECK(status, "DecimalFormat ct");
1366 
1367     expect2(f, (int32_t)123456789L, "12,34,56,789");
1368     expectPat(f, "#,##,##0");
1369     f.applyPattern("#,###", status);
1370     CHECK(status, "applyPattern");
1371 
1372     f.setSecondaryGroupingSize(4);
1373     expect2(f, (int32_t)123456789L, "12,3456,789");
1374     expectPat(f, "#,####,##0");
1375     NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
1376     CHECK_DATA(status, "createInstance(hi_IN)");
1377 
1378     UnicodeString out;
1379     int32_t l = (int32_t)1876543210L;
1380     g->format(l, out);
1381     delete g;
1382     // expect "1,87,65,43,210", but with Hindi digits
1383     //         01234567890123
1384     UBool ok = true;
1385     if (out.length() != 14) {
1386         ok = false;
1387     } else {
1388         for (int32_t i=0; i<out.length(); ++i) {
1389             UBool expectGroup = false;
1390             switch (i) {
1391             case 1:
1392             case 4:
1393             case 7:
1394             case 10:
1395                 expectGroup = true;
1396                 break;
1397             }
1398             // Later -- fix this to get the actual grouping
1399             // character from the resource bundle.
1400             UBool isGroup = (out.charAt(i) == 0x002C);
1401             if (isGroup != expectGroup) {
1402                 ok = false;
1403                 break;
1404             }
1405         }
1406     }
1407     if (!ok) {
1408         errln((UnicodeString)"FAIL  Expected " + l +
1409               " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
1410               escape(out) + "\"");
1411     } else {
1412         logln((UnicodeString)"Ok    " + l +
1413               " x hi_IN -> \"" +
1414               escape(out) + "\"");
1415     }
1416 }
1417 
TestWhiteSpaceParsing(void)1418 void NumberFormatTest::TestWhiteSpaceParsing(void) {
1419     UErrorCode ec = U_ZERO_ERROR;
1420     DecimalFormatSymbols US(Locale::getUS(), ec);
1421     DecimalFormat fmt("a  b#0c  ", US, ec);
1422     if (U_FAILURE(ec)) {
1423         errcheckln(ec, "FAIL: Constructor - %s", u_errorName(ec));
1424         return;
1425     }
1426     // From ICU 62, flexible whitespace needs lenient mode
1427     fmt.setLenient(true);
1428     int32_t n = 1234;
1429     expect(fmt, "a b1234c ", n);
1430     expect(fmt, "a   b1234c   ", n);
1431 }
1432 
1433 /**
1434  * Test currencies whose display name is a ChoiceFormat.
1435  */
TestComplexCurrency()1436 void NumberFormatTest::TestComplexCurrency() {
1437 
1438 //    UErrorCode ec = U_ZERO_ERROR;
1439 //    Locale loc("kn", "IN", "");
1440 //    NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
1441 //    if (U_SUCCESS(ec)) {
1442 //        expect2(*fmt, 1.0, CharsToUnicodeString("Re.\\u00A01.00"));
1443 //        Use .00392625 because that's 2^-8.  Any value less than 0.005 is fine.
1444 //        expect(*fmt, 1.00390625, CharsToUnicodeString("Re.\\u00A01.00")); // tricky
1445 //        expect2(*fmt, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
1446 //        expect2(*fmt, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
1447 //        expect2(*fmt, -1.0, CharsToUnicodeString("-Re.\\u00A01.00"));
1448 //        expect2(*fmt, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
1449 //    } else {
1450 //        errln("FAIL: getCurrencyInstance(kn_IN)");
1451 //    }
1452 //    delete fmt;
1453 
1454 }
1455 
1456 // -------------------------------------
1457 
1458 void
roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)1459 NumberFormatTest::roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)
1460 {
1461     nf.setMaximumFractionDigits(maxFractionDigits);
1462     UnicodeString out; nf.format(x, out);
1463     logln((UnicodeString)"" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
1464     if (!(out==expected)) errln((UnicodeString)"FAIL: Expected " + expected);
1465 }
1466 
1467 /**
1468  * Upgrade to alphaWorks
1469  */
TestExponent(void)1470 void NumberFormatTest::TestExponent(void) {
1471     UErrorCode status = U_ZERO_ERROR;
1472     DecimalFormatSymbols US(Locale::getUS(), status);
1473     CHECK(status, "DecimalFormatSymbols constructor");
1474     DecimalFormat fmt1(UnicodeString("0.###E0"), US, status);
1475     CHECK(status, "DecimalFormat(0.###E0)");
1476     DecimalFormat fmt2(UnicodeString("0.###E+0"), US, status);
1477     CHECK(status, "DecimalFormat(0.###E+0)");
1478     int32_t n = 1234;
1479     expect2(fmt1, n, "1.234E3");
1480     expect2(fmt2, n, "1.234E+3");
1481     expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
1482 }
1483 
1484 /**
1485  * Upgrade to alphaWorks
1486  */
TestScientific(void)1487 void NumberFormatTest::TestScientific(void) {
1488     UErrorCode status = U_ZERO_ERROR;
1489     DecimalFormatSymbols US(Locale::getUS(), status);
1490     CHECK(status, "DecimalFormatSymbols constructor");
1491 
1492     // Test pattern round-trip
1493     const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
1494                           "0.###E0;[0.###E0]" };
1495     int32_t PAT_length = UPRV_LENGTHOF(PAT);
1496     int32_t DIGITS[] = {
1497         // min int, max int, min frac, max frac
1498         1, 1, 0, 0, // "#E0"
1499         1, 1, 0, 4, // "0.####E0"
1500         2, 2, 3, 3, // "00.000E00"
1501         1, 3, 0, 4, // "##0.####E000"
1502         1, 1, 0, 3, // "0.###E0;[0.###E0]"
1503     };
1504     for (int32_t i=0; i<PAT_length; ++i) {
1505         UnicodeString pat(PAT[i]);
1506         DecimalFormat df(pat, US, status);
1507         CHECK(status, "DecimalFormat constructor");
1508         UnicodeString pat2;
1509         df.toPattern(pat2);
1510         if (pat == pat2) {
1511             logln(UnicodeString("Ok   Pattern rt \"") +
1512                   pat + "\" -> \"" +
1513                   pat2 + "\"");
1514         } else {
1515             errln(UnicodeString("FAIL Pattern rt \"") +
1516                   pat + "\" -> \"" +
1517                   pat2 + "\"");
1518         }
1519         // Make sure digit counts match what we expect
1520         if (df.getMinimumIntegerDigits() != DIGITS[4*i] ||
1521             df.getMaximumIntegerDigits() != DIGITS[4*i+1] ||
1522             df.getMinimumFractionDigits() != DIGITS[4*i+2] ||
1523             df.getMaximumFractionDigits() != DIGITS[4*i+3]) {
1524             errln(UnicodeString("FAIL \"" + pat +
1525                                 "\" min/max int; min/max frac = ") +
1526                   df.getMinimumIntegerDigits() + "/" +
1527                   df.getMaximumIntegerDigits() + ";" +
1528                   df.getMinimumFractionDigits() + "/" +
1529                   df.getMaximumFractionDigits() + ", expect " +
1530                   DIGITS[4*i] + "/" +
1531                   DIGITS[4*i+1] + ";" +
1532                   DIGITS[4*i+2] + "/" +
1533                   DIGITS[4*i+3]);
1534         }
1535     }
1536 
1537 
1538     // Test the constructor for default locale. We have to
1539     // manually set the default locale, as there is no
1540     // guarantee that the default locale has the same
1541     // scientific format.
1542     Locale def = Locale::getDefault();
1543     Locale::setDefault(Locale::getUS(), status);
1544     expect2(NumberFormat::createScientificInstance(status),
1545            12345.678901,
1546            "1.2345678901E4", status);
1547     Locale::setDefault(def, status);
1548 
1549     expect2(new DecimalFormat("#E0", US, status),
1550            12345.0,
1551            "1.2345E4", status);
1552     expect(new DecimalFormat("0E0", US, status),
1553            12345.0,
1554            "1E4", status);
1555     expect2(NumberFormat::createScientificInstance(Locale::getUS(), status),
1556            12345.678901,
1557            "1.2345678901E4", status);
1558     expect(new DecimalFormat("##0.###E0", US, status),
1559            12345.0,
1560            "12.34E3", status);
1561     expect(new DecimalFormat("##0.###E0", US, status),
1562            12345.00001,
1563            "12.35E3", status);
1564     expect2(new DecimalFormat("##0.####E0", US, status),
1565            (int32_t) 12345,
1566            "12.345E3", status);
1567     expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status),
1568            12345.678901,
1569            "1,2345678901E4", status);
1570     expect(new DecimalFormat("##0.####E0", US, status),
1571            789.12345e-9,
1572            "789.12E-9", status);
1573     expect2(new DecimalFormat("##0.####E0", US, status),
1574            780.e-9,
1575            "780E-9", status);
1576     expect(new DecimalFormat(".###E0", US, status),
1577            45678.0,
1578            ".457E5", status);
1579     expect2(new DecimalFormat(".###E0", US, status),
1580            (int32_t) 0,
1581            ".0E0", status);
1582     /*
1583     expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
1584                                  new DecimalFormat("##E0", US),
1585                                  new DecimalFormat("####E0", US),
1586                                  new DecimalFormat("0E0", US),
1587                                  new DecimalFormat("00E0", US),
1588                                  new DecimalFormat("000E0", US),
1589                                },
1590            new Long(45678000),
1591            new String[] { "4.5678E7",
1592                           "45.678E6",
1593                           "4567.8E4",
1594                           "5E7",
1595                           "46E6",
1596                           "457E5",
1597                         }
1598            );
1599     !
1600     ! Unroll this test into individual tests below...
1601     !
1602     */
1603     expect2(new DecimalFormat("#E0", US, status),
1604            (int32_t) 45678000, "4.5678E7", status);
1605     expect2(new DecimalFormat("##E0", US, status),
1606            (int32_t) 45678000, "45.678E6", status);
1607     expect2(new DecimalFormat("####E0", US, status),
1608            (int32_t) 45678000, "4567.8E4", status);
1609     expect(new DecimalFormat("0E0", US, status),
1610            (int32_t) 45678000, "5E7", status);
1611     expect(new DecimalFormat("00E0", US, status),
1612            (int32_t) 45678000, "46E6", status);
1613     expect(new DecimalFormat("000E0", US, status),
1614            (int32_t) 45678000, "457E5", status);
1615     /*
1616     expect(new DecimalFormat("###E0", US, status),
1617            new Object[] { new Double(0.0000123), "12.3E-6",
1618                           new Double(0.000123), "123E-6",
1619                           new Double(0.00123), "1.23E-3",
1620                           new Double(0.0123), "12.3E-3",
1621                           new Double(0.123), "123E-3",
1622                           new Double(1.23), "1.23E0",
1623                           new Double(12.3), "12.3E0",
1624                           new Double(123), "123E0",
1625                           new Double(1230), "1.23E3",
1626                          });
1627     !
1628     ! Unroll this test into individual tests below...
1629     !
1630     */
1631     expect2(new DecimalFormat("###E0", US, status),
1632            0.0000123, "12.3E-6", status);
1633     expect2(new DecimalFormat("###E0", US, status),
1634            0.000123, "123E-6", status);
1635     expect2(new DecimalFormat("###E0", US, status),
1636            0.00123, "1.23E-3", status);
1637     expect2(new DecimalFormat("###E0", US, status),
1638            0.0123, "12.3E-3", status);
1639     expect2(new DecimalFormat("###E0", US, status),
1640            0.123, "123E-3", status);
1641     expect2(new DecimalFormat("###E0", US, status),
1642            1.23, "1.23E0", status);
1643     expect2(new DecimalFormat("###E0", US, status),
1644            12.3, "12.3E0", status);
1645     expect2(new DecimalFormat("###E0", US, status),
1646            123.0, "123E0", status);
1647     expect2(new DecimalFormat("###E0", US, status),
1648            1230.0, "1.23E3", status);
1649     /*
1650     expect(new DecimalFormat("0.#E+00", US, status),
1651            new Object[] { new Double(0.00012), "1.2E-04",
1652                           new Long(12000),     "1.2E+04",
1653                          });
1654     !
1655     ! Unroll this test into individual tests below...
1656     !
1657     */
1658     expect2(new DecimalFormat("0.#E+00", US, status),
1659            0.00012, "1.2E-04", status);
1660     expect2(new DecimalFormat("0.#E+00", US, status),
1661            (int32_t) 12000, "1.2E+04", status);
1662 }
1663 
1664 /**
1665  * Upgrade to alphaWorks
1666  */
TestPad(void)1667 void NumberFormatTest::TestPad(void) {
1668     UErrorCode status = U_ZERO_ERROR;
1669     DecimalFormatSymbols US(Locale::getUS(), status);
1670     CHECK(status, "DecimalFormatSymbols constructor");
1671 
1672     expect2(new DecimalFormat("*^##.##", US, status),
1673            int32_t(0), "^^^^0", status);
1674     expect2(new DecimalFormat("*^##.##", US, status),
1675            -1.3, "^-1.3", status);
1676     expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1677            int32_t(0), "0.0E0______ g-m/s^2", status);
1678     expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1679            1.0/3, "333.333E-3_ g-m/s^2", status);
1680     expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1681            int32_t(0), "0.0______ g-m/s^2", status);
1682     expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1683            1.0/3, "0.33333__ g-m/s^2", status);
1684 
1685     // Test padding before a sign
1686     const char *formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1687     expect2(new DecimalFormat(formatStr, US, status),
1688            int32_t(-10),  "xxxxxxxxxx(10.0)", status);
1689     expect2(new DecimalFormat(formatStr, US, status),
1690            int32_t(-1000),"xxxxxxx(1,000.0)", status);
1691     expect2(new DecimalFormat(formatStr, US, status),
1692            int32_t(-1000000),"xxx(1,000,000.0)", status);
1693     expect2(new DecimalFormat(formatStr, US, status),
1694            -100.37,       "xxxxxxxx(100.37)", status);
1695     expect2(new DecimalFormat(formatStr, US, status),
1696            -10456.37,     "xxxxx(10,456.37)", status);
1697     expect2(new DecimalFormat(formatStr, US, status),
1698            -1120456.37,   "xx(1,120,456.37)", status);
1699     expect2(new DecimalFormat(formatStr, US, status),
1700            -112045600.37, "(112,045,600.37)", status);
1701     expect2(new DecimalFormat(formatStr, US, status),
1702            -1252045600.37,"(1,252,045,600.37)", status);
1703 
1704     expect2(new DecimalFormat(formatStr, US, status),
1705            int32_t(10),  "xxxxxxxxxxxx10.0", status);
1706     expect2(new DecimalFormat(formatStr, US, status),
1707            int32_t(1000),"xxxxxxxxx1,000.0", status);
1708     expect2(new DecimalFormat(formatStr, US, status),
1709            int32_t(1000000),"xxxxx1,000,000.0", status);
1710     expect2(new DecimalFormat(formatStr, US, status),
1711            100.37,       "xxxxxxxxxx100.37", status);
1712     expect2(new DecimalFormat(formatStr, US, status),
1713            10456.37,     "xxxxxxx10,456.37", status);
1714     expect2(new DecimalFormat(formatStr, US, status),
1715            1120456.37,   "xxxx1,120,456.37", status);
1716     expect2(new DecimalFormat(formatStr, US, status),
1717            112045600.37, "xx112,045,600.37", status);
1718     expect2(new DecimalFormat(formatStr, US, status),
1719            10252045600.37,"10,252,045,600.37", status);
1720 
1721 
1722     // Test padding between a sign and a number
1723     const char *formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1724     expect2(new DecimalFormat(formatStr2, US, status),
1725            int32_t(-10),  "(10.0xxxxxxxxxx)", status);
1726     expect2(new DecimalFormat(formatStr2, US, status),
1727            int32_t(-1000),"(1,000.0xxxxxxx)", status);
1728     expect2(new DecimalFormat(formatStr2, US, status),
1729            int32_t(-1000000),"(1,000,000.0xxx)", status);
1730     expect2(new DecimalFormat(formatStr2, US, status),
1731            -100.37,       "(100.37xxxxxxxx)", status);
1732     expect2(new DecimalFormat(formatStr2, US, status),
1733            -10456.37,     "(10,456.37xxxxx)", status);
1734     expect2(new DecimalFormat(formatStr2, US, status),
1735            -1120456.37,   "(1,120,456.37xx)", status);
1736     expect2(new DecimalFormat(formatStr2, US, status),
1737            -112045600.37, "(112,045,600.37)", status);
1738     expect2(new DecimalFormat(formatStr2, US, status),
1739            -1252045600.37,"(1,252,045,600.37)", status);
1740 
1741     expect2(new DecimalFormat(formatStr2, US, status),
1742            int32_t(10),  "10.0xxxxxxxxxxxx", status);
1743     expect2(new DecimalFormat(formatStr2, US, status),
1744            int32_t(1000),"1,000.0xxxxxxxxx", status);
1745     expect2(new DecimalFormat(formatStr2, US, status),
1746            int32_t(1000000),"1,000,000.0xxxxx", status);
1747     expect2(new DecimalFormat(formatStr2, US, status),
1748            100.37,       "100.37xxxxxxxxxx", status);
1749     expect2(new DecimalFormat(formatStr2, US, status),
1750            10456.37,     "10,456.37xxxxxxx", status);
1751     expect2(new DecimalFormat(formatStr2, US, status),
1752            1120456.37,   "1,120,456.37xxxx", status);
1753     expect2(new DecimalFormat(formatStr2, US, status),
1754            112045600.37, "112,045,600.37xx", status);
1755     expect2(new DecimalFormat(formatStr2, US, status),
1756            10252045600.37,"10,252,045,600.37", status);
1757 
1758     //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1759     DecimalFormat fmt("#", US, status);
1760     CHECK(status, "DecimalFormat constructor");
1761     UnicodeString padString("P");
1762     fmt.setPadCharacter(padString);
1763     expectPad(fmt, "*P##.##", DecimalFormat::kPadBeforePrefix, 5, padString);
1764     fmt.setPadCharacter((UnicodeString)"^");
1765     expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, (UnicodeString)"^");
1766     //commented until implementation is complete
1767   /*  fmt.setPadCharacter((UnicodeString)"^^^");
1768     expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1769     padString.remove();
1770     padString.append((UChar)0x0061);
1771     padString.append((UChar)0x0302);
1772     fmt.setPadCharacter(padString);
1773     UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1774     UnicodeString pattern(patternChars);
1775     expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1776  */
1777 
1778 }
1779 
1780 /**
1781  * Upgrade to alphaWorks
1782  */
TestPatterns2(void)1783 void NumberFormatTest::TestPatterns2(void) {
1784     UErrorCode status = U_ZERO_ERROR;
1785     DecimalFormatSymbols US(Locale::getUS(), status);
1786     CHECK(status, "DecimalFormatSymbols constructor");
1787 
1788     DecimalFormat fmt("#", US, status);
1789     CHECK(status, "DecimalFormat constructor");
1790 
1791     UChar hat = 0x005E; /*^*/
1792 
1793     expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, hat);
1794     expectPad(fmt, "$*^#", DecimalFormat::kPadAfterPrefix, 2, hat);
1795     expectPad(fmt, "#*^", DecimalFormat::kPadBeforeSuffix, 1, hat);
1796     expectPad(fmt, "#$*^", DecimalFormat::kPadAfterSuffix, 2, hat);
1797     expectPad(fmt, "$*^$#", ILLEGAL);
1798     expectPad(fmt, "#$*^$", ILLEGAL);
1799     expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix,
1800               12, (UChar)0x0078 /*x*/);
1801     expectPad(fmt, "''#0*x", DecimalFormat::kPadBeforeSuffix,
1802               3, (UChar)0x0078 /*x*/);
1803     expectPad(fmt, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix,
1804               10, (UChar)0x0061 /*a*/);
1805 
1806     fmt.applyPattern("AA#,##0.00ZZ", status);
1807     CHECK(status, "applyPattern");
1808     fmt.setPadCharacter(hat);
1809 
1810     fmt.setFormatWidth(10);
1811 
1812     fmt.setPadPosition(DecimalFormat::kPadBeforePrefix);
1813     expectPat(fmt, "*^AA#,##0.00ZZ");
1814 
1815     fmt.setPadPosition(DecimalFormat::kPadBeforeSuffix);
1816     expectPat(fmt, "AA#,##0.00*^ZZ");
1817 
1818     fmt.setPadPosition(DecimalFormat::kPadAfterSuffix);
1819     expectPat(fmt, "AA#,##0.00ZZ*^");
1820 
1821     //            12  3456789012
1822     UnicodeString exp("AA*^#,##0.00ZZ", "");
1823     fmt.setFormatWidth(12);
1824     fmt.setPadPosition(DecimalFormat::kPadAfterPrefix);
1825     expectPat(fmt, exp);
1826 
1827     fmt.setFormatWidth(13);
1828     //              12  34567890123
1829     expectPat(fmt, "AA*^##,##0.00ZZ");
1830 
1831     fmt.setFormatWidth(14);
1832     //              12  345678901234
1833     expectPat(fmt, "AA*^###,##0.00ZZ");
1834 
1835     fmt.setFormatWidth(15);
1836     //              12  3456789012345
1837     expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1838 
1839     fmt.setFormatWidth(16);
1840     //              12  34567890123456
1841     expectPat(fmt, "AA*^#####,##0.00ZZ");
1842 }
1843 
TestSurrogateSupport(void)1844 void NumberFormatTest::TestSurrogateSupport(void) {
1845     UErrorCode status = U_ZERO_ERROR;
1846     DecimalFormatSymbols custom(Locale::getUS(), status);
1847     CHECK(status, "DecimalFormatSymbols constructor");
1848 
1849     custom.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, "decimal");
1850     custom.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, "plus");
1851     custom.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, " minus ");
1852     custom.setSymbol(DecimalFormatSymbols::kExponentialSymbol, "exponent");
1853 
1854     UnicodeString patternStr("*\\U00010000##.##", "");
1855     patternStr = patternStr.unescape();
1856     UnicodeString expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1857     expStr = expStr.unescape();
1858     expect2(new DecimalFormat(patternStr, custom, status),
1859            int32_t(0), expStr, status);
1860 
1861     status = U_ZERO_ERROR;
1862     expect2(new DecimalFormat("*^##.##", custom, status),
1863            int32_t(0), "^^^^0", status);
1864     status = U_ZERO_ERROR;
1865     expect2(new DecimalFormat("##.##", custom, status),
1866            -1.3, " minus 1decimal3", status);
1867     status = U_ZERO_ERROR;
1868     expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1869            int32_t(0), "0decimal0exponent0 g-m/s^2", status);
1870     status = U_ZERO_ERROR;
1871     expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1872            1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
1873     status = U_ZERO_ERROR;
1874     expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1875            int32_t(0), "0decimal0 g-m/s^2", status);
1876     status = U_ZERO_ERROR;
1877     expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1878            1.0/3, "0decimal33333 g-m/s^2", status);
1879 
1880     UnicodeString zero((UChar32)0x10000);
1881     UnicodeString one((UChar32)0x10001);
1882     UnicodeString two((UChar32)0x10002);
1883     UnicodeString five((UChar32)0x10005);
1884     custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
1885     custom.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, one);
1886     custom.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, two);
1887     custom.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, five);
1888     expStr = UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1889     expStr = expStr.unescape();
1890     status = U_ZERO_ERROR;
1891     expect2(new DecimalFormat("##0.000", custom, status),
1892            1.25, expStr, status);
1893 
1894     custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
1895     custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
1896     custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
1897     patternStr = UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
1898     patternStr = patternStr.unescape();
1899     expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1900     status = U_ZERO_ERROR;
1901     expect2(new DecimalFormat(patternStr, custom, status),
1902            int32_t(-20), expStr, status);
1903 
1904     custom.setSymbol(DecimalFormatSymbols::kPercentSymbol, "percent");
1905     patternStr = "'You''ve lost ' -0.00 %' of your money today'";
1906     patternStr = patternStr.unescape();
1907     expStr = UnicodeString(" minus You've lost   minus 2000decimal00 percent of your money today", "");
1908     status = U_ZERO_ERROR;
1909     expect2(new DecimalFormat(patternStr, custom, status),
1910            int32_t(-20), expStr, status);
1911 }
1912 
TestCurrencyPatterns(void)1913 void NumberFormatTest::TestCurrencyPatterns(void) {
1914     int32_t i, locCount;
1915     const Locale* locs = NumberFormat::getAvailableLocales(locCount);
1916     for (i=0; i<locCount; ++i) {
1917         UErrorCode ec = U_ZERO_ERROR;
1918         NumberFormat* nf = NumberFormat::createCurrencyInstance(locs[i], ec);
1919         if (U_FAILURE(ec)) {
1920             errln("FAIL: Can't create NumberFormat(%s) - %s", locs[i].getName(), u_errorName(ec));
1921         } else {
1922             // Make sure currency formats do not have a variable number
1923             // of fraction digits
1924             int32_t min = nf->getMinimumFractionDigits();
1925             int32_t max = nf->getMaximumFractionDigits();
1926             if (min != max) {
1927                 UnicodeString a, b;
1928                 nf->format(1.0, a);
1929                 nf->format(1.125, b);
1930                 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1931                       " min fraction digits != max fraction digits; "
1932                       "x 1.0 => " + escape(a) +
1933                       "; x 1.125 => " + escape(b));
1934             }
1935 
1936             // Make sure EURO currency formats have exactly 2 fraction digits
1937             DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
1938             if (df != NULL) {
1939                 if (u_strcmp(EUR, df->getCurrency()) == 0) {
1940                     if (min != 2 || max != 2) {
1941                         UnicodeString a;
1942                         nf->format(1.0, a);
1943                         errln((UnicodeString)"FAIL: " + locs[i].getName() +
1944                               " is a EURO format but it does not have 2 fraction digits; "
1945                               "x 1.0 => " +
1946                               escape(a));
1947                     }
1948                 }
1949             }
1950         }
1951         delete nf;
1952     }
1953 }
1954 
TestRegCurrency(void)1955 void NumberFormatTest::TestRegCurrency(void) {
1956 #if !UCONFIG_NO_SERVICE
1957     UErrorCode status = U_ZERO_ERROR;
1958     UChar USD[4];
1959     ucurr_forLocale("en_US", USD, 4, &status);
1960     UChar YEN[4];
1961     ucurr_forLocale("ja_JP", YEN, 4, &status);
1962     UChar TMP[4];
1963 
1964     if(U_FAILURE(status)) {
1965         errcheckln(status, "Unable to get currency for locale, error %s", u_errorName(status));
1966         return;
1967     }
1968 
1969     UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
1970 
1971     ucurr_forLocale("en_US", TMP, 4, &status);
1972     if (u_strcmp(YEN, TMP) != 0) {
1973         errln("FAIL: didn't return YEN registered for en_US");
1974     }
1975 
1976     int32_t fallbackLen = ucurr_forLocale("en_XX_BAR", TMP, 4, &status);
1977     if (fallbackLen) {
1978         errln("FAIL: tried to fallback en_XX_BAR");
1979     }
1980     status = U_ZERO_ERROR; // reset
1981 
1982     if (!ucurr_unregister(enkey, &status)) {
1983         errln("FAIL: couldn't unregister enkey");
1984     }
1985 
1986     ucurr_forLocale("en_US", TMP, 4, &status);
1987     if (u_strcmp(USD, TMP) != 0) {
1988         errln("FAIL: didn't return USD for en_US after unregister of en_US");
1989     }
1990     status = U_ZERO_ERROR; // reset
1991 
1992     ucurr_forLocale("en_US_BLAH", TMP, 4, &status);
1993     if (u_strcmp(USD, TMP) != 0) {
1994         errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1995     }
1996     status = U_ZERO_ERROR; // reset
1997 #endif
1998 }
1999 
TestCurrencyNames(void)2000 void NumberFormatTest::TestCurrencyNames(void) {
2001     // Do a basic check of getName()
2002     // USD { "US$", "US Dollar"            } // 04/04/1792-
2003     UErrorCode ec = U_ZERO_ERROR;
2004     static const UChar USD[] = {0x55, 0x53, 0x44, 0}; /*USD*/
2005     static const UChar USX[] = {0x55, 0x53, 0x58, 0}; /*USX*/
2006     static const UChar CAD[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
2007     static const UChar ITL[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
2008     UBool isChoiceFormat;
2009     int32_t len;
2010     const UBool possibleDataError = true;
2011     // Warning: HARD-CODED LOCALE DATA in this test.  If it fails, CHECK
2012     // THE LOCALE DATA before diving into the code.
2013     assertEquals("USD.getName(SYMBOL_NAME, en)",
2014                  UnicodeString("$"),
2015                  UnicodeString(ucurr_getName(USD, "en",
2016                                              UCURR_SYMBOL_NAME,
2017                                              &isChoiceFormat, &len, &ec)),
2018                                              possibleDataError);
2019     assertEquals("USD.getName(NARROW_SYMBOL_NAME, en)",
2020                  UnicodeString("$"),
2021                  UnicodeString(ucurr_getName(USD, "en",
2022                                              UCURR_NARROW_SYMBOL_NAME,
2023                                              &isChoiceFormat, &len, &ec)),
2024                                              possibleDataError);
2025     assertEquals("USD.getName(LONG_NAME, en)",
2026                  UnicodeString("US Dollar"),
2027                  UnicodeString(ucurr_getName(USD, "en",
2028                                              UCURR_LONG_NAME,
2029                                              &isChoiceFormat, &len, &ec)),
2030                                              possibleDataError);
2031     assertEquals("CAD.getName(SYMBOL_NAME, en)",
2032                  UnicodeString("CA$"),
2033                  UnicodeString(ucurr_getName(CAD, "en",
2034                                              UCURR_SYMBOL_NAME,
2035                                              &isChoiceFormat, &len, &ec)),
2036                                              possibleDataError);
2037     assertEquals("CAD.getName(NARROW_SYMBOL_NAME, en)",
2038                  UnicodeString("$"),
2039                  UnicodeString(ucurr_getName(CAD, "en",
2040                                              UCURR_NARROW_SYMBOL_NAME,
2041                                              &isChoiceFormat, &len, &ec)),
2042                                              possibleDataError);
2043     assertEquals("CAD.getName(SYMBOL_NAME, en_CA)",
2044                  UnicodeString("$"),
2045                  UnicodeString(ucurr_getName(CAD, "en_CA",
2046                                              UCURR_SYMBOL_NAME,
2047                                              &isChoiceFormat, &len, &ec)),
2048                                              possibleDataError);
2049     assertEquals("USD.getName(SYMBOL_NAME, en_CA)",
2050                  UnicodeString("US$"),
2051                  UnicodeString(ucurr_getName(USD, "en_CA",
2052                                              UCURR_SYMBOL_NAME,
2053                                              &isChoiceFormat, &len, &ec)),
2054                                              possibleDataError);
2055     assertEquals("USD.getName(NARROW_SYMBOL_NAME, en_CA)",
2056                  UnicodeString("US$"),
2057                  UnicodeString(ucurr_getName(USD, "en_CA",
2058                                              UCURR_NARROW_SYMBOL_NAME,
2059                                              &isChoiceFormat, &len, &ec)),
2060                                              possibleDataError);
2061     assertEquals("USD.getName(SYMBOL_NAME) in en_NZ",
2062                  UnicodeString("US$"),
2063                  UnicodeString(ucurr_getName(USD, "en_NZ",
2064                                              UCURR_SYMBOL_NAME,
2065                                              &isChoiceFormat, &len, &ec)),
2066                                              possibleDataError);
2067     assertEquals("CAD.getName(SYMBOL_NAME)",
2068                  UnicodeString("CA$"),
2069                  UnicodeString(ucurr_getName(CAD, "en_NZ",
2070                                              UCURR_SYMBOL_NAME,
2071                                              &isChoiceFormat, &len, &ec)),
2072                                              possibleDataError);
2073     assertEquals("USX.getName(SYMBOL_NAME)",
2074                  UnicodeString("USX"),
2075                  UnicodeString(ucurr_getName(USX, "en_US",
2076                                              UCURR_SYMBOL_NAME,
2077                                              &isChoiceFormat, &len, &ec)),
2078                                              possibleDataError);
2079     assertEquals("USX.getName(NARROW_SYMBOL_NAME)",
2080                  UnicodeString("USX"),
2081                  UnicodeString(ucurr_getName(USX, "en_US",
2082                                              UCURR_NARROW_SYMBOL_NAME,
2083                                              &isChoiceFormat, &len, &ec)),
2084                                              possibleDataError);
2085     assertEquals("USX.getName(LONG_NAME)",
2086                  UnicodeString("USX"),
2087                  UnicodeString(ucurr_getName(USX, "en_US",
2088                                              UCURR_LONG_NAME,
2089                                              &isChoiceFormat, &len, &ec)),
2090                                              possibleDataError);
2091     assertSuccess("ucurr_getName", ec);
2092 
2093     ec = U_ZERO_ERROR;
2094 
2095     // Test that a default or fallback warning is being returned. JB 4239.
2096     ucurr_getName(CAD, "es_ES", UCURR_LONG_NAME, &isChoiceFormat,
2097                             &len, &ec);
2098     assertTrue("ucurr_getName (es_ES fallback)",
2099                     U_USING_FALLBACK_WARNING == ec, true, possibleDataError);
2100 
2101     ucurr_getName(CAD, "zh_TW", UCURR_LONG_NAME, &isChoiceFormat,
2102                             &len, &ec);
2103     assertTrue("ucurr_getName (zh_TW fallback)",
2104                     U_USING_FALLBACK_WARNING == ec, true, possibleDataError);
2105 
2106     ucurr_getName(CAD, "en_US", UCURR_LONG_NAME, &isChoiceFormat,
2107                             &len, &ec);
2108     assertTrue("ucurr_getName (en_US default)",
2109                     U_USING_DEFAULT_WARNING == ec || U_USING_FALLBACK_WARNING == ec, true);
2110 
2111     ucurr_getName(CAD, "ti", UCURR_LONG_NAME, &isChoiceFormat,
2112                             &len, &ec);
2113     assertTrue("ucurr_getName (ti default)",
2114                     U_USING_DEFAULT_WARNING == ec, true);
2115 
2116     // Test that a default warning is being returned when falling back to root. JB 4536.
2117     ucurr_getName(ITL, "cy", UCURR_LONG_NAME, &isChoiceFormat,
2118                             &len, &ec);
2119     assertTrue("ucurr_getName (cy default to root)",
2120                     U_USING_DEFAULT_WARNING == ec, true);
2121 
2122     // TODO add more tests later
2123 }
2124 
TestCurrencyVariants()2125 void NumberFormatTest::TestCurrencyVariants(){
2126     IcuTestErrorCode status(*this, "TestCurrencyVariants");
2127 
2128     struct TestCase {
2129         const char* locale;
2130         const char16_t* isoCode;
2131         const char16_t* expectedShort;
2132         const char16_t* expectedNarrow;
2133         const char16_t* expectedFormal;
2134         const char16_t* expectedVariant;
2135         UErrorCode expectedNarrowError;
2136     } cases[] = {
2137         {"en-US", u"CAD", u"CA$", u"$", u"CA$", u"CA$", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2138         {"en-US", u"CDF", u"CDF", u"CDF", u"CDF", u"CDF", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2139         {"sw-CD", u"CDF", u"FC", u"FC", u"FC", u"FC", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2140         {"en-US", u"GEL", u"GEL", u"₾", u"GEL", u"GEL", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2141         {"ka-GE", u"GEL", u"₾", u"₾", u"₾", u"₾", U_USING_FALLBACK_WARNING}, // narrow: fallback to ka
2142         {"ka", u"GEL", u"₾", u"₾", u"₾", u"₾", U_ZERO_ERROR}, // no fallback on narrow
2143         {"zh-TW", u"TWD", u"$", u"$", u"NT$", u"$", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2144         {"ccp", u"TRY", u"TRY", u"₺", u"TRY", u"TL", U_ZERO_ERROR}, // no fallback on variant
2145     };
2146     for (const auto& cas : cases) {
2147         status.setScope(cas.isoCode);
2148         UBool choiceFormatIgnored;
2149         int32_t lengthIgnored;
2150         const UChar* actualShort = ucurr_getName(
2151             cas.isoCode,
2152             cas.locale,
2153             UCURR_SYMBOL_NAME,
2154             &choiceFormatIgnored,
2155             &lengthIgnored,
2156             status);
2157         const UChar* actualFormal = ucurr_getName(
2158             cas.isoCode,
2159             cas.locale,
2160             UCURR_FORMAL_SYMBOL_NAME,
2161             &choiceFormatIgnored,
2162             &lengthIgnored,
2163             status);
2164         const UChar* actualVarant = ucurr_getName(
2165             cas.isoCode,
2166             cas.locale,
2167             UCURR_VARIANT_SYMBOL_NAME,
2168             &choiceFormatIgnored,
2169             &lengthIgnored,
2170             status);
2171         status.errIfFailureAndReset();
2172         const UChar* actualNarrow = ucurr_getName(
2173             cas.isoCode,
2174             cas.locale,
2175             UCURR_NARROW_SYMBOL_NAME,
2176             &choiceFormatIgnored,
2177             &lengthIgnored,
2178             status);
2179         status.expectErrorAndReset(cas.expectedNarrowError);
2180         assertEquals(UnicodeString("Short symbol: ") + cas.locale + u": " + cas.isoCode,
2181                 cas.expectedShort, actualShort);
2182         assertEquals(UnicodeString("Narrow symbol: ") + cas.locale + u": " + cas.isoCode,
2183                 cas.expectedNarrow, actualNarrow);
2184         assertEquals(UnicodeString("Formal symbol: ") + cas.locale + u": " + cas.isoCode,
2185                 cas.expectedFormal, actualFormal);
2186         assertEquals(UnicodeString("Variant symbol: ") + cas.locale + u": " + cas.isoCode,
2187                 cas.expectedVariant, actualVarant);
2188     }
2189 }
2190 
TestCurrencyUnit(void)2191 void NumberFormatTest::TestCurrencyUnit(void){
2192     UErrorCode ec = U_ZERO_ERROR;
2193     static const UChar USD[]  = u"USD";
2194     static const char USD8[]  =  "USD";
2195     static const UChar BAD[]  = u"???";
2196     static const UChar BAD2[] = u"??A";
2197     static const UChar XXX[]  = u"XXX";
2198     static const char XXX8[]  =  "XXX";
2199     static const UChar XYZ[]  = u"XYZ";
2200     static const char XYZ8[]  =  "XYZ";
2201     static const UChar INV[]  = u"{$%";
2202     static const char INV8[]  =  "{$%";
2203     static const UChar ZZZ[]  = u"zz";
2204     static const char ZZZ8[]  = "zz";
2205     static const UChar JPY[]  = u"JPY";
2206     static const char JPY8[]  =  "JPY";
2207     static const UChar jpy[]  = u"jpy";
2208     static const char jpy8[]  =  "jpy";
2209 
2210     UChar* EUR = (UChar*) malloc(6);
2211     EUR[0] = u'E';
2212     EUR[1] = u'U';
2213     EUR[2] = u'R';
2214     char* EUR8 = (char*) malloc(3);
2215     EUR8[0] = 'E';
2216     EUR8[1] = 'U';
2217     EUR8[2] = 'R';
2218 
2219     CurrencyUnit cu(USD, ec);
2220     assertSuccess("CurrencyUnit", ec);
2221     assertEquals("getISOCurrency()", USD, cu.getISOCurrency());
2222     assertEquals("getSubtype()", USD8, cu.getSubtype());
2223 
2224     // Test XYZ, a valid but non-standard currency.
2225     // Note: Country code XY is private-use, so XYZ should remain unallocated.
2226     CurrencyUnit extended(XYZ, ec);
2227     assertSuccess("non-standard", ec);
2228     assertEquals("non-standard", XYZ, extended.getISOCurrency());
2229     assertEquals("non-standard", XYZ8, extended.getSubtype());
2230 
2231     CurrencyUnit inv(INV, ec);
2232     assertEquals("non-invariant", U_INVARIANT_CONVERSION_ERROR, ec);
2233     assertEquals("non-invariant", XXX, inv.getISOCurrency());
2234     ec = U_ZERO_ERROR;
2235 
2236     CurrencyUnit zzz(ZZZ, ec);
2237     assertEquals("too short", U_ILLEGAL_ARGUMENT_ERROR, ec);
2238     assertEquals("too short", XXX, zzz.getISOCurrency());
2239     ec = U_ZERO_ERROR;
2240 
2241     CurrencyUnit eur(EUR, ec);
2242     assertEquals("non-nul-terminated", u"EUR", eur.getISOCurrency());
2243     assertEquals("non-nul-terminated", "EUR", eur.getSubtype());
2244 
2245     // Test StringPiece constructor
2246     CurrencyUnit cu8(USD8, ec);
2247     assertEquals("StringPiece constructor", USD, cu8.getISOCurrency());
2248 
2249     CurrencyUnit inv8(INV8, ec);
2250     assertEquals("non-invariant 8", U_INVARIANT_CONVERSION_ERROR, ec);
2251     assertEquals("non-invariant 8", XXX, inv8.getISOCurrency());
2252     ec = U_ZERO_ERROR;
2253 
2254     CurrencyUnit zzz8(ZZZ8, ec);
2255     assertEquals("too short 8", U_ILLEGAL_ARGUMENT_ERROR, ec);
2256     assertEquals("too short 8", XXX, zzz8.getISOCurrency());
2257     ec = U_ZERO_ERROR;
2258 
2259     CurrencyUnit zzz8b({ZZZ8, 3}, ec);
2260     assertEquals("too short 8b", U_ILLEGAL_ARGUMENT_ERROR, ec);
2261     assertEquals("too short 8b", XXX, zzz8b.getISOCurrency());
2262     ec = U_ZERO_ERROR;
2263 
2264     CurrencyUnit eur8({EUR8, 3}, ec);
2265     assertEquals("non-nul-terminated 8", u"EUR", eur8.getISOCurrency());
2266     assertEquals("non-nul-terminated 8", "EUR", eur8.getSubtype());
2267 
2268     CurrencyUnit cu2(cu);
2269     if (!(cu2 == cu)){
2270         errln("CurrencyUnit copy constructed object should be same");
2271     }
2272 
2273     CurrencyUnit * cu3 = cu.clone();
2274     if (!(*cu3 == cu)){
2275         errln("CurrencyUnit cloned object should be same");
2276     }
2277     CurrencyUnit bad(BAD, ec);
2278     assertSuccess("CurrencyUnit", ec);
2279     if (cu.getOffset() == bad.getOffset()) {
2280         errln("Indexes of different currencies should differ.");
2281     }
2282     CurrencyUnit bad2(BAD2, ec);
2283     assertSuccess("CurrencyUnit", ec);
2284     if (bad2.getOffset() != bad.getOffset()) {
2285         errln("Indexes of unrecognized currencies should be the same.");
2286     }
2287     if (bad == bad2) {
2288         errln("Different unrecognized currencies should not be equal.");
2289     }
2290     bad = bad2;
2291     if (bad != bad2) {
2292         errln("Currency unit assignment should be the same.");
2293     }
2294     delete cu3;
2295 
2296     // Test default constructor
2297     CurrencyUnit def;
2298     assertEquals("Default currency", XXX, def.getISOCurrency());
2299     assertEquals("Default currency as subtype", XXX8, def.getSubtype());
2300 
2301     // Test slicing
2302     MeasureUnit sliced1 = cu;
2303     MeasureUnit sliced2 = cu;
2304     MeasureUnit sliced3 = extended;
2305     assertEquals("Subtype after slicing 1", USD8, sliced1.getSubtype());
2306     assertEquals("Subtype after slicing 2", USD8, sliced2.getSubtype());
2307     assertEquals("Subtype after slicing 3", XYZ8, sliced3.getSubtype());
2308     CurrencyUnit restored1(sliced1, ec);
2309     CurrencyUnit restored2(sliced2, ec);
2310     CurrencyUnit restored3(sliced3, ec);
2311     assertSuccess("Restoring from MeasureUnit", ec);
2312     assertEquals("Subtype after restoring 1", USD8, restored1.getSubtype());
2313     assertEquals("Subtype after restoring 2", USD8, restored2.getSubtype());
2314     assertEquals("Subtype after restoring 3", XYZ8, restored3.getSubtype());
2315     assertEquals("ISO Code after restoring 1", USD, restored1.getISOCurrency());
2316     assertEquals("ISO Code after restoring 2", USD, restored2.getISOCurrency());
2317     assertEquals("ISO Code after restoring 3", XYZ, restored3.getISOCurrency());
2318 
2319     // Test copy constructor failure
2320     LocalPointer<MeasureUnit> meter(MeasureUnit::createMeter(ec));
2321     assertSuccess("Creating meter", ec);
2322     CurrencyUnit failure(*meter, ec);
2323     assertEquals("Copying from meter should fail", ec, U_ILLEGAL_ARGUMENT_ERROR);
2324     assertEquals("Copying should not give uninitialized ISO code", u"", failure.getISOCurrency());
2325 
2326     // Test equality
2327     ec = U_ZERO_ERROR;
2328     assertFalse("FAIL: USD == JPY", CurrencyUnit(USD, ec) == CurrencyUnit(JPY, ec));
2329     assertTrue("FAIL: USD != USD",  CurrencyUnit(USD, ec) == CurrencyUnit(USD, ec));
2330     assertTrue("FAIL: JPY != jpy",  CurrencyUnit(JPY, ec) == CurrencyUnit(jpy, ec));
2331     assertTrue("FAIL: jpy != JPY",  CurrencyUnit(jpy, ec) == CurrencyUnit(JPY, ec));
2332 
2333     // Test equality with system charset instances
2334     assertFalse("FAIL: USD8 == JPY8", CurrencyUnit(USD8, ec) == CurrencyUnit(JPY8, ec));
2335     assertTrue("FAIL: USD8 != USD8",  CurrencyUnit(USD8, ec) == CurrencyUnit(USD8, ec));
2336     assertTrue("FAIL: JPY8 != jpy8",  CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy8, ec));
2337     assertTrue("FAIL: jpy8 != JPY8",  CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY8, ec));
2338 
2339     // Test equality between UTF-16 and system charset instances
2340     assertTrue("FAIL: USD != USD8",  CurrencyUnit(USD, ec) == CurrencyUnit(USD8, ec));
2341     assertTrue("FAIL: USD8 != USD",  CurrencyUnit(USD8, ec) == CurrencyUnit(USD, ec));
2342     assertTrue("FAIL: JPY != jpy8",  CurrencyUnit(JPY, ec) == CurrencyUnit(jpy8, ec));
2343     assertTrue("FAIL: JPY8 != jpy",  CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy, ec));
2344     assertTrue("FAIL: jpy != JPY8",  CurrencyUnit(jpy, ec) == CurrencyUnit(JPY8, ec));
2345     assertTrue("FAIL: jpy8 != JPY",  CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY, ec));
2346 
2347     free(EUR);
2348     free(EUR8);
2349 }
2350 
TestCurrencyAmount(void)2351 void NumberFormatTest::TestCurrencyAmount(void){
2352     UErrorCode ec = U_ZERO_ERROR;
2353     static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
2354     CurrencyAmount ca(9, USD, ec);
2355     assertSuccess("CurrencyAmount", ec);
2356 
2357     CurrencyAmount ca2(ca);
2358     if (!(ca2 == ca)){
2359         errln("CurrencyAmount copy constructed object should be same");
2360     }
2361 
2362     ca2=ca;
2363     if (!(ca2 == ca)){
2364         errln("CurrencyAmount assigned object should be same");
2365     }
2366 
2367     CurrencyAmount *ca3 = ca.clone();
2368     if (!(*ca3 == ca)){
2369         errln("CurrencyAmount cloned object should be same");
2370     }
2371     delete ca3;
2372 }
2373 
TestSymbolsWithBadLocale(void)2374 void NumberFormatTest::TestSymbolsWithBadLocale(void) {
2375     Locale locDefault;
2376     static const char *badLocales[] = {
2377         // length < ULOC_FULLNAME_CAPACITY
2378         "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME",
2379 
2380         // length > ULOC_FULLNAME_CAPACITY
2381         "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME"
2382     }; // expect U_USING_DEFAULT_WARNING for both
2383 
2384     unsigned int i;
2385     for (i = 0; i < UPRV_LENGTHOF(badLocales); i++) {
2386         const char *localeName = badLocales[i];
2387         Locale locBad(localeName);
2388         assertTrue(WHERE, !locBad.isBogus());
2389         UErrorCode status = U_ZERO_ERROR;
2390         UnicodeString intlCurrencySymbol((UChar)0xa4);
2391 
2392         intlCurrencySymbol.append((UChar)0xa4);
2393 
2394         logln("Current locale is %s", Locale::getDefault().getName());
2395         Locale::setDefault(locBad, status);
2396         logln("Current locale is %s", Locale::getDefault().getName());
2397         DecimalFormatSymbols mySymbols(status);
2398         if (status != U_USING_DEFAULT_WARNING) {
2399             errln("DecimalFormatSymbols should return U_USING_DEFAULT_WARNING.");
2400         }
2401         if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
2402             errln("DecimalFormatSymbols does not have the right locale.", locBad.getName());
2403         }
2404         int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
2405         for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
2406             UnicodeString symbolString = mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum);
2407             logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ") + prettify(symbolString));
2408             if (symbolString.length() == 0
2409                 && symbolEnum != (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
2410                 && symbolEnum != (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol)
2411             {
2412                 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
2413             }
2414         }
2415 
2416         status = U_ZERO_ERROR;
2417         Locale::setDefault(locDefault, status);
2418         logln("Current locale is %s", Locale::getDefault().getName());
2419     }
2420 }
2421 
2422 /**
2423  * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
2424  * behave the same, except for memory ownership semantics. (No
2425  * version of this test on Java, since Java has only one method.)
2426  */
TestAdoptDecimalFormatSymbols(void)2427 void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
2428     UErrorCode ec = U_ZERO_ERROR;
2429     DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2430     if (U_FAILURE(ec)) {
2431         errcheckln(ec, "Fail: DecimalFormatSymbols constructor - %s", u_errorName(ec));
2432         delete sym;
2433         return;
2434     }
2435     UnicodeString pat(" #,##0.00");
2436     pat.insert(0, (UChar)0x00A4);
2437     DecimalFormat fmt(pat, sym, ec);
2438     if (U_FAILURE(ec)) {
2439         errln("Fail: DecimalFormat constructor");
2440         return;
2441     }
2442 
2443     UnicodeString str;
2444     fmt.format(2350.75, str);
2445     if (str == "$ 2,350.75") {
2446         logln(str);
2447     } else {
2448         dataerrln("Fail: " + str + ", expected $ 2,350.75");
2449     }
2450 
2451     sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2452     if (U_FAILURE(ec)) {
2453         errln("Fail: DecimalFormatSymbols constructor");
2454         delete sym;
2455         return;
2456     }
2457     sym->setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2458     fmt.adoptDecimalFormatSymbols(sym);
2459 
2460     str.truncate(0);
2461     fmt.format(2350.75, str);
2462     if (str == "Q 2,350.75") {
2463         logln(str);
2464     } else {
2465         dataerrln("Fail: adoptDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2466     }
2467 
2468     sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2469     if (U_FAILURE(ec)) {
2470         errln("Fail: DecimalFormatSymbols constructor");
2471         delete sym;
2472         return;
2473     }
2474     DecimalFormat fmt2(pat, sym, ec);
2475     if (U_FAILURE(ec)) {
2476         errln("Fail: DecimalFormat constructor");
2477         return;
2478     }
2479 
2480     DecimalFormatSymbols sym2(Locale::getUS(), ec);
2481     if (U_FAILURE(ec)) {
2482         errln("Fail: DecimalFormatSymbols constructor");
2483         return;
2484     }
2485     sym2.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2486     fmt2.setDecimalFormatSymbols(sym2);
2487 
2488     str.truncate(0);
2489     fmt2.format(2350.75, str);
2490     if (str == "Q 2,350.75") {
2491         logln(str);
2492     } else {
2493         dataerrln("Fail: setDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2494     }
2495 }
2496 
TestPerMill()2497 void NumberFormatTest::TestPerMill() {
2498     UErrorCode ec = U_ZERO_ERROR;
2499     UnicodeString str;
2500     DecimalFormat fmt(ctou("###.###\\u2030"), ec);
2501     if (!assertSuccess("DecimalFormat ct", ec)) return;
2502     assertEquals("0.4857 x ###.###\\u2030",
2503                  ctou("485.7\\u2030"), fmt.format(0.4857, str), true);
2504 
2505     DecimalFormatSymbols sym(Locale::getUS(), ec);
2506     if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2507         return;
2508     }
2509     sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
2510     DecimalFormat fmt2("", sym, ec);
2511     if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2512         return;
2513     }
2514     fmt2.applyLocalizedPattern("###.###m", ec);
2515     if (!assertSuccess("setup", ec)) return;
2516     str.truncate(0);
2517     assertEquals("0.4857 x ###.###m",
2518                  "485.7m", fmt2.format(0.4857, str));
2519 }
2520 
2521 /**
2522  * Generic test for patterns that should be legal/illegal.
2523  */
TestIllegalPatterns()2524 void NumberFormatTest::TestIllegalPatterns() {
2525     // Test cases:
2526     // Prefix with "-:" for illegal patterns
2527     // Prefix with "+:" for legal patterns
2528     const char* DATA[] = {
2529         // Unquoted special characters in the suffix are illegal
2530         "-:000.000|###",
2531         "+:000.000'|###'",
2532         0
2533     };
2534     for (int32_t i=0; DATA[i]; ++i) {
2535         const char* pat=DATA[i];
2536         UBool valid = (*pat) == '+';
2537         pat += 2;
2538         UErrorCode ec = U_ZERO_ERROR;
2539         DecimalFormat fmt(pat, ec); // locale doesn't matter here
2540         if (U_SUCCESS(ec) == valid) {
2541             logln("Ok: pattern \"%s\": %s",
2542                   pat, u_errorName(ec));
2543         } else {
2544             errcheckln(ec, "FAIL: pattern \"%s\" should have %s; got %s",
2545                   pat, (valid?"succeeded":"failed"),
2546                   u_errorName(ec));
2547         }
2548     }
2549 }
2550 
2551 //----------------------------------------------------------------------
2552 
2553 static const char* KEYWORDS[] = {
2554     /*0*/ "ref=", // <reference pattern to parse numbers>
2555     /*1*/ "loc=", // <locale for formats>
2556     /*2*/ "f:",   // <pattern or '-'> <number> <exp. string>
2557     /*3*/ "fp:",  // <pattern or '-'> <number> <exp. string> <exp. number>
2558     /*4*/ "rt:",  // <pattern or '-'> <(exp.) number> <(exp.) string>
2559     /*5*/ "p:",   // <pattern or '-'> <string> <exp. number>
2560     /*6*/ "perr:", // <pattern or '-'> <invalid string>
2561     /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
2562     /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2563     0
2564 };
2565 
2566 /**
2567  * Return an integer representing the next token from this
2568  * iterator.  The integer will be an index into the given list, or
2569  * -1 if there are no more tokens, or -2 if the token is not on
2570  * the list.
2571  */
keywordIndex(const UnicodeString& tok)2572 static int32_t keywordIndex(const UnicodeString& tok) {
2573     for (int32_t i=0; KEYWORDS[i]!=0; ++i) {
2574         if (tok==KEYWORDS[i]) {
2575             return i;
2576         }
2577     }
2578     return -1;
2579 }
2580 
2581 /**
2582  * Parse a CurrencyAmount using the given NumberFormat, with
2583  * the 'delim' character separating the number and the currency.
2584  */
parseCurrencyAmount(const UnicodeString& str, const NumberFormat& fmt, UChar delim, Formattable& result, UErrorCode& ec)2585 static void parseCurrencyAmount(const UnicodeString& str,
2586                                 const NumberFormat& fmt,
2587                                 UChar delim,
2588                                 Formattable& result,
2589                                 UErrorCode& ec) {
2590     UnicodeString num, cur;
2591     int32_t i = str.indexOf(delim);
2592     str.extractBetween(0, i, num);
2593     str.extractBetween(i+1, INT32_MAX, cur);
2594     Formattable n;
2595     fmt.parse(num, n, ec);
2596     result.adoptObject(new CurrencyAmount(n, cur.getTerminatedBuffer(), ec));
2597 }
2598 
TestCases()2599 void NumberFormatTest::TestCases() {
2600     UErrorCode ec = U_ZERO_ERROR;
2601     TextFile reader("NumberFormatTestCases.txt", "UTF8", ec);
2602     if (U_FAILURE(ec)) {
2603         dataerrln("Couldn't open NumberFormatTestCases.txt");
2604         return;
2605     }
2606     TokenIterator tokens(&reader);
2607 
2608     Locale loc("en", "US", "");
2609     DecimalFormat *ref = 0, *fmt = 0;
2610     MeasureFormat *mfmt = 0;
2611     UnicodeString pat, tok, mloc, str, out, where, currAmt;
2612     Formattable n;
2613 
2614     for (;;) {
2615         ec = U_ZERO_ERROR;
2616         if (!tokens.next(tok, ec)) {
2617             break;
2618         }
2619         where = UnicodeString("(") + tokens.getLineNumber() + ") ";
2620         int32_t cmd = keywordIndex(tok);
2621         switch (cmd) {
2622         case 0:
2623             // ref= <reference pattern>
2624             if (!tokens.next(tok, ec)) goto error;
2625             delete ref;
2626             ref = new DecimalFormat(tok,
2627                       new DecimalFormatSymbols(Locale::getUS(), ec), ec);
2628             if (U_FAILURE(ec)) {
2629                 dataerrln("Error constructing DecimalFormat");
2630                 goto error;
2631             }
2632             break;
2633         case 1:
2634             // loc= <locale>
2635             if (!tokens.next(tok, ec)) goto error;
2636             loc = Locale::createFromName(CharString().appendInvariantChars(tok, ec).data());
2637             break;
2638         case 2: // f:
2639         case 3: // fp:
2640         case 4: // rt:
2641         case 5: // p:
2642             if (!tokens.next(tok, ec)) goto error;
2643             if (tok != "-") {
2644                 pat = tok;
2645                 delete fmt;
2646                 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc, ec), ec);
2647                 if (U_FAILURE(ec)) {
2648                     errln("FAIL: " + where + "Pattern \"" + pat + "\": " + u_errorName(ec));
2649                     ec = U_ZERO_ERROR;
2650                     if (!tokens.next(tok, ec)) goto error;
2651                     if (!tokens.next(tok, ec)) goto error;
2652                     if (cmd == 3) {
2653                         if (!tokens.next(tok, ec)) goto error;
2654                     }
2655                     continue;
2656                 }
2657             }
2658             if (cmd == 2 || cmd == 3 || cmd == 4) {
2659                 // f: <pattern or '-'> <number> <exp. string>
2660                 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
2661                 // rt: <pattern or '-'> <number> <string>
2662                 UnicodeString num;
2663                 if (!tokens.next(num, ec)) goto error;
2664                 if (!tokens.next(str, ec)) goto error;
2665                 ref->parse(num, n, ec);
2666                 assertSuccess("parse", ec);
2667                 assertEquals(where + "\"" + pat + "\".format(" + num + ")",
2668                              str, fmt->format(n, out.remove(), ec));
2669                 assertSuccess("format", ec);
2670                 if (cmd == 3) { // fp:
2671                     if (!tokens.next(num, ec)) goto error;
2672                     ref->parse(num, n, ec);
2673                     assertSuccess("parse", ec);
2674                 }
2675                 if (cmd != 2) { // != f:
2676                     Formattable m;
2677                     fmt->parse(str, m, ec);
2678                     assertSuccess("parse", ec);
2679                     assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2680                                  n, m);
2681                 }
2682             }
2683             // p: <pattern or '-'> <string to parse> <exp. number>
2684             else {
2685                 UnicodeString expstr;
2686                 if (!tokens.next(str, ec)) goto error;
2687                 if (!tokens.next(expstr, ec)) goto error;
2688                 Formattable exp, n;
2689                 ref->parse(expstr, exp, ec);
2690                 assertSuccess("parse", ec);
2691                 fmt->parse(str, n, ec);
2692                 assertSuccess("parse", ec);
2693                 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2694                              exp, n);
2695             }
2696             break;
2697         case 8: // fpc:
2698             if (!tokens.next(tok, ec)) goto error;
2699             if (tok != "-") {
2700                 mloc = tok;
2701                 delete mfmt;
2702                 mfmt = MeasureFormat::createCurrencyFormat(
2703                     Locale::createFromName(
2704                         CharString().appendInvariantChars(mloc, ec).data()), ec);
2705                 if (U_FAILURE(ec)) {
2706                     errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
2707                     ec = U_ZERO_ERROR;
2708                     if (!tokens.next(tok, ec)) goto error;
2709                     if (!tokens.next(tok, ec)) goto error;
2710                     if (!tokens.next(tok, ec)) goto error;
2711                     continue;
2712                 }
2713             } else if (mfmt == NULL) {
2714                 errln("FAIL: " + where + "Loc \"" + mloc + "\": skip case using previous locale, no valid MeasureFormat");
2715                 if (!tokens.next(tok, ec)) goto error;
2716                 if (!tokens.next(tok, ec)) goto error;
2717                 if (!tokens.next(tok, ec)) goto error;
2718                 continue;
2719             }
2720             // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2721             if (!tokens.next(currAmt, ec)) goto error;
2722             if (!tokens.next(str, ec)) goto error;
2723             parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2724             if (assertSuccess("parseCurrencyAmount", ec)) {
2725                 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
2726                              str, mfmt->format(n, out.remove(), ec));
2727                 assertSuccess("format", ec);
2728             }
2729             if (!tokens.next(currAmt, ec)) goto error;
2730             parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2731             if (assertSuccess("parseCurrencyAmount", ec)) {
2732                 Formattable m;
2733 
2734                 mfmt->parseObject(str, m, ec);
2735                 if (assertSuccess("parseCurrency", ec)) {
2736                     assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
2737                                  n, m);
2738                 } else {
2739                     errln("FAIL: source " + str);
2740                 }
2741             }
2742             break;
2743         case 6:
2744             // perr: <pattern or '-'> <invalid string>
2745             errln("FAIL: Under construction");
2746             goto done;
2747         case 7: {
2748             // pat: <pattern> <exp. toPattern, or '-' or 'err'>
2749             UnicodeString testpat;
2750             UnicodeString exppat;
2751             if (!tokens.next(testpat, ec)) goto error;
2752             if (!tokens.next(exppat, ec)) goto error;
2753             UBool err = exppat == "err";
2754             UBool existingPat = false;
2755             if (testpat == "-") {
2756                 if (err) {
2757                     errln("FAIL: " + where + "Invalid command \"pat: - err\"");
2758                     continue;
2759                 }
2760                 existingPat = true;
2761                 testpat = pat;
2762             }
2763             if (exppat == "-") exppat = testpat;
2764             DecimalFormat* f = 0;
2765             UErrorCode ec2 = U_ZERO_ERROR;
2766             if (existingPat) {
2767                 f = fmt;
2768             } else {
2769                 f = new DecimalFormat(testpat, ec2);
2770             }
2771             if (U_SUCCESS(ec2)) {
2772                 if (err) {
2773                     errln("FAIL: " + where + "Invalid pattern \"" + testpat +
2774                           "\" was accepted");
2775                 } else {
2776                     UnicodeString pat2;
2777                     assertEquals(where + "\"" + testpat + "\".toPattern()",
2778                                  exppat, f->toPattern(pat2));
2779                 }
2780             } else {
2781                 if (err) {
2782                     logln("Ok: " + where + "Invalid pattern \"" + testpat +
2783                           "\" failed: " + u_errorName(ec2));
2784                 } else {
2785                     errln("FAIL: " + where + "Valid pattern \"" + testpat +
2786                           "\" failed: " + u_errorName(ec2));
2787                 }
2788             }
2789             if (!existingPat) delete f;
2790             } break;
2791         case -1:
2792             errln("FAIL: " + where + "Unknown command \"" + tok + "\"");
2793             goto done;
2794         }
2795     }
2796     goto done;
2797 
2798  error:
2799     if (U_SUCCESS(ec)) {
2800         errln("FAIL: Unexpected EOF");
2801     } else {
2802         errcheckln(ec, "FAIL: " + where + "Unexpected " + u_errorName(ec));
2803     }
2804 
2805  done:
2806     delete mfmt;
2807     delete fmt;
2808     delete ref;
2809 }
2810 
2811 
2812 //----------------------------------------------------------------------
2813 // Support methods
2814 //----------------------------------------------------------------------
2815 
equalValue(const Formattable& a, const Formattable& b)2816 UBool NumberFormatTest::equalValue(const Formattable& a, const Formattable& b) {
2817     if (a.getType() == b.getType()) {
2818         return a == b;
2819     }
2820 
2821     if (a.getType() == Formattable::kLong) {
2822         if (b.getType() == Formattable::kInt64) {
2823             return a.getLong() == b.getLong();
2824         } else if (b.getType() == Formattable::kDouble) {
2825             return (double) a.getLong() == b.getDouble(); // TODO check use of double instead of long
2826         }
2827     } else if (a.getType() == Formattable::kDouble) {
2828         if (b.getType() == Formattable::kLong) {
2829             return a.getDouble() == (double) b.getLong();
2830         } else if (b.getType() == Formattable::kInt64) {
2831             return a.getDouble() == (double)b.getInt64();
2832         }
2833     } else if (a.getType() == Formattable::kInt64) {
2834         if (b.getType() == Formattable::kLong) {
2835                 return a.getInt64() == (int64_t)b.getLong();
2836         } else if (b.getType() == Formattable::kDouble) {
2837             return a.getInt64() == (int64_t)b.getDouble();
2838         }
2839     }
2840     return false;
2841 }
2842 
expect3(NumberFormat& fmt, const Formattable& n, const UnicodeString& str)2843 void NumberFormatTest::expect3(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2844     // Don't round-trip format test, since we explicitly do it
2845     expect_rbnf(fmt, n, str, false);
2846     expect_rbnf(fmt, str, n);
2847 }
2848 
expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str)2849 void NumberFormatTest::expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2850     // Don't round-trip format test, since we explicitly do it
2851     expect(fmt, n, str, false);
2852     expect(fmt, str, n);
2853 }
2854 
expect2(NumberFormat* fmt, const Formattable& n, const UnicodeString& exp, UErrorCode status)2855 void NumberFormatTest::expect2(NumberFormat* fmt, const Formattable& n,
2856                                const UnicodeString& exp,
2857                                UErrorCode status) {
2858     if (fmt == NULL || U_FAILURE(status)) {
2859         dataerrln("FAIL: NumberFormat constructor");
2860     } else {
2861         expect2(*fmt, n, exp);
2862     }
2863     delete fmt;
2864 }
2865 
expect(NumberFormat& fmt, const UnicodeString& str, const Formattable& n)2866 void NumberFormatTest::expect(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2867     UErrorCode status = U_ZERO_ERROR;
2868     Formattable num;
2869     fmt.parse(str, num, status);
2870     if (U_FAILURE(status)) {
2871         dataerrln(UnicodeString("FAIL: Parse failed for \"") + str + "\" - " + u_errorName(status));
2872         return;
2873     }
2874     UnicodeString pat;
2875     ((DecimalFormat*) &fmt)->toPattern(pat);
2876     if (equalValue(num, n)) {
2877         logln(UnicodeString("Ok   \"") + str + "\" x " +
2878               pat + " = " +
2879               toString(num));
2880     } else {
2881         dataerrln(UnicodeString("FAIL \"") + str + "\" x " +
2882               pat + " = " +
2883               toString(num) + ", expected " + toString(n));
2884     }
2885 }
2886 
expect_rbnf(NumberFormat& fmt, const UnicodeString& str, const Formattable& n)2887 void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2888     UErrorCode status = U_ZERO_ERROR;
2889     Formattable num;
2890     fmt.parse(str, num, status);
2891     if (U_FAILURE(status)) {
2892         errln(UnicodeString("FAIL: Parse failed for \"") + str + "\"");
2893         return;
2894     }
2895     if (equalValue(num, n)) {
2896         logln(UnicodeString("Ok   \"") + str + " = " +
2897               toString(num));
2898     } else {
2899         errln(UnicodeString("FAIL \"") + str + " = " +
2900               toString(num) + ", expected " + toString(n));
2901     }
2902 }
2903 
expect_rbnf(NumberFormat& fmt, const Formattable& n, const UnicodeString& exp, UBool rt)2904 void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const Formattable& n,
2905                               const UnicodeString& exp, UBool rt) {
2906     UnicodeString saw;
2907     FieldPosition pos;
2908     UErrorCode status = U_ZERO_ERROR;
2909     fmt.format(n, saw, pos, status);
2910     CHECK(status, "NumberFormat::format");
2911     if (saw == exp) {
2912         logln(UnicodeString("Ok   ") + toString(n) +
2913               " = \"" +
2914               escape(saw) + "\"");
2915         // We should be able to round-trip the formatted string =>
2916         // number => string (but not the other way around: number
2917         // => string => number2, might have number2 != number):
2918         if (rt) {
2919             Formattable n2;
2920             fmt.parse(exp, n2, status);
2921             if (U_FAILURE(status)) {
2922                 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\"");
2923                 return;
2924             }
2925             UnicodeString saw2;
2926             fmt.format(n2, saw2, pos, status);
2927             CHECK(status, "NumberFormat::format");
2928             if (saw2 != exp) {
2929                 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2930                       " => \"" + saw2 + "\"");
2931             }
2932         }
2933     } else {
2934         errln(UnicodeString("FAIL ") + toString(n) +
2935               " = \"" +
2936               escape(saw) + "\", expected \"" + exp + "\"");
2937     }
2938 }
2939 
expect(NumberFormat& fmt, const Formattable& n, const UnicodeString& exp, UBool rt)2940 void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
2941                               const UnicodeString& exp, UBool rt) {
2942     UnicodeString saw;
2943     FieldPosition pos;
2944     UErrorCode status = U_ZERO_ERROR;
2945     fmt.format(n, saw, pos, status);
2946     CHECK(status, "NumberFormat::format");
2947     UnicodeString pat;
2948     ((DecimalFormat*) &fmt)->toPattern(pat);
2949     if (saw == exp) {
2950         logln(UnicodeString("Ok   ") + toString(n) + " x " +
2951               escape(pat) + " = \"" +
2952               escape(saw) + "\"");
2953         // We should be able to round-trip the formatted string =>
2954         // number => string (but not the other way around: number
2955         // => string => number2, might have number2 != number):
2956         if (rt) {
2957             Formattable n2;
2958             fmt.parse(exp, n2, status);
2959             if (U_FAILURE(status)) {
2960                 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\" - " + u_errorName(status));
2961                 return;
2962             }
2963             UnicodeString saw2;
2964             fmt.format(n2, saw2, pos, status);
2965             CHECK(status, "NumberFormat::format");
2966             if (saw2 != exp) {
2967                 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2968                       " => \"" + saw2 + "\"");
2969             }
2970         }
2971     } else {
2972         dataerrln(UnicodeString("FAIL ") + toString(n) + " x " +
2973               escape(pat) + " = \"" +
2974               escape(saw) + "\", expected \"" + exp + "\"");
2975     }
2976 }
2977 
expect(NumberFormat* fmt, const Formattable& n, const UnicodeString& exp, UBool rt, UErrorCode status)2978 void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
2979                               const UnicodeString& exp, UBool rt,
2980                               UErrorCode status) {
2981     if (fmt == NULL || U_FAILURE(status)) {
2982         dataerrln("FAIL: NumberFormat constructor");
2983     } else {
2984         expect(*fmt, n, exp, rt);
2985     }
2986     delete fmt;
2987 }
2988 
expectCurrency(NumberFormat& nf, const Locale& locale, double value, const UnicodeString& string)2989 void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
2990                                       double value, const UnicodeString& string) {
2991     UErrorCode ec = U_ZERO_ERROR;
2992     DecimalFormat& fmt = * (DecimalFormat*) &nf;
2993     const UChar DEFAULT_CURR[] = {45/*-*/,0};
2994     UChar curr[4];
2995     u_strcpy(curr, DEFAULT_CURR);
2996     if (*locale.getLanguage() != 0) {
2997         ucurr_forLocale(locale.getName(), curr, 4, &ec);
2998         assertSuccess("ucurr_forLocale", ec);
2999         fmt.setCurrency(curr, ec);
3000         assertSuccess("DecimalFormat::setCurrency", ec);
3001         fmt.setCurrency(curr); //Deprecated variant, for coverage only
3002     }
3003     UnicodeString s;
3004     fmt.format(value, s);
3005     s.findAndReplace((UChar32)0x00A0, (UChar32)0x0020);
3006 
3007     // Default display of the number yields "1234.5599999999999"
3008     // instead of "1234.56".  Use a formatter to fix this.
3009     NumberFormat* f =
3010         NumberFormat::createInstance(Locale::getUS(), ec);
3011     UnicodeString v;
3012     if (U_FAILURE(ec)) {
3013         // Oops; bad formatter.  Use default op+= display.
3014         v = (UnicodeString)"" + value;
3015     } else {
3016         f->setMaximumFractionDigits(4);
3017         f->setGroupingUsed(false);
3018         f->format(value, v);
3019     }
3020     delete f;
3021 
3022     if (s == string) {
3023         logln((UnicodeString)"Ok: " + v + " x " + curr + " => " + prettify(s));
3024     } else {
3025         errln((UnicodeString)"FAIL: " + v + " x " + curr + " => " + prettify(s) +
3026               ", expected " + prettify(string));
3027     }
3028 }
3029 
expectPat(DecimalFormat& fmt, const UnicodeString& exp)3030 void NumberFormatTest::expectPat(DecimalFormat& fmt, const UnicodeString& exp) {
3031     UnicodeString pat;
3032     fmt.toPattern(pat);
3033     if (pat == exp) {
3034         logln(UnicodeString("Ok   \"") + pat + "\"");
3035     } else {
3036         errln(UnicodeString("FAIL \"") + pat + "\", expected \"" + exp + "\"");
3037     }
3038 }
3039 
expectPad(DecimalFormat& fmt, const UnicodeString& pat, int32_t pos)3040 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3041                                  int32_t pos) {
3042     expectPad(fmt, pat, pos, 0, (UnicodeString)"");
3043 }
expectPad(DecimalFormat& fmt, const UnicodeString& pat, int32_t pos, int32_t width, UChar pad)3044 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3045                                  int32_t pos, int32_t width, UChar pad) {
3046     expectPad(fmt, pat, pos, width, UnicodeString(pad));
3047 }
expectPad(DecimalFormat& fmt, const UnicodeString& pat, int32_t pos, int32_t width, const UnicodeString& pad)3048 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3049                                  int32_t pos, int32_t width, const UnicodeString& pad) {
3050     int32_t apos = 0, awidth = 0;
3051     UnicodeString apadStr;
3052     UErrorCode status = U_ZERO_ERROR;
3053     fmt.applyPattern(pat, status);
3054     if (U_SUCCESS(status)) {
3055         apos = fmt.getPadPosition();
3056         awidth = fmt.getFormatWidth();
3057         apadStr=fmt.getPadCharacterString();
3058     } else {
3059         apos = -1;
3060         awidth = width;
3061         apadStr = pad;
3062     }
3063     if (apos == pos && awidth == width && apadStr == pad) {
3064         UnicodeString infoStr;
3065         if (pos == ILLEGAL) {
3066             infoStr = UnicodeString(" width=", "") + awidth + UnicodeString(" pad=", "") + apadStr;
3067         }
3068         logln(UnicodeString("Ok   \"") + pat + "\" pos=" + apos + infoStr);
3069     } else {
3070         errln(UnicodeString("FAIL \"") + pat + "\" pos=" + apos +
3071               " width=" + awidth + " pad=" + apadStr +
3072               ", expected " + pos + " " + width + " " + pad);
3073     }
3074 }
3075 
3076 // This test is flaky b/c the symbols for CNY and JPY are equivalent in this locale  - FIXME
TestCompatibleCurrencies()3077 void NumberFormatTest::TestCompatibleCurrencies() {
3078 /*
3079     static const UChar JPY[] = {0x4A, 0x50, 0x59, 0};
3080     static const UChar CNY[] = {0x43, 0x4E, 0x59, 0};
3081     UErrorCode status = U_ZERO_ERROR;
3082     LocalPointer<NumberFormat> fmt(
3083         NumberFormat::createCurrencyInstance(Locale::getUS(), status));
3084     if (U_FAILURE(status)) {
3085         errln("Could not create number format instance.");
3086         return;
3087     }
3088     logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3089     expectParseCurrency(*fmt, JPY, 1235,  "\\u00A51,235");
3090     logln("%s:%d - testing parse of fullwidth yen sign\n", __FILE__, __LINE__);
3091     expectParseCurrency(*fmt, JPY, 1235,  "\\uFFE51,235");
3092     logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3093     expectParseCurrency(*fmt, CNY, 1235,  "CN\\u00A51,235");
3094 
3095     LocalPointer<NumberFormat> fmtTW(
3096         NumberFormat::createCurrencyInstance(Locale::getTaiwan(), status));
3097 
3098     logln("%s:%d - testing parse of halfwidth yen sign in TW\n", __FILE__, __LINE__);
3099     expectParseCurrency(*fmtTW, CNY, 1235,  "\\u00A51,235");
3100     logln("%s:%d - testing parse of fullwidth yen sign in TW\n", __FILE__, __LINE__);
3101     expectParseCurrency(*fmtTW, CNY, 1235,  "\\uFFE51,235");
3102 
3103     LocalPointer<NumberFormat> fmtJP(
3104         NumberFormat::createCurrencyInstance(Locale::getJapan(), status));
3105 
3106     logln("%s:%d - testing parse of halfwidth yen sign in JP\n", __FILE__, __LINE__);
3107     expectParseCurrency(*fmtJP, JPY, 1235,  "\\u00A51,235");
3108     logln("%s:%d - testing parse of fullwidth yen sign in JP\n", __FILE__, __LINE__);
3109     expectParseCurrency(*fmtJP, JPY, 1235,  "\\uFFE51,235");
3110 
3111     // more..
3112 */
3113 }
3114 
expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text)3115 void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text) {
3116     ParsePosition ppos;
3117     UnicodeString utext = ctou(text);
3118     LocalPointer<CurrencyAmount> currencyAmount(fmt.parseCurrency(utext, ppos));
3119     if (!ppos.getIndex()) {
3120         errln(UnicodeString("Parse of ") + utext + " should have succeeded.");
3121         return;
3122     }
3123     UErrorCode status = U_ZERO_ERROR;
3124 
3125     char theInfo[100];
3126     sprintf(theInfo, "For locale %s, string \"%s\", currency ",
3127             fmt.getLocale(ULOC_ACTUAL_LOCALE, status).getBaseName(),
3128             text);
3129     u_austrcpy(theInfo+uprv_strlen(theInfo), currency);
3130 
3131     char theOperation[100];
3132 
3133     uprv_strcpy(theOperation, theInfo);
3134     uprv_strcat(theOperation, ", check amount:");
3135     assertTrue(theOperation, amount ==  currencyAmount->getNumber().getDouble(status));
3136 
3137     uprv_strcpy(theOperation, theInfo);
3138     uprv_strcat(theOperation, ", check currency:");
3139     assertEquals(theOperation, currency, currencyAmount->getISOCurrency());
3140 }
3141 
3142 
TestJB3832()3143 void NumberFormatTest::TestJB3832(){
3144     const char* localeID = "pt_PT@currency=PTE";
3145     Locale loc(localeID);
3146     UErrorCode status = U_ZERO_ERROR;
3147     UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0\\u200B")); // per cldrbug 7670
3148     UnicodeString s;
3149     NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
3150     if(U_FAILURE(status)){
3151         dataerrln("Could not create currency formatter for locale %s - %s", localeID, u_errorName(status));
3152         return;
3153     }
3154     currencyFmt->format(1150.50, s);
3155     if(s!=expected){
3156         errln(UnicodeString("FAIL: Expected: ")+expected
3157                 + UnicodeString(" Got: ") + s
3158                 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
3159     }
3160     if (U_FAILURE(status)){
3161         errln("FAIL: Status %s", u_errorName(status));
3162     }
3163     delete currencyFmt;
3164 }
3165 
TestHost()3166 void NumberFormatTest::TestHost()
3167 {
3168 #if U_PLATFORM_USES_ONLY_WIN32_API
3169     Win32NumberTest::testLocales(this);
3170 #endif
3171     Locale loc("en_US@compat=host");
3172     for (UNumberFormatStyle k = UNUM_DECIMAL;
3173          k < UNUM_FORMAT_STYLE_COUNT; k = (UNumberFormatStyle)(k+1)) {
3174         UErrorCode status = U_ZERO_ERROR;
3175         LocalPointer<NumberFormat> full(NumberFormat::createInstance(loc, k, status));
3176         if (!NumberFormat::isStyleSupported(k)) {
3177             if (status != U_UNSUPPORTED_ERROR) {
3178                 errln("FAIL: expected style %d to be unsupported - %s",
3179                       k, u_errorName(status));
3180             }
3181             continue;
3182         }
3183         if (full.isNull() || U_FAILURE(status)) {
3184             dataerrln("FAIL: Can't create number instance of style %d for host - %s",
3185                       k, u_errorName(status));
3186             return;
3187         }
3188         UnicodeString result1;
3189         Formattable number(10.00);
3190         full->format(number, result1, status);
3191         if (U_FAILURE(status)) {
3192             errln("FAIL: Can't format for host");
3193             return;
3194         }
3195         Formattable formattable;
3196         full->parse(result1, formattable, status);
3197         if (U_FAILURE(status)) {
3198             errln("FAIL: Can't parse for host");
3199             return;
3200         }
3201     }
3202 }
3203 
TestHostClone()3204 void NumberFormatTest::TestHostClone()
3205 {
3206     /*
3207     Verify that a cloned formatter gives the same results
3208     and is useable after the original has been deleted.
3209     */
3210     // This is mainly important on Windows.
3211     UErrorCode status = U_ZERO_ERROR;
3212     Locale loc("en_US@compat=host");
3213     UDate now = Calendar::getNow();
3214     NumberFormat *full = NumberFormat::createInstance(loc, status);
3215     if (full == NULL || U_FAILURE(status)) {
3216         dataerrln("FAIL: Can't create NumberFormat date instance - %s", u_errorName(status));
3217         return;
3218     }
3219     UnicodeString result1;
3220     full->format(now, result1, status);
3221     Format *fullClone = full->clone();
3222     delete full;
3223     full = NULL;
3224 
3225     UnicodeString result2;
3226     fullClone->format(now, result2, status);
3227     if (U_FAILURE(status)) {
3228         errln("FAIL: format failure.");
3229     }
3230     if (result1 != result2) {
3231         errln("FAIL: Clone returned different result from non-clone.");
3232     }
3233     delete fullClone;
3234 }
3235 
TestCurrencyFormat()3236 void NumberFormatTest::TestCurrencyFormat()
3237 {
3238     // This test is here to increase code coverage.
3239     UErrorCode status = U_ZERO_ERROR;
3240     MeasureFormat *cloneObj;
3241     UnicodeString str;
3242     Formattable toFormat, result;
3243     static const UChar ISO_CODE[4] = {0x0047, 0x0042, 0x0050, 0};
3244 
3245     Locale  saveDefaultLocale = Locale::getDefault();
3246     Locale::setDefault( Locale::getUK(), status );
3247     if (U_FAILURE(status)) {
3248         errln("couldn't set default Locale!");
3249         return;
3250     }
3251 
3252     MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
3253     Locale::setDefault( saveDefaultLocale, status );
3254     if (U_FAILURE(status)){
3255         dataerrln("FAIL: Status %s", u_errorName(status));
3256         return;
3257     }
3258     cloneObj = measureObj->clone();
3259     if (cloneObj == NULL) {
3260         errln("Clone doesn't work");
3261         return;
3262     }
3263     toFormat.adoptObject(new CurrencyAmount(1234.56, ISO_CODE, status));
3264     measureObj->format(toFormat, str, status);
3265     measureObj->parseObject(str, result, status);
3266     if (U_FAILURE(status)){
3267         errln("FAIL: Status %s", u_errorName(status));
3268     }
3269     if (result != toFormat) {
3270         errln("measureObj does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3271     }
3272     status = U_ZERO_ERROR;
3273     str.truncate(0);
3274     cloneObj->format(toFormat, str, status);
3275     cloneObj->parseObject(str, result, status);
3276     if (U_FAILURE(status)){
3277         errln("FAIL: Status %s", u_errorName(status));
3278     }
3279     if (result != toFormat) {
3280         errln("Clone does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3281     }
3282     if (*measureObj != *cloneObj) {
3283         errln("Cloned object is not equal to the original object");
3284     }
3285     delete measureObj;
3286     delete cloneObj;
3287 
3288     status = U_USELESS_COLLATOR_ERROR;
3289     if (MeasureFormat::createCurrencyFormat(status) != NULL) {
3290         errln("createCurrencyFormat should have returned NULL.");
3291     }
3292 }
3293 
3294 /* Port of ICU4J rounding test. */
TestRounding()3295 void NumberFormatTest::TestRounding() {
3296     UErrorCode status = U_ZERO_ERROR;
3297     DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3298 
3299     if (U_FAILURE(status)) {
3300         dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3301         return;
3302     }
3303 
3304     int roundingIncrements[]={1, 2, 5, 20, 50, 100};
3305     int testValues[]={0, 300};
3306 
3307     for (int j=0; j<2; j++) {
3308         for (int mode=DecimalFormat::kRoundUp;mode<DecimalFormat::kRoundHalfEven;mode++) {
3309             df->setRoundingMode((DecimalFormat::ERoundingMode)mode);
3310             for (int increment=0; increment<6; increment++) {
3311                 double base=testValues[j];
3312                 double rInc=roundingIncrements[increment];
3313                 checkRounding(df, base, 20, rInc);
3314                 rInc=1.000000000/rInc;
3315                 checkRounding(df, base, 20, rInc);
3316             }
3317         }
3318     }
3319     delete df;
3320 }
3321 
TestRoundingPattern()3322 void NumberFormatTest::TestRoundingPattern() {
3323     UErrorCode status = U_ZERO_ERROR;
3324     struct {
3325         UnicodeString  pattern;
3326         double        testCase;
3327         UnicodeString expected;
3328     } tests[] = {
3329             { (UnicodeString)"##0.65", 1.234, (UnicodeString)"1.30" },
3330             { (UnicodeString)"#50",    1230,  (UnicodeString)"1250" }
3331     };
3332     int32_t numOfTests = UPRV_LENGTHOF(tests);
3333     UnicodeString result;
3334 
3335     DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3336     if (U_FAILURE(status)) {
3337         dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3338         return;
3339     }
3340 
3341     for (int32_t i = 0; i < numOfTests; i++) {
3342         result.remove();
3343 
3344         df->applyPattern(tests[i].pattern, status);
3345         if (U_FAILURE(status)) {
3346             errln("Unable to apply pattern to decimal formatter. - %s", u_errorName(status));
3347         }
3348 
3349         df->format(tests[i].testCase, result);
3350 
3351         if (result != tests[i].expected) {
3352             errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
3353         }
3354     }
3355 
3356     delete df;
3357 }
3358 
checkRounding(DecimalFormat* df, double base, int iterations, double increment)3359 void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
3360     df->setRoundingIncrement(increment);
3361     assertEquals("Rounding increment round-trip", increment, df->getRoundingIncrement());
3362     double lastParsed=INT32_MIN; //Intger.MIN_VALUE
3363     for (int i=-iterations; i<=iterations;i++) {
3364         double iValue=base+(increment*(i*0.1));
3365         double smallIncrement=0.00000001;
3366         if (iValue!=0) {
3367             smallIncrement*=iValue;
3368         }
3369         //we not only test the value, but some values in a small range around it
3370         lastParsed=checkRound(df, iValue-smallIncrement, lastParsed);
3371         lastParsed=checkRound(df, iValue, lastParsed);
3372         lastParsed=checkRound(df, iValue+smallIncrement, lastParsed);
3373     }
3374 }
3375 
checkRound(DecimalFormat* df, double iValue, double lastParsed)3376 double NumberFormatTest::checkRound(DecimalFormat* df, double iValue, double lastParsed) {
3377     UErrorCode status=U_ZERO_ERROR;
3378     UnicodeString formattedDecimal;
3379     double parsed;
3380     Formattable result;
3381     df->format(iValue, formattedDecimal, status);
3382 
3383     if (U_FAILURE(status)) {
3384         errln("Error formatting number.");
3385     }
3386 
3387     df->parse(formattedDecimal, result, status);
3388 
3389     if (U_FAILURE(status)) {
3390         errln("Error parsing number.");
3391     }
3392 
3393     parsed=result.getDouble();
3394 
3395     if (lastParsed>parsed) {
3396         errln("Rounding wrong direction! %d > %d", lastParsed, parsed);
3397     }
3398 
3399     return lastParsed;
3400 }
3401 
TestNonpositiveMultiplier()3402 void NumberFormatTest::TestNonpositiveMultiplier() {
3403     UErrorCode status = U_ZERO_ERROR;
3404     DecimalFormatSymbols US(Locale::getUS(), status);
3405     CHECK(status, "DecimalFormatSymbols constructor");
3406     DecimalFormat df(UnicodeString("0"), US, status);
3407     CHECK(status, "DecimalFormat(0)");
3408 
3409     // test zero multiplier
3410 
3411     int32_t mult = df.getMultiplier();
3412     df.setMultiplier(0);
3413     if (df.getMultiplier() != mult) {
3414         errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
3415     }
3416 
3417     // test negative multiplier
3418 
3419     df.setMultiplier(-1);
3420     if (df.getMultiplier() != -1) {
3421         errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
3422         return;
3423     }
3424 
3425     expect(df, "1122.123", -1122.123);
3426     expect(df, "-1122.123", 1122.123);
3427     expect(df, "1.2", -1.2);
3428     expect(df, "-1.2", 1.2);
3429 
3430     // Note:  the tests with the final parameter of false will not round trip.
3431     //        The initial numeric value will format correctly, after the multiplier.
3432     //        Parsing the formatted text will be out-of-range for an int64, however.
3433     //        The expect() function could be modified to detect this and fall back
3434     //        to looking at the decimal parsed value, but it doesn't.
3435     expect(df, U_INT64_MIN,    "9223372036854775808", false);
3436     expect(df, U_INT64_MIN+1,  "9223372036854775807");
3437     expect(df, (int64_t)-123,                  "123");
3438     expect(df, (int64_t)123,                  "-123");
3439     expect(df, U_INT64_MAX-1, "-9223372036854775806");
3440     expect(df, U_INT64_MAX,   "-9223372036854775807");
3441 
3442     df.setMultiplier(-2);
3443     expect(df, -(U_INT64_MIN/2)-1, "-9223372036854775806");
3444     expect(df, -(U_INT64_MIN/2),   "-9223372036854775808");
3445     expect(df, -(U_INT64_MIN/2)+1, "-9223372036854775810", false);
3446 
3447     df.setMultiplier(-7);
3448     expect(df, -(U_INT64_MAX/7)-1, "9223372036854775814", false);
3449     expect(df, -(U_INT64_MAX/7),   "9223372036854775807");
3450     expect(df, -(U_INT64_MAX/7)+1, "9223372036854775800");
3451 
3452     // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
3453     // (right now the big numbers get turned into doubles and lose tons of accuracy)
3454     //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
3455     //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
3456     //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
3457     //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
3458 
3459     // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
3460     //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3461     //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3462     //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3463     //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3464 }
3465 
3466 typedef struct {
3467     const char * stringToParse;
3468     int          parsedPos;
3469     int          errorIndex;
3470     UBool        lenient;
3471 } TestSpaceParsingItem;
3472 
3473 void
TestSpaceParsing()3474 NumberFormatTest::TestSpaceParsing() {
3475     // the data are:
3476     // the string to be parsed, parsed position, parsed error index
3477     const TestSpaceParsingItem DATA[] = {
3478         {"$124",           4, -1, false},
3479         {"$124 $124",      4, -1, false},
3480         {"$124 ",          4, -1, false},
3481         {"$ 124 ",         0,  1, false},
3482         {"$\\u00A0124 ",   5, -1, false},
3483         {" $ 124 ",        0,  0, false},
3484         {"124$",           0,  4, false},
3485         {"124 $",          0,  3, false},
3486         {"$124",           4, -1, true},
3487         {"$124 $124",      4, -1, true},
3488         {"$124 ",          4, -1, true},
3489         {"$ 124 ",         5, -1, true},
3490         {"$\\u00A0124 ",   5, -1, true},
3491         {" $ 124 ",        6, -1, true},
3492         {"124$",           4, -1, true},
3493         {"124$",           4, -1, true},
3494         {"124 $",          5, -1, true},
3495         {"124 $",          5, -1, true},
3496     };
3497     UErrorCode status = U_ZERO_ERROR;
3498     Locale locale("en_US");
3499     NumberFormat* foo = NumberFormat::createCurrencyInstance(locale, status);
3500 
3501     if (U_FAILURE(status)) {
3502         delete foo;
3503         return;
3504     }
3505     for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3506         ParsePosition parsePosition(0);
3507         UnicodeString stringToBeParsed = ctou(DATA[i].stringToParse);
3508         int parsedPosition = DATA[i].parsedPos;
3509         int errorIndex = DATA[i].errorIndex;
3510         foo->setLenient(DATA[i].lenient);
3511         Formattable result;
3512         foo->parse(stringToBeParsed, result, parsePosition);
3513         logln("Parsing: " + stringToBeParsed);
3514         if (parsePosition.getIndex() != parsedPosition ||
3515             parsePosition.getErrorIndex() != errorIndex) {
3516             errln("FAILED parse " + stringToBeParsed + "; lenient: " + DATA[i].lenient + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
3517         }
3518         if (parsePosition.getErrorIndex() == -1 &&
3519             result.getType() == Formattable::kLong &&
3520             result.getLong() != 124) {
3521             errln("FAILED parse " + stringToBeParsed + "; wrong number, expect: 124, got " + result.getLong());
3522         }
3523     }
3524     delete foo;
3525 }
3526 
3527 /**
3528  * Test using various numbering systems and numbering system keyword.
3529  */
3530 typedef struct {
3531     const char *localeName;
3532     double      value;
3533     UBool        isRBNF;
3534     const char *expectedResult;
3535 } TestNumberingSystemItem;
3536 
TestNumberingSystems()3537 void NumberFormatTest::TestNumberingSystems() {
3538 
3539     const TestNumberingSystemItem DATA[] = {
3540         { "en_US@numbers=thai", 1234.567, false, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" },
3541         { "en_US@numbers=hebr", 5678.0, true, "\\u05D4\\u05F3\\u05EA\\u05E8\\u05E2\\u05F4\\u05D7" },
3542         { "en_US@numbers=arabext", 1234.567, false, "\\u06F1\\u066c\\u06F2\\u06F3\\u06F4\\u066b\\u06F5\\u06F6\\u06F7" },
3543         { "ar_EG", 1234.567, false, "\\u0661\\u066C\\u0662\\u0663\\u0664\\u066b\\u0665\\u0666\\u0667" },
3544         { "th_TH@numbers=traditional", 1234.567, false, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" }, // fall back to native per TR35
3545         { "ar_MA", 1234.567, false, "1.234,567" },
3546         { "en_US@numbers=hanidec", 1234.567, false, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3547         { "ta_IN@numbers=native", 1234.567, false, "\\u0BE7,\\u0BE8\\u0BE9\\u0BEA.\\u0BEB\\u0BEC\\u0BED" },
3548         { "ta_IN@numbers=traditional", 1235.0, true, "\\u0BF2\\u0BE8\\u0BF1\\u0BE9\\u0BF0\\u0BEB" },
3549         { "ta_IN@numbers=finance", 1234.567, false, "1,234.567" }, // fall back to default per TR35
3550         { "zh_TW@numbers=native", 1234.567, false, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3551         { "zh_TW@numbers=traditional", 1234.567, true, "\\u4E00\\u5343\\u4E8C\\u767E\\u4E09\\u5341\\u56DB\\u9EDE\\u4E94\\u516D\\u4E03" },
3552         { "zh_TW@numbers=finance", 1234.567, true, "\\u58F9\\u4EDF\\u8CB3\\u4F70\\u53C3\\u62FE\\u8086\\u9EDE\\u4F0D\\u9678\\u67D2" },
3553         { NULL, 0, false, NULL }
3554     };
3555 
3556     UErrorCode ec;
3557 
3558     const TestNumberingSystemItem *item;
3559     for (item = DATA; item->localeName != NULL; item++) {
3560         ec = U_ZERO_ERROR;
3561         Locale loc = Locale::createFromName(item->localeName);
3562 
3563         NumberFormat *origFmt = NumberFormat::createInstance(loc,ec);
3564         if (U_FAILURE(ec)) {
3565             dataerrln("FAIL: getInstance(%s) - %s", item->localeName, u_errorName(ec));
3566             continue;
3567         }
3568         // Clone to test ticket #10682
3569         NumberFormat *fmt = origFmt->clone();
3570         delete origFmt;
3571 
3572 
3573         if (item->isRBNF) {
3574             expect3(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3575         } else {
3576             expect2(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3577         }
3578         delete fmt;
3579     }
3580 
3581 
3582     // Test bogus keyword value
3583     ec = U_ZERO_ERROR;
3584     Locale loc4 = Locale::createFromName("en_US@numbers=foobar");
3585     NumberFormat* fmt4= NumberFormat::createInstance(loc4, ec);
3586     if ( ec != U_UNSUPPORTED_ERROR ) {
3587         errln("FAIL: getInstance(en_US@numbers=foobar) should have returned U_UNSUPPORTED_ERROR");
3588         delete fmt4;
3589     }
3590 
3591     ec = U_ZERO_ERROR;
3592     NumberingSystem *ns = NumberingSystem::createInstance(ec);
3593     if (U_FAILURE(ec)) {
3594         dataerrln("FAIL: NumberingSystem::createInstance(ec); - %s", u_errorName(ec));
3595     }
3596 
3597     if ( ns != NULL ) {
3598         ns->getDynamicClassID();
3599         ns->getStaticClassID();
3600     } else {
3601         errln("FAIL: getInstance() returned NULL.");
3602     }
3603 
3604     NumberingSystem *ns1 = new NumberingSystem(*ns);
3605     if (ns1 == NULL) {
3606         errln("FAIL: NumberSystem copy constructor returned NULL.");
3607     }
3608 
3609     delete ns1;
3610     delete ns;
3611 
3612 }
3613 
3614 
3615 void
TestMultiCurrencySign()3616 NumberFormatTest::TestMultiCurrencySign() {
3617     const char* DATA[][6] = {
3618         // the fields in the following test are:
3619         // locale,
3620         // currency pattern (with negative pattern),
3621         // currency number to be formatted,
3622         // currency format using currency symbol name, such as "$" for USD,
3623         // currency format using currency ISO name, such as "USD",
3624         // currency format using plural name, such as "US dollars".
3625         // for US locale
3626         {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1234.56", "$1,234.56", "USD\\u00A01,234.56", "US dollars\\u00A01,234.56"},
3627         {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD\\u00A01,234.56", "-US dollars\\u00A01,234.56"},
3628         {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD\\u00A01.00", "US dollars\\u00A01.00"},
3629         // for CHINA locale
3630         {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\u00A51,234.56", "CNY\\u00A01,234.56", "\\u4EBA\\u6C11\\u5E01\\u00A01,234.56"},
3631         {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\u00A51,234.56)", "(CNY\\u00A01,234.56)", "(\\u4EBA\\u6C11\\u5E01\\u00A01,234.56)"},
3632         {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\u00A51.00", "CNY\\u00A01.00", "\\u4EBA\\u6C11\\u5E01\\u00A01.00"}
3633     };
3634 
3635     const UChar doubleCurrencySign[] = {0xA4, 0xA4, 0};
3636     UnicodeString doubleCurrencyStr(doubleCurrencySign);
3637     const UChar tripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
3638     UnicodeString tripleCurrencyStr(tripleCurrencySign);
3639 
3640     for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3641         const char* locale = DATA[i][0];
3642         UnicodeString pat = ctou(DATA[i][1]);
3643         double numberToBeFormat = atof(DATA[i][2]);
3644         UErrorCode status = U_ZERO_ERROR;
3645         DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale(locale), status);
3646         if (U_FAILURE(status)) {
3647             delete sym;
3648             continue;
3649         }
3650         for (int j=1; j<=3; ++j) {
3651             // j represents the number of currency sign in the pattern.
3652             if (j == 2) {
3653                 pat = pat.findAndReplace(ctou("\\u00A4"), doubleCurrencyStr);
3654             } else if (j == 3) {
3655                 pat = pat.findAndReplace(ctou("\\u00A4\\u00A4"), tripleCurrencyStr);
3656             }
3657 
3658             DecimalFormat* fmt = new DecimalFormat(pat, new DecimalFormatSymbols(*sym), status);
3659             if (U_FAILURE(status)) {
3660                 errln("FAILED init DecimalFormat ");
3661                 delete fmt;
3662                 continue;
3663             }
3664             UnicodeString s;
3665             ((NumberFormat*) fmt)->format(numberToBeFormat, s);
3666             // DATA[i][3] is the currency format result using a
3667             // single currency sign.
3668             // DATA[i][4] is the currency format result using
3669             // double currency sign.
3670             // DATA[i][5] is the currency format result using
3671             // triple currency sign.
3672             // DATA[i][j+2] is the currency format result using
3673             // 'j' number of currency sign.
3674             UnicodeString currencyFormatResult = ctou(DATA[i][2+j]);
3675             if (s.compare(currencyFormatResult)) {
3676                 errln("FAIL format: Expected " + currencyFormatResult + "; Got " + s);
3677             }
3678             // mix style parsing
3679             for (int k=3; k<=5; ++k) {
3680               // DATA[i][3] is the currency format result using a
3681               // single currency sign.
3682               // DATA[i][4] is the currency format result using
3683               // double currency sign.
3684               // DATA[i][5] is the currency format result using
3685               // triple currency sign.
3686               UnicodeString oneCurrencyFormat = ctou(DATA[i][k]);
3687               UErrorCode status = U_ZERO_ERROR;
3688               Formattable parseRes;
3689               fmt->parse(oneCurrencyFormat, parseRes, status);
3690               if (U_FAILURE(status) ||
3691                   (parseRes.getType() == Formattable::kDouble &&
3692                    parseRes.getDouble() != numberToBeFormat) ||
3693                   (parseRes.getType() == Formattable::kLong &&
3694                    parseRes.getLong() != numberToBeFormat)) {
3695                   errln("FAILED parse " + oneCurrencyFormat + "; (i, j, k): " +
3696                         i + ", " + j + ", " + k);
3697               }
3698             }
3699             delete fmt;
3700         }
3701         delete sym;
3702     }
3703 }
3704 
3705 
3706 void
TestCurrencyFormatForMixParsing()3707 NumberFormatTest::TestCurrencyFormatForMixParsing() {
3708     UErrorCode status = U_ZERO_ERROR;
3709     MeasureFormat* curFmt = MeasureFormat::createCurrencyFormat(Locale("en_US"), status);
3710     if (U_FAILURE(status)) {
3711         delete curFmt;
3712         return;
3713     }
3714     const char* formats[] = {
3715         "$1,234.56",  // string to be parsed
3716         "USD1,234.56",
3717         "US dollars1,234.56",
3718         // "1,234.56 US dollars" // Fails in 62 because currency format is not compatible with pattern.
3719     };
3720     const CurrencyAmount* curramt = NULL;
3721     for (uint32_t i = 0; i < UPRV_LENGTHOF(formats); ++i) {
3722         UnicodeString stringToBeParsed = ctou(formats[i]);
3723         logln(UnicodeString("stringToBeParsed: ") + stringToBeParsed);
3724         Formattable result;
3725         UErrorCode status = U_ZERO_ERROR;
3726         curFmt->parseObject(stringToBeParsed, result, status);
3727         if (U_FAILURE(status)) {
3728           errln("FAIL: measure format parsing: '%s' ec: %s", formats[i], u_errorName(status));
3729         } else if (result.getType() != Formattable::kObject ||
3730             (curramt = dynamic_cast<const CurrencyAmount*>(result.getObject())) == NULL ||
3731             curramt->getNumber().getDouble() != 1234.56 ||
3732             UnicodeString(curramt->getISOCurrency()).compare(ISO_CURRENCY_USD)
3733         ) {
3734             errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number ");
3735             if (curramt->getNumber().getDouble() != 1234.56) {
3736                 errln((UnicodeString)"wong number, expect: 1234.56" + ", got: " + curramt->getNumber().getDouble());
3737             }
3738             if (curramt->getISOCurrency() != ISO_CURRENCY_USD) {
3739                 errln((UnicodeString)"wong currency, expect: USD" + ", got: " + curramt->getISOCurrency());
3740             }
3741         }
3742     }
3743     delete curFmt;
3744 }
3745 
3746 
3747 /** Starting in ICU 62, strict mode is actually strict with currency formats. */
TestMismatchedCurrencyFormatFail()3748 void NumberFormatTest::TestMismatchedCurrencyFormatFail() {
3749     IcuTestErrorCode status(*this, "TestMismatchedCurrencyFormatFail");
3750     LocalPointer<DecimalFormat> df(
3751             dynamic_cast<DecimalFormat*>(DecimalFormat::createCurrencyInstance("en", status)), status);
3752     if (!assertSuccess("createCurrencyInstance() failed.", status, true, __FILE__, __LINE__)) {return;}
3753     UnicodeString pattern;
3754     assertEquals("Test assumes that currency sign is at the beginning",
3755             u"\u00A4#,##0.00",
3756             df->toPattern(pattern));
3757     // Should round-trip on the correct currency format:
3758     expect2(*df, 1.23, u"\u00A41.23");
3759     df->setCurrency(u"EUR", status);
3760     expect2(*df, 1.23, u"\u20AC1.23");
3761     // Should parse with currency in the wrong place in lenient mode
3762     df->setLenient(true);
3763     expect(*df, u"1.23\u20AC", 1.23);
3764     expectParseCurrency(*df, u"EUR", 1.23, "1.23\\u20AC");
3765     // Should NOT parse with currency in the wrong place in STRICT mode
3766     df->setLenient(false);
3767     {
3768         Formattable result;
3769         ErrorCode failStatus;
3770         df->parse(u"1.23\u20AC", result, failStatus);
3771         assertEquals("Should fail to parse", U_INVALID_FORMAT_ERROR, failStatus);
3772     }
3773     {
3774         ParsePosition ppos;
3775         df->parseCurrency(u"1.23\u20AC", ppos);
3776         assertEquals("Should fail to parse currency", 0, ppos.getIndex());
3777     }
3778 }
3779 
3780 
3781 void
TestDecimalFormatCurrencyParse()3782 NumberFormatTest::TestDecimalFormatCurrencyParse() {
3783     // Locale.US
3784     UErrorCode status = U_ZERO_ERROR;
3785     DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale("en_US"), status);
3786     if (U_FAILURE(status)) {
3787         delete sym;
3788         return;
3789     }
3790     UnicodeString pat;
3791     UChar currency = 0x00A4;
3792     // "\xA4#,##0.00;-\xA4#,##0.00"
3793     pat.append(currency).append(currency).append(currency).append("#,##0.00;-").append(currency).append(currency).append(currency).append("#,##0.00");
3794     DecimalFormat* fmt = new DecimalFormat(pat, sym, status);
3795     if (U_FAILURE(status)) {
3796         delete fmt;
3797         errln("failed to new DecimalFormat in TestDecimalFormatCurrencyParse");
3798         return;
3799     }
3800     const char* DATA[][2] = {
3801         // the data are:
3802         // string to be parsed, the parsed result (number)
3803         {"$1.00", "1"},
3804         {"USD1.00", "1"},
3805         {"1.00 US dollar", "1"},
3806         {"$1,234.56", "1234.56"},
3807         {"USD1,234.56", "1234.56"},
3808         {"1,234.56 US dollar", "1234.56"},
3809     };
3810     // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3811     fmt->setLenient(true);
3812     for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3813         UnicodeString stringToBeParsed = ctou(DATA[i][0]);
3814         double parsedResult = atof(DATA[i][1]);
3815         UErrorCode status = U_ZERO_ERROR;
3816         Formattable result;
3817         fmt->parse(stringToBeParsed, result, status);
3818         logln((UnicodeString)"Input: " + stringToBeParsed + "; output: " + result.getDouble(status));
3819         if (U_FAILURE(status) ||
3820             (result.getType() == Formattable::kDouble &&
3821             result.getDouble() != parsedResult) ||
3822             (result.getType() == Formattable::kLong &&
3823             result.getLong() != parsedResult)) {
3824             errln((UnicodeString)"FAIL parse: Expected " + parsedResult);
3825         }
3826     }
3827     delete fmt;
3828 }
3829 
3830 
3831 void
TestCurrencyIsoPluralFormat()3832 NumberFormatTest::TestCurrencyIsoPluralFormat() {
3833     static const char* DATA[][6] = {
3834         // the data are:
3835         // locale,
3836         // currency amount to be formatted,
3837         // currency ISO code to be formatted,
3838         // format result using CURRENCYSTYLE,
3839         // format result using ISOCURRENCYSTYLE,
3840         // format result using PLURALCURRENCYSTYLE,
3841 
3842         {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3843         {"en_US", "1234.56", "USD", "$1,234.56", "USD\\u00A01,234.56", "1,234.56 US dollars"},
3844         {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD\\u00A01,234.56", "-1,234.56 US dollars"},
3845         {"zh_CN", "1", "USD", "US$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7F8E\\u5143"},
3846         {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD\\u00A01,234.56", "1,234.56\\u00A0\\u7F8E\\u5143"},
3847         {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A01.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3848         {"zh_CN", "1234.56", "CNY", "\\u00A51,234.56", "CNY\\u00A01,234.56", "1,234.56\\u00A0\\u4EBA\\u6C11\\u5E01"},
3849         {"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3850         {"ru_RU", "2", "RUB", "2,00\\u00A0\\u20BD", "2,00\\u00A0RUB", "2,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3851         {"ru_RU", "5", "RUB", "5,00\\u00A0\\u20BD", "5,00\\u00A0RUB", "5,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3852         // test locale without currency information
3853         {"root", "-1.23", "USD", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"},
3854         // test choice format
3855         {"es_AR", "1", "INR", "INR\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"},
3856     };
3857     static const UNumberFormatStyle currencyStyles[] = {
3858         UNUM_CURRENCY,
3859         UNUM_CURRENCY_ISO,
3860         UNUM_CURRENCY_PLURAL
3861     };
3862 
3863     for (int32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3864       const char* localeString = DATA[i][0];
3865       double numberToBeFormat = atof(DATA[i][1]);
3866       const char* currencyISOCode = DATA[i][2];
3867       logln(UnicodeString(u"Locale: ") + localeString + "; amount: " + numberToBeFormat);
3868       Locale locale(localeString);
3869       for (int32_t kIndex = 0; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3870         UNumberFormatStyle k = currencyStyles[kIndex];
3871         logln(UnicodeString(u"UNumberFormatStyle: ") + k);
3872         UErrorCode status = U_ZERO_ERROR;
3873         NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3874         if (U_FAILURE(status)) {
3875             delete numFmt;
3876             dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3877             continue;
3878         }
3879         UChar currencyCode[4];
3880         u_charsToUChars(currencyISOCode, currencyCode, 4);
3881         numFmt->setCurrency(currencyCode, status);
3882         if (U_FAILURE(status)) {
3883             delete numFmt;
3884             errln((UnicodeString)"can not set currency:" + currencyISOCode);
3885             continue;
3886         }
3887 
3888         UnicodeString strBuf;
3889         numFmt->format(numberToBeFormat, strBuf);
3890         int resultDataIndex = 3 + kIndex;
3891         // DATA[i][resultDataIndex] is the currency format result
3892         // using 'k' currency style.
3893         UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
3894         if (strBuf.compare(formatResult)) {
3895             errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
3896         }
3897         // test parsing, and test parsing for all currency formats.
3898         // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3899         numFmt->setLenient(true);
3900         for (int j = 3; j < 6; ++j) {
3901             // DATA[i][3] is the currency format result using
3902             // CURRENCYSTYLE formatter.
3903             // DATA[i][4] is the currency format result using
3904             // ISOCURRENCYSTYLE formatter.
3905             // DATA[i][5] is the currency format result using
3906             // PLURALCURRENCYSTYLE formatter.
3907             UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
3908             UErrorCode status = U_ZERO_ERROR;
3909             Formattable parseResult;
3910             numFmt->parse(oneCurrencyFormatResult, parseResult, status);
3911             if (U_FAILURE(status) ||
3912                 (parseResult.getType() == Formattable::kDouble &&
3913                  parseResult.getDouble() != numberToBeFormat) ||
3914                 (parseResult.getType() == Formattable::kLong &&
3915                  parseResult.getLong() != numberToBeFormat)) {
3916                 errln((UnicodeString)"FAIL: getCurrencyFormat of locale " +
3917                       localeString + " failed roundtripping the number");
3918                 if (parseResult.getType() == Formattable::kDouble) {
3919                     errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getDouble());
3920                 } else {
3921                     errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getLong());
3922                 }
3923             }
3924         }
3925         delete numFmt;
3926       }
3927     }
3928 }
3929 
3930 void
TestCurrencyParsing()3931 NumberFormatTest::TestCurrencyParsing() {
3932     static const char* DATA[][6] = {
3933         // the data are:
3934         // locale,
3935         // currency amount to be formatted,
3936         // currency ISO code to be formatted,
3937         // format result using CURRENCYSTYLE,
3938         // format result using ISOCURRENCYSTYLE,
3939         // format result using PLURALCURRENCYSTYLE,
3940         {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3941         {"pa_IN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\u0a2f\\u0a42.\\u0a10\\u0a38. \\u0a21\\u0a3e\\u0a32\\u0a30"},
3942         {"es_AR", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 d\\u00f3lar estadounidense"},
3943         {"ar_EG", "1", "USD", "\\u0661\\u066b\\u0660\\u0660\\u00a0US$", "\\u0661\\u066b\\u0660\\u0660\\u00a0USD", "\\u0661\\u066b\\u0660\\u0660 \\u062f\\u0648\\u0644\\u0627\\u0631 \\u0623\\u0645\\u0631\\u064a\\u0643\\u064a"},
3944         {"fa_CA", "1", "USD", "\\u200e$\\u06f1\\u066b\\u06f0\\u06f0", "\\u200eUSD\\u06f1\\u066b\\u06f0\\u06f0", "\\u06f1\\u066b\\u06f0\\u06f0 \\u062f\\u0644\\u0627\\u0631 \\u0622\\u0645\\u0631\\u06cc\\u06a9\\u0627"},
3945         {"he_IL", "1", "USD", "\\u200f1.00\\u00a0$", "\\u200f1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
3946         {"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 ameri\\u010Dkih dolara"},
3947         {"id_ID", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 Dolar Amerika Serikat"},
3948         {"it_IT", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 dollari statunitensi"},
3949         {"ko_KR", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
3950         {"ja_JP", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7c73\\u30c9\\u30eb"},
3951         {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A001.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3952         {"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3953         {"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3954         {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1 \\u65E5\\u5713"},
3955         {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3956         // ICU 62 requires #parseCurrency() to recognize variants when parsing
3957         // {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3958         {"ru_RU", "1", "RUB", "1,00\\u00A0\\u00A0\\u20BD", "1,00\\u00A0\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"}
3959     };
3960     static const UNumberFormatStyle currencyStyles[] = {
3961         UNUM_CURRENCY,
3962         UNUM_CURRENCY_ISO,
3963         UNUM_CURRENCY_PLURAL
3964     };
3965     static const char* currencyStyleNames[] = {
3966       "UNUM_CURRENCY",
3967       "UNUM_CURRENCY_ISO",
3968       "UNUM_CURRENCY_PLURAL"
3969     };
3970 
3971 #ifdef NUMFMTST_CACHE_DEBUG
3972 int deadloop = 0;
3973 for (;;) {
3974     printf("loop: %d\n", deadloop++);
3975 #endif
3976     for (uint32_t i=0; i< UPRV_LENGTHOF(DATA); ++i) {  /* i = test case #  - should be i=0*/
3977       for (int32_t kIndex = 2; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3978         UNumberFormatStyle k = currencyStyles[kIndex]; /* k = style */
3979         const char* localeString = DATA[i][0];
3980         double numberToBeFormat = atof(DATA[i][1]);
3981         const char* currencyISOCode = DATA[i][2];
3982         Locale locale(localeString);
3983         UErrorCode status = U_ZERO_ERROR;
3984         NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3985         logln("#%d NumberFormat(%s, %s) Currency=%s\n",
3986               i, localeString, currencyStyleNames[kIndex],
3987               currencyISOCode);
3988 
3989         if (U_FAILURE(status)) {
3990             delete numFmt;
3991             dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3992             continue;
3993         }
3994         UChar currencyCode[4];
3995         u_charsToUChars(currencyISOCode, currencyCode, 4);
3996         numFmt->setCurrency(currencyCode, status);
3997         if (U_FAILURE(status)) {
3998             delete numFmt;
3999             errln((UnicodeString)"can not set currency:" + currencyISOCode);
4000             continue;
4001         }
4002 
4003         UnicodeString strBuf;
4004         numFmt->format(numberToBeFormat, strBuf);
4005         int resultDataIndex = 3 + kIndex;
4006         // DATA[i][resultDataIndex] is the currency format result
4007         // using 'k' currency style.
4008         UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
4009         if (strBuf.compare(formatResult)) {
4010             errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
4011         }
4012         // test parsing, and test parsing for all currency formats.
4013         // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
4014         numFmt->setLenient(true);
4015         for (int j = 3; j < 6; ++j) {
4016             // DATA[i][3] is the currency format result using
4017             // CURRENCYSTYLE formatter.
4018             // DATA[i][4] is the currency format result using
4019             // ISOCURRENCYSTYLE formatter.
4020             // DATA[i][5] is the currency format result using
4021             // PLURALCURRENCYSTYLE formatter.
4022             UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
4023             UErrorCode status = U_ZERO_ERROR;
4024             Formattable parseResult;
4025             logln("parse(%s)", DATA[i][j]);
4026             numFmt->parse(oneCurrencyFormatResult, parseResult, status);
4027             if (U_FAILURE(status) ||
4028                 (parseResult.getType() == Formattable::kDouble &&
4029                  parseResult.getDouble() != numberToBeFormat) ||
4030                 (parseResult.getType() == Formattable::kLong &&
4031                  parseResult.getLong() != numberToBeFormat)) {
4032                 errln((UnicodeString)"FAIL: NumberFormat(" + localeString +", " + currencyStyleNames[kIndex] +
4033                       "), Currency="+currencyISOCode+", parse("+DATA[i][j]+") returned error " + (UnicodeString)u_errorName(status)+".  Testcase: data[" + i + "][" + currencyStyleNames[j-3] +"="+j+"]");
4034                 if (parseResult.getType() == Formattable::kDouble) {
4035                     errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (double): " +parseResult.getDouble());
4036                 } else {
4037                     errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (long): " +parseResult.getLong());
4038                 }
4039                 errln((UnicodeString)" round-trip would be: " + strBuf);
4040             }
4041         }
4042         delete numFmt;
4043       }
4044     }
4045 #ifdef NUMFMTST_CACHE_DEBUG
4046 }
4047 #endif
4048 }
4049 
4050 
4051 void
TestParseCurrencyInUCurr()4052 NumberFormatTest::TestParseCurrencyInUCurr() {
4053     const char* DATA[] = {
4054         "1.00 US DOLLAR",  // case in-sensitive
4055         "$1.00",
4056         "USD1.00",
4057         "usd1.00", // case in-sensitive: #13696
4058         "US dollar1.00",
4059         "US dollars1.00",
4060         "$1.00",
4061         "A$1.00",
4062         "ADP1.00",
4063         "ADP1.00",
4064         "AED1.00",
4065         "AED1.00",
4066         "AFA1.00",
4067         "AFA1.00",
4068         "AFN1.00",
4069         "ALL1.00",
4070         "AMD1.00",
4071         "ANG1.00",
4072         "AOA1.00",
4073         "AOK1.00",
4074         "AOK1.00",
4075         "AON1.00",
4076         "AON1.00",
4077         "AOR1.00",
4078         "AOR1.00",
4079         "ARS1.00",
4080         "ARA1.00",
4081         "ARA1.00",
4082         "ARP1.00",
4083         "ARP1.00",
4084         "ARS1.00",
4085         "ATS1.00",
4086         "ATS1.00",
4087         "AUD1.00",
4088         "AWG1.00",
4089         "AZM1.00",
4090         "AZM1.00",
4091         "AZN1.00",
4092         "Afghan Afghani (1927\\u20132002)1.00",
4093         "Afghan afghani (1927\\u20132002)1.00",
4094         "Afghan Afghani1.00",
4095         "Afghan Afghanis1.00",
4096         "Albanian Lek1.00",
4097         "Albanian lek1.00",
4098         "Albanian lek\\u00eb1.00",
4099         "Algerian Dinar1.00",
4100         "Algerian dinar1.00",
4101         "Algerian dinars1.00",
4102         "Andorran Peseta1.00",
4103         "Andorran peseta1.00",
4104         "Andorran pesetas1.00",
4105         "Angolan Kwanza (1977\\u20131991)1.00",
4106         "Angolan Readjusted Kwanza (1995\\u20131999)1.00",
4107         "Angolan Kwanza1.00",
4108         "Angolan New Kwanza (1990\\u20132000)1.00",
4109         "Angolan kwanza (1977\\u20131991)1.00",
4110         "Angolan readjusted kwanza (1995\\u20131999)1.00",
4111         "Angolan kwanza1.00",
4112         "Angolan kwanzas (1977\\u20131991)1.00",
4113         "Angolan readjusted kwanzas (1995\\u20131999)1.00",
4114         "Angolan kwanzas1.00",
4115         "Angolan new kwanza (1990\\u20132000)1.00",
4116         "Angolan new kwanzas (1990\\u20132000)1.00",
4117         "Argentine Austral1.00",
4118         "Argentine Peso (1983\\u20131985)1.00",
4119         "Argentine Peso1.00",
4120         "Argentine austral1.00",
4121         "Argentine australs1.00",
4122         "Argentine peso (1983\\u20131985)1.00",
4123         "Argentine peso1.00",
4124         "Argentine pesos (1983\\u20131985)1.00",
4125         "Argentine pesos1.00",
4126         "Armenian Dram1.00",
4127         "Armenian dram1.00",
4128         "Armenian drams1.00",
4129         "Aruban Florin1.00",
4130         "Aruban florin1.00",
4131         "Australian Dollar1.00",
4132         "Australian dollar1.00",
4133         "Australian dollars1.00",
4134         "Austrian Schilling1.00",
4135         "Austrian schilling1.00",
4136         "Austrian schillings1.00",
4137         "Azerbaijani Manat (1993\\u20132006)1.00",
4138         "Azerbaijani Manat1.00",
4139         "Azerbaijani manat (1993\\u20132006)1.00",
4140         "Azerbaijani manat1.00",
4141         "Azerbaijani manats (1993\\u20132006)1.00",
4142         "Azerbaijani manats1.00",
4143         "BAD1.00",
4144         "BAD1.00",
4145         "BAM1.00",
4146         "BBD1.00",
4147         "BDT1.00",
4148         "BEC1.00",
4149         "BEC1.00",
4150         "BEF1.00",
4151         "BEL1.00",
4152         "BEL1.00",
4153         "BGL1.00",
4154         "BGN1.00",
4155         "BGN1.00",
4156         "BHD1.00",
4157         "BIF1.00",
4158         "BMD1.00",
4159         "BND1.00",
4160         "BOB1.00",
4161         "BOP1.00",
4162         "BOP1.00",
4163         "BOV1.00",
4164         "BOV1.00",
4165         "BRB1.00",
4166         "BRB1.00",
4167         "BRC1.00",
4168         "BRC1.00",
4169         "BRE1.00",
4170         "BRE1.00",
4171         "BRL1.00",
4172         "BRN1.00",
4173         "BRN1.00",
4174         "BRR1.00",
4175         "BRR1.00",
4176         "BSD1.00",
4177         "BSD1.00",
4178         "BTN1.00",
4179         "BUK1.00",
4180         "BUK1.00",
4181         "BWP1.00",
4182         "BYB1.00",
4183         "BYB1.00",
4184         "BYR1.00",
4185         "BZD1.00",
4186         "Bahamian Dollar1.00",
4187         "Bahamian dollar1.00",
4188         "Bahamian dollars1.00",
4189         "Bahraini Dinar1.00",
4190         "Bahraini dinar1.00",
4191         "Bahraini dinars1.00",
4192         "Bangladeshi Taka1.00",
4193         "Bangladeshi taka1.00",
4194         "Bangladeshi takas1.00",
4195         "Barbadian Dollar1.00",
4196         "Barbadian dollar1.00",
4197         "Barbadian dollars1.00",
4198         "Belarusian Ruble (1994\\u20131999)1.00",
4199         "Belarusian Ruble1.00",
4200         "Belarusian ruble (1994\\u20131999)1.00",
4201         "Belarusian rubles (1994\\u20131999)1.00",
4202         "Belarusian ruble1.00",
4203         "Belarusian rubles1.00",
4204         "Belgian Franc (convertible)1.00",
4205         "Belgian Franc (financial)1.00",
4206         "Belgian Franc1.00",
4207         "Belgian franc (convertible)1.00",
4208         "Belgian franc (financial)1.00",
4209         "Belgian franc1.00",
4210         "Belgian francs (convertible)1.00",
4211         "Belgian francs (financial)1.00",
4212         "Belgian francs1.00",
4213         "Belize Dollar1.00",
4214         "Belize dollar1.00",
4215         "Belize dollars1.00",
4216         "Bermudan Dollar1.00",
4217         "Bermudan dollar1.00",
4218         "Bermudan dollars1.00",
4219         "Bhutanese Ngultrum1.00",
4220         "Bhutanese ngultrum1.00",
4221         "Bhutanese ngultrums1.00",
4222         "Bolivian Mvdol1.00",
4223         "Bolivian Peso1.00",
4224         "Bolivian mvdol1.00",
4225         "Bolivian mvdols1.00",
4226         "Bolivian peso1.00",
4227         "Bolivian pesos1.00",
4228         "Bolivian Boliviano1.00",
4229         "Bolivian Boliviano1.00",
4230         "Bolivian Bolivianos1.00",
4231         "Bosnia-Herzegovina Convertible Mark1.00",
4232         "Bosnia-Herzegovina Dinar (1992\\u20131994)1.00",
4233         "Bosnia-Herzegovina convertible mark1.00",
4234         "Bosnia-Herzegovina convertible marks1.00",
4235         "Bosnia-Herzegovina dinar (1992\\u20131994)1.00",
4236         "Bosnia-Herzegovina dinars (1992\\u20131994)1.00",
4237         "Botswanan Pula1.00",
4238         "Botswanan pula1.00",
4239         "Botswanan pulas1.00",
4240         "Brazilian New Cruzado (1989\\u20131990)1.00",
4241         "Brazilian Cruzado (1986\\u20131989)1.00",
4242         "Brazilian Cruzeiro (1990\\u20131993)1.00",
4243         "Brazilian New Cruzeiro (1967\\u20131986)1.00",
4244         "Brazilian Cruzeiro (1993\\u20131994)1.00",
4245         "Brazilian Real1.00",
4246         "Brazilian new cruzado (1989\\u20131990)1.00",
4247         "Brazilian new cruzados (1989\\u20131990)1.00",
4248         "Brazilian cruzado (1986\\u20131989)1.00",
4249         "Brazilian cruzados (1986\\u20131989)1.00",
4250         "Brazilian cruzeiro (1990\\u20131993)1.00",
4251         "Brazilian new cruzeiro (1967\\u20131986)1.00",
4252         "Brazilian cruzeiro (1993\\u20131994)1.00",
4253         "Brazilian cruzeiros (1990\\u20131993)1.00",
4254         "Brazilian new cruzeiros (1967\\u20131986)1.00",
4255         "Brazilian cruzeiros (1993\\u20131994)1.00",
4256         "Brazilian real1.00",
4257         "Brazilian reals1.00",
4258         "British Pound1.00",
4259         "British pound1.00",
4260         "British pounds1.00",
4261         "Brunei Dollar1.00",
4262         "Brunei dollar1.00",
4263         "Brunei dollars1.00",
4264         "Bulgarian Hard Lev1.00",
4265         "Bulgarian Lev1.00",
4266         "Bulgarian Leva1.00",
4267         "Bulgarian hard lev1.00",
4268         "Bulgarian hard leva1.00",
4269         "Bulgarian lev1.00",
4270         "Burmese Kyat1.00",
4271         "Burmese kyat1.00",
4272         "Burmese kyats1.00",
4273         "Burundian Franc1.00",
4274         "Burundian franc1.00",
4275         "Burundian francs1.00",
4276         "CA$1.00",
4277         "CAD1.00",
4278         "CDF1.00",
4279         "CDF1.00",
4280         "West African CFA Franc1.00",
4281         "Central African CFA Franc1.00",
4282         "West African CFA franc1.00",
4283         "Central African CFA franc1.00",
4284         "West African CFA francs1.00",
4285         "Central African CFA francs1.00",
4286         "CFP Franc1.00",
4287         "CFP franc1.00",
4288         "CFP francs1.00",
4289         "CFPF1.00",
4290         "CHE1.00",
4291         "CHE1.00",
4292         "CHF1.00",
4293         "CHW1.00",
4294         "CHW1.00",
4295         "CLF1.00",
4296         "CLF1.00",
4297         "CLP1.00",
4298         "CNY1.00",
4299         "COP1.00",
4300         "COU1.00",
4301         "COU1.00",
4302         "CRC1.00",
4303         "CSD1.00",
4304         "CSD1.00",
4305         "CSK1.00",
4306         "CSK1.00",
4307         "CUP1.00",
4308         "CUP1.00",
4309         "CVE1.00",
4310         "CYP1.00",
4311         "CZK1.00",
4312         "Cambodian Riel1.00",
4313         "Cambodian riel1.00",
4314         "Cambodian riels1.00",
4315         "Canadian Dollar1.00",
4316         "Canadian dollar1.00",
4317         "Canadian dollars1.00",
4318         "Cape Verdean Escudo1.00",
4319         "Cape Verdean escudo1.00",
4320         "Cape Verdean escudos1.00",
4321         "Cayman Islands Dollar1.00",
4322         "Cayman Islands dollar1.00",
4323         "Cayman Islands dollars1.00",
4324         "Chilean Peso1.00",
4325         "Chilean Unit of Account (UF)1.00",
4326         "Chilean peso1.00",
4327         "Chilean pesos1.00",
4328         "Chilean unit of account (UF)1.00",
4329         "Chilean units of account (UF)1.00",
4330         "Chinese Yuan1.00",
4331         "Chinese yuan1.00",
4332         "Colombian Peso1.00",
4333         "Colombian peso1.00",
4334         "Colombian pesos1.00",
4335         "Comorian Franc1.00",
4336         "Comorian franc1.00",
4337         "Comorian francs1.00",
4338         "Congolese Franc1.00",
4339         "Congolese franc1.00",
4340         "Congolese francs1.00",
4341         "Costa Rican Col\\u00f3n1.00",
4342         "Costa Rican col\\u00f3n1.00",
4343         "Costa Rican col\\u00f3ns1.00",
4344         "Croatian Dinar1.00",
4345         "Croatian Kuna1.00",
4346         "Croatian dinar1.00",
4347         "Croatian dinars1.00",
4348         "Croatian kuna1.00",
4349         "Croatian kunas1.00",
4350         "Cuban Peso1.00",
4351         "Cuban peso1.00",
4352         "Cuban pesos1.00",
4353         "Cypriot Pound1.00",
4354         "Cypriot pound1.00",
4355         "Cypriot pounds1.00",
4356         "Czech Koruna1.00",
4357         "Czech koruna1.00",
4358         "Czech korunas1.00",
4359         "Czechoslovak Hard Koruna1.00",
4360         "Czechoslovak hard koruna1.00",
4361         "Czechoslovak hard korunas1.00",
4362         "DDM1.00",
4363         "DDM1.00",
4364         "DEM1.00",
4365         "DEM1.00",
4366         "DJF1.00",
4367         "DKK1.00",
4368         "DOP1.00",
4369         "DZD1.00",
4370         "Danish Krone1.00",
4371         "Danish krone1.00",
4372         "Danish kroner1.00",
4373         "German Mark1.00",
4374         "German mark1.00",
4375         "German marks1.00",
4376         "Djiboutian Franc1.00",
4377         "Djiboutian franc1.00",
4378         "Djiboutian francs1.00",
4379         "Dominican Peso1.00",
4380         "Dominican peso1.00",
4381         "Dominican pesos1.00",
4382         "EC$1.00",
4383         "ECS1.00",
4384         "ECS1.00",
4385         "ECV1.00",
4386         "ECV1.00",
4387         "EEK1.00",
4388         "EEK1.00",
4389         "EGP1.00",
4390         "EGP1.00",
4391         "ERN1.00",
4392         "ERN1.00",
4393         "ESA1.00",
4394         "ESA1.00",
4395         "ESB1.00",
4396         "ESB1.00",
4397         "ESP1.00",
4398         "ETB1.00",
4399         "EUR1.00",
4400         "East Caribbean Dollar1.00",
4401         "East Caribbean dollar1.00",
4402         "East Caribbean dollars1.00",
4403         "East German Mark1.00",
4404         "East German mark1.00",
4405         "East German marks1.00",
4406         "Ecuadorian Sucre1.00",
4407         "Ecuadorian Unit of Constant Value1.00",
4408         "Ecuadorian sucre1.00",
4409         "Ecuadorian sucres1.00",
4410         "Ecuadorian unit of constant value1.00",
4411         "Ecuadorian units of constant value1.00",
4412         "Egyptian Pound1.00",
4413         "Egyptian pound1.00",
4414         "Egyptian pounds1.00",
4415         "Salvadoran Col\\u00f3n1.00",
4416         "Salvadoran col\\u00f3n1.00",
4417         "Salvadoran colones1.00",
4418         "Equatorial Guinean Ekwele1.00",
4419         "Equatorial Guinean ekwele1.00",
4420         "Eritrean Nakfa1.00",
4421         "Eritrean nakfa1.00",
4422         "Eritrean nakfas1.00",
4423         "Estonian Kroon1.00",
4424         "Estonian kroon1.00",
4425         "Estonian kroons1.00",
4426         "Ethiopian Birr1.00",
4427         "Ethiopian birr1.00",
4428         "Ethiopian birrs1.00",
4429         "Euro1.00",
4430         "European Composite Unit1.00",
4431         "European Currency Unit1.00",
4432         "European Monetary Unit1.00",
4433         "European Unit of Account (XBC)1.00",
4434         "European Unit of Account (XBD)1.00",
4435         "European composite unit1.00",
4436         "European composite units1.00",
4437         "European currency unit1.00",
4438         "European currency units1.00",
4439         "European monetary unit1.00",
4440         "European monetary units1.00",
4441         "European unit of account (XBC)1.00",
4442         "European unit of account (XBD)1.00",
4443         "European units of account (XBC)1.00",
4444         "European units of account (XBD)1.00",
4445         "FIM1.00",
4446         "FIM1.00",
4447         "FJD1.00",
4448         "FKP1.00",
4449         "FKP1.00",
4450         "FRF1.00",
4451         "FRF1.00",
4452         "Falkland Islands Pound1.00",
4453         "Falkland Islands pound1.00",
4454         "Falkland Islands pounds1.00",
4455         "Fijian Dollar1.00",
4456         "Fijian dollar1.00",
4457         "Fijian dollars1.00",
4458         "Finnish Markka1.00",
4459         "Finnish markka1.00",
4460         "Finnish markkas1.00",
4461         "CHF1.00",
4462         "French Franc1.00",
4463         "French Gold Franc1.00",
4464         "French UIC-Franc1.00",
4465         "French UIC-franc1.00",
4466         "French UIC-francs1.00",
4467         "French franc1.00",
4468         "French francs1.00",
4469         "French gold franc1.00",
4470         "French gold francs1.00",
4471         "GBP1.00",
4472         "GEK1.00",
4473         "GEK1.00",
4474         "GEL1.00",
4475         "GHC1.00",
4476         "GHC1.00",
4477         "GHS1.00",
4478         "GIP1.00",
4479         "GIP1.00",
4480         "GMD1.00",
4481         "GMD1.00",
4482         "GNF1.00",
4483         "GNS1.00",
4484         "GNS1.00",
4485         "GQE1.00",
4486         "GQE1.00",
4487         "GRD1.00",
4488         "GRD1.00",
4489         "GTQ1.00",
4490         "GWE1.00",
4491         "GWE1.00",
4492         "GWP1.00",
4493         "GWP1.00",
4494         "GYD1.00",
4495         "Gambian Dalasi1.00",
4496         "Gambian dalasi1.00",
4497         "Gambian dalasis1.00",
4498         "Georgian Kupon Larit1.00",
4499         "Georgian Lari1.00",
4500         "Georgian kupon larit1.00",
4501         "Georgian kupon larits1.00",
4502         "Georgian lari1.00",
4503         "Georgian laris1.00",
4504         "Ghanaian Cedi (1979\\u20132007)1.00",
4505         "Ghanaian Cedi1.00",
4506         "Ghanaian cedi (1979\\u20132007)1.00",
4507         "Ghanaian cedi1.00",
4508         "Ghanaian cedis (1979\\u20132007)1.00",
4509         "Ghanaian cedis1.00",
4510         "Gibraltar Pound1.00",
4511         "Gibraltar pound1.00",
4512         "Gibraltar pounds1.00",
4513         "Gold1.00",
4514         "Gold1.00",
4515         "Greek Drachma1.00",
4516         "Greek drachma1.00",
4517         "Greek drachmas1.00",
4518         "Guatemalan Quetzal1.00",
4519         "Guatemalan quetzal1.00",
4520         "Guatemalan quetzals1.00",
4521         "Guinean Franc1.00",
4522         "Guinean Syli1.00",
4523         "Guinean franc1.00",
4524         "Guinean francs1.00",
4525         "Guinean syli1.00",
4526         "Guinean sylis1.00",
4527         "Guinea-Bissau Peso1.00",
4528         "Guinea-Bissau peso1.00",
4529         "Guinea-Bissau pesos1.00",
4530         "Guyanaese Dollar1.00",
4531         "Guyanaese dollar1.00",
4532         "Guyanaese dollars1.00",
4533         "HK$1.00",
4534         "HKD1.00",
4535         "HNL1.00",
4536         "HRD1.00",
4537         "HRD1.00",
4538         "HRK1.00",
4539         "HRK1.00",
4540         "HTG1.00",
4541         "HTG1.00",
4542         "HUF1.00",
4543         "Haitian Gourde1.00",
4544         "Haitian gourde1.00",
4545         "Haitian gourdes1.00",
4546         "Honduran Lempira1.00",
4547         "Honduran lempira1.00",
4548         "Honduran lempiras1.00",
4549         "Hong Kong Dollar1.00",
4550         "Hong Kong dollar1.00",
4551         "Hong Kong dollars1.00",
4552         "Hungarian Forint1.00",
4553         "Hungarian forint1.00",
4554         "Hungarian forints1.00",
4555         "IDR1.00",
4556         "IEP1.00",
4557         "ILP1.00",
4558         "ILP1.00",
4559         "ILS1.00",
4560         "INR1.00",
4561         "IQD1.00",
4562         "IRR1.00",
4563         "ISK1.00",
4564         "ISK1.00",
4565         "ITL1.00",
4566         "Icelandic Kr\\u00f3na1.00",
4567         "Icelandic kr\\u00f3na1.00",
4568         "Icelandic kr\\u00f3nur1.00",
4569         "Indian Rupee1.00",
4570         "Indian rupee1.00",
4571         "Indian rupees1.00",
4572         "Indonesian Rupiah1.00",
4573         "Indonesian rupiah1.00",
4574         "Indonesian rupiahs1.00",
4575         "Iranian Rial1.00",
4576         "Iranian rial1.00",
4577         "Iranian rials1.00",
4578         "Iraqi Dinar1.00",
4579         "Iraqi dinar1.00",
4580         "Iraqi dinars1.00",
4581         "Irish Pound1.00",
4582         "Irish pound1.00",
4583         "Irish pounds1.00",
4584         "Israeli Pound1.00",
4585         "Israeli new shekel1.00",
4586         "Israeli pound1.00",
4587         "Israeli pounds1.00",
4588         "Italian Lira1.00",
4589         "Italian lira1.00",
4590         "Italian liras1.00",
4591         "JMD1.00",
4592         "JOD1.00",
4593         "JPY1.00",
4594         "Jamaican Dollar1.00",
4595         "Jamaican dollar1.00",
4596         "Jamaican dollars1.00",
4597         "Japanese Yen1.00",
4598         "Japanese yen1.00",
4599         "Jordanian Dinar1.00",
4600         "Jordanian dinar1.00",
4601         "Jordanian dinars1.00",
4602         "KES1.00",
4603         "KGS1.00",
4604         "KHR1.00",
4605         "KMF1.00",
4606         "KPW1.00",
4607         "KPW1.00",
4608         "KRW1.00",
4609         "KWD1.00",
4610         "KYD1.00",
4611         "KYD1.00",
4612         "KZT1.00",
4613         "Kazakhstani Tenge1.00",
4614         "Kazakhstani tenge1.00",
4615         "Kazakhstani tenges1.00",
4616         "Kenyan Shilling1.00",
4617         "Kenyan shilling1.00",
4618         "Kenyan shillings1.00",
4619         "Kuwaiti Dinar1.00",
4620         "Kuwaiti dinar1.00",
4621         "Kuwaiti dinars1.00",
4622         "Kyrgystani Som1.00",
4623         "Kyrgystani som1.00",
4624         "Kyrgystani soms1.00",
4625         "HNL1.00",
4626         "LAK1.00",
4627         "LAK1.00",
4628         "LBP1.00",
4629         "LKR1.00",
4630         "LRD1.00",
4631         "LRD1.00",
4632         "LSL1.00",
4633         "LTL1.00",
4634         "LTL1.00",
4635         "LTT1.00",
4636         "LTT1.00",
4637         "LUC1.00",
4638         "LUC1.00",
4639         "LUF1.00",
4640         "LUF1.00",
4641         "LUL1.00",
4642         "LUL1.00",
4643         "LVL1.00",
4644         "LVL1.00",
4645         "LVR1.00",
4646         "LVR1.00",
4647         "LYD1.00",
4648         "Laotian Kip1.00",
4649         "Laotian kip1.00",
4650         "Laotian kips1.00",
4651         "Latvian Lats1.00",
4652         "Latvian Ruble1.00",
4653         "Latvian lats1.00",
4654         "Latvian lati1.00",
4655         "Latvian ruble1.00",
4656         "Latvian rubles1.00",
4657         "Lebanese Pound1.00",
4658         "Lebanese pound1.00",
4659         "Lebanese pounds1.00",
4660         "Lesotho Loti1.00",
4661         "Lesotho loti1.00",
4662         "Lesotho lotis1.00",
4663         "Liberian Dollar1.00",
4664         "Liberian dollar1.00",
4665         "Liberian dollars1.00",
4666         "Libyan Dinar1.00",
4667         "Libyan dinar1.00",
4668         "Libyan dinars1.00",
4669         "Lithuanian Litas1.00",
4670         "Lithuanian Talonas1.00",
4671         "Lithuanian litas1.00",
4672         "Lithuanian litai1.00",
4673         "Lithuanian talonas1.00",
4674         "Lithuanian talonases1.00",
4675         "Luxembourgian Convertible Franc1.00",
4676         "Luxembourg Financial Franc1.00",
4677         "Luxembourgian Franc1.00",
4678         "Luxembourgian convertible franc1.00",
4679         "Luxembourgian convertible francs1.00",
4680         "Luxembourg financial franc1.00",
4681         "Luxembourg financial francs1.00",
4682         "Luxembourgian franc1.00",
4683         "Luxembourgian francs1.00",
4684         "MAD1.00",
4685         "MAD1.00",
4686         "MAF1.00",
4687         "MAF1.00",
4688         "MDL1.00",
4689         "MDL1.00",
4690         "MX$1.00",
4691         "MGA1.00",
4692         "MGA1.00",
4693         "MGF1.00",
4694         "MGF1.00",
4695         "MKD1.00",
4696         "MLF1.00",
4697         "MLF1.00",
4698         "MMK1.00",
4699         "MMK1.00",
4700         "MNT1.00",
4701         "MOP1.00",
4702         "MOP1.00",
4703         "MRO1.00",
4704         "MTL1.00",
4705         "MTP1.00",
4706         "MTP1.00",
4707         "MUR1.00",
4708         "MUR1.00",
4709         "MVR1.00",
4710         "MVR1.00",
4711         "MWK1.00",
4712         "MXN1.00",
4713         "MXP1.00",
4714         "MXP1.00",
4715         "MXV1.00",
4716         "MXV1.00",
4717         "MYR1.00",
4718         "MZE1.00",
4719         "MZE1.00",
4720         "MZM1.00",
4721         "MZN1.00",
4722         "Macanese Pataca1.00",
4723         "Macanese pataca1.00",
4724         "Macanese patacas1.00",
4725         "Macedonian Denar1.00",
4726         "Macedonian denar1.00",
4727         "Macedonian denari1.00",
4728         "Malagasy Ariaries1.00",
4729         "Malagasy Ariary1.00",
4730         "Malagasy Ariary1.00",
4731         "Malagasy Franc1.00",
4732         "Malagasy franc1.00",
4733         "Malagasy francs1.00",
4734         "Malawian Kwacha1.00",
4735         "Malawian Kwacha1.00",
4736         "Malawian Kwachas1.00",
4737         "Malaysian Ringgit1.00",
4738         "Malaysian ringgit1.00",
4739         "Malaysian ringgits1.00",
4740         "Maldivian Rufiyaa1.00",
4741         "Maldivian rufiyaa1.00",
4742         "Maldivian rufiyaas1.00",
4743         "Malian Franc1.00",
4744         "Malian franc1.00",
4745         "Malian francs1.00",
4746         "Maltese Lira1.00",
4747         "Maltese Pound1.00",
4748         "Maltese lira1.00",
4749         "Maltese lira1.00",
4750         "Maltese pound1.00",
4751         "Maltese pounds1.00",
4752         "Mauritanian Ouguiya1.00",
4753         "Mauritanian ouguiya1.00",
4754         "Mauritanian ouguiyas1.00",
4755         "Mauritian Rupee1.00",
4756         "Mauritian rupee1.00",
4757         "Mauritian rupees1.00",
4758         "Mexican Peso1.00",
4759         "Mexican Silver Peso (1861\\u20131992)1.00",
4760         "Mexican Investment Unit1.00",
4761         "Mexican peso1.00",
4762         "Mexican pesos1.00",
4763         "Mexican silver peso (1861\\u20131992)1.00",
4764         "Mexican silver pesos (1861\\u20131992)1.00",
4765         "Mexican investment unit1.00",
4766         "Mexican investment units1.00",
4767         "Moldovan Leu1.00",
4768         "Moldovan leu1.00",
4769         "Moldovan lei1.00",
4770         "Mongolian Tugrik1.00",
4771         "Mongolian tugrik1.00",
4772         "Mongolian tugriks1.00",
4773         "Moroccan Dirham1.00",
4774         "Moroccan Franc1.00",
4775         "Moroccan dirham1.00",
4776         "Moroccan dirhams1.00",
4777         "Moroccan franc1.00",
4778         "Moroccan francs1.00",
4779         "Mozambican Escudo1.00",
4780         "Mozambican Metical1.00",
4781         "Mozambican escudo1.00",
4782         "Mozambican escudos1.00",
4783         "Mozambican metical1.00",
4784         "Mozambican meticals1.00",
4785         "Myanmar Kyat1.00",
4786         "Myanmar kyat1.00",
4787         "Myanmar kyats1.00",
4788         "NAD1.00",
4789         "NGN1.00",
4790         "NIC1.00",
4791         "NIO1.00",
4792         "NIO1.00",
4793         "NLG1.00",
4794         "NLG1.00",
4795         "NOK1.00",
4796         "NPR1.00",
4797         "NT$1.00",
4798         "NZ$1.00",
4799         "NZD1.00",
4800         "Namibian Dollar1.00",
4801         "Namibian dollar1.00",
4802         "Namibian dollars1.00",
4803         "Nepalese Rupee1.00",
4804         "Nepalese rupee1.00",
4805         "Nepalese rupees1.00",
4806         "Netherlands Antillean Guilder1.00",
4807         "Netherlands Antillean guilder1.00",
4808         "Netherlands Antillean guilders1.00",
4809         "Dutch Guilder1.00",
4810         "Dutch guilder1.00",
4811         "Dutch guilders1.00",
4812         "Israeli New Shekel1.00",
4813         "Israeli New Shekels1.00",
4814         "New Zealand Dollar1.00",
4815         "New Zealand dollar1.00",
4816         "New Zealand dollars1.00",
4817         "Nicaraguan C\\u00f3rdoba1.00",
4818         "Nicaraguan C\\u00f3rdoba (1988\\u20131991)1.00",
4819         "Nicaraguan c\\u00f3rdoba1.00",
4820         "Nicaraguan c\\u00f3rdobas1.00",
4821         "Nicaraguan c\\u00f3rdoba (1988\\u20131991)1.00",
4822         "Nicaraguan c\\u00f3rdobas (1988\\u20131991)1.00",
4823         "Nigerian Naira1.00",
4824         "Nigerian naira1.00",
4825         "Nigerian nairas1.00",
4826         "North Korean Won1.00",
4827         "North Korean won1.00",
4828         "North Korean won1.00",
4829         "Norwegian Krone1.00",
4830         "Norwegian krone1.00",
4831         "Norwegian kroner1.00",
4832         "OMR1.00",
4833         "Mozambican Metical (1980\\u20132006)1.00",
4834         "Mozambican metical (1980\\u20132006)1.00",
4835         "Mozambican meticals (1980\\u20132006)1.00",
4836         "Romanian Lei (1952\\u20132006)1.00",
4837         "Romanian Leu (1952\\u20132006)1.00",
4838         "Romanian leu (1952\\u20132006)1.00",
4839         "Serbian Dinar (2002\\u20132006)1.00",
4840         "Serbian dinar (2002\\u20132006)1.00",
4841         "Serbian dinars (2002\\u20132006)1.00",
4842         "Sudanese Dinar (1992\\u20132007)1.00",
4843         "Sudanese Pound (1957\\u20131998)1.00",
4844         "Sudanese dinar (1992\\u20132007)1.00",
4845         "Sudanese dinars (1992\\u20132007)1.00",
4846         "Sudanese pound (1957\\u20131998)1.00",
4847         "Sudanese pounds (1957\\u20131998)1.00",
4848         "Turkish Lira (1922\\u20132005)1.00",
4849         "Turkish Lira (1922\\u20132005)1.00",
4850         "Omani Rial1.00",
4851         "Omani rial1.00",
4852         "Omani rials1.00",
4853         "PAB1.00",
4854         "PAB1.00",
4855         "PEI1.00",
4856         "PEI1.00",
4857         "PEN1.00",
4858         "PEN1.00",
4859         "PES1.00",
4860         "PES1.00",
4861         "PGK1.00",
4862         "PGK1.00",
4863         "PHP1.00",
4864         "PKR1.00",
4865         "PLN1.00",
4866         "PLZ1.00",
4867         "PLZ1.00",
4868         "PTE1.00",
4869         "PTE1.00",
4870         "PYG1.00",
4871         "Pakistani Rupee1.00",
4872         "Pakistani rupee1.00",
4873         "Pakistani rupees1.00",
4874         "Palladium1.00",
4875         "Palladium1.00",
4876         "Panamanian Balboa1.00",
4877         "Panamanian balboa1.00",
4878         "Panamanian balboas1.00",
4879         "Papua New Guinean Kina1.00",
4880         "Papua New Guinean kina1.00",
4881         "Papua New Guinean kina1.00",
4882         "Paraguayan Guarani1.00",
4883         "Paraguayan guarani1.00",
4884         "Paraguayan guaranis1.00",
4885         "Peruvian Inti1.00",
4886         "Peruvian Sol1.00",
4887         "Peruvian Sol (1863\\u20131965)1.00",
4888         "Peruvian inti1.00",
4889         "Peruvian intis1.00",
4890         "Peruvian sol1.00",
4891         "Peruvian soles1.00",
4892         "Peruvian sol (1863\\u20131965)1.00",
4893         "Peruvian soles (1863\\u20131965)1.00",
4894         "Philippine Peso1.00",
4895         "Philippine peso1.00",
4896         "Philippine pesos1.00",
4897         "Platinum1.00",
4898         "Platinum1.00",
4899         "Polish Zloty (1950\\u20131995)1.00",
4900         "Polish Zloty1.00",
4901         "Polish zlotys1.00",
4902         "Polish zloty (PLZ)1.00",
4903         "Polish zloty1.00",
4904         "Polish zlotys (PLZ)1.00",
4905         "Portuguese Escudo1.00",
4906         "Portuguese Guinea Escudo1.00",
4907         "Portuguese Guinea escudo1.00",
4908         "Portuguese Guinea escudos1.00",
4909         "Portuguese escudo1.00",
4910         "Portuguese escudos1.00",
4911         "GTQ1.00",
4912         "QAR1.00",
4913         "Qatari Riyal1.00",
4914         "Qatari riyal1.00",
4915         "Qatari riyals1.00",
4916         "RHD1.00",
4917         "RHD1.00",
4918         "RINET Funds1.00",
4919         "RINET Funds1.00",
4920         "CN\\u00a51.00",
4921         "ROL1.00",
4922         "ROL1.00",
4923         "RON1.00",
4924         "RON1.00",
4925         "RSD1.00",
4926         "RSD1.00",
4927         "RUB1.00",
4928         "RUR1.00",
4929         "RUR1.00",
4930         "RWF1.00",
4931         "RWF1.00",
4932         "Rhodesian Dollar1.00",
4933         "Rhodesian dollar1.00",
4934         "Rhodesian dollars1.00",
4935         "Romanian Leu1.00",
4936         "Romanian lei1.00",
4937         "Romanian leu1.00",
4938         "Russian Ruble (1991\\u20131998)1.00",
4939         "Russian Ruble1.00",
4940         "Russian ruble (1991\\u20131998)1.00",
4941         "Russian ruble1.00",
4942         "Russian rubles (1991\\u20131998)1.00",
4943         "Russian rubles1.00",
4944         "Rwandan Franc1.00",
4945         "Rwandan franc1.00",
4946         "Rwandan francs1.00",
4947         "SAR1.00",
4948         "SBD1.00",
4949         "SCR1.00",
4950         "SDD1.00",
4951         "SDD1.00",
4952         "SDG1.00",
4953         "SDG1.00",
4954         "SDP1.00",
4955         "SDP1.00",
4956         "SEK1.00",
4957         "SGD1.00",
4958         "SHP1.00",
4959         "SHP1.00",
4960         "SIT1.00",
4961         "SIT1.00",
4962         "SKK1.00",
4963         "SLL1.00",
4964         "SLL1.00",
4965         "SOS1.00",
4966         "SRD1.00",
4967         "SRD1.00",
4968         "SRG1.00",
4969         "STD1.00",
4970         "SUR1.00",
4971         "SUR1.00",
4972         "SVC1.00",
4973         "SVC1.00",
4974         "SYP1.00",
4975         "SZL1.00",
4976         "St. Helena Pound1.00",
4977         "St. Helena pound1.00",
4978         "St. Helena pounds1.00",
4979         "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra1.00",
4980         "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra1.00",
4981         "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras1.00",
4982         "Saudi Riyal1.00",
4983         "Saudi riyal1.00",
4984         "Saudi riyals1.00",
4985         "Serbian Dinar1.00",
4986         "Serbian dinar1.00",
4987         "Serbian dinars1.00",
4988         "Seychellois Rupee1.00",
4989         "Seychellois rupee1.00",
4990         "Seychellois rupees1.00",
4991         "Sierra Leonean Leone1.00",
4992         "Sierra Leonean leone1.00",
4993         "Sierra Leonean leones1.00",
4994         "Silver1.00",
4995         "Silver1.00",
4996         "Singapore Dollar1.00",
4997         "Singapore dollar1.00",
4998         "Singapore dollars1.00",
4999         "Slovak Koruna1.00",
5000         "Slovak koruna1.00",
5001         "Slovak korunas1.00",
5002         "Slovenian Tolar1.00",
5003         "Slovenian tolar1.00",
5004         "Slovenian tolars1.00",
5005         "Solomon Islands Dollar1.00",
5006         "Solomon Islands dollar1.00",
5007         "Solomon Islands dollars1.00",
5008         "Somali Shilling1.00",
5009         "Somali shilling1.00",
5010         "Somali shillings1.00",
5011         "South African Rand (financial)1.00",
5012         "South African Rand1.00",
5013         "South African rand (financial)1.00",
5014         "South African rand1.00",
5015         "South African rands (financial)1.00",
5016         "South African rand1.00",
5017         "South Korean Won1.00",
5018         "South Korean won1.00",
5019         "South Korean won1.00",
5020         "Soviet Rouble1.00",
5021         "Soviet rouble1.00",
5022         "Soviet roubles1.00",
5023         "Spanish Peseta (A account)1.00",
5024         "Spanish Peseta (convertible account)1.00",
5025         "Spanish Peseta1.00",
5026         "Spanish peseta (A account)1.00",
5027         "Spanish peseta (convertible account)1.00",
5028         "Spanish peseta1.00",
5029         "Spanish pesetas (A account)1.00",
5030         "Spanish pesetas (convertible account)1.00",
5031         "Spanish pesetas1.00",
5032         "Special Drawing Rights1.00",
5033         "Sri Lankan Rupee1.00",
5034         "Sri Lankan rupee1.00",
5035         "Sri Lankan rupees1.00",
5036         "Sudanese Pound1.00",
5037         "Sudanese pound1.00",
5038         "Sudanese pounds1.00",
5039         "Surinamese Dollar1.00",
5040         "Surinamese dollar1.00",
5041         "Surinamese dollars1.00",
5042         "Surinamese Guilder1.00",
5043         "Surinamese guilder1.00",
5044         "Surinamese guilders1.00",
5045         "Swazi Lilangeni1.00",
5046         "Swazi lilangeni1.00",
5047         "Swazi emalangeni1.00",
5048         "Swedish Krona1.00",
5049         "Swedish krona1.00",
5050         "Swedish kronor1.00",
5051         "Swiss Franc1.00",
5052         "Swiss franc1.00",
5053         "Swiss francs1.00",
5054         "Syrian Pound1.00",
5055         "Syrian pound1.00",
5056         "Syrian pounds1.00",
5057         "THB1.00",
5058         "TJR1.00",
5059         "TJR1.00",
5060         "TJS1.00",
5061         "TJS1.00",
5062         "TMM1.00",
5063         "TMM1.00",
5064         "TND1.00",
5065         "TND1.00",
5066         "TOP1.00",
5067         "TPE1.00",
5068         "TPE1.00",
5069         "TRL1.00",
5070         "TRY1.00",
5071         "TRY1.00",
5072         "TTD1.00",
5073         "TWD1.00",
5074         "TZS1.00",
5075         "New Taiwan Dollar1.00",
5076         "New Taiwan dollar1.00",
5077         "New Taiwan dollars1.00",
5078         "Tajikistani Ruble1.00",
5079         "Tajikistani Somoni1.00",
5080         "Tajikistani ruble1.00",
5081         "Tajikistani rubles1.00",
5082         "Tajikistani somoni1.00",
5083         "Tajikistani somonis1.00",
5084         "Tanzanian Shilling1.00",
5085         "Tanzanian shilling1.00",
5086         "Tanzanian shillings1.00",
5087         "Testing Currency Code1.00",
5088         "Testing Currency Code1.00",
5089         "Thai Baht1.00",
5090         "Thai baht1.00",
5091         "Thai baht1.00",
5092         "Timorese Escudo1.00",
5093         "Timorese escudo1.00",
5094         "Timorese escudos1.00",
5095         "Tongan Pa\\u02bbanga1.00",
5096         "Tongan pa\\u02bbanga1.00",
5097         "Tongan pa\\u02bbanga1.00",
5098         "Trinidad & Tobago Dollar1.00",
5099         "Trinidad & Tobago dollar1.00",
5100         "Trinidad & Tobago dollars1.00",
5101         "Tunisian Dinar1.00",
5102         "Tunisian dinar1.00",
5103         "Tunisian dinars1.00",
5104         "Turkish Lira1.00",
5105         "Turkish Lira1.00",
5106         "Turkish lira1.00",
5107         "Turkmenistani Manat1.00",
5108         "Turkmenistani manat1.00",
5109         "Turkmenistani manat1.00",
5110         "UAE dirham1.00",
5111         "UAE dirhams1.00",
5112         "UAH1.00",
5113         "UAK1.00",
5114         "UAK1.00",
5115         "UGS1.00",
5116         "UGS1.00",
5117         "UGX1.00",
5118         "US Dollar (Next day)1.00",
5119         "US Dollar (Same day)1.00",
5120         "US Dollar1.00",
5121         "US dollar (next day)1.00",
5122         "US dollar (same day)1.00",
5123         "US dollar1.00",
5124         "US dollars (next day)1.00",
5125         "US dollars (same day)1.00",
5126         "US dollars1.00",
5127         "USD1.00",
5128         "USN1.00",
5129         "USN1.00",
5130         "USS1.00",
5131         "USS1.00",
5132         "UYI1.00",
5133         "UYI1.00",
5134         "UYP1.00",
5135         "UYP1.00",
5136         "UYU1.00",
5137         "UZS1.00",
5138         "UZS1.00",
5139         "Ugandan Shilling (1966\\u20131987)1.00",
5140         "Ugandan Shilling1.00",
5141         "Ugandan shilling (1966\\u20131987)1.00",
5142         "Ugandan shilling1.00",
5143         "Ugandan shillings (1966\\u20131987)1.00",
5144         "Ugandan shillings1.00",
5145         "Ukrainian Hryvnia1.00",
5146         "Ukrainian Karbovanets1.00",
5147         "Ukrainian hryvnia1.00",
5148         "Ukrainian hryvnias1.00",
5149         "Ukrainian karbovanets1.00",
5150         "Ukrainian karbovantsiv1.00",
5151         "Colombian Real Value Unit1.00",
5152         "United Arab Emirates Dirham1.00",
5153         "Unknown Currency1.00",
5154         "Uruguayan Peso (1975\\u20131993)1.00",
5155         "Uruguayan Peso1.00",
5156         "Uruguayan Peso (Indexed Units)1.00",
5157         "Uruguayan peso (1975\\u20131993)1.00",
5158         "Uruguayan peso (indexed units)1.00",
5159         "Uruguayan peso1.00",
5160         "Uruguayan pesos (1975\\u20131993)1.00",
5161         "Uruguayan pesos (indexed units)1.00",
5162         "Uruguayan pesos1.00",
5163         "Uzbekistani Som1.00",
5164         "Uzbekistani som1.00",
5165         "Uzbekistani som1.00",
5166         "VEB1.00",
5167         "VEF1.00",
5168         "VND1.00",
5169         "VUV1.00",
5170         "Vanuatu Vatu1.00",
5171         "Vanuatu vatu1.00",
5172         "Vanuatu vatus1.00",
5173         "Venezuelan Bol\\u00edvar1.00",
5174         "Venezuelan Bol\\u00edvar (1871\\u20132008)1.00",
5175         "Venezuelan bol\\u00edvar1.00",
5176         "Venezuelan bol\\u00edvars1.00",
5177         "Venezuelan bol\\u00edvar (1871\\u20132008)1.00",
5178         "Venezuelan bol\\u00edvars (1871\\u20132008)1.00",
5179         "Vietnamese Dong1.00",
5180         "Vietnamese dong1.00",
5181         "Vietnamese dong1.00",
5182         "WIR Euro1.00",
5183         "WIR Franc1.00",
5184         "WIR euro1.00",
5185         "WIR euros1.00",
5186         "WIR franc1.00",
5187         "WIR francs1.00",
5188         "WST1.00",
5189         "WST1.00",
5190         "Samoan Tala1.00",
5191         "Samoan tala1.00",
5192         "Samoan tala1.00",
5193         "XAF1.00",
5194         "XAF1.00",
5195         "XAG1.00",
5196         "XAG1.00",
5197         "XAU1.00",
5198         "XAU1.00",
5199         "XBA1.00",
5200         "XBA1.00",
5201         "XBB1.00",
5202         "XBB1.00",
5203         "XBC1.00",
5204         "XBC1.00",
5205         "XBD1.00",
5206         "XBD1.00",
5207         "XCD1.00",
5208         "XDR1.00",
5209         "XDR1.00",
5210         "XEU1.00",
5211         "XEU1.00",
5212         "XFO1.00",
5213         "XFO1.00",
5214         "XFU1.00",
5215         "XFU1.00",
5216         "XOF1.00",
5217         "XOF1.00",
5218         "XPD1.00",
5219         "XPD1.00",
5220         "XPF1.00",
5221         "XPT1.00",
5222         "XPT1.00",
5223         "XRE1.00",
5224         "XRE1.00",
5225         "XTS1.00",
5226         "XTS1.00",
5227         "XXX1.00",
5228         "XXX1.00",
5229         "YDD1.00",
5230         "YDD1.00",
5231         "YER1.00",
5232         "YUD1.00",
5233         "YUD1.00",
5234         "YUM1.00",
5235         "YUM1.00",
5236         "YUN1.00",
5237         "YUN1.00",
5238         "Yemeni Dinar1.00",
5239         "Yemeni Rial1.00",
5240         "Yemeni dinar1.00",
5241         "Yemeni dinars1.00",
5242         "Yemeni rial1.00",
5243         "Yemeni rials1.00",
5244         "Yugoslavian Convertible Dinar (1990\\u20131992)1.00",
5245         "Yugoslavian Hard Dinar (1966\\u20131990)1.00",
5246         "Yugoslavian New Dinar (1994\\u20132002)1.00",
5247         "Yugoslavian convertible dinar (1990\\u20131992)1.00",
5248         "Yugoslavian convertible dinars (1990\\u20131992)1.00",
5249         "Yugoslavian hard dinar (1966\\u20131990)1.00",
5250         "Yugoslavian hard dinars (1966\\u20131990)1.00",
5251         "Yugoslavian new dinar (1994\\u20132002)1.00",
5252         "Yugoslavian new dinars (1994\\u20132002)1.00",
5253         "ZAL1.00",
5254         "ZAL1.00",
5255         "ZAR1.00",
5256         "ZMK1.00",
5257         "ZMK1.00",
5258         "ZRN1.00",
5259         "ZRN1.00",
5260         "ZRZ1.00",
5261         "ZRZ1.00",
5262         "ZWD1.00",
5263         "Zairean New Zaire (1993\\u20131998)1.00",
5264         "Zairean Zaire (1971\\u20131993)1.00",
5265         "Zairean new zaire (1993\\u20131998)1.00",
5266         "Zairean new zaires (1993\\u20131998)1.00",
5267         "Zairean zaire (1971\\u20131993)1.00",
5268         "Zairean zaires (1971\\u20131993)1.00",
5269         "Zambian Kwacha1.00",
5270         "Zambian kwacha1.00",
5271         "Zambian kwachas1.00",
5272         "Zimbabwean Dollar (1980\\u20132008)1.00",
5273         "Zimbabwean dollar (1980\\u20132008)1.00",
5274         "Zimbabwean dollars (1980\\u20132008)1.00",
5275         "euro1.00",
5276         "euros1.00",
5277         "Turkish lira (1922\\u20132005)1.00",
5278         "special drawing rights1.00",
5279         "Colombian real value unit1.00",
5280         "Colombian real value units1.00",
5281         "unknown currency1.00",
5282         "\\u00a31.00",
5283         "\\u00a51.00",
5284         "\\u20ab1.00",
5285         "\\u20aa1.00",
5286         "\\u20ac1.00",
5287         "\\u20b91.00",
5288         //
5289         // Following has extra text, should be parsed correctly too
5290         "$1.00 random",
5291         "USD1.00 random",
5292         "1.00 US dollar random",
5293         "1.00 US dollars random",
5294         "1.00 Afghan Afghani random",
5295         "1.00 Afghan Afghani random",
5296         "1.00 Afghan Afghanis (1927\\u20131992) random",
5297         "1.00 Afghan Afghanis random",
5298         "1.00 Albanian Lek random",
5299         "1.00 Albanian lek random",
5300         "1.00 Albanian lek\\u00eb random",
5301         "1.00 Algerian Dinar random",
5302         "1.00 Algerian dinar random",
5303         "1.00 Algerian dinars random",
5304         "1.00 Andorran Peseta random",
5305         "1.00 Andorran peseta random",
5306         "1.00 Andorran pesetas random",
5307         "1.00 Angolan Kwanza (1977\\u20131990) random",
5308         "1.00 Angolan Readjusted Kwanza (1995\\u20131999) random",
5309         "1.00 Angolan Kwanza random",
5310         "1.00 Angolan New Kwanza (1990\\u20132000) random",
5311         "1.00 Angolan kwanza (1977\\u20131991) random",
5312         "1.00 Angolan readjusted kwanza (1995\\u20131999) random",
5313         "1.00 Angolan kwanza random",
5314         "1.00 Angolan kwanzas (1977\\u20131991) random",
5315         "1.00 Angolan readjusted kwanzas (1995\\u20131999) random",
5316         "1.00 Angolan kwanzas random",
5317         "1.00 Angolan new kwanza (1990\\u20132000) random",
5318         "1.00 Angolan new kwanzas (1990\\u20132000) random",
5319         "1.00 Argentine Austral random",
5320         "1.00 Argentine Peso (1983\\u20131985) random",
5321         "1.00 Argentine Peso random",
5322         "1.00 Argentine austral random",
5323         "1.00 Argentine australs random",
5324         "1.00 Argentine peso (1983\\u20131985) random",
5325         "1.00 Argentine peso random",
5326         "1.00 Argentine pesos (1983\\u20131985) random",
5327         "1.00 Argentine pesos random",
5328         "1.00 Armenian Dram random",
5329         "1.00 Armenian dram random",
5330         "1.00 Armenian drams random",
5331         "1.00 Aruban Florin random",
5332         "1.00 Aruban florin random",
5333         "1.00 Australian Dollar random",
5334         "1.00 Australian dollar random",
5335         "1.00 Australian dollars random",
5336         "1.00 Austrian Schilling random",
5337         "1.00 Austrian schilling random",
5338         "1.00 Austrian schillings random",
5339         "1.00 Azerbaijani Manat (1993\\u20132006) random",
5340         "1.00 Azerbaijani Manat random",
5341         "1.00 Azerbaijani manat (1993\\u20132006) random",
5342         "1.00 Azerbaijani manat random",
5343         "1.00 Azerbaijani manats (1993\\u20132006) random",
5344         "1.00 Azerbaijani manats random",
5345         "1.00 Bahamian Dollar random",
5346         "1.00 Bahamian dollar random",
5347         "1.00 Bahamian dollars random",
5348         "1.00 Bahraini Dinar random",
5349         "1.00 Bahraini dinar random",
5350         "1.00 Bahraini dinars random",
5351         "1.00 Bangladeshi Taka random",
5352         "1.00 Bangladeshi taka random",
5353         "1.00 Bangladeshi takas random",
5354         "1.00 Barbadian Dollar random",
5355         "1.00 Barbadian dollar random",
5356         "1.00 Barbadian dollars random",
5357         "1.00 Belarusian Ruble (1994\\u20131999) random",
5358         "1.00 Belarusian Ruble random",
5359         "1.00 Belarusian ruble (1994\\u20131999) random",
5360         "1.00 Belarusian rubles (1994\\u20131999) random",
5361         "1.00 Belarusian ruble random",
5362         "1.00 Belarusian rubles random",
5363         "1.00 Belgian Franc (convertible) random",
5364         "1.00 Belgian Franc (financial) random",
5365         "1.00 Belgian Franc random",
5366         "1.00 Belgian franc (convertible) random",
5367         "1.00 Belgian franc (financial) random",
5368         "1.00 Belgian franc random",
5369         "1.00 Belgian francs (convertible) random",
5370         "1.00 Belgian francs (financial) random",
5371         "1.00 Belgian francs random",
5372         "1.00 Belize Dollar random",
5373         "1.00 Belize dollar random",
5374         "1.00 Belize dollars random",
5375         "1.00 Bermudan Dollar random",
5376         "1.00 Bermudan dollar random",
5377         "1.00 Bermudan dollars random",
5378         "1.00 Bhutanese Ngultrum random",
5379         "1.00 Bhutanese ngultrum random",
5380         "1.00 Bhutanese ngultrums random",
5381         "1.00 Bolivian Mvdol random",
5382         "1.00 Bolivian Peso random",
5383         "1.00 Bolivian mvdol random",
5384         "1.00 Bolivian mvdols random",
5385         "1.00 Bolivian peso random",
5386         "1.00 Bolivian pesos random",
5387         "1.00 Bolivian Boliviano random",
5388         "1.00 Bolivian Boliviano random",
5389         "1.00 Bolivian Bolivianos random",
5390         "1.00 Bosnia-Herzegovina Convertible Mark random",
5391         "1.00 Bosnia-Herzegovina Dinar (1992\\u20131994) random",
5392         "1.00 Bosnia-Herzegovina convertible mark random",
5393         "1.00 Bosnia-Herzegovina convertible marks random",
5394         "1.00 Bosnia-Herzegovina dinar (1992\\u20131994) random",
5395         "1.00 Bosnia-Herzegovina dinars (1992\\u20131994) random",
5396         "1.00 Botswanan Pula random",
5397         "1.00 Botswanan pula random",
5398         "1.00 Botswanan pulas random",
5399         "1.00 Brazilian New Cruzado (1989\\u20131990) random",
5400         "1.00 Brazilian Cruzado (1986\\u20131989) random",
5401         "1.00 Brazilian Cruzeiro (1990\\u20131993) random",
5402         "1.00 Brazilian New Cruzeiro (1967\\u20131986) random",
5403         "1.00 Brazilian Cruzeiro (1993\\u20131994) random",
5404         "1.00 Brazilian Real random",
5405         "1.00 Brazilian new cruzado (1989\\u20131990) random",
5406         "1.00 Brazilian new cruzados (1989\\u20131990) random",
5407         "1.00 Brazilian cruzado (1986\\u20131989) random",
5408         "1.00 Brazilian cruzados (1986\\u20131989) random",
5409         "1.00 Brazilian cruzeiro (1990\\u20131993) random",
5410         "1.00 Brazilian new cruzeiro (1967\\u20131986) random",
5411         "1.00 Brazilian cruzeiro (1993\\u20131994) random",
5412         "1.00 Brazilian cruzeiros (1990\\u20131993) random",
5413         "1.00 Brazilian new cruzeiros (1967\\u20131986) random",
5414         "1.00 Brazilian cruzeiros (1993\\u20131994) random",
5415         "1.00 Brazilian real random",
5416         "1.00 Brazilian reals random",
5417         "1.00 British Pound random",
5418         "1.00 British pound random",
5419         "1.00 British pounds random",
5420         "1.00 Brunei Dollar random",
5421         "1.00 Brunei dollar random",
5422         "1.00 Brunei dollars random",
5423         "1.00 Bulgarian Hard Lev random",
5424         "1.00 Bulgarian Lev random",
5425         "1.00 Bulgarian Leva random",
5426         "1.00 Bulgarian hard lev random",
5427         "1.00 Bulgarian hard leva random",
5428         "1.00 Bulgarian lev random",
5429         "1.00 Burmese Kyat random",
5430         "1.00 Burmese kyat random",
5431         "1.00 Burmese kyats random",
5432         "1.00 Burundian Franc random",
5433         "1.00 Burundian franc random",
5434         "1.00 Burundian francs random",
5435         "1.00 Cambodian Riel random",
5436         "1.00 Cambodian riel random",
5437         "1.00 Cambodian riels random",
5438         "1.00 Canadian Dollar random",
5439         "1.00 Canadian dollar random",
5440         "1.00 Canadian dollars random",
5441         "1.00 Cape Verdean Escudo random",
5442         "1.00 Cape Verdean escudo random",
5443         "1.00 Cape Verdean escudos random",
5444         "1.00 Cayman Islands Dollar random",
5445         "1.00 Cayman Islands dollar random",
5446         "1.00 Cayman Islands dollars random",
5447         "1.00 Chilean Peso random",
5448         "1.00 Chilean Unit of Account (UF) random",
5449         "1.00 Chilean peso random",
5450         "1.00 Chilean pesos random",
5451         "1.00 Chilean unit of account (UF) random",
5452         "1.00 Chilean units of account (UF) random",
5453         "1.00 Chinese Yuan random",
5454         "1.00 Chinese yuan random",
5455         "1.00 Colombian Peso random",
5456         "1.00 Colombian peso random",
5457         "1.00 Colombian pesos random",
5458         "1.00 Comorian Franc random",
5459         "1.00 Comorian franc random",
5460         "1.00 Comorian francs random",
5461         "1.00 Congolese Franc Congolais random",
5462         "1.00 Congolese franc Congolais random",
5463         "1.00 Congolese francs Congolais random",
5464         "1.00 Costa Rican Col\\u00f3n random",
5465         "1.00 Costa Rican col\\u00f3n random",
5466         "1.00 Costa Rican col\\u00f3ns random",
5467         "1.00 Croatian Dinar random",
5468         "1.00 Croatian Kuna random",
5469         "1.00 Croatian dinar random",
5470         "1.00 Croatian dinars random",
5471         "1.00 Croatian kuna random",
5472         "1.00 Croatian kunas random",
5473         "1.00 Cuban Peso random",
5474         "1.00 Cuban peso random",
5475         "1.00 Cuban pesos random",
5476         "1.00 Cypriot Pound random",
5477         "1.00 Cypriot pound random",
5478         "1.00 Cypriot pounds random",
5479         "1.00 Czech Koruna random",
5480         "1.00 Czech koruna random",
5481         "1.00 Czech korunas random",
5482         "1.00 Czechoslovak Hard Koruna random",
5483         "1.00 Czechoslovak hard koruna random",
5484         "1.00 Czechoslovak hard korunas random",
5485         "1.00 Danish Krone random",
5486         "1.00 Danish krone random",
5487         "1.00 Danish kroner random",
5488         "1.00 German Mark random",
5489         "1.00 German mark random",
5490         "1.00 German marks random",
5491         "1.00 Djiboutian Franc random",
5492         "1.00 Djiboutian franc random",
5493         "1.00 Djiboutian francs random",
5494         "1.00 Dominican Peso random",
5495         "1.00 Dominican peso random",
5496         "1.00 Dominican pesos random",
5497         "1.00 East Caribbean Dollar random",
5498         "1.00 East Caribbean dollar random",
5499         "1.00 East Caribbean dollars random",
5500         "1.00 East German Mark random",
5501         "1.00 East German mark random",
5502         "1.00 East German marks random",
5503         "1.00 Ecuadorian Sucre random",
5504         "1.00 Ecuadorian Unit of Constant Value random",
5505         "1.00 Ecuadorian sucre random",
5506         "1.00 Ecuadorian sucres random",
5507         "1.00 Ecuadorian unit of constant value random",
5508         "1.00 Ecuadorian units of constant value random",
5509         "1.00 Egyptian Pound random",
5510         "1.00 Egyptian pound random",
5511         "1.00 Egyptian pounds random",
5512         "1.00 Salvadoran Col\\u00f3n random",
5513         "1.00 Salvadoran col\\u00f3n random",
5514         "1.00 Salvadoran colones random",
5515         "1.00 Equatorial Guinean Ekwele random",
5516         "1.00 Equatorial Guinean ekwele random",
5517         "1.00 Eritrean Nakfa random",
5518         "1.00 Eritrean nakfa random",
5519         "1.00 Eritrean nakfas random",
5520         "1.00 Estonian Kroon random",
5521         "1.00 Estonian kroon random",
5522         "1.00 Estonian kroons random",
5523         "1.00 Ethiopian Birr random",
5524         "1.00 Ethiopian birr random",
5525         "1.00 Ethiopian birrs random",
5526         "1.00 European Composite Unit random",
5527         "1.00 European Currency Unit random",
5528         "1.00 European Monetary Unit random",
5529         "1.00 European Unit of Account (XBC) random",
5530         "1.00 European Unit of Account (XBD) random",
5531         "1.00 European composite unit random",
5532         "1.00 European composite units random",
5533         "1.00 European currency unit random",
5534         "1.00 European currency units random",
5535         "1.00 European monetary unit random",
5536         "1.00 European monetary units random",
5537         "1.00 European unit of account (XBC) random",
5538         "1.00 European unit of account (XBD) random",
5539         "1.00 European units of account (XBC) random",
5540         "1.00 European units of account (XBD) random",
5541         "1.00 Falkland Islands Pound random",
5542         "1.00 Falkland Islands pound random",
5543         "1.00 Falkland Islands pounds random",
5544         "1.00 Fijian Dollar random",
5545         "1.00 Fijian dollar random",
5546         "1.00 Fijian dollars random",
5547         "1.00 Finnish Markka random",
5548         "1.00 Finnish markka random",
5549         "1.00 Finnish markkas random",
5550         "1.00 French Franc random",
5551         "1.00 French Gold Franc random",
5552         "1.00 French UIC-Franc random",
5553         "1.00 French UIC-franc random",
5554         "1.00 French UIC-francs random",
5555         "1.00 French franc random",
5556         "1.00 French francs random",
5557         "1.00 French gold franc random",
5558         "1.00 French gold francs random",
5559         "1.00 Gambian Dalasi random",
5560         "1.00 Gambian dalasi random",
5561         "1.00 Gambian dalasis random",
5562         "1.00 Georgian Kupon Larit random",
5563         "1.00 Georgian Lari random",
5564         "1.00 Georgian kupon larit random",
5565         "1.00 Georgian kupon larits random",
5566         "1.00 Georgian lari random",
5567         "1.00 Georgian laris random",
5568         "1.00 Ghanaian Cedi (1979\\u20132007) random",
5569         "1.00 Ghanaian Cedi random",
5570         "1.00 Ghanaian cedi (1979\\u20132007) random",
5571         "1.00 Ghanaian cedi random",
5572         "1.00 Ghanaian cedis (1979\\u20132007) random",
5573         "1.00 Ghanaian cedis random",
5574         "1.00 Gibraltar Pound random",
5575         "1.00 Gibraltar pound random",
5576         "1.00 Gibraltar pounds random",
5577         "1.00 Gold random",
5578         "1.00 Gold random",
5579         "1.00 Greek Drachma random",
5580         "1.00 Greek drachma random",
5581         "1.00 Greek drachmas random",
5582         "1.00 Guatemalan Quetzal random",
5583         "1.00 Guatemalan quetzal random",
5584         "1.00 Guatemalan quetzals random",
5585         "1.00 Guinean Franc random",
5586         "1.00 Guinean Syli random",
5587         "1.00 Guinean franc random",
5588         "1.00 Guinean francs random",
5589         "1.00 Guinean syli random",
5590         "1.00 Guinean sylis random",
5591         "1.00 Guinea-Bissau Peso random",
5592         "1.00 Guinea-Bissau peso random",
5593         "1.00 Guinea-Bissau pesos random",
5594         "1.00 Guyanaese Dollar random",
5595         "1.00 Guyanaese dollar random",
5596         "1.00 Guyanaese dollars random",
5597         "1.00 Haitian Gourde random",
5598         "1.00 Haitian gourde random",
5599         "1.00 Haitian gourdes random",
5600         "1.00 Honduran Lempira random",
5601         "1.00 Honduran lempira random",
5602         "1.00 Honduran lempiras random",
5603         "1.00 Hong Kong Dollar random",
5604         "1.00 Hong Kong dollar random",
5605         "1.00 Hong Kong dollars random",
5606         "1.00 Hungarian Forint random",
5607         "1.00 Hungarian forint random",
5608         "1.00 Hungarian forints random",
5609         "1.00 Icelandic Kr\\u00f3na random",
5610         "1.00 Icelandic kr\\u00f3na random",
5611         "1.00 Icelandic kr\\u00f3nur random",
5612         "1.00 Indian Rupee random",
5613         "1.00 Indian rupee random",
5614         "1.00 Indian rupees random",
5615         "1.00 Indonesian Rupiah random",
5616         "1.00 Indonesian rupiah random",
5617         "1.00 Indonesian rupiahs random",
5618         "1.00 Iranian Rial random",
5619         "1.00 Iranian rial random",
5620         "1.00 Iranian rials random",
5621         "1.00 Iraqi Dinar random",
5622         "1.00 Iraqi dinar random",
5623         "1.00 Iraqi dinars random",
5624         "1.00 Irish Pound random",
5625         "1.00 Irish pound random",
5626         "1.00 Irish pounds random",
5627         "1.00 Israeli Pound random",
5628         "1.00 Israeli new shekel random",
5629         "1.00 Israeli pound random",
5630         "1.00 Israeli pounds random",
5631         "1.00 Italian Lira random",
5632         "1.00 Italian lira random",
5633         "1.00 Italian liras random",
5634         "1.00 Jamaican Dollar random",
5635         "1.00 Jamaican dollar random",
5636         "1.00 Jamaican dollars random",
5637         "1.00 Japanese Yen random",
5638         "1.00 Japanese yen random",
5639         "1.00 Jordanian Dinar random",
5640         "1.00 Jordanian dinar random",
5641         "1.00 Jordanian dinars random",
5642         "1.00 Kazakhstani Tenge random",
5643         "1.00 Kazakhstani tenge random",
5644         "1.00 Kazakhstani tenges random",
5645         "1.00 Kenyan Shilling random",
5646         "1.00 Kenyan shilling random",
5647         "1.00 Kenyan shillings random",
5648         "1.00 Kuwaiti Dinar random",
5649         "1.00 Kuwaiti dinar random",
5650         "1.00 Kuwaiti dinars random",
5651         "1.00 Kyrgystani Som random",
5652         "1.00 Kyrgystani som random",
5653         "1.00 Kyrgystani soms random",
5654         "1.00 Laotian Kip random",
5655         "1.00 Laotian kip random",
5656         "1.00 Laotian kips random",
5657         "1.00 Latvian Lats random",
5658         "1.00 Latvian Ruble random",
5659         "1.00 Latvian lats random",
5660         "1.00 Latvian lati random",
5661         "1.00 Latvian ruble random",
5662         "1.00 Latvian rubles random",
5663         "1.00 Lebanese Pound random",
5664         "1.00 Lebanese pound random",
5665         "1.00 Lebanese pounds random",
5666         "1.00 Lesotho Loti random",
5667         "1.00 Lesotho loti random",
5668         "1.00 Lesotho lotis random",
5669         "1.00 Liberian Dollar random",
5670         "1.00 Liberian dollar random",
5671         "1.00 Liberian dollars random",
5672         "1.00 Libyan Dinar random",
5673         "1.00 Libyan dinar random",
5674         "1.00 Libyan dinars random",
5675         "1.00 Lithuanian Litas random",
5676         "1.00 Lithuanian Talonas random",
5677         "1.00 Lithuanian litas random",
5678         "1.00 Lithuanian litai random",
5679         "1.00 Lithuanian talonas random",
5680         "1.00 Lithuanian talonases random",
5681         "1.00 Luxembourgian Convertible Franc random",
5682         "1.00 Luxembourg Financial Franc random",
5683         "1.00 Luxembourgian Franc random",
5684         "1.00 Luxembourgian convertible franc random",
5685         "1.00 Luxembourgian convertible francs random",
5686         "1.00 Luxembourg financial franc random",
5687         "1.00 Luxembourg financial francs random",
5688         "1.00 Luxembourgian franc random",
5689         "1.00 Luxembourgian francs random",
5690         "1.00 Macanese Pataca random",
5691         "1.00 Macanese pataca random",
5692         "1.00 Macanese patacas random",
5693         "1.00 Macedonian Denar random",
5694         "1.00 Macedonian denar random",
5695         "1.00 Macedonian denari random",
5696         "1.00 Malagasy Ariaries random",
5697         "1.00 Malagasy Ariary random",
5698         "1.00 Malagasy Ariary random",
5699         "1.00 Malagasy Franc random",
5700         "1.00 Malagasy franc random",
5701         "1.00 Malagasy francs random",
5702         "1.00 Malawian Kwacha random",
5703         "1.00 Malawian Kwacha random",
5704         "1.00 Malawian Kwachas random",
5705         "1.00 Malaysian Ringgit random",
5706         "1.00 Malaysian ringgit random",
5707         "1.00 Malaysian ringgits random",
5708         "1.00 Maldivian Rufiyaa random",
5709         "1.00 Maldivian rufiyaa random",
5710         "1.00 Maldivian rufiyaas random",
5711         "1.00 Malian Franc random",
5712         "1.00 Malian franc random",
5713         "1.00 Malian francs random",
5714         "1.00 Maltese Lira random",
5715         "1.00 Maltese Pound random",
5716         "1.00 Maltese lira random",
5717         "1.00 Maltese liras random",
5718         "1.00 Maltese pound random",
5719         "1.00 Maltese pounds random",
5720         "1.00 Mauritanian Ouguiya random",
5721         "1.00 Mauritanian ouguiya random",
5722         "1.00 Mauritanian ouguiyas random",
5723         "1.00 Mauritian Rupee random",
5724         "1.00 Mauritian rupee random",
5725         "1.00 Mauritian rupees random",
5726         "1.00 Mexican Peso random",
5727         "1.00 Mexican Silver Peso (1861\\u20131992) random",
5728         "1.00 Mexican Investment Unit random",
5729         "1.00 Mexican peso random",
5730         "1.00 Mexican pesos random",
5731         "1.00 Mexican silver peso (1861\\u20131992) random",
5732         "1.00 Mexican silver pesos (1861\\u20131992) random",
5733         "1.00 Mexican investment unit random",
5734         "1.00 Mexican investment units random",
5735         "1.00 Moldovan Leu random",
5736         "1.00 Moldovan leu random",
5737         "1.00 Moldovan lei random",
5738         "1.00 Mongolian Tugrik random",
5739         "1.00 Mongolian tugrik random",
5740         "1.00 Mongolian tugriks random",
5741         "1.00 Moroccan Dirham random",
5742         "1.00 Moroccan Franc random",
5743         "1.00 Moroccan dirham random",
5744         "1.00 Moroccan dirhams random",
5745         "1.00 Moroccan franc random",
5746         "1.00 Moroccan francs random",
5747         "1.00 Mozambican Escudo random",
5748         "1.00 Mozambican Metical random",
5749         "1.00 Mozambican escudo random",
5750         "1.00 Mozambican escudos random",
5751         "1.00 Mozambican metical random",
5752         "1.00 Mozambican meticals random",
5753         "1.00 Myanmar Kyat random",
5754         "1.00 Myanmar kyat random",
5755         "1.00 Myanmar kyats random",
5756         "1.00 Namibian Dollar random",
5757         "1.00 Namibian dollar random",
5758         "1.00 Namibian dollars random",
5759         "1.00 Nepalese Rupee random",
5760         "1.00 Nepalese rupee random",
5761         "1.00 Nepalese rupees random",
5762         "1.00 Netherlands Antillean Guilder random",
5763         "1.00 Netherlands Antillean guilder random",
5764         "1.00 Netherlands Antillean guilders random",
5765         "1.00 Dutch Guilder random",
5766         "1.00 Dutch guilder random",
5767         "1.00 Dutch guilders random",
5768         "1.00 Israeli New Shekel random",
5769         "1.00 Israeli new shekels random",
5770         "1.00 New Zealand Dollar random",
5771         "1.00 New Zealand dollar random",
5772         "1.00 New Zealand dollars random",
5773         "1.00 Nicaraguan C\\u00f3rdoba random",
5774         "1.00 Nicaraguan C\\u00f3rdoba (1988\\u20131991) random",
5775         "1.00 Nicaraguan c\\u00f3rdoba random",
5776         "1.00 Nicaraguan c\\u00f3rdoba random",
5777         "1.00 Nicaraguan c\\u00f3rdoba (1988\\u20131991) random",
5778         "1.00 Nicaraguan c\\u00f3rdobas (1988\\u20131991) random",
5779         "1.00 Nigerian Naira random",
5780         "1.00 Nigerian naira random",
5781         "1.00 Nigerian nairas random",
5782         "1.00 North Korean Won random",
5783         "1.00 North Korean won random",
5784         "1.00 North Korean won random",
5785         "1.00 Norwegian Krone random",
5786         "1.00 Norwegian krone random",
5787         "1.00 Norwegian kroner random",
5788         "1.00 Mozambican Metical (1980\\u20132006) random",
5789         "1.00 Mozambican metical (1980\\u20132006) random",
5790         "1.00 Mozambican meticals (1980\\u20132006) random",
5791         "1.00 Romanian Lei (1952\\u20132006) random",
5792         "1.00 Romanian Leu (1952\\u20132006) random",
5793         "1.00 Romanian leu (1952\\u20132006) random",
5794         "1.00 Serbian Dinar (2002\\u20132006) random",
5795         "1.00 Serbian dinar (2002\\u20132006) random",
5796         "1.00 Serbian dinars (2002\\u20132006) random",
5797         "1.00 Sudanese Dinar (1992\\u20132007) random",
5798         "1.00 Sudanese Pound (1957\\u20131998) random",
5799         "1.00 Sudanese dinar (1992\\u20132007) random",
5800         "1.00 Sudanese dinars (1992\\u20132007) random",
5801         "1.00 Sudanese pound (1957\\u20131998) random",
5802         "1.00 Sudanese pounds (1957\\u20131998) random",
5803         "1.00 Turkish Lira (1922\\u20132005) random",
5804         "1.00 Turkish Lira (1922\\u20132005) random",
5805         "1.00 Omani Rial random",
5806         "1.00 Omani rial random",
5807         "1.00 Omani rials random",
5808         "1.00 Pakistani Rupee random",
5809         "1.00 Pakistani rupee random",
5810         "1.00 Pakistani rupees random",
5811         "1.00 Palladium random",
5812         "1.00 Palladium random",
5813         "1.00 Panamanian Balboa random",
5814         "1.00 Panamanian balboa random",
5815         "1.00 Panamanian balboas random",
5816         "1.00 Papua New Guinean Kina random",
5817         "1.00 Papua New Guinean kina random",
5818         "1.00 Papua New Guinean kina random",
5819         "1.00 Paraguayan Guarani random",
5820         "1.00 Paraguayan guarani random",
5821         "1.00 Paraguayan guaranis random",
5822         "1.00 Peruvian Inti random",
5823         "1.00 Peruvian Sol random",
5824         "1.00 Peruvian Sol (1863\\u20131965) random",
5825         "1.00 Peruvian inti random",
5826         "1.00 Peruvian intis random",
5827         "1.00 Peruvian sol random",
5828         "1.00 Peruvian soles random",
5829         "1.00 Peruvian sol (1863\\u20131965) random",
5830         "1.00 Peruvian soles (1863\\u20131965) random",
5831         "1.00 Philippine Peso random",
5832         "1.00 Philippine peso random",
5833         "1.00 Philippine pesos random",
5834         "1.00 Platinum random",
5835         "1.00 Platinum random",
5836         "1.00 Polish Zloty (1950\\u20131995) random",
5837         "1.00 Polish Zloty random",
5838         "1.00 Polish zlotys random",
5839         "1.00 Polish zloty (PLZ) random",
5840         "1.00 Polish zloty random",
5841         "1.00 Polish zlotys (PLZ) random",
5842         "1.00 Portuguese Escudo random",
5843         "1.00 Portuguese Guinea Escudo random",
5844         "1.00 Portuguese Guinea escudo random",
5845         "1.00 Portuguese Guinea escudos random",
5846         "1.00 Portuguese escudo random",
5847         "1.00 Portuguese escudos random",
5848         "1.00 Qatari Riyal random",
5849         "1.00 Qatari riyal random",
5850         "1.00 Qatari riyals random",
5851         "1.00 RINET Funds random",
5852         "1.00 RINET Funds random",
5853         "1.00 Rhodesian Dollar random",
5854         "1.00 Rhodesian dollar random",
5855         "1.00 Rhodesian dollars random",
5856         "1.00 Romanian Leu random",
5857         "1.00 Romanian lei random",
5858         "1.00 Romanian leu random",
5859         "1.00 Russian Ruble (1991\\u20131998) random",
5860         "1.00 Russian Ruble random",
5861         "1.00 Russian ruble (1991\\u20131998) random",
5862         "1.00 Russian ruble random",
5863         "1.00 Russian rubles (1991\\u20131998) random",
5864         "1.00 Russian rubles random",
5865         "1.00 Rwandan Franc random",
5866         "1.00 Rwandan franc random",
5867         "1.00 Rwandan francs random",
5868         "1.00 St. Helena Pound random",
5869         "1.00 St. Helena pound random",
5870         "1.00 St. Helena pounds random",
5871         "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra random",
5872         "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra random",
5873         "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras random",
5874         "1.00 Saudi Riyal random",
5875         "1.00 Saudi riyal random",
5876         "1.00 Saudi riyals random",
5877         "1.00 Serbian Dinar random",
5878         "1.00 Serbian dinar random",
5879         "1.00 Serbian dinars random",
5880         "1.00 Seychellois Rupee random",
5881         "1.00 Seychellois rupee random",
5882         "1.00 Seychellois rupees random",
5883         "1.00 Sierra Leonean Leone random",
5884         "1.00 Sierra Leonean leone random",
5885         "1.00 Sierra Leonean leones random",
5886         "1.00 Singapore Dollar random",
5887         "1.00 Singapore dollar random",
5888         "1.00 Singapore dollars random",
5889         "1.00 Slovak Koruna random",
5890         "1.00 Slovak koruna random",
5891         "1.00 Slovak korunas random",
5892         "1.00 Slovenian Tolar random",
5893         "1.00 Slovenian tolar random",
5894         "1.00 Slovenian tolars random",
5895         "1.00 Solomon Islands Dollar random",
5896         "1.00 Solomon Islands dollar random",
5897         "1.00 Solomon Islands dollars random",
5898         "1.00 Somali Shilling random",
5899         "1.00 Somali shilling random",
5900         "1.00 Somali shillings random",
5901         "1.00 South African Rand (financial) random",
5902         "1.00 South African Rand random",
5903         "1.00 South African rand (financial) random",
5904         "1.00 South African rand random",
5905         "1.00 South African rands (financial) random",
5906         "1.00 South African rand random",
5907         "1.00 South Korean Won random",
5908         "1.00 South Korean won random",
5909         "1.00 South Korean won random",
5910         "1.00 Soviet Rouble random",
5911         "1.00 Soviet rouble random",
5912         "1.00 Soviet roubles random",
5913         "1.00 Spanish Peseta (A account) random",
5914         "1.00 Spanish Peseta (convertible account) random",
5915         "1.00 Spanish Peseta random",
5916         "1.00 Spanish peseta (A account) random",
5917         "1.00 Spanish peseta (convertible account) random",
5918         "1.00 Spanish peseta random",
5919         "1.00 Spanish pesetas (A account) random",
5920         "1.00 Spanish pesetas (convertible account) random",
5921         "1.00 Spanish pesetas random",
5922         "1.00 Special Drawing Rights random",
5923         "1.00 Sri Lankan Rupee random",
5924         "1.00 Sri Lankan rupee random",
5925         "1.00 Sri Lankan rupees random",
5926         "1.00 Sudanese Pound random",
5927         "1.00 Sudanese pound random",
5928         "1.00 Sudanese pounds random",
5929         "1.00 Surinamese Dollar random",
5930         "1.00 Surinamese dollar random",
5931         "1.00 Surinamese dollars random",
5932         "1.00 Surinamese Guilder random",
5933         "1.00 Surinamese guilder random",
5934         "1.00 Surinamese guilders random",
5935         "1.00 Swazi Lilangeni random",
5936         "1.00 Swazi lilangeni random",
5937         "1.00 Swazi emalangeni random",
5938         "1.00 Swedish Krona random",
5939         "1.00 Swedish krona random",
5940         "1.00 Swedish kronor random",
5941         "1.00 Swiss Franc random",
5942         "1.00 Swiss franc random",
5943         "1.00 Swiss francs random",
5944         "1.00 Syrian Pound random",
5945         "1.00 Syrian pound random",
5946         "1.00 Syrian pounds random",
5947         "1.00 New Taiwan Dollar random",
5948         "1.00 New Taiwan dollar random",
5949         "1.00 New Taiwan dollars random",
5950         "1.00 Tajikistani Ruble random",
5951         "1.00 Tajikistani Somoni random",
5952         "1.00 Tajikistani ruble random",
5953         "1.00 Tajikistani rubles random",
5954         "1.00 Tajikistani somoni random",
5955         "1.00 Tajikistani somonis random",
5956         "1.00 Tanzanian Shilling random",
5957         "1.00 Tanzanian shilling random",
5958         "1.00 Tanzanian shillings random",
5959         "1.00 Testing Currency Code random",
5960         "1.00 Testing Currency Code random",
5961         "1.00 Thai Baht random",
5962         "1.00 Thai baht random",
5963         "1.00 Thai baht random",
5964         "1.00 Timorese Escudo random",
5965         "1.00 Timorese escudo random",
5966         "1.00 Timorese escudos random",
5967         "1.00 Trinidad & Tobago Dollar random",
5968         "1.00 Trinidad & Tobago dollar random",
5969         "1.00 Trinidad & Tobago dollars random",
5970         "1.00 Tunisian Dinar random",
5971         "1.00 Tunisian dinar random",
5972         "1.00 Tunisian dinars random",
5973         "1.00 Turkish Lira random",
5974         "1.00 Turkish Lira random",
5975         "1.00 Turkish lira random",
5976         "1.00 Turkmenistani Manat random",
5977         "1.00 Turkmenistani manat random",
5978         "1.00 Turkmenistani manat random",
5979         "1.00 US Dollar (Next day) random",
5980         "1.00 US Dollar (Same day) random",
5981         "1.00 US Dollar random",
5982         "1.00 US dollar (next day) random",
5983         "1.00 US dollar (same day) random",
5984         "1.00 US dollar random",
5985         "1.00 US dollars (next day) random",
5986         "1.00 US dollars (same day) random",
5987         "1.00 US dollars random",
5988         "1.00 Ugandan Shilling (1966\\u20131987) random",
5989         "1.00 Ugandan Shilling random",
5990         "1.00 Ugandan shilling (1966\\u20131987) random",
5991         "1.00 Ugandan shilling random",
5992         "1.00 Ugandan shillings (1966\\u20131987) random",
5993         "1.00 Ugandan shillings random",
5994         "1.00 Ukrainian Hryvnia random",
5995         "1.00 Ukrainian Karbovanets random",
5996         "1.00 Ukrainian hryvnia random",
5997         "1.00 Ukrainian hryvnias random",
5998         "1.00 Ukrainian karbovanets random",
5999         "1.00 Ukrainian karbovantsiv random",
6000         "1.00 Colombian Real Value Unit random",
6001         "1.00 United Arab Emirates Dirham random",
6002         "1.00 Unknown Currency random",
6003         "1.00 Uruguayan Peso (1975\\u20131993) random",
6004         "1.00 Uruguayan Peso random",
6005         "1.00 Uruguayan Peso (Indexed Units) random",
6006         "1.00 Uruguayan peso (1975\\u20131993) random",
6007         "1.00 Uruguayan peso (indexed units) random",
6008         "1.00 Uruguayan peso random",
6009         "1.00 Uruguayan pesos (1975\\u20131993) random",
6010         "1.00 Uruguayan pesos (indexed units) random",
6011         "1.00 Uzbekistani Som random",
6012         "1.00 Uzbekistani som random",
6013         "1.00 Uzbekistani som random",
6014         "1.00 Vanuatu Vatu random",
6015         "1.00 Vanuatu vatu random",
6016         "1.00 Vanuatu vatus random",
6017         "1.00 Venezuelan Bol\\u00edvar random",
6018         "1.00 Venezuelan Bol\\u00edvar (1871\\u20132008) random",
6019         "1.00 Venezuelan bol\\u00edvar random",
6020         "1.00 Venezuelan bol\\u00edvars random",
6021         "1.00 Venezuelan bol\\u00edvar (1871\\u20132008) random",
6022         "1.00 Venezuelan bol\\u00edvars (1871\\u20132008) random",
6023         "1.00 Vietnamese Dong random",
6024         "1.00 Vietnamese dong random",
6025         "1.00 Vietnamese dong random",
6026         "1.00 WIR Euro random",
6027         "1.00 WIR Franc random",
6028         "1.00 WIR euro random",
6029         "1.00 WIR euros random",
6030         "1.00 WIR franc random",
6031         "1.00 WIR francs random",
6032         "1.00 Samoan Tala random",
6033         "1.00 Samoan tala random",
6034         "1.00 Samoan tala random",
6035         "1.00 Yemeni Dinar random",
6036         "1.00 Yemeni Rial random",
6037         "1.00 Yemeni dinar random",
6038         "1.00 Yemeni dinars random",
6039         "1.00 Yemeni rial random",
6040         "1.00 Yemeni rials random",
6041         "1.00 Yugoslavian Convertible Dinar (1990\\u20131992) random",
6042         "1.00 Yugoslavian Hard Dinar (1966\\u20131990) random",
6043         "1.00 Yugoslavian New Dinar (1994\\u20132002) random",
6044         "1.00 Yugoslavian convertible dinar (1990\\u20131992) random",
6045         "1.00 Yugoslavian convertible dinars (1990\\u20131992) random",
6046         "1.00 Yugoslavian hard dinar (1966\\u20131990) random",
6047         "1.00 Yugoslavian hard dinars (1966\\u20131990) random",
6048         "1.00 Yugoslavian new dinar (1994\\u20132002) random",
6049         "1.00 Yugoslavian new dinars (1994\\u20132002) random",
6050         "1.00 Zairean New Zaire (1993\\u20131998) random",
6051         "1.00 Zairean Zaire (1971\\u20131993) random",
6052         "1.00 Zairean new zaire (1993\\u20131998) random",
6053         "1.00 Zairean new zaires (1993\\u20131998) random",
6054         "1.00 Zairean zaire (1971\\u20131993) random",
6055         "1.00 Zairean zaires (1971\\u20131993) random",
6056         "1.00 Zambian Kwacha random",
6057         "1.00 Zambian kwacha random",
6058         "1.00 Zambian kwachas random",
6059         "1.00 Zimbabwean Dollar (1980\\u20132008) random",
6060         "1.00 Zimbabwean dollar (1980\\u20132008) random",
6061         "1.00 Zimbabwean dollars (1980\\u20132008) random",
6062         "1.00 euro random",
6063         "1.00 euros random",
6064         "1.00 Turkish lira (1922\\u20132005) random",
6065         "1.00 special drawing rights random",
6066         "1.00 Colombian real value unit random",
6067         "1.00 Colombian real value units random",
6068         "1.00 unknown currency random",
6069     };
6070 
6071     const char* WRONG_DATA[] = {
6072         // Following are missing one last char in the currency name
6073         "1.00 Nicaraguan Cordob",
6074         "1.00 Namibian Dolla",
6075         "1.00 Namibian dolla",
6076         "1.00 Nepalese Rupe",
6077         "1.00 Nepalese rupe",
6078         "1.00 Netherlands Antillean Guilde",
6079         "1.00 Netherlands Antillean guilde",
6080         "1.00 Dutch Guilde",
6081         "1.00 Dutch guilde",
6082         "1.00 Israeli New Sheqe",
6083         "1.00 New Zealand Dolla",
6084         "1.00 New Zealand dolla",
6085         "1.00 Nicaraguan cordob",
6086         "1.00 Nigerian Nair",
6087         "1.00 Nigerian nair",
6088         "1.00 North Korean Wo",
6089         "1.00 North Korean wo",
6090         "1.00 Norwegian Kron",
6091         "1.00 Norwegian kron",
6092         "1.00 US dolla",
6093         "1.00",
6094         "A1.00",
6095         "AD1.00",
6096         "AE1.00",
6097         "AF1.00",
6098         "AL1.00",
6099         "AM1.00",
6100         "AN1.00",
6101         "AO1.00",
6102         "AR1.00",
6103         "AT1.00",
6104         "AU1.00",
6105         "AW1.00",
6106         "AZ1.00",
6107         "Afghan Afghan1.00",
6108         "Afghan Afghani (1927\\u201320021.00",
6109         "Afl1.00",
6110         "Albanian Le1.00",
6111         "Algerian Dina1.00",
6112         "Andorran Peset1.00",
6113         "Angolan Kwanz1.00",
6114         "Angolan Kwanza (1977\\u201319901.00",
6115         "Angolan Readjusted Kwanza (1995\\u201319991.00",
6116         "Angolan New Kwanza (1990\\u201320001.00",
6117         "Argentine Austra1.00",
6118         "Argentine Pes1.00",
6119         "Argentine Peso (1983\\u201319851.00",
6120         "Armenian Dra1.00",
6121         "Aruban Flori1.00",
6122         "Australian Dolla1.00",
6123         "Austrian Schillin1.00",
6124         "Azerbaijani Mana1.00",
6125         "Azerbaijani Manat (1993\\u201320061.00",
6126         "B1.00",
6127         "BA1.00",
6128         "BB1.00",
6129         "BE1.00",
6130         "BG1.00",
6131         "BH1.00",
6132         "BI1.00",
6133         "BM1.00",
6134         "BN1.00",
6135         "BO1.00",
6136         "BR1.00",
6137         "BS1.00",
6138         "BT1.00",
6139         "BU1.00",
6140         "BW1.00",
6141         "BY1.00",
6142         "BZ1.00",
6143         "Bahamian Dolla1.00",
6144         "Bahraini Dina1.00",
6145         "Bangladeshi Tak1.00",
6146         "Barbadian Dolla1.00",
6147         "Bds1.00",
6148         "Belarusian Ruble (1994\\u201319991.00",
6149         "Belarusian Rubl1.00",
6150         "Belgian Fran1.00",
6151         "Belgian Franc (convertible1.00",
6152         "Belgian Franc (financial1.00",
6153         "Belize Dolla1.00",
6154         "Bermudan Dolla1.00",
6155         "Bhutanese Ngultru1.00",
6156         "Bolivian Mvdo1.00",
6157         "Bolivian Pes1.00",
6158         "Bolivian Bolivian1.00",
6159         "Bosnia-Herzegovina Convertible Mar1.00",
6160         "Bosnia-Herzegovina Dina1.00",
6161         "Botswanan Pul1.00",
6162         "Brazilian Cruzad1.00",
6163         "Brazilian Cruzado Nov1.00",
6164         "Brazilian Cruzeir1.00",
6165         "Brazilian Cruzeiro (1990\\u201319931.00",
6166         "Brazilian New Cruzeiro (1967\\u201319861.00",
6167         "Brazilian Rea1.00",
6168         "British Pound Sterlin1.00",
6169         "Brunei Dolla1.00",
6170         "Bulgarian Hard Le1.00",
6171         "Bulgarian Le1.00",
6172         "Burmese Kya1.00",
6173         "Burundian Fran1.00",
6174         "C1.00",
6175         "CA1.00",
6176         "CD1.00",
6177         "CFP Fran1.00",
6178         "CFP1.00",
6179         "CH1.00",
6180         "CL1.00",
6181         "CN1.00",
6182         "CO1.00",
6183         "CS1.00",
6184         "CU1.00",
6185         "CV1.00",
6186         "CY1.00",
6187         "CZ1.00",
6188         "Cambodian Rie1.00",
6189         "Canadian Dolla1.00",
6190         "Cape Verdean Escud1.00",
6191         "Cayman Islands Dolla1.00",
6192         "Chilean Pes1.00",
6193         "Chilean Unit of Accoun1.00",
6194         "Chinese Yua1.00",
6195         "Colombian Pes1.00",
6196         "Comoro Fran1.00",
6197         "Congolese Fran1.00",
6198         "Costa Rican Col\\u00f31.00",
6199         "Croatian Dina1.00",
6200         "Croatian Kun1.00",
6201         "Cuban Pes1.00",
6202         "Cypriot Poun1.00",
6203         "Czech Republic Korun1.00",
6204         "Czechoslovak Hard Korun1.00",
6205         "D1.00",
6206         "DD1.00",
6207         "DE1.00",
6208         "DJ1.00",
6209         "DK1.00",
6210         "DO1.00",
6211         "DZ1.00",
6212         "Danish Kron1.00",
6213         "German Mar1.00",
6214         "Djiboutian Fran1.00",
6215         "Dk1.00",
6216         "Dominican Pes1.00",
6217         "EC1.00",
6218         "EE1.00",
6219         "EG1.00",
6220         "EQ1.00",
6221         "ER1.00",
6222         "ES1.00",
6223         "ET1.00",
6224         "EU1.00",
6225         "East Caribbean Dolla1.00",
6226         "East German Ostmar1.00",
6227         "Ecuadorian Sucr1.00",
6228         "Ecuadorian Unit of Constant Valu1.00",
6229         "Egyptian Poun1.00",
6230         "Ekwel1.00",
6231         "Salvadoran Col\\u00f31.00",
6232         "Equatorial Guinean Ekwel1.00",
6233         "Eritrean Nakf1.00",
6234         "Es1.00",
6235         "Estonian Kroo1.00",
6236         "Ethiopian Bir1.00",
6237         "Eur1.00",
6238         "European Composite Uni1.00",
6239         "European Currency Uni1.00",
6240         "European Monetary Uni1.00",
6241         "European Unit of Account (XBC1.00",
6242         "European Unit of Account (XBD1.00",
6243         "F1.00",
6244         "FB1.00",
6245         "FI1.00",
6246         "FJ1.00",
6247         "FK1.00",
6248         "FR1.00",
6249         "Falkland Islands Poun1.00",
6250         "Fd1.00",
6251         "Fijian Dolla1.00",
6252         "Finnish Markk1.00",
6253         "Fr1.00",
6254         "French Fran1.00",
6255         "French Gold Fran1.00",
6256         "French UIC-Fran1.00",
6257         "G1.00",
6258         "GB1.00",
6259         "GE1.00",
6260         "GH1.00",
6261         "GI1.00",
6262         "GM1.00",
6263         "GN1.00",
6264         "GQ1.00",
6265         "GR1.00",
6266         "GT1.00",
6267         "GW1.00",
6268         "GY1.00",
6269         "Gambian Dalas1.00",
6270         "Georgian Kupon Lari1.00",
6271         "Georgian Lar1.00",
6272         "Ghanaian Ced1.00",
6273         "Ghanaian Cedi (1979\\u201320071.00",
6274         "Gibraltar Poun1.00",
6275         "Gol1.00",
6276         "Greek Drachm1.00",
6277         "Guatemalan Quetza1.00",
6278         "Guinean Fran1.00",
6279         "Guinean Syl1.00",
6280         "Guinea-Bissau Pes1.00",
6281         "Guyanaese Dolla1.00",
6282         "HK1.00",
6283         "HN1.00",
6284         "HR1.00",
6285         "HT1.00",
6286         "HU1.00",
6287         "Haitian Gourd1.00",
6288         "Honduran Lempir1.00",
6289         "Hong Kong Dolla1.00",
6290         "Hungarian Forin1.00",
6291         "I1.00",
6292         "IE1.00",
6293         "IL1.00",
6294         "IN1.00",
6295         "IQ1.00",
6296         "IR1.00",
6297         "IS1.00",
6298         "IT1.00",
6299         "Icelandic Kron1.00",
6300         "Indian Rupe1.00",
6301         "Indonesian Rupia1.00",
6302         "Iranian Ria1.00",
6303         "Iraqi Dina1.00",
6304         "Irish Poun1.00",
6305         "Israeli Poun1.00",
6306         "Italian Lir1.00",
6307         "J1.00",
6308         "JM1.00",
6309         "JO1.00",
6310         "JP1.00",
6311         "Jamaican Dolla1.00",
6312         "Japanese Ye1.00",
6313         "Jordanian Dina1.00",
6314         "K S1.00",
6315         "K1.00",
6316         "KE1.00",
6317         "KG1.00",
6318         "KH1.00",
6319         "KP1.00",
6320         "KR1.00",
6321         "KW1.00",
6322         "KY1.00",
6323         "KZ1.00",
6324         "Kazakhstani Teng1.00",
6325         "Kenyan Shillin1.00",
6326         "Kuwaiti Dina1.00",
6327         "Kyrgystani So1.00",
6328         "LA1.00",
6329         "LB1.00",
6330         "LK1.00",
6331         "LR1.00",
6332         "LT1.00",
6333         "LU1.00",
6334         "LV1.00",
6335         "LY1.00",
6336         "Laotian Ki1.00",
6337         "Latvian Lat1.00",
6338         "Latvian Rubl1.00",
6339         "Lebanese Poun1.00",
6340         "Lesotho Lot1.00",
6341         "Liberian Dolla1.00",
6342         "Libyan Dina1.00",
6343         "Lithuanian Lit1.00",
6344         "Lithuanian Talona1.00",
6345         "Luxembourgian Convertible Fran1.00",
6346         "Luxembourg Financial Fran1.00",
6347         "Luxembourgian Fran1.00",
6348         "MA1.00",
6349         "MD1.00",
6350         "MDe1.00",
6351         "MEX1.00",
6352         "MG1.00",
6353         "ML1.00",
6354         "MM1.00",
6355         "MN1.00",
6356         "MO1.00",
6357         "MR1.00",
6358         "MT1.00",
6359         "MU1.00",
6360         "MV1.00",
6361         "MW1.00",
6362         "MX1.00",
6363         "MY1.00",
6364         "MZ1.00",
6365         "Macanese Patac1.00",
6366         "Macedonian Dena1.00",
6367         "Malagasy Ariar1.00",
6368         "Malagasy Fran1.00",
6369         "Malawian Kwach1.00",
6370         "Malaysian Ringgi1.00",
6371         "Maldivian Rufiya1.00",
6372         "Malian Fran1.00",
6373         "Malot1.00",
6374         "Maltese Lir1.00",
6375         "Maltese Poun1.00",
6376         "Mauritanian Ouguiy1.00",
6377         "Mauritian Rupe1.00",
6378         "Mexican Pes1.00",
6379         "Mexican Silver Peso (1861\\u201319921.00",
6380         "Mexican Investment Uni1.00",
6381         "Moldovan Le1.00",
6382         "Mongolian Tugri1.00",
6383         "Moroccan Dirha1.00",
6384         "Moroccan Fran1.00",
6385         "Mozambican Escud1.00",
6386         "Mozambican Metica1.00",
6387         "Myanmar Kya1.00",
6388         "N1.00",
6389         "NA1.00",
6390         "NAf1.00",
6391         "NG1.00",
6392         "NI1.00",
6393         "NK1.00",
6394         "NL1.00",
6395         "NO1.00",
6396         "NP1.00",
6397         "NT1.00",
6398         "Namibian Dolla1.00",
6399         "Nepalese Rupe1.00",
6400         "Netherlands Antillean Guilde1.00",
6401         "Dutch Guilde1.00",
6402         "Israeli New Sheqe1.00",
6403         "New Zealand Dolla1.00",
6404         "Nicaraguan C\\u00f3rdoba (1988\\u201319911.00",
6405         "Nicaraguan C\\u00f3rdob1.00",
6406         "Nigerian Nair1.00",
6407         "North Korean Wo1.00",
6408         "Norwegian Kron1.00",
6409         "Nr1.00",
6410         "OM1.00",
6411         "Old Mozambican Metica1.00",
6412         "Romanian Leu (1952\\u201320061.00",
6413         "Serbian Dinar (2002\\u201320061.00",
6414         "Sudanese Dinar (1992\\u201320071.00",
6415         "Sudanese Pound (1957\\u201319981.00",
6416         "Turkish Lira (1922\\u201320051.00",
6417         "Omani Ria1.00",
6418         "PA1.00",
6419         "PE1.00",
6420         "PG1.00",
6421         "PH1.00",
6422         "PK1.00",
6423         "PL1.00",
6424         "PT1.00",
6425         "PY1.00",
6426         "Pakistani Rupe1.00",
6427         "Palladiu1.00",
6428         "Panamanian Balbo1.00",
6429         "Papua New Guinean Kin1.00",
6430         "Paraguayan Guaran1.00",
6431         "Peruvian Int1.00",
6432         "Peruvian Sol (1863\\u201319651.00",
6433         "Peruvian Sol Nuev1.00",
6434         "Philippine Pes1.00",
6435         "Platinu1.00",
6436         "Polish Zlot1.00",
6437         "Polish Zloty (1950\\u201319951.00",
6438         "Portuguese Escud1.00",
6439         "Portuguese Guinea Escud1.00",
6440         "Pr1.00",
6441         "QA1.00",
6442         "Qatari Riya1.00",
6443         "RD1.00",
6444         "RH1.00",
6445         "RINET Fund1.00",
6446         "RS1.00",
6447         "RU1.00",
6448         "RW1.00",
6449         "Rb1.00",
6450         "Rhodesian Dolla1.00",
6451         "Romanian Le1.00",
6452         "Russian Rubl1.00",
6453         "Russian Ruble (1991\\u201319981.00",
6454         "Rwandan Fran1.00",
6455         "S1.00",
6456         "SA1.00",
6457         "SB1.00",
6458         "SC1.00",
6459         "SD1.00",
6460         "SE1.00",
6461         "SG1.00",
6462         "SH1.00",
6463         "SI1.00",
6464         "SK1.00",
6465         "SL R1.00",
6466         "SL1.00",
6467         "SO1.00",
6468         "ST1.00",
6469         "SU1.00",
6470         "SV1.00",
6471         "SY1.00",
6472         "SZ1.00",
6473         "St. Helena Poun1.00",
6474         "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobr1.00",
6475         "Saudi Riya1.00",
6476         "Serbian Dina1.00",
6477         "Seychellois Rupe1.00",
6478         "Sh1.00",
6479         "Sierra Leonean Leon1.00",
6480         "Silve1.00",
6481         "Singapore Dolla1.00",
6482         "Slovak Korun1.00",
6483         "Slovenian Tola1.00",
6484         "Solomon Islands Dolla1.00",
6485         "Somali Shillin1.00",
6486         "South African Ran1.00",
6487         "South African Rand (financial1.00",
6488         "South Korean Wo1.00",
6489         "Soviet Roubl1.00",
6490         "Spanish Peset1.00",
6491         "Spanish Peseta (A account1.00",
6492         "Spanish Peseta (convertible account1.00",
6493         "Special Drawing Right1.00",
6494         "Sri Lankan Rupe1.00",
6495         "Sudanese Poun1.00",
6496         "Surinamese Dolla1.00",
6497         "Surinamese Guilde1.00",
6498         "Swazi Lilangen1.00",
6499         "Swedish Kron1.00",
6500         "Swiss Fran1.00",
6501         "Syrian Poun1.00",
6502         "T S1.00",
6503         "TH1.00",
6504         "TJ1.00",
6505         "TM1.00",
6506         "TN1.00",
6507         "TO1.00",
6508         "TP1.00",
6509         "TR1.00",
6510         "TT1.00",
6511         "TW1.00",
6512         "TZ1.00",
6513         "New Taiwan Dolla1.00",
6514         "Tajikistani Rubl1.00",
6515         "Tajikistani Somon1.00",
6516         "Tanzanian Shillin1.00",
6517         "Testing Currency Cod1.00",
6518         "Thai Bah1.00",
6519         "Timorese Escud1.00",
6520         "Tongan Pa\\u20bbang1.00",
6521         "Trinidad & Tobago Dolla1.00",
6522         "Tunisian Dina1.00",
6523         "Turkish Lir1.00",
6524         "Turkmenistani Mana1.00",
6525         "U S1.00",
6526         "U1.00",
6527         "UA1.00",
6528         "UG1.00",
6529         "US Dolla1.00",
6530         "US Dollar (Next day1.00",
6531         "US Dollar (Same day1.00",
6532         "US1.00",
6533         "UY1.00",
6534         "UZ1.00",
6535         "Ugandan Shillin1.00",
6536         "Ugandan Shilling (1966\\u201319871.00",
6537         "Ukrainian Hryvni1.00",
6538         "Ukrainian Karbovanet1.00",
6539         "Colombian Real Value Uni1.00",
6540         "United Arab Emirates Dirha1.00",
6541         "Unknown Currenc1.00",
6542         "Ur1.00",
6543         "Uruguay Peso (1975\\u201319931.00",
6544         "Uruguay Peso Uruguay1.00",
6545         "Uruguay Peso (Indexed Units1.00",
6546         "Uzbekistani So1.00",
6547         "V1.00",
6548         "VE1.00",
6549         "VN1.00",
6550         "VU1.00",
6551         "Vanuatu Vat1.00",
6552         "Venezuelan Bol\\u00edva1.00",
6553         "Venezuelan Bol\\u00edvar Fuert1.00",
6554         "Vietnamese Don1.00",
6555         "West African CFA Fran1.00",
6556         "Central African CFA Fran1.00",
6557         "WIR Eur1.00",
6558         "WIR Fran1.00",
6559         "WS1.00",
6560         "Samoa Tal1.00",
6561         "XA1.00",
6562         "XB1.00",
6563         "XC1.00",
6564         "XD1.00",
6565         "XE1.00",
6566         "XF1.00",
6567         "XO1.00",
6568         "XP1.00",
6569         "XR1.00",
6570         "XT1.00",
6571         "XX1.00",
6572         "YD1.00",
6573         "YE1.00",
6574         "YU1.00",
6575         "Yemeni Dina1.00",
6576         "Yemeni Ria1.00",
6577         "Yugoslavian Convertible Dina1.00",
6578         "Yugoslavian Hard Dinar (1966\\u201319901.00",
6579         "Yugoslavian New Dina1.00",
6580         "Z1.00",
6581         "ZA1.00",
6582         "ZM1.00",
6583         "ZR1.00",
6584         "ZW1.00",
6585         "Zairean New Zaire (1993\\u201319981.00",
6586         "Zairean Zair1.00",
6587         "Zambian Kwach1.00",
6588         "Zimbabwean Dollar (1980\\u201320081.00",
6589         "dra1.00",
6590         "lar1.00",
6591         "le1.00",
6592         "man1.00",
6593         "so1.00",
6594     };
6595 
6596     Locale locale("en_US");
6597     for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
6598         UnicodeString formatted = ctou(DATA[i]);
6599         UErrorCode status = U_ZERO_ERROR;
6600         LocalPointer<NumberFormat> numFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status), status);
6601         if (!assertSuccess("", status, true, __FILE__, __LINE__)) {
6602             return;
6603         }
6604         // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
6605         numFmt->setLenient(true);
6606         ParsePosition parsePos;
6607         LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6608         if (parsePos.getIndex() > 0) {
6609             double doubleVal = currAmt->getNumber().getDouble(status);
6610             if ( doubleVal != 1.0 ) {
6611                 errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
6612             }
6613         } else {
6614             errln("Failed to parse as currency: " + formatted);
6615         }
6616     }
6617 
6618     for (uint32_t i=0; i<UPRV_LENGTHOF(WRONG_DATA); ++i) {
6619       UnicodeString formatted = ctou(WRONG_DATA[i]);
6620       UErrorCode status = U_ZERO_ERROR;
6621       NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6622       if (numFmt != NULL && U_SUCCESS(status)) {
6623           ParsePosition parsePos;
6624           LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6625           if (parsePos.getIndex() > 0) {
6626               double doubleVal = currAmt->getNumber().getDouble(status);
6627               errln("Parsed as currency, should not have: " + formatted + " -> " + doubleVal);
6628           }
6629       } else {
6630           dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));
6631           delete numFmt;
6632           break;
6633       }
6634       delete numFmt;
6635     }
6636 }
6637 
6638 const char* attrString(int32_t);
6639 
6640 // UnicodeString s;
6641 //  std::string ss;
6642 //  std::cout << s.toUTF8String(ss)
expectPositions(FieldPositionIterator& iter, int32_t *values, int32_t tupleCount, const UnicodeString& str)6643 void NumberFormatTest::expectPositions(FieldPositionIterator& iter, int32_t *values, int32_t tupleCount,
6644                                        const UnicodeString& str)  {
6645   UBool found[10];
6646   FieldPosition fp;
6647 
6648   if (tupleCount > 10) {
6649     assertTrue("internal error, tupleCount too large", false);
6650   } else {
6651     for (int i = 0; i < tupleCount; ++i) {
6652       found[i] = false;
6653     }
6654   }
6655 
6656   logln(str);
6657   while (iter.next(fp)) {
6658     UBool ok = false;
6659     int32_t id = fp.getField();
6660     int32_t start = fp.getBeginIndex();
6661     int32_t limit = fp.getEndIndex();
6662 
6663     // is there a logln using printf?
6664     char buf[128];
6665     sprintf(buf, "%24s %3d %3d %3d", attrString(id), id, start, limit);
6666     logln(buf);
6667 
6668     for (int i = 0; i < tupleCount; ++i) {
6669       if (found[i]) {
6670         continue;
6671       }
6672       if (values[i*3] == id &&
6673           values[i*3+1] == start &&
6674           values[i*3+2] == limit) {
6675         found[i] = ok = true;
6676         break;
6677       }
6678     }
6679 
6680     assertTrue((UnicodeString)"found [" + id + "," + start + "," + limit + "]", ok);
6681   }
6682 
6683   // check that all were found
6684   UBool ok = true;
6685   for (int i = 0; i < tupleCount; ++i) {
6686     if (!found[i]) {
6687       ok = false;
6688       assertTrue((UnicodeString) "missing [" + values[i*3] + "," + values[i*3+1] + "," + values[i*3+2] + "]", found[i]);
6689     }
6690   }
6691   assertTrue("no expected values were missing", ok);
6692 }
6693 
expectPosition(FieldPosition& pos, int32_t id, int32_t start, int32_t limit, const UnicodeString& str)6694 void NumberFormatTest::expectPosition(FieldPosition& pos, int32_t id, int32_t start, int32_t limit,
6695                                        const UnicodeString& str)  {
6696   logln(str);
6697   assertTrue((UnicodeString)"id " + id + " == " + pos.getField(), id == pos.getField());
6698   assertTrue((UnicodeString)"begin " + start + " == " + pos.getBeginIndex(), start == pos.getBeginIndex());
6699   assertTrue((UnicodeString)"end " + limit + " == " + pos.getEndIndex(), limit == pos.getEndIndex());
6700 }
6701 
TestFieldPositionIterator()6702 void NumberFormatTest::TestFieldPositionIterator() {
6703   // bug 7372
6704   UErrorCode status = U_ZERO_ERROR;
6705   FieldPositionIterator iter1;
6706   FieldPositionIterator iter2;
6707   FieldPosition pos;
6708 
6709   DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(status);
6710   if (failure(status, "NumberFormat::createInstance", true)) return;
6711 
6712   double num = 1234.56;
6713   UnicodeString str1;
6714   UnicodeString str2;
6715 
6716   assertTrue((UnicodeString)"self==", iter1 == iter1);
6717   assertTrue((UnicodeString)"iter1==iter2", iter1 == iter2);
6718 
6719   decFmt->format(num, str1, &iter1, status);
6720   assertTrue((UnicodeString)"iter1 != iter2", iter1 != iter2);
6721   decFmt->format(num, str2, &iter2, status);
6722   assertTrue((UnicodeString)"iter1 == iter2 (2)", iter1 == iter2);
6723   iter1.next(pos);
6724   assertTrue((UnicodeString)"iter1 != iter2 (2)", iter1 != iter2);
6725   iter2.next(pos);
6726   assertTrue((UnicodeString)"iter1 == iter2 (3)", iter1 == iter2);
6727 
6728   // should format ok with no iterator
6729   str2.remove();
6730   decFmt->format(num, str2, NULL, status);
6731   assertEquals("null fpiter", str1, str2);
6732 
6733   delete decFmt;
6734 }
6735 
TestFormatAttributes()6736 void NumberFormatTest::TestFormatAttributes() {
6737   Locale locale("en_US");
6738   UErrorCode status = U_ZERO_ERROR;
6739   DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6740     if (failure(status, "NumberFormat::createInstance", true)) return;
6741   double val = 12345.67;
6742 
6743   {
6744     int32_t expected[] = {
6745       UNUM_CURRENCY_FIELD, 0, 1,
6746       UNUM_GROUPING_SEPARATOR_FIELD, 3, 4,
6747       UNUM_INTEGER_FIELD, 1, 7,
6748       UNUM_DECIMAL_SEPARATOR_FIELD, 7, 8,
6749       UNUM_FRACTION_FIELD, 8, 10,
6750     };
6751     int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6752 
6753     FieldPositionIterator posIter;
6754     UnicodeString result;
6755     decFmt->format(val, result, &posIter, status);
6756     expectPositions(posIter, expected, tupleCount, result);
6757   }
6758   {
6759     FieldPosition fp(UNUM_INTEGER_FIELD);
6760     UnicodeString result;
6761     decFmt->format(val, result, fp);
6762     expectPosition(fp, UNUM_INTEGER_FIELD, 1, 7, result);
6763   }
6764   {
6765     FieldPosition fp(UNUM_FRACTION_FIELD);
6766     UnicodeString result;
6767     decFmt->format(val, result, fp);
6768     expectPosition(fp, UNUM_FRACTION_FIELD, 8, 10, result);
6769   }
6770   delete decFmt;
6771 
6772   decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_SCIENTIFIC, status);
6773   val = -0.0000123;
6774   {
6775     int32_t expected[] = {
6776       UNUM_SIGN_FIELD, 0, 1,
6777       UNUM_INTEGER_FIELD, 1, 2,
6778       UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3,
6779       UNUM_FRACTION_FIELD, 3, 5,
6780       UNUM_EXPONENT_SYMBOL_FIELD, 5, 6,
6781       UNUM_EXPONENT_SIGN_FIELD, 6, 7,
6782       UNUM_EXPONENT_FIELD, 7, 8
6783     };
6784     int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6785 
6786     FieldPositionIterator posIter;
6787     UnicodeString result;
6788     decFmt->format(val, result, &posIter, status);
6789     expectPositions(posIter, expected, tupleCount, result);
6790   }
6791   {
6792     FieldPosition fp(UNUM_INTEGER_FIELD);
6793     UnicodeString result;
6794     decFmt->format(val, result, fp);
6795     expectPosition(fp, UNUM_INTEGER_FIELD, 1, 2, result);
6796   }
6797   {
6798     FieldPosition fp(UNUM_FRACTION_FIELD);
6799     UnicodeString result;
6800     decFmt->format(val, result, fp);
6801     expectPosition(fp, UNUM_FRACTION_FIELD, 3, 5, result);
6802   }
6803   delete decFmt;
6804 
6805   fflush(stderr);
6806 }
6807 
attrString(int32_t attrId)6808 const char* attrString(int32_t attrId) {
6809   switch (attrId) {
6810     case UNUM_INTEGER_FIELD: return "integer";
6811     case UNUM_FRACTION_FIELD: return "fraction";
6812     case UNUM_DECIMAL_SEPARATOR_FIELD: return "decimal separator";
6813     case UNUM_EXPONENT_SYMBOL_FIELD: return "exponent symbol";
6814     case UNUM_EXPONENT_SIGN_FIELD: return "exponent sign";
6815     case UNUM_EXPONENT_FIELD: return "exponent";
6816     case UNUM_GROUPING_SEPARATOR_FIELD: return "grouping separator";
6817     case UNUM_CURRENCY_FIELD: return "currency";
6818     case UNUM_PERCENT_FIELD: return "percent";
6819     case UNUM_PERMILL_FIELD: return "permille";
6820     case UNUM_SIGN_FIELD: return "sign";
6821     default: return "";
6822   }
6823 }
6824 
6825 //
6826 //   Test formatting & parsing of big decimals.
6827 //      API test, not a comprehensive test.
6828 //      See DecimalFormatTest/DataDrivenTests
6829 //
6830 #define ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \
6831     assertSuccess(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (status)); \
6832 } UPRV_BLOCK_MACRO_END
6833 #define ASSERT_EQUALS(expected, actual) UPRV_BLOCK_MACRO_BEGIN { \
6834     assertEquals(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (expected), (actual)); \
6835 } UPRV_BLOCK_MACRO_END
6836 
TestDecimal()6837 void NumberFormatTest::TestDecimal() {
6838     {
6839         UErrorCode  status = U_ZERO_ERROR;
6840         Formattable f("12.345678999987654321E666", status);
6841         ASSERT_SUCCESS(status);
6842         StringPiece s = f.getDecimalNumber(status);
6843         ASSERT_SUCCESS(status);
6844         ASSERT_EQUALS("1.2345678999987654321E+667", s.data());
6845         //printf("%s\n", s.data());
6846     }
6847 
6848     {
6849         UErrorCode status = U_ZERO_ERROR;
6850         Formattable f1("this is not a number", status);
6851         ASSERT_EQUALS(U_DECIMAL_NUMBER_SYNTAX_ERROR, status);
6852     }
6853 
6854     {
6855         UErrorCode status = U_ZERO_ERROR;
6856         Formattable f;
6857         f.setDecimalNumber("123.45", status);
6858         ASSERT_SUCCESS(status);
6859         ASSERT_EQUALS( Formattable::kDouble, f.getType());
6860         ASSERT_EQUALS(123.45, f.getDouble());
6861         ASSERT_EQUALS(123.45, f.getDouble(status));
6862         ASSERT_SUCCESS(status);
6863         ASSERT_EQUALS("123.45", f.getDecimalNumber(status).data());
6864         ASSERT_SUCCESS(status);
6865 
6866         f.setDecimalNumber("4.5678E7", status);
6867         int32_t n;
6868         n = f.getLong();
6869         ASSERT_EQUALS(45678000, n);
6870 
6871         status = U_ZERO_ERROR;
6872         f.setDecimalNumber("-123", status);
6873         ASSERT_SUCCESS(status);
6874         ASSERT_EQUALS( Formattable::kLong, f.getType());
6875         ASSERT_EQUALS(-123, f.getLong());
6876         ASSERT_EQUALS(-123, f.getLong(status));
6877         ASSERT_SUCCESS(status);
6878         ASSERT_EQUALS("-123", f.getDecimalNumber(status).data());
6879         ASSERT_SUCCESS(status);
6880 
6881         status = U_ZERO_ERROR;
6882         f.setDecimalNumber("1234567890123", status);  // Number too big for 32 bits
6883         ASSERT_SUCCESS(status);
6884         ASSERT_EQUALS( Formattable::kInt64, f.getType());
6885         ASSERT_EQUALS(1234567890123LL, f.getInt64());
6886         ASSERT_EQUALS(1234567890123LL, f.getInt64(status));
6887         ASSERT_SUCCESS(status);
6888         ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status).data());
6889         ASSERT_SUCCESS(status);
6890     }
6891 
6892     {
6893         UErrorCode status = U_ZERO_ERROR;
6894         NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6895         if (U_FAILURE(status) || fmtr == NULL) {
6896             dataerrln("Unable to create NumberFormat");
6897         } else {
6898             UnicodeString formattedResult;
6899             StringPiece num("244444444444444444444444444444444444446.4");
6900             fmtr->format(num, formattedResult, NULL, status);
6901             ASSERT_SUCCESS(status);
6902             ASSERT_EQUALS("244,444,444,444,444,444,444,444,444,444,444,444,446.4", formattedResult);
6903             //std::string ss; std::cout << formattedResult.toUTF8String(ss);
6904             delete fmtr;
6905         }
6906     }
6907 
6908     {
6909         // Check formatting a DigitList.  DigitList is internal, but this is
6910         // a critical interface that must work.
6911         UErrorCode status = U_ZERO_ERROR;
6912         NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6913         if (U_FAILURE(status) || fmtr == NULL) {
6914             dataerrln("Unable to create NumberFormat");
6915         } else {
6916             UnicodeString formattedResult;
6917             DecimalQuantity dl;
6918             StringPiece num("123.4566666666666666666666666666666666621E+40");
6919             dl.setToDecNumber(num, status);
6920             ASSERT_SUCCESS(status);
6921             fmtr->format(dl, formattedResult, NULL, status);
6922             ASSERT_SUCCESS(status);
6923             ASSERT_EQUALS("1,234,566,666,666,666,666,666,666,666,666,666,666,621,000", formattedResult);
6924 
6925             status = U_ZERO_ERROR;
6926             num.set("666.666");
6927             dl.setToDecNumber(num, status);
6928             FieldPosition pos(NumberFormat::FRACTION_FIELD);
6929             ASSERT_SUCCESS(status);
6930             formattedResult.remove();
6931             fmtr->format(dl, formattedResult, pos, status);
6932             ASSERT_SUCCESS(status);
6933             ASSERT_EQUALS("666.666", formattedResult);
6934             ASSERT_EQUALS(4, pos.getBeginIndex());
6935             ASSERT_EQUALS(7, pos.getEndIndex());
6936             delete fmtr;
6937         }
6938     }
6939 
6940     {
6941         // Check a parse with a formatter with a multiplier.
6942         UErrorCode status = U_ZERO_ERROR;
6943         NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_PERCENT, status);
6944         if (U_FAILURE(status) || fmtr == NULL) {
6945             dataerrln("Unable to create NumberFormat");
6946         } else {
6947             UnicodeString input = "1.84%";
6948             Formattable result;
6949             fmtr->parse(input, result, status);
6950             ASSERT_SUCCESS(status);
6951             ASSERT_EQUALS("0.0184", result.getDecimalNumber(status).data());
6952             //std::cout << result.getDecimalNumber(status).data();
6953             delete fmtr;
6954         }
6955     }
6956 
6957 #if U_PLATFORM != U_PF_CYGWIN || defined(CYGWINMSVC)
6958     /*
6959      * This test fails on Cygwin (1.7.16) using GCC because of a rounding issue with strtod().
6960      * See #9463
6961      */
6962     {
6963         // Check that a parse returns a decimal number with full accuracy
6964         UErrorCode status = U_ZERO_ERROR;
6965         NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6966         if (U_FAILURE(status) || fmtr == NULL) {
6967             dataerrln("Unable to create NumberFormat");
6968         } else {
6969             UnicodeString input = "1.002200044400088880000070000";
6970             Formattable result;
6971             fmtr->parse(input, result, status);
6972             ASSERT_SUCCESS(status);
6973             ASSERT_EQUALS(0, strcmp("1.00220004440008888000007", result.getDecimalNumber(status).data()));
6974             ASSERT_EQUALS(1.00220004440008888,   result.getDouble());
6975             //std::cout << result.getDecimalNumber(status).data();
6976             delete fmtr;
6977         }
6978     }
6979 #endif
6980 
6981 }
6982 
TestCurrencyFractionDigits()6983 void NumberFormatTest::TestCurrencyFractionDigits() {
6984     UErrorCode status = U_ZERO_ERROR;
6985     UnicodeString text1, text2;
6986     double value = 99.12345;
6987 
6988     // Create currenct instance
6989     NumberFormat* fmt = NumberFormat::createCurrencyInstance("ja_JP", status);
6990     if (U_FAILURE(status) || fmt == NULL) {
6991         dataerrln("Unable to create NumberFormat");
6992     } else {
6993         fmt->format(value, text1);
6994 
6995         // Reset the same currency and format the test value again
6996         fmt->setCurrency(fmt->getCurrency(), status);
6997         ASSERT_SUCCESS(status);
6998         fmt->format(value, text2);
6999 
7000         if (text1 != text2) {
7001             errln((UnicodeString)"NumberFormat::format() should return the same result - text1="
7002                 + text1 + " text2=" + text2);
7003         }
7004     }
7005     delete fmt;
7006 }
7007 
TestExponentParse()7008 void NumberFormatTest::TestExponentParse() {
7009 
7010     UErrorCode status = U_ZERO_ERROR;
7011     Formattable result;
7012     ParsePosition parsePos(0);
7013 
7014     // set the exponent symbol
7015     status = U_ZERO_ERROR;
7016     DecimalFormatSymbols symbols(Locale::getDefault(), status);
7017     if(U_FAILURE(status)) {
7018         dataerrln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (Default)");
7019         return;
7020     }
7021 
7022     // create format instance
7023     status = U_ZERO_ERROR;
7024     DecimalFormat fmt(u"#####", symbols, status);
7025     if(U_FAILURE(status)) {
7026         errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
7027     }
7028 
7029     // parse the text
7030     fmt.parse("5.06e-27", result, parsePos);
7031     if(result.getType() != Formattable::kDouble &&
7032        result.getDouble() != 5.06E-27 &&
7033        parsePos.getIndex() != 8
7034        )
7035     {
7036         errln("ERROR: parse failed - expected 5.06E-27, 8  - returned %d, %i",
7037               result.getDouble(), parsePos.getIndex());
7038     }
7039 }
7040 
TestExplicitParents()7041 void NumberFormatTest::TestExplicitParents() {
7042 
7043     /* Test that number formats are properly inherited from es_419 */
7044     /* These could be subject to change if the CLDR data changes */
7045     static const char* parentLocaleTests[][2]= {
7046     /* locale ID */  /* expected */
7047     {"es_CO", "1.250,75" },
7048     {"es_ES", "1.250,75" },
7049     {"es_GQ", "1.250,75" },
7050     {"es_MX", "1,250.75" },
7051     {"es_US", "1,250.75" },
7052     {"es_VE", "1.250,75" },
7053     };
7054 
7055     UnicodeString s;
7056 
7057     for(int i=0; i < UPRV_LENGTHOF(parentLocaleTests); i++){
7058         UErrorCode status = U_ZERO_ERROR;
7059         const char *localeID = parentLocaleTests[i][0];
7060         UnicodeString expected(parentLocaleTests[i][1], -1, US_INV);
7061         expected = expected.unescape();
7062         char loc[256]={0};
7063         uloc_canonicalize(localeID, loc, 256, &status);
7064         NumberFormat *fmt= NumberFormat::createInstance(Locale(loc), status);
7065         if(U_FAILURE(status)){
7066             dataerrln("Could not create number formatter for locale %s - %s",localeID, u_errorName(status));
7067             continue;
7068         }
7069         s.remove();
7070         fmt->format(1250.75, s);
7071         if(s!=expected){
7072             errln(UnicodeString("FAIL: Expected: ")+expected
7073                     + UnicodeString(" Got: ") + s
7074                     + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
7075         }
7076         if (U_FAILURE(status)){
7077             errln((UnicodeString)"FAIL: Status " + (int32_t)status);
7078         }
7079         delete fmt;
7080     }
7081 
7082 }
7083 
7084 /**
7085  * Test available numbering systems API.
7086  */
TestAvailableNumberingSystems()7087 void NumberFormatTest::TestAvailableNumberingSystems() {
7088     IcuTestErrorCode status(*this, "TestAvailableNumberingSystems");
7089     StringEnumeration *availableNumberingSystems = NumberingSystem::getAvailableNames(status);
7090     CHECK_DATA(status, "NumberingSystem::getAvailableNames()");
7091 
7092     int32_t nsCount = availableNumberingSystems->count(status);
7093     if ( nsCount < 74 ) {
7094         errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 74, got %d",nsCount);
7095     }
7096 
7097     /* A relatively simple test of the API.  We call getAvailableNames() and cycle through */
7098     /* each name returned, attempting to create a numbering system based on that name and  */
7099     /* verifying that the name returned from the resulting numbering system is the same    */
7100     /* one that we initially thought.                                                      */
7101 
7102     int32_t len;
7103     const char* prevName = nullptr;
7104     for ( int32_t i = 0 ; i < nsCount ; i++ ) {
7105         const char *nsname = availableNumberingSystems->next(&len,status);
7106         NumberingSystem* ns = NumberingSystem::createInstanceByName(nsname,status);
7107         logln("OK for ns = %s",nsname);
7108         if ( uprv_strcmp(nsname,ns->getName()) ) {
7109             errln("FAIL: Numbering system name didn't match for name = %s\n",nsname);
7110         }
7111         if (prevName != nullptr) {
7112             int comp = uprv_strcmp(prevName, nsname);
7113             assertTrue(
7114                 UnicodeString(u"NS names should be in alphabetical order: ")
7115                     + prevName + u" vs " + nsname,
7116                 // TODO: Why are there duplicates? This doesn't work if comp < 0
7117                 comp <= 0);
7118         }
7119         prevName = nsname;
7120 
7121         delete ns;
7122     }
7123 
7124     LocalPointer<NumberingSystem> dummy(NumberingSystem::createInstanceByName("dummy", status), status);
7125     status.expectErrorAndReset(U_UNSUPPORTED_ERROR);
7126     assertTrue("Non-existent numbering system should return null", dummy.isNull());
7127 
7128     delete availableNumberingSystems;
7129 }
7130 
7131 void
Test9087(void)7132 NumberFormatTest::Test9087(void)
7133 {
7134     U_STRING_DECL(pattern,"#",1);
7135     U_STRING_INIT(pattern,"#",1);
7136 
7137     U_STRING_DECL(infstr,"INF",3);
7138     U_STRING_INIT(infstr,"INF",3);
7139 
7140     U_STRING_DECL(nanstr,"NAN",3);
7141     U_STRING_INIT(nanstr,"NAN",3);
7142 
7143     UChar outputbuf[50] = {0};
7144     UErrorCode status = U_ZERO_ERROR;
7145     UNumberFormat* fmt = unum_open(UNUM_PATTERN_DECIMAL,pattern,1,NULL,NULL,&status);
7146     if ( U_FAILURE(status) ) {
7147         dataerrln("FAIL: error in unum_open() - %s", u_errorName(status));
7148         return;
7149     }
7150 
7151     unum_setSymbol(fmt,UNUM_INFINITY_SYMBOL,infstr,3,&status);
7152     unum_setSymbol(fmt,UNUM_NAN_SYMBOL,nanstr,3,&status);
7153     if ( U_FAILURE(status) ) {
7154         errln("FAIL: error setting symbols");
7155     }
7156 
7157     double inf = uprv_getInfinity();
7158 
7159     unum_setAttribute(fmt,UNUM_ROUNDING_MODE,UNUM_ROUND_HALFEVEN);
7160     unum_setDoubleAttribute(fmt,UNUM_ROUNDING_INCREMENT,0);
7161 
7162     UFieldPosition position = { 0, 0, 0};
7163     unum_formatDouble(fmt,inf,outputbuf,50,&position,&status);
7164 
7165     if ( u_strcmp(infstr, outputbuf)) {
7166         errln((UnicodeString)"FAIL: unexpected result for infinity - expected " + infstr + " got " + outputbuf);
7167     }
7168 
7169     unum_close(fmt);
7170 }
7171 
TestFormatFastpaths()7172 void NumberFormatTest::TestFormatFastpaths() {
7173     // get some additional case
7174     {
7175         UErrorCode status=U_ZERO_ERROR;
7176         DecimalFormat df(UnicodeString(u"0000"),status);
7177         if (U_FAILURE(status)) {
7178             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7179         } else {
7180             int64_t long_number = 1;
7181             UnicodeString expect = "0001";
7182             UnicodeString result;
7183             FieldPosition pos;
7184             df.format(long_number, result, pos);
7185             if(U_FAILURE(status)||expect!=result) {
7186                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s",
7187                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7188              } else {
7189                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
7190             }
7191         }
7192     }
7193     {
7194         UErrorCode status=U_ZERO_ERROR;
7195         DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7196         if (U_FAILURE(status)) {
7197             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7198         } else {
7199             int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
7200             // uint8_t bits[8];
7201             // memcpy(bits,&long_number,8);
7202             // for(int i=0;i<8;i++) {
7203             //   logln("bits: %02X", (unsigned int)bits[i]);
7204             // }
7205             UnicodeString expect = "-9223372036854775808";
7206             UnicodeString result;
7207             FieldPosition pos;
7208             df.format(long_number, result, pos);
7209             if(U_FAILURE(status)||expect!=result) {
7210                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775808",
7211                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7212             } else {
7213                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
7214             }
7215         }
7216     }
7217     {
7218         UErrorCode status=U_ZERO_ERROR;
7219         DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7220         if (U_FAILURE(status)) {
7221             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7222         } else {
7223             int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
7224             // uint8_t bits[8];
7225             // memcpy(bits,&long_number,8);
7226             // for(int i=0;i<8;i++) {
7227             //   logln("bits: %02X", (unsigned int)bits[i]);
7228             // }
7229             UnicodeString expect = "9223372036854775807";
7230             UnicodeString result;
7231             FieldPosition pos;
7232             df.format(long_number, result, pos);
7233             if(U_FAILURE(status)||expect!=result) {
7234                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on U_INT64_MAX",
7235                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7236             } else {
7237                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
7238             }
7239         }
7240     }
7241     {
7242         UErrorCode status=U_ZERO_ERROR;
7243         DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7244         if (U_FAILURE(status)) {
7245             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7246         } else {
7247             int64_t long_number = 0;
7248             // uint8_t bits[8];
7249             // memcpy(bits,&long_number,8);
7250             // for(int i=0;i<8;i++) {
7251             //   logln("bits: %02X", (unsigned int)bits[i]);
7252             // }
7253             UnicodeString expect = "0000000000000000000";
7254             UnicodeString result;
7255             FieldPosition pos;
7256             df.format(long_number, result, pos);
7257             if(U_FAILURE(status)||expect!=result) {
7258                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on 0",
7259                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7260             } else {
7261                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
7262             }
7263         }
7264     }
7265     {
7266         UErrorCode status=U_ZERO_ERROR;
7267         DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7268         if (U_FAILURE(status)) {
7269             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7270         } else {
7271             int64_t long_number = U_INT64_MIN + 1;
7272             UnicodeString expect = "-9223372036854775807";
7273             UnicodeString result;
7274             FieldPosition pos;
7275             df.format(long_number, result, pos);
7276             if(U_FAILURE(status)||expect!=result) {
7277                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775807",
7278                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7279             } else {
7280                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
7281             }
7282         }
7283     }
7284 }
7285 
7286 
TestFormattableSize(void)7287 void NumberFormatTest::TestFormattableSize(void) {
7288   if(sizeof(Formattable) > 112) {
7289     errln("Error: sizeof(Formattable)=%d, 112=%d\n",
7290           sizeof(Formattable), 112);
7291   } else if(sizeof(Formattable) < 112) {
7292     logln("Warning: sizeof(Formattable)=%d, 112=%d\n",
7293         sizeof(Formattable), 112);
7294   } else {
7295     logln("sizeof(Formattable)=%d, 112=%d\n",
7296         sizeof(Formattable), 112);
7297   }
7298 }
7299 
testFormattableAsUFormattable(const char *file, int line, Formattable &f)7300 UBool NumberFormatTest::testFormattableAsUFormattable(const char *file, int line, Formattable &f) {
7301   UnicodeString fileLine = UnicodeString(file)+UnicodeString(":")+line+UnicodeString(": ");
7302 
7303   UFormattable *u = f.toUFormattable();
7304   logln();
7305   if (u == NULL) {
7306     errln("%s:%d: Error: f.toUFormattable() retuned NULL.");
7307     return false;
7308   }
7309   logln("%s:%d: comparing Formattable with UFormattable", file, line);
7310   logln(fileLine + toString(f));
7311 
7312   UErrorCode status = U_ZERO_ERROR;
7313   UErrorCode valueStatus = U_ZERO_ERROR;
7314   UFormattableType expectUType = UFMT_COUNT; // invalid
7315 
7316   UBool triedExact = false; // did we attempt an exact comparison?
7317   UBool exactMatch = false; // was the exact comparison true?
7318 
7319   switch( f.getType() ) {
7320   case Formattable::kDate:
7321     expectUType = UFMT_DATE;
7322     exactMatch = (f.getDate()==ufmt_getDate(u, &valueStatus));
7323     triedExact = true;
7324     break;
7325   case Formattable::kDouble:
7326     expectUType = UFMT_DOUBLE;
7327     exactMatch = (f.getDouble()==ufmt_getDouble(u, &valueStatus));
7328     triedExact = true;
7329     break;
7330   case Formattable::kLong:
7331     expectUType = UFMT_LONG;
7332     exactMatch = (f.getLong()==ufmt_getLong(u, &valueStatus));
7333     triedExact = true;
7334     break;
7335   case Formattable::kString:
7336     expectUType = UFMT_STRING;
7337     {
7338       UnicodeString str;
7339       f.getString(str);
7340       int32_t len;
7341       const UChar* uch = ufmt_getUChars(u, &len, &valueStatus);
7342       if(U_SUCCESS(valueStatus)) {
7343         UnicodeString str2(uch, len);
7344         assertTrue("UChar* NULL-terminated", uch[len]==0);
7345         exactMatch = (str == str2);
7346       }
7347       triedExact = true;
7348     }
7349     break;
7350   case Formattable::kArray:
7351     expectUType = UFMT_ARRAY;
7352     triedExact = true;
7353     {
7354       int32_t count = ufmt_getArrayLength(u, &valueStatus);
7355       int32_t count2;
7356       const Formattable *array2 = f.getArray(count2);
7357       exactMatch = assertEquals(fileLine + " array count", count, count2);
7358 
7359       if(exactMatch) {
7360         for(int i=0;U_SUCCESS(valueStatus) && i<count;i++) {
7361           UFormattable *uu = ufmt_getArrayItemByIndex(u, i, &valueStatus);
7362           if(*Formattable::fromUFormattable(uu) != (array2[i])) {
7363             errln("%s:%d: operator== did not match at index[%d] - %p vs %p", file, line, i,
7364                   (const void*)Formattable::fromUFormattable(uu), (const void*)&(array2[i]));
7365             exactMatch = false;
7366           } else {
7367             if(!testFormattableAsUFormattable("(sub item)",i,*Formattable::fromUFormattable(uu))) {
7368               exactMatch = false;
7369             }
7370           }
7371         }
7372       }
7373     }
7374     break;
7375   case Formattable::kInt64:
7376     expectUType = UFMT_INT64;
7377     exactMatch = (f.getInt64()==ufmt_getInt64(u, &valueStatus));
7378     triedExact = true;
7379     break;
7380   case Formattable::kObject:
7381     expectUType = UFMT_OBJECT;
7382     exactMatch = (f.getObject()==ufmt_getObject(u, &valueStatus));
7383     triedExact = true;
7384     break;
7385   }
7386   UFormattableType uType = ufmt_getType(u, &status);
7387 
7388   if(U_FAILURE(status)) {
7389     errln("%s:%d: Error calling ufmt_getType - %s", file, line, u_errorName(status));
7390     return false;
7391   }
7392 
7393   if(uType != expectUType) {
7394     errln("%s:%d: got type (%d) expected (%d) from ufmt_getType", file, line, (int) uType, (int) expectUType);
7395   }
7396 
7397   if(triedExact) {
7398     if(U_FAILURE(valueStatus)) {
7399       errln("%s:%d: got err %s trying to ufmt_get...() for exact match check", file, line, u_errorName(valueStatus));
7400     } else if(!exactMatch) {
7401      errln("%s:%d: failed exact match for the Formattable type", file, line);
7402     } else {
7403       logln("%s:%d: exact match OK", file, line);
7404     }
7405   } else {
7406     logln("%s:%d: note, did not attempt exact match for this formattable type", file, line);
7407   }
7408 
7409   if( assertEquals(fileLine + " isNumeric()", f.isNumeric(), ufmt_isNumeric(u))
7410       && f.isNumeric()) {
7411     UErrorCode convStatus = U_ZERO_ERROR;
7412 
7413     if(uType != UFMT_INT64) { // may fail to compare
7414       assertTrue(fileLine + " as doubles ==", f.getDouble(convStatus)==ufmt_getDouble(u, &convStatus));
7415     }
7416 
7417     if( assertSuccess(fileLine + " (numeric conversion status)", convStatus) ) {
7418       StringPiece fDecNum = f.getDecimalNumber(convStatus);
7419 #if 1
7420       int32_t len;
7421       const char *decNumChars = ufmt_getDecNumChars(u, &len, &convStatus);
7422 #else
7423       // copy version
7424       char decNumChars[200];
7425       int32_t len = ufmt_getDecNumChars(u, decNumChars, 200, &convStatus);
7426 #endif
7427 
7428       if( assertSuccess(fileLine + " (decNumbers conversion)", convStatus) ) {
7429         logln(fileLine + decNumChars);
7430         assertEquals(fileLine + " decNumChars length==", len, fDecNum.length());
7431         assertEquals(fileLine + " decNumChars digits", decNumChars, fDecNum.data());
7432       }
7433 
7434       UErrorCode int64ConversionF = U_ZERO_ERROR;
7435       int64_t l = f.getInt64(int64ConversionF);
7436       UErrorCode int64ConversionU = U_ZERO_ERROR;
7437       int64_t r = ufmt_getInt64(u, &int64ConversionU);
7438 
7439       if( (l==r)
7440           && ( uType != UFMT_INT64 ) // int64 better not overflow
7441           && (U_INVALID_FORMAT_ERROR==int64ConversionU)
7442           && (U_INVALID_FORMAT_ERROR==int64ConversionF) ) {
7443         logln("%s:%d: OK: 64 bit overflow", file, line);
7444       } else {
7445         assertEquals(fileLine + " as int64 ==", l, r);
7446         assertSuccess(fileLine + " Formattable.getnt64()", int64ConversionF);
7447         assertSuccess(fileLine + " ufmt_getInt64()", int64ConversionU);
7448       }
7449     }
7450   }
7451   return exactMatch || !triedExact;
7452 }
7453 
TestUFormattable(void)7454 void NumberFormatTest::TestUFormattable(void) {
7455   {
7456     // test that a default formattable is equal to Formattable()
7457     UErrorCode status = U_ZERO_ERROR;
7458     LocalUFormattablePointer defaultUFormattable(ufmt_open(&status));
7459     assertSuccess("calling umt_open", status);
7460     Formattable defaultFormattable;
7461     assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7462                (defaultFormattable
7463                 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7464     assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7465                (defaultFormattable
7466                 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7467     assertTrue((UnicodeString)"comparing Formattable() round tripped through UFormattable",
7468                (defaultFormattable
7469                 == *(Formattable::fromUFormattable(defaultFormattable.toUFormattable()))));
7470     assertTrue((UnicodeString)"comparing &Formattable() round tripped through UFormattable",
7471                ((&defaultFormattable)
7472                 == Formattable::fromUFormattable(defaultFormattable.toUFormattable())));
7473     assertFalse((UnicodeString)"comparing &Formattable() with ufmt_open()",
7474                ((&defaultFormattable)
7475                 == Formattable::fromUFormattable(defaultUFormattable.getAlias())));
7476     testFormattableAsUFormattable(__FILE__, __LINE__, defaultFormattable);
7477   }
7478   // test some random Formattables
7479   {
7480     Formattable f(ucal_getNow(), Formattable::kIsDate);
7481     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7482   }
7483   {
7484     Formattable f((double)1.61803398874989484820); // golden ratio
7485     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7486   }
7487   {
7488     Formattable f((int64_t)80994231587905127LL); // weight of the moon, in kilotons http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
7489     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7490   }
7491   {
7492     Formattable f((int32_t)4); // random number, source: http://www.xkcd.com/221/
7493     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7494   }
7495   {
7496     Formattable f("Hello world."); // should be invariant?
7497     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7498   }
7499   {
7500     UErrorCode status2 = U_ZERO_ERROR;
7501     Formattable f(StringPiece("73476730924573500000000.0"), status2); // weight of the moon, kg
7502     assertSuccess("Constructing a StringPiece", status2);
7503     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7504   }
7505   {
7506     UErrorCode status2 = U_ZERO_ERROR;
7507     UObject *obj = new Locale();
7508     Formattable f(obj);
7509     assertSuccess("Constructing a Formattable from a default constructed Locale()", status2);
7510     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7511   }
7512   {
7513     const Formattable array[] = {
7514       Formattable(ucal_getNow(), Formattable::kIsDate),
7515       Formattable((int32_t)4),
7516       Formattable((double)1.234),
7517     };
7518 
7519     Formattable fa(array, 3);
7520     testFormattableAsUFormattable(__FILE__, __LINE__, fa);
7521   }
7522 }
7523 
TestSignificantDigits(void)7524 void NumberFormatTest::TestSignificantDigits(void) {
7525   double input[] = {
7526         0, 0,
7527         0.1, -0.1,
7528         123, -123,
7529         12345, -12345,
7530         123.45, -123.45,
7531         123.44501, -123.44501,
7532         0.001234, -0.001234,
7533         0.00000000123, -0.00000000123,
7534         0.0000000000000000000123, -0.0000000000000000000123,
7535         1.2, -1.2,
7536         0.0000000012344501, -0.0000000012344501,
7537         123445.01, -123445.01,
7538         12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0,
7539     };
7540     const char* expected[] = {
7541         "0.00", "0.00",
7542         "0.100", "-0.100",
7543         "123", "-123",
7544         "12345", "-12345",
7545         "123.45", "-123.45",
7546         "123.45", "-123.45",
7547         "0.001234", "-0.001234",
7548         "0.00000000123", "-0.00000000123",
7549         "0.0000000000000000000123", "-0.0000000000000000000123",
7550         "1.20", "-1.20",
7551         "0.0000000012345", "-0.0000000012345",
7552         "123450", "-123450",
7553         "12345000000000000000000000000000000", "-12345000000000000000000000000000000",
7554     };
7555 
7556     UErrorCode status = U_ZERO_ERROR;
7557     Locale locale("en_US");
7558     LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7559             NumberFormat::createInstance(locale, status)));
7560     CHECK_DATA(status,"NumberFormat::createInstance");
7561 
7562     numberFormat->setSignificantDigitsUsed(true);
7563     numberFormat->setMinimumSignificantDigits(3);
7564     numberFormat->setMaximumSignificantDigits(5);
7565     numberFormat->setGroupingUsed(false);
7566 
7567     UnicodeString result;
7568     UnicodeString expectedResult;
7569     for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
7570         numberFormat->format(input[i], result);
7571         UnicodeString expectedResult(expected[i]);
7572         if (result != expectedResult) {
7573           errln((UnicodeString)"Expected: '" + expectedResult + "' got '" + result);
7574         }
7575         result.remove();
7576     }
7577 
7578     // Test for ICU-20063
7579     {
7580         DecimalFormat df({"en-us", status}, status);
7581         df.setSignificantDigitsUsed(true);
7582         expect(df, 9.87654321, u"9.87654");
7583         df.setMaximumSignificantDigits(3);
7584         expect(df, 9.87654321, u"9.88");
7585         // setSignificantDigitsUsed with maxSig only
7586         df.setSignificantDigitsUsed(true);
7587         expect(df, 9.87654321, u"9.88");
7588         df.setMinimumSignificantDigits(2);
7589         expect(df, 9, u"9.0");
7590         // setSignificantDigitsUsed with both minSig and maxSig
7591         df.setSignificantDigitsUsed(true);
7592         expect(df, 9, u"9.0");
7593         // setSignificantDigitsUsed to false: should revert to fraction rounding
7594         df.setSignificantDigitsUsed(false);
7595         expect(df, 9.87654321, u"9.876543");
7596         expect(df, 9, u"9");
7597         df.setSignificantDigitsUsed(true);
7598         df.setMinimumSignificantDigits(2);
7599         expect(df, 9.87654321, u"9.87654");
7600         expect(df, 9, u"9.0");
7601         // setSignificantDigitsUsed with minSig only
7602         df.setSignificantDigitsUsed(true);
7603         expect(df, 9.87654321, u"9.87654");
7604         expect(df, 9, u"9.0");
7605     }
7606 }
7607 
TestShowZero()7608 void NumberFormatTest::TestShowZero() {
7609     UErrorCode status = U_ZERO_ERROR;
7610     Locale locale("en_US");
7611     LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7612             NumberFormat::createInstance(locale, status)));
7613     CHECK_DATA(status, "NumberFormat::createInstance");
7614 
7615     numberFormat->setSignificantDigitsUsed(true);
7616     numberFormat->setMaximumSignificantDigits(3);
7617 
7618     UnicodeString result;
7619     numberFormat->format(0.0, result);
7620     if (result != "0") {
7621         errln((UnicodeString)"Expected: 0, got " + result);
7622     }
7623 }
7624 
TestBug9936()7625 void NumberFormatTest::TestBug9936() {
7626     UErrorCode status = U_ZERO_ERROR;
7627     Locale locale("en_US");
7628     LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7629             NumberFormat::createInstance(locale, status)));
7630     if (U_FAILURE(status)) {
7631         dataerrln("File %s, Line %d: status = %s.\n", __FILE__, __LINE__, u_errorName(status));
7632         return;
7633     }
7634 
7635     if (numberFormat->areSignificantDigitsUsed() == true) {
7636         errln("File %s, Line %d: areSignificantDigitsUsed() was true, expected false.\n", __FILE__, __LINE__);
7637     }
7638     numberFormat->setSignificantDigitsUsed(true);
7639     if (numberFormat->areSignificantDigitsUsed() == false) {
7640         errln("File %s, Line %d: areSignificantDigitsUsed() was false, expected true.\n", __FILE__, __LINE__);
7641     }
7642 
7643     numberFormat->setSignificantDigitsUsed(false);
7644     if (numberFormat->areSignificantDigitsUsed() == true) {
7645         errln("File %s, Line %d: areSignificantDigitsUsed() was true, expected false.\n", __FILE__, __LINE__);
7646     }
7647 
7648     numberFormat->setMinimumSignificantDigits(3);
7649     if (numberFormat->areSignificantDigitsUsed() == false) {
7650         errln("File %s, Line %d: areSignificantDigitsUsed() was false, expected true.\n", __FILE__, __LINE__);
7651     }
7652 
7653     numberFormat->setSignificantDigitsUsed(false);
7654     numberFormat->setMaximumSignificantDigits(6);
7655     if (numberFormat->areSignificantDigitsUsed() == false) {
7656         errln("File %s, Line %d: areSignificantDigitsUsed() was false, expected true.\n", __FILE__, __LINE__);
7657     }
7658 
7659 }
7660 
TestParseNegativeWithFaLocale()7661 void NumberFormatTest::TestParseNegativeWithFaLocale() {
7662     UErrorCode status = U_ZERO_ERROR;
7663     DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status);
7664     CHECK_DATA(status, "NumberFormat::createInstance");
7665     test->setLenient(true);
7666     Formattable af;
7667     ParsePosition ppos;
7668     UnicodeString value("\\u200e-0,5");
7669     value = value.unescape();
7670     test->parse(value, af, ppos);
7671     if (ppos.getIndex() == 0) {
7672         errln("Expected -0,5 to parse for Farsi.");
7673     }
7674     delete test;
7675 }
7676 
TestParseNegativeWithAlternateMinusSign()7677 void NumberFormatTest::TestParseNegativeWithAlternateMinusSign() {
7678     UErrorCode status = U_ZERO_ERROR;
7679     DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("en", status);
7680     CHECK_DATA(status, "NumberFormat::createInstance");
7681     test->setLenient(true);
7682     Formattable af;
7683     ParsePosition ppos;
7684     UnicodeString value("\\u208B0.5");
7685     value = value.unescape();
7686     test->parse(value, af, ppos);
7687     if (ppos.getIndex() == 0) {
7688         errln(UnicodeString("Expected ") + value + UnicodeString(" to parse."));
7689     }
7690     delete test;
7691 }
7692 
TestCustomCurrencySignAndSeparator()7693 void NumberFormatTest::TestCustomCurrencySignAndSeparator() {
7694     UErrorCode status = U_ZERO_ERROR;
7695     DecimalFormatSymbols custom(Locale::getUS(), status);
7696     CHECK(status, "DecimalFormatSymbols constructor");
7697 
7698     custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "*");
7699     custom.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, "^");
7700     custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, ":");
7701 
7702     UnicodeString pat(" #,##0.00");
7703     pat.insert(0, (UChar)0x00A4);
7704 
7705     DecimalFormat fmt(pat, custom, status);
7706     CHECK(status, "DecimalFormat constructor");
7707 
7708     UnicodeString numstr("* 1^234:56");
7709     expect2(fmt, (Formattable)((double)1234.56), numstr);
7710 }
7711 
7712 typedef struct {
7713     const char *   locale;
7714     UBool          lenient;
7715     UnicodeString  numString;
7716     double         value;
7717 } SignsAndMarksItem;
7718 
7719 
TestParseSignsAndMarks()7720 void NumberFormatTest::TestParseSignsAndMarks() {
7721     const SignsAndMarksItem items[] = {
7722         // locale               lenient numString                                                       value
7723         { "en",                 false,  CharsToUnicodeString("12"),                                      12 },
7724         { "en",                 true,   CharsToUnicodeString("12"),                                      12 },
7725         { "en",                 false,  CharsToUnicodeString("-23"),                                    -23 },
7726         { "en",                 true,   CharsToUnicodeString("-23"),                                    -23 },
7727         { "en",                 true,   CharsToUnicodeString("- 23"),                                   -23 },
7728         { "en",                 false,  CharsToUnicodeString("\\u200E-23"),                             -23 },
7729         { "en",                 true,   CharsToUnicodeString("\\u200E-23"),                             -23 },
7730         { "en",                 true,   CharsToUnicodeString("\\u200E- 23"),                            -23 },
7731 
7732         { "en@numbers=arab",    false,  CharsToUnicodeString("\\u0663\\u0664"),                          34 },
7733         { "en@numbers=arab",    true,   CharsToUnicodeString("\\u0663\\u0664"),                          34 },
7734         { "en@numbers=arab",    false,  CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
7735         { "en@numbers=arab",    true,   CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
7736         { "en@numbers=arab",    true,   CharsToUnicodeString("- \\u0664\\u0665"),                       -45 },
7737         { "en@numbers=arab",    false,  CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
7738         { "en@numbers=arab",    true,   CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
7739         { "en@numbers=arab",    true,   CharsToUnicodeString("\\u200F- \\u0664\\u0665"),                -45 },
7740 
7741         { "en@numbers=arabext", false,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7742         { "en@numbers=arabext", true,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7743         { "en@numbers=arabext", false,  CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
7744         { "en@numbers=arabext", true,   CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
7745         { "en@numbers=arabext", true,   CharsToUnicodeString("- \\u06F6\\u06F7"),                       -67 },
7746         { "en@numbers=arabext", false,  CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
7747         { "en@numbers=arabext", true,   CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
7748         { "en@numbers=arabext", true,   CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"),         -67 },
7749 
7750         { "he",                 false,  CharsToUnicodeString("12"),                                      12 },
7751         { "he",                 true,   CharsToUnicodeString("12"),                                      12 },
7752         { "he",                 false,  CharsToUnicodeString("-23"),                                    -23 },
7753         { "he",                 true,   CharsToUnicodeString("-23"),                                    -23 },
7754         { "he",                 true,   CharsToUnicodeString("- 23"),                                   -23 },
7755         { "he",                 false,  CharsToUnicodeString("\\u200E-23"),                             -23 },
7756         { "he",                 true,   CharsToUnicodeString("\\u200E-23"),                             -23 },
7757         { "he",                 true,   CharsToUnicodeString("\\u200E- 23"),                            -23 },
7758 
7759         { "ar",                 false,  CharsToUnicodeString("\\u0663\\u0664"),                          34 },
7760         { "ar",                 true,   CharsToUnicodeString("\\u0663\\u0664"),                          34 },
7761         { "ar",                 false,  CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
7762         { "ar",                 true,   CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
7763         { "ar",                 true,   CharsToUnicodeString("- \\u0664\\u0665"),                       -45 },
7764         { "ar",                 false,  CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
7765         { "ar",                 true,   CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
7766         { "ar",                 true,   CharsToUnicodeString("\\u200F- \\u0664\\u0665"),                -45 },
7767 
7768         { "ar_MA",              false,  CharsToUnicodeString("12"),                                      12 },
7769         { "ar_MA",              true,   CharsToUnicodeString("12"),                                      12 },
7770         { "ar_MA",              false,  CharsToUnicodeString("-23"),                                    -23 },
7771         { "ar_MA",              true,   CharsToUnicodeString("-23"),                                    -23 },
7772         { "ar_MA",              true,   CharsToUnicodeString("- 23"),                                   -23 },
7773         { "ar_MA",              false,  CharsToUnicodeString("\\u200E-23"),                             -23 },
7774         { "ar_MA",              true,   CharsToUnicodeString("\\u200E-23"),                             -23 },
7775         { "ar_MA",              true,   CharsToUnicodeString("\\u200E- 23"),                            -23 },
7776 
7777         { "fa",                 false,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7778         { "fa",                 true,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7779         { "fa",                 false,  CharsToUnicodeString("\\u2212\\u06F6\\u06F7"),                  -67 },
7780         { "fa",                 true,   CharsToUnicodeString("\\u2212\\u06F6\\u06F7"),                  -67 },
7781         { "fa",                 true,   CharsToUnicodeString("\\u2212 \\u06F6\\u06F7"),                 -67 },
7782         { "fa",                 false,  CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"),    -67 },
7783         { "fa",                 true,   CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"),    -67 },
7784         { "fa",                 true,   CharsToUnicodeString("\\u200E\\u2212\\u200E \\u06F6\\u06F7"),   -67 },
7785 
7786         { "ps",                 false,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7787         { "ps",                 true,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7788         { "ps",                 false,  CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
7789         { "ps",                 true,   CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
7790         { "ps",                 true,   CharsToUnicodeString("- \\u06F6\\u06F7"),                       -67 },
7791         { "ps",                 false,  CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
7792         { "ps",                 true,   CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
7793         { "ps",                 true,   CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"),         -67 },
7794         { "ps",                 false,  CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"),                 -67 },
7795         { "ps",                 true,   CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"),                 -67 },
7796         { "ps",                 true,   CharsToUnicodeString("-\\u200E \\u06F6\\u06F7"),                -67 },
7797         // terminator
7798         { NULL,                 0,      UnicodeString(""),                                                0 },
7799     };
7800 
7801     const SignsAndMarksItem * itemPtr;
7802     for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
7803         UErrorCode status = U_ZERO_ERROR;
7804         NumberFormat *numfmt = NumberFormat::createInstance(Locale(itemPtr->locale), status);
7805         if (U_SUCCESS(status)) {
7806             numfmt->setLenient(itemPtr->lenient);
7807             Formattable fmtobj;
7808             ParsePosition ppos;
7809             numfmt->parse(itemPtr->numString, fmtobj, ppos);
7810             if (ppos.getIndex() == itemPtr->numString.length()) {
7811                 double parsedValue = fmtobj.getDouble(status);
7812                 if (U_FAILURE(status) || parsedValue != itemPtr->value) {
7813                     errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives value " + parsedValue);
7814                 }
7815             } else {
7816                 errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives position " + ppos.getIndex());
7817             }
7818         } else {
7819             dataerrln("FAIL: NumberFormat::createInstance for locale % gives error %s", itemPtr->locale, u_errorName(status));
7820         }
7821         delete numfmt;
7822     }
7823 }
7824 
7825 typedef struct {
7826   DecimalFormat::ERoundingMode mode;
7827   double value;
7828   UnicodeString expected;
7829 } Test10419Data;
7830 
7831 
7832 // Tests that rounding works right when fractional digits is set to 0.
Test10419RoundingWith0FractionDigits()7833 void NumberFormatTest::Test10419RoundingWith0FractionDigits() {
7834     const Test10419Data items[] = {
7835         { DecimalFormat::kRoundCeiling, 1.488,  "2"},
7836         { DecimalFormat::kRoundDown, 1.588,  "1"},
7837         { DecimalFormat::kRoundFloor, 1.888,  "1"},
7838         { DecimalFormat::kRoundHalfDown, 1.5,  "1"},
7839         { DecimalFormat::kRoundHalfEven, 2.5,  "2"},
7840         { DecimalFormat::kRoundHalfUp, 2.5,  "3"},
7841         { DecimalFormat::kRoundUp, 1.5,  "2"},
7842     };
7843     UErrorCode status = U_ZERO_ERROR;
7844     LocalPointer<DecimalFormat> decfmt((DecimalFormat *) NumberFormat::createInstance(Locale("en_US"), status));
7845     if (U_FAILURE(status)) {
7846         dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
7847         return;
7848     }
7849     for (int32_t i = 0; i < UPRV_LENGTHOF(items); ++i) {
7850         decfmt->setRoundingMode(items[i].mode);
7851         decfmt->setMaximumFractionDigits(0);
7852         UnicodeString actual;
7853         if (items[i].expected != decfmt->format(items[i].value, actual)) {
7854             errln("Expected " + items[i].expected + ", got " + actual);
7855         }
7856     }
7857 }
7858 
Test10468ApplyPattern()7859 void NumberFormatTest::Test10468ApplyPattern() {
7860     // Padding char of fmt is now 'a'
7861     UErrorCode status = U_ZERO_ERROR;
7862     DecimalFormat fmt("'I''ll'*a###.##", status);
7863 
7864     if (U_FAILURE(status)) {
7865         errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7866         return;
7867     }
7868 
7869     assertEquals("Padding character should be 'a'.", u"a", fmt.getPadCharacterString());
7870 
7871     // Padding char of fmt ought to be '*' since that is the default and no
7872     // explicit padding char is specified in the new pattern.
7873     fmt.applyPattern("AA#,##0.00ZZ", status);
7874 
7875     // Oops this still prints 'a' even though we changed the pattern.
7876     assertEquals("applyPattern did not clear padding character.", u" ", fmt.getPadCharacterString());
7877 }
7878 
TestRoundingScientific10542()7879 void NumberFormatTest::TestRoundingScientific10542() {
7880     UErrorCode status = U_ZERO_ERROR;
7881     DecimalFormat format("0.00E0", status);
7882     if (U_FAILURE(status)) {
7883         errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7884         return;
7885     }
7886 
7887     DecimalFormat::ERoundingMode roundingModes[] = {
7888             DecimalFormat::kRoundCeiling,
7889             DecimalFormat::kRoundDown,
7890             DecimalFormat::kRoundFloor,
7891             DecimalFormat::kRoundHalfDown,
7892             DecimalFormat::kRoundHalfEven,
7893             DecimalFormat::kRoundHalfUp,
7894             DecimalFormat::kRoundUp};
7895     const char *descriptions[] = {
7896             "Round Ceiling",
7897             "Round Down",
7898             "Round Floor",
7899             "Round half down",
7900             "Round half even",
7901             "Round half up",
7902             "Round up"};
7903 
7904     {
7905         double values[] = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016};
7906         // The order of these expected values correspond to the order of roundingModes and the order of values.
7907         const char *expected[] = {
7908                 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.02E-3", "3.02E-3", "3.02E-3",
7909                 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7910                 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7911                 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.02E-3",
7912                 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7913                 "-3.01E-3", "-3.01E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7914                 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.02E-3", "3.02E-3", "3.02E-3"};
7915         verifyRounding(
7916                 format,
7917                 values,
7918                 expected,
7919                 roundingModes,
7920                 descriptions,
7921                 UPRV_LENGTHOF(values),
7922                 UPRV_LENGTHOF(roundingModes));
7923     }
7924     {
7925         double values[] = {-3006.0, -3005, -3004, 3014, 3015, 3016};
7926         // The order of these expected values correspond to the order of roundingModes and the order of values.
7927         const char *expected[] = {
7928                 "-3.00E3", "-3.00E3", "-3.00E3", "3.02E3", "3.02E3", "3.02E3",
7929                 "-3.00E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.01E3",
7930                 "-3.01E3", "-3.01E3", "-3.01E3", "3.01E3", "3.01E3", "3.01E3",
7931                 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.02E3",
7932                 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7933                 "-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7934                 "-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"};
7935         verifyRounding(
7936                 format,
7937                 values,
7938                 expected,
7939                 roundingModes,
7940                 descriptions,
7941                 UPRV_LENGTHOF(values),
7942                 UPRV_LENGTHOF(roundingModes));
7943     }
7944 /* Commented out for now until we decide how rounding to zero should work, +0 vs. -0
7945     {
7946         double values[] = {0.0, -0.0};
7947         // The order of these expected values correspond to the order of roundingModes and the order of values.
7948         const char *expected[] = {
7949                 "0.00E0", "-0.00E0",
7950                 "0.00E0", "-0.00E0",
7951                 "0.00E0", "-0.00E0",
7952                 "0.00E0", "-0.00E0",
7953                 "0.00E0", "-0.00E0",
7954                 "0.00E0", "-0.00E0",
7955                 "0.00E0", "-0.00E0"};
7956         verifyRounding(
7957                 format,
7958                 values,
7959                 expected,
7960                 roundingModes,
7961                 descriptions,
7962                 UPRV_LENGTHOF(values),
7963                 UPRV_LENGTHOF(roundingModes));
7964     }
7965 */
7966     {
7967 
7968         double values[] = {1e25, 1e25 + 1e15, 1e25 - 1e15};
7969         // The order of these expected values correspond to the order of roundingModes and the order of values.
7970         const char *expected[] = {
7971                 "1.00E25", "1.01E25", "1.00E25",
7972                 "1.00E25", "1.00E25", "9.99E24",
7973                 "1.00E25", "1.00E25", "9.99E24",
7974                 "1.00E25", "1.00E25", "1.00E25",
7975                 "1.00E25", "1.00E25", "1.00E25",
7976                 "1.00E25", "1.00E25", "1.00E25",
7977                 "1.00E25", "1.01E25", "1.00E25"};
7978         verifyRounding(
7979                 format,
7980                 values,
7981                 expected,
7982                 roundingModes,
7983                 descriptions,
7984                 UPRV_LENGTHOF(values),
7985                 UPRV_LENGTHOF(roundingModes));
7986         }
7987     {
7988         double values[] = {-1e25, -1e25 + 1e15, -1e25 - 1e15};
7989         // The order of these expected values correspond to the order of roundingModes and the order of values.
7990         const char *expected[] = {
7991                 "-1.00E25", "-9.99E24", "-1.00E25",
7992                 "-1.00E25", "-9.99E24", "-1.00E25",
7993                 "-1.00E25", "-1.00E25", "-1.01E25",
7994                 "-1.00E25", "-1.00E25", "-1.00E25",
7995                 "-1.00E25", "-1.00E25", "-1.00E25",
7996                 "-1.00E25", "-1.00E25", "-1.00E25",
7997                 "-1.00E25", "-1.00E25", "-1.01E25"};
7998         verifyRounding(
7999                 format,
8000                 values,
8001                 expected,
8002                 roundingModes,
8003                 descriptions,
8004                 UPRV_LENGTHOF(values),
8005                 UPRV_LENGTHOF(roundingModes));
8006         }
8007     {
8008         double values[] = {1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
8009         // The order of these expected values correspond to the order of roundingModes and the order of values.
8010         const char *expected[] = {
8011                 "1.00E-25", "1.01E-25", "1.00E-25",
8012                 "1.00E-25", "1.00E-25", "9.99E-26",
8013                 "1.00E-25", "1.00E-25", "9.99E-26",
8014                 "1.00E-25", "1.00E-25", "1.00E-25",
8015                 "1.00E-25", "1.00E-25", "1.00E-25",
8016                 "1.00E-25", "1.00E-25", "1.00E-25",
8017                 "1.00E-25", "1.01E-25", "1.00E-25"};
8018         verifyRounding(
8019                 format,
8020                 values,
8021                 expected,
8022                 roundingModes,
8023                 descriptions,
8024                 UPRV_LENGTHOF(values),
8025                 UPRV_LENGTHOF(roundingModes));
8026         }
8027     {
8028         double values[] = {-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
8029         // The order of these expected values correspond to the order of roundingModes and the order of values.
8030         const char *expected[] = {
8031                 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8032                 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8033                 "-1.00E-25", "-1.00E-25", "-1.01E-25",
8034                 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8035                 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8036                 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8037                 "-1.00E-25", "-1.00E-25", "-1.01E-25"};
8038         verifyRounding(
8039                 format,
8040                 values,
8041                 expected,
8042                 roundingModes,
8043                 descriptions,
8044                 UPRV_LENGTHOF(values),
8045                 UPRV_LENGTHOF(roundingModes));
8046     }
8047 }
8048 
TestZeroScientific10547()8049 void NumberFormatTest::TestZeroScientific10547() {
8050     UErrorCode status = U_ZERO_ERROR;
8051     DecimalFormat fmt("0.00E0", status);
8052     if (!assertSuccess("Format creation", status)) {
8053         return;
8054     }
8055     UnicodeString out;
8056     fmt.format(-0.0, out);
8057     assertEquals("format", "-0.00E0", out, true);
8058 }
8059 
verifyRounding( DecimalFormat& format, const double *values, const char * const *expected, const DecimalFormat::ERoundingMode *roundingModes, const char * const *descriptions, int32_t valueSize, int32_t roundingModeSize)8060 void NumberFormatTest::verifyRounding(
8061         DecimalFormat& format,
8062         const double *values,
8063         const char * const *expected,
8064         const DecimalFormat::ERoundingMode *roundingModes,
8065         const char * const *descriptions,
8066         int32_t valueSize,
8067         int32_t roundingModeSize) {
8068     for (int32_t i = 0; i < roundingModeSize; ++i) {
8069         format.setRoundingMode(roundingModes[i]);
8070         for (int32_t j = 0; j < valueSize; j++) {
8071             UnicodeString currentExpected(expected[i * valueSize + j]);
8072             currentExpected = currentExpected.unescape();
8073             UnicodeString actual;
8074             format.format(values[j], actual);
8075             if (currentExpected != actual) {
8076                 dataerrln("For %s value %f, expected '%s', got '%s'",
8077                           descriptions[i], values[j], CStr(currentExpected)(), CStr(actual)());
8078             }
8079         }
8080     }
8081 }
8082 
TestAccountingCurrency()8083 void NumberFormatTest::TestAccountingCurrency() {
8084     UErrorCode status = U_ZERO_ERROR;
8085     UNumberFormatStyle style = UNUM_CURRENCY_ACCOUNTING;
8086 
8087     expect(NumberFormat::createInstance("en_US", style, status),
8088         (Formattable)(double)1234.5, "$1,234.50", true, status);
8089     expect(NumberFormat::createInstance("en_US", style, status),
8090         (Formattable)(double)-1234.5, "($1,234.50)", true, status);
8091     expect(NumberFormat::createInstance("en_US", style, status),
8092         (Formattable)(double)0, "$0.00", true, status);
8093     expect(NumberFormat::createInstance("en_US", style, status),
8094         (Formattable)(double)-0.2, "($0.20)", true, status);
8095     expect(NumberFormat::createInstance("ja_JP", style, status),
8096         (Formattable)(double)10000, UnicodeString("\\uFFE510,000").unescape(), true, status);
8097     expect(NumberFormat::createInstance("ja_JP", style, status),
8098         (Formattable)(double)-1000.5, UnicodeString("(\\uFFE51,000)").unescape(), false, status);
8099     expect(NumberFormat::createInstance("de_DE", style, status),
8100         (Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), true, status);
8101     expect(NumberFormat::createInstance("en_ID", style, status),
8102         (Formattable)(double)0, UnicodeString("IDR\\u00A00.00").unescape(), true, status);
8103     expect(NumberFormat::createInstance("en_ID", style, status),
8104         (Formattable)(double)-0.2, UnicodeString("(IDR\\u00A00.20)").unescape(), true, status);
8105     expect(NumberFormat::createInstance("sh_ME", style, status),
8106         (Formattable)(double)0, UnicodeString("0,00\\u00A0\\u20AC").unescape(), true, status);
8107     expect(NumberFormat::createInstance("sh_ME", style, status),
8108         (Formattable)(double)-0.2, UnicodeString("(0,20\\u00A0\\u20AC)").unescape(), true, status);
8109 }
8110 
8111 /**
8112  * ICU4J has the behavior explained below, but ICU4C is not affected. Test is added to prevent regression.
8113  *
8114  * en_ID/sh_ME uses language only locales en/sh which requires NumberFormatServiceShim to fill in the currency, but
8115  * prior to ICU-20631, currency was not filled in for accounting, cash and standard, so currency placeholder was
8116  * used instead of the desired locale's currency.
8117  */
TestCurrencyFormatForMissingLocale()8118 void NumberFormatTest::TestCurrencyFormatForMissingLocale() {
8119     IcuTestErrorCode status(*this, "TestCurrencyFormatForMissingLocale");
8120     Locale locale = Locale::createCanonical("sh_ME");
8121 
8122     LocalPointer<NumberFormat> curFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status));
8123     // Fail here with missing data.
8124     if (!assertTrue(WHERE, curFmt.isValid(), false, true)) {return;};
8125     assertEquals("Currency instance is not for the desired locale for CURRENCYSTYLE", curFmt->getCurrency(), "EUR");
8126     UnicodeString currBuf;
8127     curFmt->format(-1234.5, currBuf);
8128     assertEquals("NumberFormat format outputs wrong value for CURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", currBuf);
8129 
8130     LocalPointer<NumberFormat> accFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_ACCOUNTING, status));
8131     assertEquals("Currency instance is not for the desired locale for ACCOUNTINGCURRENCYSTYLE", accFmt->getCurrency(), "EUR");
8132     UnicodeString accBuf;
8133     accFmt->format(-1234.5, accBuf);
8134     assertEquals("NumberFormat format outputs wrong value for ACCOUNTINGCURRENCYSTYLE", u"(1.234,50\u00A0\u20AC)", accBuf);
8135 
8136     LocalPointer<NumberFormat> cashFmt(NumberFormat::createInstance(locale, UNUM_CASH_CURRENCY, status));
8137     assertEquals("Currency instance is not for the desired locale for CASHCURRENCYSTYLE", cashFmt->getCurrency(), "EUR");
8138     UnicodeString cashBuf;
8139     cashFmt->format(-1234.5, cashBuf);
8140     assertEquals("NumberFormat format outputs wrong value for CASHCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", cashBuf);
8141 
8142     LocalPointer<NumberFormat> stdFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_STANDARD, status));
8143     assertEquals("Currency instance is not for the desired locale for STANDARDCURRENCYSTYLE", stdFmt->getCurrency(), "EUR");
8144     UnicodeString stdBuf;
8145     stdFmt->format(-1234.5, stdBuf);
8146     assertEquals("NumberFormat format outputs wrong value for STANDARDCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", stdBuf);
8147 }
8148 
8149 // for #5186
TestEquality()8150 void NumberFormatTest::TestEquality() {
8151     UErrorCode status = U_ZERO_ERROR;
8152     DecimalFormatSymbols symbols(Locale("root"), status);
8153     if (U_FAILURE(status)) {
8154     	dataerrln("Fail: can't create DecimalFormatSymbols for root");
8155     	return;
8156     }
8157     UnicodeString pattern("#,##0.###");
8158     DecimalFormat fmtBase(pattern, symbols, status);
8159     if (U_FAILURE(status)) {
8160     	dataerrln("Fail: can't create DecimalFormat using root symbols");
8161     	return;
8162     }
8163 
8164     DecimalFormat* fmtClone = fmtBase.clone();
8165     fmtClone->setFormatWidth(fmtBase.getFormatWidth() + 32);
8166     if (*fmtClone == fmtBase) {
8167         errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth");
8168     }
8169     delete fmtClone;
8170 }
8171 
TestCurrencyUsage()8172 void NumberFormatTest::TestCurrencyUsage() {
8173     double agent = 123.567;
8174 
8175     UErrorCode status;
8176     DecimalFormat *fmt;
8177 
8178     // compare the Currency and Currency Cash Digits
8179     // Note that as of CLDR 26:
8180     // * TWD and PKR switched from 0 decimals to 2; ISK still has 0, so change test to that
8181     // * CAD rounds to .05 in cash mode only
8182     // 1st time for getter/setter, 2nd time for factory method
8183     Locale enUS_ISK("en_US@currency=ISK");
8184 
8185     for(int i=0; i<2; i++){
8186         status = U_ZERO_ERROR;
8187         if(i == 0){
8188             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CURRENCY, status);
8189             if (assertSuccess("en_US@currency=ISK/CURRENCY", status, true) == false) {
8190                 continue;
8191             }
8192 
8193             UnicodeString original;
8194             fmt->format(agent,original);
8195             assertEquals("Test Currency Usage 1", u"ISK\u00A0124", original);
8196 
8197             // test the getter here
8198             UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8199             assertEquals("Test usage getter - standard", (int32_t)curUsage, (int32_t)UCURR_USAGE_STANDARD);
8200 
8201             fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8202         }else{
8203             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CASH_CURRENCY, status);
8204             if (assertSuccess("en_US@currency=ISK/CASH", status, true) == false) {
8205                 continue;
8206             }
8207         }
8208 
8209         // must be usage = cash
8210         UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8211         assertEquals("Test usage getter - cash", (int32_t)curUsage, (int32_t)UCURR_USAGE_CASH);
8212 
8213         UnicodeString cash_currency;
8214         fmt->format(agent,cash_currency);
8215         assertEquals("Test Currency Usage 2", u"ISK\u00A0124", cash_currency);
8216         delete fmt;
8217     }
8218 
8219     // compare the Currency and Currency Cash Rounding
8220     // 1st time for getter/setter, 2nd time for factory method
8221     Locale enUS_CAD("en_US@currency=CAD");
8222     for(int i=0; i<2; i++){
8223         status = U_ZERO_ERROR;
8224         if(i == 0){
8225             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8226             if (assertSuccess("en_US@currency=CAD/CURRENCY", status, true) == false) {
8227                 continue;
8228             }
8229 
8230             UnicodeString original_rounding;
8231             fmt->format(agent, original_rounding);
8232             assertEquals("Test Currency Usage 3", u"CA$123.57", original_rounding);
8233             fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8234         }else{
8235             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8236             if (assertSuccess("en_US@currency=CAD/CASH", status, true) == false) {
8237                 continue;
8238             }
8239         }
8240 
8241         UnicodeString cash_rounding_currency;
8242         fmt->format(agent, cash_rounding_currency);
8243         assertEquals("Test Currency Usage 4", u"CA$123.55", cash_rounding_currency);
8244         delete fmt;
8245     }
8246 
8247     // Test the currency change
8248     // 1st time for getter/setter, 2nd time for factory method
8249     const UChar CUR_PKR[] = {0x50, 0x4B, 0x52, 0};
8250     for(int i=0; i<2; i++){
8251         status = U_ZERO_ERROR;
8252         if(i == 0){
8253             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8254             if (assertSuccess("en_US@currency=CAD/CURRENCY", status, true) == false) {
8255                 continue;
8256             }
8257             fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8258         }else{
8259             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8260             if (assertSuccess("en_US@currency=CAD/CASH", status, true) == false) {
8261                 continue;
8262             }
8263         }
8264 
8265         UnicodeString cur_original;
8266         fmt->setCurrencyUsage(UCURR_USAGE_STANDARD, &status);
8267         fmt->format(agent, cur_original);
8268         assertEquals("Test Currency Usage 5", u"CA$123.57", cur_original);
8269 
8270         fmt->setCurrency(CUR_PKR, status);
8271         assertSuccess("Set currency to PKR", status);
8272 
8273         UnicodeString PKR_changed;
8274         fmt->format(agent, PKR_changed);
8275         assertEquals("Test Currency Usage 6", u"PKR\u00A0123.57", PKR_changed);
8276         delete fmt;
8277     }
8278 }
8279 
8280 
8281 // Check the constant MAX_INT64_IN_DOUBLE.
8282 // The value should convert to a double with no loss of precision.
8283 // A failure may indicate a platform with a different double format, requiring
8284 // a revision to the constant.
8285 //
8286 // Note that this is actually hard to test, because the language standard gives
8287 //  compilers considerable flexibility to do unexpected things with rounding and
8288 //  with overflow in simple int to/from float conversions. Some compilers will completely optimize
8289 //  away a simple round-trip conversion from int64_t -> double -> int64_t.
8290 
TestDoubleLimit11439()8291 void NumberFormatTest::TestDoubleLimit11439() {
8292     char  buf[50];
8293     for (int64_t num = MAX_INT64_IN_DOUBLE-10; num<=MAX_INT64_IN_DOUBLE; num++) {
8294         sprintf(buf, "%lld", (long long)num);
8295         double fNum = 0.0;
8296         sscanf(buf, "%lf", &fNum);
8297         int64_t rtNum = static_cast<int64_t>(fNum);
8298         if (num != rtNum) {
8299             errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8300             return;
8301         }
8302     }
8303     for (int64_t num = -MAX_INT64_IN_DOUBLE+10; num>=-MAX_INT64_IN_DOUBLE; num--) {
8304         sprintf(buf, "%lld", (long long)num);
8305         double fNum = 0.0;
8306         sscanf(buf, "%lf", &fNum);
8307         int64_t rtNum = static_cast<int64_t>(fNum);
8308         if (num != rtNum) {
8309             errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8310             return;
8311         }
8312     }
8313 }
8314 
TestGetAffixes()8315 void NumberFormatTest::TestGetAffixes() {
8316     UErrorCode status = U_ZERO_ERROR;
8317     DecimalFormatSymbols sym("en_US", status);
8318     UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8319     pattern = pattern.unescape();
8320     DecimalFormat fmt(pattern, sym, status);
8321     if (U_FAILURE(status)) {
8322         dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8323         return;
8324     }
8325     UnicodeString affixStr;
8326     assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8327     assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8328     assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8329     assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8330 
8331     // Test equality with affixes. set affix methods can't capture special
8332     // characters which is why equality should fail.
8333     {
8334         DecimalFormat fmtCopy(fmt);
8335         assertTrue("", fmt == fmtCopy);
8336         UnicodeString someAffix;
8337         fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(someAffix));
8338         assertTrue("", fmt != fmtCopy);
8339     }
8340     {
8341         DecimalFormat fmtCopy(fmt);
8342         assertTrue("", fmt == fmtCopy);
8343         UnicodeString someAffix;
8344         fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(someAffix));
8345         assertTrue("", fmt != fmtCopy);
8346     }
8347     {
8348         DecimalFormat fmtCopy(fmt);
8349         assertTrue("", fmt == fmtCopy);
8350         UnicodeString someAffix;
8351         fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(someAffix));
8352         assertTrue("", fmt != fmtCopy);
8353     }
8354     {
8355         DecimalFormat fmtCopy(fmt);
8356         assertTrue("", fmt == fmtCopy);
8357         UnicodeString someAffix;
8358         fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(someAffix));
8359         assertTrue("", fmt != fmtCopy);
8360     }
8361     fmt.setPositivePrefix("Don't");
8362     fmt.setPositiveSuffix("do");
8363     UnicodeString someAffix("be''eet\\u00a4\\u00a4\\u00a4 it.");
8364     someAffix = someAffix.unescape();
8365     fmt.setNegativePrefix(someAffix);
8366     fmt.setNegativeSuffix("%");
8367     assertEquals("", "Don't", fmt.getPositivePrefix(affixStr));
8368     assertEquals("", "do", fmt.getPositiveSuffix(affixStr));
8369     assertEquals("", someAffix, fmt.getNegativePrefix(affixStr));
8370     assertEquals("", "%", fmt.getNegativeSuffix(affixStr));
8371 }
8372 
TestToPatternScientific11648()8373 void NumberFormatTest::TestToPatternScientific11648() {
8374     UErrorCode status = U_ZERO_ERROR;
8375     Locale en("en");
8376     DecimalFormatSymbols sym(en, status);
8377     DecimalFormat fmt("0.00", sym, status);
8378     if (U_FAILURE(status)) {
8379         dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8380         return;
8381     }
8382     fmt.setScientificNotation(true);
8383     UnicodeString pattern;
8384     assertEquals("", "0.00E0", fmt.toPattern(pattern));
8385     DecimalFormat fmt2(pattern, sym, status);
8386     assertSuccess("", status);
8387 }
8388 
TestBenchmark()8389 void NumberFormatTest::TestBenchmark() {
8390 /*
8391     UErrorCode status = U_ZERO_ERROR;
8392     Locale en("en");
8393     DecimalFormatSymbols sym(en, status);
8394     DecimalFormat fmt("0.0000000", new DecimalFormatSymbols(sym), status);
8395 //    DecimalFormat fmt("0.00000E0", new DecimalFormatSymbols(sym), status);
8396 //    DecimalFormat fmt("0", new DecimalFormatSymbols(sym), status);
8397     FieldPosition fpos(FieldPosition::DONT_CARE);
8398     clock_t start = clock();
8399     for (int32_t i = 0; i < 1000000; ++i) {
8400         UnicodeString append;
8401         fmt.format(3.0, append, fpos, status);
8402 //        fmt.format(4.6692016, append, fpos, status);
8403 //        fmt.format(1234567.8901, append, fpos, status);
8404 //        fmt.format(2.99792458E8, append, fpos, status);
8405 //        fmt.format(31, append);
8406     }
8407     errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8408     assertSuccess("", status);
8409 
8410     UErrorCode status = U_ZERO_ERROR;
8411     MessageFormat fmt("{0, plural, one {I have # friend.} other {I have # friends.}}", status);
8412     FieldPosition fpos(FieldPosition::DONT_CARE);
8413     Formattable one(1.0);
8414     Formattable three(3.0);
8415     clock_t start = clock();
8416     for (int32_t i = 0; i < 500000; ++i) {
8417         UnicodeString append;
8418         fmt.format(&one, 1, append, fpos, status);
8419         UnicodeString append2;
8420         fmt.format(&three, 1, append2, fpos, status);
8421     }
8422     errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8423     assertSuccess("", status);
8424 
8425     UErrorCode status = U_ZERO_ERROR;
8426     Locale en("en");
8427     Measure measureC(23, MeasureUnit::createCelsius(status), status);
8428     MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
8429     FieldPosition fpos(FieldPosition::DONT_CARE);
8430     clock_t start = clock();
8431     for (int32_t i = 0; i < 1000000; ++i) {
8432         UnicodeString appendTo;
8433         fmt.formatMeasures(
8434                 &measureC, 1, appendTo, fpos, status);
8435     }
8436     errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8437     assertSuccess("", status);
8438 */
8439 }
8440 
TestFractionalDigitsForCurrency()8441 void NumberFormatTest::TestFractionalDigitsForCurrency() {
8442     UErrorCode status = U_ZERO_ERROR;
8443     LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance("en", status));
8444     if (U_FAILURE(status)) {
8445         dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8446         return;
8447     }
8448     UChar JPY[] = {0x4A, 0x50, 0x59, 0x0};
8449     fmt->setCurrency(JPY, status);
8450     if (!assertSuccess("", status)) {
8451         return;
8452     }
8453     assertEquals("", 0, fmt->getMaximumFractionDigits());
8454 }
8455 
8456 
TestFormatCurrencyPlural()8457 void NumberFormatTest::TestFormatCurrencyPlural() {
8458     UErrorCode status = U_ZERO_ERROR;
8459     Locale locale = Locale::createCanonical("en_US");
8460     NumberFormat *fmt = NumberFormat::createInstance(locale, UNUM_CURRENCY_PLURAL, status);
8461     if (U_FAILURE(status)) {
8462         dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8463         return;
8464     }
8465    UnicodeString formattedNum;
8466    fmt->format(11234.567, formattedNum, NULL, status);
8467    assertEquals("", "11,234.57 US dollars", formattedNum);
8468    delete fmt;
8469 }
8470 
TestCtorApplyPatternDifference()8471 void NumberFormatTest::TestCtorApplyPatternDifference() {
8472     UErrorCode status = U_ZERO_ERROR;
8473     DecimalFormatSymbols sym("en_US", status);
8474     UnicodeString pattern("\\u00a40");
8475     DecimalFormat fmt(pattern.unescape(), sym, status);
8476     if (U_FAILURE(status)) {
8477         dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8478         return;
8479     }
8480     UnicodeString result;
8481     assertEquals(
8482             "ctor favors precision of currency",
8483             "$5.00",
8484             fmt.format((double)5, result));
8485     result.remove();
8486     fmt.applyPattern(pattern.unescape(), status);
8487     assertEquals(
8488             "applyPattern favors precision of pattern",
8489             "$5",
8490             fmt.format((double)5, result));
8491 }
8492 
Test11868()8493 void NumberFormatTest::Test11868() {
8494     double posAmt = 34.567;
8495     double negAmt = -9876.543;
8496 
8497     Locale selectedLocale("en_US");
8498     UErrorCode status = U_ZERO_ERROR;
8499 
8500     UnicodeString result;
8501     FieldPosition fpCurr(UNUM_CURRENCY_FIELD);
8502     LocalPointer<NumberFormat> fmt(
8503             NumberFormat::createInstance(
8504                     selectedLocale, UNUM_CURRENCY_PLURAL, status));
8505     if (!assertSuccess("Format creation", status)) {
8506         return;
8507     }
8508     fmt->format(posAmt, result, fpCurr, status);
8509     assertEquals("", "34.57 US dollars", result);
8510     assertEquals("begin index", 6, fpCurr.getBeginIndex());
8511     assertEquals("end index", 16, fpCurr.getEndIndex());
8512 
8513     // Test field position iterator
8514     {
8515         NumberFormatTest_Attributes attributes[] = {
8516                 {UNUM_INTEGER_FIELD, 0, 2},
8517                 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8518                 {UNUM_FRACTION_FIELD, 3, 5},
8519                 {UNUM_CURRENCY_FIELD, 6, 16},
8520                 {0, -1, 0}};
8521         UnicodeString result;
8522         FieldPositionIterator iter;
8523         fmt->format(posAmt, result, &iter, status);
8524         assertEquals("", "34.57 US dollars", result);
8525         verifyFieldPositionIterator(attributes, iter);
8526     }
8527 
8528     result.remove();
8529     fmt->format(negAmt, result, fpCurr, status);
8530     assertEquals("", "-9,876.54 US dollars", result);
8531     assertEquals("begin index", 10, fpCurr.getBeginIndex());
8532     assertEquals("end index", 20, fpCurr.getEndIndex());
8533 
8534     // Test field position iterator
8535     {
8536         NumberFormatTest_Attributes attributes[] = {
8537                 {UNUM_SIGN_FIELD, 0, 1},
8538                 {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
8539                 {UNUM_INTEGER_FIELD, 1, 6},
8540                 {UNUM_DECIMAL_SEPARATOR_FIELD, 6, 7},
8541                 {UNUM_FRACTION_FIELD, 7, 9},
8542                 {UNUM_CURRENCY_FIELD, 10, 20},
8543                 {0, -1, 0}};
8544         UnicodeString result;
8545         FieldPositionIterator iter;
8546         fmt->format(negAmt, result, &iter, status);
8547         assertEquals("", "-9,876.54 US dollars", result);
8548         verifyFieldPositionIterator(attributes, iter);
8549     }
8550 }
8551 
Test10727_RoundingZero()8552 void NumberFormatTest::Test10727_RoundingZero() {
8553     IcuTestErrorCode status(*this, "Test10727_RoundingZero");
8554     DecimalQuantity dq;
8555     dq.setToDouble(-0.0);
8556     assertTrue("", dq.isNegative());
8557     dq.roundToMagnitude(0, UNUM_ROUND_HALFEVEN, status);
8558     assertTrue("", dq.isNegative());
8559 }
8560 
Test11739_ParseLongCurrency()8561 void NumberFormatTest::Test11739_ParseLongCurrency() {
8562     IcuTestErrorCode status(*this, "Test11739_ParseLongCurrency");
8563     LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("sr_BA", status));
8564     if (status.errDataIfFailureAndReset()) { return; }
8565     ((DecimalFormat*) nf.getAlias())->applyPattern(u"#,##0.0 ¤¤¤", status);
8566     ParsePosition ppos(0);
8567     LocalPointer<CurrencyAmount> result(nf->parseCurrency(u"1.500 амерички долар", ppos));
8568     assertEquals("Should parse to 1500 USD", -1, ppos.getErrorIndex());
8569     if (ppos.getErrorIndex() != -1) {
8570         return;
8571     }
8572     assertEquals("Should parse to 1500 USD", 1500LL, result->getNumber().getInt64(status));
8573     assertEquals("Should parse to 1500 USD", u"USD", result->getISOCurrency());
8574 }
8575 
Test13035_MultiCodePointPaddingInPattern()8576 void NumberFormatTest::Test13035_MultiCodePointPaddingInPattern() {
8577     IcuTestErrorCode status(*this, "Test13035_MultiCodePointPaddingInPattern");
8578     DecimalFormat df(u"a*'நி'###0b", status);
8579     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8580     UnicodeString result;
8581     df.format(12, result.remove());
8582     // TODO(13034): Re-enable this test when support is added in ICU4C.
8583     //assertEquals("Multi-codepoint padding should not be split", u"aநிநி12b", result);
8584     df = DecimalFormat(u"a*\U0001F601###0b", status);
8585     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8586     result = df.format(12, result.remove());
8587     assertEquals("Single-codepoint padding should not be split", u"a\U0001F601\U0001F60112b", result, true);
8588     df = DecimalFormat(u"a*''###0b", status);
8589     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8590     result = df.format(12, result.remove());
8591     assertEquals("Quote should be escapable in padding syntax", "a''12b", result, true);
8592 }
8593 
Test13737_ParseScientificStrict()8594 void NumberFormatTest::Test13737_ParseScientificStrict() {
8595     IcuTestErrorCode status(*this, "Test13737_ParseScientificStrict");
8596     LocalPointer<NumberFormat> df(NumberFormat::createScientificInstance("en", status), status);
8597     if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8598     df->setLenient(false);
8599     // Parse Test
8600     expect(*df, u"1.2", 1.2);
8601 }
8602 
Test11376_getAndSetPositivePrefix()8603 void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
8604     {
8605         const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8606         UErrorCode status = U_ZERO_ERROR;
8607         LocalPointer<NumberFormat> fmt(
8608                 NumberFormat::createCurrencyInstance("en", status));
8609         if (!assertSuccess("", status)) {
8610             return;
8611         }
8612         DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8613         dfmt->setCurrency(USD);
8614         UnicodeString result;
8615 
8616         // This line should be a no-op. I am setting the positive prefix
8617         // to be the same thing it was before.
8618         dfmt->setPositivePrefix(dfmt->getPositivePrefix(result));
8619 
8620         UnicodeString appendTo;
8621         assertEquals("", "$3.78", dfmt->format(3.78, appendTo, status));
8622         assertSuccess("", status);
8623     }
8624     {
8625         const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8626         UErrorCode status = U_ZERO_ERROR;
8627         LocalPointer<NumberFormat> fmt(
8628                 NumberFormat::createInstance("en", UNUM_CURRENCY_PLURAL, status));
8629         if (!assertSuccess("", status)) {
8630             return;
8631         }
8632         DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8633         UnicodeString result;
8634         assertEquals("", u" (unknown currency)", dfmt->getPositiveSuffix(result));
8635         dfmt->setCurrency(USD);
8636 
8637         // getPositiveSuffix() always returns the suffix for the
8638         // "other" plural category
8639         assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8640         UnicodeString appendTo;
8641         assertEquals("", "3.78 US dollars", dfmt->format(3.78, appendTo, status));
8642         assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8643         dfmt->setPositiveSuffix("booya");
8644         appendTo.remove();
8645         assertEquals("", "3.78booya", dfmt->format(3.78, appendTo, status));
8646         assertEquals("", "booya", dfmt->getPositiveSuffix(result));
8647     }
8648 }
8649 
Test11475_signRecognition()8650 void NumberFormatTest::Test11475_signRecognition() {
8651     UErrorCode status = U_ZERO_ERROR;
8652     DecimalFormatSymbols sym("en", status);
8653     UnicodeString result;
8654     {
8655         DecimalFormat fmt("+0.00", sym, status);
8656         if (!assertSuccess("", status)) {
8657             return;
8658         }
8659         NumberFormatTest_Attributes attributes[] = {
8660                 {UNUM_SIGN_FIELD, 0, 1},
8661                 {UNUM_INTEGER_FIELD, 1, 2},
8662                 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8663                 {UNUM_FRACTION_FIELD, 3, 5},
8664                 {0, -1, 0}};
8665         UnicodeString result;
8666         FieldPositionIterator iter;
8667         fmt.format(2.3, result, &iter, status);
8668         assertEquals("", "+2.30", result);
8669         verifyFieldPositionIterator(attributes, iter);
8670     }
8671     {
8672         DecimalFormat fmt("++0.00+;-(#)--", sym, status);
8673         if (!assertSuccess("", status)) {
8674             return;
8675         }
8676         {
8677             NumberFormatTest_Attributes attributes[] = {
8678                     {UNUM_SIGN_FIELD, 0, 2},
8679                     {UNUM_INTEGER_FIELD, 2, 3},
8680                     {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8681                     {UNUM_FRACTION_FIELD, 4, 6},
8682                     {UNUM_SIGN_FIELD, 6, 7},
8683                     {0, -1, 0}};
8684             UnicodeString result;
8685             FieldPositionIterator iter;
8686             fmt.format(2.3, result, &iter, status);
8687             assertEquals("", "++2.30+", result);
8688             verifyFieldPositionIterator(attributes, iter);
8689         }
8690         {
8691             NumberFormatTest_Attributes attributes[] = {
8692                     {UNUM_SIGN_FIELD, 0, 1},
8693                     {UNUM_INTEGER_FIELD, 2, 3},
8694                     {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8695                     {UNUM_FRACTION_FIELD, 4, 6},
8696                     {UNUM_SIGN_FIELD, 7, 9},
8697                     {0, -1, 0}};
8698             UnicodeString result;
8699             FieldPositionIterator iter;
8700             fmt.format(-2.3, result, &iter, status);
8701             assertEquals("", "-(2.30)--", result);
8702             verifyFieldPositionIterator(attributes, iter);
8703         }
8704     }
8705 }
8706 
Test11640_getAffixes()8707 void NumberFormatTest::Test11640_getAffixes() {
8708     UErrorCode status = U_ZERO_ERROR;
8709     DecimalFormatSymbols symbols("en_US", status);
8710     if (!assertSuccess("", status)) {
8711         return;
8712     }
8713     UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8714     pattern = pattern.unescape();
8715     DecimalFormat fmt(pattern, symbols, status);
8716     if (!assertSuccess("", status)) {
8717         return;
8718     }
8719     UnicodeString affixStr;
8720     assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8721     assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8722     assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8723     assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8724 }
8725 
Test11649_toPatternWithMultiCurrency()8726 void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
8727     UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
8728     pattern = pattern.unescape();
8729     UErrorCode status = U_ZERO_ERROR;
8730     DecimalFormat fmt(pattern, status);
8731     if (!assertSuccess("", status)) {
8732         return;
8733     }
8734     static UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8735     fmt.setCurrency(USD);
8736     UnicodeString appendTo;
8737 
8738     assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
8739 
8740     UnicodeString topattern;
8741     fmt.toPattern(topattern);
8742     DecimalFormat fmt2(topattern, status);
8743     if (!assertSuccess("", status)) {
8744         return;
8745     }
8746     fmt2.setCurrency(USD);
8747 
8748     appendTo.remove();
8749     assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
8750 }
8751 
Test13327_numberingSystemBufferOverflow()8752 void NumberFormatTest::Test13327_numberingSystemBufferOverflow() {
8753     UErrorCode status = U_ZERO_ERROR;
8754     for (int runId = 0; runId < 2; runId++) {
8755         // Construct a locale string with a very long "numbers" value.
8756         // The first time, make the value length exactly equal to ULOC_KEYWORDS_CAPACITY.
8757         // The second time, make it exceed ULOC_KEYWORDS_CAPACITY.
8758         int extraLength = (runId == 0) ? 0 : 5;
8759 
8760         CharString localeId("en@numbers=", status);
8761         for (int i = 0; i < ULOC_KEYWORDS_CAPACITY + extraLength; i++) {
8762             localeId.append('x', status);
8763         }
8764         assertSuccess("Constructing locale string", status);
8765         Locale locale(localeId.data());
8766 
8767         LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(locale, status));
8768         assertFalse("Should not be null", ns.getAlias() == nullptr);
8769         assertSuccess("Should create with no error", status);
8770     }
8771 }
8772 
Test13391_chakmaParsing()8773 void NumberFormatTest::Test13391_chakmaParsing() {
8774     UErrorCode status = U_ZERO_ERROR;
8775     LocalPointer<DecimalFormat> df(dynamic_cast<DecimalFormat*>(
8776         NumberFormat::createInstance(Locale("ccp"), status)));
8777     if (df == nullptr) {
8778         dataerrln("%s %d Chakma df is null",  __FILE__, __LINE__);
8779         return;
8780     }
8781     const UChar* expected = u"\U00011137\U00011138,\U00011139\U0001113A\U0001113B";
8782     UnicodeString actual;
8783     df->format(12345, actual, status);
8784     assertSuccess("Should not fail when formatting in ccp", status);
8785     assertEquals("Should produce expected output in ccp", expected, actual);
8786 
8787     Formattable result;
8788     df->parse(expected, result, status);
8789     assertSuccess("Should not fail when parsing in ccp", status);
8790     assertEquals("Should parse to 12345 in ccp", 12345, result);
8791 
8792     const UChar* expectedScientific = u"\U00011137.\U00011139E\U00011138";
8793     UnicodeString actualScientific;
8794     df.adoptInstead(static_cast<DecimalFormat*>(
8795         NumberFormat::createScientificInstance(Locale("ccp"), status)));
8796     df->format(130, actualScientific, status);
8797     assertSuccess("Should not fail when formatting scientific in ccp", status);
8798     assertEquals("Should produce expected scientific output in ccp",
8799         expectedScientific, actualScientific);
8800 
8801     Formattable resultScientific;
8802     df->parse(expectedScientific, resultScientific, status);
8803     assertSuccess("Should not fail when parsing scientific in ccp", status);
8804     assertEquals("Should parse scientific to 130 in ccp", 130, resultScientific);
8805 }
8806 
8807 
verifyFieldPositionIterator( NumberFormatTest_Attributes *expected, FieldPositionIterator &iter)8808 void NumberFormatTest::verifyFieldPositionIterator(
8809         NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
8810     int32_t idx = 0;
8811     FieldPosition fp;
8812     while (iter.next(fp)) {
8813         if (expected[idx].spos == -1) {
8814             errln("Iterator should have ended. got %d", fp.getField());
8815             return;
8816         }
8817         assertEquals("id", expected[idx].id, fp.getField());
8818         assertEquals("start", expected[idx].spos, fp.getBeginIndex());
8819         assertEquals("end", expected[idx].epos, fp.getEndIndex());
8820         ++idx;
8821     }
8822     if (expected[idx].spos != -1) {
8823         errln("Premature end of iterator. expected %d", expected[idx].id);
8824     }
8825 }
8826 
Test11735_ExceptionIssue()8827 void NumberFormatTest::Test11735_ExceptionIssue() {
8828     IcuTestErrorCode status(*this, "Test11735_ExceptionIssue");
8829     Locale enLocale("en");
8830     DecimalFormatSymbols symbols(enLocale, status);
8831     if (status.isSuccess()) {
8832         DecimalFormat fmt("0", symbols, status);
8833         assertSuccess("Fail: Construct DecimalFormat formatter", status, true, __FILE__, __LINE__);
8834         ParsePosition ppos(0);
8835         fmt.parseCurrency("53.45", ppos);  // NPE thrown here in ICU4J.
8836         assertEquals("Issue11735 ppos", 0, ppos.getIndex());
8837     }
8838 }
8839 
Test11035_FormatCurrencyAmount()8840 void NumberFormatTest::Test11035_FormatCurrencyAmount() {
8841     UErrorCode status = U_ZERO_ERROR;
8842     double amount = 12345.67;
8843     const char16_t* expected = u"12,345$67 ​";
8844 
8845     // Test two ways to set a currency via API
8846 
8847     Locale loc1 = Locale("pt_PT");
8848     LocalPointer<NumberFormat> fmt1(NumberFormat::createCurrencyInstance(loc1, status),
8849                                     status);
8850     if (U_FAILURE(status)) {
8851       dataerrln("%s %d NumberFormat instance fmt1 is null",  __FILE__, __LINE__);
8852       return;
8853     }
8854     fmt1->setCurrency(u"PTE", status);
8855     assertSuccess("Setting currency on fmt1", status);
8856     UnicodeString actualSetCurrency;
8857     fmt1->format(amount, actualSetCurrency);
8858 
8859     Locale loc2 = Locale("pt_PT@currency=PTE");
8860     LocalPointer<NumberFormat> fmt2(NumberFormat::createCurrencyInstance(loc2, status));
8861     assertSuccess("Creating fmt2", status);
8862     UnicodeString actualLocaleString;
8863     fmt2->format(amount, actualLocaleString);
8864 
8865     assertEquals("Custom Currency Pattern, Set Currency", expected, actualSetCurrency);
8866     assertEquals("Custom Currency Pattern, Locale String", expected, actualLocaleString);
8867 }
8868 
Test11318_DoubleConversion()8869 void NumberFormatTest::Test11318_DoubleConversion() {
8870     IcuTestErrorCode status(*this, "Test11318_DoubleConversion");
8871     LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
8872     if (U_FAILURE(status)) {
8873       dataerrln("%s %d Error in NumberFormat instance creation",  __FILE__, __LINE__);
8874       return;
8875     }
8876     nf->setMaximumFractionDigits(40);
8877     nf->setMaximumIntegerDigits(40);
8878     UnicodeString appendTo;
8879     nf->format(999999999999999.9, appendTo);
8880     assertEquals("Should render all digits", u"999,999,999,999,999.9", appendTo);
8881 }
8882 
TestParsePercentRegression()8883 void NumberFormatTest::TestParsePercentRegression() {
8884     IcuTestErrorCode status(*this, "TestParsePercentRegression");
8885     LocalPointer<DecimalFormat> df1((DecimalFormat*) NumberFormat::createInstance("en", status), status);
8886     LocalPointer<DecimalFormat> df2((DecimalFormat*) NumberFormat::createPercentInstance("en", status), status);
8887     if (status.isFailure()) {return; }
8888     df1->setLenient(true);
8889     df2->setLenient(true);
8890 
8891     {
8892         ParsePosition ppos;
8893         Formattable result;
8894         df1->parse("50%", result, ppos);
8895         assertEquals("df1 should accept a number but not the percent sign", 2, ppos.getIndex());
8896         assertEquals("df1 should return the number as 50", 50.0, result.getDouble(status));
8897     }
8898     {
8899         ParsePosition ppos;
8900         Formattable result;
8901         df2->parse("50%", result, ppos);
8902         assertEquals("df2 should accept the percent sign", 3, ppos.getIndex());
8903         assertEquals("df2 should return the number as 0.5", 0.5, result.getDouble(status));
8904     }
8905     {
8906         ParsePosition ppos;
8907         Formattable result;
8908         df2->parse("50", result, ppos);
8909         assertEquals("df2 should return the number as 0.5 even though the percent sign is missing",
8910                 0.5,
8911                 result.getDouble(status));
8912     }
8913 }
8914 
TestMultiplierWithScale()8915 void NumberFormatTest::TestMultiplierWithScale() {
8916     IcuTestErrorCode status(*this, "TestMultiplierWithScale");
8917 
8918     // Test magnitude combined with multiplier, as shown in API docs
8919     DecimalFormat df("0", {"en", status}, status);
8920     if (status.isSuccess()) {
8921         df.setMultiplier(5);
8922         df.setMultiplierScale(-1);
8923         expect2(df, 100, u"50"); // round-trip test
8924     }
8925 }
8926 
TestFastFormatInt32()8927 void NumberFormatTest::TestFastFormatInt32() {
8928     IcuTestErrorCode status(*this, "TestFastFormatInt32");
8929 
8930     // The two simplest formatters, old API and new API.
8931     // Old API should use the fastpath for ints.
8932     LocalizedNumberFormatter lnf = NumberFormatter::withLocale("en");
8933     LocalPointer<NumberFormat> df(NumberFormat::createInstance("en", status), status);
8934     if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8935 
8936     double nums[] = {
8937             0.0,
8938             -0.0,
8939             NAN,
8940             INFINITY,
8941             0.1,
8942             1.0,
8943             1.1,
8944             2.0,
8945             3.0,
8946             9.0,
8947             10.0,
8948             99.0,
8949             100.0,
8950             999.0,
8951             1000.0,
8952             9999.0,
8953             10000.0,
8954             99999.0,
8955             100000.0,
8956             999999.0,
8957             1000000.0,
8958             static_cast<double>(INT32_MAX) - 1,
8959             static_cast<double>(INT32_MAX),
8960             static_cast<double>(INT32_MAX) + 1,
8961             static_cast<double>(INT32_MIN) - 1,
8962             static_cast<double>(INT32_MIN),
8963             static_cast<double>(INT32_MIN) + 1};
8964 
8965     for (auto num : nums) {
8966         UnicodeString expected = lnf.formatDouble(num, status).toString(status);
8967         UnicodeString actual;
8968         df->format(num, actual);
8969         assertEquals(UnicodeString("d = ") + num, expected, actual);
8970     }
8971 }
8972 
Test11646_Equality()8973 void NumberFormatTest::Test11646_Equality() {
8974     UErrorCode status = U_ZERO_ERROR;
8975     DecimalFormatSymbols symbols(Locale::getEnglish(), status);
8976     UnicodeString pattern(u"\u00a4\u00a4\u00a4 0.00 %\u00a4\u00a4");
8977     DecimalFormat fmt(pattern, symbols, status);
8978     if (!assertSuccess("", status)) return;
8979 
8980     // Test equality with affixes. set affix methods can't capture special
8981     // characters which is why equality should fail.
8982     {
8983         DecimalFormat fmtCopy(fmt);
8984         assertTrue("", fmt == fmtCopy);
8985         UnicodeString positivePrefix;
8986         fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(positivePrefix));
8987         assertFalse("", fmt == fmtCopy);
8988     }
8989     {
8990         DecimalFormat fmtCopy = DecimalFormat(fmt);
8991         assertTrue("", fmt == fmtCopy);
8992         UnicodeString positivePrefix;
8993         fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(positivePrefix));
8994         assertFalse("", fmt == fmtCopy);
8995     }
8996     {
8997         DecimalFormat fmtCopy(fmt);
8998         assertTrue("", fmt == fmtCopy);
8999         UnicodeString negativePrefix;
9000         fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(negativePrefix));
9001         assertFalse("", fmt == fmtCopy);
9002     }
9003     {
9004         DecimalFormat fmtCopy(fmt);
9005         assertTrue("", fmt == fmtCopy);
9006         UnicodeString negativePrefix;
9007         fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(negativePrefix));
9008         assertFalse("", fmt == fmtCopy);
9009     }
9010 }
9011 
TestParseNaN()9012 void NumberFormatTest::TestParseNaN() {
9013     IcuTestErrorCode status(*this, "TestParseNaN");
9014 
9015     DecimalFormat df("0", { "en", status }, status);
9016     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9017     Formattable parseResult;
9018     df.parse(u"NaN", parseResult, status);
9019     assertEquals("NaN should parse successfully", NAN, parseResult.getDouble());
9020     assertFalse("Result NaN should be positive", std::signbit(parseResult.getDouble()));
9021     UnicodeString formatResult;
9022     df.format(parseResult.getDouble(), formatResult);
9023     assertEquals("NaN should round-trip", u"NaN", formatResult);
9024 }
9025 
TestFormatFailIfMoreThanMaxDigits()9026 void NumberFormatTest::TestFormatFailIfMoreThanMaxDigits() {
9027     IcuTestErrorCode status(*this, "TestFormatFailIfMoreThanMaxDigits");
9028 
9029     DecimalFormat df("0", {"en-US", status}, status);
9030     if (status.errDataIfFailureAndReset()) {
9031         return;
9032     }
9033     assertEquals("Coverage for getter 1", (UBool) false, df.isFormatFailIfMoreThanMaxDigits());
9034     df.setFormatFailIfMoreThanMaxDigits(true);
9035     assertEquals("Coverage for getter 2", (UBool) true, df.isFormatFailIfMoreThanMaxDigits());
9036     df.setMaximumIntegerDigits(2);
9037     UnicodeString result;
9038     df.format(1234, result, status);
9039     status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
9040 }
9041 
TestParseCaseSensitive()9042 void NumberFormatTest::TestParseCaseSensitive() {
9043     IcuTestErrorCode status(*this, "TestParseCaseSensitive");
9044 
9045     DecimalFormat df(u"0", {"en-US", status}, status);
9046     if (status.errDataIfFailureAndReset()) {
9047         return;
9048     }
9049     assertEquals("Coverage for getter 1", (UBool) false, df.isParseCaseSensitive());
9050     df.setParseCaseSensitive(true);
9051     assertEquals("Coverage for getter 1", (UBool) true, df.isParseCaseSensitive());
9052     Formattable result;
9053     ParsePosition ppos;
9054     df.parse(u"1e2", result, ppos);
9055     assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9056     assertEquals("Result should be 1", 1.0, result.getDouble(status));
9057 }
9058 
TestParseNoExponent()9059 void NumberFormatTest::TestParseNoExponent() {
9060     IcuTestErrorCode status(*this, "TestParseNoExponent");
9061 
9062     DecimalFormat df(u"0", {"en-US", status}, status);
9063     if (status.errDataIfFailureAndReset()) {
9064         return;
9065     }
9066     assertEquals("Coverage for getter 1", (UBool) false, df.isParseNoExponent());
9067     df.setParseNoExponent(true);
9068     assertEquals("Coverage for getter 1", (UBool) true, df.isParseNoExponent());
9069     Formattable result;
9070     ParsePosition ppos;
9071     df.parse(u"1E2", result, ppos);
9072     assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9073     assertEquals("Result should be 1", 1.0, result.getDouble(status));
9074 }
9075 
TestSignAlwaysShown()9076 void NumberFormatTest::TestSignAlwaysShown() {
9077     IcuTestErrorCode status(*this, "TestSignAlwaysShown");
9078 
9079     DecimalFormat df(u"0", {"en-US", status}, status);
9080     if (status.errDataIfFailureAndReset()) {
9081         return;
9082     }
9083     assertEquals("Coverage for getter 1", (UBool) false, df.isSignAlwaysShown());
9084     df.setSignAlwaysShown(true);
9085     assertEquals("Coverage for getter 1", (UBool) true, df.isSignAlwaysShown());
9086     UnicodeString result;
9087     df.format(1234, result, status);
9088     status.errIfFailureAndReset();
9089     assertEquals("Should show sign on positive number", u"+1234", result);
9090 }
9091 
TestMinimumGroupingDigits()9092 void NumberFormatTest::TestMinimumGroupingDigits() {
9093     IcuTestErrorCode status(*this, "TestMinimumGroupingDigits");
9094 
9095     DecimalFormat df(u"#,##0", {"en-US", status}, status);
9096     if (status.errDataIfFailureAndReset()) {
9097         return;
9098     }
9099     assertEquals("Coverage for getter 1", -1, df.getMinimumGroupingDigits());
9100     df.setMinimumGroupingDigits(2);
9101     assertEquals("Coverage for getter 1", 2, df.getMinimumGroupingDigits());
9102     UnicodeString result;
9103     df.format(1234, result, status);
9104     status.errIfFailureAndReset();
9105     assertEquals("Should not have grouping", u"1234", result);
9106     df.format(12345, result.remove(), status);
9107     status.errIfFailureAndReset();
9108     assertEquals("Should have grouping", u"12,345", result);
9109 
9110 
9111     // Test special values -1, UNUM_MINIMUM_GROUPING_DIGITS_AUTO and
9112     // UNUM_MINIMUM_GROUPING_DIGITS_MIN2
9113     struct TestCase {
9114         const char* locale;
9115         int32_t minGroup;
9116         double input;
9117         const char16_t* expected;
9118     } cases[] = {
9119         { "en-US", 1, 1000, u"1,000" },
9120         { "en-US", 1, 10000, u"10,000" },
9121         { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1,000" },
9122         { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10,000" },
9123         { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9124         { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10,000" },
9125 
9126         { "es", 1, 1000, u"1.000" },
9127         { "es", 1, 10000, u"10.000" },
9128         { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1000" },
9129         { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10.000" },
9130         { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9131         { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10.000" },
9132     };
9133     for (const auto& cas : cases) {
9134         UnicodeString message = UnicodeString(cas.locale)
9135             + u" " + Int64ToUnicodeString(cas.minGroup)
9136             + u" " + DoubleToUnicodeString(cas.input);
9137         status.setScope(message);
9138         DecimalFormat df(u"#,##0", {cas.locale, status}, status);
9139         if (status.errIfFailureAndReset()) { continue; }
9140         df.setMinimumGroupingDigits(cas.minGroup);
9141         UnicodeString actual;
9142         df.format(cas.input, actual, status);
9143         if (status.errIfFailureAndReset()) { continue; }
9144         assertEquals(message, cas.expected, actual);
9145     }
9146 }
9147 
Test11897_LocalizedPatternSeparator()9148 void NumberFormatTest::Test11897_LocalizedPatternSeparator() {
9149     IcuTestErrorCode status(*this, "Test11897_LocalizedPatternSeparator");
9150 
9151     // In a locale with a different <list> symbol, like arabic,
9152     // kPatternSeparatorSymbol should still be ';'
9153     {
9154         DecimalFormatSymbols dfs("ar", status);
9155         assertEquals("pattern separator symbol should be ;",
9156                 u";",
9157                 dfs.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
9158     }
9159 
9160     // However, the custom symbol should be used in localized notation
9161     // when set manually via API
9162     {
9163         DecimalFormatSymbols dfs("en", status);
9164         dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u"!", false);
9165         DecimalFormat df(u"0", dfs, status);
9166         if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9167         df.applyPattern("a0;b0", status); // should not throw
9168         UnicodeString result;
9169         assertEquals("should apply the normal pattern",
9170                 df.getNegativePrefix(result.remove()),
9171                 "b");
9172         df.applyLocalizedPattern(u"c0!d0", status); // should not throw
9173         assertEquals("should apply the localized pattern",
9174                 df.getNegativePrefix(result.remove()),
9175                 "d");
9176     }
9177 }
9178 
Test13055_PercentageRounding()9179 void NumberFormatTest::Test13055_PercentageRounding() {
9180   IcuTestErrorCode status(*this, "PercentageRounding");
9181   UnicodeString actual;
9182   LocalPointer<NumberFormat>pFormat(NumberFormat::createPercentInstance("en_US", status));
9183   if (U_FAILURE(status)) {
9184       dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9185       return;
9186   }
9187   pFormat->setMaximumFractionDigits(0);
9188   pFormat->setRoundingMode(DecimalFormat::kRoundHalfEven);
9189   pFormat->format(2.155, actual);
9190   assertEquals("Should round percent toward even number", "216%", actual);
9191 }
9192 
Test11839()9193 void NumberFormatTest::Test11839() {
9194     IcuTestErrorCode errorCode(*this, "Test11839");
9195     // Ticket #11839: DecimalFormat does not respect custom plus sign
9196     LocalPointer<DecimalFormatSymbols> dfs(new DecimalFormatSymbols(Locale::getEnglish(), errorCode), errorCode);
9197     if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9198     dfs->setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"a∸");
9199     dfs->setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"b∔"); //  ∔  U+2214 DOT PLUS
9200     DecimalFormat df(u"0.00+;0.00-", dfs.orphan(), errorCode);
9201     UnicodeString result;
9202     df.format(-1.234, result, errorCode);
9203     assertEquals("Locale-specific minus sign should be used", u"1.23a∸", result);
9204     df.format(1.234, result.remove(), errorCode);
9205     assertEquals("Locale-specific plus sign should be used", u"1.23b∔", result);
9206     // Test round-trip with parse
9207     expect2(df, -456, u"456.00a∸");
9208     expect2(df, 456, u"456.00b∔");
9209 }
9210 
Test10354()9211 void NumberFormatTest::Test10354() {
9212     IcuTestErrorCode errorCode(*this, "Test10354");
9213     // Ticket #10354: invalid FieldPositionIterator when formatting with empty NaN
9214     DecimalFormatSymbols dfs(errorCode);
9215     UnicodeString empty;
9216     dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, empty);
9217     DecimalFormat df(errorCode);
9218     df.setDecimalFormatSymbols(dfs);
9219     UnicodeString result;
9220     FieldPositionIterator positions;
9221     df.format(NAN, result, &positions, errorCode);
9222     errorCode.errIfFailureAndReset("DecimalFormat.format(NAN, FieldPositionIterator) failed");
9223     FieldPosition fp;
9224     while (positions.next(fp)) {
9225         // Should not loop forever
9226     }
9227 }
9228 
Test11645_ApplyPatternEquality()9229 void NumberFormatTest::Test11645_ApplyPatternEquality() {
9230     IcuTestErrorCode status(*this, "Test11645_ApplyPatternEquality");
9231     const char16_t* pattern = u"#,##0.0#";
9232     LocalPointer<DecimalFormat> fmt((DecimalFormat*) NumberFormat::createInstance(status), status);
9233     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9234     fmt->applyPattern(pattern, status);
9235     LocalPointer<DecimalFormat> fmtCopy;
9236 
9237     static const int32_t newMultiplier = 37;
9238     fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9239     assertFalse("Value before setter", fmtCopy->getMultiplier() == newMultiplier);
9240     fmtCopy->setMultiplier(newMultiplier);
9241     assertEquals("Value after setter", fmtCopy->getMultiplier(), newMultiplier);
9242     fmtCopy->applyPattern(pattern, status);
9243     assertEquals("Value after applyPattern", fmtCopy->getMultiplier(), newMultiplier);
9244     assertFalse("multiplier", *fmt == *fmtCopy);
9245 
9246     static const NumberFormat::ERoundingMode newRoundingMode = NumberFormat::ERoundingMode::kRoundCeiling;
9247     fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9248     assertFalse("Value before setter", fmtCopy->getRoundingMode() == newRoundingMode);
9249     fmtCopy->setRoundingMode(newRoundingMode);
9250     assertEquals("Value after setter", fmtCopy->getRoundingMode(), newRoundingMode);
9251     fmtCopy->applyPattern(pattern, status);
9252     assertEquals("Value after applyPattern", fmtCopy->getRoundingMode(), newRoundingMode);
9253     assertFalse("roundingMode", *fmt == *fmtCopy);
9254 
9255     static const char16_t *const newCurrency = u"EAT";
9256     fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9257     assertFalse("Value before setter", fmtCopy->getCurrency() == newCurrency);
9258     fmtCopy->setCurrency(newCurrency);
9259     assertEquals("Value after setter", fmtCopy->getCurrency(), newCurrency);
9260     fmtCopy->applyPattern(pattern, status);
9261     assertEquals("Value after applyPattern", fmtCopy->getCurrency(), newCurrency);
9262     assertFalse("currency", *fmt == *fmtCopy);
9263 
9264     static const UCurrencyUsage newCurrencyUsage = UCurrencyUsage::UCURR_USAGE_CASH;
9265     fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9266     assertFalse("Value before setter", fmtCopy->getCurrencyUsage() == newCurrencyUsage);
9267     fmtCopy->setCurrencyUsage(newCurrencyUsage, status);
9268     assertEquals("Value after setter", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9269     fmtCopy->applyPattern(pattern, status);
9270     assertEquals("Value after applyPattern", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9271     assertFalse("currencyUsage", *fmt == *fmtCopy);
9272 }
9273 
Test12567()9274 void NumberFormatTest::Test12567() {
9275     IcuTestErrorCode errorCode(*this, "Test12567");
9276     // Ticket #12567: DecimalFormat.equals() may not be symmetric
9277     LocalPointer<DecimalFormat> df1((DecimalFormat *)
9278         NumberFormat::createInstance(Locale::getUS(), UNUM_CURRENCY, errorCode));
9279     LocalPointer<DecimalFormat> df2((DecimalFormat *)
9280         NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, errorCode));
9281     if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9282     // NOTE: CurrencyPluralInfo equality not tested in C++ because its operator== is not defined.
9283     df1->applyPattern(u"0.00", errorCode);
9284     df2->applyPattern(u"0.00", errorCode);
9285     assertTrue("df1 == df2", *df1 == *df2);
9286     assertTrue("df2 == df1", *df2 == *df1);
9287     df2->setPositivePrefix(u"abc");
9288     assertTrue("df1 != df2", *df1 != *df2);
9289     assertTrue("df2 != df1", *df2 != *df1);
9290 }
9291 
Test11626_CustomizeCurrencyPluralInfo()9292 void NumberFormatTest::Test11626_CustomizeCurrencyPluralInfo() {
9293     IcuTestErrorCode errorCode(*this, "Test11626_CustomizeCurrencyPluralInfo");
9294     // Ticket #11626: No unit test demonstrating how to use CurrencyPluralInfo to
9295     // change formatting spelled out currencies
9296     // Use locale sr because it has interesting plural rules.
9297     Locale locale("sr");
9298     LocalPointer<DecimalFormatSymbols> symbols(new DecimalFormatSymbols(locale, errorCode), errorCode);
9299     CurrencyPluralInfo info(locale, errorCode);
9300     if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9301     info.setCurrencyPluralPattern(u"one", u"0 qwerty", errorCode);
9302     info.setCurrencyPluralPattern(u"few", u"0 dvorak", errorCode);
9303     DecimalFormat df(u"#", symbols.orphan(), UNUM_CURRENCY_PLURAL, errorCode);
9304     df.setCurrencyPluralInfo(info);
9305     df.setCurrency(u"USD");
9306     df.setMaximumFractionDigits(0);
9307 
9308     UnicodeString result;
9309     assertEquals("Plural one", u"1 qwerty", df.format(1, result, errorCode));
9310     assertEquals("Plural few", u"3 dvorak", df.format(3, result.remove(), errorCode));
9311     assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9312 
9313     info.setPluralRules(u"few: n is 1; one: n in 2..4", errorCode);
9314     df.setCurrencyPluralInfo(info);
9315     assertEquals("Plural one", u"1 dvorak", df.format(1, result.remove(), errorCode));
9316     assertEquals("Plural few", u"3 qwerty", df.format(3, result.remove(), errorCode));
9317     assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9318 }
9319 
Test20073_StrictPercentParseErrorIndex()9320 void NumberFormatTest::Test20073_StrictPercentParseErrorIndex() {
9321     IcuTestErrorCode status(*this, "Test20073_StrictPercentParseErrorIndex");
9322     ParsePosition parsePosition(0);
9323     DecimalFormat df(u"0%", {"en-us", status}, status);
9324     if (U_FAILURE(status)) {
9325         dataerrln("Unable to create DecimalFormat instance.");
9326         return;
9327     }
9328     df.setLenient(false);
9329     Formattable result;
9330     df.parse(u"%2%", result, parsePosition);
9331     assertEquals("", 0, parsePosition.getIndex());
9332     assertEquals("", 0, parsePosition.getErrorIndex());
9333 }
9334 
Test13056_GroupingSize()9335 void NumberFormatTest::Test13056_GroupingSize() {
9336     UErrorCode status = U_ZERO_ERROR;
9337     DecimalFormat df(u"#,##0", status);
9338     if (!assertSuccess("", status)) return;
9339     assertEquals("Primary grouping should return 3", 3, df.getGroupingSize());
9340     assertEquals("Secondary grouping should return 0", 0, df.getSecondaryGroupingSize());
9341     df.setSecondaryGroupingSize(3);
9342     assertEquals("Primary grouping should still return 3", 3, df.getGroupingSize());
9343     assertEquals("Secondary grouping should round-trip", 3, df.getSecondaryGroupingSize());
9344     df.setGroupingSize(4);
9345     assertEquals("Primary grouping should return 4", 4, df.getGroupingSize());
9346     assertEquals("Secondary should remember explicit setting and return 3", 3, df.getSecondaryGroupingSize());
9347 }
9348 
9349 
Test11025_CurrencyPadding()9350 void NumberFormatTest::Test11025_CurrencyPadding() {
9351     UErrorCode status = U_ZERO_ERROR;
9352     UnicodeString pattern(u"¤¤ **####0.00");
9353     DecimalFormatSymbols sym(Locale::getFrance(), status);
9354     if (!assertSuccess("", status)) return;
9355     DecimalFormat fmt(pattern, sym, status);
9356     if (!assertSuccess("", status)) return;
9357     UnicodeString result;
9358     fmt.format(433.0, result);
9359     assertEquals("Number should be padded to 11 characters", "EUR *433,00", result);
9360 }
9361 
Test11648_ExpDecFormatMalPattern()9362 void NumberFormatTest::Test11648_ExpDecFormatMalPattern() {
9363     UErrorCode status = U_ZERO_ERROR;
9364 
9365     DecimalFormat fmt("0.00", {"en", status}, status);
9366     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9367     fmt.setScientificNotation(true);
9368     UnicodeString pattern;
9369 
9370     assertEquals("A valid scientific notation pattern should be produced",
9371             "0.00E0",
9372             fmt.toPattern(pattern));
9373 
9374     DecimalFormat fmt2(pattern, status);
9375     assertSuccess("", status);
9376 }
9377 
Test11649_DecFmtCurrencies()9378 void NumberFormatTest::Test11649_DecFmtCurrencies() {
9379     IcuTestErrorCode status(*this, "Test11649_DecFmtCurrencies");
9380     UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
9381     pattern = pattern.unescape();
9382     DecimalFormat fmt(pattern, status);
9383     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9384     static const UChar USD[] = u"USD";
9385     fmt.setCurrency(USD);
9386     UnicodeString appendTo;
9387 
9388     assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
9389     UnicodeString topattern;
9390 
9391     assertEquals("", pattern, fmt.toPattern(topattern));
9392     DecimalFormat fmt2(topattern, status);
9393     fmt2.setCurrency(USD);
9394 
9395     appendTo.remove();
9396     assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
9397 }
9398 
Test13148_ParseGroupingSeparators()9399 void NumberFormatTest::Test13148_ParseGroupingSeparators() {
9400   IcuTestErrorCode status(*this, "Test13148");
9401   LocalPointer<DecimalFormat> fmt(
9402       (DecimalFormat*)NumberFormat::createInstance("en-ZA", status), status);
9403   if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9404 
9405   DecimalFormatSymbols symbols = *fmt->getDecimalFormatSymbols();
9406 
9407   symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'.');
9408   symbols.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u',');
9409   fmt->setDecimalFormatSymbols(symbols);
9410   Formattable number;
9411   fmt->parse(u"300,000", number, status);
9412   assertEquals("Should parse as 300000", 300000LL, number.getInt64(status));
9413 }
9414 
Test12753_PatternDecimalPoint()9415 void NumberFormatTest::Test12753_PatternDecimalPoint() {
9416     UErrorCode status = U_ZERO_ERROR;
9417     DecimalFormatSymbols symbols(Locale::getUS(), status);
9418     symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"*", false);
9419     DecimalFormat df(u"0.00", symbols, status);
9420     if (!assertSuccess("", status)) return;
9421     df.setDecimalPatternMatchRequired(true);
9422     Formattable result;
9423     df.parse(u"123",result, status);
9424     assertEquals("Parsing integer succeeded even though setDecimalPatternMatchRequired was set",
9425                  U_INVALID_FORMAT_ERROR, status);
9426     }
9427 
Test11647_PatternCurrencySymbols()9428  void NumberFormatTest::Test11647_PatternCurrencySymbols() {
9429     UErrorCode status = U_ZERO_ERROR;
9430     DecimalFormat df(status);
9431     df.applyPattern(u"¤¤¤¤#", status);
9432     if (!assertSuccess("", status)) return;
9433     UnicodeString actual;
9434     df.format(123, actual);
9435     assertEquals("Should replace 4 currency signs with U+FFFD", u"\uFFFD123", actual);
9436 }
9437 
Test11913_BigDecimal()9438 void NumberFormatTest::Test11913_BigDecimal() {
9439     UErrorCode status = U_ZERO_ERROR;
9440     LocalPointer<NumberFormat> df(NumberFormat::createInstance(Locale::getEnglish(), status), status);
9441     if (!assertSuccess("", status)) return;
9442     UnicodeString result;
9443     df->format(StringPiece("1.23456789E400"), result, nullptr, status);
9444     assertSuccess("", status);
9445     assertEquals("Should format more than 309 digits", u"12,345,678", UnicodeString(result, 0, 10));
9446     assertEquals("Should format more than 309 digits", 534, result.length());
9447 }
9448 
Test11020_RoundingInScientificNotation()9449 void NumberFormatTest::Test11020_RoundingInScientificNotation() {
9450     UErrorCode status = U_ZERO_ERROR;
9451     DecimalFormatSymbols sym(Locale::getFrance(), status);
9452     DecimalFormat fmt(u"0.05E0", sym, status);
9453     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9454     assertSuccess("", status);
9455     UnicodeString result;
9456     fmt.format(12301.2, result);
9457     assertEquals("Rounding increment should be applied after magnitude scaling", u"1,25E4", result);
9458 }
9459 
Test11640_TripleCurrencySymbol()9460 void NumberFormatTest::Test11640_TripleCurrencySymbol() {
9461     IcuTestErrorCode status(*this, "Test11640_TripleCurrencySymbol");
9462     UnicodeString actual;
9463     DecimalFormat dFormat(u"¤¤¤ 0", status);
9464     if (U_FAILURE(status)) {
9465         dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9466         return;
9467     }
9468     dFormat.setCurrency(u"USD");
9469     UnicodeString result;
9470     dFormat.getPositivePrefix(result);
9471     assertEquals("Triple-currency should give long name on getPositivePrefix",
9472                 "US dollars ", result);
9473 }
9474 
9475 
Test13763_FieldPositionIteratorOffset()9476 void NumberFormatTest::Test13763_FieldPositionIteratorOffset() {
9477     IcuTestErrorCode status(*this, "Test13763_FieldPositionIteratorOffset");
9478     FieldPositionIterator fpi;
9479     UnicodeString result(u"foo\U0001F4FBbar"); // 8 code units
9480     LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9481     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9482     nf->format(5142.3, result, &fpi, status);
9483 
9484     int32_t expected[] = {
9485       UNUM_GROUPING_SEPARATOR_FIELD, 9, 10,
9486       UNUM_INTEGER_FIELD, 8, 13,
9487       UNUM_DECIMAL_SEPARATOR_FIELD, 13, 14,
9488       UNUM_FRACTION_FIELD, 14, 15,
9489     };
9490     int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
9491     expectPositions(fpi, expected, tupleCount, result);
9492 }
9493 
Test13777_ParseLongNameNonCurrencyMode()9494 void NumberFormatTest::Test13777_ParseLongNameNonCurrencyMode() {
9495     IcuTestErrorCode status(*this, "Test13777_ParseLongNameNonCurrencyMode");
9496 
9497     LocalPointer<NumberFormat> df(
9498         NumberFormat::createInstance("en-us", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9499     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9500     expect2(*df, 1.5, u"1.50 US dollars");
9501 }
9502 
Test13804_EmptyStringsWhenParsing()9503 void NumberFormatTest::Test13804_EmptyStringsWhenParsing() {
9504     IcuTestErrorCode status(*this, "Test13804_EmptyStringsWhenParsing");
9505 
9506     DecimalFormatSymbols dfs("en", status);
9507     if (status.errIfFailureAndReset()) {
9508         return;
9509     }
9510     dfs.setSymbol(DecimalFormatSymbols::kCurrencySymbol, u"", false);
9511     dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"", false);
9512     dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u"", false);
9513     dfs.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, u"", false);
9514     dfs.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, u"", false);
9515     dfs.setSymbol(DecimalFormatSymbols::kThreeDigitSymbol, u"", false);
9516     dfs.setSymbol(DecimalFormatSymbols::kFourDigitSymbol, u"", false);
9517     dfs.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, u"", false);
9518     dfs.setSymbol(DecimalFormatSymbols::kSixDigitSymbol, u"", false);
9519     dfs.setSymbol(DecimalFormatSymbols::kSevenDigitSymbol, u"", false);
9520     dfs.setSymbol(DecimalFormatSymbols::kEightDigitSymbol, u"", false);
9521     dfs.setSymbol(DecimalFormatSymbols::kNineDigitSymbol, u"", false);
9522     dfs.setSymbol(DecimalFormatSymbols::kExponentMultiplicationSymbol, u"", false);
9523     dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"", false);
9524     dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u"", false);
9525     dfs.setSymbol(DecimalFormatSymbols::kInfinitySymbol, u"", false);
9526     dfs.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, u"", false);
9527     dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"", false);
9528     dfs.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, u"", false);
9529     dfs.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, u"", false);
9530     dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, u"", false);
9531     dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, false, u"");
9532     dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, true, u"");
9533     dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u"", false);
9534     dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u"", false);
9535     dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"", false);
9536 
9537     DecimalFormat df("0", dfs, status);
9538     if (status.errIfFailureAndReset()) {
9539         return;
9540     }
9541     df.setGroupingUsed(true);
9542     df.setScientificNotation(true);
9543     df.setLenient(true); // enable all matchers
9544     {
9545         UnicodeString result;
9546         df.format(0, result); // should not crash or hit infinite loop
9547     }
9548     const char16_t* samples[] = {
9549             u"",
9550             u"123",
9551             u"$123",
9552             u"-",
9553             u"+",
9554             u"44%",
9555             u"1E+2.3"
9556     };
9557     for (auto& sample : samples) {
9558         logln(UnicodeString(u"Attempting parse on: ") + sample);
9559         status.setScope(sample);
9560         // We don't care about the results, only that we don't crash and don't loop.
9561         Formattable result;
9562         ParsePosition ppos(0);
9563         df.parse(sample, result, ppos);
9564         ppos = ParsePosition(0);
9565         LocalPointer<CurrencyAmount> curramt(df.parseCurrency(sample, ppos));
9566         status.errIfFailureAndReset();
9567     }
9568 
9569     // Test with a nonempty exponent separator symbol to cover more code
9570     dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"E", false);
9571     df.setDecimalFormatSymbols(dfs);
9572     {
9573         Formattable result;
9574         ParsePosition ppos(0);
9575         df.parse(u"1E+2.3", result, ppos);
9576     }
9577 }
9578 
Test20037_ScientificIntegerOverflow()9579 void NumberFormatTest::Test20037_ScientificIntegerOverflow() {
9580     IcuTestErrorCode status(*this, "Test20037_ScientificIntegerOverflow");
9581 
9582     LocalPointer<NumberFormat> nf(NumberFormat::createInstance(status));
9583     if (U_FAILURE(status)) {
9584         dataerrln("Unable to create NumberFormat instance.");
9585         return;
9586     }
9587     Formattable result;
9588 
9589     // Test overflow of exponent
9590     nf->parse(u"1E-2147483648", result, status);
9591     StringPiece sp = result.getDecimalNumber(status);
9592     assertEquals(u"Should snap to zero",
9593                  u"0",
9594                  {sp.data(), sp.length(), US_INV});
9595 
9596     // Test edge case overflow of exponent
9597     result = Formattable();
9598     nf->parse(u"1E-2147483647E-1", result, status);
9599     sp = result.getDecimalNumber(status);
9600     assertEquals(u"Should not overflow and should parse only the first exponent",
9601                  u"1E-2147483647",
9602                  {sp.data(), sp.length(), US_INV});
9603 
9604     // Test edge case overflow of exponent
9605     result = Formattable();
9606     nf->parse(u".0003e-2147483644", result, status);
9607     sp = result.getDecimalNumber(status);
9608     assertEquals(u"Should not overflow",
9609                  u"3E-2147483648",
9610                  {sp.data(), sp.length(), US_INV});
9611 
9612     // Test largest parseable exponent
9613     result = Formattable();
9614     nf->parse(u"9876e2147483643", result, status);
9615     sp = result.getDecimalNumber(status);
9616     assertEquals(u"Should not overflow",
9617                  u"9.876E+2147483646",
9618                  {sp.data(), sp.length(), US_INV});
9619 
9620     // Test max value as well
9621     const char16_t* infinityInputs[] = {
9622             u"9876e2147483644",
9623             u"9876e2147483645",
9624             u"9876e2147483646",
9625             u"9876e2147483647",
9626             u"9876e2147483648",
9627             u"9876e2147483649",
9628     };
9629     for (const auto& input : infinityInputs) {
9630         result = Formattable();
9631         nf->parse(input, result, status);
9632         sp = result.getDecimalNumber(status);
9633         assertEquals(UnicodeString("Should become Infinity: ") + input,
9634                     u"Infinity",
9635                     {sp.data(), sp.length(), US_INV});
9636     }
9637 }
9638 
Test13840_ParseLongStringCrash()9639 void NumberFormatTest::Test13840_ParseLongStringCrash() {
9640     IcuTestErrorCode status(*this, "Test13840_ParseLongStringCrash");
9641 
9642     LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9643     if (status.errIfFailureAndReset()) { return; }
9644 
9645     Formattable result;
9646     static const char16_t* bigString =
9647         u"111111111111111111111111111111111111111111111111111111111111111111111"
9648         u"111111111111111111111111111111111111111111111111111111111111111111111"
9649         u"111111111111111111111111111111111111111111111111111111111111111111111"
9650         u"111111111111111111111111111111111111111111111111111111111111111111111"
9651         u"111111111111111111111111111111111111111111111111111111111111111111111"
9652         u"111111111111111111111111111111111111111111111111111111111111111111111";
9653     nf->parse(bigString, result, status);
9654 
9655     // Normalize the input string:
9656     CharString expectedChars;
9657     expectedChars.appendInvariantChars(bigString, status);
9658     DecimalQuantity expectedDQ;
9659     expectedDQ.setToDecNumber(expectedChars.toStringPiece(), status);
9660     UnicodeString expectedUString = expectedDQ.toScientificString();
9661 
9662     // Get the output string:
9663     StringPiece actualChars = result.getDecimalNumber(status);
9664     UnicodeString actualUString = UnicodeString(actualChars.data(), actualChars.length(), US_INV);
9665 
9666     assertEquals("Should round-trip without crashing", expectedUString, actualUString);
9667 }
9668 
Test13850_EmptyStringCurrency()9669 void NumberFormatTest::Test13850_EmptyStringCurrency() {
9670     IcuTestErrorCode status(*this, "Test13840_EmptyStringCurrency");
9671 
9672     struct TestCase {
9673         const char16_t* currencyArg;
9674         UErrorCode expectedError;
9675     } cases[] = {
9676         {u"", U_USING_FALLBACK_WARNING},
9677         {u"U", U_ILLEGAL_ARGUMENT_ERROR},
9678         {u"Us", U_ILLEGAL_ARGUMENT_ERROR},
9679         {nullptr, U_USING_FALLBACK_WARNING},
9680         {u"U$D", U_INVARIANT_CONVERSION_ERROR},
9681         {u"Xxx", U_USING_FALLBACK_WARNING}
9682     };
9683     for (const auto& cas : cases) {
9684         UnicodeString message(u"with currency arg: ");
9685         if (cas.currencyArg == nullptr) {
9686             message += u"nullptr";
9687         } else {
9688             message += UnicodeString(cas.currencyArg);
9689         }
9690         status.setScope(message);
9691         LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-US", status), status);
9692         if (status.errIfFailureAndReset()) { return; }
9693         UnicodeString actual;
9694         nf->format(1, actual, status);
9695         status.errIfFailureAndReset();
9696         assertEquals(u"Should format with US currency " + message, u"$1.00", actual);
9697         nf->setCurrency(cas.currencyArg, status);
9698         if (status.expectErrorAndReset(cas.expectedError)) {
9699             // If an error occurred, do not check formatting.
9700             continue;
9701         }
9702         nf->format(1, actual.remove(), status);
9703         assertEquals(u"Should unset the currency " + message, u"\u00A41.00", actual);
9704         status.errIfFailureAndReset();
9705     }
9706 }
9707 
Test20348_CurrencyPrefixOverride()9708 void NumberFormatTest::Test20348_CurrencyPrefixOverride() {
9709     IcuTestErrorCode status(*this, "Test20348_CurrencyPrefixOverride");
9710     LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9711         NumberFormat::createCurrencyInstance("en", status)));
9712     if (status.errIfFailureAndReset()) { return; }
9713     UnicodeString result;
9714     assertEquals("Initial pattern",
9715         u"¤#,##0.00", fmt->toPattern(result.remove()));
9716     assertEquals("Initial prefix",
9717         u"¤", fmt->getPositivePrefix(result.remove()));
9718     assertEquals("Initial suffix",
9719         u"-¤", fmt->getNegativePrefix(result.remove()));
9720     assertEquals("Initial format",
9721         u"\u00A4100.00", fmt->format(100, result.remove(), NULL, status));
9722 
9723     fmt->setPositivePrefix(u"$");
9724     assertEquals("Set positive prefix pattern",
9725         u"$#,##0.00;-\u00A4#,##0.00", fmt->toPattern(result.remove()));
9726     assertEquals("Set positive prefix prefix",
9727         u"$", fmt->getPositivePrefix(result.remove()));
9728     assertEquals("Set positive prefix suffix",
9729         u"-¤", fmt->getNegativePrefix(result.remove()));
9730     assertEquals("Set positive prefix format",
9731         u"$100.00", fmt->format(100, result.remove(), NULL, status));
9732 
9733     fmt->setNegativePrefix(u"-$");
9734     assertEquals("Set negative prefix pattern",
9735         u"$#,##0.00;'-'$#,##0.00", fmt->toPattern(result.remove()));
9736     assertEquals("Set negative prefix prefix",
9737         u"$", fmt->getPositivePrefix(result.remove()));
9738     assertEquals("Set negative prefix suffix",
9739         u"-$", fmt->getNegativePrefix(result.remove()));
9740     assertEquals("Set negative prefix format",
9741         u"$100.00", fmt->format(100, result.remove(), NULL, status));
9742 }
9743 
Test20956_MonetarySymbolGetters()9744 void NumberFormatTest::Test20956_MonetarySymbolGetters() {
9745     IcuTestErrorCode status(*this, "Test20956_MonetarySymbolGetters");
9746     LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9747         NumberFormat::createCurrencyInstance("et", status)));
9748     if (status.errDataIfFailureAndReset()) {
9749         return;
9750     }
9751 
9752     decimalFormat->setCurrency(u"EEK");
9753 
9754     const DecimalFormatSymbols* decimalFormatSymbols = decimalFormat->getDecimalFormatSymbols();
9755     assertEquals("MONETARY DECIMAL SEPARATOR",
9756         u".",
9757         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
9758     assertEquals("DECIMAL SEPARATOR",
9759         u",",
9760         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol));
9761     assertEquals("MONETARY GROUPING SEPARATOR",
9762         u" ",
9763         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol));
9764     assertEquals("GROUPING SEPARATOR",
9765         u" ",
9766         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
9767     assertEquals("CURRENCY SYMBOL",
9768         u"kr",
9769         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
9770 
9771     UnicodeString sb;
9772     decimalFormat->format(12345.12, sb, status);
9773     assertEquals("OUTPUT", u"12 345.12 kr", sb);
9774 }
9775 
Test20358_GroupingInPattern()9776 void NumberFormatTest::Test20358_GroupingInPattern() {
9777     IcuTestErrorCode status(*this, "Test20358_GroupingInPattern");
9778     LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9779         NumberFormat::createInstance("en", status)));
9780     if (status.errIfFailureAndReset()) { return; }
9781     UnicodeString result;
9782     assertEquals("Initial pattern",
9783         u"#,##0.###", fmt->toPattern(result.remove()));
9784     assertTrue("Initial grouping",
9785         fmt->isGroupingUsed());
9786     assertEquals("Initial format",
9787         u"54,321", fmt->format(54321, result.remove(), NULL, status));
9788 
9789     fmt->setGroupingUsed(false);
9790     assertEquals("Set grouping false",
9791         u"0.###", fmt->toPattern(result.remove()));
9792     assertFalse("Set grouping false grouping",
9793         fmt->isGroupingUsed());
9794     assertEquals("Set grouping false format",
9795         u"54321", fmt->format(54321, result.remove(), NULL, status));
9796 
9797     fmt->setGroupingUsed(true);
9798     assertEquals("Set grouping true",
9799         u"#,##0.###", fmt->toPattern(result.remove()));
9800     assertTrue("Set grouping true grouping",
9801         fmt->isGroupingUsed());
9802     assertEquals("Set grouping true format",
9803         u"54,321", fmt->format(54321, result.remove(), NULL, status));
9804 }
9805 
Test13731_DefaultCurrency()9806 void NumberFormatTest::Test13731_DefaultCurrency() {
9807     IcuTestErrorCode status(*this, "Test13731_DefaultCurrency");
9808     UnicodeString result;
9809     {
9810         LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9811             "en", UNumberFormatStyle::UNUM_CURRENCY, status), status);
9812         if (status.errIfFailureAndReset()) { return; }
9813         assertEquals("symbol", u"¤1.10",
9814             nf->format(1.1, result.remove(), status));
9815         assertEquals("currency", u"XXX", nf->getCurrency());
9816     }
9817     {
9818         LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9819             "en", UNumberFormatStyle::UNUM_CURRENCY_ISO, status), status);
9820         if (status.errIfFailureAndReset()) { return; }
9821         assertEquals("iso_code", u"XXX 1.10",
9822             nf->format(1.1, result.remove(), status));
9823         assertEquals("currency", u"XXX", nf->getCurrency());
9824     }
9825     {
9826         LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9827             "en", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9828         if (status.errIfFailureAndReset()) { return; }
9829         assertEquals("plural", u"1.10 (unknown currency)",
9830             nf->format(1.1, result.remove(), status));
9831         assertEquals("currency", u"XXX", nf->getCurrency());
9832     }
9833 }
9834 
Test20499_CurrencyVisibleDigitsPlural()9835 void NumberFormatTest::Test20499_CurrencyVisibleDigitsPlural() {
9836     IcuTestErrorCode status(*this, "Test20499_CurrencyVisibleDigitsPlural");
9837     LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9838         "ro-RO", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9839     const char16_t* expected = u"24,00 lei românești";
9840     for (int32_t i=0; i<5; i++) {
9841         UnicodeString actual;
9842         nf->format(24, actual, status);
9843         assertEquals(UnicodeString(u"iteration ") + Int64ToUnicodeString(i),
9844             expected, actual);
9845     }
9846 }
9847 
Test13735_GroupingSizeGetter()9848 void NumberFormatTest::Test13735_GroupingSizeGetter() {
9849     IcuTestErrorCode status(*this, "Test13735_GroupingSizeGetter");
9850     {
9851         DecimalFormat df("0", {"en", status}, status);
9852         assertEquals("pat 0: ", 0, df.getGroupingSize());
9853         df.setGroupingUsed(false);
9854         assertEquals("pat 0 then disabled: ", 0, df.getGroupingSize());
9855         df.setGroupingUsed(true);
9856         assertEquals("pat 0 then enabled: ", 0, df.getGroupingSize());
9857     }
9858     {
9859         DecimalFormat df("#,##0", {"en", status}, status);
9860         assertEquals("pat #,##0: ", 3, df.getGroupingSize());
9861         df.setGroupingUsed(false);
9862         assertEquals("pat #,##0 then disabled: ", 3, df.getGroupingSize());
9863         df.setGroupingUsed(true);
9864         assertEquals("pat #,##0 then enabled: ", 3, df.getGroupingSize());
9865     }
9866 }
9867 
Test13734_StrictFlexibleWhitespace()9868 void NumberFormatTest::Test13734_StrictFlexibleWhitespace() {
9869     IcuTestErrorCode status(*this, "Test13734_StrictFlexibleWhitespace");
9870     {
9871         DecimalFormat df("+0", {"en", status}, status);
9872         df.setLenient(false);
9873         Formattable result;
9874         ParsePosition ppos;
9875         df.parse("+  33", result, ppos);
9876         assertEquals("ppos : ", 0, ppos.getIndex());
9877         assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9878     }
9879     {
9880         DecimalFormat df("+ 0", {"en", status}, status);
9881         df.setLenient(false);
9882         Formattable result;
9883         ParsePosition ppos;
9884         df.parse("+  33", result, ppos);
9885         assertEquals("ppos : ", 0, ppos.getIndex());
9886         assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9887     }
9888 }
9889 
Test20961_CurrencyPluralPattern()9890 void NumberFormatTest::Test20961_CurrencyPluralPattern() {
9891     IcuTestErrorCode status(*this, "Test20961_CurrencyPluralPattern");
9892     {
9893         LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9894             NumberFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9895         if (status.errDataIfFailureAndReset()) {
9896             return;
9897         }
9898         UnicodeString result;
9899         decimalFormat->toPattern(result);
9900         assertEquals("Currency pattern", u"#,##0.00 ¤¤¤", result);
9901     }
9902 }
9903 
Test21134_ToNumberFormatter()9904 void NumberFormatTest::Test21134_ToNumberFormatter() {
9905     IcuTestErrorCode status(*this, "Test21134_ToNumberFormatter");
9906     LocalizedNumberFormatter outer1;
9907     LocalizedNumberFormatter outer2;
9908     LocalPointer<LocalizedNumberFormatter> outer3;
9909     {
9910         // Case 1: new formatter object
9911         DecimalFormat inner(u"a0b", {"en", status}, status);
9912         if (auto ptr = inner.toNumberFormatter(status)) {
9913             // Copy assignment
9914             outer1 = *ptr;
9915         } else {
9916             status.errIfFailureAndReset();
9917             return;
9918         }
9919     }
9920     {
9921         // Case 2: compiled formatter object (used at least 3 times)
9922         DecimalFormat inner(u"c0d", {"en", status}, status);
9923         UnicodeString dummy;
9924         inner.format(100, dummy);
9925         inner.format(100, dummy);
9926         inner.format(100, dummy);
9927         if (auto ptr = inner.toNumberFormatter(status)) {
9928             // Copy assignment
9929             outer2 = *ptr;
9930         } else {
9931             status.errIfFailureAndReset();
9932             return;
9933         }
9934     }
9935     {
9936         // Case 3: currency plural info (different code path)
9937         LocalPointer<DecimalFormat> inner(static_cast<DecimalFormat*>(
9938             DecimalFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9939         if (auto ptr = inner->toNumberFormatter(status)) {
9940             // Copy constructor
9941             outer3.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(*ptr), status);
9942         } else {
9943             status.errIfFailureAndReset();
9944             return;
9945         }
9946     }
9947     auto result1 = outer1.formatDouble(99, status);
9948     assertEquals("Using NumberFormatter from DecimalFormat, new version",
9949         u"a99b",
9950         result1.toTempString(status));
9951     auto result2 = outer2.formatDouble(99, status);
9952     assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9953         u"c99d",
9954         result2.toTempString(status));
9955     auto result3 = outer3->formatDouble(99, status);
9956     assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9957         u"99.00 US dollars",
9958         result3.toTempString(status));
9959 }
9960 
Test13733_StrictAndLenient()9961 void NumberFormatTest::Test13733_StrictAndLenient() {
9962     IcuTestErrorCode status(*this, "Test13733_StrictAndLenient");
9963 
9964     static const struct TestCase {
9965         const char16_t* inputString;
9966         const char16_t* patternString;
9967         int64_t expectedStrictParse;
9968         int64_t expectedLenientParse;
9969     } cases[] = { {u"CA$ 12", u"¤ 0", 12, 12},
9970                   {u"CA$12", u"¤0", 12, 12},
9971                   {u"CAD 12", u"¤¤ 0", 12, 12},
9972                   {u"12 CAD", u"0 ¤¤", 12, 12},
9973                   {u"12 Canadian dollars", u"0 ¤¤¤", 12, 12},
9974                   {u"$12 ", u"¤¤¤¤0", 12, 12},
9975                   {u"12$", u"0¤¤¤¤", 12, 12},
9976                   {u"CA$ 12", u"¤0", 0, 12},
9977                   {u"CA$ 12", u"0 ¤¤", 0, 12},
9978                   {u"CA$ 12", u"0 ¤¤¤", 0, 12},
9979                   {u"CA$ 12", u"¤¤¤¤0", 0, 12},
9980                   {u"CA$ 12", u"0¤¤¤¤", 0, 12},
9981                   {u"CA$12", u"¤ 0", 0, 12},
9982                   {u"CA$12", u"¤¤ 0", 0, 12},
9983                   {u"CA$12", u"0 ¤¤", 0, 12},
9984                   {u"CA$12", u"0 ¤¤¤", 0, 12},
9985                   {u"CA$12", u"0¤¤¤¤", 0, 12},
9986                   {u"CAD 12", u"¤0", 0, 12},
9987                   {u"CAD 12", u"0 ¤¤", 0, 12},
9988                   {u"CAD 12", u"0 ¤¤¤", 0, 12},
9989                   {u"CAD 12", u"¤¤¤¤0", 0, 12},
9990                   {u"CAD 12", u"0¤¤¤¤", 0, 12},
9991                   {u"12 CAD", u"¤ 0", 0, 12},
9992                   {u"12 CAD", u"¤0", 0, 12},
9993                   {u"12 CAD", u"¤¤ 0", 0, 12},
9994                   {u"12 CAD", u"¤¤¤¤0", 0, 12},
9995                   {u"12 CAD", u"0¤¤¤¤", 0, 12},
9996                   {u"12 Canadian dollars", u"¤ 0", 0, 12},
9997                   {u"12 Canadian dollars", u"¤0", 0, 12},
9998                   {u"12 Canadian dollars", u"¤¤ 0", 0, 12},
9999                   {u"12 Canadian dollars", u"¤¤¤¤0", 0, 12},
10000                   {u"12 Canadian dollars", u"0¤¤¤¤", 0, 12},
10001                   {u"$12 ", u"¤ 0", 0, 12},
10002                   {u"$12 ", u"¤¤ 0", 0, 12},
10003                   {u"$12 ", u"0 ¤¤", 0, 12},
10004                   {u"$12 ", u"0 ¤¤¤", 0, 12},
10005                   {u"$12 ", u"0¤¤¤¤", 0, 12},
10006                   {u"12$", u"¤ 0", 0, 12},
10007                   {u"12$", u"¤0", 0, 12},
10008                   {u"12$", u"¤¤ 0", 0, 12},
10009                   {u"12$", u"0 ¤¤", 0, 12},
10010                   {u"12$", u"0 ¤¤¤", 0, 12},
10011                   {u"12$", u"¤¤¤¤0", 0, 12} };
10012     for (auto& cas : cases) {
10013         UnicodeString inputString(cas.inputString);
10014         UnicodeString patternString(cas.patternString);
10015         int64_t parsedStrictValue = 0;
10016         int64_t parsedLenientValue = 0;
10017         ParsePosition ppos;
10018 
10019         DecimalFormatSymbols dfs(Locale::getEnglish(), status);
10020         if (status.errDataIfFailureAndReset()) {
10021             return;
10022         }
10023         DecimalFormat df(patternString, dfs, status);
10024         if (status.errDataIfFailureAndReset()) {
10025             return;
10026         }
10027         df.setLenient(false);
10028         LocalPointer<CurrencyAmount> ca_strict(df.parseCurrency(inputString, ppos));
10029         if (ca_strict != nullptr) {
10030             parsedStrictValue = ca_strict->getNumber().getInt64();
10031         }
10032         assertEquals("Strict parse of " + inputString + " using " + patternString,
10033             parsedStrictValue, cas.expectedStrictParse);
10034 
10035         ppos.setIndex(0);
10036         df.setLenient(true);
10037         LocalPointer<CurrencyAmount> ca_lenient(df.parseCurrency(inputString, ppos));
10038         Formattable parsedNumber_lenient = ca_lenient->getNumber();
10039         if (ca_lenient != nullptr) {
10040             parsedLenientValue = ca_lenient->getNumber().getInt64();
10041         }
10042         assertEquals("Lenient parse of " + inputString + " using " + patternString,
10043             parsedLenientValue, cas.expectedLenientParse);
10044     }
10045 }
10046 
Test20425_IntegerIncrement()10047 void NumberFormatTest::Test20425_IntegerIncrement() {
10048     IcuTestErrorCode status(*this, "Test20425_IntegerIncrement");
10049 
10050     DecimalFormat df("##00", status);
10051     df.setRoundingIncrement(1);
10052     UnicodeString actual;
10053     df.format(1235.5, actual, status);
10054     assertEquals("Should round to integer", u"1236", actual);
10055 }
10056 
Test20425_FractionWithIntegerIncrement()10057 void NumberFormatTest::Test20425_FractionWithIntegerIncrement() {
10058     IcuTestErrorCode status(*this, "Test20425_FractionWithIntegerIncrement");
10059 
10060     DecimalFormat df("0.0", status);
10061     df.setRoundingIncrement(1);
10062     UnicodeString actual;
10063     df.format(8.6, actual, status);
10064     assertEquals("Should have a fraction digit", u"9.0", actual);
10065 }
10066 
Test21232_ParseTimeout()10067 void NumberFormatTest::Test21232_ParseTimeout() {
10068     IcuTestErrorCode status(*this, "Test21232_ParseTimeout");
10069 
10070     DecimalFormat df(status);
10071     if (status.errDataIfFailureAndReset()) {
10072         return;
10073     }
10074 
10075     UnicodeString input = u"4444444444444444444444444444444444444444";
10076     if (quick) {
10077         for (int32_t i = 0; i < 5; i++) {
10078             input.append(input);
10079         }
10080         assertEquals("Somewhat long input of digits", 1280, input.length());
10081     } else {
10082         for (int32_t i = 0; i < 12; i++) {
10083             input.append(input);
10084         }
10085         assertEquals("Very long input of digits", 163840, input.length());
10086     }
10087     Formattable result;
10088     df.parse(input, result, status);
10089     // Should not hang
10090 }
10091 
Test10997_FormatCurrency()10092 void NumberFormatTest::Test10997_FormatCurrency() {
10093     IcuTestErrorCode status(*this, "Test10997_FormatCurrency");
10094 
10095     LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance(Locale::getUS(), status));
10096     if (status.errDataIfFailureAndReset()) {
10097         return;
10098     }
10099     fmt->setMinimumFractionDigits(4);
10100     fmt->setMaximumFractionDigits(4);
10101 
10102     FieldPosition fp;
10103 
10104     UnicodeString str;
10105     Formattable usdAmnt(new CurrencyAmount(123.45, u"USD", status));
10106     fmt->format(usdAmnt, str, fp, status);
10107     assertEquals("minFrac 4 should be respected in default currency", u"$123.4500", str);
10108 
10109     UnicodeString str2;
10110     Formattable eurAmnt(new CurrencyAmount(123.45, u"EUR", status));
10111     fmt->format(eurAmnt, str2, fp, status);
10112     assertEquals("minFrac 4 should be respected in different currency", u"€123.4500", str2);
10113 }
10114 
Test21556_CurrencyAsDecimal()10115 void NumberFormatTest::Test21556_CurrencyAsDecimal() {
10116     IcuTestErrorCode status(*this, "Test21556_CurrencyAsDecimal");
10117 
10118     {
10119         DecimalFormat df(u"a0¤00b", status);
10120         if (status.errDataIfFailureAndReset()) {
10121             return;
10122         }
10123         df.setCurrency(u"EUR", status);
10124         UnicodeString result;
10125         FieldPosition fp(UNUM_CURRENCY_FIELD);
10126         df.format(3.141, result, fp);
10127         assertEquals("Basic test: format", u"a3€14b", result);
10128         UnicodeString pattern;
10129         assertEquals("Basic test: toPattern", u"a0¤00b", df.toPattern(pattern));
10130         assertEquals("Basic test: field position begin", 2, fp.getBeginIndex());
10131         assertEquals("Basic test: field position end", 3, fp.getEndIndex());
10132     }
10133 
10134     {
10135         LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-GB", status));
10136         DecimalFormat* df = static_cast<DecimalFormat*>(nf.getAlias());
10137         df->applyPattern(u"a0¤00b", status);
10138         UnicodeString result;
10139         FieldPosition fp(UNUM_CURRENCY_FIELD);
10140         df->format(3.141, result, fp);
10141         assertEquals("Via applyPattern: format", u"a3£14b", result);
10142         UnicodeString pattern;
10143         assertEquals("Via applyPattern: toPattern", u"a0¤00b", df->toPattern(pattern));
10144         assertEquals("Via applyPattern: field position begin", 2, fp.getBeginIndex());
10145         assertEquals("Via applyPattern: field position end", 3, fp.getEndIndex());
10146     }
10147 }
10148 
Test22088_Ethiopic()10149 void NumberFormatTest::Test22088_Ethiopic() {
10150     IcuTestErrorCode err(*this, "Test22088_Ethiopic");
10151     LocalPointer<NumberFormat> nf1(NumberFormat::createInstance(Locale("am_ET@numbers=ethi"), UNUM_DEFAULT, err));
10152     LocalPointer<NumberFormat> nf2(NumberFormat::createInstance(Locale("am_ET@numbers=ethi"), UNUM_NUMBERING_SYSTEM, err));
10153     LocalPointer<NumberFormat> nf3(NumberFormat::createInstance(Locale::getUS(), UNUM_NUMBERING_SYSTEM, err));
10154 
10155     if (!err.errIfFailureAndReset("Creation of number formatters failed")) {
10156         UnicodeString result;
10157         assertEquals("Wrong result with UNUM_DEFAULT", u"፻፳፫", nf1->format(123, result));
10158         result.remove();
10159         assertEquals("Wrong result with UNUM_NUMBERING_SYSTEM", u"፻፳፫", nf2->format(123, result));
10160         result.remove();
10161         assertEquals("Wrong result with UNUM_NUMBERING_SYSTEM and English", u"123", nf3->format(123, result));
10162     }
10163 }
10164 
10165 #endif /* #if !UCONFIG_NO_FORMATTING */
10166