• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4  * 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(Test21232_ParseTimeout);
251   TESTCASE_AUTO_END;
252 }
253 
254 // -------------------------------------
255 
256 // Test API (increase code coverage)
257 void
TestAPI(void)258 NumberFormatTest::TestAPI(void)
259 {
260   logln("Test API");
261   UErrorCode status = U_ZERO_ERROR;
262   NumberFormat *test = NumberFormat::createInstance("root", status);
263   if(U_FAILURE(status)) {
264     dataerrln("unable to create format object - %s", u_errorName(status));
265   }
266   if(test != NULL) {
267     test->setMinimumIntegerDigits(10);
268     test->setMaximumIntegerDigits(1);
269 
270     test->setMinimumFractionDigits(10);
271     test->setMaximumFractionDigits(1);
272 
273     UnicodeString result;
274     FieldPosition pos;
275     Formattable bla("Paja Patak"); // Donald Duck for non Serbian speakers
276     test->format(bla, result, pos, status);
277     if(U_SUCCESS(status)) {
278       errln("Yuck... Formatted a duck... As a number!");
279     } else {
280       status = U_ZERO_ERROR;
281     }
282 
283     result.remove();
284     int64_t ll = 12;
285     test->format(ll, result);
286     assertEquals("format int64_t error", u"2.0", result);
287 
288     test->setMinimumIntegerDigits(4);
289     test->setMinimumFractionDigits(4);
290 
291     result.remove();
292     test->format(ll, result);
293     assertEquals("format int64_t error", u"0,012.0000", result);
294 
295     ParsePosition ppos;
296     LocalPointer<CurrencyAmount> currAmt(test->parseCurrency("",ppos));
297     // old test for (U_FAILURE(status)) was bogus here, method does not set status!
298     if (ppos.getIndex()) {
299         errln("Parsed empty string as currency");
300     }
301 
302     delete test;
303   }
304 }
305 
306 class StubNumberFormat :public NumberFormat{
307 public:
StubNumberFormat()308     StubNumberFormat(){}
format(double,UnicodeString & appendTo,FieldPosition &) const309     virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const {
310         return appendTo;
311     }
format(int32_t,UnicodeString & appendTo,FieldPosition &) const312     virtual UnicodeString& format(int32_t ,UnicodeString& appendTo,FieldPosition& ) const {
313         return appendTo.append((UChar)0x0033);
314     }
format(int64_t number,UnicodeString & appendTo,FieldPosition & pos) const315     virtual UnicodeString& format(int64_t number,UnicodeString& appendTo,FieldPosition& pos) const {
316         return NumberFormat::format(number, appendTo, pos);
317     }
format(const Formattable &,UnicodeString & appendTo,FieldPosition &,UErrorCode &) const318     virtual UnicodeString& format(const Formattable& , UnicodeString& appendTo, FieldPosition& , UErrorCode& ) const {
319         return appendTo;
320     }
parse(const UnicodeString &,Formattable &,ParsePosition &) const321     virtual void parse(const UnicodeString& ,
322                     Formattable& ,
323                     ParsePosition& ) const {}
parse(const UnicodeString &,Formattable &,UErrorCode &) const324     virtual void parse( const UnicodeString& ,
325                         Formattable& ,
326                         UErrorCode& ) const {}
getDynamicClassID(void) const327     virtual UClassID getDynamicClassID(void) const {
328         static char classID = 0;
329         return (UClassID)&classID;
330     }
clone() const331     virtual StubNumberFormat* clone() const {return NULL;}
332 };
333 
334 void
TestCoverage(void)335 NumberFormatTest::TestCoverage(void){
336     StubNumberFormat stub;
337     UnicodeString agent("agent");
338     FieldPosition pos;
339     int64_t num = 4;
340     if (stub.format(num, agent, pos) != UnicodeString("agent3")){
341         errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)");
342     }
343 }
344 
TestLocalizedPatternSymbolCoverage()345 void NumberFormatTest::TestLocalizedPatternSymbolCoverage() {
346     IcuTestErrorCode errorCode(*this, "TestLocalizedPatternSymbolCoverage");
347     // Ticket #12961: DecimalFormat::toLocalizedPattern() is not working as designed.
348     DecimalFormatSymbols dfs(errorCode);
349     dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u'⁖');
350     dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'⁘');
351     dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u'⁙');
352     dfs.setSymbol(DecimalFormatSymbols::kDigitSymbol, u'▰');
353     dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u'໐');
354     dfs.setSymbol(DecimalFormatSymbols::kSignificantDigitSymbol, u'⁕');
355     dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u'†');
356     dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u'‡');
357     dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u'⁜');
358     dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u'‱');
359     dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"⁑⁑"); // tests multi-char sequence
360     dfs.setSymbol(DecimalFormatSymbols::kPadEscapeSymbol, u'⁂');
361 
362     {
363         UnicodeString standardPattern(u"#,##0.05+%;#,##0.05-%");
364         UnicodeString localizedPattern(u"▰⁖▰▰໐⁘໐໕†⁜⁙▰⁖▰▰໐⁘໐໕‡⁜");
365 
366         DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
367         df1.applyPattern(standardPattern, errorCode);
368         DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
369         df2.applyLocalizedPattern(localizedPattern, errorCode);
370         assertTrue("DecimalFormat instances should be equal", df1 == df2);
371         UnicodeString p2;
372         assertEquals("toPattern should match on localizedPattern instance",
373                 standardPattern, df2.toPattern(p2));
374         UnicodeString lp1;
375         assertEquals("toLocalizedPattern should match on standardPattern instance",
376                 localizedPattern, df1.toLocalizedPattern(lp1));
377     }
378 
379     {
380         UnicodeString standardPattern(u"* @@@E0‰");
381         UnicodeString localizedPattern(u"⁂ ⁕⁕⁕⁑⁑໐‱");
382 
383         DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
384         df1.applyPattern(standardPattern, errorCode);
385         DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
386         df2.applyLocalizedPattern(localizedPattern, errorCode);
387         assertTrue("DecimalFormat instances should be equal", df1 == df2);
388         UnicodeString p2;
389         assertEquals("toPattern should match on localizedPattern instance",
390                 standardPattern, df2.toPattern(p2));
391         UnicodeString lp1;
392         assertEquals("toLocalizedPattern should match on standardPattern instance",
393                 localizedPattern, df1.toLocalizedPattern(lp1));
394     }
395 }
396 
397 // Test various patterns
398 void
TestPatterns(void)399 NumberFormatTest::TestPatterns(void)
400 {
401     UErrorCode status = U_ZERO_ERROR;
402     DecimalFormatSymbols sym(Locale::getUS(), status);
403     if (U_FAILURE(status)) { errcheckln(status, "FAIL: Could not construct DecimalFormatSymbols - %s", u_errorName(status)); return; }
404 
405     const char* pat[]    = { "#.#", "#.", ".#", "#" };
406     int32_t pat_length = UPRV_LENGTHOF(pat);
407     const char* newpat[] = { "0.#", "0.", "#.0", "0" };
408     const char* num[]    = { "0",   "0.", ".0", "0" };
409     for (int32_t i=0; i<pat_length; ++i)
410     {
411         status = U_ZERO_ERROR;
412         DecimalFormat fmt(pat[i], sym, status);
413         if (U_FAILURE(status)) { errln((UnicodeString)"FAIL: DecimalFormat constructor failed for " + pat[i]); continue; }
414         UnicodeString newp; fmt.toPattern(newp);
415         if (!(newp == newpat[i]))
416             errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
417                   "; " + newp + " seen instead");
418 
419         UnicodeString s; (*(NumberFormat*)&fmt).format((int32_t)0, s);
420         if (!(s == num[i]))
421         {
422             errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
423                   "; " + s + " seen instead");
424             logln((UnicodeString)"Min integer digits = " + fmt.getMinimumIntegerDigits());
425         }
426     }
427 }
428 
Test20186_SpacesAroundSemicolon()429 void NumberFormatTest::Test20186_SpacesAroundSemicolon() {
430     IcuTestErrorCode status(*this, "Test20186_SpacesAroundSemicolon");
431     DecimalFormat df(u"0.00 ; -0.00", {"en-us", status}, status);
432     expect2(df, 1, u"1.00 ");
433     expect2(df, -1, u" -1.00");
434 
435     df = DecimalFormat(u"0.00;", {"en-us", status}, status);
436     expect2(df, 1, u"1.00");
437     expect2(df, -1, u"-1.00");
438 
439     df = DecimalFormat(u"0.00;0.00", {"en-us", status}, status);
440     expect2(df, 1, u"1.00");
441     expect(df, -1, u"1.00");  // parses as 1, not -1
442 
443     df = DecimalFormat(u" 0.00 ; -0.00 ", {"en-us", status}, status);
444     expect2(df, 1, u" 1.00 ");
445     expect2(df, -1, u" -1.00 ");
446 }
447 
448 /*
449 icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
450 icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
451 icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
452 */
453 /*
454 void
455 NumberFormatTest::TestDigitList(void)
456 {
457   // API coverage for DigitList
458   DigitList list1;
459   list1.append('1');
460   list1.fDecimalAt = 1;
461   DigitList list2;
462   list2.set((int32_t)1);
463   if (list1 != list2) {
464     errln("digitlist append, operator!= or set failed ");
465   }
466   if (!(list1 == list2)) {
467     errln("digitlist append, operator== or set failed ");
468   }
469 }
470 */
471 
472 // -------------------------------------
473 
474 // Test exponential pattern
475 void
TestExponential(void)476 NumberFormatTest::TestExponential(void)
477 {
478     UErrorCode status = U_ZERO_ERROR;
479     DecimalFormatSymbols sym(Locale::getUS(), status);
480     if (U_FAILURE(status)) { errcheckln(status, "FAIL: Bad status returned by DecimalFormatSymbols ct - %s", u_errorName(status)); return; }
481     const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]"  };
482     int32_t pat_length = UPRV_LENGTHOF(pat);
483 
484 // The following #if statements allow this test to be built and run on
485 // platforms that do not have standard IEEE numerics.  For example,
486 // S/390 doubles have an exponent range of -78 to +75.  For the
487 // following #if statements to work, float.h must define
488 // DBL_MAX_10_EXP to be a compile-time constant.
489 
490 // This section may be expanded as needed.
491 
492 #if DBL_MAX_10_EXP > 300
493     double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
494     int32_t val_length = UPRV_LENGTHOF(val);
495     const char* valFormat[] =
496     {
497         // 0.####E0
498         "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
499         // 00.000E00
500         "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
501         // ##0.######E000
502         "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
503         // 0.###E0;[0.###E0]
504         "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
505     };
506     double valParse[] =
507     {
508         0.01234, 123460000, 1.23E300, -3.1416E-271,
509         0.01234, 123460000, 1.23E300, -3.1416E-271,
510         0.01234, 123456800, 1.23E300, -3.141593E-271,
511         0.01234, 123500000, 1.23E300, -3.142E-271,
512     };
513 #elif DBL_MAX_10_EXP > 70
514     double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
515     int32_t val_length = UPRV_LENGTHOF(val);
516     char* valFormat[] =
517     {
518         // 0.####E0
519         "1.234E-2", "1.2346E8", "1.23E70", "-3.1416E-71",
520         // 00.000E00
521         "12.340E-03", "12.346E07", "12.300E69", "-31.416E-72",
522         // ##0.######E000
523         "12.34E-003", "123.4568E006", "12.3E069", "-31.41593E-072",
524         // 0.###E0;[0.###E0]
525         "1.234E-2", "1.235E8", "1.23E70", "[3.142E-71]"
526     };
527     double valParse[] =
528     {
529         0.01234, 123460000, 1.23E70, -3.1416E-71,
530         0.01234, 123460000, 1.23E70, -3.1416E-71,
531         0.01234, 123456800, 1.23E70, -3.141593E-71,
532         0.01234, 123500000, 1.23E70, -3.142E-71,
533     };
534 #else
535     // Don't test double conversion
536     double* val = 0;
537     int32_t val_length = 0;
538     char** valFormat = 0;
539     double* valParse = 0;
540     logln("Warning: Skipping double conversion tests");
541 #endif
542 
543     int32_t lval[] = { 0, -1, 1, 123456789 };
544     int32_t lval_length = UPRV_LENGTHOF(lval);
545     const char* lvalFormat[] =
546     {
547         // 0.####E0
548         "0E0", "-1E0", "1E0", "1.2346E8",
549         // 00.000E00
550         "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
551         // ##0.######E000
552         "0E000", "-1E000", "1E000", "123.4568E006",
553         // 0.###E0;[0.###E0]
554         "0E0", "[1E0]", "1E0", "1.235E8"
555     };
556     int32_t lvalParse[] =
557     {
558         0, -1, 1, 123460000,
559         0, -1, 1, 123460000,
560         0, -1, 1, 123456800,
561         0, -1, 1, 123500000,
562     };
563     int32_t ival = 0, ilval = 0;
564     for (int32_t p=0; p<pat_length; ++p)
565     {
566         DecimalFormat fmt(pat[p], sym, status);
567         if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormat ct"); continue; }
568         UnicodeString pattern;
569         logln((UnicodeString)"Pattern \"" + pat[p] + "\" -toPattern-> \"" +
570           fmt.toPattern(pattern) + "\"");
571         int32_t v;
572         for (v=0; v<val_length; ++v)
573         {
574             UnicodeString s; (*(NumberFormat*)&fmt).format(val[v], s);
575             logln((UnicodeString)" " + val[v] + " -format-> " + s);
576             if (s != valFormat[v+ival])
577                 errln((UnicodeString)"FAIL: Expected " + valFormat[v+ival]);
578 
579             ParsePosition pos(0);
580             Formattable af;
581             fmt.parse(s, af, pos);
582             double a;
583             UBool useEpsilon = FALSE;
584             if (af.getType() == Formattable::kLong)
585                 a = af.getLong();
586             else if (af.getType() == Formattable::kDouble) {
587                 a = af.getDouble();
588 #if U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400
589                 // S/390 will show a failure like this:
590                 //| -3.141592652999999e-271 -format-> -3.1416E-271
591                 //|                          -parse-> -3.1416e-271
592                 //| FAIL: Expected -3.141599999999999e-271
593                 // To compensate, we use an epsilon-based equality
594                 // test on S/390 only.  We don't want to do this in
595                 // general because it's less exacting.
596                 useEpsilon = TRUE;
597 #endif
598             }
599             else {
600                 errln(UnicodeString("FAIL: Non-numeric Formattable returned: ") + pattern + " " + s);
601                 continue;
602             }
603             if (pos.getIndex() == s.length())
604             {
605                 logln((UnicodeString)"  -parse-> " + a);
606                 // Use epsilon comparison as necessary
607                 if ((useEpsilon &&
608                     (uprv_fabs(a - valParse[v+ival]) / a > (2*DBL_EPSILON))) ||
609                     (!useEpsilon && a != valParse[v+ival]))
610                 {
611                     errln((UnicodeString)"FAIL: Expected " + valParse[v+ival] + " but got " + a
612                         + " on input " + s);
613                 }
614             }
615             else {
616                 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
617                 errln((UnicodeString)"  should be (" + s.length() + " chars) -> " + valParse[v+ival]);
618             }
619         }
620         for (v=0; v<lval_length; ++v)
621         {
622             UnicodeString s;
623             (*(NumberFormat*)&fmt).format(lval[v], s);
624             logln((UnicodeString)" " + lval[v] + "L -format-> " + s);
625             if (s != lvalFormat[v+ilval])
626                 errln((UnicodeString)"ERROR: Expected " + lvalFormat[v+ilval] + " Got: " + s);
627 
628             ParsePosition pos(0);
629             Formattable af;
630             fmt.parse(s, af, pos);
631             if (af.getType() == Formattable::kLong ||
632                 af.getType() == Formattable::kInt64) {
633                 UErrorCode status = U_ZERO_ERROR;
634                 int32_t a = af.getLong(status);
635                 if (pos.getIndex() == s.length())
636                 {
637                     logln((UnicodeString)"  -parse-> " + a);
638                     if (a != lvalParse[v+ilval])
639                         errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval] + " but got " + a);
640                 }
641                 else
642                     errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
643             }
644             else
645                 errln((UnicodeString)"FAIL: Non-long Formattable returned for " + s
646                     + " Double: " + af.getDouble()
647                     + ", Long: " + af.getLong());
648         }
649         ival += val_length;
650         ilval += lval_length;
651     }
652 }
653 
654 void
TestScientific2()655 NumberFormatTest::TestScientific2() {
656     // jb 2552
657     UErrorCode status = U_ZERO_ERROR;
658     DecimalFormat* fmt = (DecimalFormat*)NumberFormat::createCurrencyInstance("en_US", status);
659     if (U_SUCCESS(status)) {
660         double num = 12.34;
661         expect(*fmt, num, "$12.34");
662         fmt->setScientificNotation(TRUE);
663         expect(*fmt, num, "$1.23E1");
664         fmt->setScientificNotation(FALSE);
665         expect(*fmt, num, "$12.34");
666     }
667     delete fmt;
668 }
669 
670 void
TestScientificGrouping()671 NumberFormatTest::TestScientificGrouping() {
672     // jb 2552
673     UErrorCode status = U_ZERO_ERROR;
674     DecimalFormat fmt("##0.00E0",status);
675     if (assertSuccess("", status, true, __FILE__, __LINE__)) {
676         expect(fmt, .01234, "12.3E-3");
677         expect(fmt, .1234, "123E-3");
678         expect(fmt, 1.234, "1.23E0");
679         expect(fmt, 12.34, "12.3E0");
680         expect(fmt, 123.4, "123E0");
681         expect(fmt, 1234., "1.23E3");
682     }
683 }
684 
685 /*static void setFromString(DigitList& dl, const char* str) {
686     char c;
687     UBool decimalSet = FALSE;
688     dl.clear();
689     while ((c = *str++)) {
690         if (c == '-') {
691             dl.fIsPositive = FALSE;
692         } else if (c == '+') {
693             dl.fIsPositive = TRUE;
694         } else if (c == '.') {
695             dl.fDecimalAt = dl.fCount;
696             decimalSet = TRUE;
697         } else {
698             dl.append(c);
699         }
700     }
701     if (!decimalSet) {
702         dl.fDecimalAt = dl.fCount;
703     }
704 }*/
705 
706 void
TestInt64()707 NumberFormatTest::TestInt64() {
708     UErrorCode status = U_ZERO_ERROR;
709     DecimalFormat fmt("#.#E0",status);
710     if (U_FAILURE(status)) {
711         dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
712         return;
713     }
714     fmt.setMaximumFractionDigits(20);
715     if (U_SUCCESS(status)) {
716         expect(fmt, (Formattable)(int64_t)0, "0E0");
717         expect(fmt, (Formattable)(int64_t)-1, "-1E0");
718         expect(fmt, (Formattable)(int64_t)1, "1E0");
719         expect(fmt, (Formattable)(int64_t)2147483647, "2.147483647E9");
720         expect(fmt, (Formattable)((int64_t)-2147483647-1), "-2.147483648E9");
721         expect(fmt, (Formattable)(int64_t)U_INT64_MAX, "9.223372036854775807E18");
722         expect(fmt, (Formattable)(int64_t)U_INT64_MIN, "-9.223372036854775808E18");
723     }
724 
725     // also test digitlist
726 /*    int64_t int64max = U_INT64_MAX;
727     int64_t int64min = U_INT64_MIN;
728     const char* int64maxstr = "9223372036854775807";
729     const char* int64minstr = "-9223372036854775808";
730     UnicodeString fail("fail: ");
731 
732     // test max int64 value
733     DigitList dl;
734     setFromString(dl, int64maxstr);
735     {
736         if (!dl.fitsIntoInt64(FALSE)) {
737             errln(fail + int64maxstr + " didn't fit");
738         }
739         int64_t int64Value = dl.getInt64();
740         if (int64Value != int64max) {
741             errln(fail + int64maxstr);
742         }
743         dl.set(int64Value);
744         int64Value = dl.getInt64();
745         if (int64Value != int64max) {
746             errln(fail + int64maxstr);
747         }
748     }
749     // test negative of max int64 value (1 shy of min int64 value)
750     dl.fIsPositive = FALSE;
751     {
752         if (!dl.fitsIntoInt64(FALSE)) {
753             errln(fail + "-" + int64maxstr + " didn't fit");
754         }
755         int64_t int64Value = dl.getInt64();
756         if (int64Value != -int64max) {
757             errln(fail + "-" + int64maxstr);
758         }
759         dl.set(int64Value);
760         int64Value = dl.getInt64();
761         if (int64Value != -int64max) {
762             errln(fail + "-" + int64maxstr);
763         }
764     }
765     // test min int64 value
766     setFromString(dl, int64minstr);
767     {
768         if (!dl.fitsIntoInt64(FALSE)) {
769             errln(fail + "-" + int64minstr + " didn't fit");
770         }
771         int64_t int64Value = dl.getInt64();
772         if (int64Value != int64min) {
773             errln(fail + int64minstr);
774         }
775         dl.set(int64Value);
776         int64Value = dl.getInt64();
777         if (int64Value != int64min) {
778             errln(fail + int64minstr);
779         }
780     }
781     // test negative of min int 64 value (1 more than max int64 value)
782     dl.fIsPositive = TRUE; // won't fit
783     {
784         if (dl.fitsIntoInt64(FALSE)) {
785             errln(fail + "-(" + int64minstr + ") didn't fit");
786         }
787     }*/
788 }
789 
790 // -------------------------------------
791 
792 // Test the handling of quotes
793 void
TestQuotes(void)794 NumberFormatTest::TestQuotes(void)
795 {
796     UErrorCode status = U_ZERO_ERROR;
797     UnicodeString *pat;
798     DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), status);
799     if (U_FAILURE(status)) {
800         errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
801         delete sym;
802         return;
803     }
804     pat = new UnicodeString("a'fo''o'b#");
805     DecimalFormat *fmt = new DecimalFormat(*pat, *sym, status);
806     UnicodeString s;
807     ((NumberFormat*)fmt)->format((int32_t)123, s);
808     logln((UnicodeString)"Pattern \"" + *pat + "\"");
809     logln((UnicodeString)" Format 123 -> " + escape(s));
810     if (!(s=="afo'ob123"))
811         errln((UnicodeString)"FAIL: Expected afo'ob123");
812 
813     s.truncate(0);
814     delete fmt;
815     delete pat;
816 
817     pat = new UnicodeString("a''b#");
818     fmt = new DecimalFormat(*pat, *sym, status);
819     ((NumberFormat*)fmt)->format((int32_t)123, s);
820     logln((UnicodeString)"Pattern \"" + *pat + "\"");
821     logln((UnicodeString)" Format 123 -> " + escape(s));
822     if (!(s=="a'b123"))
823         errln((UnicodeString)"FAIL: Expected a'b123");
824     delete fmt;
825     delete pat;
826     delete sym;
827 }
828 
829 /**
830  * Test the handling of the currency symbol in patterns.
831  */
832 void
TestCurrencySign(void)833 NumberFormatTest::TestCurrencySign(void)
834 {
835     UErrorCode status = U_ZERO_ERROR;
836     DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale::getUS(), status);
837     UnicodeString pat;
838     UChar currency = 0x00A4;
839     if (U_FAILURE(status)) {
840         errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
841         delete sym;
842         return;
843     }
844     // "\xA4#,##0.00;-\xA4#,##0.00"
845     pat.append(currency).append("#,##0.00;-").
846         append(currency).append("#,##0.00");
847     DecimalFormat *fmt = new DecimalFormat(pat, *sym, status);
848     UnicodeString s; ((NumberFormat*)fmt)->format(1234.56, s);
849     pat.truncate(0);
850     logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
851     logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
852     if (s != "$1,234.56") dataerrln((UnicodeString)"FAIL: Expected $1,234.56");
853     s.truncate(0);
854     ((NumberFormat*)fmt)->format(- 1234.56, s);
855     logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
856     if (s != "-$1,234.56") dataerrln((UnicodeString)"FAIL: Expected -$1,234.56");
857     delete fmt;
858     pat.truncate(0);
859     // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
860     pat.append(currency).append(currency).
861         append(" #,##0.00;").
862         append(currency).append(currency).
863         append(" -#,##0.00");
864     fmt = new DecimalFormat(pat, *sym, status);
865     s.truncate(0);
866     ((NumberFormat*)fmt)->format(1234.56, s);
867     logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
868     logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
869     if (s != "USD 1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD 1,234.56");
870     s.truncate(0);
871     ((NumberFormat*)fmt)->format(-1234.56, s);
872     logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
873     if (s != "USD -1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD -1,234.56");
874     delete fmt;
875     delete sym;
876     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + u_errorName(status));
877 }
878 
879 // -------------------------------------
880 
toHexString(int32_t i)881 static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
882 
883 UnicodeString&
escape(UnicodeString & s)884 NumberFormatTest::escape(UnicodeString& s)
885 {
886     UnicodeString buf;
887     for (int32_t i=0; i<s.length(); ++i)
888     {
889         UChar c = s[(int32_t)i];
890         if (c <= (UChar)0x7F) buf += c;
891         else {
892             buf += (UChar)0x5c; buf += (UChar)0x55;
893             buf += toHexString((c & 0xF000) >> 12);
894             buf += toHexString((c & 0x0F00) >> 8);
895             buf += toHexString((c & 0x00F0) >> 4);
896             buf += toHexString(c & 0x000F);
897         }
898     }
899     return (s = buf);
900 }
901 
902 
903 // -------------------------------------
904 static const char* testCases[][2]= {
905      /* locale ID */  /* expected */
906     {"ca_ES@currency=ESP", "\\u20A7\\u00A01.150" },
907     {"de_LU@currency=LUF", "1,150\\u00A0F" },
908     {"el_GR@currency=GRD", "1.150,50\\u00A0\\u0394\\u03C1\\u03C7" },
909     {"en_BE@currency=BEF", "1.150,50\\u00A0BEF" },
910     {"es_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
911     {"eu_ES@currency=ESP", "\\u20A7\\u00A01.150" },
912     {"gl_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
913     {"it_IT@currency=ITL", "ITL\\u00A01.150" },
914     {"pt_PT@currency=PTE", "1,150$50\\u00A0\\u200B"}, // per cldrbug 7670
915     {"en_US@currency=JPY", "\\u00A51,150"},
916     {"en_US@currency=jpy", "\\u00A51,150"},
917     {"en-US-u-cu-jpy", "\\u00A51,150"}
918 };
919 /**
920  * Test localized currency patterns.
921  */
922 void
TestCurrency(void)923 NumberFormatTest::TestCurrency(void)
924 {
925     UErrorCode status = U_ZERO_ERROR;
926     NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
927     if (U_FAILURE(status)) {
928         dataerrln("Error calling NumberFormat::createCurrencyInstance()");
929         return;
930     }
931 
932     UnicodeString s; currencyFmt->format(1.50, s);
933     logln((UnicodeString)"Un pauvre ici a..........." + s);
934     if (!(s==CharsToUnicodeString("1,50\\u00A0$\\u00A0CA")))
935         errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$<nbsp>CA but got " + s);
936     delete currencyFmt;
937     s.truncate(0);
938     char loc[256]={0};
939     int len = uloc_canonicalize("de_DE@currency=DEM", loc, 256, &status);
940     (void)len;  // Suppress unused variable warning.
941     currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
942     currencyFmt->format(1.50, s);
943     logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
944     if (!(s==CharsToUnicodeString("1,50\\u00A0DM")))
945         errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM but got " + s);
946     delete currencyFmt;
947     s.truncate(0);
948     len = uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status);
949     currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
950     currencyFmt->format(1.50, s);
951     logln((UnicodeString)"Un pauvre en France a....." + s);
952     if (!(s==CharsToUnicodeString("1,50\\u00A0F")))
953         errln((UnicodeString)"FAIL: Expected 1,50<nbsp>F");
954     delete currencyFmt;
955     if (U_FAILURE(status))
956         errln((UnicodeString)"FAIL: Status " + (int32_t)status);
957 
958     for(int i=0; i < UPRV_LENGTHOF(testCases); i++){
959         status = U_ZERO_ERROR;
960         const char *localeID = testCases[i][0];
961         UnicodeString expected(testCases[i][1], -1, US_INV);
962         expected = expected.unescape();
963         s.truncate(0);
964         char loc[256]={0};
965         uloc_canonicalize(localeID, loc, 256, &status);
966         currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
967         if(U_FAILURE(status)){
968             errln("Could not create currency formatter for locale %s",localeID);
969             continue;
970         }
971         currencyFmt->format(1150.50, s);
972         if(s!=expected){
973             errln(UnicodeString("FAIL: Expected: ")+expected
974                     + UnicodeString(" Got: ") + s
975                     + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
976         }
977         if (U_FAILURE(status)){
978             errln((UnicodeString)"FAIL: Status " + (int32_t)status);
979         }
980         delete currencyFmt;
981     }
982 }
983 
984 // -------------------------------------
985 
986 /**
987  * Test the Currency object handling, new as of ICU 2.2.
988  */
TestCurrencyObject()989 void NumberFormatTest::TestCurrencyObject() {
990     UErrorCode ec = U_ZERO_ERROR;
991     NumberFormat* fmt =
992         NumberFormat::createCurrencyInstance(Locale::getUS(), ec);
993 
994     if (U_FAILURE(ec)) {
995         dataerrln("FAIL: getCurrencyInstance(US) - %s", u_errorName(ec));
996         delete fmt;
997         return;
998     }
999 
1000     Locale null("", "", "");
1001 
1002     expectCurrency(*fmt, null, 1234.56, "$1,234.56");
1003 
1004     expectCurrency(*fmt, Locale::getFrance(),
1005                    1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro
1006 
1007     expectCurrency(*fmt, Locale::getJapan(),
1008                    1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
1009 
1010     expectCurrency(*fmt, Locale("fr", "CH", ""),
1011                    1234.56, "CHF 1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
1012 
1013     expectCurrency(*fmt, Locale::getUS(),
1014                    1234.56, "$1,234.56");
1015 
1016     delete fmt;
1017     fmt = NumberFormat::createCurrencyInstance(Locale::getFrance(), ec);
1018 
1019     if (U_FAILURE(ec)) {
1020         errln("FAIL: getCurrencyInstance(FRANCE)");
1021         delete fmt;
1022         return;
1023     }
1024 
1025     expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC"));
1026 
1027     expectCurrency(*fmt, Locale::getJapan(),
1028                    1234.56, CharsToUnicodeString("1\\u202F235 JPY")); // Yen
1029 
1030     expectCurrency(*fmt, Locale("fr", "CH", ""),
1031                    1234.56, CharsToUnicodeString("1\\u202F234,56 CHF")); // no more 0.05 rounding here, see cldrbug 5548
1032 
1033     expectCurrency(*fmt, Locale::getUS(),
1034                    1234.56, CharsToUnicodeString("1\\u202F234,56 $US"));
1035 
1036     expectCurrency(*fmt, Locale::getFrance(),
1037                    1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC")); // Euro
1038 
1039     delete fmt;
1040 }
1041 
1042 // -------------------------------------
1043 
1044 /**
1045  * Do rudimentary testing of parsing.
1046  */
1047 void
TestParse(void)1048 NumberFormatTest::TestParse(void)
1049 {
1050     UErrorCode status = U_ZERO_ERROR;
1051     UnicodeString arg("0");
1052     DecimalFormat* format = new DecimalFormat("00", status);
1053     //try {
1054         Formattable n; format->parse(arg, n, status);
1055         logln((UnicodeString)"parse(" + arg + ") = " + n.getLong());
1056         if (n.getType() != Formattable::kLong ||
1057             n.getLong() != 0) errln((UnicodeString)"FAIL: Expected 0");
1058     delete format;
1059     if (U_FAILURE(status)) errcheckln(status, (UnicodeString)"FAIL: Status " + u_errorName(status));
1060     //}
1061     //catch(Exception e) {
1062     //    errln((UnicodeString)"Exception caught: " + e);
1063     //}
1064 }
1065 
1066 // -------------------------------------
1067 
1068 static const char *lenientAffixTestCases[] = {
1069         "(1)",
1070         "( 1)",
1071         "(1 )",
1072         "( 1 )"
1073 };
1074 
1075 static const char *lenientMinusTestCases[] = {
1076     "-5",
1077     "\\u22125",
1078     "\\u27965"
1079 };
1080 
1081 static const char *lenientCurrencyTestCases[] = {
1082         "$1,000",
1083         "$ 1,000",
1084         "$1000",
1085         "$ 1000",
1086         "$1 000.00",
1087         "$ 1 000.00",
1088         "$ 1\\u00A0000.00",
1089         "1000.00"
1090 };
1091 
1092 // changed from () to - per cldrbug 5674
1093 static const char *lenientNegativeCurrencyTestCases[] = {
1094         "-$1,000",
1095         "-$ 1,000",
1096         "-$1000",
1097         "-$ 1000",
1098         "-$1 000.00",
1099         "-$ 1 000.00",
1100         "- $ 1,000.00 ",
1101         "-$ 1\\u00A0000.00",
1102         "-1000.00"
1103 };
1104 
1105 static const char *lenientPercentTestCases[] = {
1106         "25%",
1107         " 25%",
1108         " 25 %",
1109     	"25 %",
1110 		"25\\u00A0%",
1111 		"25"
1112 };
1113 
1114 static const char *lenientNegativePercentTestCases[] = {
1115 		"-25%",
1116 		" -25%",
1117 		" - 25%",
1118 		"- 25 %",
1119 		" - 25 %",
1120 		"-25 %",
1121 		"-25\\u00A0%",
1122 		"-25",
1123 		"- 25"
1124 };
1125 
1126 static const char *strictFailureTestCases[] = {
1127 		" 1000",
1128 		"10,00",
1129 		"1,000,.0"
1130 };
1131 
1132 /**
1133  * Test lenient parsing.
1134  */
1135 void
TestLenientParse(void)1136 NumberFormatTest::TestLenientParse(void)
1137 {
1138     UErrorCode status = U_ZERO_ERROR;
1139     DecimalFormat *format = new DecimalFormat("(#,##0)", status);
1140     Formattable n;
1141 
1142     if (format == NULL || U_FAILURE(status)) {
1143         dataerrln("Unable to create DecimalFormat (#,##0) - %s", u_errorName(status));
1144     } else {
1145         format->setLenient(TRUE);
1146         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientAffixTestCases); t += 1) {
1147         	UnicodeString testCase = ctou(lenientAffixTestCases[t]);
1148 
1149             format->parse(testCase, n, status);
1150             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1151 
1152             if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
1153             	n.getLong() != 1) {
1154             	dataerrln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t]
1155                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1156             	status = U_ZERO_ERROR;
1157             }
1158        }
1159        delete format;
1160     }
1161 
1162     Locale en_US("en_US");
1163     Locale sv_SE("sv_SE");
1164 
1165     NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, UNUM_DECIMAL, status);
1166 
1167     if (mFormat == NULL || U_FAILURE(status)) {
1168         dataerrln("Unable to create NumberFormat (sv_SE, UNUM_DECIMAL) - %s", u_errorName(status));
1169     } else {
1170         mFormat->setLenient(TRUE);
1171         for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1172             UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1173 
1174             mFormat->parse(testCase, n, status);
1175             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1176 
1177             if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1178                 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1179                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1180                 status = U_ZERO_ERROR;
1181             }
1182         }
1183         delete mFormat;
1184     }
1185 
1186     mFormat = NumberFormat::createInstance(en_US, UNUM_DECIMAL, status);
1187 
1188     if (mFormat == NULL || U_FAILURE(status)) {
1189         dataerrln("Unable to create NumberFormat (en_US, UNUM_DECIMAL) - %s", u_errorName(status));
1190     } else {
1191         mFormat->setLenient(TRUE);
1192         for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1193             UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1194 
1195             mFormat->parse(testCase, n, status);
1196             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1197 
1198             if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1199                 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1200                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1201                 status = U_ZERO_ERROR;
1202             }
1203         }
1204         delete mFormat;
1205     }
1206 
1207     NumberFormat *cFormat = NumberFormat::createInstance(en_US, UNUM_CURRENCY, status);
1208 
1209     if (cFormat == NULL || U_FAILURE(status)) {
1210         dataerrln("Unable to create NumberFormat (en_US, UNUM_CURRENCY) - %s", u_errorName(status));
1211     } else {
1212         cFormat->setLenient(TRUE);
1213         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientCurrencyTestCases); t += 1) {
1214         	UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
1215 
1216             cFormat->parse(testCase, n, status);
1217             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1218 
1219             if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1220             	n.getLong() != 1000) {
1221             	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t]
1222                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1223             	status = U_ZERO_ERROR;
1224             }
1225         }
1226 
1227         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativeCurrencyTestCases); t += 1) {
1228         	UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
1229 
1230             cFormat->parse(testCase, n, status);
1231             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1232 
1233             if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1234             	n.getLong() != -1000) {
1235             	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t]
1236                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1237             	status = U_ZERO_ERROR;
1238             }
1239         }
1240 
1241         delete cFormat;
1242     }
1243 
1244     NumberFormat *pFormat = NumberFormat::createPercentInstance(en_US, status);
1245 
1246     if (pFormat == NULL || U_FAILURE(status)) {
1247         dataerrln("Unable to create NumberFormat::createPercentInstance (en_US) - %s", u_errorName(status));
1248     } else {
1249         pFormat->setLenient(TRUE);
1250         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientPercentTestCases); t += 1) {
1251         	UnicodeString testCase = ctou(lenientPercentTestCases[t]);
1252 
1253         	pFormat->parse(testCase, n, status);
1254             logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1255 
1256             if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1257             	n.getDouble() != 0.25) {
1258             	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t]
1259                       + (UnicodeString) "\"; error code = " + u_errorName(status)
1260                       + "; got: " + n.getDouble(status));
1261             	status = U_ZERO_ERROR;
1262             }
1263         }
1264 
1265         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativePercentTestCases); t += 1) {
1266         	UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
1267 
1268         	pFormat->parse(testCase, n, status);
1269             logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1270 
1271             if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1272             	n.getDouble() != -0.25) {
1273             	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t]
1274                       + (UnicodeString) "\"; error code = " + u_errorName(status)
1275                       + "; got: " + n.getDouble(status));
1276             	status = U_ZERO_ERROR;
1277             }
1278         }
1279 
1280         delete pFormat;
1281     }
1282 
1283    // Test cases that should fail with a strict parse and pass with a
1284    // lenient parse.
1285    NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);
1286 
1287    if (nFormat == NULL || U_FAILURE(status)) {
1288        dataerrln("Unable to create NumberFormat (en_US) - %s", u_errorName(status));
1289    } else {
1290        // first, make sure that they fail with a strict parse
1291        for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1292 	       UnicodeString testCase = ctou(strictFailureTestCases[t]);
1293 
1294 	       nFormat->parse(testCase, n, status);
1295 	       logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1296 
1297 	       if (! U_FAILURE(status)) {
1298 		       errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t]
1299                      + (UnicodeString) "\"; error code = " + u_errorName(status));
1300 	       }
1301 
1302 	       status = U_ZERO_ERROR;
1303        }
1304 
1305        // then, make sure that they pass with a lenient parse
1306        nFormat->setLenient(TRUE);
1307        for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1308 	       UnicodeString testCase = ctou(strictFailureTestCases[t]);
1309 
1310 	       nFormat->parse(testCase, n, status);
1311 	       logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1312 
1313 	       if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1314 	            	n.getLong() != 1000) {
1315 		       errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t]
1316                      + (UnicodeString) "\"; error code = " + u_errorName(status));
1317 		       status = U_ZERO_ERROR;
1318 	       }
1319        }
1320 
1321        delete nFormat;
1322    }
1323 }
1324 
1325 // -------------------------------------
1326 
1327 /**
1328  * Test proper rounding by the format method.
1329  */
1330 void
TestRounding487(void)1331 NumberFormatTest::TestRounding487(void)
1332 {
1333     UErrorCode status = U_ZERO_ERROR;
1334     NumberFormat *nf = NumberFormat::createInstance(status);
1335     if (U_FAILURE(status)) {
1336         dataerrln("Error calling NumberFormat::createInstance()");
1337         return;
1338     }
1339 
1340     roundingTest(*nf, 0.00159999, 4, "0.0016");
1341     roundingTest(*nf, 0.00995, 4, "0.01");
1342 
1343     roundingTest(*nf, 12.3995, 3, "12.4");
1344 
1345     roundingTest(*nf, 12.4999, 0, "12");
1346     roundingTest(*nf, - 19.5, 0, "-20");
1347     delete nf;
1348     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
1349 }
1350 
1351 /**
1352  * Test the functioning of the secondary grouping value.
1353  */
TestSecondaryGrouping(void)1354 void NumberFormatTest::TestSecondaryGrouping(void) {
1355     UErrorCode status = U_ZERO_ERROR;
1356     DecimalFormatSymbols US(Locale::getUS(), status);
1357     CHECK(status, "DecimalFormatSymbols ct");
1358 
1359     DecimalFormat f("#,##,###", US, status);
1360     CHECK(status, "DecimalFormat ct");
1361 
1362     expect2(f, (int32_t)123456789L, "12,34,56,789");
1363     expectPat(f, "#,##,##0");
1364     f.applyPattern("#,###", status);
1365     CHECK(status, "applyPattern");
1366 
1367     f.setSecondaryGroupingSize(4);
1368     expect2(f, (int32_t)123456789L, "12,3456,789");
1369     expectPat(f, "#,####,##0");
1370     NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
1371     CHECK_DATA(status, "createInstance(hi_IN)");
1372 
1373     UnicodeString out;
1374     int32_t l = (int32_t)1876543210L;
1375     g->format(l, out);
1376     delete g;
1377     // expect "1,87,65,43,210", but with Hindi digits
1378     //         01234567890123
1379     UBool ok = TRUE;
1380     if (out.length() != 14) {
1381         ok = FALSE;
1382     } else {
1383         for (int32_t i=0; i<out.length(); ++i) {
1384             UBool expectGroup = FALSE;
1385             switch (i) {
1386             case 1:
1387             case 4:
1388             case 7:
1389             case 10:
1390                 expectGroup = TRUE;
1391                 break;
1392             }
1393             // Later -- fix this to get the actual grouping
1394             // character from the resource bundle.
1395             UBool isGroup = (out.charAt(i) == 0x002C);
1396             if (isGroup != expectGroup) {
1397                 ok = FALSE;
1398                 break;
1399             }
1400         }
1401     }
1402     if (!ok) {
1403         errln((UnicodeString)"FAIL  Expected " + l +
1404               " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
1405               escape(out) + "\"");
1406     } else {
1407         logln((UnicodeString)"Ok    " + l +
1408               " x hi_IN -> \"" +
1409               escape(out) + "\"");
1410     }
1411 }
1412 
TestWhiteSpaceParsing(void)1413 void NumberFormatTest::TestWhiteSpaceParsing(void) {
1414     UErrorCode ec = U_ZERO_ERROR;
1415     DecimalFormatSymbols US(Locale::getUS(), ec);
1416     DecimalFormat fmt("a  b#0c  ", US, ec);
1417     if (U_FAILURE(ec)) {
1418         errcheckln(ec, "FAIL: Constructor - %s", u_errorName(ec));
1419         return;
1420     }
1421     // From ICU 62, flexible whitespace needs lenient mode
1422     fmt.setLenient(TRUE);
1423     int32_t n = 1234;
1424     expect(fmt, "a b1234c ", n);
1425     expect(fmt, "a   b1234c   ", n);
1426 }
1427 
1428 /**
1429  * Test currencies whose display name is a ChoiceFormat.
1430  */
TestComplexCurrency()1431 void NumberFormatTest::TestComplexCurrency() {
1432 
1433 //    UErrorCode ec = U_ZERO_ERROR;
1434 //    Locale loc("kn", "IN", "");
1435 //    NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
1436 //    if (U_SUCCESS(ec)) {
1437 //        expect2(*fmt, 1.0, CharsToUnicodeString("Re.\\u00A01.00"));
1438 //        Use .00392625 because that's 2^-8.  Any value less than 0.005 is fine.
1439 //        expect(*fmt, 1.00390625, CharsToUnicodeString("Re.\\u00A01.00")); // tricky
1440 //        expect2(*fmt, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
1441 //        expect2(*fmt, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
1442 //        expect2(*fmt, -1.0, CharsToUnicodeString("-Re.\\u00A01.00"));
1443 //        expect2(*fmt, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
1444 //    } else {
1445 //        errln("FAIL: getCurrencyInstance(kn_IN)");
1446 //    }
1447 //    delete fmt;
1448 
1449 }
1450 
1451 // -------------------------------------
1452 
1453 void
roundingTest(NumberFormat & nf,double x,int32_t maxFractionDigits,const char * expected)1454 NumberFormatTest::roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)
1455 {
1456     nf.setMaximumFractionDigits(maxFractionDigits);
1457     UnicodeString out; nf.format(x, out);
1458     logln((UnicodeString)"" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
1459     if (!(out==expected)) errln((UnicodeString)"FAIL: Expected " + expected);
1460 }
1461 
1462 /**
1463  * Upgrade to alphaWorks
1464  */
TestExponent(void)1465 void NumberFormatTest::TestExponent(void) {
1466     UErrorCode status = U_ZERO_ERROR;
1467     DecimalFormatSymbols US(Locale::getUS(), status);
1468     CHECK(status, "DecimalFormatSymbols constructor");
1469     DecimalFormat fmt1(UnicodeString("0.###E0"), US, status);
1470     CHECK(status, "DecimalFormat(0.###E0)");
1471     DecimalFormat fmt2(UnicodeString("0.###E+0"), US, status);
1472     CHECK(status, "DecimalFormat(0.###E+0)");
1473     int32_t n = 1234;
1474     expect2(fmt1, n, "1.234E3");
1475     expect2(fmt2, n, "1.234E+3");
1476     expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
1477 }
1478 
1479 /**
1480  * Upgrade to alphaWorks
1481  */
TestScientific(void)1482 void NumberFormatTest::TestScientific(void) {
1483     UErrorCode status = U_ZERO_ERROR;
1484     DecimalFormatSymbols US(Locale::getUS(), status);
1485     CHECK(status, "DecimalFormatSymbols constructor");
1486 
1487     // Test pattern round-trip
1488     const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
1489                           "0.###E0;[0.###E0]" };
1490     int32_t PAT_length = UPRV_LENGTHOF(PAT);
1491     int32_t DIGITS[] = {
1492         // min int, max int, min frac, max frac
1493         1, 1, 0, 0, // "#E0"
1494         1, 1, 0, 4, // "0.####E0"
1495         2, 2, 3, 3, // "00.000E00"
1496         1, 3, 0, 4, // "##0.####E000"
1497         1, 1, 0, 3, // "0.###E0;[0.###E0]"
1498     };
1499     for (int32_t i=0; i<PAT_length; ++i) {
1500         UnicodeString pat(PAT[i]);
1501         DecimalFormat df(pat, US, status);
1502         CHECK(status, "DecimalFormat constructor");
1503         UnicodeString pat2;
1504         df.toPattern(pat2);
1505         if (pat == pat2) {
1506             logln(UnicodeString("Ok   Pattern rt \"") +
1507                   pat + "\" -> \"" +
1508                   pat2 + "\"");
1509         } else {
1510             errln(UnicodeString("FAIL Pattern rt \"") +
1511                   pat + "\" -> \"" +
1512                   pat2 + "\"");
1513         }
1514         // Make sure digit counts match what we expect
1515         if (df.getMinimumIntegerDigits() != DIGITS[4*i] ||
1516             df.getMaximumIntegerDigits() != DIGITS[4*i+1] ||
1517             df.getMinimumFractionDigits() != DIGITS[4*i+2] ||
1518             df.getMaximumFractionDigits() != DIGITS[4*i+3]) {
1519             errln(UnicodeString("FAIL \"" + pat +
1520                                 "\" min/max int; min/max frac = ") +
1521                   df.getMinimumIntegerDigits() + "/" +
1522                   df.getMaximumIntegerDigits() + ";" +
1523                   df.getMinimumFractionDigits() + "/" +
1524                   df.getMaximumFractionDigits() + ", expect " +
1525                   DIGITS[4*i] + "/" +
1526                   DIGITS[4*i+1] + ";" +
1527                   DIGITS[4*i+2] + "/" +
1528                   DIGITS[4*i+3]);
1529         }
1530     }
1531 
1532 
1533     // Test the constructor for default locale. We have to
1534     // manually set the default locale, as there is no
1535     // guarantee that the default locale has the same
1536     // scientific format.
1537     Locale def = Locale::getDefault();
1538     Locale::setDefault(Locale::getUS(), status);
1539     expect2(NumberFormat::createScientificInstance(status),
1540            12345.678901,
1541            "1.2345678901E4", status);
1542     Locale::setDefault(def, status);
1543 
1544     expect2(new DecimalFormat("#E0", US, status),
1545            12345.0,
1546            "1.2345E4", status);
1547     expect(new DecimalFormat("0E0", US, status),
1548            12345.0,
1549            "1E4", status);
1550     expect2(NumberFormat::createScientificInstance(Locale::getUS(), status),
1551            12345.678901,
1552            "1.2345678901E4", status);
1553     expect(new DecimalFormat("##0.###E0", US, status),
1554            12345.0,
1555            "12.34E3", status);
1556     expect(new DecimalFormat("##0.###E0", US, status),
1557            12345.00001,
1558            "12.35E3", status);
1559     expect2(new DecimalFormat("##0.####E0", US, status),
1560            (int32_t) 12345,
1561            "12.345E3", status);
1562     expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status),
1563            12345.678901,
1564            "1,2345678901E4", status);
1565     expect(new DecimalFormat("##0.####E0", US, status),
1566            789.12345e-9,
1567            "789.12E-9", status);
1568     expect2(new DecimalFormat("##0.####E0", US, status),
1569            780.e-9,
1570            "780E-9", status);
1571     expect(new DecimalFormat(".###E0", US, status),
1572            45678.0,
1573            ".457E5", status);
1574     expect2(new DecimalFormat(".###E0", US, status),
1575            (int32_t) 0,
1576            ".0E0", status);
1577     /*
1578     expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
1579                                  new DecimalFormat("##E0", US),
1580                                  new DecimalFormat("####E0", US),
1581                                  new DecimalFormat("0E0", US),
1582                                  new DecimalFormat("00E0", US),
1583                                  new DecimalFormat("000E0", US),
1584                                },
1585            new Long(45678000),
1586            new String[] { "4.5678E7",
1587                           "45.678E6",
1588                           "4567.8E4",
1589                           "5E7",
1590                           "46E6",
1591                           "457E5",
1592                         }
1593            );
1594     !
1595     ! Unroll this test into individual tests below...
1596     !
1597     */
1598     expect2(new DecimalFormat("#E0", US, status),
1599            (int32_t) 45678000, "4.5678E7", status);
1600     expect2(new DecimalFormat("##E0", US, status),
1601            (int32_t) 45678000, "45.678E6", status);
1602     expect2(new DecimalFormat("####E0", US, status),
1603            (int32_t) 45678000, "4567.8E4", status);
1604     expect(new DecimalFormat("0E0", US, status),
1605            (int32_t) 45678000, "5E7", status);
1606     expect(new DecimalFormat("00E0", US, status),
1607            (int32_t) 45678000, "46E6", status);
1608     expect(new DecimalFormat("000E0", US, status),
1609            (int32_t) 45678000, "457E5", status);
1610     /*
1611     expect(new DecimalFormat("###E0", US, status),
1612            new Object[] { new Double(0.0000123), "12.3E-6",
1613                           new Double(0.000123), "123E-6",
1614                           new Double(0.00123), "1.23E-3",
1615                           new Double(0.0123), "12.3E-3",
1616                           new Double(0.123), "123E-3",
1617                           new Double(1.23), "1.23E0",
1618                           new Double(12.3), "12.3E0",
1619                           new Double(123), "123E0",
1620                           new Double(1230), "1.23E3",
1621                          });
1622     !
1623     ! Unroll this test into individual tests below...
1624     !
1625     */
1626     expect2(new DecimalFormat("###E0", US, status),
1627            0.0000123, "12.3E-6", status);
1628     expect2(new DecimalFormat("###E0", US, status),
1629            0.000123, "123E-6", status);
1630     expect2(new DecimalFormat("###E0", US, status),
1631            0.00123, "1.23E-3", status);
1632     expect2(new DecimalFormat("###E0", US, status),
1633            0.0123, "12.3E-3", status);
1634     expect2(new DecimalFormat("###E0", US, status),
1635            0.123, "123E-3", status);
1636     expect2(new DecimalFormat("###E0", US, status),
1637            1.23, "1.23E0", status);
1638     expect2(new DecimalFormat("###E0", US, status),
1639            12.3, "12.3E0", status);
1640     expect2(new DecimalFormat("###E0", US, status),
1641            123.0, "123E0", status);
1642     expect2(new DecimalFormat("###E0", US, status),
1643            1230.0, "1.23E3", status);
1644     /*
1645     expect(new DecimalFormat("0.#E+00", US, status),
1646            new Object[] { new Double(0.00012), "1.2E-04",
1647                           new Long(12000),     "1.2E+04",
1648                          });
1649     !
1650     ! Unroll this test into individual tests below...
1651     !
1652     */
1653     expect2(new DecimalFormat("0.#E+00", US, status),
1654            0.00012, "1.2E-04", status);
1655     expect2(new DecimalFormat("0.#E+00", US, status),
1656            (int32_t) 12000, "1.2E+04", status);
1657 }
1658 
1659 /**
1660  * Upgrade to alphaWorks
1661  */
TestPad(void)1662 void NumberFormatTest::TestPad(void) {
1663     UErrorCode status = U_ZERO_ERROR;
1664     DecimalFormatSymbols US(Locale::getUS(), status);
1665     CHECK(status, "DecimalFormatSymbols constructor");
1666 
1667     expect2(new DecimalFormat("*^##.##", US, status),
1668            int32_t(0), "^^^^0", status);
1669     expect2(new DecimalFormat("*^##.##", US, status),
1670            -1.3, "^-1.3", status);
1671     expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1672            int32_t(0), "0.0E0______ g-m/s^2", status);
1673     expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1674            1.0/3, "333.333E-3_ g-m/s^2", status);
1675     expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1676            int32_t(0), "0.0______ g-m/s^2", status);
1677     expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1678            1.0/3, "0.33333__ g-m/s^2", status);
1679 
1680     // Test padding before a sign
1681     const char *formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1682     expect2(new DecimalFormat(formatStr, US, status),
1683            int32_t(-10),  "xxxxxxxxxx(10.0)", status);
1684     expect2(new DecimalFormat(formatStr, US, status),
1685            int32_t(-1000),"xxxxxxx(1,000.0)", status);
1686     expect2(new DecimalFormat(formatStr, US, status),
1687            int32_t(-1000000),"xxx(1,000,000.0)", status);
1688     expect2(new DecimalFormat(formatStr, US, status),
1689            -100.37,       "xxxxxxxx(100.37)", status);
1690     expect2(new DecimalFormat(formatStr, US, status),
1691            -10456.37,     "xxxxx(10,456.37)", status);
1692     expect2(new DecimalFormat(formatStr, US, status),
1693            -1120456.37,   "xx(1,120,456.37)", status);
1694     expect2(new DecimalFormat(formatStr, US, status),
1695            -112045600.37, "(112,045,600.37)", status);
1696     expect2(new DecimalFormat(formatStr, US, status),
1697            -1252045600.37,"(1,252,045,600.37)", status);
1698 
1699     expect2(new DecimalFormat(formatStr, US, status),
1700            int32_t(10),  "xxxxxxxxxxxx10.0", status);
1701     expect2(new DecimalFormat(formatStr, US, status),
1702            int32_t(1000),"xxxxxxxxx1,000.0", status);
1703     expect2(new DecimalFormat(formatStr, US, status),
1704            int32_t(1000000),"xxxxx1,000,000.0", status);
1705     expect2(new DecimalFormat(formatStr, US, status),
1706            100.37,       "xxxxxxxxxx100.37", status);
1707     expect2(new DecimalFormat(formatStr, US, status),
1708            10456.37,     "xxxxxxx10,456.37", status);
1709     expect2(new DecimalFormat(formatStr, US, status),
1710            1120456.37,   "xxxx1,120,456.37", status);
1711     expect2(new DecimalFormat(formatStr, US, status),
1712            112045600.37, "xx112,045,600.37", status);
1713     expect2(new DecimalFormat(formatStr, US, status),
1714            10252045600.37,"10,252,045,600.37", status);
1715 
1716 
1717     // Test padding between a sign and a number
1718     const char *formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1719     expect2(new DecimalFormat(formatStr2, US, status),
1720            int32_t(-10),  "(10.0xxxxxxxxxx)", status);
1721     expect2(new DecimalFormat(formatStr2, US, status),
1722            int32_t(-1000),"(1,000.0xxxxxxx)", status);
1723     expect2(new DecimalFormat(formatStr2, US, status),
1724            int32_t(-1000000),"(1,000,000.0xxx)", status);
1725     expect2(new DecimalFormat(formatStr2, US, status),
1726            -100.37,       "(100.37xxxxxxxx)", status);
1727     expect2(new DecimalFormat(formatStr2, US, status),
1728            -10456.37,     "(10,456.37xxxxx)", status);
1729     expect2(new DecimalFormat(formatStr2, US, status),
1730            -1120456.37,   "(1,120,456.37xx)", status);
1731     expect2(new DecimalFormat(formatStr2, US, status),
1732            -112045600.37, "(112,045,600.37)", status);
1733     expect2(new DecimalFormat(formatStr2, US, status),
1734            -1252045600.37,"(1,252,045,600.37)", status);
1735 
1736     expect2(new DecimalFormat(formatStr2, US, status),
1737            int32_t(10),  "10.0xxxxxxxxxxxx", status);
1738     expect2(new DecimalFormat(formatStr2, US, status),
1739            int32_t(1000),"1,000.0xxxxxxxxx", status);
1740     expect2(new DecimalFormat(formatStr2, US, status),
1741            int32_t(1000000),"1,000,000.0xxxxx", status);
1742     expect2(new DecimalFormat(formatStr2, US, status),
1743            100.37,       "100.37xxxxxxxxxx", status);
1744     expect2(new DecimalFormat(formatStr2, US, status),
1745            10456.37,     "10,456.37xxxxxxx", status);
1746     expect2(new DecimalFormat(formatStr2, US, status),
1747            1120456.37,   "1,120,456.37xxxx", status);
1748     expect2(new DecimalFormat(formatStr2, US, status),
1749            112045600.37, "112,045,600.37xx", status);
1750     expect2(new DecimalFormat(formatStr2, US, status),
1751            10252045600.37,"10,252,045,600.37", status);
1752 
1753     //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1754     DecimalFormat fmt("#", US, status);
1755     CHECK(status, "DecimalFormat constructor");
1756     UnicodeString padString("P");
1757     fmt.setPadCharacter(padString);
1758     expectPad(fmt, "*P##.##", DecimalFormat::kPadBeforePrefix, 5, padString);
1759     fmt.setPadCharacter((UnicodeString)"^");
1760     expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, (UnicodeString)"^");
1761     //commented untill implementation is complete
1762   /*  fmt.setPadCharacter((UnicodeString)"^^^");
1763     expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1764     padString.remove();
1765     padString.append((UChar)0x0061);
1766     padString.append((UChar)0x0302);
1767     fmt.setPadCharacter(padString);
1768     UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1769     UnicodeString pattern(patternChars);
1770     expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1771  */
1772 
1773 }
1774 
1775 /**
1776  * Upgrade to alphaWorks
1777  */
TestPatterns2(void)1778 void NumberFormatTest::TestPatterns2(void) {
1779     UErrorCode status = U_ZERO_ERROR;
1780     DecimalFormatSymbols US(Locale::getUS(), status);
1781     CHECK(status, "DecimalFormatSymbols constructor");
1782 
1783     DecimalFormat fmt("#", US, status);
1784     CHECK(status, "DecimalFormat constructor");
1785 
1786     UChar hat = 0x005E; /*^*/
1787 
1788     expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, hat);
1789     expectPad(fmt, "$*^#", DecimalFormat::kPadAfterPrefix, 2, hat);
1790     expectPad(fmt, "#*^", DecimalFormat::kPadBeforeSuffix, 1, hat);
1791     expectPad(fmt, "#$*^", DecimalFormat::kPadAfterSuffix, 2, hat);
1792     expectPad(fmt, "$*^$#", ILLEGAL);
1793     expectPad(fmt, "#$*^$", ILLEGAL);
1794     expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix,
1795               12, (UChar)0x0078 /*x*/);
1796     expectPad(fmt, "''#0*x", DecimalFormat::kPadBeforeSuffix,
1797               3, (UChar)0x0078 /*x*/);
1798     expectPad(fmt, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix,
1799               10, (UChar)0x0061 /*a*/);
1800 
1801     fmt.applyPattern("AA#,##0.00ZZ", status);
1802     CHECK(status, "applyPattern");
1803     fmt.setPadCharacter(hat);
1804 
1805     fmt.setFormatWidth(10);
1806 
1807     fmt.setPadPosition(DecimalFormat::kPadBeforePrefix);
1808     expectPat(fmt, "*^AA#,##0.00ZZ");
1809 
1810     fmt.setPadPosition(DecimalFormat::kPadBeforeSuffix);
1811     expectPat(fmt, "AA#,##0.00*^ZZ");
1812 
1813     fmt.setPadPosition(DecimalFormat::kPadAfterSuffix);
1814     expectPat(fmt, "AA#,##0.00ZZ*^");
1815 
1816     //            12  3456789012
1817     UnicodeString exp("AA*^#,##0.00ZZ", "");
1818     fmt.setFormatWidth(12);
1819     fmt.setPadPosition(DecimalFormat::kPadAfterPrefix);
1820     expectPat(fmt, exp);
1821 
1822     fmt.setFormatWidth(13);
1823     //              12  34567890123
1824     expectPat(fmt, "AA*^##,##0.00ZZ");
1825 
1826     fmt.setFormatWidth(14);
1827     //              12  345678901234
1828     expectPat(fmt, "AA*^###,##0.00ZZ");
1829 
1830     fmt.setFormatWidth(15);
1831     //              12  3456789012345
1832     expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1833 
1834     fmt.setFormatWidth(16);
1835     //              12  34567890123456
1836     expectPat(fmt, "AA*^#####,##0.00ZZ");
1837 }
1838 
TestSurrogateSupport(void)1839 void NumberFormatTest::TestSurrogateSupport(void) {
1840     UErrorCode status = U_ZERO_ERROR;
1841     DecimalFormatSymbols custom(Locale::getUS(), status);
1842     CHECK(status, "DecimalFormatSymbols constructor");
1843 
1844     custom.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, "decimal");
1845     custom.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, "plus");
1846     custom.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, " minus ");
1847     custom.setSymbol(DecimalFormatSymbols::kExponentialSymbol, "exponent");
1848 
1849     UnicodeString patternStr("*\\U00010000##.##", "");
1850     patternStr = patternStr.unescape();
1851     UnicodeString expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1852     expStr = expStr.unescape();
1853     expect2(new DecimalFormat(patternStr, custom, status),
1854            int32_t(0), expStr, status);
1855 
1856     status = U_ZERO_ERROR;
1857     expect2(new DecimalFormat("*^##.##", custom, status),
1858            int32_t(0), "^^^^0", status);
1859     status = U_ZERO_ERROR;
1860     expect2(new DecimalFormat("##.##", custom, status),
1861            -1.3, " minus 1decimal3", status);
1862     status = U_ZERO_ERROR;
1863     expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1864            int32_t(0), "0decimal0exponent0 g-m/s^2", status);
1865     status = U_ZERO_ERROR;
1866     expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1867            1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
1868     status = U_ZERO_ERROR;
1869     expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1870            int32_t(0), "0decimal0 g-m/s^2", status);
1871     status = U_ZERO_ERROR;
1872     expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1873            1.0/3, "0decimal33333 g-m/s^2", status);
1874 
1875     UnicodeString zero((UChar32)0x10000);
1876     UnicodeString one((UChar32)0x10001);
1877     UnicodeString two((UChar32)0x10002);
1878     UnicodeString five((UChar32)0x10005);
1879     custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
1880     custom.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, one);
1881     custom.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, two);
1882     custom.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, five);
1883     expStr = UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1884     expStr = expStr.unescape();
1885     status = U_ZERO_ERROR;
1886     expect2(new DecimalFormat("##0.000", custom, status),
1887            1.25, expStr, status);
1888 
1889     custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
1890     custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
1891     custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
1892     patternStr = UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
1893     patternStr = patternStr.unescape();
1894     expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1895     status = U_ZERO_ERROR;
1896     expect2(new DecimalFormat(patternStr, custom, status),
1897            int32_t(-20), expStr, status);
1898 
1899     custom.setSymbol(DecimalFormatSymbols::kPercentSymbol, "percent");
1900     patternStr = "'You''ve lost ' -0.00 %' of your money today'";
1901     patternStr = patternStr.unescape();
1902     expStr = UnicodeString(" minus You've lost   minus 2000decimal00 percent of your money today", "");
1903     status = U_ZERO_ERROR;
1904     expect2(new DecimalFormat(patternStr, custom, status),
1905            int32_t(-20), expStr, status);
1906 }
1907 
TestCurrencyPatterns(void)1908 void NumberFormatTest::TestCurrencyPatterns(void) {
1909     int32_t i, locCount;
1910     const Locale* locs = NumberFormat::getAvailableLocales(locCount);
1911     for (i=0; i<locCount; ++i) {
1912         UErrorCode ec = U_ZERO_ERROR;
1913         NumberFormat* nf = NumberFormat::createCurrencyInstance(locs[i], ec);
1914         if (U_FAILURE(ec)) {
1915             errln("FAIL: Can't create NumberFormat(%s) - %s", locs[i].getName(), u_errorName(ec));
1916         } else {
1917             // Make sure currency formats do not have a variable number
1918             // of fraction digits
1919             int32_t min = nf->getMinimumFractionDigits();
1920             int32_t max = nf->getMaximumFractionDigits();
1921             if (min != max) {
1922                 UnicodeString a, b;
1923                 nf->format(1.0, a);
1924                 nf->format(1.125, b);
1925                 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1926                       " min fraction digits != max fraction digits; "
1927                       "x 1.0 => " + escape(a) +
1928                       "; x 1.125 => " + escape(b));
1929             }
1930 
1931             // Make sure EURO currency formats have exactly 2 fraction digits
1932             DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
1933             if (df != NULL) {
1934                 if (u_strcmp(EUR, df->getCurrency()) == 0) {
1935                     if (min != 2 || max != 2) {
1936                         UnicodeString a;
1937                         nf->format(1.0, a);
1938                         errln((UnicodeString)"FAIL: " + locs[i].getName() +
1939                               " is a EURO format but it does not have 2 fraction digits; "
1940                               "x 1.0 => " +
1941                               escape(a));
1942                     }
1943                 }
1944             }
1945         }
1946         delete nf;
1947     }
1948 }
1949 
TestRegCurrency(void)1950 void NumberFormatTest::TestRegCurrency(void) {
1951 #if !UCONFIG_NO_SERVICE
1952     UErrorCode status = U_ZERO_ERROR;
1953     UChar USD[4];
1954     ucurr_forLocale("en_US", USD, 4, &status);
1955     UChar YEN[4];
1956     ucurr_forLocale("ja_JP", YEN, 4, &status);
1957     UChar TMP[4];
1958 
1959     if(U_FAILURE(status)) {
1960         errcheckln(status, "Unable to get currency for locale, error %s", u_errorName(status));
1961         return;
1962     }
1963 
1964     UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
1965 
1966     ucurr_forLocale("en_US", TMP, 4, &status);
1967     if (u_strcmp(YEN, TMP) != 0) {
1968         errln("FAIL: didn't return YEN registered for en_US");
1969     }
1970 
1971     int32_t fallbackLen = ucurr_forLocale("en_XX_BAR", TMP, 4, &status);
1972     if (fallbackLen) {
1973         errln("FAIL: tried to fallback en_XX_BAR");
1974     }
1975     status = U_ZERO_ERROR; // reset
1976 
1977     if (!ucurr_unregister(enkey, &status)) {
1978         errln("FAIL: couldn't unregister enkey");
1979     }
1980 
1981     ucurr_forLocale("en_US", TMP, 4, &status);
1982     if (u_strcmp(USD, TMP) != 0) {
1983         errln("FAIL: didn't return USD for en_US after unregister of en_US");
1984     }
1985     status = U_ZERO_ERROR; // reset
1986 
1987     ucurr_forLocale("en_US_BLAH", TMP, 4, &status);
1988     if (u_strcmp(USD, TMP) != 0) {
1989         errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1990     }
1991     status = U_ZERO_ERROR; // reset
1992 #endif
1993 }
1994 
TestCurrencyNames(void)1995 void NumberFormatTest::TestCurrencyNames(void) {
1996     // Do a basic check of getName()
1997     // USD { "US$", "US Dollar"            } // 04/04/1792-
1998     UErrorCode ec = U_ZERO_ERROR;
1999     static const UChar USD[] = {0x55, 0x53, 0x44, 0}; /*USD*/
2000     static const UChar USX[] = {0x55, 0x53, 0x58, 0}; /*USX*/
2001     static const UChar CAD[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
2002     static const UChar ITL[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
2003     UBool isChoiceFormat;
2004     int32_t len;
2005     const UBool possibleDataError = TRUE;
2006     // Warning: HARD-CODED LOCALE DATA in this test.  If it fails, CHECK
2007     // THE LOCALE DATA before diving into the code.
2008     assertEquals("USD.getName(SYMBOL_NAME, en)",
2009                  UnicodeString("$"),
2010                  UnicodeString(ucurr_getName(USD, "en",
2011                                              UCURR_SYMBOL_NAME,
2012                                              &isChoiceFormat, &len, &ec)),
2013                                              possibleDataError);
2014     assertEquals("USD.getName(NARROW_SYMBOL_NAME, en)",
2015                  UnicodeString("$"),
2016                  UnicodeString(ucurr_getName(USD, "en",
2017                                              UCURR_NARROW_SYMBOL_NAME,
2018                                              &isChoiceFormat, &len, &ec)),
2019                                              possibleDataError);
2020     assertEquals("USD.getName(LONG_NAME, en)",
2021                  UnicodeString("US Dollar"),
2022                  UnicodeString(ucurr_getName(USD, "en",
2023                                              UCURR_LONG_NAME,
2024                                              &isChoiceFormat, &len, &ec)),
2025                                              possibleDataError);
2026     assertEquals("CAD.getName(SYMBOL_NAME, en)",
2027                  UnicodeString("CA$"),
2028                  UnicodeString(ucurr_getName(CAD, "en",
2029                                              UCURR_SYMBOL_NAME,
2030                                              &isChoiceFormat, &len, &ec)),
2031                                              possibleDataError);
2032     assertEquals("CAD.getName(NARROW_SYMBOL_NAME, en)",
2033                  UnicodeString("$"),
2034                  UnicodeString(ucurr_getName(CAD, "en",
2035                                              UCURR_NARROW_SYMBOL_NAME,
2036                                              &isChoiceFormat, &len, &ec)),
2037                                              possibleDataError);
2038     assertEquals("CAD.getName(SYMBOL_NAME, en_CA)",
2039                  UnicodeString("$"),
2040                  UnicodeString(ucurr_getName(CAD, "en_CA",
2041                                              UCURR_SYMBOL_NAME,
2042                                              &isChoiceFormat, &len, &ec)),
2043                                              possibleDataError);
2044     assertEquals("USD.getName(SYMBOL_NAME, en_CA)",
2045                  UnicodeString("US$"),
2046                  UnicodeString(ucurr_getName(USD, "en_CA",
2047                                              UCURR_SYMBOL_NAME,
2048                                              &isChoiceFormat, &len, &ec)),
2049                                              possibleDataError);
2050     assertEquals("USD.getName(NARROW_SYMBOL_NAME, en_CA)",
2051                  UnicodeString("$"),
2052                  UnicodeString(ucurr_getName(USD, "en_CA",
2053                                              UCURR_NARROW_SYMBOL_NAME,
2054                                              &isChoiceFormat, &len, &ec)),
2055                                              possibleDataError);
2056     assertEquals("USD.getName(SYMBOL_NAME) in en_NZ",
2057                  UnicodeString("US$"),
2058                  UnicodeString(ucurr_getName(USD, "en_NZ",
2059                                              UCURR_SYMBOL_NAME,
2060                                              &isChoiceFormat, &len, &ec)),
2061                                              possibleDataError);
2062     assertEquals("CAD.getName(SYMBOL_NAME)",
2063                  UnicodeString("CA$"),
2064                  UnicodeString(ucurr_getName(CAD, "en_NZ",
2065                                              UCURR_SYMBOL_NAME,
2066                                              &isChoiceFormat, &len, &ec)),
2067                                              possibleDataError);
2068     assertEquals("USX.getName(SYMBOL_NAME)",
2069                  UnicodeString("USX"),
2070                  UnicodeString(ucurr_getName(USX, "en_US",
2071                                              UCURR_SYMBOL_NAME,
2072                                              &isChoiceFormat, &len, &ec)),
2073                                              possibleDataError);
2074     assertEquals("USX.getName(NARROW_SYMBOL_NAME)",
2075                  UnicodeString("USX"),
2076                  UnicodeString(ucurr_getName(USX, "en_US",
2077                                              UCURR_NARROW_SYMBOL_NAME,
2078                                              &isChoiceFormat, &len, &ec)),
2079                                              possibleDataError);
2080     assertEquals("USX.getName(LONG_NAME)",
2081                  UnicodeString("USX"),
2082                  UnicodeString(ucurr_getName(USX, "en_US",
2083                                              UCURR_LONG_NAME,
2084                                              &isChoiceFormat, &len, &ec)),
2085                                              possibleDataError);
2086     assertSuccess("ucurr_getName", ec);
2087 
2088     ec = U_ZERO_ERROR;
2089 
2090     // Test that a default or fallback warning is being returned. JB 4239.
2091     ucurr_getName(CAD, "es_ES", UCURR_LONG_NAME, &isChoiceFormat,
2092                             &len, &ec);
2093     assertTrue("ucurr_getName (es_ES fallback)",
2094                     U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);
2095 
2096     ucurr_getName(CAD, "zh_TW", UCURR_LONG_NAME, &isChoiceFormat,
2097                             &len, &ec);
2098     assertTrue("ucurr_getName (zh_TW fallback)",
2099                     U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);
2100 
2101     ucurr_getName(CAD, "en_US", UCURR_LONG_NAME, &isChoiceFormat,
2102                             &len, &ec);
2103     assertTrue("ucurr_getName (en_US default)",
2104                     U_USING_DEFAULT_WARNING == ec || U_USING_FALLBACK_WARNING == ec, TRUE);
2105 
2106     ucurr_getName(CAD, "ti", UCURR_LONG_NAME, &isChoiceFormat,
2107                             &len, &ec);
2108     assertTrue("ucurr_getName (ti default)",
2109                     U_USING_DEFAULT_WARNING == ec, TRUE);
2110 
2111     // Test that a default warning is being returned when falling back to root. JB 4536.
2112     ucurr_getName(ITL, "cy", UCURR_LONG_NAME, &isChoiceFormat,
2113                             &len, &ec);
2114     assertTrue("ucurr_getName (cy default to root)",
2115                     U_USING_DEFAULT_WARNING == ec, TRUE);
2116 
2117     // TODO add more tests later
2118 }
2119 
TestCurrencyVariants()2120 void NumberFormatTest::TestCurrencyVariants(){
2121     IcuTestErrorCode status(*this, "TestCurrencyVariants");
2122 
2123     struct TestCase {
2124         const char* locale;
2125         const char16_t* isoCode;
2126         const char16_t* expectedShort;
2127         const char16_t* expectedNarrow;
2128         const char16_t* expectedFormal;
2129         const char16_t* expectedVariant;
2130         UErrorCode expectedNarrowError;
2131     } cases[] = {
2132         {"en-US", u"CAD", u"CA$", u"$", u"CA$", u"CA$", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2133         {"en-US", u"CDF", u"CDF", u"CDF", u"CDF", u"CDF", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2134         {"sw-CD", u"CDF", u"FC", u"FC", u"FC", u"FC", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2135         {"en-US", u"GEL", u"GEL", u"₾", u"GEL", u"GEL", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2136         {"ka-GE", u"GEL", u"₾", u"₾", u"₾", u"₾", U_USING_FALLBACK_WARNING}, // narrow: fallback to ka
2137         {"ka", u"GEL", u"₾", u"₾", u"₾", u"₾", U_ZERO_ERROR}, // no fallback on narrow
2138         {"zh-TW", u"TWD", u"$", u"$", u"NT$", u"$", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2139         {"ccp", u"TRY", u"TRY", u"₺", u"TRY", u"TL", U_ZERO_ERROR}, // no fallback on variant
2140     };
2141     for (const auto& cas : cases) {
2142         status.setScope(cas.isoCode);
2143         UBool choiceFormatIgnored;
2144         int32_t lengthIgnored;
2145         const UChar* actualShort = ucurr_getName(
2146             cas.isoCode,
2147             cas.locale,
2148             UCURR_SYMBOL_NAME,
2149             &choiceFormatIgnored,
2150             &lengthIgnored,
2151             status);
2152         const UChar* actualFormal = ucurr_getName(
2153             cas.isoCode,
2154             cas.locale,
2155             UCURR_FORMAL_SYMBOL_NAME,
2156             &choiceFormatIgnored,
2157             &lengthIgnored,
2158             status);
2159         const UChar* actualVarant = ucurr_getName(
2160             cas.isoCode,
2161             cas.locale,
2162             UCURR_VARIANT_SYMBOL_NAME,
2163             &choiceFormatIgnored,
2164             &lengthIgnored,
2165             status);
2166         status.errIfFailureAndReset();
2167         const UChar* actualNarrow = ucurr_getName(
2168             cas.isoCode,
2169             cas.locale,
2170             UCURR_NARROW_SYMBOL_NAME,
2171             &choiceFormatIgnored,
2172             &lengthIgnored,
2173             status);
2174         status.expectErrorAndReset(cas.expectedNarrowError);
2175         assertEquals(UnicodeString("Short symbol: ") + cas.locale + u": " + cas.isoCode,
2176                 cas.expectedShort, actualShort);
2177         assertEquals(UnicodeString("Narrow symbol: ") + cas.locale + u": " + cas.isoCode,
2178                 cas.expectedNarrow, actualNarrow);
2179         assertEquals(UnicodeString("Formal symbol: ") + cas.locale + u": " + cas.isoCode,
2180                 cas.expectedFormal, actualFormal);
2181         assertEquals(UnicodeString("Variant symbol: ") + cas.locale + u": " + cas.isoCode,
2182                 cas.expectedVariant, actualVarant);
2183     }
2184 }
2185 
TestCurrencyUnit(void)2186 void NumberFormatTest::TestCurrencyUnit(void){
2187     UErrorCode ec = U_ZERO_ERROR;
2188     static const UChar USD[]  = u"USD";
2189     static const char USD8[]  =  "USD";
2190     static const UChar BAD[]  = u"???";
2191     static const UChar BAD2[] = u"??A";
2192     static const UChar XXX[]  = u"XXX";
2193     static const char XXX8[]  =  "XXX";
2194     static const UChar XYZ[]  = u"XYZ";
2195     static const char XYZ8[]  =  "XYZ";
2196     static const UChar INV[]  = u"{$%";
2197     static const char INV8[]  =  "{$%";
2198     static const UChar ZZZ[]  = u"zz";
2199     static const char ZZZ8[]  = "zz";
2200     static const UChar JPY[]  = u"JPY";
2201     static const char JPY8[]  =  "JPY";
2202     static const UChar jpy[]  = u"jpy";
2203     static const char jpy8[]  =  "jpy";
2204 
2205     UChar* EUR = (UChar*) malloc(6);
2206     EUR[0] = u'E';
2207     EUR[1] = u'U';
2208     EUR[2] = u'R';
2209     char* EUR8 = (char*) malloc(3);
2210     EUR8[0] = 'E';
2211     EUR8[1] = 'U';
2212     EUR8[2] = 'R';
2213 
2214     CurrencyUnit cu(USD, ec);
2215     assertSuccess("CurrencyUnit", ec);
2216     assertEquals("getISOCurrency()", USD, cu.getISOCurrency());
2217     assertEquals("getSubtype()", USD8, cu.getSubtype());
2218 
2219     // Test XYZ, a valid but non-standard currency.
2220     // Note: Country code XY is private-use, so XYZ should remain unallocated.
2221     CurrencyUnit extended(XYZ, ec);
2222     assertSuccess("non-standard", ec);
2223     assertEquals("non-standard", XYZ, extended.getISOCurrency());
2224     assertEquals("non-standard", XYZ8, extended.getSubtype());
2225 
2226     CurrencyUnit inv(INV, ec);
2227     assertEquals("non-invariant", U_INVARIANT_CONVERSION_ERROR, ec);
2228     assertEquals("non-invariant", XXX, inv.getISOCurrency());
2229     ec = U_ZERO_ERROR;
2230 
2231     CurrencyUnit zzz(ZZZ, ec);
2232     assertEquals("too short", U_ILLEGAL_ARGUMENT_ERROR, ec);
2233     assertEquals("too short", XXX, zzz.getISOCurrency());
2234     ec = U_ZERO_ERROR;
2235 
2236     CurrencyUnit eur(EUR, ec);
2237     assertEquals("non-nul-terminated", u"EUR", eur.getISOCurrency());
2238     assertEquals("non-nul-terminated", "EUR", eur.getSubtype());
2239 
2240     // Test StringPiece constructor
2241     CurrencyUnit cu8(USD8, ec);
2242     assertEquals("StringPiece constructor", USD, cu8.getISOCurrency());
2243 
2244     CurrencyUnit inv8(INV8, ec);
2245     assertEquals("non-invariant 8", U_INVARIANT_CONVERSION_ERROR, ec);
2246     assertEquals("non-invariant 8", XXX, inv8.getISOCurrency());
2247     ec = U_ZERO_ERROR;
2248 
2249     CurrencyUnit zzz8(ZZZ8, ec);
2250     assertEquals("too short 8", U_ILLEGAL_ARGUMENT_ERROR, ec);
2251     assertEquals("too short 8", XXX, zzz8.getISOCurrency());
2252     ec = U_ZERO_ERROR;
2253 
2254     CurrencyUnit zzz8b({ZZZ8, 3}, ec);
2255     assertEquals("too short 8b", U_ILLEGAL_ARGUMENT_ERROR, ec);
2256     assertEquals("too short 8b", XXX, zzz8b.getISOCurrency());
2257     ec = U_ZERO_ERROR;
2258 
2259     CurrencyUnit eur8({EUR8, 3}, ec);
2260     assertEquals("non-nul-terminated 8", u"EUR", eur8.getISOCurrency());
2261     assertEquals("non-nul-terminated 8", "EUR", eur8.getSubtype());
2262 
2263     CurrencyUnit cu2(cu);
2264     if (!(cu2 == cu)){
2265         errln("CurrencyUnit copy constructed object should be same");
2266     }
2267 
2268     CurrencyUnit * cu3 = cu.clone();
2269     if (!(*cu3 == cu)){
2270         errln("CurrencyUnit cloned object should be same");
2271     }
2272     CurrencyUnit bad(BAD, ec);
2273     assertSuccess("CurrencyUnit", ec);
2274     if (cu.getOffset() == bad.getOffset()) {
2275         errln("Indexes of different currencies should differ.");
2276     }
2277     CurrencyUnit bad2(BAD2, ec);
2278     assertSuccess("CurrencyUnit", ec);
2279     if (bad2.getOffset() != bad.getOffset()) {
2280         errln("Indexes of unrecognized currencies should be the same.");
2281     }
2282     if (bad == bad2) {
2283         errln("Different unrecognized currencies should not be equal.");
2284     }
2285     bad = bad2;
2286     if (bad != bad2) {
2287         errln("Currency unit assignment should be the same.");
2288     }
2289     delete cu3;
2290 
2291     // Test default constructor
2292     CurrencyUnit def;
2293     assertEquals("Default currency", XXX, def.getISOCurrency());
2294     assertEquals("Default currency as subtype", XXX8, def.getSubtype());
2295 
2296     // Test slicing
2297     MeasureUnit sliced1 = cu;
2298     MeasureUnit sliced2 = cu;
2299     MeasureUnit sliced3 = extended;
2300     assertEquals("Subtype after slicing 1", USD8, sliced1.getSubtype());
2301     assertEquals("Subtype after slicing 2", USD8, sliced2.getSubtype());
2302     assertEquals("Subtype after slicing 3", XYZ8, sliced3.getSubtype());
2303     CurrencyUnit restored1(sliced1, ec);
2304     CurrencyUnit restored2(sliced2, ec);
2305     CurrencyUnit restored3(sliced3, ec);
2306     assertSuccess("Restoring from MeasureUnit", ec);
2307     assertEquals("Subtype after restoring 1", USD8, restored1.getSubtype());
2308     assertEquals("Subtype after restoring 2", USD8, restored2.getSubtype());
2309     assertEquals("Subtype after restoring 3", XYZ8, restored3.getSubtype());
2310     assertEquals("ISO Code after restoring 1", USD, restored1.getISOCurrency());
2311     assertEquals("ISO Code after restoring 2", USD, restored2.getISOCurrency());
2312     assertEquals("ISO Code after restoring 3", XYZ, restored3.getISOCurrency());
2313 
2314     // Test copy constructor failure
2315     LocalPointer<MeasureUnit> meter(MeasureUnit::createMeter(ec));
2316     assertSuccess("Creating meter", ec);
2317     CurrencyUnit failure(*meter, ec);
2318     assertEquals("Copying from meter should fail", ec, U_ILLEGAL_ARGUMENT_ERROR);
2319     assertEquals("Copying should not give uninitialized ISO code", u"", failure.getISOCurrency());
2320 
2321     // Test equality
2322     ec = U_ZERO_ERROR;
2323     assertFalse("FAIL: USD == JPY", CurrencyUnit(USD, ec) == CurrencyUnit(JPY, ec));
2324     assertTrue("FAIL: USD != USD",  CurrencyUnit(USD, ec) == CurrencyUnit(USD, ec));
2325     assertTrue("FAIL: JPY != jpy",  CurrencyUnit(JPY, ec) == CurrencyUnit(jpy, ec));
2326     assertTrue("FAIL: jpy != JPY",  CurrencyUnit(jpy, ec) == CurrencyUnit(JPY, ec));
2327 
2328     // Test equality with system charset instances
2329     assertFalse("FAIL: USD8 == JPY8", CurrencyUnit(USD8, ec) == CurrencyUnit(JPY8, ec));
2330     assertTrue("FAIL: USD8 != USD8",  CurrencyUnit(USD8, ec) == CurrencyUnit(USD8, ec));
2331     assertTrue("FAIL: JPY8 != jpy8",  CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy8, ec));
2332     assertTrue("FAIL: jpy8 != JPY8",  CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY8, ec));
2333 
2334     // Test equality between UTF-16 and system charset instances
2335     assertTrue("FAIL: USD != USD8",  CurrencyUnit(USD, ec) == CurrencyUnit(USD8, ec));
2336     assertTrue("FAIL: USD8 != USD",  CurrencyUnit(USD8, ec) == CurrencyUnit(USD, ec));
2337     assertTrue("FAIL: JPY != jpy8",  CurrencyUnit(JPY, ec) == CurrencyUnit(jpy8, ec));
2338     assertTrue("FAIL: JPY8 != jpy",  CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy, ec));
2339     assertTrue("FAIL: jpy != JPY8",  CurrencyUnit(jpy, ec) == CurrencyUnit(JPY8, ec));
2340     assertTrue("FAIL: jpy8 != JPY",  CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY, ec));
2341 
2342     free(EUR);
2343     free(EUR8);
2344 }
2345 
TestCurrencyAmount(void)2346 void NumberFormatTest::TestCurrencyAmount(void){
2347     UErrorCode ec = U_ZERO_ERROR;
2348     static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
2349     CurrencyAmount ca(9, USD, ec);
2350     assertSuccess("CurrencyAmount", ec);
2351 
2352     CurrencyAmount ca2(ca);
2353     if (!(ca2 == ca)){
2354         errln("CurrencyAmount copy constructed object should be same");
2355     }
2356 
2357     ca2=ca;
2358     if (!(ca2 == ca)){
2359         errln("CurrencyAmount assigned object should be same");
2360     }
2361 
2362     CurrencyAmount *ca3 = ca.clone();
2363     if (!(*ca3 == ca)){
2364         errln("CurrencyAmount cloned object should be same");
2365     }
2366     delete ca3;
2367 }
2368 
TestSymbolsWithBadLocale(void)2369 void NumberFormatTest::TestSymbolsWithBadLocale(void) {
2370     Locale locDefault;
2371     static const char *badLocales[] = {
2372         // length < ULOC_FULLNAME_CAPACITY
2373         "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME",
2374 
2375         // length > ULOC_FULLNAME_CAPACITY
2376         "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"
2377     }; // expect U_USING_DEFAULT_WARNING for both
2378 
2379     unsigned int i;
2380     for (i = 0; i < UPRV_LENGTHOF(badLocales); i++) {
2381         const char *localeName = badLocales[i];
2382         Locale locBad(localeName);
2383         assertTrue(WHERE, !locBad.isBogus());
2384         UErrorCode status = U_ZERO_ERROR;
2385         UnicodeString intlCurrencySymbol((UChar)0xa4);
2386 
2387         intlCurrencySymbol.append((UChar)0xa4);
2388 
2389         logln("Current locale is %s", Locale::getDefault().getName());
2390         Locale::setDefault(locBad, status);
2391         logln("Current locale is %s", Locale::getDefault().getName());
2392         DecimalFormatSymbols mySymbols(status);
2393         if (status != U_USING_DEFAULT_WARNING) {
2394             errln("DecimalFormatSymbols should return U_USING_DEFAULT_WARNING.");
2395         }
2396         if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
2397             errln("DecimalFormatSymbols does not have the right locale.", locBad.getName());
2398         }
2399         int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
2400         for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
2401             UnicodeString symbolString = mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum);
2402             logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ") + prettify(symbolString));
2403             if (symbolString.length() == 0
2404                 && symbolEnum != (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
2405                 && symbolEnum != (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol)
2406             {
2407                 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
2408             }
2409         }
2410 
2411         status = U_ZERO_ERROR;
2412         Locale::setDefault(locDefault, status);
2413         logln("Current locale is %s", Locale::getDefault().getName());
2414     }
2415 }
2416 
2417 /**
2418  * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
2419  * behave the same, except for memory ownership semantics. (No
2420  * version of this test on Java, since Java has only one method.)
2421  */
TestAdoptDecimalFormatSymbols(void)2422 void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
2423     UErrorCode ec = U_ZERO_ERROR;
2424     DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2425     if (U_FAILURE(ec)) {
2426         errcheckln(ec, "Fail: DecimalFormatSymbols constructor - %s", u_errorName(ec));
2427         delete sym;
2428         return;
2429     }
2430     UnicodeString pat(" #,##0.00");
2431     pat.insert(0, (UChar)0x00A4);
2432     DecimalFormat fmt(pat, sym, ec);
2433     if (U_FAILURE(ec)) {
2434         errln("Fail: DecimalFormat constructor");
2435         return;
2436     }
2437 
2438     UnicodeString str;
2439     fmt.format(2350.75, str);
2440     if (str == "$ 2,350.75") {
2441         logln(str);
2442     } else {
2443         dataerrln("Fail: " + str + ", expected $ 2,350.75");
2444     }
2445 
2446     sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2447     if (U_FAILURE(ec)) {
2448         errln("Fail: DecimalFormatSymbols constructor");
2449         delete sym;
2450         return;
2451     }
2452     sym->setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2453     fmt.adoptDecimalFormatSymbols(sym);
2454 
2455     str.truncate(0);
2456     fmt.format(2350.75, str);
2457     if (str == "Q 2,350.75") {
2458         logln(str);
2459     } else {
2460         dataerrln("Fail: adoptDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2461     }
2462 
2463     sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2464     if (U_FAILURE(ec)) {
2465         errln("Fail: DecimalFormatSymbols constructor");
2466         delete sym;
2467         return;
2468     }
2469     DecimalFormat fmt2(pat, sym, ec);
2470     if (U_FAILURE(ec)) {
2471         errln("Fail: DecimalFormat constructor");
2472         return;
2473     }
2474 
2475     DecimalFormatSymbols sym2(Locale::getUS(), ec);
2476     if (U_FAILURE(ec)) {
2477         errln("Fail: DecimalFormatSymbols constructor");
2478         return;
2479     }
2480     sym2.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2481     fmt2.setDecimalFormatSymbols(sym2);
2482 
2483     str.truncate(0);
2484     fmt2.format(2350.75, str);
2485     if (str == "Q 2,350.75") {
2486         logln(str);
2487     } else {
2488         dataerrln("Fail: setDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2489     }
2490 }
2491 
TestPerMill()2492 void NumberFormatTest::TestPerMill() {
2493     UErrorCode ec = U_ZERO_ERROR;
2494     UnicodeString str;
2495     DecimalFormat fmt(ctou("###.###\\u2030"), ec);
2496     if (!assertSuccess("DecimalFormat ct", ec)) return;
2497     assertEquals("0.4857 x ###.###\\u2030",
2498                  ctou("485.7\\u2030"), fmt.format(0.4857, str), true);
2499 
2500     DecimalFormatSymbols sym(Locale::getUS(), ec);
2501     if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2502         return;
2503     }
2504     sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
2505     DecimalFormat fmt2("", sym, ec);
2506     if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2507         return;
2508     }
2509     fmt2.applyLocalizedPattern("###.###m", ec);
2510     if (!assertSuccess("setup", ec)) return;
2511     str.truncate(0);
2512     assertEquals("0.4857 x ###.###m",
2513                  "485.7m", fmt2.format(0.4857, str));
2514 }
2515 
2516 /**
2517  * Generic test for patterns that should be legal/illegal.
2518  */
TestIllegalPatterns()2519 void NumberFormatTest::TestIllegalPatterns() {
2520     // Test cases:
2521     // Prefix with "-:" for illegal patterns
2522     // Prefix with "+:" for legal patterns
2523     const char* DATA[] = {
2524         // Unquoted special characters in the suffix are illegal
2525         "-:000.000|###",
2526         "+:000.000'|###'",
2527         0
2528     };
2529     for (int32_t i=0; DATA[i]; ++i) {
2530         const char* pat=DATA[i];
2531         UBool valid = (*pat) == '+';
2532         pat += 2;
2533         UErrorCode ec = U_ZERO_ERROR;
2534         DecimalFormat fmt(pat, ec); // locale doesn't matter here
2535         if (U_SUCCESS(ec) == valid) {
2536             logln("Ok: pattern \"%s\": %s",
2537                   pat, u_errorName(ec));
2538         } else {
2539             errcheckln(ec, "FAIL: pattern \"%s\" should have %s; got %s",
2540                   pat, (valid?"succeeded":"failed"),
2541                   u_errorName(ec));
2542         }
2543     }
2544 }
2545 
2546 //----------------------------------------------------------------------
2547 
2548 static const char* KEYWORDS[] = {
2549     /*0*/ "ref=", // <reference pattern to parse numbers>
2550     /*1*/ "loc=", // <locale for formats>
2551     /*2*/ "f:",   // <pattern or '-'> <number> <exp. string>
2552     /*3*/ "fp:",  // <pattern or '-'> <number> <exp. string> <exp. number>
2553     /*4*/ "rt:",  // <pattern or '-'> <(exp.) number> <(exp.) string>
2554     /*5*/ "p:",   // <pattern or '-'> <string> <exp. number>
2555     /*6*/ "perr:", // <pattern or '-'> <invalid string>
2556     /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
2557     /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2558     0
2559 };
2560 
2561 /**
2562  * Return an integer representing the next token from this
2563  * iterator.  The integer will be an index into the given list, or
2564  * -1 if there are no more tokens, or -2 if the token is not on
2565  * the list.
2566  */
keywordIndex(const UnicodeString & tok)2567 static int32_t keywordIndex(const UnicodeString& tok) {
2568     for (int32_t i=0; KEYWORDS[i]!=0; ++i) {
2569         if (tok==KEYWORDS[i]) {
2570             return i;
2571         }
2572     }
2573     return -1;
2574 }
2575 
2576 /**
2577  * Parse a CurrencyAmount using the given NumberFormat, with
2578  * the 'delim' character separating the number and the currency.
2579  */
parseCurrencyAmount(const UnicodeString & str,const NumberFormat & fmt,UChar delim,Formattable & result,UErrorCode & ec)2580 static void parseCurrencyAmount(const UnicodeString& str,
2581                                 const NumberFormat& fmt,
2582                                 UChar delim,
2583                                 Formattable& result,
2584                                 UErrorCode& ec) {
2585     UnicodeString num, cur;
2586     int32_t i = str.indexOf(delim);
2587     str.extractBetween(0, i, num);
2588     str.extractBetween(i+1, INT32_MAX, cur);
2589     Formattable n;
2590     fmt.parse(num, n, ec);
2591     result.adoptObject(new CurrencyAmount(n, cur.getTerminatedBuffer(), ec));
2592 }
2593 
TestCases()2594 void NumberFormatTest::TestCases() {
2595     UErrorCode ec = U_ZERO_ERROR;
2596     TextFile reader("NumberFormatTestCases.txt", "UTF8", ec);
2597     if (U_FAILURE(ec)) {
2598         dataerrln("Couldn't open NumberFormatTestCases.txt");
2599         return;
2600     }
2601     TokenIterator tokens(&reader);
2602 
2603     Locale loc("en", "US", "");
2604     DecimalFormat *ref = 0, *fmt = 0;
2605     MeasureFormat *mfmt = 0;
2606     UnicodeString pat, tok, mloc, str, out, where, currAmt;
2607     Formattable n;
2608 
2609     for (;;) {
2610         ec = U_ZERO_ERROR;
2611         if (!tokens.next(tok, ec)) {
2612             break;
2613         }
2614         where = UnicodeString("(") + tokens.getLineNumber() + ") ";
2615         int32_t cmd = keywordIndex(tok);
2616         switch (cmd) {
2617         case 0:
2618             // ref= <reference pattern>
2619             if (!tokens.next(tok, ec)) goto error;
2620             delete ref;
2621             ref = new DecimalFormat(tok,
2622                       new DecimalFormatSymbols(Locale::getUS(), ec), ec);
2623             if (U_FAILURE(ec)) {
2624                 dataerrln("Error constructing DecimalFormat");
2625                 goto error;
2626             }
2627             break;
2628         case 1:
2629             // loc= <locale>
2630             if (!tokens.next(tok, ec)) goto error;
2631             loc = Locale::createFromName(CharString().appendInvariantChars(tok, ec).data());
2632             break;
2633         case 2: // f:
2634         case 3: // fp:
2635         case 4: // rt:
2636         case 5: // p:
2637             if (!tokens.next(tok, ec)) goto error;
2638             if (tok != "-") {
2639                 pat = tok;
2640                 delete fmt;
2641                 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc, ec), ec);
2642                 if (U_FAILURE(ec)) {
2643                     errln("FAIL: " + where + "Pattern \"" + pat + "\": " + u_errorName(ec));
2644                     ec = U_ZERO_ERROR;
2645                     if (!tokens.next(tok, ec)) goto error;
2646                     if (!tokens.next(tok, ec)) goto error;
2647                     if (cmd == 3) {
2648                         if (!tokens.next(tok, ec)) goto error;
2649                     }
2650                     continue;
2651                 }
2652             }
2653             if (cmd == 2 || cmd == 3 || cmd == 4) {
2654                 // f: <pattern or '-'> <number> <exp. string>
2655                 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
2656                 // rt: <pattern or '-'> <number> <string>
2657                 UnicodeString num;
2658                 if (!tokens.next(num, ec)) goto error;
2659                 if (!tokens.next(str, ec)) goto error;
2660                 ref->parse(num, n, ec);
2661                 assertSuccess("parse", ec);
2662                 assertEquals(where + "\"" + pat + "\".format(" + num + ")",
2663                              str, fmt->format(n, out.remove(), ec));
2664                 assertSuccess("format", ec);
2665                 if (cmd == 3) { // fp:
2666                     if (!tokens.next(num, ec)) goto error;
2667                     ref->parse(num, n, ec);
2668                     assertSuccess("parse", ec);
2669                 }
2670                 if (cmd != 2) { // != f:
2671                     Formattable m;
2672                     fmt->parse(str, m, ec);
2673                     assertSuccess("parse", ec);
2674                     assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2675                                  n, m);
2676                 }
2677             }
2678             // p: <pattern or '-'> <string to parse> <exp. number>
2679             else {
2680                 UnicodeString expstr;
2681                 if (!tokens.next(str, ec)) goto error;
2682                 if (!tokens.next(expstr, ec)) goto error;
2683                 Formattable exp, n;
2684                 ref->parse(expstr, exp, ec);
2685                 assertSuccess("parse", ec);
2686                 fmt->parse(str, n, ec);
2687                 assertSuccess("parse", ec);
2688                 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2689                              exp, n);
2690             }
2691             break;
2692         case 8: // fpc:
2693             if (!tokens.next(tok, ec)) goto error;
2694             if (tok != "-") {
2695                 mloc = tok;
2696                 delete mfmt;
2697                 mfmt = MeasureFormat::createCurrencyFormat(
2698                     Locale::createFromName(
2699                         CharString().appendInvariantChars(mloc, ec).data()), ec);
2700                 if (U_FAILURE(ec)) {
2701                     errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
2702                     ec = U_ZERO_ERROR;
2703                     if (!tokens.next(tok, ec)) goto error;
2704                     if (!tokens.next(tok, ec)) goto error;
2705                     if (!tokens.next(tok, ec)) goto error;
2706                     continue;
2707                 }
2708             } else if (mfmt == NULL) {
2709                 errln("FAIL: " + where + "Loc \"" + mloc + "\": skip case using previous locale, no valid MeasureFormat");
2710                 if (!tokens.next(tok, ec)) goto error;
2711                 if (!tokens.next(tok, ec)) goto error;
2712                 if (!tokens.next(tok, ec)) goto error;
2713                 continue;
2714             }
2715             // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2716             if (!tokens.next(currAmt, ec)) goto error;
2717             if (!tokens.next(str, ec)) goto error;
2718             parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2719             if (assertSuccess("parseCurrencyAmount", ec)) {
2720                 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
2721                              str, mfmt->format(n, out.remove(), ec));
2722                 assertSuccess("format", ec);
2723             }
2724             if (!tokens.next(currAmt, ec)) goto error;
2725             parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2726             if (assertSuccess("parseCurrencyAmount", ec)) {
2727                 Formattable m;
2728 
2729                 mfmt->parseObject(str, m, ec);
2730                 if (assertSuccess("parseCurrency", ec)) {
2731                     assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
2732                                  n, m);
2733                 } else {
2734                     errln("FAIL: source " + str);
2735                 }
2736             }
2737             break;
2738         case 6:
2739             // perr: <pattern or '-'> <invalid string>
2740             errln("FAIL: Under construction");
2741             goto done;
2742         case 7: {
2743             // pat: <pattern> <exp. toPattern, or '-' or 'err'>
2744             UnicodeString testpat;
2745             UnicodeString exppat;
2746             if (!tokens.next(testpat, ec)) goto error;
2747             if (!tokens.next(exppat, ec)) goto error;
2748             UBool err = exppat == "err";
2749             UBool existingPat = FALSE;
2750             if (testpat == "-") {
2751                 if (err) {
2752                     errln("FAIL: " + where + "Invalid command \"pat: - err\"");
2753                     continue;
2754                 }
2755                 existingPat = TRUE;
2756                 testpat = pat;
2757             }
2758             if (exppat == "-") exppat = testpat;
2759             DecimalFormat* f = 0;
2760             UErrorCode ec2 = U_ZERO_ERROR;
2761             if (existingPat) {
2762                 f = fmt;
2763             } else {
2764                 f = new DecimalFormat(testpat, ec2);
2765             }
2766             if (U_SUCCESS(ec2)) {
2767                 if (err) {
2768                     errln("FAIL: " + where + "Invalid pattern \"" + testpat +
2769                           "\" was accepted");
2770                 } else {
2771                     UnicodeString pat2;
2772                     assertEquals(where + "\"" + testpat + "\".toPattern()",
2773                                  exppat, f->toPattern(pat2));
2774                 }
2775             } else {
2776                 if (err) {
2777                     logln("Ok: " + where + "Invalid pattern \"" + testpat +
2778                           "\" failed: " + u_errorName(ec2));
2779                 } else {
2780                     errln("FAIL: " + where + "Valid pattern \"" + testpat +
2781                           "\" failed: " + u_errorName(ec2));
2782                 }
2783             }
2784             if (!existingPat) delete f;
2785             } break;
2786         case -1:
2787             errln("FAIL: " + where + "Unknown command \"" + tok + "\"");
2788             goto done;
2789         }
2790     }
2791     goto done;
2792 
2793  error:
2794     if (U_SUCCESS(ec)) {
2795         errln("FAIL: Unexpected EOF");
2796     } else {
2797         errcheckln(ec, "FAIL: " + where + "Unexpected " + u_errorName(ec));
2798     }
2799 
2800  done:
2801     delete mfmt;
2802     delete fmt;
2803     delete ref;
2804 }
2805 
2806 
2807 //----------------------------------------------------------------------
2808 // Support methods
2809 //----------------------------------------------------------------------
2810 
equalValue(const Formattable & a,const Formattable & b)2811 UBool NumberFormatTest::equalValue(const Formattable& a, const Formattable& b) {
2812     if (a.getType() == b.getType()) {
2813         return a == b;
2814     }
2815 
2816     if (a.getType() == Formattable::kLong) {
2817         if (b.getType() == Formattable::kInt64) {
2818             return a.getLong() == b.getLong();
2819         } else if (b.getType() == Formattable::kDouble) {
2820             return (double) a.getLong() == b.getDouble(); // TODO check use of double instead of long
2821         }
2822     } else if (a.getType() == Formattable::kDouble) {
2823         if (b.getType() == Formattable::kLong) {
2824             return a.getDouble() == (double) b.getLong();
2825         } else if (b.getType() == Formattable::kInt64) {
2826             return a.getDouble() == (double)b.getInt64();
2827         }
2828     } else if (a.getType() == Formattable::kInt64) {
2829         if (b.getType() == Formattable::kLong) {
2830                 return a.getInt64() == (int64_t)b.getLong();
2831         } else if (b.getType() == Formattable::kDouble) {
2832             return a.getInt64() == (int64_t)b.getDouble();
2833         }
2834     }
2835     return FALSE;
2836 }
2837 
expect3(NumberFormat & fmt,const Formattable & n,const UnicodeString & str)2838 void NumberFormatTest::expect3(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2839     // Don't round-trip format test, since we explicitly do it
2840     expect_rbnf(fmt, n, str, FALSE);
2841     expect_rbnf(fmt, str, n);
2842 }
2843 
expect2(NumberFormat & fmt,const Formattable & n,const UnicodeString & str)2844 void NumberFormatTest::expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2845     // Don't round-trip format test, since we explicitly do it
2846     expect(fmt, n, str, FALSE);
2847     expect(fmt, str, n);
2848 }
2849 
expect2(NumberFormat * fmt,const Formattable & n,const UnicodeString & exp,UErrorCode status)2850 void NumberFormatTest::expect2(NumberFormat* fmt, const Formattable& n,
2851                                const UnicodeString& exp,
2852                                UErrorCode status) {
2853     if (fmt == NULL || U_FAILURE(status)) {
2854         dataerrln("FAIL: NumberFormat constructor");
2855     } else {
2856         expect2(*fmt, n, exp);
2857     }
2858     delete fmt;
2859 }
2860 
expect(NumberFormat & fmt,const UnicodeString & str,const Formattable & n)2861 void NumberFormatTest::expect(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2862     UErrorCode status = U_ZERO_ERROR;
2863     Formattable num;
2864     fmt.parse(str, num, status);
2865     if (U_FAILURE(status)) {
2866         dataerrln(UnicodeString("FAIL: Parse failed for \"") + str + "\" - " + u_errorName(status));
2867         return;
2868     }
2869     UnicodeString pat;
2870     ((DecimalFormat*) &fmt)->toPattern(pat);
2871     if (equalValue(num, n)) {
2872         logln(UnicodeString("Ok   \"") + str + "\" x " +
2873               pat + " = " +
2874               toString(num));
2875     } else {
2876         dataerrln(UnicodeString("FAIL \"") + str + "\" x " +
2877               pat + " = " +
2878               toString(num) + ", expected " + toString(n));
2879     }
2880 }
2881 
expect_rbnf(NumberFormat & fmt,const UnicodeString & str,const Formattable & n)2882 void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2883     UErrorCode status = U_ZERO_ERROR;
2884     Formattable num;
2885     fmt.parse(str, num, status);
2886     if (U_FAILURE(status)) {
2887         errln(UnicodeString("FAIL: Parse failed for \"") + str + "\"");
2888         return;
2889     }
2890     if (equalValue(num, n)) {
2891         logln(UnicodeString("Ok   \"") + str + " = " +
2892               toString(num));
2893     } else {
2894         errln(UnicodeString("FAIL \"") + str + " = " +
2895               toString(num) + ", expected " + toString(n));
2896     }
2897 }
2898 
expect_rbnf(NumberFormat & fmt,const Formattable & n,const UnicodeString & exp,UBool rt)2899 void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const Formattable& n,
2900                               const UnicodeString& exp, UBool rt) {
2901     UnicodeString saw;
2902     FieldPosition pos;
2903     UErrorCode status = U_ZERO_ERROR;
2904     fmt.format(n, saw, pos, status);
2905     CHECK(status, "NumberFormat::format");
2906     if (saw == exp) {
2907         logln(UnicodeString("Ok   ") + toString(n) +
2908               " = \"" +
2909               escape(saw) + "\"");
2910         // We should be able to round-trip the formatted string =>
2911         // number => string (but not the other way around: number
2912         // => string => number2, might have number2 != number):
2913         if (rt) {
2914             Formattable n2;
2915             fmt.parse(exp, n2, status);
2916             if (U_FAILURE(status)) {
2917                 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\"");
2918                 return;
2919             }
2920             UnicodeString saw2;
2921             fmt.format(n2, saw2, pos, status);
2922             CHECK(status, "NumberFormat::format");
2923             if (saw2 != exp) {
2924                 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2925                       " => \"" + saw2 + "\"");
2926             }
2927         }
2928     } else {
2929         errln(UnicodeString("FAIL ") + toString(n) +
2930               " = \"" +
2931               escape(saw) + "\", expected \"" + exp + "\"");
2932     }
2933 }
2934 
expect(NumberFormat & fmt,const Formattable & n,const UnicodeString & exp,UBool rt)2935 void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
2936                               const UnicodeString& exp, UBool rt) {
2937     UnicodeString saw;
2938     FieldPosition pos;
2939     UErrorCode status = U_ZERO_ERROR;
2940     fmt.format(n, saw, pos, status);
2941     CHECK(status, "NumberFormat::format");
2942     UnicodeString pat;
2943     ((DecimalFormat*) &fmt)->toPattern(pat);
2944     if (saw == exp) {
2945         logln(UnicodeString("Ok   ") + toString(n) + " x " +
2946               escape(pat) + " = \"" +
2947               escape(saw) + "\"");
2948         // We should be able to round-trip the formatted string =>
2949         // number => string (but not the other way around: number
2950         // => string => number2, might have number2 != number):
2951         if (rt) {
2952             Formattable n2;
2953             fmt.parse(exp, n2, status);
2954             if (U_FAILURE(status)) {
2955                 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\" - " + u_errorName(status));
2956                 return;
2957             }
2958             UnicodeString saw2;
2959             fmt.format(n2, saw2, pos, status);
2960             CHECK(status, "NumberFormat::format");
2961             if (saw2 != exp) {
2962                 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2963                       " => \"" + saw2 + "\"");
2964             }
2965         }
2966     } else {
2967         dataerrln(UnicodeString("FAIL ") + toString(n) + " x " +
2968               escape(pat) + " = \"" +
2969               escape(saw) + "\", expected \"" + exp + "\"");
2970     }
2971 }
2972 
expect(NumberFormat * fmt,const Formattable & n,const UnicodeString & exp,UBool rt,UErrorCode status)2973 void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
2974                               const UnicodeString& exp, UBool rt,
2975                               UErrorCode status) {
2976     if (fmt == NULL || U_FAILURE(status)) {
2977         dataerrln("FAIL: NumberFormat constructor");
2978     } else {
2979         expect(*fmt, n, exp, rt);
2980     }
2981     delete fmt;
2982 }
2983 
expectCurrency(NumberFormat & nf,const Locale & locale,double value,const UnicodeString & string)2984 void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
2985                                       double value, const UnicodeString& string) {
2986     UErrorCode ec = U_ZERO_ERROR;
2987     DecimalFormat& fmt = * (DecimalFormat*) &nf;
2988     const UChar DEFAULT_CURR[] = {45/*-*/,0};
2989     UChar curr[4];
2990     u_strcpy(curr, DEFAULT_CURR);
2991     if (*locale.getLanguage() != 0) {
2992         ucurr_forLocale(locale.getName(), curr, 4, &ec);
2993         assertSuccess("ucurr_forLocale", ec);
2994         fmt.setCurrency(curr, ec);
2995         assertSuccess("DecimalFormat::setCurrency", ec);
2996         fmt.setCurrency(curr); //Deprecated variant, for coverage only
2997     }
2998     UnicodeString s;
2999     fmt.format(value, s);
3000     s.findAndReplace((UChar32)0x00A0, (UChar32)0x0020);
3001 
3002     // Default display of the number yields "1234.5599999999999"
3003     // instead of "1234.56".  Use a formatter to fix this.
3004     NumberFormat* f =
3005         NumberFormat::createInstance(Locale::getUS(), ec);
3006     UnicodeString v;
3007     if (U_FAILURE(ec)) {
3008         // Oops; bad formatter.  Use default op+= display.
3009         v = (UnicodeString)"" + value;
3010     } else {
3011         f->setMaximumFractionDigits(4);
3012         f->setGroupingUsed(FALSE);
3013         f->format(value, v);
3014     }
3015     delete f;
3016 
3017     if (s == string) {
3018         logln((UnicodeString)"Ok: " + v + " x " + curr + " => " + prettify(s));
3019     } else {
3020         errln((UnicodeString)"FAIL: " + v + " x " + curr + " => " + prettify(s) +
3021               ", expected " + prettify(string));
3022     }
3023 }
3024 
expectPat(DecimalFormat & fmt,const UnicodeString & exp)3025 void NumberFormatTest::expectPat(DecimalFormat& fmt, const UnicodeString& exp) {
3026     UnicodeString pat;
3027     fmt.toPattern(pat);
3028     if (pat == exp) {
3029         logln(UnicodeString("Ok   \"") + pat + "\"");
3030     } else {
3031         errln(UnicodeString("FAIL \"") + pat + "\", expected \"" + exp + "\"");
3032     }
3033 }
3034 
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos)3035 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3036                                  int32_t pos) {
3037     expectPad(fmt, pat, pos, 0, (UnicodeString)"");
3038 }
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos,int32_t width,UChar pad)3039 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3040                                  int32_t pos, int32_t width, UChar pad) {
3041     expectPad(fmt, pat, pos, width, UnicodeString(pad));
3042 }
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos,int32_t width,const UnicodeString & pad)3043 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3044                                  int32_t pos, int32_t width, const UnicodeString& pad) {
3045     int32_t apos = 0, awidth = 0;
3046     UnicodeString apadStr;
3047     UErrorCode status = U_ZERO_ERROR;
3048     fmt.applyPattern(pat, status);
3049     if (U_SUCCESS(status)) {
3050         apos = fmt.getPadPosition();
3051         awidth = fmt.getFormatWidth();
3052         apadStr=fmt.getPadCharacterString();
3053     } else {
3054         apos = -1;
3055         awidth = width;
3056         apadStr = pad;
3057     }
3058     if (apos == pos && awidth == width && apadStr == pad) {
3059         UnicodeString infoStr;
3060         if (pos == ILLEGAL) {
3061             infoStr = UnicodeString(" width=", "") + awidth + UnicodeString(" pad=", "") + apadStr;
3062         }
3063         logln(UnicodeString("Ok   \"") + pat + "\" pos=" + apos + infoStr);
3064     } else {
3065         errln(UnicodeString("FAIL \"") + pat + "\" pos=" + apos +
3066               " width=" + awidth + " pad=" + apadStr +
3067               ", expected " + pos + " " + width + " " + pad);
3068     }
3069 }
3070 
3071 // This test is flaky b/c the symbols for CNY and JPY are equivalent in this locale  - FIXME
TestCompatibleCurrencies()3072 void NumberFormatTest::TestCompatibleCurrencies() {
3073 /*
3074     static const UChar JPY[] = {0x4A, 0x50, 0x59, 0};
3075     static const UChar CNY[] = {0x43, 0x4E, 0x59, 0};
3076     UErrorCode status = U_ZERO_ERROR;
3077     LocalPointer<NumberFormat> fmt(
3078         NumberFormat::createCurrencyInstance(Locale::getUS(), status));
3079     if (U_FAILURE(status)) {
3080         errln("Could not create number format instance.");
3081         return;
3082     }
3083     logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3084     expectParseCurrency(*fmt, JPY, 1235,  "\\u00A51,235");
3085     logln("%s:%d - testing parse of fullwidth yen sign\n", __FILE__, __LINE__);
3086     expectParseCurrency(*fmt, JPY, 1235,  "\\uFFE51,235");
3087     logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3088     expectParseCurrency(*fmt, CNY, 1235,  "CN\\u00A51,235");
3089 
3090     LocalPointer<NumberFormat> fmtTW(
3091         NumberFormat::createCurrencyInstance(Locale::getTaiwan(), status));
3092 
3093     logln("%s:%d - testing parse of halfwidth yen sign in TW\n", __FILE__, __LINE__);
3094     expectParseCurrency(*fmtTW, CNY, 1235,  "\\u00A51,235");
3095     logln("%s:%d - testing parse of fullwidth yen sign in TW\n", __FILE__, __LINE__);
3096     expectParseCurrency(*fmtTW, CNY, 1235,  "\\uFFE51,235");
3097 
3098     LocalPointer<NumberFormat> fmtJP(
3099         NumberFormat::createCurrencyInstance(Locale::getJapan(), status));
3100 
3101     logln("%s:%d - testing parse of halfwidth yen sign in JP\n", __FILE__, __LINE__);
3102     expectParseCurrency(*fmtJP, JPY, 1235,  "\\u00A51,235");
3103     logln("%s:%d - testing parse of fullwidth yen sign in JP\n", __FILE__, __LINE__);
3104     expectParseCurrency(*fmtJP, JPY, 1235,  "\\uFFE51,235");
3105 
3106     // more..
3107 */
3108 }
3109 
expectParseCurrency(const NumberFormat & fmt,const UChar * currency,double amount,const char * text)3110 void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text) {
3111     ParsePosition ppos;
3112     UnicodeString utext = ctou(text);
3113     LocalPointer<CurrencyAmount> currencyAmount(fmt.parseCurrency(utext, ppos));
3114     if (!ppos.getIndex()) {
3115         errln(UnicodeString("Parse of ") + utext + " should have succeeded.");
3116         return;
3117     }
3118     UErrorCode status = U_ZERO_ERROR;
3119 
3120     char theInfo[100];
3121     sprintf(theInfo, "For locale %s, string \"%s\", currency ",
3122             fmt.getLocale(ULOC_ACTUAL_LOCALE, status).getBaseName(),
3123             text);
3124     u_austrcpy(theInfo+uprv_strlen(theInfo), currency);
3125 
3126     char theOperation[100];
3127 
3128     uprv_strcpy(theOperation, theInfo);
3129     uprv_strcat(theOperation, ", check amount:");
3130     assertTrue(theOperation, amount ==  currencyAmount->getNumber().getDouble(status));
3131 
3132     uprv_strcpy(theOperation, theInfo);
3133     uprv_strcat(theOperation, ", check currency:");
3134     assertEquals(theOperation, currency, currencyAmount->getISOCurrency());
3135 }
3136 
3137 
TestJB3832()3138 void NumberFormatTest::TestJB3832(){
3139     const char* localeID = "pt_PT@currency=PTE";
3140     Locale loc(localeID);
3141     UErrorCode status = U_ZERO_ERROR;
3142     UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0\\u200B")); // per cldrbug 7670
3143     UnicodeString s;
3144     NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
3145     if(U_FAILURE(status)){
3146         dataerrln("Could not create currency formatter for locale %s - %s", localeID, u_errorName(status));
3147         return;
3148     }
3149     currencyFmt->format(1150.50, s);
3150     if(s!=expected){
3151         errln(UnicodeString("FAIL: Expected: ")+expected
3152                 + UnicodeString(" Got: ") + s
3153                 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
3154     }
3155     if (U_FAILURE(status)){
3156         errln("FAIL: Status %s", u_errorName(status));
3157     }
3158     delete currencyFmt;
3159 }
3160 
TestHost()3161 void NumberFormatTest::TestHost()
3162 {
3163 #if U_PLATFORM_USES_ONLY_WIN32_API
3164     Win32NumberTest::testLocales(this);
3165 #endif
3166     Locale loc("en_US@compat=host");
3167     for (UNumberFormatStyle k = UNUM_DECIMAL;
3168          k < UNUM_FORMAT_STYLE_COUNT; k = (UNumberFormatStyle)(k+1)) {
3169         UErrorCode status = U_ZERO_ERROR;
3170         LocalPointer<NumberFormat> full(NumberFormat::createInstance(loc, k, status));
3171         if (!NumberFormat::isStyleSupported(k)) {
3172             if (status != U_UNSUPPORTED_ERROR) {
3173                 errln("FAIL: expected style %d to be unsupported - %s",
3174                       k, u_errorName(status));
3175             }
3176             continue;
3177         }
3178         if (full.isNull() || U_FAILURE(status)) {
3179             dataerrln("FAIL: Can't create number instance of style %d for host - %s",
3180                       k, u_errorName(status));
3181             return;
3182         }
3183         UnicodeString result1;
3184         Formattable number(10.00);
3185         full->format(number, result1, status);
3186         if (U_FAILURE(status)) {
3187             errln("FAIL: Can't format for host");
3188             return;
3189         }
3190         Formattable formattable;
3191         full->parse(result1, formattable, status);
3192         if (U_FAILURE(status)) {
3193             errln("FAIL: Can't parse for host");
3194             return;
3195         }
3196     }
3197 }
3198 
TestHostClone()3199 void NumberFormatTest::TestHostClone()
3200 {
3201     /*
3202     Verify that a cloned formatter gives the same results
3203     and is useable after the original has been deleted.
3204     */
3205     // This is mainly important on Windows.
3206     UErrorCode status = U_ZERO_ERROR;
3207     Locale loc("en_US@compat=host");
3208     UDate now = Calendar::getNow();
3209     NumberFormat *full = NumberFormat::createInstance(loc, status);
3210     if (full == NULL || U_FAILURE(status)) {
3211         dataerrln("FAIL: Can't create NumberFormat date instance - %s", u_errorName(status));
3212         return;
3213     }
3214     UnicodeString result1;
3215     full->format(now, result1, status);
3216     Format *fullClone = full->clone();
3217     delete full;
3218     full = NULL;
3219 
3220     UnicodeString result2;
3221     fullClone->format(now, result2, status);
3222     if (U_FAILURE(status)) {
3223         errln("FAIL: format failure.");
3224     }
3225     if (result1 != result2) {
3226         errln("FAIL: Clone returned different result from non-clone.");
3227     }
3228     delete fullClone;
3229 }
3230 
TestCurrencyFormat()3231 void NumberFormatTest::TestCurrencyFormat()
3232 {
3233     // This test is here to increase code coverage.
3234     UErrorCode status = U_ZERO_ERROR;
3235     MeasureFormat *cloneObj;
3236     UnicodeString str;
3237     Formattable toFormat, result;
3238     static const UChar ISO_CODE[4] = {0x0047, 0x0042, 0x0050, 0};
3239 
3240     Locale  saveDefaultLocale = Locale::getDefault();
3241     Locale::setDefault( Locale::getUK(), status );
3242     if (U_FAILURE(status)) {
3243         errln("couldn't set default Locale!");
3244         return;
3245     }
3246 
3247     MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
3248     Locale::setDefault( saveDefaultLocale, status );
3249     if (U_FAILURE(status)){
3250         dataerrln("FAIL: Status %s", u_errorName(status));
3251         return;
3252     }
3253     cloneObj = measureObj->clone();
3254     if (cloneObj == NULL) {
3255         errln("Clone doesn't work");
3256         return;
3257     }
3258     toFormat.adoptObject(new CurrencyAmount(1234.56, ISO_CODE, status));
3259     measureObj->format(toFormat, str, status);
3260     measureObj->parseObject(str, result, status);
3261     if (U_FAILURE(status)){
3262         errln("FAIL: Status %s", u_errorName(status));
3263     }
3264     if (result != toFormat) {
3265         errln("measureObj does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3266     }
3267     status = U_ZERO_ERROR;
3268     str.truncate(0);
3269     cloneObj->format(toFormat, str, status);
3270     cloneObj->parseObject(str, result, status);
3271     if (U_FAILURE(status)){
3272         errln("FAIL: Status %s", u_errorName(status));
3273     }
3274     if (result != toFormat) {
3275         errln("Clone does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3276     }
3277     if (*measureObj != *cloneObj) {
3278         errln("Cloned object is not equal to the original object");
3279     }
3280     delete measureObj;
3281     delete cloneObj;
3282 
3283     status = U_USELESS_COLLATOR_ERROR;
3284     if (MeasureFormat::createCurrencyFormat(status) != NULL) {
3285         errln("createCurrencyFormat should have returned NULL.");
3286     }
3287 }
3288 
3289 /* Port of ICU4J rounding test. */
TestRounding()3290 void NumberFormatTest::TestRounding() {
3291     UErrorCode status = U_ZERO_ERROR;
3292     DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3293 
3294     if (U_FAILURE(status)) {
3295         dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3296         return;
3297     }
3298 
3299     int roundingIncrements[]={1, 2, 5, 20, 50, 100};
3300     int testValues[]={0, 300};
3301 
3302     for (int j=0; j<2; j++) {
3303         for (int mode=DecimalFormat::kRoundUp;mode<DecimalFormat::kRoundHalfEven;mode++) {
3304             df->setRoundingMode((DecimalFormat::ERoundingMode)mode);
3305             for (int increment=0; increment<6; increment++) {
3306                 double base=testValues[j];
3307                 double rInc=roundingIncrements[increment];
3308                 checkRounding(df, base, 20, rInc);
3309                 rInc=1.000000000/rInc;
3310                 checkRounding(df, base, 20, rInc);
3311             }
3312         }
3313     }
3314     delete df;
3315 }
3316 
TestRoundingPattern()3317 void NumberFormatTest::TestRoundingPattern() {
3318     UErrorCode status = U_ZERO_ERROR;
3319     struct {
3320         UnicodeString  pattern;
3321         double        testCase;
3322         UnicodeString expected;
3323     } tests[] = {
3324             { (UnicodeString)"##0.65", 1.234, (UnicodeString)"1.30" },
3325             { (UnicodeString)"#50",    1230,  (UnicodeString)"1250" }
3326     };
3327     int32_t numOfTests = UPRV_LENGTHOF(tests);
3328     UnicodeString result;
3329 
3330     DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3331     if (U_FAILURE(status)) {
3332         dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3333         return;
3334     }
3335 
3336     for (int32_t i = 0; i < numOfTests; i++) {
3337         result.remove();
3338 
3339         df->applyPattern(tests[i].pattern, status);
3340         if (U_FAILURE(status)) {
3341             errln("Unable to apply pattern to decimal formatter. - %s", u_errorName(status));
3342         }
3343 
3344         df->format(tests[i].testCase, result);
3345 
3346         if (result != tests[i].expected) {
3347             errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
3348         }
3349     }
3350 
3351     delete df;
3352 }
3353 
checkRounding(DecimalFormat * df,double base,int iterations,double increment)3354 void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
3355     df->setRoundingIncrement(increment);
3356     double lastParsed=INT32_MIN; //Intger.MIN_VALUE
3357     for (int i=-iterations; i<=iterations;i++) {
3358         double iValue=base+(increment*(i*0.1));
3359         double smallIncrement=0.00000001;
3360         if (iValue!=0) {
3361             smallIncrement*=iValue;
3362         }
3363         //we not only test the value, but some values in a small range around it
3364         lastParsed=checkRound(df, iValue-smallIncrement, lastParsed);
3365         lastParsed=checkRound(df, iValue, lastParsed);
3366         lastParsed=checkRound(df, iValue+smallIncrement, lastParsed);
3367     }
3368 }
3369 
checkRound(DecimalFormat * df,double iValue,double lastParsed)3370 double NumberFormatTest::checkRound(DecimalFormat* df, double iValue, double lastParsed) {
3371     UErrorCode status=U_ZERO_ERROR;
3372     UnicodeString formattedDecimal;
3373     double parsed;
3374     Formattable result;
3375     df->format(iValue, formattedDecimal, status);
3376 
3377     if (U_FAILURE(status)) {
3378         errln("Error formatting number.");
3379     }
3380 
3381     df->parse(formattedDecimal, result, status);
3382 
3383     if (U_FAILURE(status)) {
3384         errln("Error parsing number.");
3385     }
3386 
3387     parsed=result.getDouble();
3388 
3389     if (lastParsed>parsed) {
3390         errln("Rounding wrong direction! %d > %d", lastParsed, parsed);
3391     }
3392 
3393     return lastParsed;
3394 }
3395 
TestNonpositiveMultiplier()3396 void NumberFormatTest::TestNonpositiveMultiplier() {
3397     UErrorCode status = U_ZERO_ERROR;
3398     DecimalFormatSymbols US(Locale::getUS(), status);
3399     CHECK(status, "DecimalFormatSymbols constructor");
3400     DecimalFormat df(UnicodeString("0"), US, status);
3401     CHECK(status, "DecimalFormat(0)");
3402 
3403     // test zero multiplier
3404 
3405     int32_t mult = df.getMultiplier();
3406     df.setMultiplier(0);
3407     if (df.getMultiplier() != mult) {
3408         errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
3409     }
3410 
3411     // test negative multiplier
3412 
3413     df.setMultiplier(-1);
3414     if (df.getMultiplier() != -1) {
3415         errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
3416         return;
3417     }
3418 
3419     expect(df, "1122.123", -1122.123);
3420     expect(df, "-1122.123", 1122.123);
3421     expect(df, "1.2", -1.2);
3422     expect(df, "-1.2", 1.2);
3423 
3424     // Note:  the tests with the final parameter of FALSE will not round trip.
3425     //        The initial numeric value will format correctly, after the multiplier.
3426     //        Parsing the formatted text will be out-of-range for an int64, however.
3427     //        The expect() function could be modified to detect this and fall back
3428     //        to looking at the decimal parsed value, but it doesn't.
3429     expect(df, U_INT64_MIN,    "9223372036854775808", FALSE);
3430     expect(df, U_INT64_MIN+1,  "9223372036854775807");
3431     expect(df, (int64_t)-123,                  "123");
3432     expect(df, (int64_t)123,                  "-123");
3433     expect(df, U_INT64_MAX-1, "-9223372036854775806");
3434     expect(df, U_INT64_MAX,   "-9223372036854775807");
3435 
3436     df.setMultiplier(-2);
3437     expect(df, -(U_INT64_MIN/2)-1, "-9223372036854775806");
3438     expect(df, -(U_INT64_MIN/2),   "-9223372036854775808");
3439     expect(df, -(U_INT64_MIN/2)+1, "-9223372036854775810", FALSE);
3440 
3441     df.setMultiplier(-7);
3442     expect(df, -(U_INT64_MAX/7)-1, "9223372036854775814", FALSE);
3443     expect(df, -(U_INT64_MAX/7),   "9223372036854775807");
3444     expect(df, -(U_INT64_MAX/7)+1, "9223372036854775800");
3445 
3446     // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
3447     // (right now the big numbers get turned into doubles and lose tons of accuracy)
3448     //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
3449     //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
3450     //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
3451     //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
3452 
3453     // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
3454     //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3455     //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3456     //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3457     //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3458 }
3459 
3460 typedef struct {
3461     const char * stringToParse;
3462     int          parsedPos;
3463     int          errorIndex;
3464     UBool        lenient;
3465 } TestSpaceParsingItem;
3466 
3467 void
TestSpaceParsing()3468 NumberFormatTest::TestSpaceParsing() {
3469     // the data are:
3470     // the string to be parsed, parsed position, parsed error index
3471     const TestSpaceParsingItem DATA[] = {
3472         {"$124",           4, -1, FALSE},
3473         {"$124 $124",      4, -1, FALSE},
3474         {"$124 ",          4, -1, FALSE},
3475         {"$ 124 ",         0,  1, FALSE},
3476         {"$\\u00A0124 ",   5, -1, FALSE},
3477         {" $ 124 ",        0,  0, FALSE},
3478         {"124$",           0,  4, FALSE},
3479         {"124 $",          0,  3, FALSE},
3480         {"$124",           4, -1, TRUE},
3481         {"$124 $124",      4, -1, TRUE},
3482         {"$124 ",          4, -1, TRUE},
3483         {"$ 124 ",         5, -1, TRUE},
3484         {"$\\u00A0124 ",   5, -1, TRUE},
3485         {" $ 124 ",        6, -1, TRUE},
3486         {"124$",           4, -1, TRUE},
3487         {"124$",           4, -1, TRUE},
3488         {"124 $",          5, -1, TRUE},
3489         {"124 $",          5, -1, TRUE},
3490     };
3491     UErrorCode status = U_ZERO_ERROR;
3492     Locale locale("en_US");
3493     NumberFormat* foo = NumberFormat::createCurrencyInstance(locale, status);
3494 
3495     if (U_FAILURE(status)) {
3496         delete foo;
3497         return;
3498     }
3499     for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3500         ParsePosition parsePosition(0);
3501         UnicodeString stringToBeParsed = ctou(DATA[i].stringToParse);
3502         int parsedPosition = DATA[i].parsedPos;
3503         int errorIndex = DATA[i].errorIndex;
3504         foo->setLenient(DATA[i].lenient);
3505         Formattable result;
3506         foo->parse(stringToBeParsed, result, parsePosition);
3507         logln("Parsing: " + stringToBeParsed);
3508         if (parsePosition.getIndex() != parsedPosition ||
3509             parsePosition.getErrorIndex() != errorIndex) {
3510             errln("FAILED parse " + stringToBeParsed + "; lenient: " + DATA[i].lenient + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
3511         }
3512         if (parsePosition.getErrorIndex() == -1 &&
3513             result.getType() == Formattable::kLong &&
3514             result.getLong() != 124) {
3515             errln("FAILED parse " + stringToBeParsed + "; wrong number, expect: 124, got " + result.getLong());
3516         }
3517     }
3518     delete foo;
3519 }
3520 
3521 /**
3522  * Test using various numbering systems and numbering system keyword.
3523  */
3524 typedef struct {
3525     const char *localeName;
3526     double      value;
3527     UBool        isRBNF;
3528     const char *expectedResult;
3529 } TestNumberingSystemItem;
3530 
TestNumberingSystems()3531 void NumberFormatTest::TestNumberingSystems() {
3532 
3533     const TestNumberingSystemItem DATA[] = {
3534         { "en_US@numbers=thai", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" },
3535         { "en_US@numbers=hebr", 5678.0, TRUE, "\\u05D4\\u05F3\\u05EA\\u05E8\\u05E2\\u05F4\\u05D7" },
3536         { "en_US@numbers=arabext", 1234.567, FALSE, "\\u06F1\\u066c\\u06F2\\u06F3\\u06F4\\u066b\\u06F5\\u06F6\\u06F7" },
3537         { "ar_EG", 1234.567, FALSE, "\\u0661\\u066C\\u0662\\u0663\\u0664\\u066b\\u0665\\u0666\\u0667" },
3538         { "th_TH@numbers=traditional", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" }, // fall back to native per TR35
3539         { "ar_MA", 1234.567, FALSE, "1.234,567" },
3540         { "en_US@numbers=hanidec", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3541         { "ta_IN@numbers=native", 1234.567, FALSE, "\\u0BE7,\\u0BE8\\u0BE9\\u0BEA.\\u0BEB\\u0BEC\\u0BED" },
3542         { "ta_IN@numbers=traditional", 1235.0, TRUE, "\\u0BF2\\u0BE8\\u0BF1\\u0BE9\\u0BF0\\u0BEB" },
3543         { "ta_IN@numbers=finance", 1234.567, FALSE, "1,234.567" }, // fall back to default per TR35
3544         { "zh_TW@numbers=native", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3545         { "zh_TW@numbers=traditional", 1234.567, TRUE, "\\u4E00\\u5343\\u4E8C\\u767E\\u4E09\\u5341\\u56DB\\u9EDE\\u4E94\\u516D\\u4E03" },
3546         { "zh_TW@numbers=finance", 1234.567, TRUE, "\\u58F9\\u4EDF\\u8CB3\\u4F70\\u53C3\\u62FE\\u8086\\u9EDE\\u4F0D\\u9678\\u67D2" },
3547         { NULL, 0, FALSE, NULL }
3548     };
3549 
3550     UErrorCode ec;
3551 
3552     const TestNumberingSystemItem *item;
3553     for (item = DATA; item->localeName != NULL; item++) {
3554         ec = U_ZERO_ERROR;
3555         Locale loc = Locale::createFromName(item->localeName);
3556 
3557         NumberFormat *origFmt = NumberFormat::createInstance(loc,ec);
3558         if (U_FAILURE(ec)) {
3559             dataerrln("FAIL: getInstance(%s) - %s", item->localeName, u_errorName(ec));
3560             continue;
3561         }
3562         // Clone to test ticket #10682
3563         NumberFormat *fmt = origFmt->clone();
3564         delete origFmt;
3565 
3566 
3567         if (item->isRBNF) {
3568             expect3(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3569         } else {
3570             expect2(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3571         }
3572         delete fmt;
3573     }
3574 
3575 
3576     // Test bogus keyword value
3577     ec = U_ZERO_ERROR;
3578     Locale loc4 = Locale::createFromName("en_US@numbers=foobar");
3579     NumberFormat* fmt4= NumberFormat::createInstance(loc4, ec);
3580     if ( ec != U_UNSUPPORTED_ERROR ) {
3581         errln("FAIL: getInstance(en_US@numbers=foobar) should have returned U_UNSUPPORTED_ERROR");
3582         delete fmt4;
3583     }
3584 
3585     ec = U_ZERO_ERROR;
3586     NumberingSystem *ns = NumberingSystem::createInstance(ec);
3587     if (U_FAILURE(ec)) {
3588         dataerrln("FAIL: NumberingSystem::createInstance(ec); - %s", u_errorName(ec));
3589     }
3590 
3591     if ( ns != NULL ) {
3592         ns->getDynamicClassID();
3593         ns->getStaticClassID();
3594     } else {
3595         errln("FAIL: getInstance() returned NULL.");
3596     }
3597 
3598     NumberingSystem *ns1 = new NumberingSystem(*ns);
3599     if (ns1 == NULL) {
3600         errln("FAIL: NumberSystem copy constructor returned NULL.");
3601     }
3602 
3603     delete ns1;
3604     delete ns;
3605 
3606 }
3607 
3608 
3609 void
TestMultiCurrencySign()3610 NumberFormatTest::TestMultiCurrencySign() {
3611     const char* DATA[][6] = {
3612         // the fields in the following test are:
3613         // locale,
3614         // currency pattern (with negative pattern),
3615         // currency number to be formatted,
3616         // currency format using currency symbol name, such as "$" for USD,
3617         // currency format using currency ISO name, such as "USD",
3618         // currency format using plural name, such as "US dollars".
3619         // for US locale
3620         {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1234.56", "$1,234.56", "USD\\u00A01,234.56", "US dollars\\u00A01,234.56"},
3621         {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD\\u00A01,234.56", "-US dollars\\u00A01,234.56"},
3622         {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD\\u00A01.00", "US dollars\\u00A01.00"},
3623         // for CHINA locale
3624         {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\u00A51,234.56", "CNY\\u00A01,234.56", "\\u4EBA\\u6C11\\u5E01\\u00A01,234.56"},
3625         {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\u00A51,234.56)", "(CNY\\u00A01,234.56)", "(\\u4EBA\\u6C11\\u5E01\\u00A01,234.56)"},
3626         {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\u00A51.00", "CNY\\u00A01.00", "\\u4EBA\\u6C11\\u5E01\\u00A01.00"}
3627     };
3628 
3629     const UChar doubleCurrencySign[] = {0xA4, 0xA4, 0};
3630     UnicodeString doubleCurrencyStr(doubleCurrencySign);
3631     const UChar tripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
3632     UnicodeString tripleCurrencyStr(tripleCurrencySign);
3633 
3634     for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3635         const char* locale = DATA[i][0];
3636         UnicodeString pat = ctou(DATA[i][1]);
3637         double numberToBeFormat = atof(DATA[i][2]);
3638         UErrorCode status = U_ZERO_ERROR;
3639         DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale(locale), status);
3640         if (U_FAILURE(status)) {
3641             delete sym;
3642             continue;
3643         }
3644         for (int j=1; j<=3; ++j) {
3645             // j represents the number of currency sign in the pattern.
3646             if (j == 2) {
3647                 pat = pat.findAndReplace(ctou("\\u00A4"), doubleCurrencyStr);
3648             } else if (j == 3) {
3649                 pat = pat.findAndReplace(ctou("\\u00A4\\u00A4"), tripleCurrencyStr);
3650             }
3651 
3652             DecimalFormat* fmt = new DecimalFormat(pat, new DecimalFormatSymbols(*sym), status);
3653             if (U_FAILURE(status)) {
3654                 errln("FAILED init DecimalFormat ");
3655                 delete fmt;
3656                 continue;
3657             }
3658             UnicodeString s;
3659             ((NumberFormat*) fmt)->format(numberToBeFormat, s);
3660             // DATA[i][3] is the currency format result using a
3661             // single currency sign.
3662             // DATA[i][4] is the currency format result using
3663             // double currency sign.
3664             // DATA[i][5] is the currency format result using
3665             // triple currency sign.
3666             // DATA[i][j+2] is the currency format result using
3667             // 'j' number of currency sign.
3668             UnicodeString currencyFormatResult = ctou(DATA[i][2+j]);
3669             if (s.compare(currencyFormatResult)) {
3670                 errln("FAIL format: Expected " + currencyFormatResult + "; Got " + s);
3671             }
3672             // mix style parsing
3673             for (int k=3; k<=5; ++k) {
3674               // DATA[i][3] is the currency format result using a
3675               // single currency sign.
3676               // DATA[i][4] is the currency format result using
3677               // double currency sign.
3678               // DATA[i][5] is the currency format result using
3679               // triple currency sign.
3680               UnicodeString oneCurrencyFormat = ctou(DATA[i][k]);
3681               UErrorCode status = U_ZERO_ERROR;
3682               Formattable parseRes;
3683               fmt->parse(oneCurrencyFormat, parseRes, status);
3684               if (U_FAILURE(status) ||
3685                   (parseRes.getType() == Formattable::kDouble &&
3686                    parseRes.getDouble() != numberToBeFormat) ||
3687                   (parseRes.getType() == Formattable::kLong &&
3688                    parseRes.getLong() != numberToBeFormat)) {
3689                   errln("FAILED parse " + oneCurrencyFormat + "; (i, j, k): " +
3690                         i + ", " + j + ", " + k);
3691               }
3692             }
3693             delete fmt;
3694         }
3695         delete sym;
3696     }
3697 }
3698 
3699 
3700 void
TestCurrencyFormatForMixParsing()3701 NumberFormatTest::TestCurrencyFormatForMixParsing() {
3702     UErrorCode status = U_ZERO_ERROR;
3703     MeasureFormat* curFmt = MeasureFormat::createCurrencyFormat(Locale("en_US"), status);
3704     if (U_FAILURE(status)) {
3705         delete curFmt;
3706         return;
3707     }
3708     const char* formats[] = {
3709         "$1,234.56",  // string to be parsed
3710         "USD1,234.56",
3711         "US dollars1,234.56",
3712         // "1,234.56 US dollars" // Fails in 62 because currency format is not compatible with pattern.
3713     };
3714     const CurrencyAmount* curramt = NULL;
3715     for (uint32_t i = 0; i < UPRV_LENGTHOF(formats); ++i) {
3716         UnicodeString stringToBeParsed = ctou(formats[i]);
3717         logln(UnicodeString("stringToBeParsed: ") + stringToBeParsed);
3718         Formattable result;
3719         UErrorCode status = U_ZERO_ERROR;
3720         curFmt->parseObject(stringToBeParsed, result, status);
3721         if (U_FAILURE(status)) {
3722           errln("FAIL: measure format parsing: '%s' ec: %s", formats[i], u_errorName(status));
3723         } else if (result.getType() != Formattable::kObject ||
3724             (curramt = dynamic_cast<const CurrencyAmount*>(result.getObject())) == NULL ||
3725             curramt->getNumber().getDouble() != 1234.56 ||
3726             UnicodeString(curramt->getISOCurrency()).compare(ISO_CURRENCY_USD)
3727         ) {
3728             errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number ");
3729             if (curramt->getNumber().getDouble() != 1234.56) {
3730                 errln((UnicodeString)"wong number, expect: 1234.56" + ", got: " + curramt->getNumber().getDouble());
3731             }
3732             if (curramt->getISOCurrency() != ISO_CURRENCY_USD) {
3733                 errln((UnicodeString)"wong currency, expect: USD" + ", got: " + curramt->getISOCurrency());
3734             }
3735         }
3736     }
3737     delete curFmt;
3738 }
3739 
3740 
3741 /** Starting in ICU 62, strict mode is actually strict with currency formats. */
TestMismatchedCurrencyFormatFail()3742 void NumberFormatTest::TestMismatchedCurrencyFormatFail() {
3743     IcuTestErrorCode status(*this, "TestMismatchedCurrencyFormatFail");
3744     LocalPointer<DecimalFormat> df(
3745             dynamic_cast<DecimalFormat*>(DecimalFormat::createCurrencyInstance("en", status)), status);
3746     if (!assertSuccess("createCurrencyInstance() failed.", status, true, __FILE__, __LINE__)) {return;}
3747     UnicodeString pattern;
3748     assertEquals("Test assumes that currency sign is at the beginning",
3749             u"\u00A4#,##0.00",
3750             df->toPattern(pattern));
3751     // Should round-trip on the correct currency format:
3752     expect2(*df, 1.23, u"\u00A41.23");
3753     df->setCurrency(u"EUR", status);
3754     expect2(*df, 1.23, u"\u20AC1.23");
3755     // Should parse with currency in the wrong place in lenient mode
3756     df->setLenient(TRUE);
3757     expect(*df, u"1.23\u20AC", 1.23);
3758     expectParseCurrency(*df, u"EUR", 1.23, "1.23\\u20AC");
3759     // Should NOT parse with currency in the wrong place in STRICT mode
3760     df->setLenient(FALSE);
3761     {
3762         Formattable result;
3763         ErrorCode failStatus;
3764         df->parse(u"1.23\u20AC", result, failStatus);
3765         assertEquals("Should fail to parse", U_INVALID_FORMAT_ERROR, failStatus);
3766     }
3767     {
3768         ParsePosition ppos;
3769         df->parseCurrency(u"1.23\u20AC", ppos);
3770         assertEquals("Should fail to parse currency", 0, ppos.getIndex());
3771     }
3772 }
3773 
3774 
3775 void
TestDecimalFormatCurrencyParse()3776 NumberFormatTest::TestDecimalFormatCurrencyParse() {
3777     // Locale.US
3778     UErrorCode status = U_ZERO_ERROR;
3779     DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale("en_US"), status);
3780     if (U_FAILURE(status)) {
3781         delete sym;
3782         return;
3783     }
3784     UnicodeString pat;
3785     UChar currency = 0x00A4;
3786     // "\xA4#,##0.00;-\xA4#,##0.00"
3787     pat.append(currency).append(currency).append(currency).append("#,##0.00;-").append(currency).append(currency).append(currency).append("#,##0.00");
3788     DecimalFormat* fmt = new DecimalFormat(pat, sym, status);
3789     if (U_FAILURE(status)) {
3790         delete fmt;
3791         errln("failed to new DecimalFormat in TestDecimalFormatCurrencyParse");
3792         return;
3793     }
3794     const char* DATA[][2] = {
3795         // the data are:
3796         // string to be parsed, the parsed result (number)
3797         {"$1.00", "1"},
3798         {"USD1.00", "1"},
3799         {"1.00 US dollar", "1"},
3800         {"$1,234.56", "1234.56"},
3801         {"USD1,234.56", "1234.56"},
3802         {"1,234.56 US dollar", "1234.56"},
3803     };
3804     // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3805     fmt->setLenient(TRUE);
3806     for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3807         UnicodeString stringToBeParsed = ctou(DATA[i][0]);
3808         double parsedResult = atof(DATA[i][1]);
3809         UErrorCode status = U_ZERO_ERROR;
3810         Formattable result;
3811         fmt->parse(stringToBeParsed, result, status);
3812         logln((UnicodeString)"Input: " + stringToBeParsed + "; output: " + result.getDouble(status));
3813         if (U_FAILURE(status) ||
3814             (result.getType() == Formattable::kDouble &&
3815             result.getDouble() != parsedResult) ||
3816             (result.getType() == Formattable::kLong &&
3817             result.getLong() != parsedResult)) {
3818             errln((UnicodeString)"FAIL parse: Expected " + parsedResult);
3819         }
3820     }
3821     delete fmt;
3822 }
3823 
3824 
3825 void
TestCurrencyIsoPluralFormat()3826 NumberFormatTest::TestCurrencyIsoPluralFormat() {
3827     static const char* DATA[][6] = {
3828         // the data are:
3829         // locale,
3830         // currency amount to be formatted,
3831         // currency ISO code to be formatted,
3832         // format result using CURRENCYSTYLE,
3833         // format result using ISOCURRENCYSTYLE,
3834         // format result using PLURALCURRENCYSTYLE,
3835 
3836         {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3837         {"en_US", "1234.56", "USD", "$1,234.56", "USD\\u00A01,234.56", "1,234.56 US dollars"},
3838         {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD\\u00A01,234.56", "-1,234.56 US dollars"},
3839         {"zh_CN", "1", "USD", "US$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7F8E\\u5143"},
3840         {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD\\u00A01,234.56", "1,234.56\\u00A0\\u7F8E\\u5143"},
3841         {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A01.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3842         {"zh_CN", "1234.56", "CNY", "\\u00A51,234.56", "CNY\\u00A01,234.56", "1,234.56\\u00A0\\u4EBA\\u6C11\\u5E01"},
3843         {"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"},
3844         {"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"},
3845         {"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"},
3846         // test locale without currency information
3847         {"root", "-1.23", "USD", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"},
3848         // test choice format
3849         {"es_AR", "1", "INR", "INR\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"},
3850     };
3851     static const UNumberFormatStyle currencyStyles[] = {
3852         UNUM_CURRENCY,
3853         UNUM_CURRENCY_ISO,
3854         UNUM_CURRENCY_PLURAL
3855     };
3856 
3857     for (int32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3858       const char* localeString = DATA[i][0];
3859       double numberToBeFormat = atof(DATA[i][1]);
3860       const char* currencyISOCode = DATA[i][2];
3861       logln(UnicodeString(u"Locale: ") + localeString + "; amount: " + numberToBeFormat);
3862       Locale locale(localeString);
3863       for (int32_t kIndex = 0; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3864         UNumberFormatStyle k = currencyStyles[kIndex];
3865         logln(UnicodeString(u"UNumberFormatStyle: ") + k);
3866         UErrorCode status = U_ZERO_ERROR;
3867         NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3868         if (U_FAILURE(status)) {
3869             delete numFmt;
3870             dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3871             continue;
3872         }
3873         UChar currencyCode[4];
3874         u_charsToUChars(currencyISOCode, currencyCode, 4);
3875         numFmt->setCurrency(currencyCode, status);
3876         if (U_FAILURE(status)) {
3877             delete numFmt;
3878             errln((UnicodeString)"can not set currency:" + currencyISOCode);
3879             continue;
3880         }
3881 
3882         UnicodeString strBuf;
3883         numFmt->format(numberToBeFormat, strBuf);
3884         int resultDataIndex = 3 + kIndex;
3885         // DATA[i][resultDataIndex] is the currency format result
3886         // using 'k' currency style.
3887         UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
3888         if (strBuf.compare(formatResult)) {
3889             errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
3890         }
3891         // test parsing, and test parsing for all currency formats.
3892         // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3893         numFmt->setLenient(TRUE);
3894         for (int j = 3; j < 6; ++j) {
3895             // DATA[i][3] is the currency format result using
3896             // CURRENCYSTYLE formatter.
3897             // DATA[i][4] is the currency format result using
3898             // ISOCURRENCYSTYLE formatter.
3899             // DATA[i][5] is the currency format result using
3900             // PLURALCURRENCYSTYLE formatter.
3901             UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
3902             UErrorCode status = U_ZERO_ERROR;
3903             Formattable parseResult;
3904             numFmt->parse(oneCurrencyFormatResult, parseResult, status);
3905             if (U_FAILURE(status) ||
3906                 (parseResult.getType() == Formattable::kDouble &&
3907                  parseResult.getDouble() != numberToBeFormat) ||
3908                 (parseResult.getType() == Formattable::kLong &&
3909                  parseResult.getLong() != numberToBeFormat)) {
3910                 errln((UnicodeString)"FAIL: getCurrencyFormat of locale " +
3911                       localeString + " failed roundtripping the number");
3912                 if (parseResult.getType() == Formattable::kDouble) {
3913                     errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getDouble());
3914                 } else {
3915                     errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getLong());
3916                 }
3917             }
3918         }
3919         delete numFmt;
3920       }
3921     }
3922 }
3923 
3924 void
TestCurrencyParsing()3925 NumberFormatTest::TestCurrencyParsing() {
3926     static const char* DATA[][6] = {
3927         // the data are:
3928         // locale,
3929         // currency amount to be formatted,
3930         // currency ISO code to be formatted,
3931         // format result using CURRENCYSTYLE,
3932         // format result using ISOCURRENCYSTYLE,
3933         // format result using PLURALCURRENCYSTYLE,
3934         {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3935         {"pa_IN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\u0a2f\\u0a42.\\u0a10\\u0a38. \\u0a21\\u0a3e\\u0a32\\u0a30"},
3936         {"es_AR", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 d\\u00f3lar estadounidense"},
3937         {"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"},
3938         {"fa_CA", "1", "USD", "\\u200e$\\u06f1\\u066b\\u06f0\\u06f0", "\\u200eUSD\\u06f1\\u066b\\u06f0\\u06f0", "\\u06f1\\u066b\\u06f0\\u06f0 \\u062f\\u0644\\u0627\\u0631 \\u0627\\u0645\\u0631\\u06cc\\u06a9\\u0627"},
3939         {"he_IL", "1", "USD", "\\u200f1.00\\u00a0$", "\\u200f1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
3940         {"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 ameri\\u010Dkih dolara"},
3941         {"id_ID", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 Dolar Amerika Serikat"},
3942         {"it_IT", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 dollari statunitensi"},
3943         {"ko_KR", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
3944         {"ja_JP", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7c73\\u30c9\\u30eb"},
3945         {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A001.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3946         {"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3947         {"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3948         {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1 \\u65E5\\u5713"},
3949         {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3950         // ICU 62 requires #parseCurrency() to recognize variants when parsing
3951         // {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3952         {"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"}
3953     };
3954     static const UNumberFormatStyle currencyStyles[] = {
3955         UNUM_CURRENCY,
3956         UNUM_CURRENCY_ISO,
3957         UNUM_CURRENCY_PLURAL
3958     };
3959     static const char* currencyStyleNames[] = {
3960       "UNUM_CURRENCY",
3961       "UNUM_CURRENCY_ISO",
3962       "UNUM_CURRENCY_PLURAL"
3963     };
3964 
3965 #ifdef NUMFMTST_CACHE_DEBUG
3966 int deadloop = 0;
3967 for (;;) {
3968     printf("loop: %d\n", deadloop++);
3969 #endif
3970     for (uint32_t i=0; i< UPRV_LENGTHOF(DATA); ++i) {  /* i = test case #  - should be i=0*/
3971       for (int32_t kIndex = 2; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3972         UNumberFormatStyle k = currencyStyles[kIndex]; /* k = style */
3973         const char* localeString = DATA[i][0];
3974         double numberToBeFormat = atof(DATA[i][1]);
3975         const char* currencyISOCode = DATA[i][2];
3976         Locale locale(localeString);
3977         UErrorCode status = U_ZERO_ERROR;
3978         NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3979         logln("#%d NumberFormat(%s, %s) Currency=%s\n",
3980               i, localeString, currencyStyleNames[kIndex],
3981               currencyISOCode);
3982 
3983         if (U_FAILURE(status)) {
3984             delete numFmt;
3985             dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3986             continue;
3987         }
3988         UChar currencyCode[4];
3989         u_charsToUChars(currencyISOCode, currencyCode, 4);
3990         numFmt->setCurrency(currencyCode, status);
3991         if (U_FAILURE(status)) {
3992             delete numFmt;
3993             errln((UnicodeString)"can not set currency:" + currencyISOCode);
3994             continue;
3995         }
3996 
3997         UnicodeString strBuf;
3998         numFmt->format(numberToBeFormat, strBuf);
3999         int resultDataIndex = 3 + kIndex;
4000         // DATA[i][resultDataIndex] is the currency format result
4001         // using 'k' currency style.
4002         UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
4003         if (strBuf.compare(formatResult)) {
4004             errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
4005         }
4006         // test parsing, and test parsing for all currency formats.
4007         // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
4008         numFmt->setLenient(TRUE);
4009         for (int j = 3; j < 6; ++j) {
4010             // DATA[i][3] is the currency format result using
4011             // CURRENCYSTYLE formatter.
4012             // DATA[i][4] is the currency format result using
4013             // ISOCURRENCYSTYLE formatter.
4014             // DATA[i][5] is the currency format result using
4015             // PLURALCURRENCYSTYLE formatter.
4016             UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
4017             UErrorCode status = U_ZERO_ERROR;
4018             Formattable parseResult;
4019             logln("parse(%s)", DATA[i][j]);
4020             numFmt->parse(oneCurrencyFormatResult, parseResult, status);
4021             if (U_FAILURE(status) ||
4022                 (parseResult.getType() == Formattable::kDouble &&
4023                  parseResult.getDouble() != numberToBeFormat) ||
4024                 (parseResult.getType() == Formattable::kLong &&
4025                  parseResult.getLong() != numberToBeFormat)) {
4026                 errln((UnicodeString)"FAIL: NumberFormat(" + localeString +", " + currencyStyleNames[kIndex] +
4027                       "), Currency="+currencyISOCode+", parse("+DATA[i][j]+") returned error " + (UnicodeString)u_errorName(status)+".  Testcase: data[" + i + "][" + currencyStyleNames[j-3] +"="+j+"]");
4028                 if (parseResult.getType() == Formattable::kDouble) {
4029                     errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (double): " +parseResult.getDouble());
4030                 } else {
4031                     errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (long): " +parseResult.getLong());
4032                 }
4033                 errln((UnicodeString)" round-trip would be: " + strBuf);
4034             }
4035         }
4036         delete numFmt;
4037       }
4038     }
4039 #ifdef NUMFMTST_CACHE_DEBUG
4040 }
4041 #endif
4042 }
4043 
4044 
4045 void
TestParseCurrencyInUCurr()4046 NumberFormatTest::TestParseCurrencyInUCurr() {
4047     const char* DATA[] = {
4048         "1.00 US DOLLAR",  // case in-sensitive
4049         "$1.00",
4050         "USD1.00",
4051         "usd1.00", // case in-sensitive: #13696
4052         "US dollar1.00",
4053         "US dollars1.00",
4054         "$1.00",
4055         "A$1.00",
4056         "ADP1.00",
4057         "ADP1.00",
4058         "AED1.00",
4059         "AED1.00",
4060         "AFA1.00",
4061         "AFA1.00",
4062         "AFN1.00",
4063         "ALL1.00",
4064         "AMD1.00",
4065         "ANG1.00",
4066         "AOA1.00",
4067         "AOK1.00",
4068         "AOK1.00",
4069         "AON1.00",
4070         "AON1.00",
4071         "AOR1.00",
4072         "AOR1.00",
4073         "ARS1.00",
4074         "ARA1.00",
4075         "ARA1.00",
4076         "ARP1.00",
4077         "ARP1.00",
4078         "ARS1.00",
4079         "ATS1.00",
4080         "ATS1.00",
4081         "AUD1.00",
4082         "AWG1.00",
4083         "AZM1.00",
4084         "AZM1.00",
4085         "AZN1.00",
4086         "Afghan Afghani (1927\\u20132002)1.00",
4087         "Afghan afghani (1927\\u20132002)1.00",
4088         "Afghan Afghani1.00",
4089         "Afghan Afghanis1.00",
4090         "Albanian Lek1.00",
4091         "Albanian lek1.00",
4092         "Albanian lek\\u00eb1.00",
4093         "Algerian Dinar1.00",
4094         "Algerian dinar1.00",
4095         "Algerian dinars1.00",
4096         "Andorran Peseta1.00",
4097         "Andorran peseta1.00",
4098         "Andorran pesetas1.00",
4099         "Angolan Kwanza (1977\\u20131991)1.00",
4100         "Angolan Readjusted Kwanza (1995\\u20131999)1.00",
4101         "Angolan Kwanza1.00",
4102         "Angolan New Kwanza (1990\\u20132000)1.00",
4103         "Angolan kwanza (1977\\u20131991)1.00",
4104         "Angolan readjusted kwanza (1995\\u20131999)1.00",
4105         "Angolan kwanza1.00",
4106         "Angolan kwanzas (1977\\u20131991)1.00",
4107         "Angolan readjusted kwanzas (1995\\u20131999)1.00",
4108         "Angolan kwanzas1.00",
4109         "Angolan new kwanza (1990\\u20132000)1.00",
4110         "Angolan new kwanzas (1990\\u20132000)1.00",
4111         "Argentine Austral1.00",
4112         "Argentine Peso (1983\\u20131985)1.00",
4113         "Argentine Peso1.00",
4114         "Argentine austral1.00",
4115         "Argentine australs1.00",
4116         "Argentine peso (1983\\u20131985)1.00",
4117         "Argentine peso1.00",
4118         "Argentine pesos (1983\\u20131985)1.00",
4119         "Argentine pesos1.00",
4120         "Armenian Dram1.00",
4121         "Armenian dram1.00",
4122         "Armenian drams1.00",
4123         "Aruban Florin1.00",
4124         "Aruban florin1.00",
4125         "Australian Dollar1.00",
4126         "Australian dollar1.00",
4127         "Australian dollars1.00",
4128         "Austrian Schilling1.00",
4129         "Austrian schilling1.00",
4130         "Austrian schillings1.00",
4131         "Azerbaijani Manat (1993\\u20132006)1.00",
4132         "Azerbaijani Manat1.00",
4133         "Azerbaijani manat (1993\\u20132006)1.00",
4134         "Azerbaijani manat1.00",
4135         "Azerbaijani manats (1993\\u20132006)1.00",
4136         "Azerbaijani manats1.00",
4137         "BAD1.00",
4138         "BAD1.00",
4139         "BAM1.00",
4140         "BBD1.00",
4141         "BDT1.00",
4142         "BEC1.00",
4143         "BEC1.00",
4144         "BEF1.00",
4145         "BEL1.00",
4146         "BEL1.00",
4147         "BGL1.00",
4148         "BGN1.00",
4149         "BGN1.00",
4150         "BHD1.00",
4151         "BIF1.00",
4152         "BMD1.00",
4153         "BND1.00",
4154         "BOB1.00",
4155         "BOP1.00",
4156         "BOP1.00",
4157         "BOV1.00",
4158         "BOV1.00",
4159         "BRB1.00",
4160         "BRB1.00",
4161         "BRC1.00",
4162         "BRC1.00",
4163         "BRE1.00",
4164         "BRE1.00",
4165         "BRL1.00",
4166         "BRN1.00",
4167         "BRN1.00",
4168         "BRR1.00",
4169         "BRR1.00",
4170         "BSD1.00",
4171         "BSD1.00",
4172         "BTN1.00",
4173         "BUK1.00",
4174         "BUK1.00",
4175         "BWP1.00",
4176         "BYB1.00",
4177         "BYB1.00",
4178         "BYR1.00",
4179         "BZD1.00",
4180         "Bahamian Dollar1.00",
4181         "Bahamian dollar1.00",
4182         "Bahamian dollars1.00",
4183         "Bahraini Dinar1.00",
4184         "Bahraini dinar1.00",
4185         "Bahraini dinars1.00",
4186         "Bangladeshi Taka1.00",
4187         "Bangladeshi taka1.00",
4188         "Bangladeshi takas1.00",
4189         "Barbadian Dollar1.00",
4190         "Barbadian dollar1.00",
4191         "Barbadian dollars1.00",
4192         "Belarusian Ruble (1994\\u20131999)1.00",
4193         "Belarusian Ruble1.00",
4194         "Belarusian ruble (1994\\u20131999)1.00",
4195         "Belarusian rubles (1994\\u20131999)1.00",
4196         "Belarusian ruble1.00",
4197         "Belarusian rubles1.00",
4198         "Belgian Franc (convertible)1.00",
4199         "Belgian Franc (financial)1.00",
4200         "Belgian Franc1.00",
4201         "Belgian franc (convertible)1.00",
4202         "Belgian franc (financial)1.00",
4203         "Belgian franc1.00",
4204         "Belgian francs (convertible)1.00",
4205         "Belgian francs (financial)1.00",
4206         "Belgian francs1.00",
4207         "Belize Dollar1.00",
4208         "Belize dollar1.00",
4209         "Belize dollars1.00",
4210         "Bermudan Dollar1.00",
4211         "Bermudan dollar1.00",
4212         "Bermudan dollars1.00",
4213         "Bhutanese Ngultrum1.00",
4214         "Bhutanese ngultrum1.00",
4215         "Bhutanese ngultrums1.00",
4216         "Bolivian Mvdol1.00",
4217         "Bolivian Peso1.00",
4218         "Bolivian mvdol1.00",
4219         "Bolivian mvdols1.00",
4220         "Bolivian peso1.00",
4221         "Bolivian pesos1.00",
4222         "Bolivian Boliviano1.00",
4223         "Bolivian Boliviano1.00",
4224         "Bolivian Bolivianos1.00",
4225         "Bosnia-Herzegovina Convertible Mark1.00",
4226         "Bosnia-Herzegovina Dinar (1992\\u20131994)1.00",
4227         "Bosnia-Herzegovina convertible mark1.00",
4228         "Bosnia-Herzegovina convertible marks1.00",
4229         "Bosnia-Herzegovina dinar (1992\\u20131994)1.00",
4230         "Bosnia-Herzegovina dinars (1992\\u20131994)1.00",
4231         "Botswanan Pula1.00",
4232         "Botswanan pula1.00",
4233         "Botswanan pulas1.00",
4234         "Brazilian New Cruzado (1989\\u20131990)1.00",
4235         "Brazilian Cruzado (1986\\u20131989)1.00",
4236         "Brazilian Cruzeiro (1990\\u20131993)1.00",
4237         "Brazilian New Cruzeiro (1967\\u20131986)1.00",
4238         "Brazilian Cruzeiro (1993\\u20131994)1.00",
4239         "Brazilian Real1.00",
4240         "Brazilian new cruzado (1989\\u20131990)1.00",
4241         "Brazilian new cruzados (1989\\u20131990)1.00",
4242         "Brazilian cruzado (1986\\u20131989)1.00",
4243         "Brazilian cruzados (1986\\u20131989)1.00",
4244         "Brazilian cruzeiro (1990\\u20131993)1.00",
4245         "Brazilian new cruzeiro (1967\\u20131986)1.00",
4246         "Brazilian cruzeiro (1993\\u20131994)1.00",
4247         "Brazilian cruzeiros (1990\\u20131993)1.00",
4248         "Brazilian new cruzeiros (1967\\u20131986)1.00",
4249         "Brazilian cruzeiros (1993\\u20131994)1.00",
4250         "Brazilian real1.00",
4251         "Brazilian reals1.00",
4252         "British Pound1.00",
4253         "British pound1.00",
4254         "British pounds1.00",
4255         "Brunei Dollar1.00",
4256         "Brunei dollar1.00",
4257         "Brunei dollars1.00",
4258         "Bulgarian Hard Lev1.00",
4259         "Bulgarian Lev1.00",
4260         "Bulgarian Leva1.00",
4261         "Bulgarian hard lev1.00",
4262         "Bulgarian hard leva1.00",
4263         "Bulgarian lev1.00",
4264         "Burmese Kyat1.00",
4265         "Burmese kyat1.00",
4266         "Burmese kyats1.00",
4267         "Burundian Franc1.00",
4268         "Burundian franc1.00",
4269         "Burundian francs1.00",
4270         "CA$1.00",
4271         "CAD1.00",
4272         "CDF1.00",
4273         "CDF1.00",
4274         "West African CFA Franc1.00",
4275         "Central African CFA Franc1.00",
4276         "West African CFA franc1.00",
4277         "Central African CFA franc1.00",
4278         "West African CFA francs1.00",
4279         "Central African CFA francs1.00",
4280         "CFP Franc1.00",
4281         "CFP franc1.00",
4282         "CFP francs1.00",
4283         "CFPF1.00",
4284         "CHE1.00",
4285         "CHE1.00",
4286         "CHF1.00",
4287         "CHW1.00",
4288         "CHW1.00",
4289         "CLF1.00",
4290         "CLF1.00",
4291         "CLP1.00",
4292         "CNY1.00",
4293         "COP1.00",
4294         "COU1.00",
4295         "COU1.00",
4296         "CRC1.00",
4297         "CSD1.00",
4298         "CSD1.00",
4299         "CSK1.00",
4300         "CSK1.00",
4301         "CUP1.00",
4302         "CUP1.00",
4303         "CVE1.00",
4304         "CYP1.00",
4305         "CZK1.00",
4306         "Cambodian Riel1.00",
4307         "Cambodian riel1.00",
4308         "Cambodian riels1.00",
4309         "Canadian Dollar1.00",
4310         "Canadian dollar1.00",
4311         "Canadian dollars1.00",
4312         "Cape Verdean Escudo1.00",
4313         "Cape Verdean escudo1.00",
4314         "Cape Verdean escudos1.00",
4315         "Cayman Islands Dollar1.00",
4316         "Cayman Islands dollar1.00",
4317         "Cayman Islands dollars1.00",
4318         "Chilean Peso1.00",
4319         "Chilean Unit of Account (UF)1.00",
4320         "Chilean peso1.00",
4321         "Chilean pesos1.00",
4322         "Chilean unit of account (UF)1.00",
4323         "Chilean units of account (UF)1.00",
4324         "Chinese Yuan1.00",
4325         "Chinese yuan1.00",
4326         "Colombian Peso1.00",
4327         "Colombian peso1.00",
4328         "Colombian pesos1.00",
4329         "Comorian Franc1.00",
4330         "Comorian franc1.00",
4331         "Comorian francs1.00",
4332         "Congolese Franc1.00",
4333         "Congolese franc1.00",
4334         "Congolese francs1.00",
4335         "Costa Rican Col\\u00f3n1.00",
4336         "Costa Rican col\\u00f3n1.00",
4337         "Costa Rican col\\u00f3ns1.00",
4338         "Croatian Dinar1.00",
4339         "Croatian Kuna1.00",
4340         "Croatian dinar1.00",
4341         "Croatian dinars1.00",
4342         "Croatian kuna1.00",
4343         "Croatian kunas1.00",
4344         "Cuban Peso1.00",
4345         "Cuban peso1.00",
4346         "Cuban pesos1.00",
4347         "Cypriot Pound1.00",
4348         "Cypriot pound1.00",
4349         "Cypriot pounds1.00",
4350         "Czech Koruna1.00",
4351         "Czech koruna1.00",
4352         "Czech korunas1.00",
4353         "Czechoslovak Hard Koruna1.00",
4354         "Czechoslovak hard koruna1.00",
4355         "Czechoslovak hard korunas1.00",
4356         "DDM1.00",
4357         "DDM1.00",
4358         "DEM1.00",
4359         "DEM1.00",
4360         "DJF1.00",
4361         "DKK1.00",
4362         "DOP1.00",
4363         "DZD1.00",
4364         "Danish Krone1.00",
4365         "Danish krone1.00",
4366         "Danish kroner1.00",
4367         "German Mark1.00",
4368         "German mark1.00",
4369         "German marks1.00",
4370         "Djiboutian Franc1.00",
4371         "Djiboutian franc1.00",
4372         "Djiboutian francs1.00",
4373         "Dominican Peso1.00",
4374         "Dominican peso1.00",
4375         "Dominican pesos1.00",
4376         "EC$1.00",
4377         "ECS1.00",
4378         "ECS1.00",
4379         "ECV1.00",
4380         "ECV1.00",
4381         "EEK1.00",
4382         "EEK1.00",
4383         "EGP1.00",
4384         "EGP1.00",
4385         "ERN1.00",
4386         "ERN1.00",
4387         "ESA1.00",
4388         "ESA1.00",
4389         "ESB1.00",
4390         "ESB1.00",
4391         "ESP1.00",
4392         "ETB1.00",
4393         "EUR1.00",
4394         "East Caribbean Dollar1.00",
4395         "East Caribbean dollar1.00",
4396         "East Caribbean dollars1.00",
4397         "East German Mark1.00",
4398         "East German mark1.00",
4399         "East German marks1.00",
4400         "Ecuadorian Sucre1.00",
4401         "Ecuadorian Unit of Constant Value1.00",
4402         "Ecuadorian sucre1.00",
4403         "Ecuadorian sucres1.00",
4404         "Ecuadorian unit of constant value1.00",
4405         "Ecuadorian units of constant value1.00",
4406         "Egyptian Pound1.00",
4407         "Egyptian pound1.00",
4408         "Egyptian pounds1.00",
4409         "Salvadoran Col\\u00f3n1.00",
4410         "Salvadoran col\\u00f3n1.00",
4411         "Salvadoran colones1.00",
4412         "Equatorial Guinean Ekwele1.00",
4413         "Equatorial Guinean ekwele1.00",
4414         "Eritrean Nakfa1.00",
4415         "Eritrean nakfa1.00",
4416         "Eritrean nakfas1.00",
4417         "Estonian Kroon1.00",
4418         "Estonian kroon1.00",
4419         "Estonian kroons1.00",
4420         "Ethiopian Birr1.00",
4421         "Ethiopian birr1.00",
4422         "Ethiopian birrs1.00",
4423         "Euro1.00",
4424         "European Composite Unit1.00",
4425         "European Currency Unit1.00",
4426         "European Monetary Unit1.00",
4427         "European Unit of Account (XBC)1.00",
4428         "European Unit of Account (XBD)1.00",
4429         "European composite unit1.00",
4430         "European composite units1.00",
4431         "European currency unit1.00",
4432         "European currency units1.00",
4433         "European monetary unit1.00",
4434         "European monetary units1.00",
4435         "European unit of account (XBC)1.00",
4436         "European unit of account (XBD)1.00",
4437         "European units of account (XBC)1.00",
4438         "European units of account (XBD)1.00",
4439         "FIM1.00",
4440         "FIM1.00",
4441         "FJD1.00",
4442         "FKP1.00",
4443         "FKP1.00",
4444         "FRF1.00",
4445         "FRF1.00",
4446         "Falkland Islands Pound1.00",
4447         "Falkland Islands pound1.00",
4448         "Falkland Islands pounds1.00",
4449         "Fijian Dollar1.00",
4450         "Fijian dollar1.00",
4451         "Fijian dollars1.00",
4452         "Finnish Markka1.00",
4453         "Finnish markka1.00",
4454         "Finnish markkas1.00",
4455         "CHF1.00",
4456         "French Franc1.00",
4457         "French Gold Franc1.00",
4458         "French UIC-Franc1.00",
4459         "French UIC-franc1.00",
4460         "French UIC-francs1.00",
4461         "French franc1.00",
4462         "French francs1.00",
4463         "French gold franc1.00",
4464         "French gold francs1.00",
4465         "GBP1.00",
4466         "GEK1.00",
4467         "GEK1.00",
4468         "GEL1.00",
4469         "GHC1.00",
4470         "GHC1.00",
4471         "GHS1.00",
4472         "GIP1.00",
4473         "GIP1.00",
4474         "GMD1.00",
4475         "GMD1.00",
4476         "GNF1.00",
4477         "GNS1.00",
4478         "GNS1.00",
4479         "GQE1.00",
4480         "GQE1.00",
4481         "GRD1.00",
4482         "GRD1.00",
4483         "GTQ1.00",
4484         "GWE1.00",
4485         "GWE1.00",
4486         "GWP1.00",
4487         "GWP1.00",
4488         "GYD1.00",
4489         "Gambian Dalasi1.00",
4490         "Gambian dalasi1.00",
4491         "Gambian dalasis1.00",
4492         "Georgian Kupon Larit1.00",
4493         "Georgian Lari1.00",
4494         "Georgian kupon larit1.00",
4495         "Georgian kupon larits1.00",
4496         "Georgian lari1.00",
4497         "Georgian laris1.00",
4498         "Ghanaian Cedi (1979\\u20132007)1.00",
4499         "Ghanaian Cedi1.00",
4500         "Ghanaian cedi (1979\\u20132007)1.00",
4501         "Ghanaian cedi1.00",
4502         "Ghanaian cedis (1979\\u20132007)1.00",
4503         "Ghanaian cedis1.00",
4504         "Gibraltar Pound1.00",
4505         "Gibraltar pound1.00",
4506         "Gibraltar pounds1.00",
4507         "Gold1.00",
4508         "Gold1.00",
4509         "Greek Drachma1.00",
4510         "Greek drachma1.00",
4511         "Greek drachmas1.00",
4512         "Guatemalan Quetzal1.00",
4513         "Guatemalan quetzal1.00",
4514         "Guatemalan quetzals1.00",
4515         "Guinean Franc1.00",
4516         "Guinean Syli1.00",
4517         "Guinean franc1.00",
4518         "Guinean francs1.00",
4519         "Guinean syli1.00",
4520         "Guinean sylis1.00",
4521         "Guinea-Bissau Peso1.00",
4522         "Guinea-Bissau peso1.00",
4523         "Guinea-Bissau pesos1.00",
4524         "Guyanaese Dollar1.00",
4525         "Guyanaese dollar1.00",
4526         "Guyanaese dollars1.00",
4527         "HK$1.00",
4528         "HKD1.00",
4529         "HNL1.00",
4530         "HRD1.00",
4531         "HRD1.00",
4532         "HRK1.00",
4533         "HRK1.00",
4534         "HTG1.00",
4535         "HTG1.00",
4536         "HUF1.00",
4537         "Haitian Gourde1.00",
4538         "Haitian gourde1.00",
4539         "Haitian gourdes1.00",
4540         "Honduran Lempira1.00",
4541         "Honduran lempira1.00",
4542         "Honduran lempiras1.00",
4543         "Hong Kong Dollar1.00",
4544         "Hong Kong dollar1.00",
4545         "Hong Kong dollars1.00",
4546         "Hungarian Forint1.00",
4547         "Hungarian forint1.00",
4548         "Hungarian forints1.00",
4549         "IDR1.00",
4550         "IEP1.00",
4551         "ILP1.00",
4552         "ILP1.00",
4553         "ILS1.00",
4554         "INR1.00",
4555         "IQD1.00",
4556         "IRR1.00",
4557         "ISK1.00",
4558         "ISK1.00",
4559         "ITL1.00",
4560         "Icelandic Kr\\u00f3na1.00",
4561         "Icelandic kr\\u00f3na1.00",
4562         "Icelandic kr\\u00f3nur1.00",
4563         "Indian Rupee1.00",
4564         "Indian rupee1.00",
4565         "Indian rupees1.00",
4566         "Indonesian Rupiah1.00",
4567         "Indonesian rupiah1.00",
4568         "Indonesian rupiahs1.00",
4569         "Iranian Rial1.00",
4570         "Iranian rial1.00",
4571         "Iranian rials1.00",
4572         "Iraqi Dinar1.00",
4573         "Iraqi dinar1.00",
4574         "Iraqi dinars1.00",
4575         "Irish Pound1.00",
4576         "Irish pound1.00",
4577         "Irish pounds1.00",
4578         "Israeli Pound1.00",
4579         "Israeli new shekel1.00",
4580         "Israeli pound1.00",
4581         "Israeli pounds1.00",
4582         "Italian Lira1.00",
4583         "Italian lira1.00",
4584         "Italian liras1.00",
4585         "JMD1.00",
4586         "JOD1.00",
4587         "JPY1.00",
4588         "Jamaican Dollar1.00",
4589         "Jamaican dollar1.00",
4590         "Jamaican dollars1.00",
4591         "Japanese Yen1.00",
4592         "Japanese yen1.00",
4593         "Jordanian Dinar1.00",
4594         "Jordanian dinar1.00",
4595         "Jordanian dinars1.00",
4596         "KES1.00",
4597         "KGS1.00",
4598         "KHR1.00",
4599         "KMF1.00",
4600         "KPW1.00",
4601         "KPW1.00",
4602         "KRW1.00",
4603         "KWD1.00",
4604         "KYD1.00",
4605         "KYD1.00",
4606         "KZT1.00",
4607         "Kazakhstani Tenge1.00",
4608         "Kazakhstani tenge1.00",
4609         "Kazakhstani tenges1.00",
4610         "Kenyan Shilling1.00",
4611         "Kenyan shilling1.00",
4612         "Kenyan shillings1.00",
4613         "Kuwaiti Dinar1.00",
4614         "Kuwaiti dinar1.00",
4615         "Kuwaiti dinars1.00",
4616         "Kyrgystani Som1.00",
4617         "Kyrgystani som1.00",
4618         "Kyrgystani soms1.00",
4619         "HNL1.00",
4620         "LAK1.00",
4621         "LAK1.00",
4622         "LBP1.00",
4623         "LKR1.00",
4624         "LRD1.00",
4625         "LRD1.00",
4626         "LSL1.00",
4627         "LTL1.00",
4628         "LTL1.00",
4629         "LTT1.00",
4630         "LTT1.00",
4631         "LUC1.00",
4632         "LUC1.00",
4633         "LUF1.00",
4634         "LUF1.00",
4635         "LUL1.00",
4636         "LUL1.00",
4637         "LVL1.00",
4638         "LVL1.00",
4639         "LVR1.00",
4640         "LVR1.00",
4641         "LYD1.00",
4642         "Laotian Kip1.00",
4643         "Laotian kip1.00",
4644         "Laotian kips1.00",
4645         "Latvian Lats1.00",
4646         "Latvian Ruble1.00",
4647         "Latvian lats1.00",
4648         "Latvian lati1.00",
4649         "Latvian ruble1.00",
4650         "Latvian rubles1.00",
4651         "Lebanese Pound1.00",
4652         "Lebanese pound1.00",
4653         "Lebanese pounds1.00",
4654         "Lesotho Loti1.00",
4655         "Lesotho loti1.00",
4656         "Lesotho lotis1.00",
4657         "Liberian Dollar1.00",
4658         "Liberian dollar1.00",
4659         "Liberian dollars1.00",
4660         "Libyan Dinar1.00",
4661         "Libyan dinar1.00",
4662         "Libyan dinars1.00",
4663         "Lithuanian Litas1.00",
4664         "Lithuanian Talonas1.00",
4665         "Lithuanian litas1.00",
4666         "Lithuanian litai1.00",
4667         "Lithuanian talonas1.00",
4668         "Lithuanian talonases1.00",
4669         "Luxembourgian Convertible Franc1.00",
4670         "Luxembourg Financial Franc1.00",
4671         "Luxembourgian Franc1.00",
4672         "Luxembourgian convertible franc1.00",
4673         "Luxembourgian convertible francs1.00",
4674         "Luxembourg financial franc1.00",
4675         "Luxembourg financial francs1.00",
4676         "Luxembourgian franc1.00",
4677         "Luxembourgian francs1.00",
4678         "MAD1.00",
4679         "MAD1.00",
4680         "MAF1.00",
4681         "MAF1.00",
4682         "MDL1.00",
4683         "MDL1.00",
4684         "MX$1.00",
4685         "MGA1.00",
4686         "MGA1.00",
4687         "MGF1.00",
4688         "MGF1.00",
4689         "MKD1.00",
4690         "MLF1.00",
4691         "MLF1.00",
4692         "MMK1.00",
4693         "MMK1.00",
4694         "MNT1.00",
4695         "MOP1.00",
4696         "MOP1.00",
4697         "MRO1.00",
4698         "MTL1.00",
4699         "MTP1.00",
4700         "MTP1.00",
4701         "MUR1.00",
4702         "MUR1.00",
4703         "MVR1.00",
4704         "MVR1.00",
4705         "MWK1.00",
4706         "MXN1.00",
4707         "MXP1.00",
4708         "MXP1.00",
4709         "MXV1.00",
4710         "MXV1.00",
4711         "MYR1.00",
4712         "MZE1.00",
4713         "MZE1.00",
4714         "MZM1.00",
4715         "MZN1.00",
4716         "Macanese Pataca1.00",
4717         "Macanese pataca1.00",
4718         "Macanese patacas1.00",
4719         "Macedonian Denar1.00",
4720         "Macedonian denar1.00",
4721         "Macedonian denari1.00",
4722         "Malagasy Ariaries1.00",
4723         "Malagasy Ariary1.00",
4724         "Malagasy Ariary1.00",
4725         "Malagasy Franc1.00",
4726         "Malagasy franc1.00",
4727         "Malagasy francs1.00",
4728         "Malawian Kwacha1.00",
4729         "Malawian Kwacha1.00",
4730         "Malawian Kwachas1.00",
4731         "Malaysian Ringgit1.00",
4732         "Malaysian ringgit1.00",
4733         "Malaysian ringgits1.00",
4734         "Maldivian Rufiyaa1.00",
4735         "Maldivian rufiyaa1.00",
4736         "Maldivian rufiyaas1.00",
4737         "Malian Franc1.00",
4738         "Malian franc1.00",
4739         "Malian francs1.00",
4740         "Maltese Lira1.00",
4741         "Maltese Pound1.00",
4742         "Maltese lira1.00",
4743         "Maltese lira1.00",
4744         "Maltese pound1.00",
4745         "Maltese pounds1.00",
4746         "Mauritanian Ouguiya1.00",
4747         "Mauritanian ouguiya1.00",
4748         "Mauritanian ouguiyas1.00",
4749         "Mauritian Rupee1.00",
4750         "Mauritian rupee1.00",
4751         "Mauritian rupees1.00",
4752         "Mexican Peso1.00",
4753         "Mexican Silver Peso (1861\\u20131992)1.00",
4754         "Mexican Investment Unit1.00",
4755         "Mexican peso1.00",
4756         "Mexican pesos1.00",
4757         "Mexican silver peso (1861\\u20131992)1.00",
4758         "Mexican silver pesos (1861\\u20131992)1.00",
4759         "Mexican investment unit1.00",
4760         "Mexican investment units1.00",
4761         "Moldovan Leu1.00",
4762         "Moldovan leu1.00",
4763         "Moldovan lei1.00",
4764         "Mongolian Tugrik1.00",
4765         "Mongolian tugrik1.00",
4766         "Mongolian tugriks1.00",
4767         "Moroccan Dirham1.00",
4768         "Moroccan Franc1.00",
4769         "Moroccan dirham1.00",
4770         "Moroccan dirhams1.00",
4771         "Moroccan franc1.00",
4772         "Moroccan francs1.00",
4773         "Mozambican Escudo1.00",
4774         "Mozambican Metical1.00",
4775         "Mozambican escudo1.00",
4776         "Mozambican escudos1.00",
4777         "Mozambican metical1.00",
4778         "Mozambican meticals1.00",
4779         "Myanmar Kyat1.00",
4780         "Myanmar kyat1.00",
4781         "Myanmar kyats1.00",
4782         "NAD1.00",
4783         "NGN1.00",
4784         "NIC1.00",
4785         "NIO1.00",
4786         "NIO1.00",
4787         "NLG1.00",
4788         "NLG1.00",
4789         "NOK1.00",
4790         "NPR1.00",
4791         "NT$1.00",
4792         "NZ$1.00",
4793         "NZD1.00",
4794         "Namibian Dollar1.00",
4795         "Namibian dollar1.00",
4796         "Namibian dollars1.00",
4797         "Nepalese Rupee1.00",
4798         "Nepalese rupee1.00",
4799         "Nepalese rupees1.00",
4800         "Netherlands Antillean Guilder1.00",
4801         "Netherlands Antillean guilder1.00",
4802         "Netherlands Antillean guilders1.00",
4803         "Dutch Guilder1.00",
4804         "Dutch guilder1.00",
4805         "Dutch guilders1.00",
4806         "Israeli New Shekel1.00",
4807         "Israeli New Shekels1.00",
4808         "New Zealand Dollar1.00",
4809         "New Zealand dollar1.00",
4810         "New Zealand dollars1.00",
4811         "Nicaraguan C\\u00f3rdoba1.00",
4812         "Nicaraguan C\\u00f3rdoba (1988\\u20131991)1.00",
4813         "Nicaraguan c\\u00f3rdoba1.00",
4814         "Nicaraguan c\\u00f3rdobas1.00",
4815         "Nicaraguan c\\u00f3rdoba (1988\\u20131991)1.00",
4816         "Nicaraguan c\\u00f3rdobas (1988\\u20131991)1.00",
4817         "Nigerian Naira1.00",
4818         "Nigerian naira1.00",
4819         "Nigerian nairas1.00",
4820         "North Korean Won1.00",
4821         "North Korean won1.00",
4822         "North Korean won1.00",
4823         "Norwegian Krone1.00",
4824         "Norwegian krone1.00",
4825         "Norwegian kroner1.00",
4826         "OMR1.00",
4827         "Mozambican Metical (1980\\u20132006)1.00",
4828         "Mozambican metical (1980\\u20132006)1.00",
4829         "Mozambican meticals (1980\\u20132006)1.00",
4830         "Romanian Lei (1952\\u20132006)1.00",
4831         "Romanian Leu (1952\\u20132006)1.00",
4832         "Romanian leu (1952\\u20132006)1.00",
4833         "Serbian Dinar (2002\\u20132006)1.00",
4834         "Serbian dinar (2002\\u20132006)1.00",
4835         "Serbian dinars (2002\\u20132006)1.00",
4836         "Sudanese Dinar (1992\\u20132007)1.00",
4837         "Sudanese Pound (1957\\u20131998)1.00",
4838         "Sudanese dinar (1992\\u20132007)1.00",
4839         "Sudanese dinars (1992\\u20132007)1.00",
4840         "Sudanese pound (1957\\u20131998)1.00",
4841         "Sudanese pounds (1957\\u20131998)1.00",
4842         "Turkish Lira (1922\\u20132005)1.00",
4843         "Turkish Lira (1922\\u20132005)1.00",
4844         "Omani Rial1.00",
4845         "Omani rial1.00",
4846         "Omani rials1.00",
4847         "PAB1.00",
4848         "PAB1.00",
4849         "PEI1.00",
4850         "PEI1.00",
4851         "PEN1.00",
4852         "PEN1.00",
4853         "PES1.00",
4854         "PES1.00",
4855         "PGK1.00",
4856         "PGK1.00",
4857         "PHP1.00",
4858         "PKR1.00",
4859         "PLN1.00",
4860         "PLZ1.00",
4861         "PLZ1.00",
4862         "PTE1.00",
4863         "PTE1.00",
4864         "PYG1.00",
4865         "Pakistani Rupee1.00",
4866         "Pakistani rupee1.00",
4867         "Pakistani rupees1.00",
4868         "Palladium1.00",
4869         "Palladium1.00",
4870         "Panamanian Balboa1.00",
4871         "Panamanian balboa1.00",
4872         "Panamanian balboas1.00",
4873         "Papua New Guinean Kina1.00",
4874         "Papua New Guinean kina1.00",
4875         "Papua New Guinean kina1.00",
4876         "Paraguayan Guarani1.00",
4877         "Paraguayan guarani1.00",
4878         "Paraguayan guaranis1.00",
4879         "Peruvian Inti1.00",
4880         "Peruvian Sol1.00",
4881         "Peruvian Sol (1863\\u20131965)1.00",
4882         "Peruvian inti1.00",
4883         "Peruvian intis1.00",
4884         "Peruvian sol1.00",
4885         "Peruvian soles1.00",
4886         "Peruvian sol (1863\\u20131965)1.00",
4887         "Peruvian soles (1863\\u20131965)1.00",
4888         "Philippine Piso1.00",
4889         "Philippine piso1.00",
4890         "Philippine pisos1.00",
4891         "Platinum1.00",
4892         "Platinum1.00",
4893         "Polish Zloty (1950\\u20131995)1.00",
4894         "Polish Zloty1.00",
4895         "Polish zlotys1.00",
4896         "Polish zloty (PLZ)1.00",
4897         "Polish zloty1.00",
4898         "Polish zlotys (PLZ)1.00",
4899         "Portuguese Escudo1.00",
4900         "Portuguese Guinea Escudo1.00",
4901         "Portuguese Guinea escudo1.00",
4902         "Portuguese Guinea escudos1.00",
4903         "Portuguese escudo1.00",
4904         "Portuguese escudos1.00",
4905         "GTQ1.00",
4906         "QAR1.00",
4907         "Qatari Rial1.00",
4908         "Qatari rial1.00",
4909         "Qatari rials1.00",
4910         "RHD1.00",
4911         "RHD1.00",
4912         "RINET Funds1.00",
4913         "RINET Funds1.00",
4914         "CN\\u00a51.00",
4915         "ROL1.00",
4916         "ROL1.00",
4917         "RON1.00",
4918         "RON1.00",
4919         "RSD1.00",
4920         "RSD1.00",
4921         "RUB1.00",
4922         "RUR1.00",
4923         "RUR1.00",
4924         "RWF1.00",
4925         "RWF1.00",
4926         "Rhodesian Dollar1.00",
4927         "Rhodesian dollar1.00",
4928         "Rhodesian dollars1.00",
4929         "Romanian Leu1.00",
4930         "Romanian lei1.00",
4931         "Romanian leu1.00",
4932         "Russian Ruble (1991\\u20131998)1.00",
4933         "Russian Ruble1.00",
4934         "Russian ruble (1991\\u20131998)1.00",
4935         "Russian ruble1.00",
4936         "Russian rubles (1991\\u20131998)1.00",
4937         "Russian rubles1.00",
4938         "Rwandan Franc1.00",
4939         "Rwandan franc1.00",
4940         "Rwandan francs1.00",
4941         "SAR1.00",
4942         "SBD1.00",
4943         "SCR1.00",
4944         "SDD1.00",
4945         "SDD1.00",
4946         "SDG1.00",
4947         "SDG1.00",
4948         "SDP1.00",
4949         "SDP1.00",
4950         "SEK1.00",
4951         "SGD1.00",
4952         "SHP1.00",
4953         "SHP1.00",
4954         "SIT1.00",
4955         "SIT1.00",
4956         "SKK1.00",
4957         "SLL1.00",
4958         "SLL1.00",
4959         "SOS1.00",
4960         "SRD1.00",
4961         "SRD1.00",
4962         "SRG1.00",
4963         "STD1.00",
4964         "SUR1.00",
4965         "SUR1.00",
4966         "SVC1.00",
4967         "SVC1.00",
4968         "SYP1.00",
4969         "SZL1.00",
4970         "St. Helena Pound1.00",
4971         "St. Helena pound1.00",
4972         "St. Helena pounds1.00",
4973         "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra1.00",
4974         "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra1.00",
4975         "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras1.00",
4976         "Saudi Riyal1.00",
4977         "Saudi riyal1.00",
4978         "Saudi riyals1.00",
4979         "Serbian Dinar1.00",
4980         "Serbian dinar1.00",
4981         "Serbian dinars1.00",
4982         "Seychellois Rupee1.00",
4983         "Seychellois rupee1.00",
4984         "Seychellois rupees1.00",
4985         "Sierra Leonean Leone1.00",
4986         "Sierra Leonean leone1.00",
4987         "Sierra Leonean leones1.00",
4988         "Silver1.00",
4989         "Silver1.00",
4990         "Singapore Dollar1.00",
4991         "Singapore dollar1.00",
4992         "Singapore dollars1.00",
4993         "Slovak Koruna1.00",
4994         "Slovak koruna1.00",
4995         "Slovak korunas1.00",
4996         "Slovenian Tolar1.00",
4997         "Slovenian tolar1.00",
4998         "Slovenian tolars1.00",
4999         "Solomon Islands Dollar1.00",
5000         "Solomon Islands dollar1.00",
5001         "Solomon Islands dollars1.00",
5002         "Somali Shilling1.00",
5003         "Somali shilling1.00",
5004         "Somali shillings1.00",
5005         "South African Rand (financial)1.00",
5006         "South African Rand1.00",
5007         "South African rand (financial)1.00",
5008         "South African rand1.00",
5009         "South African rands (financial)1.00",
5010         "South African rand1.00",
5011         "South Korean Won1.00",
5012         "South Korean won1.00",
5013         "South Korean won1.00",
5014         "Soviet Rouble1.00",
5015         "Soviet rouble1.00",
5016         "Soviet roubles1.00",
5017         "Spanish Peseta (A account)1.00",
5018         "Spanish Peseta (convertible account)1.00",
5019         "Spanish Peseta1.00",
5020         "Spanish peseta (A account)1.00",
5021         "Spanish peseta (convertible account)1.00",
5022         "Spanish peseta1.00",
5023         "Spanish pesetas (A account)1.00",
5024         "Spanish pesetas (convertible account)1.00",
5025         "Spanish pesetas1.00",
5026         "Special Drawing Rights1.00",
5027         "Sri Lankan Rupee1.00",
5028         "Sri Lankan rupee1.00",
5029         "Sri Lankan rupees1.00",
5030         "Sudanese Pound1.00",
5031         "Sudanese pound1.00",
5032         "Sudanese pounds1.00",
5033         "Surinamese Dollar1.00",
5034         "Surinamese dollar1.00",
5035         "Surinamese dollars1.00",
5036         "Surinamese Guilder1.00",
5037         "Surinamese guilder1.00",
5038         "Surinamese guilders1.00",
5039         "Swazi Lilangeni1.00",
5040         "Swazi lilangeni1.00",
5041         "Swazi emalangeni1.00",
5042         "Swedish Krona1.00",
5043         "Swedish krona1.00",
5044         "Swedish kronor1.00",
5045         "Swiss Franc1.00",
5046         "Swiss franc1.00",
5047         "Swiss francs1.00",
5048         "Syrian Pound1.00",
5049         "Syrian pound1.00",
5050         "Syrian pounds1.00",
5051         "THB1.00",
5052         "TJR1.00",
5053         "TJR1.00",
5054         "TJS1.00",
5055         "TJS1.00",
5056         "TMM1.00",
5057         "TMM1.00",
5058         "TND1.00",
5059         "TND1.00",
5060         "TOP1.00",
5061         "TPE1.00",
5062         "TPE1.00",
5063         "TRL1.00",
5064         "TRY1.00",
5065         "TRY1.00",
5066         "TTD1.00",
5067         "TWD1.00",
5068         "TZS1.00",
5069         "New Taiwan Dollar1.00",
5070         "New Taiwan dollar1.00",
5071         "New Taiwan dollars1.00",
5072         "Tajikistani Ruble1.00",
5073         "Tajikistani Somoni1.00",
5074         "Tajikistani ruble1.00",
5075         "Tajikistani rubles1.00",
5076         "Tajikistani somoni1.00",
5077         "Tajikistani somonis1.00",
5078         "Tanzanian Shilling1.00",
5079         "Tanzanian shilling1.00",
5080         "Tanzanian shillings1.00",
5081         "Testing Currency Code1.00",
5082         "Testing Currency Code1.00",
5083         "Thai Baht1.00",
5084         "Thai baht1.00",
5085         "Thai baht1.00",
5086         "Timorese Escudo1.00",
5087         "Timorese escudo1.00",
5088         "Timorese escudos1.00",
5089         "Tongan Pa\\u02bbanga1.00",
5090         "Tongan pa\\u02bbanga1.00",
5091         "Tongan pa\\u02bbanga1.00",
5092         "Trinidad & Tobago Dollar1.00",
5093         "Trinidad & Tobago dollar1.00",
5094         "Trinidad & Tobago dollars1.00",
5095         "Tunisian Dinar1.00",
5096         "Tunisian dinar1.00",
5097         "Tunisian dinars1.00",
5098         "Turkish Lira1.00",
5099         "Turkish Lira1.00",
5100         "Turkish lira1.00",
5101         "Turkmenistani Manat1.00",
5102         "Turkmenistani manat1.00",
5103         "Turkmenistani manat1.00",
5104         "UAE dirham1.00",
5105         "UAE dirhams1.00",
5106         "UAH1.00",
5107         "UAK1.00",
5108         "UAK1.00",
5109         "UGS1.00",
5110         "UGS1.00",
5111         "UGX1.00",
5112         "US Dollar (Next day)1.00",
5113         "US Dollar (Same day)1.00",
5114         "US Dollar1.00",
5115         "US dollar (next day)1.00",
5116         "US dollar (same day)1.00",
5117         "US dollar1.00",
5118         "US dollars (next day)1.00",
5119         "US dollars (same day)1.00",
5120         "US dollars1.00",
5121         "USD1.00",
5122         "USN1.00",
5123         "USN1.00",
5124         "USS1.00",
5125         "USS1.00",
5126         "UYI1.00",
5127         "UYI1.00",
5128         "UYP1.00",
5129         "UYP1.00",
5130         "UYU1.00",
5131         "UZS1.00",
5132         "UZS1.00",
5133         "Ugandan Shilling (1966\\u20131987)1.00",
5134         "Ugandan Shilling1.00",
5135         "Ugandan shilling (1966\\u20131987)1.00",
5136         "Ugandan shilling1.00",
5137         "Ugandan shillings (1966\\u20131987)1.00",
5138         "Ugandan shillings1.00",
5139         "Ukrainian Hryvnia1.00",
5140         "Ukrainian Karbovanets1.00",
5141         "Ukrainian hryvnia1.00",
5142         "Ukrainian hryvnias1.00",
5143         "Ukrainian karbovanets1.00",
5144         "Ukrainian karbovantsiv1.00",
5145         "Colombian Real Value Unit1.00",
5146         "United Arab Emirates Dirham1.00",
5147         "Unknown Currency1.00",
5148         "Uruguayan Peso (1975\\u20131993)1.00",
5149         "Uruguayan Peso1.00",
5150         "Uruguayan Peso (Indexed Units)1.00",
5151         "Uruguayan peso (1975\\u20131993)1.00",
5152         "Uruguayan peso (indexed units)1.00",
5153         "Uruguayan peso1.00",
5154         "Uruguayan pesos (1975\\u20131993)1.00",
5155         "Uruguayan pesos (indexed units)1.00",
5156         "Uruguayan pesos1.00",
5157         "Uzbekistani Som1.00",
5158         "Uzbekistani som1.00",
5159         "Uzbekistani som1.00",
5160         "VEB1.00",
5161         "VEF1.00",
5162         "VND1.00",
5163         "VUV1.00",
5164         "Vanuatu Vatu1.00",
5165         "Vanuatu vatu1.00",
5166         "Vanuatu vatus1.00",
5167         "Venezuelan Bol\\u00edvar1.00",
5168         "Venezuelan Bol\\u00edvar (1871\\u20132008)1.00",
5169         "Venezuelan bol\\u00edvar1.00",
5170         "Venezuelan bol\\u00edvars1.00",
5171         "Venezuelan bol\\u00edvar (1871\\u20132008)1.00",
5172         "Venezuelan bol\\u00edvars (1871\\u20132008)1.00",
5173         "Vietnamese Dong1.00",
5174         "Vietnamese dong1.00",
5175         "Vietnamese dong1.00",
5176         "WIR Euro1.00",
5177         "WIR Franc1.00",
5178         "WIR euro1.00",
5179         "WIR euros1.00",
5180         "WIR franc1.00",
5181         "WIR francs1.00",
5182         "WST1.00",
5183         "WST1.00",
5184         "Samoan Tala1.00",
5185         "Samoan tala1.00",
5186         "Samoan tala1.00",
5187         "XAF1.00",
5188         "XAF1.00",
5189         "XAG1.00",
5190         "XAG1.00",
5191         "XAU1.00",
5192         "XAU1.00",
5193         "XBA1.00",
5194         "XBA1.00",
5195         "XBB1.00",
5196         "XBB1.00",
5197         "XBC1.00",
5198         "XBC1.00",
5199         "XBD1.00",
5200         "XBD1.00",
5201         "XCD1.00",
5202         "XDR1.00",
5203         "XDR1.00",
5204         "XEU1.00",
5205         "XEU1.00",
5206         "XFO1.00",
5207         "XFO1.00",
5208         "XFU1.00",
5209         "XFU1.00",
5210         "XOF1.00",
5211         "XOF1.00",
5212         "XPD1.00",
5213         "XPD1.00",
5214         "XPF1.00",
5215         "XPT1.00",
5216         "XPT1.00",
5217         "XRE1.00",
5218         "XRE1.00",
5219         "XTS1.00",
5220         "XTS1.00",
5221         "XXX1.00",
5222         "XXX1.00",
5223         "YDD1.00",
5224         "YDD1.00",
5225         "YER1.00",
5226         "YUD1.00",
5227         "YUD1.00",
5228         "YUM1.00",
5229         "YUM1.00",
5230         "YUN1.00",
5231         "YUN1.00",
5232         "Yemeni Dinar1.00",
5233         "Yemeni Rial1.00",
5234         "Yemeni dinar1.00",
5235         "Yemeni dinars1.00",
5236         "Yemeni rial1.00",
5237         "Yemeni rials1.00",
5238         "Yugoslavian Convertible Dinar (1990\\u20131992)1.00",
5239         "Yugoslavian Hard Dinar (1966\\u20131990)1.00",
5240         "Yugoslavian New Dinar (1994\\u20132002)1.00",
5241         "Yugoslavian convertible dinar (1990\\u20131992)1.00",
5242         "Yugoslavian convertible dinars (1990\\u20131992)1.00",
5243         "Yugoslavian hard dinar (1966\\u20131990)1.00",
5244         "Yugoslavian hard dinars (1966\\u20131990)1.00",
5245         "Yugoslavian new dinar (1994\\u20132002)1.00",
5246         "Yugoslavian new dinars (1994\\u20132002)1.00",
5247         "ZAL1.00",
5248         "ZAL1.00",
5249         "ZAR1.00",
5250         "ZMK1.00",
5251         "ZMK1.00",
5252         "ZRN1.00",
5253         "ZRN1.00",
5254         "ZRZ1.00",
5255         "ZRZ1.00",
5256         "ZWD1.00",
5257         "Zairean New Zaire (1993\\u20131998)1.00",
5258         "Zairean Zaire (1971\\u20131993)1.00",
5259         "Zairean new zaire (1993\\u20131998)1.00",
5260         "Zairean new zaires (1993\\u20131998)1.00",
5261         "Zairean zaire (1971\\u20131993)1.00",
5262         "Zairean zaires (1971\\u20131993)1.00",
5263         "Zambian Kwacha1.00",
5264         "Zambian kwacha1.00",
5265         "Zambian kwachas1.00",
5266         "Zimbabwean Dollar (1980\\u20132008)1.00",
5267         "Zimbabwean dollar (1980\\u20132008)1.00",
5268         "Zimbabwean dollars (1980\\u20132008)1.00",
5269         "euro1.00",
5270         "euros1.00",
5271         "Turkish lira (1922\\u20132005)1.00",
5272         "special drawing rights1.00",
5273         "Colombian real value unit1.00",
5274         "Colombian real value units1.00",
5275         "unknown currency1.00",
5276         "\\u00a31.00",
5277         "\\u00a51.00",
5278         "\\u20ab1.00",
5279         "\\u20aa1.00",
5280         "\\u20ac1.00",
5281         "\\u20b91.00",
5282         //
5283         // Following has extra text, should be parsed correctly too
5284         "$1.00 random",
5285         "USD1.00 random",
5286         "1.00 US dollar random",
5287         "1.00 US dollars random",
5288         "1.00 Afghan Afghani random",
5289         "1.00 Afghan Afghani random",
5290         "1.00 Afghan Afghanis (1927\\u20131992) random",
5291         "1.00 Afghan Afghanis random",
5292         "1.00 Albanian Lek random",
5293         "1.00 Albanian lek random",
5294         "1.00 Albanian lek\\u00eb random",
5295         "1.00 Algerian Dinar random",
5296         "1.00 Algerian dinar random",
5297         "1.00 Algerian dinars random",
5298         "1.00 Andorran Peseta random",
5299         "1.00 Andorran peseta random",
5300         "1.00 Andorran pesetas random",
5301         "1.00 Angolan Kwanza (1977\\u20131990) random",
5302         "1.00 Angolan Readjusted Kwanza (1995\\u20131999) random",
5303         "1.00 Angolan Kwanza random",
5304         "1.00 Angolan New Kwanza (1990\\u20132000) random",
5305         "1.00 Angolan kwanza (1977\\u20131991) random",
5306         "1.00 Angolan readjusted kwanza (1995\\u20131999) random",
5307         "1.00 Angolan kwanza random",
5308         "1.00 Angolan kwanzas (1977\\u20131991) random",
5309         "1.00 Angolan readjusted kwanzas (1995\\u20131999) random",
5310         "1.00 Angolan kwanzas random",
5311         "1.00 Angolan new kwanza (1990\\u20132000) random",
5312         "1.00 Angolan new kwanzas (1990\\u20132000) random",
5313         "1.00 Argentine Austral random",
5314         "1.00 Argentine Peso (1983\\u20131985) random",
5315         "1.00 Argentine Peso random",
5316         "1.00 Argentine austral random",
5317         "1.00 Argentine australs random",
5318         "1.00 Argentine peso (1983\\u20131985) random",
5319         "1.00 Argentine peso random",
5320         "1.00 Argentine pesos (1983\\u20131985) random",
5321         "1.00 Argentine pesos random",
5322         "1.00 Armenian Dram random",
5323         "1.00 Armenian dram random",
5324         "1.00 Armenian drams random",
5325         "1.00 Aruban Florin random",
5326         "1.00 Aruban florin random",
5327         "1.00 Australian Dollar random",
5328         "1.00 Australian dollar random",
5329         "1.00 Australian dollars random",
5330         "1.00 Austrian Schilling random",
5331         "1.00 Austrian schilling random",
5332         "1.00 Austrian schillings random",
5333         "1.00 Azerbaijani Manat (1993\\u20132006) random",
5334         "1.00 Azerbaijani Manat random",
5335         "1.00 Azerbaijani manat (1993\\u20132006) random",
5336         "1.00 Azerbaijani manat random",
5337         "1.00 Azerbaijani manats (1993\\u20132006) random",
5338         "1.00 Azerbaijani manats random",
5339         "1.00 Bahamian Dollar random",
5340         "1.00 Bahamian dollar random",
5341         "1.00 Bahamian dollars random",
5342         "1.00 Bahraini Dinar random",
5343         "1.00 Bahraini dinar random",
5344         "1.00 Bahraini dinars random",
5345         "1.00 Bangladeshi Taka random",
5346         "1.00 Bangladeshi taka random",
5347         "1.00 Bangladeshi takas random",
5348         "1.00 Barbadian Dollar random",
5349         "1.00 Barbadian dollar random",
5350         "1.00 Barbadian dollars random",
5351         "1.00 Belarusian Ruble (1994\\u20131999) random",
5352         "1.00 Belarusian Ruble random",
5353         "1.00 Belarusian ruble (1994\\u20131999) random",
5354         "1.00 Belarusian rubles (1994\\u20131999) random",
5355         "1.00 Belarusian ruble random",
5356         "1.00 Belarusian rubles random",
5357         "1.00 Belgian Franc (convertible) random",
5358         "1.00 Belgian Franc (financial) random",
5359         "1.00 Belgian Franc random",
5360         "1.00 Belgian franc (convertible) random",
5361         "1.00 Belgian franc (financial) random",
5362         "1.00 Belgian franc random",
5363         "1.00 Belgian francs (convertible) random",
5364         "1.00 Belgian francs (financial) random",
5365         "1.00 Belgian francs random",
5366         "1.00 Belize Dollar random",
5367         "1.00 Belize dollar random",
5368         "1.00 Belize dollars random",
5369         "1.00 Bermudan Dollar random",
5370         "1.00 Bermudan dollar random",
5371         "1.00 Bermudan dollars random",
5372         "1.00 Bhutanese Ngultrum random",
5373         "1.00 Bhutanese ngultrum random",
5374         "1.00 Bhutanese ngultrums random",
5375         "1.00 Bolivian Mvdol random",
5376         "1.00 Bolivian Peso random",
5377         "1.00 Bolivian mvdol random",
5378         "1.00 Bolivian mvdols random",
5379         "1.00 Bolivian peso random",
5380         "1.00 Bolivian pesos random",
5381         "1.00 Bolivian Boliviano random",
5382         "1.00 Bolivian Boliviano random",
5383         "1.00 Bolivian Bolivianos random",
5384         "1.00 Bosnia-Herzegovina Convertible Mark random",
5385         "1.00 Bosnia-Herzegovina Dinar (1992\\u20131994) random",
5386         "1.00 Bosnia-Herzegovina convertible mark random",
5387         "1.00 Bosnia-Herzegovina convertible marks random",
5388         "1.00 Bosnia-Herzegovina dinar (1992\\u20131994) random",
5389         "1.00 Bosnia-Herzegovina dinars (1992\\u20131994) random",
5390         "1.00 Botswanan Pula random",
5391         "1.00 Botswanan pula random",
5392         "1.00 Botswanan pulas random",
5393         "1.00 Brazilian New Cruzado (1989\\u20131990) random",
5394         "1.00 Brazilian Cruzado (1986\\u20131989) random",
5395         "1.00 Brazilian Cruzeiro (1990\\u20131993) random",
5396         "1.00 Brazilian New Cruzeiro (1967\\u20131986) random",
5397         "1.00 Brazilian Cruzeiro (1993\\u20131994) random",
5398         "1.00 Brazilian Real random",
5399         "1.00 Brazilian new cruzado (1989\\u20131990) random",
5400         "1.00 Brazilian new cruzados (1989\\u20131990) random",
5401         "1.00 Brazilian cruzado (1986\\u20131989) random",
5402         "1.00 Brazilian cruzados (1986\\u20131989) random",
5403         "1.00 Brazilian cruzeiro (1990\\u20131993) random",
5404         "1.00 Brazilian new cruzeiro (1967\\u20131986) random",
5405         "1.00 Brazilian cruzeiro (1993\\u20131994) random",
5406         "1.00 Brazilian cruzeiros (1990\\u20131993) random",
5407         "1.00 Brazilian new cruzeiros (1967\\u20131986) random",
5408         "1.00 Brazilian cruzeiros (1993\\u20131994) random",
5409         "1.00 Brazilian real random",
5410         "1.00 Brazilian reals random",
5411         "1.00 British Pound random",
5412         "1.00 British pound random",
5413         "1.00 British pounds random",
5414         "1.00 Brunei Dollar random",
5415         "1.00 Brunei dollar random",
5416         "1.00 Brunei dollars random",
5417         "1.00 Bulgarian Hard Lev random",
5418         "1.00 Bulgarian Lev random",
5419         "1.00 Bulgarian Leva random",
5420         "1.00 Bulgarian hard lev random",
5421         "1.00 Bulgarian hard leva random",
5422         "1.00 Bulgarian lev random",
5423         "1.00 Burmese Kyat random",
5424         "1.00 Burmese kyat random",
5425         "1.00 Burmese kyats random",
5426         "1.00 Burundian Franc random",
5427         "1.00 Burundian franc random",
5428         "1.00 Burundian francs random",
5429         "1.00 Cambodian Riel random",
5430         "1.00 Cambodian riel random",
5431         "1.00 Cambodian riels random",
5432         "1.00 Canadian Dollar random",
5433         "1.00 Canadian dollar random",
5434         "1.00 Canadian dollars random",
5435         "1.00 Cape Verdean Escudo random",
5436         "1.00 Cape Verdean escudo random",
5437         "1.00 Cape Verdean escudos random",
5438         "1.00 Cayman Islands Dollar random",
5439         "1.00 Cayman Islands dollar random",
5440         "1.00 Cayman Islands dollars random",
5441         "1.00 Chilean Peso random",
5442         "1.00 Chilean Unit of Account (UF) random",
5443         "1.00 Chilean peso random",
5444         "1.00 Chilean pesos random",
5445         "1.00 Chilean unit of account (UF) random",
5446         "1.00 Chilean units of account (UF) random",
5447         "1.00 Chinese Yuan random",
5448         "1.00 Chinese yuan random",
5449         "1.00 Colombian Peso random",
5450         "1.00 Colombian peso random",
5451         "1.00 Colombian pesos random",
5452         "1.00 Comorian Franc random",
5453         "1.00 Comorian franc random",
5454         "1.00 Comorian francs random",
5455         "1.00 Congolese Franc Congolais random",
5456         "1.00 Congolese franc Congolais random",
5457         "1.00 Congolese francs Congolais random",
5458         "1.00 Costa Rican Col\\u00f3n random",
5459         "1.00 Costa Rican col\\u00f3n random",
5460         "1.00 Costa Rican col\\u00f3ns random",
5461         "1.00 Croatian Dinar random",
5462         "1.00 Croatian Kuna random",
5463         "1.00 Croatian dinar random",
5464         "1.00 Croatian dinars random",
5465         "1.00 Croatian kuna random",
5466         "1.00 Croatian kunas random",
5467         "1.00 Cuban Peso random",
5468         "1.00 Cuban peso random",
5469         "1.00 Cuban pesos random",
5470         "1.00 Cypriot Pound random",
5471         "1.00 Cypriot pound random",
5472         "1.00 Cypriot pounds random",
5473         "1.00 Czech Koruna random",
5474         "1.00 Czech koruna random",
5475         "1.00 Czech korunas random",
5476         "1.00 Czechoslovak Hard Koruna random",
5477         "1.00 Czechoslovak hard koruna random",
5478         "1.00 Czechoslovak hard korunas random",
5479         "1.00 Danish Krone random",
5480         "1.00 Danish krone random",
5481         "1.00 Danish kroner random",
5482         "1.00 German Mark random",
5483         "1.00 German mark random",
5484         "1.00 German marks random",
5485         "1.00 Djiboutian Franc random",
5486         "1.00 Djiboutian franc random",
5487         "1.00 Djiboutian francs random",
5488         "1.00 Dominican Peso random",
5489         "1.00 Dominican peso random",
5490         "1.00 Dominican pesos random",
5491         "1.00 East Caribbean Dollar random",
5492         "1.00 East Caribbean dollar random",
5493         "1.00 East Caribbean dollars random",
5494         "1.00 East German Mark random",
5495         "1.00 East German mark random",
5496         "1.00 East German marks random",
5497         "1.00 Ecuadorian Sucre random",
5498         "1.00 Ecuadorian Unit of Constant Value random",
5499         "1.00 Ecuadorian sucre random",
5500         "1.00 Ecuadorian sucres random",
5501         "1.00 Ecuadorian unit of constant value random",
5502         "1.00 Ecuadorian units of constant value random",
5503         "1.00 Egyptian Pound random",
5504         "1.00 Egyptian pound random",
5505         "1.00 Egyptian pounds random",
5506         "1.00 Salvadoran Col\\u00f3n random",
5507         "1.00 Salvadoran col\\u00f3n random",
5508         "1.00 Salvadoran colones random",
5509         "1.00 Equatorial Guinean Ekwele random",
5510         "1.00 Equatorial Guinean ekwele random",
5511         "1.00 Eritrean Nakfa random",
5512         "1.00 Eritrean nakfa random",
5513         "1.00 Eritrean nakfas random",
5514         "1.00 Estonian Kroon random",
5515         "1.00 Estonian kroon random",
5516         "1.00 Estonian kroons random",
5517         "1.00 Ethiopian Birr random",
5518         "1.00 Ethiopian birr random",
5519         "1.00 Ethiopian birrs random",
5520         "1.00 European Composite Unit random",
5521         "1.00 European Currency Unit random",
5522         "1.00 European Monetary Unit random",
5523         "1.00 European Unit of Account (XBC) random",
5524         "1.00 European Unit of Account (XBD) random",
5525         "1.00 European composite unit random",
5526         "1.00 European composite units random",
5527         "1.00 European currency unit random",
5528         "1.00 European currency units random",
5529         "1.00 European monetary unit random",
5530         "1.00 European monetary units random",
5531         "1.00 European unit of account (XBC) random",
5532         "1.00 European unit of account (XBD) random",
5533         "1.00 European units of account (XBC) random",
5534         "1.00 European units of account (XBD) random",
5535         "1.00 Falkland Islands Pound random",
5536         "1.00 Falkland Islands pound random",
5537         "1.00 Falkland Islands pounds random",
5538         "1.00 Fijian Dollar random",
5539         "1.00 Fijian dollar random",
5540         "1.00 Fijian dollars random",
5541         "1.00 Finnish Markka random",
5542         "1.00 Finnish markka random",
5543         "1.00 Finnish markkas random",
5544         "1.00 French Franc random",
5545         "1.00 French Gold Franc random",
5546         "1.00 French UIC-Franc random",
5547         "1.00 French UIC-franc random",
5548         "1.00 French UIC-francs random",
5549         "1.00 French franc random",
5550         "1.00 French francs random",
5551         "1.00 French gold franc random",
5552         "1.00 French gold francs random",
5553         "1.00 Gambian Dalasi random",
5554         "1.00 Gambian dalasi random",
5555         "1.00 Gambian dalasis random",
5556         "1.00 Georgian Kupon Larit random",
5557         "1.00 Georgian Lari random",
5558         "1.00 Georgian kupon larit random",
5559         "1.00 Georgian kupon larits random",
5560         "1.00 Georgian lari random",
5561         "1.00 Georgian laris random",
5562         "1.00 Ghanaian Cedi (1979\\u20132007) random",
5563         "1.00 Ghanaian Cedi random",
5564         "1.00 Ghanaian cedi (1979\\u20132007) random",
5565         "1.00 Ghanaian cedi random",
5566         "1.00 Ghanaian cedis (1979\\u20132007) random",
5567         "1.00 Ghanaian cedis random",
5568         "1.00 Gibraltar Pound random",
5569         "1.00 Gibraltar pound random",
5570         "1.00 Gibraltar pounds random",
5571         "1.00 Gold random",
5572         "1.00 Gold random",
5573         "1.00 Greek Drachma random",
5574         "1.00 Greek drachma random",
5575         "1.00 Greek drachmas random",
5576         "1.00 Guatemalan Quetzal random",
5577         "1.00 Guatemalan quetzal random",
5578         "1.00 Guatemalan quetzals random",
5579         "1.00 Guinean Franc random",
5580         "1.00 Guinean Syli random",
5581         "1.00 Guinean franc random",
5582         "1.00 Guinean francs random",
5583         "1.00 Guinean syli random",
5584         "1.00 Guinean sylis random",
5585         "1.00 Guinea-Bissau Peso random",
5586         "1.00 Guinea-Bissau peso random",
5587         "1.00 Guinea-Bissau pesos random",
5588         "1.00 Guyanaese Dollar random",
5589         "1.00 Guyanaese dollar random",
5590         "1.00 Guyanaese dollars random",
5591         "1.00 Haitian Gourde random",
5592         "1.00 Haitian gourde random",
5593         "1.00 Haitian gourdes random",
5594         "1.00 Honduran Lempira random",
5595         "1.00 Honduran lempira random",
5596         "1.00 Honduran lempiras random",
5597         "1.00 Hong Kong Dollar random",
5598         "1.00 Hong Kong dollar random",
5599         "1.00 Hong Kong dollars random",
5600         "1.00 Hungarian Forint random",
5601         "1.00 Hungarian forint random",
5602         "1.00 Hungarian forints random",
5603         "1.00 Icelandic Kr\\u00f3na random",
5604         "1.00 Icelandic kr\\u00f3na random",
5605         "1.00 Icelandic kr\\u00f3nur random",
5606         "1.00 Indian Rupee random",
5607         "1.00 Indian rupee random",
5608         "1.00 Indian rupees random",
5609         "1.00 Indonesian Rupiah random",
5610         "1.00 Indonesian rupiah random",
5611         "1.00 Indonesian rupiahs random",
5612         "1.00 Iranian Rial random",
5613         "1.00 Iranian rial random",
5614         "1.00 Iranian rials random",
5615         "1.00 Iraqi Dinar random",
5616         "1.00 Iraqi dinar random",
5617         "1.00 Iraqi dinars random",
5618         "1.00 Irish Pound random",
5619         "1.00 Irish pound random",
5620         "1.00 Irish pounds random",
5621         "1.00 Israeli Pound random",
5622         "1.00 Israeli new shekel random",
5623         "1.00 Israeli pound random",
5624         "1.00 Israeli pounds random",
5625         "1.00 Italian Lira random",
5626         "1.00 Italian lira random",
5627         "1.00 Italian liras random",
5628         "1.00 Jamaican Dollar random",
5629         "1.00 Jamaican dollar random",
5630         "1.00 Jamaican dollars random",
5631         "1.00 Japanese Yen random",
5632         "1.00 Japanese yen random",
5633         "1.00 Jordanian Dinar random",
5634         "1.00 Jordanian dinar random",
5635         "1.00 Jordanian dinars random",
5636         "1.00 Kazakhstani Tenge random",
5637         "1.00 Kazakhstani tenge random",
5638         "1.00 Kazakhstani tenges random",
5639         "1.00 Kenyan Shilling random",
5640         "1.00 Kenyan shilling random",
5641         "1.00 Kenyan shillings random",
5642         "1.00 Kuwaiti Dinar random",
5643         "1.00 Kuwaiti dinar random",
5644         "1.00 Kuwaiti dinars random",
5645         "1.00 Kyrgystani Som random",
5646         "1.00 Kyrgystani som random",
5647         "1.00 Kyrgystani soms random",
5648         "1.00 Laotian Kip random",
5649         "1.00 Laotian kip random",
5650         "1.00 Laotian kips random",
5651         "1.00 Latvian Lats random",
5652         "1.00 Latvian Ruble random",
5653         "1.00 Latvian lats random",
5654         "1.00 Latvian lati random",
5655         "1.00 Latvian ruble random",
5656         "1.00 Latvian rubles random",
5657         "1.00 Lebanese Pound random",
5658         "1.00 Lebanese pound random",
5659         "1.00 Lebanese pounds random",
5660         "1.00 Lesotho Loti random",
5661         "1.00 Lesotho loti random",
5662         "1.00 Lesotho lotis random",
5663         "1.00 Liberian Dollar random",
5664         "1.00 Liberian dollar random",
5665         "1.00 Liberian dollars random",
5666         "1.00 Libyan Dinar random",
5667         "1.00 Libyan dinar random",
5668         "1.00 Libyan dinars random",
5669         "1.00 Lithuanian Litas random",
5670         "1.00 Lithuanian Talonas random",
5671         "1.00 Lithuanian litas random",
5672         "1.00 Lithuanian litai random",
5673         "1.00 Lithuanian talonas random",
5674         "1.00 Lithuanian talonases random",
5675         "1.00 Luxembourgian Convertible Franc random",
5676         "1.00 Luxembourg Financial Franc random",
5677         "1.00 Luxembourgian Franc random",
5678         "1.00 Luxembourgian convertible franc random",
5679         "1.00 Luxembourgian convertible francs random",
5680         "1.00 Luxembourg financial franc random",
5681         "1.00 Luxembourg financial francs random",
5682         "1.00 Luxembourgian franc random",
5683         "1.00 Luxembourgian francs random",
5684         "1.00 Macanese Pataca random",
5685         "1.00 Macanese pataca random",
5686         "1.00 Macanese patacas random",
5687         "1.00 Macedonian Denar random",
5688         "1.00 Macedonian denar random",
5689         "1.00 Macedonian denari random",
5690         "1.00 Malagasy Ariaries random",
5691         "1.00 Malagasy Ariary random",
5692         "1.00 Malagasy Ariary random",
5693         "1.00 Malagasy Franc random",
5694         "1.00 Malagasy franc random",
5695         "1.00 Malagasy francs random",
5696         "1.00 Malawian Kwacha random",
5697         "1.00 Malawian Kwacha random",
5698         "1.00 Malawian Kwachas random",
5699         "1.00 Malaysian Ringgit random",
5700         "1.00 Malaysian ringgit random",
5701         "1.00 Malaysian ringgits random",
5702         "1.00 Maldivian Rufiyaa random",
5703         "1.00 Maldivian rufiyaa random",
5704         "1.00 Maldivian rufiyaas random",
5705         "1.00 Malian Franc random",
5706         "1.00 Malian franc random",
5707         "1.00 Malian francs random",
5708         "1.00 Maltese Lira random",
5709         "1.00 Maltese Pound random",
5710         "1.00 Maltese lira random",
5711         "1.00 Maltese liras random",
5712         "1.00 Maltese pound random",
5713         "1.00 Maltese pounds random",
5714         "1.00 Mauritanian Ouguiya random",
5715         "1.00 Mauritanian ouguiya random",
5716         "1.00 Mauritanian ouguiyas random",
5717         "1.00 Mauritian Rupee random",
5718         "1.00 Mauritian rupee random",
5719         "1.00 Mauritian rupees random",
5720         "1.00 Mexican Peso random",
5721         "1.00 Mexican Silver Peso (1861\\u20131992) random",
5722         "1.00 Mexican Investment Unit random",
5723         "1.00 Mexican peso random",
5724         "1.00 Mexican pesos random",
5725         "1.00 Mexican silver peso (1861\\u20131992) random",
5726         "1.00 Mexican silver pesos (1861\\u20131992) random",
5727         "1.00 Mexican investment unit random",
5728         "1.00 Mexican investment units random",
5729         "1.00 Moldovan Leu random",
5730         "1.00 Moldovan leu random",
5731         "1.00 Moldovan lei random",
5732         "1.00 Mongolian Tugrik random",
5733         "1.00 Mongolian tugrik random",
5734         "1.00 Mongolian tugriks random",
5735         "1.00 Moroccan Dirham random",
5736         "1.00 Moroccan Franc random",
5737         "1.00 Moroccan dirham random",
5738         "1.00 Moroccan dirhams random",
5739         "1.00 Moroccan franc random",
5740         "1.00 Moroccan francs random",
5741         "1.00 Mozambican Escudo random",
5742         "1.00 Mozambican Metical random",
5743         "1.00 Mozambican escudo random",
5744         "1.00 Mozambican escudos random",
5745         "1.00 Mozambican metical random",
5746         "1.00 Mozambican meticals random",
5747         "1.00 Myanmar Kyat random",
5748         "1.00 Myanmar kyat random",
5749         "1.00 Myanmar kyats random",
5750         "1.00 Namibian Dollar random",
5751         "1.00 Namibian dollar random",
5752         "1.00 Namibian dollars random",
5753         "1.00 Nepalese Rupee random",
5754         "1.00 Nepalese rupee random",
5755         "1.00 Nepalese rupees random",
5756         "1.00 Netherlands Antillean Guilder random",
5757         "1.00 Netherlands Antillean guilder random",
5758         "1.00 Netherlands Antillean guilders random",
5759         "1.00 Dutch Guilder random",
5760         "1.00 Dutch guilder random",
5761         "1.00 Dutch guilders random",
5762         "1.00 Israeli New Shekel random",
5763         "1.00 Israeli new shekels random",
5764         "1.00 New Zealand Dollar random",
5765         "1.00 New Zealand dollar random",
5766         "1.00 New Zealand dollars random",
5767         "1.00 Nicaraguan C\\u00f3rdoba random",
5768         "1.00 Nicaraguan C\\u00f3rdoba (1988\\u20131991) random",
5769         "1.00 Nicaraguan c\\u00f3rdoba random",
5770         "1.00 Nicaraguan c\\u00f3rdoba random",
5771         "1.00 Nicaraguan c\\u00f3rdoba (1988\\u20131991) random",
5772         "1.00 Nicaraguan c\\u00f3rdobas (1988\\u20131991) random",
5773         "1.00 Nigerian Naira random",
5774         "1.00 Nigerian naira random",
5775         "1.00 Nigerian nairas random",
5776         "1.00 North Korean Won random",
5777         "1.00 North Korean won random",
5778         "1.00 North Korean won random",
5779         "1.00 Norwegian Krone random",
5780         "1.00 Norwegian krone random",
5781         "1.00 Norwegian kroner random",
5782         "1.00 Mozambican Metical (1980\\u20132006) random",
5783         "1.00 Mozambican metical (1980\\u20132006) random",
5784         "1.00 Mozambican meticals (1980\\u20132006) random",
5785         "1.00 Romanian Lei (1952\\u20132006) random",
5786         "1.00 Romanian Leu (1952\\u20132006) random",
5787         "1.00 Romanian leu (1952\\u20132006) random",
5788         "1.00 Serbian Dinar (2002\\u20132006) random",
5789         "1.00 Serbian dinar (2002\\u20132006) random",
5790         "1.00 Serbian dinars (2002\\u20132006) random",
5791         "1.00 Sudanese Dinar (1992\\u20132007) random",
5792         "1.00 Sudanese Pound (1957\\u20131998) random",
5793         "1.00 Sudanese dinar (1992\\u20132007) random",
5794         "1.00 Sudanese dinars (1992\\u20132007) random",
5795         "1.00 Sudanese pound (1957\\u20131998) random",
5796         "1.00 Sudanese pounds (1957\\u20131998) random",
5797         "1.00 Turkish Lira (1922\\u20132005) random",
5798         "1.00 Turkish Lira (1922\\u20132005) random",
5799         "1.00 Omani Rial random",
5800         "1.00 Omani rial random",
5801         "1.00 Omani rials random",
5802         "1.00 Pakistani Rupee random",
5803         "1.00 Pakistani rupee random",
5804         "1.00 Pakistani rupees random",
5805         "1.00 Palladium random",
5806         "1.00 Palladium random",
5807         "1.00 Panamanian Balboa random",
5808         "1.00 Panamanian balboa random",
5809         "1.00 Panamanian balboas random",
5810         "1.00 Papua New Guinean Kina random",
5811         "1.00 Papua New Guinean kina random",
5812         "1.00 Papua New Guinean kina random",
5813         "1.00 Paraguayan Guarani random",
5814         "1.00 Paraguayan guarani random",
5815         "1.00 Paraguayan guaranis random",
5816         "1.00 Peruvian Inti random",
5817         "1.00 Peruvian Sol random",
5818         "1.00 Peruvian Sol (1863\\u20131965) random",
5819         "1.00 Peruvian inti random",
5820         "1.00 Peruvian intis random",
5821         "1.00 Peruvian sol random",
5822         "1.00 Peruvian soles random",
5823         "1.00 Peruvian sol (1863\\u20131965) random",
5824         "1.00 Peruvian soles (1863\\u20131965) random",
5825         "1.00 Philippine Piso random",
5826         "1.00 Philippine piso random",
5827         "1.00 Philippine pisos random",
5828         "1.00 Platinum random",
5829         "1.00 Platinum random",
5830         "1.00 Polish Zloty (1950\\u20131995) random",
5831         "1.00 Polish Zloty random",
5832         "1.00 Polish zlotys random",
5833         "1.00 Polish zloty (PLZ) random",
5834         "1.00 Polish zloty random",
5835         "1.00 Polish zlotys (PLZ) random",
5836         "1.00 Portuguese Escudo random",
5837         "1.00 Portuguese Guinea Escudo random",
5838         "1.00 Portuguese Guinea escudo random",
5839         "1.00 Portuguese Guinea escudos random",
5840         "1.00 Portuguese escudo random",
5841         "1.00 Portuguese escudos random",
5842         "1.00 Qatari Rial random",
5843         "1.00 Qatari rial random",
5844         "1.00 Qatari rials random",
5845         "1.00 RINET Funds random",
5846         "1.00 RINET Funds random",
5847         "1.00 Rhodesian Dollar random",
5848         "1.00 Rhodesian dollar random",
5849         "1.00 Rhodesian dollars random",
5850         "1.00 Romanian Leu random",
5851         "1.00 Romanian lei random",
5852         "1.00 Romanian leu random",
5853         "1.00 Russian Ruble (1991\\u20131998) random",
5854         "1.00 Russian Ruble random",
5855         "1.00 Russian ruble (1991\\u20131998) random",
5856         "1.00 Russian ruble random",
5857         "1.00 Russian rubles (1991\\u20131998) random",
5858         "1.00 Russian rubles random",
5859         "1.00 Rwandan Franc random",
5860         "1.00 Rwandan franc random",
5861         "1.00 Rwandan francs random",
5862         "1.00 St. Helena Pound random",
5863         "1.00 St. Helena pound random",
5864         "1.00 St. Helena pounds random",
5865         "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra random",
5866         "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra random",
5867         "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras random",
5868         "1.00 Saudi Riyal random",
5869         "1.00 Saudi riyal random",
5870         "1.00 Saudi riyals random",
5871         "1.00 Serbian Dinar random",
5872         "1.00 Serbian dinar random",
5873         "1.00 Serbian dinars random",
5874         "1.00 Seychellois Rupee random",
5875         "1.00 Seychellois rupee random",
5876         "1.00 Seychellois rupees random",
5877         "1.00 Sierra Leonean Leone random",
5878         "1.00 Sierra Leonean leone random",
5879         "1.00 Sierra Leonean leones random",
5880         "1.00 Singapore Dollar random",
5881         "1.00 Singapore dollar random",
5882         "1.00 Singapore dollars random",
5883         "1.00 Slovak Koruna random",
5884         "1.00 Slovak koruna random",
5885         "1.00 Slovak korunas random",
5886         "1.00 Slovenian Tolar random",
5887         "1.00 Slovenian tolar random",
5888         "1.00 Slovenian tolars random",
5889         "1.00 Solomon Islands Dollar random",
5890         "1.00 Solomon Islands dollar random",
5891         "1.00 Solomon Islands dollars random",
5892         "1.00 Somali Shilling random",
5893         "1.00 Somali shilling random",
5894         "1.00 Somali shillings random",
5895         "1.00 South African Rand (financial) random",
5896         "1.00 South African Rand random",
5897         "1.00 South African rand (financial) random",
5898         "1.00 South African rand random",
5899         "1.00 South African rands (financial) random",
5900         "1.00 South African rand random",
5901         "1.00 South Korean Won random",
5902         "1.00 South Korean won random",
5903         "1.00 South Korean won random",
5904         "1.00 Soviet Rouble random",
5905         "1.00 Soviet rouble random",
5906         "1.00 Soviet roubles random",
5907         "1.00 Spanish Peseta (A account) random",
5908         "1.00 Spanish Peseta (convertible account) random",
5909         "1.00 Spanish Peseta random",
5910         "1.00 Spanish peseta (A account) random",
5911         "1.00 Spanish peseta (convertible account) random",
5912         "1.00 Spanish peseta random",
5913         "1.00 Spanish pesetas (A account) random",
5914         "1.00 Spanish pesetas (convertible account) random",
5915         "1.00 Spanish pesetas random",
5916         "1.00 Special Drawing Rights random",
5917         "1.00 Sri Lankan Rupee random",
5918         "1.00 Sri Lankan rupee random",
5919         "1.00 Sri Lankan rupees random",
5920         "1.00 Sudanese Pound random",
5921         "1.00 Sudanese pound random",
5922         "1.00 Sudanese pounds random",
5923         "1.00 Surinamese Dollar random",
5924         "1.00 Surinamese dollar random",
5925         "1.00 Surinamese dollars random",
5926         "1.00 Surinamese Guilder random",
5927         "1.00 Surinamese guilder random",
5928         "1.00 Surinamese guilders random",
5929         "1.00 Swazi Lilangeni random",
5930         "1.00 Swazi lilangeni random",
5931         "1.00 Swazi emalangeni random",
5932         "1.00 Swedish Krona random",
5933         "1.00 Swedish krona random",
5934         "1.00 Swedish kronor random",
5935         "1.00 Swiss Franc random",
5936         "1.00 Swiss franc random",
5937         "1.00 Swiss francs random",
5938         "1.00 Syrian Pound random",
5939         "1.00 Syrian pound random",
5940         "1.00 Syrian pounds random",
5941         "1.00 New Taiwan Dollar random",
5942         "1.00 New Taiwan dollar random",
5943         "1.00 New Taiwan dollars random",
5944         "1.00 Tajikistani Ruble random",
5945         "1.00 Tajikistani Somoni random",
5946         "1.00 Tajikistani ruble random",
5947         "1.00 Tajikistani rubles random",
5948         "1.00 Tajikistani somoni random",
5949         "1.00 Tajikistani somonis random",
5950         "1.00 Tanzanian Shilling random",
5951         "1.00 Tanzanian shilling random",
5952         "1.00 Tanzanian shillings random",
5953         "1.00 Testing Currency Code random",
5954         "1.00 Testing Currency Code random",
5955         "1.00 Thai Baht random",
5956         "1.00 Thai baht random",
5957         "1.00 Thai baht random",
5958         "1.00 Timorese Escudo random",
5959         "1.00 Timorese escudo random",
5960         "1.00 Timorese escudos random",
5961         "1.00 Trinidad & Tobago Dollar random",
5962         "1.00 Trinidad & Tobago dollar random",
5963         "1.00 Trinidad & Tobago dollars random",
5964         "1.00 Tunisian Dinar random",
5965         "1.00 Tunisian dinar random",
5966         "1.00 Tunisian dinars random",
5967         "1.00 Turkish Lira random",
5968         "1.00 Turkish Lira random",
5969         "1.00 Turkish lira random",
5970         "1.00 Turkmenistani Manat random",
5971         "1.00 Turkmenistani manat random",
5972         "1.00 Turkmenistani manat random",
5973         "1.00 US Dollar (Next day) random",
5974         "1.00 US Dollar (Same day) random",
5975         "1.00 US Dollar random",
5976         "1.00 US dollar (next day) random",
5977         "1.00 US dollar (same day) random",
5978         "1.00 US dollar random",
5979         "1.00 US dollars (next day) random",
5980         "1.00 US dollars (same day) random",
5981         "1.00 US dollars random",
5982         "1.00 Ugandan Shilling (1966\\u20131987) random",
5983         "1.00 Ugandan Shilling random",
5984         "1.00 Ugandan shilling (1966\\u20131987) random",
5985         "1.00 Ugandan shilling random",
5986         "1.00 Ugandan shillings (1966\\u20131987) random",
5987         "1.00 Ugandan shillings random",
5988         "1.00 Ukrainian Hryvnia random",
5989         "1.00 Ukrainian Karbovanets random",
5990         "1.00 Ukrainian hryvnia random",
5991         "1.00 Ukrainian hryvnias random",
5992         "1.00 Ukrainian karbovanets random",
5993         "1.00 Ukrainian karbovantsiv random",
5994         "1.00 Colombian Real Value Unit random",
5995         "1.00 United Arab Emirates Dirham random",
5996         "1.00 Unknown Currency random",
5997         "1.00 Uruguayan Peso (1975\\u20131993) random",
5998         "1.00 Uruguayan Peso random",
5999         "1.00 Uruguayan Peso (Indexed Units) random",
6000         "1.00 Uruguayan peso (1975\\u20131993) random",
6001         "1.00 Uruguayan peso (indexed units) random",
6002         "1.00 Uruguayan peso random",
6003         "1.00 Uruguayan pesos (1975\\u20131993) random",
6004         "1.00 Uruguayan pesos (indexed units) random",
6005         "1.00 Uzbekistani Som random",
6006         "1.00 Uzbekistani som random",
6007         "1.00 Uzbekistani som random",
6008         "1.00 Vanuatu Vatu random",
6009         "1.00 Vanuatu vatu random",
6010         "1.00 Vanuatu vatus random",
6011         "1.00 Venezuelan Bol\\u00edvar random",
6012         "1.00 Venezuelan Bol\\u00edvar (1871\\u20132008) random",
6013         "1.00 Venezuelan bol\\u00edvar random",
6014         "1.00 Venezuelan bol\\u00edvars random",
6015         "1.00 Venezuelan bol\\u00edvar (1871\\u20132008) random",
6016         "1.00 Venezuelan bol\\u00edvars (1871\\u20132008) random",
6017         "1.00 Vietnamese Dong random",
6018         "1.00 Vietnamese dong random",
6019         "1.00 Vietnamese dong random",
6020         "1.00 WIR Euro random",
6021         "1.00 WIR Franc random",
6022         "1.00 WIR euro random",
6023         "1.00 WIR euros random",
6024         "1.00 WIR franc random",
6025         "1.00 WIR francs random",
6026         "1.00 Samoan Tala random",
6027         "1.00 Samoan tala random",
6028         "1.00 Samoan tala random",
6029         "1.00 Yemeni Dinar random",
6030         "1.00 Yemeni Rial random",
6031         "1.00 Yemeni dinar random",
6032         "1.00 Yemeni dinars random",
6033         "1.00 Yemeni rial random",
6034         "1.00 Yemeni rials random",
6035         "1.00 Yugoslavian Convertible Dinar (1990\\u20131992) random",
6036         "1.00 Yugoslavian Hard Dinar (1966\\u20131990) random",
6037         "1.00 Yugoslavian New Dinar (1994\\u20132002) random",
6038         "1.00 Yugoslavian convertible dinar (1990\\u20131992) random",
6039         "1.00 Yugoslavian convertible dinars (1990\\u20131992) random",
6040         "1.00 Yugoslavian hard dinar (1966\\u20131990) random",
6041         "1.00 Yugoslavian hard dinars (1966\\u20131990) random",
6042         "1.00 Yugoslavian new dinar (1994\\u20132002) random",
6043         "1.00 Yugoslavian new dinars (1994\\u20132002) random",
6044         "1.00 Zairean New Zaire (1993\\u20131998) random",
6045         "1.00 Zairean Zaire (1971\\u20131993) random",
6046         "1.00 Zairean new zaire (1993\\u20131998) random",
6047         "1.00 Zairean new zaires (1993\\u20131998) random",
6048         "1.00 Zairean zaire (1971\\u20131993) random",
6049         "1.00 Zairean zaires (1971\\u20131993) random",
6050         "1.00 Zambian Kwacha random",
6051         "1.00 Zambian kwacha random",
6052         "1.00 Zambian kwachas random",
6053         "1.00 Zimbabwean Dollar (1980\\u20132008) random",
6054         "1.00 Zimbabwean dollar (1980\\u20132008) random",
6055         "1.00 Zimbabwean dollars (1980\\u20132008) random",
6056         "1.00 euro random",
6057         "1.00 euros random",
6058         "1.00 Turkish lira (1922\\u20132005) random",
6059         "1.00 special drawing rights random",
6060         "1.00 Colombian real value unit random",
6061         "1.00 Colombian real value units random",
6062         "1.00 unknown currency random",
6063     };
6064 
6065     const char* WRONG_DATA[] = {
6066         // Following are missing one last char in the currency name
6067         "1.00 Nicaraguan Cordob",
6068         "1.00 Namibian Dolla",
6069         "1.00 Namibian dolla",
6070         "1.00 Nepalese Rupe",
6071         "1.00 Nepalese rupe",
6072         "1.00 Netherlands Antillean Guilde",
6073         "1.00 Netherlands Antillean guilde",
6074         "1.00 Dutch Guilde",
6075         "1.00 Dutch guilde",
6076         "1.00 Israeli New Sheqe",
6077         "1.00 New Zealand Dolla",
6078         "1.00 New Zealand dolla",
6079         "1.00 Nicaraguan cordob",
6080         "1.00 Nigerian Nair",
6081         "1.00 Nigerian nair",
6082         "1.00 North Korean Wo",
6083         "1.00 North Korean wo",
6084         "1.00 Norwegian Kron",
6085         "1.00 Norwegian kron",
6086         "1.00 US dolla",
6087         "1.00",
6088         "A1.00",
6089         "AD1.00",
6090         "AE1.00",
6091         "AF1.00",
6092         "AL1.00",
6093         "AM1.00",
6094         "AN1.00",
6095         "AO1.00",
6096         "AR1.00",
6097         "AT1.00",
6098         "AU1.00",
6099         "AW1.00",
6100         "AZ1.00",
6101         "Afghan Afghan1.00",
6102         "Afghan Afghani (1927\\u201320021.00",
6103         "Afl1.00",
6104         "Albanian Le1.00",
6105         "Algerian Dina1.00",
6106         "Andorran Peset1.00",
6107         "Angolan Kwanz1.00",
6108         "Angolan Kwanza (1977\\u201319901.00",
6109         "Angolan Readjusted Kwanza (1995\\u201319991.00",
6110         "Angolan New Kwanza (1990\\u201320001.00",
6111         "Argentine Austra1.00",
6112         "Argentine Pes1.00",
6113         "Argentine Peso (1983\\u201319851.00",
6114         "Armenian Dra1.00",
6115         "Aruban Flori1.00",
6116         "Australian Dolla1.00",
6117         "Austrian Schillin1.00",
6118         "Azerbaijani Mana1.00",
6119         "Azerbaijani Manat (1993\\u201320061.00",
6120         "B1.00",
6121         "BA1.00",
6122         "BB1.00",
6123         "BE1.00",
6124         "BG1.00",
6125         "BH1.00",
6126         "BI1.00",
6127         "BM1.00",
6128         "BN1.00",
6129         "BO1.00",
6130         "BR1.00",
6131         "BS1.00",
6132         "BT1.00",
6133         "BU1.00",
6134         "BW1.00",
6135         "BY1.00",
6136         "BZ1.00",
6137         "Bahamian Dolla1.00",
6138         "Bahraini Dina1.00",
6139         "Bangladeshi Tak1.00",
6140         "Barbadian Dolla1.00",
6141         "Bds1.00",
6142         "Belarusian Ruble (1994\\u201319991.00",
6143         "Belarusian Rubl1.00",
6144         "Belgian Fran1.00",
6145         "Belgian Franc (convertible1.00",
6146         "Belgian Franc (financial1.00",
6147         "Belize Dolla1.00",
6148         "Bermudan Dolla1.00",
6149         "Bhutanese Ngultru1.00",
6150         "Bolivian Mvdo1.00",
6151         "Bolivian Pes1.00",
6152         "Bolivian Bolivian1.00",
6153         "Bosnia-Herzegovina Convertible Mar1.00",
6154         "Bosnia-Herzegovina Dina1.00",
6155         "Botswanan Pul1.00",
6156         "Brazilian Cruzad1.00",
6157         "Brazilian Cruzado Nov1.00",
6158         "Brazilian Cruzeir1.00",
6159         "Brazilian Cruzeiro (1990\\u201319931.00",
6160         "Brazilian New Cruzeiro (1967\\u201319861.00",
6161         "Brazilian Rea1.00",
6162         "British Pound Sterlin1.00",
6163         "Brunei Dolla1.00",
6164         "Bulgarian Hard Le1.00",
6165         "Bulgarian Le1.00",
6166         "Burmese Kya1.00",
6167         "Burundian Fran1.00",
6168         "C1.00",
6169         "CA1.00",
6170         "CD1.00",
6171         "CFP Fran1.00",
6172         "CFP1.00",
6173         "CH1.00",
6174         "CL1.00",
6175         "CN1.00",
6176         "CO1.00",
6177         "CS1.00",
6178         "CU1.00",
6179         "CV1.00",
6180         "CY1.00",
6181         "CZ1.00",
6182         "Cambodian Rie1.00",
6183         "Canadian Dolla1.00",
6184         "Cape Verdean Escud1.00",
6185         "Cayman Islands Dolla1.00",
6186         "Chilean Pes1.00",
6187         "Chilean Unit of Accoun1.00",
6188         "Chinese Yua1.00",
6189         "Colombian Pes1.00",
6190         "Comoro Fran1.00",
6191         "Congolese Fran1.00",
6192         "Costa Rican Col\\u00f31.00",
6193         "Croatian Dina1.00",
6194         "Croatian Kun1.00",
6195         "Cuban Pes1.00",
6196         "Cypriot Poun1.00",
6197         "Czech Republic Korun1.00",
6198         "Czechoslovak Hard Korun1.00",
6199         "D1.00",
6200         "DD1.00",
6201         "DE1.00",
6202         "DJ1.00",
6203         "DK1.00",
6204         "DO1.00",
6205         "DZ1.00",
6206         "Danish Kron1.00",
6207         "German Mar1.00",
6208         "Djiboutian Fran1.00",
6209         "Dk1.00",
6210         "Dominican Pes1.00",
6211         "EC1.00",
6212         "EE1.00",
6213         "EG1.00",
6214         "EQ1.00",
6215         "ER1.00",
6216         "ES1.00",
6217         "ET1.00",
6218         "EU1.00",
6219         "East Caribbean Dolla1.00",
6220         "East German Ostmar1.00",
6221         "Ecuadorian Sucr1.00",
6222         "Ecuadorian Unit of Constant Valu1.00",
6223         "Egyptian Poun1.00",
6224         "Ekwel1.00",
6225         "Salvadoran Col\\u00f31.00",
6226         "Equatorial Guinean Ekwel1.00",
6227         "Eritrean Nakf1.00",
6228         "Es1.00",
6229         "Estonian Kroo1.00",
6230         "Ethiopian Bir1.00",
6231         "Eur1.00",
6232         "European Composite Uni1.00",
6233         "European Currency Uni1.00",
6234         "European Monetary Uni1.00",
6235         "European Unit of Account (XBC1.00",
6236         "European Unit of Account (XBD1.00",
6237         "F1.00",
6238         "FB1.00",
6239         "FI1.00",
6240         "FJ1.00",
6241         "FK1.00",
6242         "FR1.00",
6243         "Falkland Islands Poun1.00",
6244         "Fd1.00",
6245         "Fijian Dolla1.00",
6246         "Finnish Markk1.00",
6247         "Fr1.00",
6248         "French Fran1.00",
6249         "French Gold Fran1.00",
6250         "French UIC-Fran1.00",
6251         "G1.00",
6252         "GB1.00",
6253         "GE1.00",
6254         "GH1.00",
6255         "GI1.00",
6256         "GM1.00",
6257         "GN1.00",
6258         "GQ1.00",
6259         "GR1.00",
6260         "GT1.00",
6261         "GW1.00",
6262         "GY1.00",
6263         "Gambian Dalas1.00",
6264         "Georgian Kupon Lari1.00",
6265         "Georgian Lar1.00",
6266         "Ghanaian Ced1.00",
6267         "Ghanaian Cedi (1979\\u201320071.00",
6268         "Gibraltar Poun1.00",
6269         "Gol1.00",
6270         "Greek Drachm1.00",
6271         "Guatemalan Quetza1.00",
6272         "Guinean Fran1.00",
6273         "Guinean Syl1.00",
6274         "Guinea-Bissau Pes1.00",
6275         "Guyanaese Dolla1.00",
6276         "HK1.00",
6277         "HN1.00",
6278         "HR1.00",
6279         "HT1.00",
6280         "HU1.00",
6281         "Haitian Gourd1.00",
6282         "Honduran Lempir1.00",
6283         "Hong Kong Dolla1.00",
6284         "Hungarian Forin1.00",
6285         "I1.00",
6286         "IE1.00",
6287         "IL1.00",
6288         "IN1.00",
6289         "IQ1.00",
6290         "IR1.00",
6291         "IS1.00",
6292         "IT1.00",
6293         "Icelandic Kron1.00",
6294         "Indian Rupe1.00",
6295         "Indonesian Rupia1.00",
6296         "Iranian Ria1.00",
6297         "Iraqi Dina1.00",
6298         "Irish Poun1.00",
6299         "Israeli Poun1.00",
6300         "Italian Lir1.00",
6301         "J1.00",
6302         "JM1.00",
6303         "JO1.00",
6304         "JP1.00",
6305         "Jamaican Dolla1.00",
6306         "Japanese Ye1.00",
6307         "Jordanian Dina1.00",
6308         "K S1.00",
6309         "K1.00",
6310         "KE1.00",
6311         "KG1.00",
6312         "KH1.00",
6313         "KP1.00",
6314         "KR1.00",
6315         "KW1.00",
6316         "KY1.00",
6317         "KZ1.00",
6318         "Kazakhstani Teng1.00",
6319         "Kenyan Shillin1.00",
6320         "Kuwaiti Dina1.00",
6321         "Kyrgystani So1.00",
6322         "LA1.00",
6323         "LB1.00",
6324         "LK1.00",
6325         "LR1.00",
6326         "LT1.00",
6327         "LU1.00",
6328         "LV1.00",
6329         "LY1.00",
6330         "Laotian Ki1.00",
6331         "Latvian Lat1.00",
6332         "Latvian Rubl1.00",
6333         "Lebanese Poun1.00",
6334         "Lesotho Lot1.00",
6335         "Liberian Dolla1.00",
6336         "Libyan Dina1.00",
6337         "Lithuanian Lit1.00",
6338         "Lithuanian Talona1.00",
6339         "Luxembourgian Convertible Fran1.00",
6340         "Luxembourg Financial Fran1.00",
6341         "Luxembourgian Fran1.00",
6342         "MA1.00",
6343         "MD1.00",
6344         "MDe1.00",
6345         "MEX1.00",
6346         "MG1.00",
6347         "ML1.00",
6348         "MM1.00",
6349         "MN1.00",
6350         "MO1.00",
6351         "MR1.00",
6352         "MT1.00",
6353         "MU1.00",
6354         "MV1.00",
6355         "MW1.00",
6356         "MX1.00",
6357         "MY1.00",
6358         "MZ1.00",
6359         "Macanese Patac1.00",
6360         "Macedonian Dena1.00",
6361         "Malagasy Ariar1.00",
6362         "Malagasy Fran1.00",
6363         "Malawian Kwach1.00",
6364         "Malaysian Ringgi1.00",
6365         "Maldivian Rufiya1.00",
6366         "Malian Fran1.00",
6367         "Malot1.00",
6368         "Maltese Lir1.00",
6369         "Maltese Poun1.00",
6370         "Mauritanian Ouguiy1.00",
6371         "Mauritian Rupe1.00",
6372         "Mexican Pes1.00",
6373         "Mexican Silver Peso (1861\\u201319921.00",
6374         "Mexican Investment Uni1.00",
6375         "Moldovan Le1.00",
6376         "Mongolian Tugri1.00",
6377         "Moroccan Dirha1.00",
6378         "Moroccan Fran1.00",
6379         "Mozambican Escud1.00",
6380         "Mozambican Metica1.00",
6381         "Myanmar Kya1.00",
6382         "N1.00",
6383         "NA1.00",
6384         "NAf1.00",
6385         "NG1.00",
6386         "NI1.00",
6387         "NK1.00",
6388         "NL1.00",
6389         "NO1.00",
6390         "NP1.00",
6391         "NT1.00",
6392         "Namibian Dolla1.00",
6393         "Nepalese Rupe1.00",
6394         "Netherlands Antillean Guilde1.00",
6395         "Dutch Guilde1.00",
6396         "Israeli New Sheqe1.00",
6397         "New Zealand Dolla1.00",
6398         "Nicaraguan C\\u00f3rdoba (1988\\u201319911.00",
6399         "Nicaraguan C\\u00f3rdob1.00",
6400         "Nigerian Nair1.00",
6401         "North Korean Wo1.00",
6402         "Norwegian Kron1.00",
6403         "Nr1.00",
6404         "OM1.00",
6405         "Old Mozambican Metica1.00",
6406         "Romanian Leu (1952\\u201320061.00",
6407         "Serbian Dinar (2002\\u201320061.00",
6408         "Sudanese Dinar (1992\\u201320071.00",
6409         "Sudanese Pound (1957\\u201319981.00",
6410         "Turkish Lira (1922\\u201320051.00",
6411         "Omani Ria1.00",
6412         "PA1.00",
6413         "PE1.00",
6414         "PG1.00",
6415         "PH1.00",
6416         "PK1.00",
6417         "PL1.00",
6418         "PT1.00",
6419         "PY1.00",
6420         "Pakistani Rupe1.00",
6421         "Palladiu1.00",
6422         "Panamanian Balbo1.00",
6423         "Papua New Guinean Kin1.00",
6424         "Paraguayan Guaran1.00",
6425         "Peruvian Int1.00",
6426         "Peruvian Sol (1863\\u201319651.00",
6427         "Peruvian Sol Nuev1.00",
6428         "Philippine Pes1.00",
6429         "Platinu1.00",
6430         "Polish Zlot1.00",
6431         "Polish Zloty (1950\\u201319951.00",
6432         "Portuguese Escud1.00",
6433         "Portuguese Guinea Escud1.00",
6434         "Pr1.00",
6435         "QA1.00",
6436         "Qatari Ria1.00",
6437         "RD1.00",
6438         "RH1.00",
6439         "RINET Fund1.00",
6440         "RS1.00",
6441         "RU1.00",
6442         "RW1.00",
6443         "Rb1.00",
6444         "Rhodesian Dolla1.00",
6445         "Romanian Le1.00",
6446         "Russian Rubl1.00",
6447         "Russian Ruble (1991\\u201319981.00",
6448         "Rwandan Fran1.00",
6449         "S1.00",
6450         "SA1.00",
6451         "SB1.00",
6452         "SC1.00",
6453         "SD1.00",
6454         "SE1.00",
6455         "SG1.00",
6456         "SH1.00",
6457         "SI1.00",
6458         "SK1.00",
6459         "SL R1.00",
6460         "SL1.00",
6461         "SO1.00",
6462         "ST1.00",
6463         "SU1.00",
6464         "SV1.00",
6465         "SY1.00",
6466         "SZ1.00",
6467         "St. Helena Poun1.00",
6468         "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobr1.00",
6469         "Saudi Riya1.00",
6470         "Serbian Dina1.00",
6471         "Seychellois Rupe1.00",
6472         "Sh1.00",
6473         "Sierra Leonean Leon1.00",
6474         "Silve1.00",
6475         "Singapore Dolla1.00",
6476         "Slovak Korun1.00",
6477         "Slovenian Tola1.00",
6478         "Solomon Islands Dolla1.00",
6479         "Somali Shillin1.00",
6480         "South African Ran1.00",
6481         "South African Rand (financial1.00",
6482         "South Korean Wo1.00",
6483         "Soviet Roubl1.00",
6484         "Spanish Peset1.00",
6485         "Spanish Peseta (A account1.00",
6486         "Spanish Peseta (convertible account1.00",
6487         "Special Drawing Right1.00",
6488         "Sri Lankan Rupe1.00",
6489         "Sudanese Poun1.00",
6490         "Surinamese Dolla1.00",
6491         "Surinamese Guilde1.00",
6492         "Swazi Lilangen1.00",
6493         "Swedish Kron1.00",
6494         "Swiss Fran1.00",
6495         "Syrian Poun1.00",
6496         "T S1.00",
6497         "TH1.00",
6498         "TJ1.00",
6499         "TM1.00",
6500         "TN1.00",
6501         "TO1.00",
6502         "TP1.00",
6503         "TR1.00",
6504         "TT1.00",
6505         "TW1.00",
6506         "TZ1.00",
6507         "New Taiwan Dolla1.00",
6508         "Tajikistani Rubl1.00",
6509         "Tajikistani Somon1.00",
6510         "Tanzanian Shillin1.00",
6511         "Testing Currency Cod1.00",
6512         "Thai Bah1.00",
6513         "Timorese Escud1.00",
6514         "Tongan Pa\\u20bbang1.00",
6515         "Trinidad & Tobago Dolla1.00",
6516         "Tunisian Dina1.00",
6517         "Turkish Lir1.00",
6518         "Turkmenistani Mana1.00",
6519         "U S1.00",
6520         "U1.00",
6521         "UA1.00",
6522         "UG1.00",
6523         "US Dolla1.00",
6524         "US Dollar (Next day1.00",
6525         "US Dollar (Same day1.00",
6526         "US1.00",
6527         "UY1.00",
6528         "UZ1.00",
6529         "Ugandan Shillin1.00",
6530         "Ugandan Shilling (1966\\u201319871.00",
6531         "Ukrainian Hryvni1.00",
6532         "Ukrainian Karbovanet1.00",
6533         "Colombian Real Value Uni1.00",
6534         "United Arab Emirates Dirha1.00",
6535         "Unknown Currenc1.00",
6536         "Ur1.00",
6537         "Uruguay Peso (1975\\u201319931.00",
6538         "Uruguay Peso Uruguay1.00",
6539         "Uruguay Peso (Indexed Units1.00",
6540         "Uzbekistani So1.00",
6541         "V1.00",
6542         "VE1.00",
6543         "VN1.00",
6544         "VU1.00",
6545         "Vanuatu Vat1.00",
6546         "Venezuelan Bol\\u00edva1.00",
6547         "Venezuelan Bol\\u00edvar Fuert1.00",
6548         "Vietnamese Don1.00",
6549         "West African CFA Fran1.00",
6550         "Central African CFA Fran1.00",
6551         "WIR Eur1.00",
6552         "WIR Fran1.00",
6553         "WS1.00",
6554         "Samoa Tal1.00",
6555         "XA1.00",
6556         "XB1.00",
6557         "XC1.00",
6558         "XD1.00",
6559         "XE1.00",
6560         "XF1.00",
6561         "XO1.00",
6562         "XP1.00",
6563         "XR1.00",
6564         "XT1.00",
6565         "XX1.00",
6566         "YD1.00",
6567         "YE1.00",
6568         "YU1.00",
6569         "Yemeni Dina1.00",
6570         "Yemeni Ria1.00",
6571         "Yugoslavian Convertible Dina1.00",
6572         "Yugoslavian Hard Dinar (1966\\u201319901.00",
6573         "Yugoslavian New Dina1.00",
6574         "Z1.00",
6575         "ZA1.00",
6576         "ZM1.00",
6577         "ZR1.00",
6578         "ZW1.00",
6579         "Zairean New Zaire (1993\\u201319981.00",
6580         "Zairean Zair1.00",
6581         "Zambian Kwach1.00",
6582         "Zimbabwean Dollar (1980\\u201320081.00",
6583         "dra1.00",
6584         "lar1.00",
6585         "le1.00",
6586         "man1.00",
6587         "so1.00",
6588     };
6589 
6590     Locale locale("en_US");
6591     for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
6592         UnicodeString formatted = ctou(DATA[i]);
6593         UErrorCode status = U_ZERO_ERROR;
6594         LocalPointer<NumberFormat> numFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status), status);
6595         if (!assertSuccess("", status, true, __FILE__, __LINE__)) {
6596             return;
6597         }
6598         // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
6599         numFmt->setLenient(TRUE);
6600         ParsePosition parsePos;
6601         LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6602         if (parsePos.getIndex() > 0) {
6603             double doubleVal = currAmt->getNumber().getDouble(status);
6604             if ( doubleVal != 1.0 ) {
6605                 errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
6606             }
6607         } else {
6608             errln("Failed to parse as currency: " + formatted);
6609         }
6610     }
6611 
6612     for (uint32_t i=0; i<UPRV_LENGTHOF(WRONG_DATA); ++i) {
6613       UnicodeString formatted = ctou(WRONG_DATA[i]);
6614       UErrorCode status = U_ZERO_ERROR;
6615       NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6616       if (numFmt != NULL && U_SUCCESS(status)) {
6617           ParsePosition parsePos;
6618           LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6619           if (parsePos.getIndex() > 0) {
6620               double doubleVal = currAmt->getNumber().getDouble(status);
6621               errln("Parsed as currency, should not have: " + formatted + " -> " + doubleVal);
6622           }
6623       } else {
6624           dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));
6625           delete numFmt;
6626           break;
6627       }
6628       delete numFmt;
6629     }
6630 }
6631 
6632 const char* attrString(int32_t);
6633 
6634 // UnicodeString s;
6635 //  std::string ss;
6636 //  std::cout << s.toUTF8String(ss)
expectPositions(FieldPositionIterator & iter,int32_t * values,int32_t tupleCount,const UnicodeString & str)6637 void NumberFormatTest::expectPositions(FieldPositionIterator& iter, int32_t *values, int32_t tupleCount,
6638                                        const UnicodeString& str)  {
6639   UBool found[10];
6640   FieldPosition fp;
6641 
6642   if (tupleCount > 10) {
6643     assertTrue("internal error, tupleCount too large", FALSE);
6644   } else {
6645     for (int i = 0; i < tupleCount; ++i) {
6646       found[i] = FALSE;
6647     }
6648   }
6649 
6650   logln(str);
6651   while (iter.next(fp)) {
6652     UBool ok = FALSE;
6653     int32_t id = fp.getField();
6654     int32_t start = fp.getBeginIndex();
6655     int32_t limit = fp.getEndIndex();
6656 
6657     // is there a logln using printf?
6658     char buf[128];
6659     sprintf(buf, "%24s %3d %3d %3d", attrString(id), id, start, limit);
6660     logln(buf);
6661 
6662     for (int i = 0; i < tupleCount; ++i) {
6663       if (found[i]) {
6664         continue;
6665       }
6666       if (values[i*3] == id &&
6667           values[i*3+1] == start &&
6668           values[i*3+2] == limit) {
6669         found[i] = ok = TRUE;
6670         break;
6671       }
6672     }
6673 
6674     assertTrue((UnicodeString)"found [" + id + "," + start + "," + limit + "]", ok);
6675   }
6676 
6677   // check that all were found
6678   UBool ok = TRUE;
6679   for (int i = 0; i < tupleCount; ++i) {
6680     if (!found[i]) {
6681       ok = FALSE;
6682       assertTrue((UnicodeString) "missing [" + values[i*3] + "," + values[i*3+1] + "," + values[i*3+2] + "]", found[i]);
6683     }
6684   }
6685   assertTrue("no expected values were missing", ok);
6686 }
6687 
expectPosition(FieldPosition & pos,int32_t id,int32_t start,int32_t limit,const UnicodeString & str)6688 void NumberFormatTest::expectPosition(FieldPosition& pos, int32_t id, int32_t start, int32_t limit,
6689                                        const UnicodeString& str)  {
6690   logln(str);
6691   assertTrue((UnicodeString)"id " + id + " == " + pos.getField(), id == pos.getField());
6692   assertTrue((UnicodeString)"begin " + start + " == " + pos.getBeginIndex(), start == pos.getBeginIndex());
6693   assertTrue((UnicodeString)"end " + limit + " == " + pos.getEndIndex(), limit == pos.getEndIndex());
6694 }
6695 
TestFieldPositionIterator()6696 void NumberFormatTest::TestFieldPositionIterator() {
6697   // bug 7372
6698   UErrorCode status = U_ZERO_ERROR;
6699   FieldPositionIterator iter1;
6700   FieldPositionIterator iter2;
6701   FieldPosition pos;
6702 
6703   DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(status);
6704   if (failure(status, "NumberFormat::createInstance", TRUE)) return;
6705 
6706   double num = 1234.56;
6707   UnicodeString str1;
6708   UnicodeString str2;
6709 
6710   assertTrue((UnicodeString)"self==", iter1 == iter1);
6711   assertTrue((UnicodeString)"iter1==iter2", iter1 == iter2);
6712 
6713   decFmt->format(num, str1, &iter1, status);
6714   assertTrue((UnicodeString)"iter1 != iter2", iter1 != iter2);
6715   decFmt->format(num, str2, &iter2, status);
6716   assertTrue((UnicodeString)"iter1 == iter2 (2)", iter1 == iter2);
6717   iter1.next(pos);
6718   assertTrue((UnicodeString)"iter1 != iter2 (2)", iter1 != iter2);
6719   iter2.next(pos);
6720   assertTrue((UnicodeString)"iter1 == iter2 (3)", iter1 == iter2);
6721 
6722   // should format ok with no iterator
6723   str2.remove();
6724   decFmt->format(num, str2, NULL, status);
6725   assertEquals("null fpiter", str1, str2);
6726 
6727   delete decFmt;
6728 }
6729 
TestFormatAttributes()6730 void NumberFormatTest::TestFormatAttributes() {
6731   Locale locale("en_US");
6732   UErrorCode status = U_ZERO_ERROR;
6733   DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6734     if (failure(status, "NumberFormat::createInstance", TRUE)) return;
6735   double val = 12345.67;
6736 
6737   {
6738     int32_t expected[] = {
6739       UNUM_CURRENCY_FIELD, 0, 1,
6740       UNUM_GROUPING_SEPARATOR_FIELD, 3, 4,
6741       UNUM_INTEGER_FIELD, 1, 7,
6742       UNUM_DECIMAL_SEPARATOR_FIELD, 7, 8,
6743       UNUM_FRACTION_FIELD, 8, 10,
6744     };
6745     int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6746 
6747     FieldPositionIterator posIter;
6748     UnicodeString result;
6749     decFmt->format(val, result, &posIter, status);
6750     expectPositions(posIter, expected, tupleCount, result);
6751   }
6752   {
6753     FieldPosition fp(UNUM_INTEGER_FIELD);
6754     UnicodeString result;
6755     decFmt->format(val, result, fp);
6756     expectPosition(fp, UNUM_INTEGER_FIELD, 1, 7, result);
6757   }
6758   {
6759     FieldPosition fp(UNUM_FRACTION_FIELD);
6760     UnicodeString result;
6761     decFmt->format(val, result, fp);
6762     expectPosition(fp, UNUM_FRACTION_FIELD, 8, 10, result);
6763   }
6764   delete decFmt;
6765 
6766   decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_SCIENTIFIC, status);
6767   val = -0.0000123;
6768   {
6769     int32_t expected[] = {
6770       UNUM_SIGN_FIELD, 0, 1,
6771       UNUM_INTEGER_FIELD, 1, 2,
6772       UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3,
6773       UNUM_FRACTION_FIELD, 3, 5,
6774       UNUM_EXPONENT_SYMBOL_FIELD, 5, 6,
6775       UNUM_EXPONENT_SIGN_FIELD, 6, 7,
6776       UNUM_EXPONENT_FIELD, 7, 8
6777     };
6778     int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6779 
6780     FieldPositionIterator posIter;
6781     UnicodeString result;
6782     decFmt->format(val, result, &posIter, status);
6783     expectPositions(posIter, expected, tupleCount, result);
6784   }
6785   {
6786     FieldPosition fp(UNUM_INTEGER_FIELD);
6787     UnicodeString result;
6788     decFmt->format(val, result, fp);
6789     expectPosition(fp, UNUM_INTEGER_FIELD, 1, 2, result);
6790   }
6791   {
6792     FieldPosition fp(UNUM_FRACTION_FIELD);
6793     UnicodeString result;
6794     decFmt->format(val, result, fp);
6795     expectPosition(fp, UNUM_FRACTION_FIELD, 3, 5, result);
6796   }
6797   delete decFmt;
6798 
6799   fflush(stderr);
6800 }
6801 
attrString(int32_t attrId)6802 const char* attrString(int32_t attrId) {
6803   switch (attrId) {
6804     case UNUM_INTEGER_FIELD: return "integer";
6805     case UNUM_FRACTION_FIELD: return "fraction";
6806     case UNUM_DECIMAL_SEPARATOR_FIELD: return "decimal separator";
6807     case UNUM_EXPONENT_SYMBOL_FIELD: return "exponent symbol";
6808     case UNUM_EXPONENT_SIGN_FIELD: return "exponent sign";
6809     case UNUM_EXPONENT_FIELD: return "exponent";
6810     case UNUM_GROUPING_SEPARATOR_FIELD: return "grouping separator";
6811     case UNUM_CURRENCY_FIELD: return "currency";
6812     case UNUM_PERCENT_FIELD: return "percent";
6813     case UNUM_PERMILL_FIELD: return "permille";
6814     case UNUM_SIGN_FIELD: return "sign";
6815     default: return "";
6816   }
6817 }
6818 
6819 //
6820 //   Test formatting & parsing of big decimals.
6821 //      API test, not a comprehensive test.
6822 //      See DecimalFormatTest/DataDrivenTests
6823 //
6824 #define ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \
6825     assertSuccess(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (status)); \
6826 } UPRV_BLOCK_MACRO_END
6827 #define ASSERT_EQUALS(expected, actual) UPRV_BLOCK_MACRO_BEGIN { \
6828     assertEquals(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (expected), (actual)); \
6829 } UPRV_BLOCK_MACRO_END
6830 
TestDecimal()6831 void NumberFormatTest::TestDecimal() {
6832     {
6833         UErrorCode  status = U_ZERO_ERROR;
6834         Formattable f("12.345678999987654321E666", status);
6835         ASSERT_SUCCESS(status);
6836         StringPiece s = f.getDecimalNumber(status);
6837         ASSERT_SUCCESS(status);
6838         ASSERT_EQUALS("1.2345678999987654321E+667", s.data());
6839         //printf("%s\n", s.data());
6840     }
6841 
6842     {
6843         UErrorCode status = U_ZERO_ERROR;
6844         Formattable f1("this is not a number", status);
6845         ASSERT_EQUALS(U_DECIMAL_NUMBER_SYNTAX_ERROR, status);
6846     }
6847 
6848     {
6849         UErrorCode status = U_ZERO_ERROR;
6850         Formattable f;
6851         f.setDecimalNumber("123.45", status);
6852         ASSERT_SUCCESS(status);
6853         ASSERT_EQUALS( Formattable::kDouble, f.getType());
6854         ASSERT_EQUALS(123.45, f.getDouble());
6855         ASSERT_EQUALS(123.45, f.getDouble(status));
6856         ASSERT_SUCCESS(status);
6857         ASSERT_EQUALS("123.45", f.getDecimalNumber(status).data());
6858         ASSERT_SUCCESS(status);
6859 
6860         f.setDecimalNumber("4.5678E7", status);
6861         int32_t n;
6862         n = f.getLong();
6863         ASSERT_EQUALS(45678000, n);
6864 
6865         status = U_ZERO_ERROR;
6866         f.setDecimalNumber("-123", status);
6867         ASSERT_SUCCESS(status);
6868         ASSERT_EQUALS( Formattable::kLong, f.getType());
6869         ASSERT_EQUALS(-123, f.getLong());
6870         ASSERT_EQUALS(-123, f.getLong(status));
6871         ASSERT_SUCCESS(status);
6872         ASSERT_EQUALS("-123", f.getDecimalNumber(status).data());
6873         ASSERT_SUCCESS(status);
6874 
6875         status = U_ZERO_ERROR;
6876         f.setDecimalNumber("1234567890123", status);  // Number too big for 32 bits
6877         ASSERT_SUCCESS(status);
6878         ASSERT_EQUALS( Formattable::kInt64, f.getType());
6879         ASSERT_EQUALS(1234567890123LL, f.getInt64());
6880         ASSERT_EQUALS(1234567890123LL, f.getInt64(status));
6881         ASSERT_SUCCESS(status);
6882         ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status).data());
6883         ASSERT_SUCCESS(status);
6884     }
6885 
6886     {
6887         UErrorCode status = U_ZERO_ERROR;
6888         NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6889         if (U_FAILURE(status) || fmtr == NULL) {
6890             dataerrln("Unable to create NumberFormat");
6891         } else {
6892             UnicodeString formattedResult;
6893             StringPiece num("244444444444444444444444444444444444446.4");
6894             fmtr->format(num, formattedResult, NULL, status);
6895             ASSERT_SUCCESS(status);
6896             ASSERT_EQUALS("244,444,444,444,444,444,444,444,444,444,444,444,446.4", formattedResult);
6897             //std::string ss; std::cout << formattedResult.toUTF8String(ss);
6898             delete fmtr;
6899         }
6900     }
6901 
6902     {
6903         // Check formatting a DigitList.  DigitList is internal, but this is
6904         // a critical interface that must work.
6905         UErrorCode status = U_ZERO_ERROR;
6906         NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6907         if (U_FAILURE(status) || fmtr == NULL) {
6908             dataerrln("Unable to create NumberFormat");
6909         } else {
6910             UnicodeString formattedResult;
6911             DecimalQuantity dl;
6912             StringPiece num("123.4566666666666666666666666666666666621E+40");
6913             dl.setToDecNumber(num, status);
6914             ASSERT_SUCCESS(status);
6915             fmtr->format(dl, formattedResult, NULL, status);
6916             ASSERT_SUCCESS(status);
6917             ASSERT_EQUALS("1,234,566,666,666,666,666,666,666,666,666,666,666,621,000", formattedResult);
6918 
6919             status = U_ZERO_ERROR;
6920             num.set("666.666");
6921             dl.setToDecNumber(num, status);
6922             FieldPosition pos(NumberFormat::FRACTION_FIELD);
6923             ASSERT_SUCCESS(status);
6924             formattedResult.remove();
6925             fmtr->format(dl, formattedResult, pos, status);
6926             ASSERT_SUCCESS(status);
6927             ASSERT_EQUALS("666.666", formattedResult);
6928             ASSERT_EQUALS(4, pos.getBeginIndex());
6929             ASSERT_EQUALS(7, pos.getEndIndex());
6930             delete fmtr;
6931         }
6932     }
6933 
6934     {
6935         // Check a parse with a formatter with a multiplier.
6936         UErrorCode status = U_ZERO_ERROR;
6937         NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_PERCENT, status);
6938         if (U_FAILURE(status) || fmtr == NULL) {
6939             dataerrln("Unable to create NumberFormat");
6940         } else {
6941             UnicodeString input = "1.84%";
6942             Formattable result;
6943             fmtr->parse(input, result, status);
6944             ASSERT_SUCCESS(status);
6945             ASSERT_EQUALS("0.0184", result.getDecimalNumber(status).data());
6946             //std::cout << result.getDecimalNumber(status).data();
6947             delete fmtr;
6948         }
6949     }
6950 
6951 #if U_PLATFORM != U_PF_CYGWIN || defined(CYGWINMSVC)
6952     /*
6953      * This test fails on Cygwin (1.7.16) using GCC because of a rounding issue with strtod().
6954      * See #9463
6955      */
6956     {
6957         // Check that a parse returns a decimal number with full accuracy
6958         UErrorCode status = U_ZERO_ERROR;
6959         NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6960         if (U_FAILURE(status) || fmtr == NULL) {
6961             dataerrln("Unable to create NumberFormat");
6962         } else {
6963             UnicodeString input = "1.002200044400088880000070000";
6964             Formattable result;
6965             fmtr->parse(input, result, status);
6966             ASSERT_SUCCESS(status);
6967             ASSERT_EQUALS(0, strcmp("1.00220004440008888000007", result.getDecimalNumber(status).data()));
6968             ASSERT_EQUALS(1.00220004440008888,   result.getDouble());
6969             //std::cout << result.getDecimalNumber(status).data();
6970             delete fmtr;
6971         }
6972     }
6973 #endif
6974 
6975 }
6976 
TestCurrencyFractionDigits()6977 void NumberFormatTest::TestCurrencyFractionDigits() {
6978     UErrorCode status = U_ZERO_ERROR;
6979     UnicodeString text1, text2;
6980     double value = 99.12345;
6981 
6982     // Create currenct instance
6983     NumberFormat* fmt = NumberFormat::createCurrencyInstance("ja_JP", status);
6984     if (U_FAILURE(status) || fmt == NULL) {
6985         dataerrln("Unable to create NumberFormat");
6986     } else {
6987         fmt->format(value, text1);
6988 
6989         // Reset the same currency and format the test value again
6990         fmt->setCurrency(fmt->getCurrency(), status);
6991         ASSERT_SUCCESS(status);
6992         fmt->format(value, text2);
6993 
6994         if (text1 != text2) {
6995             errln((UnicodeString)"NumberFormat::format() should return the same result - text1="
6996                 + text1 + " text2=" + text2);
6997         }
6998     }
6999     delete fmt;
7000 }
7001 
TestExponentParse()7002 void NumberFormatTest::TestExponentParse() {
7003 
7004     UErrorCode status = U_ZERO_ERROR;
7005     Formattable result;
7006     ParsePosition parsePos(0);
7007 
7008     // set the exponent symbol
7009     status = U_ZERO_ERROR;
7010     DecimalFormatSymbols symbols(Locale::getDefault(), status);
7011     if(U_FAILURE(status)) {
7012         dataerrln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (Default)");
7013         return;
7014     }
7015 
7016     // create format instance
7017     status = U_ZERO_ERROR;
7018     DecimalFormat fmt(u"#####", symbols, status);
7019     if(U_FAILURE(status)) {
7020         errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
7021     }
7022 
7023     // parse the text
7024     fmt.parse("5.06e-27", result, parsePos);
7025     if(result.getType() != Formattable::kDouble &&
7026        result.getDouble() != 5.06E-27 &&
7027        parsePos.getIndex() != 8
7028        )
7029     {
7030         errln("ERROR: parse failed - expected 5.06E-27, 8  - returned %d, %i",
7031               result.getDouble(), parsePos.getIndex());
7032     }
7033 }
7034 
TestExplicitParents()7035 void NumberFormatTest::TestExplicitParents() {
7036 
7037     /* Test that number formats are properly inherited from es_419 */
7038     /* These could be subject to change if the CLDR data changes */
7039     static const char* parentLocaleTests[][2]= {
7040     /* locale ID */  /* expected */
7041     {"es_CO", "1.250,75" },
7042     {"es_ES", "1.250,75" },
7043     {"es_GQ", "1.250,75" },
7044     {"es_MX", "1,250.75" },
7045     {"es_US", "1,250.75" },
7046     {"es_VE", "1.250,75" },
7047     };
7048 
7049     UnicodeString s;
7050 
7051     for(int i=0; i < UPRV_LENGTHOF(parentLocaleTests); i++){
7052         UErrorCode status = U_ZERO_ERROR;
7053         const char *localeID = parentLocaleTests[i][0];
7054         UnicodeString expected(parentLocaleTests[i][1], -1, US_INV);
7055         expected = expected.unescape();
7056         char loc[256]={0};
7057         uloc_canonicalize(localeID, loc, 256, &status);
7058         NumberFormat *fmt= NumberFormat::createInstance(Locale(loc), status);
7059         if(U_FAILURE(status)){
7060             dataerrln("Could not create number formatter for locale %s - %s",localeID, u_errorName(status));
7061             continue;
7062         }
7063         s.remove();
7064         fmt->format(1250.75, s);
7065         if(s!=expected){
7066             errln(UnicodeString("FAIL: Expected: ")+expected
7067                     + UnicodeString(" Got: ") + s
7068                     + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
7069         }
7070         if (U_FAILURE(status)){
7071             errln((UnicodeString)"FAIL: Status " + (int32_t)status);
7072         }
7073         delete fmt;
7074     }
7075 
7076 }
7077 
7078 /**
7079  * Test available numbering systems API.
7080  */
TestAvailableNumberingSystems()7081 void NumberFormatTest::TestAvailableNumberingSystems() {
7082     IcuTestErrorCode status(*this, "TestAvailableNumberingSystems");
7083     StringEnumeration *availableNumberingSystems = NumberingSystem::getAvailableNames(status);
7084     CHECK_DATA(status, "NumberingSystem::getAvailableNames()");
7085 
7086     int32_t nsCount = availableNumberingSystems->count(status);
7087     if ( nsCount < 74 ) {
7088         errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 74, got %d",nsCount);
7089     }
7090 
7091     /* A relatively simple test of the API.  We call getAvailableNames() and cycle through */
7092     /* each name returned, attempting to create a numbering system based on that name and  */
7093     /* verifying that the name returned from the resulting numbering system is the same    */
7094     /* one that we initially thought.                                                      */
7095 
7096     int32_t len;
7097     const char* prevName = nullptr;
7098     for ( int32_t i = 0 ; i < nsCount ; i++ ) {
7099         const char *nsname = availableNumberingSystems->next(&len,status);
7100         NumberingSystem* ns = NumberingSystem::createInstanceByName(nsname,status);
7101         logln("OK for ns = %s",nsname);
7102         if ( uprv_strcmp(nsname,ns->getName()) ) {
7103             errln("FAIL: Numbering system name didn't match for name = %s\n",nsname);
7104         }
7105         if (prevName != nullptr) {
7106             int comp = uprv_strcmp(prevName, nsname);
7107             assertTrue(
7108                 UnicodeString(u"NS names should be in alphabetical order: ")
7109                     + prevName + u" vs " + nsname,
7110                 // TODO: Why are there duplicates? This doesn't work if comp < 0
7111                 comp <= 0);
7112         }
7113         prevName = nsname;
7114 
7115         delete ns;
7116     }
7117 
7118     LocalPointer<NumberingSystem> dummy(NumberingSystem::createInstanceByName("dummy", status), status);
7119     status.expectErrorAndReset(U_UNSUPPORTED_ERROR);
7120     assertTrue("Non-existent numbering system should return null", dummy.isNull());
7121 
7122     delete availableNumberingSystems;
7123 }
7124 
7125 void
Test9087(void)7126 NumberFormatTest::Test9087(void)
7127 {
7128     U_STRING_DECL(pattern,"#",1);
7129     U_STRING_INIT(pattern,"#",1);
7130 
7131     U_STRING_DECL(infstr,"INF",3);
7132     U_STRING_INIT(infstr,"INF",3);
7133 
7134     U_STRING_DECL(nanstr,"NAN",3);
7135     U_STRING_INIT(nanstr,"NAN",3);
7136 
7137     UChar outputbuf[50] = {0};
7138     UErrorCode status = U_ZERO_ERROR;
7139     UNumberFormat* fmt = unum_open(UNUM_PATTERN_DECIMAL,pattern,1,NULL,NULL,&status);
7140     if ( U_FAILURE(status) ) {
7141         dataerrln("FAIL: error in unum_open() - %s", u_errorName(status));
7142         return;
7143     }
7144 
7145     unum_setSymbol(fmt,UNUM_INFINITY_SYMBOL,infstr,3,&status);
7146     unum_setSymbol(fmt,UNUM_NAN_SYMBOL,nanstr,3,&status);
7147     if ( U_FAILURE(status) ) {
7148         errln("FAIL: error setting symbols");
7149     }
7150 
7151     double inf = uprv_getInfinity();
7152 
7153     unum_setAttribute(fmt,UNUM_ROUNDING_MODE,UNUM_ROUND_HALFEVEN);
7154     unum_setDoubleAttribute(fmt,UNUM_ROUNDING_INCREMENT,0);
7155 
7156     UFieldPosition position = { 0, 0, 0};
7157     unum_formatDouble(fmt,inf,outputbuf,50,&position,&status);
7158 
7159     if ( u_strcmp(infstr, outputbuf)) {
7160         errln((UnicodeString)"FAIL: unexpected result for infinity - expected " + infstr + " got " + outputbuf);
7161     }
7162 
7163     unum_close(fmt);
7164 }
7165 
TestFormatFastpaths()7166 void NumberFormatTest::TestFormatFastpaths() {
7167     // get some additional case
7168     {
7169         UErrorCode status=U_ZERO_ERROR;
7170         DecimalFormat df(UnicodeString(u"0000"),status);
7171         if (U_FAILURE(status)) {
7172             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7173         } else {
7174             int64_t long_number = 1;
7175             UnicodeString expect = "0001";
7176             UnicodeString result;
7177             FieldPosition pos;
7178             df.format(long_number, result, pos);
7179             if(U_FAILURE(status)||expect!=result) {
7180                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s",
7181                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7182              } else {
7183                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
7184             }
7185         }
7186     }
7187     {
7188         UErrorCode status=U_ZERO_ERROR;
7189         DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7190         if (U_FAILURE(status)) {
7191             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7192         } else {
7193             int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
7194             // uint8_t bits[8];
7195             // memcpy(bits,&long_number,8);
7196             // for(int i=0;i<8;i++) {
7197             //   logln("bits: %02X", (unsigned int)bits[i]);
7198             // }
7199             UnicodeString expect = "-9223372036854775808";
7200             UnicodeString result;
7201             FieldPosition pos;
7202             df.format(long_number, result, pos);
7203             if(U_FAILURE(status)||expect!=result) {
7204                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775808",
7205                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7206             } else {
7207                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
7208             }
7209         }
7210     }
7211     {
7212         UErrorCode status=U_ZERO_ERROR;
7213         DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7214         if (U_FAILURE(status)) {
7215             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7216         } else {
7217             int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
7218             // uint8_t bits[8];
7219             // memcpy(bits,&long_number,8);
7220             // for(int i=0;i<8;i++) {
7221             //   logln("bits: %02X", (unsigned int)bits[i]);
7222             // }
7223             UnicodeString expect = "9223372036854775807";
7224             UnicodeString result;
7225             FieldPosition pos;
7226             df.format(long_number, result, pos);
7227             if(U_FAILURE(status)||expect!=result) {
7228                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on U_INT64_MAX",
7229                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7230             } else {
7231                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
7232             }
7233         }
7234     }
7235     {
7236         UErrorCode status=U_ZERO_ERROR;
7237         DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7238         if (U_FAILURE(status)) {
7239             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7240         } else {
7241             int64_t long_number = 0;
7242             // uint8_t bits[8];
7243             // memcpy(bits,&long_number,8);
7244             // for(int i=0;i<8;i++) {
7245             //   logln("bits: %02X", (unsigned int)bits[i]);
7246             // }
7247             UnicodeString expect = "0000000000000000000";
7248             UnicodeString result;
7249             FieldPosition pos;
7250             df.format(long_number, result, pos);
7251             if(U_FAILURE(status)||expect!=result) {
7252                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on 0",
7253                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7254             } else {
7255                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
7256             }
7257         }
7258     }
7259     {
7260         UErrorCode status=U_ZERO_ERROR;
7261         DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7262         if (U_FAILURE(status)) {
7263             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7264         } else {
7265             int64_t long_number = U_INT64_MIN + 1;
7266             UnicodeString expect = "-9223372036854775807";
7267             UnicodeString result;
7268             FieldPosition pos;
7269             df.format(long_number, result, pos);
7270             if(U_FAILURE(status)||expect!=result) {
7271                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775807",
7272                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7273             } else {
7274                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
7275             }
7276         }
7277     }
7278 }
7279 
7280 
TestFormattableSize(void)7281 void NumberFormatTest::TestFormattableSize(void) {
7282   if(sizeof(Formattable) > 112) {
7283     errln("Error: sizeof(Formattable)=%d, 112=%d\n",
7284           sizeof(Formattable), 112);
7285   } else if(sizeof(Formattable) < 112) {
7286     logln("Warning: sizeof(Formattable)=%d, 112=%d\n",
7287         sizeof(Formattable), 112);
7288   } else {
7289     logln("sizeof(Formattable)=%d, 112=%d\n",
7290         sizeof(Formattable), 112);
7291   }
7292 }
7293 
testFormattableAsUFormattable(const char * file,int line,Formattable & f)7294 UBool NumberFormatTest::testFormattableAsUFormattable(const char *file, int line, Formattable &f) {
7295   UnicodeString fileLine = UnicodeString(file)+UnicodeString(":")+line+UnicodeString(": ");
7296 
7297   UFormattable *u = f.toUFormattable();
7298   logln();
7299   if (u == NULL) {
7300     errln("%s:%d: Error: f.toUFormattable() retuned NULL.");
7301     return FALSE;
7302   }
7303   logln("%s:%d: comparing Formattable with UFormattable", file, line);
7304   logln(fileLine + toString(f));
7305 
7306   UErrorCode status = U_ZERO_ERROR;
7307   UErrorCode valueStatus = U_ZERO_ERROR;
7308   UFormattableType expectUType = UFMT_COUNT; // invalid
7309 
7310   UBool triedExact = FALSE; // did we attempt an exact comparison?
7311   UBool exactMatch = FALSE; // was the exact comparison true?
7312 
7313   switch( f.getType() ) {
7314   case Formattable::kDate:
7315     expectUType = UFMT_DATE;
7316     exactMatch = (f.getDate()==ufmt_getDate(u, &valueStatus));
7317     triedExact = TRUE;
7318     break;
7319   case Formattable::kDouble:
7320     expectUType = UFMT_DOUBLE;
7321     exactMatch = (f.getDouble()==ufmt_getDouble(u, &valueStatus));
7322     triedExact = TRUE;
7323     break;
7324   case Formattable::kLong:
7325     expectUType = UFMT_LONG;
7326     exactMatch = (f.getLong()==ufmt_getLong(u, &valueStatus));
7327     triedExact = TRUE;
7328     break;
7329   case Formattable::kString:
7330     expectUType = UFMT_STRING;
7331     {
7332       UnicodeString str;
7333       f.getString(str);
7334       int32_t len;
7335       const UChar* uch = ufmt_getUChars(u, &len, &valueStatus);
7336       if(U_SUCCESS(valueStatus)) {
7337         UnicodeString str2(uch, len);
7338         assertTrue("UChar* NULL-terminated", uch[len]==0);
7339         exactMatch = (str == str2);
7340       }
7341       triedExact = TRUE;
7342     }
7343     break;
7344   case Formattable::kArray:
7345     expectUType = UFMT_ARRAY;
7346     triedExact = TRUE;
7347     {
7348       int32_t count = ufmt_getArrayLength(u, &valueStatus);
7349       int32_t count2;
7350       const Formattable *array2 = f.getArray(count2);
7351       exactMatch = assertEquals(fileLine + " array count", count, count2);
7352 
7353       if(exactMatch) {
7354         for(int i=0;U_SUCCESS(valueStatus) && i<count;i++) {
7355           UFormattable *uu = ufmt_getArrayItemByIndex(u, i, &valueStatus);
7356           if(*Formattable::fromUFormattable(uu) != (array2[i])) {
7357             errln("%s:%d: operator== did not match at index[%d] - %p vs %p", file, line, i,
7358                   (const void*)Formattable::fromUFormattable(uu), (const void*)&(array2[i]));
7359             exactMatch = FALSE;
7360           } else {
7361             if(!testFormattableAsUFormattable("(sub item)",i,*Formattable::fromUFormattable(uu))) {
7362               exactMatch = FALSE;
7363             }
7364           }
7365         }
7366       }
7367     }
7368     break;
7369   case Formattable::kInt64:
7370     expectUType = UFMT_INT64;
7371     exactMatch = (f.getInt64()==ufmt_getInt64(u, &valueStatus));
7372     triedExact = TRUE;
7373     break;
7374   case Formattable::kObject:
7375     expectUType = UFMT_OBJECT;
7376     exactMatch = (f.getObject()==ufmt_getObject(u, &valueStatus));
7377     triedExact = TRUE;
7378     break;
7379   }
7380   UFormattableType uType = ufmt_getType(u, &status);
7381 
7382   if(U_FAILURE(status)) {
7383     errln("%s:%d: Error calling ufmt_getType - %s", file, line, u_errorName(status));
7384     return FALSE;
7385   }
7386 
7387   if(uType != expectUType) {
7388     errln("%s:%d: got type (%d) expected (%d) from ufmt_getType", file, line, (int) uType, (int) expectUType);
7389   }
7390 
7391   if(triedExact) {
7392     if(U_FAILURE(valueStatus)) {
7393       errln("%s:%d: got err %s trying to ufmt_get...() for exact match check", file, line, u_errorName(valueStatus));
7394     } else if(!exactMatch) {
7395      errln("%s:%d: failed exact match for the Formattable type", file, line);
7396     } else {
7397       logln("%s:%d: exact match OK", file, line);
7398     }
7399   } else {
7400     logln("%s:%d: note, did not attempt exact match for this formattable type", file, line);
7401   }
7402 
7403   if( assertEquals(fileLine + " isNumeric()", f.isNumeric(), ufmt_isNumeric(u))
7404       && f.isNumeric()) {
7405     UErrorCode convStatus = U_ZERO_ERROR;
7406 
7407     if(uType != UFMT_INT64) { // may fail to compare
7408       assertTrue(fileLine + " as doubles ==", f.getDouble(convStatus)==ufmt_getDouble(u, &convStatus));
7409     }
7410 
7411     if( assertSuccess(fileLine + " (numeric conversion status)", convStatus) ) {
7412       StringPiece fDecNum = f.getDecimalNumber(convStatus);
7413 #if 1
7414       int32_t len;
7415       const char *decNumChars = ufmt_getDecNumChars(u, &len, &convStatus);
7416 #else
7417       // copy version
7418       char decNumChars[200];
7419       int32_t len = ufmt_getDecNumChars(u, decNumChars, 200, &convStatus);
7420 #endif
7421 
7422       if( assertSuccess(fileLine + " (decNumbers conversion)", convStatus) ) {
7423         logln(fileLine + decNumChars);
7424         assertEquals(fileLine + " decNumChars length==", len, fDecNum.length());
7425         assertEquals(fileLine + " decNumChars digits", decNumChars, fDecNum.data());
7426       }
7427 
7428       UErrorCode int64ConversionF = U_ZERO_ERROR;
7429       int64_t l = f.getInt64(int64ConversionF);
7430       UErrorCode int64ConversionU = U_ZERO_ERROR;
7431       int64_t r = ufmt_getInt64(u, &int64ConversionU);
7432 
7433       if( (l==r)
7434           && ( uType != UFMT_INT64 ) // int64 better not overflow
7435           && (U_INVALID_FORMAT_ERROR==int64ConversionU)
7436           && (U_INVALID_FORMAT_ERROR==int64ConversionF) ) {
7437         logln("%s:%d: OK: 64 bit overflow", file, line);
7438       } else {
7439         assertEquals(fileLine + " as int64 ==", l, r);
7440         assertSuccess(fileLine + " Formattable.getnt64()", int64ConversionF);
7441         assertSuccess(fileLine + " ufmt_getInt64()", int64ConversionU);
7442       }
7443     }
7444   }
7445   return exactMatch || !triedExact;
7446 }
7447 
TestUFormattable(void)7448 void NumberFormatTest::TestUFormattable(void) {
7449   {
7450     // test that a default formattable is equal to Formattable()
7451     UErrorCode status = U_ZERO_ERROR;
7452     LocalUFormattablePointer defaultUFormattable(ufmt_open(&status));
7453     assertSuccess("calling umt_open", status);
7454     Formattable defaultFormattable;
7455     assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7456                (defaultFormattable
7457                 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7458     assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7459                (defaultFormattable
7460                 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7461     assertTrue((UnicodeString)"comparing Formattable() round tripped through UFormattable",
7462                (defaultFormattable
7463                 == *(Formattable::fromUFormattable(defaultFormattable.toUFormattable()))));
7464     assertTrue((UnicodeString)"comparing &Formattable() round tripped through UFormattable",
7465                ((&defaultFormattable)
7466                 == Formattable::fromUFormattable(defaultFormattable.toUFormattable())));
7467     assertFalse((UnicodeString)"comparing &Formattable() with ufmt_open()",
7468                ((&defaultFormattable)
7469                 == Formattable::fromUFormattable(defaultUFormattable.getAlias())));
7470     testFormattableAsUFormattable(__FILE__, __LINE__, defaultFormattable);
7471   }
7472   // test some random Formattables
7473   {
7474     Formattable f(ucal_getNow(), Formattable::kIsDate);
7475     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7476   }
7477   {
7478     Formattable f((double)1.61803398874989484820); // golden ratio
7479     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7480   }
7481   {
7482     Formattable f((int64_t)80994231587905127LL); // weight of the moon, in kilotons http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
7483     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7484   }
7485   {
7486     Formattable f((int32_t)4); // random number, source: http://www.xkcd.com/221/
7487     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7488   }
7489   {
7490     Formattable f("Hello world."); // should be invariant?
7491     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7492   }
7493   {
7494     UErrorCode status2 = U_ZERO_ERROR;
7495     Formattable f(StringPiece("73476730924573500000000.0"), status2); // weight of the moon, kg
7496     assertSuccess("Constructing a StringPiece", status2);
7497     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7498   }
7499   {
7500     UErrorCode status2 = U_ZERO_ERROR;
7501     UObject *obj = new Locale();
7502     Formattable f(obj);
7503     assertSuccess("Constructing a Formattable from a default constructed Locale()", status2);
7504     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7505   }
7506   {
7507     const Formattable array[] = {
7508       Formattable(ucal_getNow(), Formattable::kIsDate),
7509       Formattable((int32_t)4),
7510       Formattable((double)1.234),
7511     };
7512 
7513     Formattable fa(array, 3);
7514     testFormattableAsUFormattable(__FILE__, __LINE__, fa);
7515   }
7516 }
7517 
TestSignificantDigits(void)7518 void NumberFormatTest::TestSignificantDigits(void) {
7519   double input[] = {
7520         0, 0,
7521         0.1, -0.1,
7522         123, -123,
7523         12345, -12345,
7524         123.45, -123.45,
7525         123.44501, -123.44501,
7526         0.001234, -0.001234,
7527         0.00000000123, -0.00000000123,
7528         0.0000000000000000000123, -0.0000000000000000000123,
7529         1.2, -1.2,
7530         0.0000000012344501, -0.0000000012344501,
7531         123445.01, -123445.01,
7532         12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0,
7533     };
7534     const char* expected[] = {
7535         "0.00", "0.00",
7536         "0.100", "-0.100",
7537         "123", "-123",
7538         "12345", "-12345",
7539         "123.45", "-123.45",
7540         "123.45", "-123.45",
7541         "0.001234", "-0.001234",
7542         "0.00000000123", "-0.00000000123",
7543         "0.0000000000000000000123", "-0.0000000000000000000123",
7544         "1.20", "-1.20",
7545         "0.0000000012345", "-0.0000000012345",
7546         "123450", "-123450",
7547         "12345000000000000000000000000000000", "-12345000000000000000000000000000000",
7548     };
7549 
7550     UErrorCode status = U_ZERO_ERROR;
7551     Locale locale("en_US");
7552     LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7553             NumberFormat::createInstance(locale, status)));
7554     CHECK_DATA(status,"NumberFormat::createInstance");
7555 
7556     numberFormat->setSignificantDigitsUsed(TRUE);
7557     numberFormat->setMinimumSignificantDigits(3);
7558     numberFormat->setMaximumSignificantDigits(5);
7559     numberFormat->setGroupingUsed(false);
7560 
7561     UnicodeString result;
7562     UnicodeString expectedResult;
7563     for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
7564         numberFormat->format(input[i], result);
7565         UnicodeString expectedResult(expected[i]);
7566         if (result != expectedResult) {
7567           errln((UnicodeString)"Expected: '" + expectedResult + "' got '" + result);
7568         }
7569         result.remove();
7570     }
7571 
7572     // Test for ICU-20063
7573     {
7574         DecimalFormat df({"en-us", status}, status);
7575         df.setSignificantDigitsUsed(TRUE);
7576         expect(df, 9.87654321, u"9.87654");
7577         df.setMaximumSignificantDigits(3);
7578         expect(df, 9.87654321, u"9.88");
7579         // setSignificantDigitsUsed with maxSig only
7580         df.setSignificantDigitsUsed(TRUE);
7581         expect(df, 9.87654321, u"9.88");
7582         df.setMinimumSignificantDigits(2);
7583         expect(df, 9, u"9.0");
7584         // setSignificantDigitsUsed with both minSig and maxSig
7585         df.setSignificantDigitsUsed(TRUE);
7586         expect(df, 9, u"9.0");
7587         // setSignificantDigitsUsed to false: should revert to fraction rounding
7588         df.setSignificantDigitsUsed(FALSE);
7589         expect(df, 9.87654321, u"9.876543");
7590         expect(df, 9, u"9");
7591         df.setSignificantDigitsUsed(TRUE);
7592         df.setMinimumSignificantDigits(2);
7593         expect(df, 9.87654321, u"9.87654");
7594         expect(df, 9, u"9.0");
7595         // setSignificantDigitsUsed with minSig only
7596         df.setSignificantDigitsUsed(TRUE);
7597         expect(df, 9.87654321, u"9.87654");
7598         expect(df, 9, u"9.0");
7599     }
7600 }
7601 
TestShowZero()7602 void NumberFormatTest::TestShowZero() {
7603     UErrorCode status = U_ZERO_ERROR;
7604     Locale locale("en_US");
7605     LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7606             NumberFormat::createInstance(locale, status)));
7607     CHECK_DATA(status, "NumberFormat::createInstance");
7608 
7609     numberFormat->setSignificantDigitsUsed(TRUE);
7610     numberFormat->setMaximumSignificantDigits(3);
7611 
7612     UnicodeString result;
7613     numberFormat->format(0.0, result);
7614     if (result != "0") {
7615         errln((UnicodeString)"Expected: 0, got " + result);
7616     }
7617 }
7618 
TestBug9936()7619 void NumberFormatTest::TestBug9936() {
7620     UErrorCode status = U_ZERO_ERROR;
7621     Locale locale("en_US");
7622     LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7623             NumberFormat::createInstance(locale, status)));
7624     if (U_FAILURE(status)) {
7625         dataerrln("File %s, Line %d: status = %s.\n", __FILE__, __LINE__, u_errorName(status));
7626         return;
7627     }
7628 
7629     if (numberFormat->areSignificantDigitsUsed() == TRUE) {
7630         errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
7631     }
7632     numberFormat->setSignificantDigitsUsed(TRUE);
7633     if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7634         errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7635     }
7636 
7637     numberFormat->setSignificantDigitsUsed(FALSE);
7638     if (numberFormat->areSignificantDigitsUsed() == TRUE) {
7639         errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
7640     }
7641 
7642     numberFormat->setMinimumSignificantDigits(3);
7643     if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7644         errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7645     }
7646 
7647     numberFormat->setSignificantDigitsUsed(FALSE);
7648     numberFormat->setMaximumSignificantDigits(6);
7649     if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7650         errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7651     }
7652 
7653 }
7654 
TestParseNegativeWithFaLocale()7655 void NumberFormatTest::TestParseNegativeWithFaLocale() {
7656     UErrorCode status = U_ZERO_ERROR;
7657     DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status);
7658     CHECK_DATA(status, "NumberFormat::createInstance");
7659     test->setLenient(TRUE);
7660     Formattable af;
7661     ParsePosition ppos;
7662     UnicodeString value("\\u200e-0,5");
7663     value = value.unescape();
7664     test->parse(value, af, ppos);
7665     if (ppos.getIndex() == 0) {
7666         errln("Expected -0,5 to parse for Farsi.");
7667     }
7668     delete test;
7669 }
7670 
TestParseNegativeWithAlternateMinusSign()7671 void NumberFormatTest::TestParseNegativeWithAlternateMinusSign() {
7672     UErrorCode status = U_ZERO_ERROR;
7673     DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("en", status);
7674     CHECK_DATA(status, "NumberFormat::createInstance");
7675     test->setLenient(TRUE);
7676     Formattable af;
7677     ParsePosition ppos;
7678     UnicodeString value("\\u208B0.5");
7679     value = value.unescape();
7680     test->parse(value, af, ppos);
7681     if (ppos.getIndex() == 0) {
7682         errln(UnicodeString("Expected ") + value + UnicodeString(" to parse."));
7683     }
7684     delete test;
7685 }
7686 
TestCustomCurrencySignAndSeparator()7687 void NumberFormatTest::TestCustomCurrencySignAndSeparator() {
7688     UErrorCode status = U_ZERO_ERROR;
7689     DecimalFormatSymbols custom(Locale::getUS(), status);
7690     CHECK(status, "DecimalFormatSymbols constructor");
7691 
7692     custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "*");
7693     custom.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, "^");
7694     custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, ":");
7695 
7696     UnicodeString pat(" #,##0.00");
7697     pat.insert(0, (UChar)0x00A4);
7698 
7699     DecimalFormat fmt(pat, custom, status);
7700     CHECK(status, "DecimalFormat constructor");
7701 
7702     UnicodeString numstr("* 1^234:56");
7703     expect2(fmt, (Formattable)((double)1234.56), numstr);
7704 }
7705 
7706 typedef struct {
7707     const char *   locale;
7708     UBool          lenient;
7709     UnicodeString  numString;
7710     double         value;
7711 } SignsAndMarksItem;
7712 
7713 
TestParseSignsAndMarks()7714 void NumberFormatTest::TestParseSignsAndMarks() {
7715     const SignsAndMarksItem items[] = {
7716         // locale               lenient numString                                                       value
7717         { "en",                 FALSE,  CharsToUnicodeString("12"),                                      12 },
7718         { "en",                 TRUE,   CharsToUnicodeString("12"),                                      12 },
7719         { "en",                 FALSE,  CharsToUnicodeString("-23"),                                    -23 },
7720         { "en",                 TRUE,   CharsToUnicodeString("-23"),                                    -23 },
7721         { "en",                 TRUE,   CharsToUnicodeString("- 23"),                                   -23 },
7722         { "en",                 FALSE,  CharsToUnicodeString("\\u200E-23"),                             -23 },
7723         { "en",                 TRUE,   CharsToUnicodeString("\\u200E-23"),                             -23 },
7724         { "en",                 TRUE,   CharsToUnicodeString("\\u200E- 23"),                            -23 },
7725 
7726         { "en@numbers=arab",    FALSE,  CharsToUnicodeString("\\u0663\\u0664"),                          34 },
7727         { "en@numbers=arab",    TRUE,   CharsToUnicodeString("\\u0663\\u0664"),                          34 },
7728         { "en@numbers=arab",    FALSE,  CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
7729         { "en@numbers=arab",    TRUE,   CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
7730         { "en@numbers=arab",    TRUE,   CharsToUnicodeString("- \\u0664\\u0665"),                       -45 },
7731         { "en@numbers=arab",    FALSE,  CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
7732         { "en@numbers=arab",    TRUE,   CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
7733         { "en@numbers=arab",    TRUE,   CharsToUnicodeString("\\u200F- \\u0664\\u0665"),                -45 },
7734 
7735         { "en@numbers=arabext", FALSE,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7736         { "en@numbers=arabext", TRUE,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7737         { "en@numbers=arabext", FALSE,  CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
7738         { "en@numbers=arabext", TRUE,   CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
7739         { "en@numbers=arabext", TRUE,   CharsToUnicodeString("- \\u06F6\\u06F7"),                       -67 },
7740         { "en@numbers=arabext", FALSE,  CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
7741         { "en@numbers=arabext", TRUE,   CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
7742         { "en@numbers=arabext", TRUE,   CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"),         -67 },
7743 
7744         { "he",                 FALSE,  CharsToUnicodeString("12"),                                      12 },
7745         { "he",                 TRUE,   CharsToUnicodeString("12"),                                      12 },
7746         { "he",                 FALSE,  CharsToUnicodeString("-23"),                                    -23 },
7747         { "he",                 TRUE,   CharsToUnicodeString("-23"),                                    -23 },
7748         { "he",                 TRUE,   CharsToUnicodeString("- 23"),                                   -23 },
7749         { "he",                 FALSE,  CharsToUnicodeString("\\u200E-23"),                             -23 },
7750         { "he",                 TRUE,   CharsToUnicodeString("\\u200E-23"),                             -23 },
7751         { "he",                 TRUE,   CharsToUnicodeString("\\u200E- 23"),                            -23 },
7752 
7753         { "ar",                 FALSE,  CharsToUnicodeString("\\u0663\\u0664"),                          34 },
7754         { "ar",                 TRUE,   CharsToUnicodeString("\\u0663\\u0664"),                          34 },
7755         { "ar",                 FALSE,  CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
7756         { "ar",                 TRUE,   CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
7757         { "ar",                 TRUE,   CharsToUnicodeString("- \\u0664\\u0665"),                       -45 },
7758         { "ar",                 FALSE,  CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
7759         { "ar",                 TRUE,   CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
7760         { "ar",                 TRUE,   CharsToUnicodeString("\\u200F- \\u0664\\u0665"),                -45 },
7761 
7762         { "ar_MA",              FALSE,  CharsToUnicodeString("12"),                                      12 },
7763         { "ar_MA",              TRUE,   CharsToUnicodeString("12"),                                      12 },
7764         { "ar_MA",              FALSE,  CharsToUnicodeString("-23"),                                    -23 },
7765         { "ar_MA",              TRUE,   CharsToUnicodeString("-23"),                                    -23 },
7766         { "ar_MA",              TRUE,   CharsToUnicodeString("- 23"),                                   -23 },
7767         { "ar_MA",              FALSE,  CharsToUnicodeString("\\u200E-23"),                             -23 },
7768         { "ar_MA",              TRUE,   CharsToUnicodeString("\\u200E-23"),                             -23 },
7769         { "ar_MA",              TRUE,   CharsToUnicodeString("\\u200E- 23"),                            -23 },
7770 
7771         { "fa",                 FALSE,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7772         { "fa",                 TRUE,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7773         { "fa",                 FALSE,  CharsToUnicodeString("\\u2212\\u06F6\\u06F7"),                  -67 },
7774         { "fa",                 TRUE,   CharsToUnicodeString("\\u2212\\u06F6\\u06F7"),                  -67 },
7775         { "fa",                 TRUE,   CharsToUnicodeString("\\u2212 \\u06F6\\u06F7"),                 -67 },
7776         { "fa",                 FALSE,  CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"),    -67 },
7777         { "fa",                 TRUE,   CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"),    -67 },
7778         { "fa",                 TRUE,   CharsToUnicodeString("\\u200E\\u2212\\u200E \\u06F6\\u06F7"),   -67 },
7779 
7780         { "ps",                 FALSE,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7781         { "ps",                 TRUE,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7782         { "ps",                 FALSE,  CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
7783         { "ps",                 TRUE,   CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
7784         { "ps",                 TRUE,   CharsToUnicodeString("- \\u06F6\\u06F7"),                       -67 },
7785         { "ps",                 FALSE,  CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
7786         { "ps",                 TRUE,   CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
7787         { "ps",                 TRUE,   CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"),         -67 },
7788         { "ps",                 FALSE,  CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"),                 -67 },
7789         { "ps",                 TRUE,   CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"),                 -67 },
7790         { "ps",                 TRUE,   CharsToUnicodeString("-\\u200E \\u06F6\\u06F7"),                -67 },
7791         // terminator
7792         { NULL,                 0,      UnicodeString(""),                                                0 },
7793     };
7794 
7795     const SignsAndMarksItem * itemPtr;
7796     for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
7797         UErrorCode status = U_ZERO_ERROR;
7798         NumberFormat *numfmt = NumberFormat::createInstance(Locale(itemPtr->locale), status);
7799         if (U_SUCCESS(status)) {
7800             numfmt->setLenient(itemPtr->lenient);
7801             Formattable fmtobj;
7802             ParsePosition ppos;
7803             numfmt->parse(itemPtr->numString, fmtobj, ppos);
7804             if (ppos.getIndex() == itemPtr->numString.length()) {
7805                 double parsedValue = fmtobj.getDouble(status);
7806                 if (U_FAILURE(status) || parsedValue != itemPtr->value) {
7807                     errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives value " + parsedValue);
7808                 }
7809             } else {
7810                 errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives position " + ppos.getIndex());
7811             }
7812         } else {
7813             dataerrln("FAIL: NumberFormat::createInstance for locale % gives error %s", itemPtr->locale, u_errorName(status));
7814         }
7815         delete numfmt;
7816     }
7817 }
7818 
7819 typedef struct {
7820   DecimalFormat::ERoundingMode mode;
7821   double value;
7822   UnicodeString expected;
7823 } Test10419Data;
7824 
7825 
7826 // Tests that rounding works right when fractional digits is set to 0.
Test10419RoundingWith0FractionDigits()7827 void NumberFormatTest::Test10419RoundingWith0FractionDigits() {
7828     const Test10419Data items[] = {
7829         { DecimalFormat::kRoundCeiling, 1.488,  "2"},
7830         { DecimalFormat::kRoundDown, 1.588,  "1"},
7831         { DecimalFormat::kRoundFloor, 1.888,  "1"},
7832         { DecimalFormat::kRoundHalfDown, 1.5,  "1"},
7833         { DecimalFormat::kRoundHalfEven, 2.5,  "2"},
7834         { DecimalFormat::kRoundHalfUp, 2.5,  "3"},
7835         { DecimalFormat::kRoundUp, 1.5,  "2"},
7836     };
7837     UErrorCode status = U_ZERO_ERROR;
7838     LocalPointer<DecimalFormat> decfmt((DecimalFormat *) NumberFormat::createInstance(Locale("en_US"), status));
7839     if (U_FAILURE(status)) {
7840         dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
7841         return;
7842     }
7843     for (int32_t i = 0; i < UPRV_LENGTHOF(items); ++i) {
7844         decfmt->setRoundingMode(items[i].mode);
7845         decfmt->setMaximumFractionDigits(0);
7846         UnicodeString actual;
7847         if (items[i].expected != decfmt->format(items[i].value, actual)) {
7848             errln("Expected " + items[i].expected + ", got " + actual);
7849         }
7850     }
7851 }
7852 
Test10468ApplyPattern()7853 void NumberFormatTest::Test10468ApplyPattern() {
7854     // Padding char of fmt is now 'a'
7855     UErrorCode status = U_ZERO_ERROR;
7856     DecimalFormat fmt("'I''ll'*a###.##", status);
7857 
7858     if (U_FAILURE(status)) {
7859         errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7860         return;
7861     }
7862 
7863     assertEquals("Padding character should be 'a'.", u"a", fmt.getPadCharacterString());
7864 
7865     // Padding char of fmt ought to be '*' since that is the default and no
7866     // explicit padding char is specified in the new pattern.
7867     fmt.applyPattern("AA#,##0.00ZZ", status);
7868 
7869     // Oops this still prints 'a' even though we changed the pattern.
7870     assertEquals("applyPattern did not clear padding character.", u" ", fmt.getPadCharacterString());
7871 }
7872 
TestRoundingScientific10542()7873 void NumberFormatTest::TestRoundingScientific10542() {
7874     UErrorCode status = U_ZERO_ERROR;
7875     DecimalFormat format("0.00E0", status);
7876     if (U_FAILURE(status)) {
7877         errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7878         return;
7879     }
7880 
7881     DecimalFormat::ERoundingMode roundingModes[] = {
7882             DecimalFormat::kRoundCeiling,
7883             DecimalFormat::kRoundDown,
7884             DecimalFormat::kRoundFloor,
7885             DecimalFormat::kRoundHalfDown,
7886             DecimalFormat::kRoundHalfEven,
7887             DecimalFormat::kRoundHalfUp,
7888             DecimalFormat::kRoundUp};
7889     const char *descriptions[] = {
7890             "Round Ceiling",
7891             "Round Down",
7892             "Round Floor",
7893             "Round half down",
7894             "Round half even",
7895             "Round half up",
7896             "Round up"};
7897 
7898     {
7899         double values[] = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016};
7900         // The order of these expected values correspond to the order of roundingModes and the order of values.
7901         const char *expected[] = {
7902                 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.02E-3", "3.02E-3", "3.02E-3",
7903                 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7904                 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7905                 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.02E-3",
7906                 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7907                 "-3.01E-3", "-3.01E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7908                 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.02E-3", "3.02E-3", "3.02E-3"};
7909         verifyRounding(
7910                 format,
7911                 values,
7912                 expected,
7913                 roundingModes,
7914                 descriptions,
7915                 UPRV_LENGTHOF(values),
7916                 UPRV_LENGTHOF(roundingModes));
7917     }
7918     {
7919         double values[] = {-3006.0, -3005, -3004, 3014, 3015, 3016};
7920         // The order of these expected values correspond to the order of roundingModes and the order of values.
7921         const char *expected[] = {
7922                 "-3.00E3", "-3.00E3", "-3.00E3", "3.02E3", "3.02E3", "3.02E3",
7923                 "-3.00E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.01E3",
7924                 "-3.01E3", "-3.01E3", "-3.01E3", "3.01E3", "3.01E3", "3.01E3",
7925                 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.02E3",
7926                 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7927                 "-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7928                 "-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"};
7929         verifyRounding(
7930                 format,
7931                 values,
7932                 expected,
7933                 roundingModes,
7934                 descriptions,
7935                 UPRV_LENGTHOF(values),
7936                 UPRV_LENGTHOF(roundingModes));
7937     }
7938 /* Commented out for now until we decide how rounding to zero should work, +0 vs. -0
7939     {
7940         double values[] = {0.0, -0.0};
7941         // The order of these expected values correspond to the order of roundingModes and the order of values.
7942         const char *expected[] = {
7943                 "0.00E0", "-0.00E0",
7944                 "0.00E0", "-0.00E0",
7945                 "0.00E0", "-0.00E0",
7946                 "0.00E0", "-0.00E0",
7947                 "0.00E0", "-0.00E0",
7948                 "0.00E0", "-0.00E0",
7949                 "0.00E0", "-0.00E0"};
7950         verifyRounding(
7951                 format,
7952                 values,
7953                 expected,
7954                 roundingModes,
7955                 descriptions,
7956                 UPRV_LENGTHOF(values),
7957                 UPRV_LENGTHOF(roundingModes));
7958     }
7959 */
7960     {
7961 
7962         double values[] = {1e25, 1e25 + 1e15, 1e25 - 1e15};
7963         // The order of these expected values correspond to the order of roundingModes and the order of values.
7964         const char *expected[] = {
7965                 "1.00E25", "1.01E25", "1.00E25",
7966                 "1.00E25", "1.00E25", "9.99E24",
7967                 "1.00E25", "1.00E25", "9.99E24",
7968                 "1.00E25", "1.00E25", "1.00E25",
7969                 "1.00E25", "1.00E25", "1.00E25",
7970                 "1.00E25", "1.00E25", "1.00E25",
7971                 "1.00E25", "1.01E25", "1.00E25"};
7972         verifyRounding(
7973                 format,
7974                 values,
7975                 expected,
7976                 roundingModes,
7977                 descriptions,
7978                 UPRV_LENGTHOF(values),
7979                 UPRV_LENGTHOF(roundingModes));
7980         }
7981     {
7982         double values[] = {-1e25, -1e25 + 1e15, -1e25 - 1e15};
7983         // The order of these expected values correspond to the order of roundingModes and the order of values.
7984         const char *expected[] = {
7985                 "-1.00E25", "-9.99E24", "-1.00E25",
7986                 "-1.00E25", "-9.99E24", "-1.00E25",
7987                 "-1.00E25", "-1.00E25", "-1.01E25",
7988                 "-1.00E25", "-1.00E25", "-1.00E25",
7989                 "-1.00E25", "-1.00E25", "-1.00E25",
7990                 "-1.00E25", "-1.00E25", "-1.00E25",
7991                 "-1.00E25", "-1.00E25", "-1.01E25"};
7992         verifyRounding(
7993                 format,
7994                 values,
7995                 expected,
7996                 roundingModes,
7997                 descriptions,
7998                 UPRV_LENGTHOF(values),
7999                 UPRV_LENGTHOF(roundingModes));
8000         }
8001     {
8002         double values[] = {1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
8003         // The order of these expected values correspond to the order of roundingModes and the order of values.
8004         const char *expected[] = {
8005                 "1.00E-25", "1.01E-25", "1.00E-25",
8006                 "1.00E-25", "1.00E-25", "9.99E-26",
8007                 "1.00E-25", "1.00E-25", "9.99E-26",
8008                 "1.00E-25", "1.00E-25", "1.00E-25",
8009                 "1.00E-25", "1.00E-25", "1.00E-25",
8010                 "1.00E-25", "1.00E-25", "1.00E-25",
8011                 "1.00E-25", "1.01E-25", "1.00E-25"};
8012         verifyRounding(
8013                 format,
8014                 values,
8015                 expected,
8016                 roundingModes,
8017                 descriptions,
8018                 UPRV_LENGTHOF(values),
8019                 UPRV_LENGTHOF(roundingModes));
8020         }
8021     {
8022         double values[] = {-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
8023         // The order of these expected values correspond to the order of roundingModes and the order of values.
8024         const char *expected[] = {
8025                 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8026                 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8027                 "-1.00E-25", "-1.00E-25", "-1.01E-25",
8028                 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8029                 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8030                 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8031                 "-1.00E-25", "-1.00E-25", "-1.01E-25"};
8032         verifyRounding(
8033                 format,
8034                 values,
8035                 expected,
8036                 roundingModes,
8037                 descriptions,
8038                 UPRV_LENGTHOF(values),
8039                 UPRV_LENGTHOF(roundingModes));
8040     }
8041 }
8042 
TestZeroScientific10547()8043 void NumberFormatTest::TestZeroScientific10547() {
8044     UErrorCode status = U_ZERO_ERROR;
8045     DecimalFormat fmt("0.00E0", status);
8046     if (!assertSuccess("Format creation", status)) {
8047         return;
8048     }
8049     UnicodeString out;
8050     fmt.format(-0.0, out);
8051     assertEquals("format", "-0.00E0", out, true);
8052 }
8053 
verifyRounding(DecimalFormat & format,const double * values,const char * const * expected,const DecimalFormat::ERoundingMode * roundingModes,const char * const * descriptions,int32_t valueSize,int32_t roundingModeSize)8054 void NumberFormatTest::verifyRounding(
8055         DecimalFormat& format,
8056         const double *values,
8057         const char * const *expected,
8058         const DecimalFormat::ERoundingMode *roundingModes,
8059         const char * const *descriptions,
8060         int32_t valueSize,
8061         int32_t roundingModeSize) {
8062     for (int32_t i = 0; i < roundingModeSize; ++i) {
8063         format.setRoundingMode(roundingModes[i]);
8064         for (int32_t j = 0; j < valueSize; j++) {
8065             UnicodeString currentExpected(expected[i * valueSize + j]);
8066             currentExpected = currentExpected.unescape();
8067             UnicodeString actual;
8068             format.format(values[j], actual);
8069             if (currentExpected != actual) {
8070                 dataerrln("For %s value %f, expected '%s', got '%s'",
8071                           descriptions[i], values[j], CStr(currentExpected)(), CStr(actual)());
8072             }
8073         }
8074     }
8075 }
8076 
TestAccountingCurrency()8077 void NumberFormatTest::TestAccountingCurrency() {
8078     UErrorCode status = U_ZERO_ERROR;
8079     UNumberFormatStyle style = UNUM_CURRENCY_ACCOUNTING;
8080 
8081     expect(NumberFormat::createInstance("en_US", style, status),
8082         (Formattable)(double)1234.5, "$1,234.50", TRUE, status);
8083     expect(NumberFormat::createInstance("en_US", style, status),
8084         (Formattable)(double)-1234.5, "($1,234.50)", TRUE, status);
8085     expect(NumberFormat::createInstance("en_US", style, status),
8086         (Formattable)(double)0, "$0.00", TRUE, status);
8087     expect(NumberFormat::createInstance("en_US", style, status),
8088         (Formattable)(double)-0.2, "($0.20)", TRUE, status);
8089     expect(NumberFormat::createInstance("ja_JP", style, status),
8090         (Formattable)(double)10000, UnicodeString("\\uFFE510,000").unescape(), TRUE, status);
8091     expect(NumberFormat::createInstance("ja_JP", style, status),
8092         (Formattable)(double)-1000.5, UnicodeString("(\\uFFE51,000)").unescape(), FALSE, status);
8093     expect(NumberFormat::createInstance("de_DE", style, status),
8094         (Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status);
8095     expect(NumberFormat::createInstance("en_ID", style, status),
8096         (Formattable)(double)0, UnicodeString("IDR\\u00A00.00").unescape(), TRUE, status);
8097     expect(NumberFormat::createInstance("en_ID", style, status),
8098         (Formattable)(double)-0.2, UnicodeString("(IDR\\u00A00.20)").unescape(), TRUE, status);
8099     expect(NumberFormat::createInstance("sh_ME", style, status),
8100         (Formattable)(double)0, UnicodeString("0,00\\u00A0\\u20AC").unescape(), TRUE, status);
8101     expect(NumberFormat::createInstance("sh_ME", style, status),
8102         (Formattable)(double)-0.2, UnicodeString("(0,20\\u00A0\\u20AC)").unescape(), TRUE, status);
8103 }
8104 
8105 /**
8106  * ICU4J has the behavior explained below, but ICU4C is not affected. Test is added to prevent regression.
8107  *
8108  * en_ID/sh_ME uses language only locales en/sh which requires NumberFormatServiceShim to fill in the currency, but
8109  * prior to ICU-20631, currency was not filled in for accounting, cash and standard, so currency placeholder was
8110  * used instead of the desired locale's currency.
8111  */
TestCurrencyFormatForMissingLocale()8112 void NumberFormatTest::TestCurrencyFormatForMissingLocale() {
8113     IcuTestErrorCode status(*this, "TestCurrencyFormatForMissingLocale");
8114     Locale locale = Locale::createCanonical("sh_ME");
8115 
8116     LocalPointer<NumberFormat> curFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status));
8117     // Fail here with missing data.
8118     if (!assertTrue(WHERE, curFmt.isValid(), false, true)) {return;};
8119     assertEquals("Currency instance is not for the desired locale for CURRENCYSTYLE", curFmt->getCurrency(), "EUR");
8120     UnicodeString currBuf;
8121     curFmt->format(-1234.5, currBuf);
8122     assertEquals("NumberFormat format outputs wrong value for CURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", currBuf);
8123 
8124     LocalPointer<NumberFormat> accFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_ACCOUNTING, status));
8125     assertEquals("Currency instance is not for the desired locale for ACCOUNTINGCURRENCYSTYLE", accFmt->getCurrency(), "EUR");
8126     UnicodeString accBuf;
8127     accFmt->format(-1234.5, accBuf);
8128     assertEquals("NumberFormat format outputs wrong value for ACCOUNTINGCURRENCYSTYLE", u"(1.234,50\u00A0\u20AC)", accBuf);
8129 
8130     LocalPointer<NumberFormat> cashFmt(NumberFormat::createInstance(locale, UNUM_CASH_CURRENCY, status));
8131     assertEquals("Currency instance is not for the desired locale for CASHCURRENCYSTYLE", cashFmt->getCurrency(), "EUR");
8132     UnicodeString cashBuf;
8133     cashFmt->format(-1234.5, cashBuf);
8134     assertEquals("NumberFormat format outputs wrong value for CASHCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", cashBuf);
8135 
8136     LocalPointer<NumberFormat> stdFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_STANDARD, status));
8137     assertEquals("Currency instance is not for the desired locale for STANDARDCURRENCYSTYLE", stdFmt->getCurrency(), "EUR");
8138     UnicodeString stdBuf;
8139     stdFmt->format(-1234.5, stdBuf);
8140     assertEquals("NumberFormat format outputs wrong value for STANDARDCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", stdBuf);
8141 }
8142 
8143 // for #5186
TestEquality()8144 void NumberFormatTest::TestEquality() {
8145     UErrorCode status = U_ZERO_ERROR;
8146     DecimalFormatSymbols symbols(Locale("root"), status);
8147     if (U_FAILURE(status)) {
8148     	dataerrln("Fail: can't create DecimalFormatSymbols for root");
8149     	return;
8150     }
8151     UnicodeString pattern("#,##0.###");
8152     DecimalFormat fmtBase(pattern, symbols, status);
8153     if (U_FAILURE(status)) {
8154     	dataerrln("Fail: can't create DecimalFormat using root symbols");
8155     	return;
8156     }
8157 
8158     DecimalFormat* fmtClone = fmtBase.clone();
8159     fmtClone->setFormatWidth(fmtBase.getFormatWidth() + 32);
8160     if (*fmtClone == fmtBase) {
8161         errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth");
8162     }
8163     delete fmtClone;
8164 }
8165 
TestCurrencyUsage()8166 void NumberFormatTest::TestCurrencyUsage() {
8167     double agent = 123.567;
8168 
8169     UErrorCode status;
8170     DecimalFormat *fmt;
8171 
8172     // compare the Currency and Currency Cash Digits
8173     // Note that as of CLDR 26:
8174     // * TWD and PKR switched from 0 decimals to 2; ISK still has 0, so change test to that
8175     // * CAD rounds to .05 in cash mode only
8176     // 1st time for getter/setter, 2nd time for factory method
8177     Locale enUS_ISK("en_US@currency=ISK");
8178 
8179     for(int i=0; i<2; i++){
8180         status = U_ZERO_ERROR;
8181         if(i == 0){
8182             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CURRENCY, status);
8183             if (assertSuccess("en_US@currency=ISK/CURRENCY", status, TRUE) == FALSE) {
8184                 continue;
8185             }
8186 
8187             UnicodeString original;
8188             fmt->format(agent,original);
8189             assertEquals("Test Currency Usage 1", u"ISK\u00A0124", original);
8190 
8191             // test the getter here
8192             UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8193             assertEquals("Test usage getter - standard", (int32_t)curUsage, (int32_t)UCURR_USAGE_STANDARD);
8194 
8195             fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8196         }else{
8197             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CASH_CURRENCY, status);
8198             if (assertSuccess("en_US@currency=ISK/CASH", status, TRUE) == FALSE) {
8199                 continue;
8200             }
8201         }
8202 
8203         // must be usage = cash
8204         UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8205         assertEquals("Test usage getter - cash", (int32_t)curUsage, (int32_t)UCURR_USAGE_CASH);
8206 
8207         UnicodeString cash_currency;
8208         fmt->format(agent,cash_currency);
8209         assertEquals("Test Currency Usage 2", u"ISK\u00A0124", cash_currency);
8210         delete fmt;
8211     }
8212 
8213     // compare the Currency and Currency Cash Rounding
8214     // 1st time for getter/setter, 2nd time for factory method
8215     Locale enUS_CAD("en_US@currency=CAD");
8216     for(int i=0; i<2; i++){
8217         status = U_ZERO_ERROR;
8218         if(i == 0){
8219             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8220             if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
8221                 continue;
8222             }
8223 
8224             UnicodeString original_rounding;
8225             fmt->format(agent, original_rounding);
8226             assertEquals("Test Currency Usage 3", u"CA$123.57", original_rounding);
8227             fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8228         }else{
8229             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8230             if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
8231                 continue;
8232             }
8233         }
8234 
8235         UnicodeString cash_rounding_currency;
8236         fmt->format(agent, cash_rounding_currency);
8237         assertEquals("Test Currency Usage 4", u"CA$123.55", cash_rounding_currency);
8238         delete fmt;
8239     }
8240 
8241     // Test the currency change
8242     // 1st time for getter/setter, 2nd time for factory method
8243     const UChar CUR_PKR[] = {0x50, 0x4B, 0x52, 0};
8244     for(int i=0; i<2; i++){
8245         status = U_ZERO_ERROR;
8246         if(i == 0){
8247             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8248             if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
8249                 continue;
8250             }
8251             fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8252         }else{
8253             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8254             if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
8255                 continue;
8256             }
8257         }
8258 
8259         UnicodeString cur_original;
8260         fmt->setCurrencyUsage(UCURR_USAGE_STANDARD, &status);
8261         fmt->format(agent, cur_original);
8262         assertEquals("Test Currency Usage 5", u"CA$123.57", cur_original);
8263 
8264         fmt->setCurrency(CUR_PKR, status);
8265         assertSuccess("Set currency to PKR", status);
8266 
8267         UnicodeString PKR_changed;
8268         fmt->format(agent, PKR_changed);
8269         assertEquals("Test Currency Usage 6", u"PKR\u00A0123.57", PKR_changed);
8270         delete fmt;
8271     }
8272 }
8273 
8274 
8275 // Check the constant MAX_INT64_IN_DOUBLE.
8276 // The value should convert to a double with no loss of precision.
8277 // A failure may indicate a platform with a different double format, requiring
8278 // a revision to the constant.
8279 //
8280 // Note that this is actually hard to test, because the language standard gives
8281 //  compilers considerable flexibility to do unexpected things with rounding and
8282 //  with overflow in simple int to/from float conversions. Some compilers will completely optimize
8283 //  away a simple round-trip conversion from int64_t -> double -> int64_t.
8284 
TestDoubleLimit11439()8285 void NumberFormatTest::TestDoubleLimit11439() {
8286     char  buf[50];
8287     for (int64_t num = MAX_INT64_IN_DOUBLE-10; num<=MAX_INT64_IN_DOUBLE; num++) {
8288         sprintf(buf, "%lld", (long long)num);
8289         double fNum = 0.0;
8290         sscanf(buf, "%lf", &fNum);
8291         int64_t rtNum = static_cast<int64_t>(fNum);
8292         if (num != rtNum) {
8293             errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8294             return;
8295         }
8296     }
8297     for (int64_t num = -MAX_INT64_IN_DOUBLE+10; num>=-MAX_INT64_IN_DOUBLE; num--) {
8298         sprintf(buf, "%lld", (long long)num);
8299         double fNum = 0.0;
8300         sscanf(buf, "%lf", &fNum);
8301         int64_t rtNum = static_cast<int64_t>(fNum);
8302         if (num != rtNum) {
8303             errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8304             return;
8305         }
8306     }
8307 }
8308 
TestGetAffixes()8309 void NumberFormatTest::TestGetAffixes() {
8310     UErrorCode status = U_ZERO_ERROR;
8311     DecimalFormatSymbols sym("en_US", status);
8312     UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8313     pattern = pattern.unescape();
8314     DecimalFormat fmt(pattern, sym, status);
8315     if (U_FAILURE(status)) {
8316         dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8317         return;
8318     }
8319     UnicodeString affixStr;
8320     assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8321     assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8322     assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8323     assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8324 
8325     // Test equality with affixes. set affix methods can't capture special
8326     // characters which is why equality should fail.
8327     {
8328         DecimalFormat fmtCopy(fmt);
8329         assertTrue("", fmt == fmtCopy);
8330         UnicodeString someAffix;
8331         fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(someAffix));
8332         assertTrue("", fmt != fmtCopy);
8333     }
8334     {
8335         DecimalFormat fmtCopy(fmt);
8336         assertTrue("", fmt == fmtCopy);
8337         UnicodeString someAffix;
8338         fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(someAffix));
8339         assertTrue("", fmt != fmtCopy);
8340     }
8341     {
8342         DecimalFormat fmtCopy(fmt);
8343         assertTrue("", fmt == fmtCopy);
8344         UnicodeString someAffix;
8345         fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(someAffix));
8346         assertTrue("", fmt != fmtCopy);
8347     }
8348     {
8349         DecimalFormat fmtCopy(fmt);
8350         assertTrue("", fmt == fmtCopy);
8351         UnicodeString someAffix;
8352         fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(someAffix));
8353         assertTrue("", fmt != fmtCopy);
8354     }
8355     fmt.setPositivePrefix("Don't");
8356     fmt.setPositiveSuffix("do");
8357     UnicodeString someAffix("be''eet\\u00a4\\u00a4\\u00a4 it.");
8358     someAffix = someAffix.unescape();
8359     fmt.setNegativePrefix(someAffix);
8360     fmt.setNegativeSuffix("%");
8361     assertEquals("", "Don't", fmt.getPositivePrefix(affixStr));
8362     assertEquals("", "do", fmt.getPositiveSuffix(affixStr));
8363     assertEquals("", someAffix, fmt.getNegativePrefix(affixStr));
8364     assertEquals("", "%", fmt.getNegativeSuffix(affixStr));
8365 }
8366 
TestToPatternScientific11648()8367 void NumberFormatTest::TestToPatternScientific11648() {
8368     UErrorCode status = U_ZERO_ERROR;
8369     Locale en("en");
8370     DecimalFormatSymbols sym(en, status);
8371     DecimalFormat fmt("0.00", sym, status);
8372     if (U_FAILURE(status)) {
8373         dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8374         return;
8375     }
8376     fmt.setScientificNotation(TRUE);
8377     UnicodeString pattern;
8378     assertEquals("", "0.00E0", fmt.toPattern(pattern));
8379     DecimalFormat fmt2(pattern, sym, status);
8380     assertSuccess("", status);
8381 }
8382 
TestBenchmark()8383 void NumberFormatTest::TestBenchmark() {
8384 /*
8385     UErrorCode status = U_ZERO_ERROR;
8386     Locale en("en");
8387     DecimalFormatSymbols sym(en, status);
8388     DecimalFormat fmt("0.0000000", new DecimalFormatSymbols(sym), status);
8389 //    DecimalFormat fmt("0.00000E0", new DecimalFormatSymbols(sym), status);
8390 //    DecimalFormat fmt("0", new DecimalFormatSymbols(sym), status);
8391     FieldPosition fpos(FieldPosition::DONT_CARE);
8392     clock_t start = clock();
8393     for (int32_t i = 0; i < 1000000; ++i) {
8394         UnicodeString append;
8395         fmt.format(3.0, append, fpos, status);
8396 //        fmt.format(4.6692016, append, fpos, status);
8397 //        fmt.format(1234567.8901, append, fpos, status);
8398 //        fmt.format(2.99792458E8, append, fpos, status);
8399 //        fmt.format(31, append);
8400     }
8401     errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8402     assertSuccess("", status);
8403 
8404     UErrorCode status = U_ZERO_ERROR;
8405     MessageFormat fmt("{0, plural, one {I have # friend.} other {I have # friends.}}", status);
8406     FieldPosition fpos(FieldPosition::DONT_CARE);
8407     Formattable one(1.0);
8408     Formattable three(3.0);
8409     clock_t start = clock();
8410     for (int32_t i = 0; i < 500000; ++i) {
8411         UnicodeString append;
8412         fmt.format(&one, 1, append, fpos, status);
8413         UnicodeString append2;
8414         fmt.format(&three, 1, append2, fpos, status);
8415     }
8416     errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8417     assertSuccess("", status);
8418 
8419     UErrorCode status = U_ZERO_ERROR;
8420     Locale en("en");
8421     Measure measureC(23, MeasureUnit::createCelsius(status), status);
8422     MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
8423     FieldPosition fpos(FieldPosition::DONT_CARE);
8424     clock_t start = clock();
8425     for (int32_t i = 0; i < 1000000; ++i) {
8426         UnicodeString appendTo;
8427         fmt.formatMeasures(
8428                 &measureC, 1, appendTo, fpos, status);
8429     }
8430     errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8431     assertSuccess("", status);
8432 */
8433 }
8434 
TestFractionalDigitsForCurrency()8435 void NumberFormatTest::TestFractionalDigitsForCurrency() {
8436     UErrorCode status = U_ZERO_ERROR;
8437     LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance("en", status));
8438     if (U_FAILURE(status)) {
8439         dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8440         return;
8441     }
8442     UChar JPY[] = {0x4A, 0x50, 0x59, 0x0};
8443     fmt->setCurrency(JPY, status);
8444     if (!assertSuccess("", status)) {
8445         return;
8446     }
8447     assertEquals("", 0, fmt->getMaximumFractionDigits());
8448 }
8449 
8450 
TestFormatCurrencyPlural()8451 void NumberFormatTest::TestFormatCurrencyPlural() {
8452     UErrorCode status = U_ZERO_ERROR;
8453     Locale locale = Locale::createCanonical("en_US");
8454     NumberFormat *fmt = NumberFormat::createInstance(locale, UNUM_CURRENCY_PLURAL, status);
8455     if (U_FAILURE(status)) {
8456         dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8457         return;
8458     }
8459    UnicodeString formattedNum;
8460    fmt->format(11234.567, formattedNum, NULL, status);
8461    assertEquals("", "11,234.57 US dollars", formattedNum);
8462    delete fmt;
8463 }
8464 
TestCtorApplyPatternDifference()8465 void NumberFormatTest::TestCtorApplyPatternDifference() {
8466     UErrorCode status = U_ZERO_ERROR;
8467     DecimalFormatSymbols sym("en_US", status);
8468     UnicodeString pattern("\\u00a40");
8469     DecimalFormat fmt(pattern.unescape(), sym, status);
8470     if (U_FAILURE(status)) {
8471         dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8472         return;
8473     }
8474     UnicodeString result;
8475     assertEquals(
8476             "ctor favors precision of currency",
8477             "$5.00",
8478             fmt.format((double)5, result));
8479     result.remove();
8480     fmt.applyPattern(pattern.unescape(), status);
8481     assertEquals(
8482             "applyPattern favors precision of pattern",
8483             "$5",
8484             fmt.format((double)5, result));
8485 }
8486 
Test11868()8487 void NumberFormatTest::Test11868() {
8488     double posAmt = 34.567;
8489     double negAmt = -9876.543;
8490 
8491     Locale selectedLocale("en_US");
8492     UErrorCode status = U_ZERO_ERROR;
8493 
8494     UnicodeString result;
8495     FieldPosition fpCurr(UNUM_CURRENCY_FIELD);
8496     LocalPointer<NumberFormat> fmt(
8497             NumberFormat::createInstance(
8498                     selectedLocale, UNUM_CURRENCY_PLURAL, status));
8499     if (!assertSuccess("Format creation", status)) {
8500         return;
8501     }
8502     fmt->format(posAmt, result, fpCurr, status);
8503     assertEquals("", "34.57 US dollars", result);
8504     assertEquals("begin index", 6, fpCurr.getBeginIndex());
8505     assertEquals("end index", 16, fpCurr.getEndIndex());
8506 
8507     // Test field position iterator
8508     {
8509         NumberFormatTest_Attributes attributes[] = {
8510                 {UNUM_INTEGER_FIELD, 0, 2},
8511                 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8512                 {UNUM_FRACTION_FIELD, 3, 5},
8513                 {UNUM_CURRENCY_FIELD, 6, 16},
8514                 {0, -1, 0}};
8515         UnicodeString result;
8516         FieldPositionIterator iter;
8517         fmt->format(posAmt, result, &iter, status);
8518         assertEquals("", "34.57 US dollars", result);
8519         verifyFieldPositionIterator(attributes, iter);
8520     }
8521 
8522     result.remove();
8523     fmt->format(negAmt, result, fpCurr, status);
8524     assertEquals("", "-9,876.54 US dollars", result);
8525     assertEquals("begin index", 10, fpCurr.getBeginIndex());
8526     assertEquals("end index", 20, fpCurr.getEndIndex());
8527 
8528     // Test field position iterator
8529     {
8530         NumberFormatTest_Attributes attributes[] = {
8531                 {UNUM_SIGN_FIELD, 0, 1},
8532                 {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
8533                 {UNUM_INTEGER_FIELD, 1, 6},
8534                 {UNUM_DECIMAL_SEPARATOR_FIELD, 6, 7},
8535                 {UNUM_FRACTION_FIELD, 7, 9},
8536                 {UNUM_CURRENCY_FIELD, 10, 20},
8537                 {0, -1, 0}};
8538         UnicodeString result;
8539         FieldPositionIterator iter;
8540         fmt->format(negAmt, result, &iter, status);
8541         assertEquals("", "-9,876.54 US dollars", result);
8542         verifyFieldPositionIterator(attributes, iter);
8543     }
8544 }
8545 
Test10727_RoundingZero()8546 void NumberFormatTest::Test10727_RoundingZero() {
8547     IcuTestErrorCode status(*this, "Test10727_RoundingZero");
8548     DecimalQuantity dq;
8549     dq.setToDouble(-0.0);
8550     assertTrue("", dq.isNegative());
8551     dq.roundToMagnitude(0, UNUM_ROUND_HALFEVEN, status);
8552     assertTrue("", dq.isNegative());
8553 }
8554 
Test11739_ParseLongCurrency()8555 void NumberFormatTest::Test11739_ParseLongCurrency() {
8556     IcuTestErrorCode status(*this, "Test11739_ParseLongCurrency");
8557     LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("sr_BA", status));
8558     if (status.errDataIfFailureAndReset()) { return; }
8559     ((DecimalFormat*) nf.getAlias())->applyPattern(u"#,##0.0 ¤¤¤", status);
8560     ParsePosition ppos(0);
8561     LocalPointer<CurrencyAmount> result(nf->parseCurrency(u"1.500 амерички долар", ppos));
8562     assertEquals("Should parse to 1500 USD", -1, ppos.getErrorIndex());
8563     if (ppos.getErrorIndex() != -1) {
8564         return;
8565     }
8566     assertEquals("Should parse to 1500 USD", 1500LL, result->getNumber().getInt64(status));
8567     assertEquals("Should parse to 1500 USD", u"USD", result->getISOCurrency());
8568 }
8569 
Test13035_MultiCodePointPaddingInPattern()8570 void NumberFormatTest::Test13035_MultiCodePointPaddingInPattern() {
8571     IcuTestErrorCode status(*this, "Test13035_MultiCodePointPaddingInPattern");
8572     DecimalFormat df(u"a*'நி'###0b", status);
8573     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8574     UnicodeString result;
8575     df.format(12, result.remove());
8576     // TODO(13034): Re-enable this test when support is added in ICU4C.
8577     //assertEquals("Multi-codepoint padding should not be split", u"aநிநி12b", result);
8578     df = DecimalFormat(u"a*\U0001F601###0b", status);
8579     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8580     result = df.format(12, result.remove());
8581     assertEquals("Single-codepoint padding should not be split", u"a\U0001F601\U0001F60112b", result, true);
8582     df = DecimalFormat(u"a*''###0b", status);
8583     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8584     result = df.format(12, result.remove());
8585     assertEquals("Quote should be escapable in padding syntax", "a''12b", result, true);
8586 }
8587 
Test13737_ParseScientificStrict()8588 void NumberFormatTest::Test13737_ParseScientificStrict() {
8589     IcuTestErrorCode status(*this, "Test13737_ParseScientificStrict");
8590     LocalPointer<NumberFormat> df(NumberFormat::createScientificInstance("en", status), status);
8591     if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8592     df->setLenient(FALSE);
8593     // Parse Test
8594     expect(*df, u"1.2", 1.2);
8595 }
8596 
Test11376_getAndSetPositivePrefix()8597 void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
8598     {
8599         const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8600         UErrorCode status = U_ZERO_ERROR;
8601         LocalPointer<NumberFormat> fmt(
8602                 NumberFormat::createCurrencyInstance("en", status));
8603         if (!assertSuccess("", status)) {
8604             return;
8605         }
8606         DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8607         dfmt->setCurrency(USD);
8608         UnicodeString result;
8609 
8610         // This line should be a no-op. I am setting the positive prefix
8611         // to be the same thing it was before.
8612         dfmt->setPositivePrefix(dfmt->getPositivePrefix(result));
8613 
8614         UnicodeString appendTo;
8615         assertEquals("", "$3.78", dfmt->format(3.78, appendTo, status));
8616         assertSuccess("", status);
8617     }
8618     {
8619         const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8620         UErrorCode status = U_ZERO_ERROR;
8621         LocalPointer<NumberFormat> fmt(
8622                 NumberFormat::createInstance("en", UNUM_CURRENCY_PLURAL, status));
8623         if (!assertSuccess("", status)) {
8624             return;
8625         }
8626         DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8627         UnicodeString result;
8628         assertEquals("", u" (unknown currency)", dfmt->getPositiveSuffix(result));
8629         dfmt->setCurrency(USD);
8630 
8631         // getPositiveSuffix() always returns the suffix for the
8632         // "other" plural category
8633         assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8634         UnicodeString appendTo;
8635         assertEquals("", "3.78 US dollars", dfmt->format(3.78, appendTo, status));
8636         assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8637         dfmt->setPositiveSuffix("booya");
8638         appendTo.remove();
8639         assertEquals("", "3.78booya", dfmt->format(3.78, appendTo, status));
8640         assertEquals("", "booya", dfmt->getPositiveSuffix(result));
8641     }
8642 }
8643 
Test11475_signRecognition()8644 void NumberFormatTest::Test11475_signRecognition() {
8645     UErrorCode status = U_ZERO_ERROR;
8646     DecimalFormatSymbols sym("en", status);
8647     UnicodeString result;
8648     {
8649         DecimalFormat fmt("+0.00", sym, status);
8650         if (!assertSuccess("", status)) {
8651             return;
8652         }
8653         NumberFormatTest_Attributes attributes[] = {
8654                 {UNUM_SIGN_FIELD, 0, 1},
8655                 {UNUM_INTEGER_FIELD, 1, 2},
8656                 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8657                 {UNUM_FRACTION_FIELD, 3, 5},
8658                 {0, -1, 0}};
8659         UnicodeString result;
8660         FieldPositionIterator iter;
8661         fmt.format(2.3, result, &iter, status);
8662         assertEquals("", "+2.30", result);
8663         verifyFieldPositionIterator(attributes, iter);
8664     }
8665     {
8666         DecimalFormat fmt("++0.00+;-(#)--", sym, status);
8667         if (!assertSuccess("", status)) {
8668             return;
8669         }
8670         {
8671             NumberFormatTest_Attributes attributes[] = {
8672                     {UNUM_SIGN_FIELD, 0, 2},
8673                     {UNUM_INTEGER_FIELD, 2, 3},
8674                     {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8675                     {UNUM_FRACTION_FIELD, 4, 6},
8676                     {UNUM_SIGN_FIELD, 6, 7},
8677                     {0, -1, 0}};
8678             UnicodeString result;
8679             FieldPositionIterator iter;
8680             fmt.format(2.3, result, &iter, status);
8681             assertEquals("", "++2.30+", result);
8682             verifyFieldPositionIterator(attributes, iter);
8683         }
8684         {
8685             NumberFormatTest_Attributes attributes[] = {
8686                     {UNUM_SIGN_FIELD, 0, 1},
8687                     {UNUM_INTEGER_FIELD, 2, 3},
8688                     {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8689                     {UNUM_FRACTION_FIELD, 4, 6},
8690                     {UNUM_SIGN_FIELD, 7, 9},
8691                     {0, -1, 0}};
8692             UnicodeString result;
8693             FieldPositionIterator iter;
8694             fmt.format(-2.3, result, &iter, status);
8695             assertEquals("", "-(2.30)--", result);
8696             verifyFieldPositionIterator(attributes, iter);
8697         }
8698     }
8699 }
8700 
Test11640_getAffixes()8701 void NumberFormatTest::Test11640_getAffixes() {
8702     UErrorCode status = U_ZERO_ERROR;
8703     DecimalFormatSymbols symbols("en_US", status);
8704     if (!assertSuccess("", status)) {
8705         return;
8706     }
8707     UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8708     pattern = pattern.unescape();
8709     DecimalFormat fmt(pattern, symbols, status);
8710     if (!assertSuccess("", status)) {
8711         return;
8712     }
8713     UnicodeString affixStr;
8714     assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8715     assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8716     assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8717     assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8718 }
8719 
Test11649_toPatternWithMultiCurrency()8720 void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
8721     UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
8722     pattern = pattern.unescape();
8723     UErrorCode status = U_ZERO_ERROR;
8724     DecimalFormat fmt(pattern, status);
8725     if (!assertSuccess("", status)) {
8726         return;
8727     }
8728     static UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8729     fmt.setCurrency(USD);
8730     UnicodeString appendTo;
8731 
8732     assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
8733 
8734     UnicodeString topattern;
8735     fmt.toPattern(topattern);
8736     DecimalFormat fmt2(topattern, status);
8737     if (!assertSuccess("", status)) {
8738         return;
8739     }
8740     fmt2.setCurrency(USD);
8741 
8742     appendTo.remove();
8743     assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
8744 }
8745 
Test13327_numberingSystemBufferOverflow()8746 void NumberFormatTest::Test13327_numberingSystemBufferOverflow() {
8747     UErrorCode status = U_ZERO_ERROR;
8748     for (int runId = 0; runId < 2; runId++) {
8749         // Construct a locale string with a very long "numbers" value.
8750         // The first time, make the value length exactly equal to ULOC_KEYWORDS_CAPACITY.
8751         // The second time, make it exceed ULOC_KEYWORDS_CAPACITY.
8752         int extraLength = (runId == 0) ? 0 : 5;
8753 
8754         CharString localeId("en@numbers=", status);
8755         for (int i = 0; i < ULOC_KEYWORDS_CAPACITY + extraLength; i++) {
8756             localeId.append('x', status);
8757         }
8758         assertSuccess("Constructing locale string", status);
8759         Locale locale(localeId.data());
8760 
8761         LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(locale, status));
8762         assertFalse("Should not be null", ns.getAlias() == nullptr);
8763         assertSuccess("Should create with no error", status);
8764     }
8765 }
8766 
Test13391_chakmaParsing()8767 void NumberFormatTest::Test13391_chakmaParsing() {
8768     UErrorCode status = U_ZERO_ERROR;
8769     LocalPointer<DecimalFormat> df(dynamic_cast<DecimalFormat*>(
8770         NumberFormat::createInstance(Locale("ccp"), status)));
8771     if (df == nullptr) {
8772         dataerrln("%s %d Chakma df is null",  __FILE__, __LINE__);
8773         return;
8774     }
8775     const UChar* expected = u"\U00011137\U00011138,\U00011139\U0001113A\U0001113B";
8776     UnicodeString actual;
8777     df->format(12345, actual, status);
8778     assertSuccess("Should not fail when formatting in ccp", status);
8779     assertEquals("Should produce expected output in ccp", expected, actual);
8780 
8781     Formattable result;
8782     df->parse(expected, result, status);
8783     assertSuccess("Should not fail when parsing in ccp", status);
8784     assertEquals("Should parse to 12345 in ccp", 12345, result);
8785 
8786     const UChar* expectedScientific = u"\U00011137.\U00011139E\U00011138";
8787     UnicodeString actualScientific;
8788     df.adoptInstead(static_cast<DecimalFormat*>(
8789         NumberFormat::createScientificInstance(Locale("ccp"), status)));
8790     df->format(130, actualScientific, status);
8791     assertSuccess("Should not fail when formatting scientific in ccp", status);
8792     assertEquals("Should produce expected scientific output in ccp",
8793         expectedScientific, actualScientific);
8794 
8795     Formattable resultScientific;
8796     df->parse(expectedScientific, resultScientific, status);
8797     assertSuccess("Should not fail when parsing scientific in ccp", status);
8798     assertEquals("Should parse scientific to 130 in ccp", 130, resultScientific);
8799 }
8800 
8801 
verifyFieldPositionIterator(NumberFormatTest_Attributes * expected,FieldPositionIterator & iter)8802 void NumberFormatTest::verifyFieldPositionIterator(
8803         NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
8804     int32_t idx = 0;
8805     FieldPosition fp;
8806     while (iter.next(fp)) {
8807         if (expected[idx].spos == -1) {
8808             errln("Iterator should have ended. got %d", fp.getField());
8809             return;
8810         }
8811         assertEquals("id", expected[idx].id, fp.getField());
8812         assertEquals("start", expected[idx].spos, fp.getBeginIndex());
8813         assertEquals("end", expected[idx].epos, fp.getEndIndex());
8814         ++idx;
8815     }
8816     if (expected[idx].spos != -1) {
8817         errln("Premature end of iterator. expected %d", expected[idx].id);
8818     }
8819 }
8820 
Test11735_ExceptionIssue()8821 void NumberFormatTest::Test11735_ExceptionIssue() {
8822     IcuTestErrorCode status(*this, "Test11735_ExceptionIssue");
8823     Locale enLocale("en");
8824     DecimalFormatSymbols symbols(enLocale, status);
8825     if (status.isSuccess()) {
8826         DecimalFormat fmt("0", symbols, status);
8827         assertSuccess("Fail: Construct DecimalFormat formatter", status, true, __FILE__, __LINE__);
8828         ParsePosition ppos(0);
8829         fmt.parseCurrency("53.45", ppos);  // NPE thrown here in ICU4J.
8830         assertEquals("Issue11735 ppos", 0, ppos.getIndex());
8831     }
8832 }
8833 
Test11035_FormatCurrencyAmount()8834 void NumberFormatTest::Test11035_FormatCurrencyAmount() {
8835     UErrorCode status = U_ZERO_ERROR;
8836     double amount = 12345.67;
8837     const char16_t* expected = u"12,345$67 ​";
8838 
8839     // Test two ways to set a currency via API
8840 
8841     Locale loc1 = Locale("pt_PT");
8842     LocalPointer<NumberFormat> fmt1(NumberFormat::createCurrencyInstance(loc1, status),
8843                                     status);
8844     if (U_FAILURE(status)) {
8845       dataerrln("%s %d NumberFormat instance fmt1 is null",  __FILE__, __LINE__);
8846       return;
8847     }
8848     fmt1->setCurrency(u"PTE", status);
8849     assertSuccess("Setting currency on fmt1", status);
8850     UnicodeString actualSetCurrency;
8851     fmt1->format(amount, actualSetCurrency);
8852 
8853     Locale loc2 = Locale("pt_PT@currency=PTE");
8854     LocalPointer<NumberFormat> fmt2(NumberFormat::createCurrencyInstance(loc2, status));
8855     assertSuccess("Creating fmt2", status);
8856     UnicodeString actualLocaleString;
8857     fmt2->format(amount, actualLocaleString);
8858 
8859     assertEquals("Custom Currency Pattern, Set Currency", expected, actualSetCurrency);
8860     assertEquals("Custom Currency Pattern, Locale String", expected, actualLocaleString);
8861 }
8862 
Test11318_DoubleConversion()8863 void NumberFormatTest::Test11318_DoubleConversion() {
8864     IcuTestErrorCode status(*this, "Test11318_DoubleConversion");
8865     LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
8866     if (U_FAILURE(status)) {
8867       dataerrln("%s %d Error in NumberFormat instance creation",  __FILE__, __LINE__);
8868       return;
8869     }
8870     nf->setMaximumFractionDigits(40);
8871     nf->setMaximumIntegerDigits(40);
8872     UnicodeString appendTo;
8873     nf->format(999999999999999.9, appendTo);
8874     assertEquals("Should render all digits", u"999,999,999,999,999.9", appendTo);
8875 }
8876 
TestParsePercentRegression()8877 void NumberFormatTest::TestParsePercentRegression() {
8878     IcuTestErrorCode status(*this, "TestParsePercentRegression");
8879     LocalPointer<DecimalFormat> df1((DecimalFormat*) NumberFormat::createInstance("en", status), status);
8880     LocalPointer<DecimalFormat> df2((DecimalFormat*) NumberFormat::createPercentInstance("en", status), status);
8881     if (status.isFailure()) {return; }
8882     df1->setLenient(TRUE);
8883     df2->setLenient(TRUE);
8884 
8885     {
8886         ParsePosition ppos;
8887         Formattable result;
8888         df1->parse("50%", result, ppos);
8889         assertEquals("df1 should accept a number but not the percent sign", 2, ppos.getIndex());
8890         assertEquals("df1 should return the number as 50", 50.0, result.getDouble(status));
8891     }
8892     {
8893         ParsePosition ppos;
8894         Formattable result;
8895         df2->parse("50%", result, ppos);
8896         assertEquals("df2 should accept the percent sign", 3, ppos.getIndex());
8897         assertEquals("df2 should return the number as 0.5", 0.5, result.getDouble(status));
8898     }
8899     {
8900         ParsePosition ppos;
8901         Formattable result;
8902         df2->parse("50", result, ppos);
8903         assertEquals("df2 should return the number as 0.5 even though the percent sign is missing",
8904                 0.5,
8905                 result.getDouble(status));
8906     }
8907 }
8908 
TestMultiplierWithScale()8909 void NumberFormatTest::TestMultiplierWithScale() {
8910     IcuTestErrorCode status(*this, "TestMultiplierWithScale");
8911 
8912     // Test magnitude combined with multiplier, as shown in API docs
8913     DecimalFormat df("0", {"en", status}, status);
8914     if (status.isSuccess()) {
8915         df.setMultiplier(5);
8916         df.setMultiplierScale(-1);
8917         expect2(df, 100, u"50"); // round-trip test
8918     }
8919 }
8920 
TestFastFormatInt32()8921 void NumberFormatTest::TestFastFormatInt32() {
8922     IcuTestErrorCode status(*this, "TestFastFormatInt32");
8923 
8924     // The two simplest formatters, old API and new API.
8925     // Old API should use the fastpath for ints.
8926     LocalizedNumberFormatter lnf = NumberFormatter::withLocale("en");
8927     LocalPointer<NumberFormat> df(NumberFormat::createInstance("en", status), status);
8928     if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8929 
8930     double nums[] = {
8931             0.0,
8932             -0.0,
8933             NAN,
8934             INFINITY,
8935             0.1,
8936             1.0,
8937             1.1,
8938             2.0,
8939             3.0,
8940             9.0,
8941             10.0,
8942             99.0,
8943             100.0,
8944             999.0,
8945             1000.0,
8946             9999.0,
8947             10000.0,
8948             99999.0,
8949             100000.0,
8950             999999.0,
8951             1000000.0,
8952             static_cast<double>(INT32_MAX) - 1,
8953             static_cast<double>(INT32_MAX),
8954             static_cast<double>(INT32_MAX) + 1,
8955             static_cast<double>(INT32_MIN) - 1,
8956             static_cast<double>(INT32_MIN),
8957             static_cast<double>(INT32_MIN) + 1};
8958 
8959     for (auto num : nums) {
8960         UnicodeString expected = lnf.formatDouble(num, status).toString(status);
8961         UnicodeString actual;
8962         df->format(num, actual);
8963         assertEquals(UnicodeString("d = ") + num, expected, actual);
8964     }
8965 }
8966 
Test11646_Equality()8967 void NumberFormatTest::Test11646_Equality() {
8968     UErrorCode status = U_ZERO_ERROR;
8969     DecimalFormatSymbols symbols(Locale::getEnglish(), status);
8970     UnicodeString pattern(u"\u00a4\u00a4\u00a4 0.00 %\u00a4\u00a4");
8971     DecimalFormat fmt(pattern, symbols, status);
8972     if (!assertSuccess("", status)) return;
8973 
8974     // Test equality with affixes. set affix methods can't capture special
8975     // characters which is why equality should fail.
8976     {
8977         DecimalFormat fmtCopy(fmt);
8978         assertTrue("", fmt == fmtCopy);
8979         UnicodeString positivePrefix;
8980         fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(positivePrefix));
8981         assertFalse("", fmt == fmtCopy);
8982     }
8983     {
8984         DecimalFormat fmtCopy = DecimalFormat(fmt);
8985         assertTrue("", fmt == fmtCopy);
8986         UnicodeString positivePrefix;
8987         fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(positivePrefix));
8988         assertFalse("", fmt == fmtCopy);
8989     }
8990     {
8991         DecimalFormat fmtCopy(fmt);
8992         assertTrue("", fmt == fmtCopy);
8993         UnicodeString negativePrefix;
8994         fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(negativePrefix));
8995         assertFalse("", fmt == fmtCopy);
8996     }
8997     {
8998         DecimalFormat fmtCopy(fmt);
8999         assertTrue("", fmt == fmtCopy);
9000         UnicodeString negativePrefix;
9001         fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(negativePrefix));
9002         assertFalse("", fmt == fmtCopy);
9003     }
9004 }
9005 
TestParseNaN()9006 void NumberFormatTest::TestParseNaN() {
9007     IcuTestErrorCode status(*this, "TestParseNaN");
9008 
9009     DecimalFormat df("0", { "en", status }, status);
9010     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9011     Formattable parseResult;
9012     df.parse(u"NaN", parseResult, status);
9013     assertEquals("NaN should parse successfully", NAN, parseResult.getDouble());
9014     assertFalse("Result NaN should be positive", std::signbit(parseResult.getDouble()));
9015     UnicodeString formatResult;
9016     df.format(parseResult.getDouble(), formatResult);
9017     assertEquals("NaN should round-trip", u"NaN", formatResult);
9018 }
9019 
TestFormatFailIfMoreThanMaxDigits()9020 void NumberFormatTest::TestFormatFailIfMoreThanMaxDigits() {
9021     IcuTestErrorCode status(*this, "TestFormatFailIfMoreThanMaxDigits");
9022 
9023     DecimalFormat df("0", {"en-US", status}, status);
9024     if (status.errDataIfFailureAndReset()) {
9025         return;
9026     }
9027     assertEquals("Coverage for getter 1", (UBool) FALSE, df.isFormatFailIfMoreThanMaxDigits());
9028     df.setFormatFailIfMoreThanMaxDigits(TRUE);
9029     assertEquals("Coverage for getter 2", (UBool) TRUE, df.isFormatFailIfMoreThanMaxDigits());
9030     df.setMaximumIntegerDigits(2);
9031     UnicodeString result;
9032     df.format(1234, result, status);
9033     status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
9034 }
9035 
TestParseCaseSensitive()9036 void NumberFormatTest::TestParseCaseSensitive() {
9037     IcuTestErrorCode status(*this, "TestParseCaseSensitive");
9038 
9039     DecimalFormat df(u"0", {"en-US", status}, status);
9040     if (status.errDataIfFailureAndReset()) {
9041         return;
9042     }
9043     assertEquals("Coverage for getter 1", (UBool) FALSE, df.isParseCaseSensitive());
9044     df.setParseCaseSensitive(TRUE);
9045     assertEquals("Coverage for getter 1", (UBool) TRUE, df.isParseCaseSensitive());
9046     Formattable result;
9047     ParsePosition ppos;
9048     df.parse(u"1e2", result, ppos);
9049     assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9050     assertEquals("Result should be 1", 1.0, result.getDouble(status));
9051 }
9052 
TestParseNoExponent()9053 void NumberFormatTest::TestParseNoExponent() {
9054     IcuTestErrorCode status(*this, "TestParseNoExponent");
9055 
9056     DecimalFormat df(u"0", {"en-US", status}, status);
9057     if (status.errDataIfFailureAndReset()) {
9058         return;
9059     }
9060     assertEquals("Coverage for getter 1", (UBool) FALSE, df.isParseNoExponent());
9061     df.setParseNoExponent(TRUE);
9062     assertEquals("Coverage for getter 1", (UBool) TRUE, df.isParseNoExponent());
9063     Formattable result;
9064     ParsePosition ppos;
9065     df.parse(u"1E2", result, ppos);
9066     assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9067     assertEquals("Result should be 1", 1.0, result.getDouble(status));
9068 }
9069 
TestSignAlwaysShown()9070 void NumberFormatTest::TestSignAlwaysShown() {
9071     IcuTestErrorCode status(*this, "TestSignAlwaysShown");
9072 
9073     DecimalFormat df(u"0", {"en-US", status}, status);
9074     if (status.errDataIfFailureAndReset()) {
9075         return;
9076     }
9077     assertEquals("Coverage for getter 1", (UBool) FALSE, df.isSignAlwaysShown());
9078     df.setSignAlwaysShown(TRUE);
9079     assertEquals("Coverage for getter 1", (UBool) TRUE, df.isSignAlwaysShown());
9080     UnicodeString result;
9081     df.format(1234, result, status);
9082     status.errIfFailureAndReset();
9083     assertEquals("Should show sign on positive number", u"+1234", result);
9084 }
9085 
TestMinimumGroupingDigits()9086 void NumberFormatTest::TestMinimumGroupingDigits() {
9087     IcuTestErrorCode status(*this, "TestMinimumGroupingDigits");
9088 
9089     DecimalFormat df(u"#,##0", {"en-US", status}, status);
9090     if (status.errDataIfFailureAndReset()) {
9091         return;
9092     }
9093     assertEquals("Coverage for getter 1", -1, df.getMinimumGroupingDigits());
9094     df.setMinimumGroupingDigits(2);
9095     assertEquals("Coverage for getter 1", 2, df.getMinimumGroupingDigits());
9096     UnicodeString result;
9097     df.format(1234, result, status);
9098     status.errIfFailureAndReset();
9099     assertEquals("Should not have grouping", u"1234", result);
9100     df.format(12345, result.remove(), status);
9101     status.errIfFailureAndReset();
9102     assertEquals("Should have grouping", u"12,345", result);
9103 
9104 
9105     // Test special values -1, UNUM_MINIMUM_GROUPING_DIGITS_AUTO and
9106     // UNUM_MINIMUM_GROUPING_DIGITS_MIN2
9107     struct TestCase {
9108         const char* locale;
9109         int32_t minGroup;
9110         double input;
9111         const char16_t* expected;
9112     } cases[] = {
9113         { "en-US", 1, 1000, u"1,000" },
9114         { "en-US", 1, 10000, u"10,000" },
9115         { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1,000" },
9116         { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10,000" },
9117         { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9118         { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10,000" },
9119 
9120         { "es", 1, 1000, u"1.000" },
9121         { "es", 1, 10000, u"10.000" },
9122         { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1000" },
9123         { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10.000" },
9124         { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9125         { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10.000" },
9126     };
9127     for (const auto& cas : cases) {
9128         UnicodeString message = UnicodeString(cas.locale)
9129             + u" " + Int64ToUnicodeString(cas.minGroup)
9130             + u" " + DoubleToUnicodeString(cas.input);
9131         status.setScope(message);
9132         DecimalFormat df(u"#,##0", {cas.locale, status}, status);
9133         if (status.errIfFailureAndReset()) { continue; }
9134         df.setMinimumGroupingDigits(cas.minGroup);
9135         UnicodeString actual;
9136         df.format(cas.input, actual, status);
9137         if (status.errIfFailureAndReset()) { continue; }
9138         assertEquals(message, cas.expected, actual);
9139     }
9140 }
9141 
Test11897_LocalizedPatternSeparator()9142 void NumberFormatTest::Test11897_LocalizedPatternSeparator() {
9143     IcuTestErrorCode status(*this, "Test11897_LocalizedPatternSeparator");
9144 
9145     // In a locale with a different <list> symbol, like arabic,
9146     // kPatternSeparatorSymbol should still be ';'
9147     {
9148         DecimalFormatSymbols dfs("ar", status);
9149         assertEquals("pattern separator symbol should be ;",
9150                 u";",
9151                 dfs.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
9152     }
9153 
9154     // However, the custom symbol should be used in localized notation
9155     // when set manually via API
9156     {
9157         DecimalFormatSymbols dfs("en", status);
9158         dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u"!", FALSE);
9159         DecimalFormat df(u"0", dfs, status);
9160         if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9161         df.applyPattern("a0;b0", status); // should not throw
9162         UnicodeString result;
9163         assertEquals("should apply the normal pattern",
9164                 df.getNegativePrefix(result.remove()),
9165                 "b");
9166         df.applyLocalizedPattern(u"c0!d0", status); // should not throw
9167         assertEquals("should apply the localized pattern",
9168                 df.getNegativePrefix(result.remove()),
9169                 "d");
9170     }
9171 }
9172 
Test13055_PercentageRounding()9173 void NumberFormatTest::Test13055_PercentageRounding() {
9174   IcuTestErrorCode status(*this, "PercentageRounding");
9175   UnicodeString actual;
9176   LocalPointer<NumberFormat>pFormat(NumberFormat::createPercentInstance("en_US", status));
9177   if (U_FAILURE(status)) {
9178       dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9179       return;
9180   }
9181   pFormat->setMaximumFractionDigits(0);
9182   pFormat->setRoundingMode(DecimalFormat::kRoundHalfEven);
9183   pFormat->format(2.155, actual);
9184   assertEquals("Should round percent toward even number", "216%", actual);
9185 }
9186 
Test11839()9187 void NumberFormatTest::Test11839() {
9188     IcuTestErrorCode errorCode(*this, "Test11839");
9189     // Ticket #11839: DecimalFormat does not respect custom plus sign
9190     LocalPointer<DecimalFormatSymbols> dfs(new DecimalFormatSymbols(Locale::getEnglish(), errorCode), errorCode);
9191     if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9192     dfs->setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"a∸");
9193     dfs->setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"b∔"); //  ∔  U+2214 DOT PLUS
9194     DecimalFormat df(u"0.00+;0.00-", dfs.orphan(), errorCode);
9195     UnicodeString result;
9196     df.format(-1.234, result, errorCode);
9197     assertEquals("Locale-specific minus sign should be used", u"1.23a∸", result);
9198     df.format(1.234, result.remove(), errorCode);
9199     assertEquals("Locale-specific plus sign should be used", u"1.23b∔", result);
9200     // Test round-trip with parse
9201     expect2(df, -456, u"456.00a∸");
9202     expect2(df, 456, u"456.00b∔");
9203 }
9204 
Test10354()9205 void NumberFormatTest::Test10354() {
9206     IcuTestErrorCode errorCode(*this, "Test10354");
9207     // Ticket #10354: invalid FieldPositionIterator when formatting with empty NaN
9208     DecimalFormatSymbols dfs(errorCode);
9209     UnicodeString empty;
9210     dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, empty);
9211     DecimalFormat df(errorCode);
9212     df.setDecimalFormatSymbols(dfs);
9213     UnicodeString result;
9214     FieldPositionIterator positions;
9215     df.format(NAN, result, &positions, errorCode);
9216     errorCode.errIfFailureAndReset("DecimalFormat.format(NAN, FieldPositionIterator) failed");
9217     FieldPosition fp;
9218     while (positions.next(fp)) {
9219         // Should not loop forever
9220     }
9221 }
9222 
Test11645_ApplyPatternEquality()9223 void NumberFormatTest::Test11645_ApplyPatternEquality() {
9224     IcuTestErrorCode status(*this, "Test11645_ApplyPatternEquality");
9225     const char16_t* pattern = u"#,##0.0#";
9226     LocalPointer<DecimalFormat> fmt((DecimalFormat*) NumberFormat::createInstance(status), status);
9227     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9228     fmt->applyPattern(pattern, status);
9229     LocalPointer<DecimalFormat> fmtCopy;
9230 
9231     static const int32_t newMultiplier = 37;
9232     fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9233     assertFalse("Value before setter", fmtCopy->getMultiplier() == newMultiplier);
9234     fmtCopy->setMultiplier(newMultiplier);
9235     assertEquals("Value after setter", fmtCopy->getMultiplier(), newMultiplier);
9236     fmtCopy->applyPattern(pattern, status);
9237     assertEquals("Value after applyPattern", fmtCopy->getMultiplier(), newMultiplier);
9238     assertFalse("multiplier", *fmt == *fmtCopy);
9239 
9240     static const NumberFormat::ERoundingMode newRoundingMode = NumberFormat::ERoundingMode::kRoundCeiling;
9241     fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9242     assertFalse("Value before setter", fmtCopy->getRoundingMode() == newRoundingMode);
9243     fmtCopy->setRoundingMode(newRoundingMode);
9244     assertEquals("Value after setter", fmtCopy->getRoundingMode(), newRoundingMode);
9245     fmtCopy->applyPattern(pattern, status);
9246     assertEquals("Value after applyPattern", fmtCopy->getRoundingMode(), newRoundingMode);
9247     assertFalse("roundingMode", *fmt == *fmtCopy);
9248 
9249     static const char16_t *const newCurrency = u"EAT";
9250     fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9251     assertFalse("Value before setter", fmtCopy->getCurrency() == newCurrency);
9252     fmtCopy->setCurrency(newCurrency);
9253     assertEquals("Value after setter", fmtCopy->getCurrency(), newCurrency);
9254     fmtCopy->applyPattern(pattern, status);
9255     assertEquals("Value after applyPattern", fmtCopy->getCurrency(), newCurrency);
9256     assertFalse("currency", *fmt == *fmtCopy);
9257 
9258     static const UCurrencyUsage newCurrencyUsage = UCurrencyUsage::UCURR_USAGE_CASH;
9259     fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9260     assertFalse("Value before setter", fmtCopy->getCurrencyUsage() == newCurrencyUsage);
9261     fmtCopy->setCurrencyUsage(newCurrencyUsage, status);
9262     assertEquals("Value after setter", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9263     fmtCopy->applyPattern(pattern, status);
9264     assertEquals("Value after applyPattern", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9265     assertFalse("currencyUsage", *fmt == *fmtCopy);
9266 }
9267 
Test12567()9268 void NumberFormatTest::Test12567() {
9269     IcuTestErrorCode errorCode(*this, "Test12567");
9270     // Ticket #12567: DecimalFormat.equals() may not be symmetric
9271     LocalPointer<DecimalFormat> df1((DecimalFormat *)
9272         NumberFormat::createInstance(Locale::getUS(), UNUM_CURRENCY, errorCode));
9273     LocalPointer<DecimalFormat> df2((DecimalFormat *)
9274         NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, errorCode));
9275     if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9276     // NOTE: CurrencyPluralInfo equality not tested in C++ because its operator== is not defined.
9277     df1->applyPattern(u"0.00", errorCode);
9278     df2->applyPattern(u"0.00", errorCode);
9279     assertTrue("df1 == df2", *df1 == *df2);
9280     assertTrue("df2 == df1", *df2 == *df1);
9281     df2->setPositivePrefix(u"abc");
9282     assertTrue("df1 != df2", *df1 != *df2);
9283     assertTrue("df2 != df1", *df2 != *df1);
9284 }
9285 
Test11626_CustomizeCurrencyPluralInfo()9286 void NumberFormatTest::Test11626_CustomizeCurrencyPluralInfo() {
9287     IcuTestErrorCode errorCode(*this, "Test11626_CustomizeCurrencyPluralInfo");
9288     // Ticket #11626: No unit test demonstrating how to use CurrencyPluralInfo to
9289     // change formatting spelled out currencies
9290     // Use locale sr because it has interesting plural rules.
9291     Locale locale("sr");
9292     LocalPointer<DecimalFormatSymbols> symbols(new DecimalFormatSymbols(locale, errorCode), errorCode);
9293     CurrencyPluralInfo info(locale, errorCode);
9294     if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9295     info.setCurrencyPluralPattern(u"one", u"0 qwerty", errorCode);
9296     info.setCurrencyPluralPattern(u"few", u"0 dvorak", errorCode);
9297     DecimalFormat df(u"#", symbols.orphan(), UNUM_CURRENCY_PLURAL, errorCode);
9298     df.setCurrencyPluralInfo(info);
9299     df.setCurrency(u"USD");
9300     df.setMaximumFractionDigits(0);
9301 
9302     UnicodeString result;
9303     assertEquals("Plural one", u"1 qwerty", df.format(1, result, errorCode));
9304     assertEquals("Plural few", u"3 dvorak", df.format(3, result.remove(), errorCode));
9305     assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9306 
9307     info.setPluralRules(u"few: n is 1; one: n in 2..4", errorCode);
9308     df.setCurrencyPluralInfo(info);
9309     assertEquals("Plural one", u"1 dvorak", df.format(1, result.remove(), errorCode));
9310     assertEquals("Plural few", u"3 qwerty", df.format(3, result.remove(), errorCode));
9311     assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9312 }
9313 
Test20073_StrictPercentParseErrorIndex()9314 void NumberFormatTest::Test20073_StrictPercentParseErrorIndex() {
9315     IcuTestErrorCode status(*this, "Test20073_StrictPercentParseErrorIndex");
9316     ParsePosition parsePosition(0);
9317     DecimalFormat df(u"0%", {"en-us", status}, status);
9318     if (U_FAILURE(status)) {
9319         dataerrln("Unable to create DecimalFormat instance.");
9320         return;
9321     }
9322     df.setLenient(FALSE);
9323     Formattable result;
9324     df.parse(u"%2%", result, parsePosition);
9325     assertEquals("", 0, parsePosition.getIndex());
9326     assertEquals("", 0, parsePosition.getErrorIndex());
9327 }
9328 
Test13056_GroupingSize()9329 void NumberFormatTest::Test13056_GroupingSize() {
9330     UErrorCode status = U_ZERO_ERROR;
9331     DecimalFormat df(u"#,##0", status);
9332     if (!assertSuccess("", status)) return;
9333     assertEquals("Primary grouping should return 3", 3, df.getGroupingSize());
9334     assertEquals("Secondary grouping should return 0", 0, df.getSecondaryGroupingSize());
9335     df.setSecondaryGroupingSize(3);
9336     assertEquals("Primary grouping should still return 3", 3, df.getGroupingSize());
9337     assertEquals("Secondary grouping should round-trip", 3, df.getSecondaryGroupingSize());
9338     df.setGroupingSize(4);
9339     assertEquals("Primary grouping should return 4", 4, df.getGroupingSize());
9340     assertEquals("Secondary should remember explicit setting and return 3", 3, df.getSecondaryGroupingSize());
9341 }
9342 
9343 
Test11025_CurrencyPadding()9344 void NumberFormatTest::Test11025_CurrencyPadding() {
9345     UErrorCode status = U_ZERO_ERROR;
9346     UnicodeString pattern(u"¤¤ **####0.00");
9347     DecimalFormatSymbols sym(Locale::getFrance(), status);
9348     if (!assertSuccess("", status)) return;
9349     DecimalFormat fmt(pattern, sym, status);
9350     if (!assertSuccess("", status)) return;
9351     UnicodeString result;
9352     fmt.format(433.0, result);
9353     assertEquals("Number should be padded to 11 characters", "EUR *433,00", result);
9354 }
9355 
Test11648_ExpDecFormatMalPattern()9356 void NumberFormatTest::Test11648_ExpDecFormatMalPattern() {
9357     UErrorCode status = U_ZERO_ERROR;
9358 
9359     DecimalFormat fmt("0.00", {"en", status}, status);
9360     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9361     fmt.setScientificNotation(TRUE);
9362     UnicodeString pattern;
9363 
9364     assertEquals("A valid scientific notation pattern should be produced",
9365             "0.00E0",
9366             fmt.toPattern(pattern));
9367 
9368     DecimalFormat fmt2(pattern, status);
9369     assertSuccess("", status);
9370 }
9371 
Test11649_DecFmtCurrencies()9372 void NumberFormatTest::Test11649_DecFmtCurrencies() {
9373     IcuTestErrorCode status(*this, "Test11649_DecFmtCurrencies");
9374     UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
9375     pattern = pattern.unescape();
9376     DecimalFormat fmt(pattern, status);
9377     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9378     static const UChar USD[] = u"USD";
9379     fmt.setCurrency(USD);
9380     UnicodeString appendTo;
9381 
9382     assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
9383     UnicodeString topattern;
9384 
9385     assertEquals("", pattern, fmt.toPattern(topattern));
9386     DecimalFormat fmt2(topattern, status);
9387     fmt2.setCurrency(USD);
9388 
9389     appendTo.remove();
9390     assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
9391 }
9392 
Test13148_ParseGroupingSeparators()9393 void NumberFormatTest::Test13148_ParseGroupingSeparators() {
9394   IcuTestErrorCode status(*this, "Test13148");
9395   LocalPointer<DecimalFormat> fmt(
9396       (DecimalFormat*)NumberFormat::createInstance("en-ZA", status), status);
9397   if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9398 
9399   DecimalFormatSymbols symbols = *fmt->getDecimalFormatSymbols();
9400 
9401   symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'.');
9402   symbols.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u',');
9403   fmt->setDecimalFormatSymbols(symbols);
9404   Formattable number;
9405   fmt->parse(u"300,000", number, status);
9406   assertEquals("Should parse as 300000", 300000LL, number.getInt64(status));
9407 }
9408 
Test12753_PatternDecimalPoint()9409 void NumberFormatTest::Test12753_PatternDecimalPoint() {
9410     UErrorCode status = U_ZERO_ERROR;
9411     DecimalFormatSymbols symbols(Locale::getUS(), status);
9412     symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"*", false);
9413     DecimalFormat df(u"0.00", symbols, status);
9414     if (!assertSuccess("", status)) return;
9415     df.setDecimalPatternMatchRequired(true);
9416     Formattable result;
9417     df.parse(u"123",result, status);
9418     assertEquals("Parsing integer succeeded even though setDecimalPatternMatchRequired was set",
9419                  U_INVALID_FORMAT_ERROR, status);
9420     }
9421 
Test11647_PatternCurrencySymbols()9422  void NumberFormatTest::Test11647_PatternCurrencySymbols() {
9423     UErrorCode status = U_ZERO_ERROR;
9424     DecimalFormat df(status);
9425     df.applyPattern(u"¤¤¤¤#", status);
9426     if (!assertSuccess("", status)) return;
9427     UnicodeString actual;
9428     df.format(123, actual);
9429     assertEquals("Should replace 4 currency signs with U+FFFD", u"\uFFFD123", actual);
9430 }
9431 
Test11913_BigDecimal()9432 void NumberFormatTest::Test11913_BigDecimal() {
9433     UErrorCode status = U_ZERO_ERROR;
9434     LocalPointer<NumberFormat> df(NumberFormat::createInstance(Locale::getEnglish(), status), status);
9435     if (!assertSuccess("", status)) return;
9436     UnicodeString result;
9437     df->format(StringPiece("1.23456789E400"), result, nullptr, status);
9438     assertSuccess("", status);
9439     assertEquals("Should format more than 309 digits", u"12,345,678", UnicodeString(result, 0, 10));
9440     assertEquals("Should format more than 309 digits", 534, result.length());
9441 }
9442 
Test11020_RoundingInScientificNotation()9443 void NumberFormatTest::Test11020_RoundingInScientificNotation() {
9444     UErrorCode status = U_ZERO_ERROR;
9445     DecimalFormatSymbols sym(Locale::getFrance(), status);
9446     DecimalFormat fmt(u"0.05E0", sym, status);
9447     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9448     assertSuccess("", status);
9449     UnicodeString result;
9450     fmt.format(12301.2, result);
9451     assertEquals("Rounding increment should be applied after magnitude scaling", u"1,25E4", result);
9452 }
9453 
Test11640_TripleCurrencySymbol()9454 void NumberFormatTest::Test11640_TripleCurrencySymbol() {
9455     IcuTestErrorCode status(*this, "Test11640_TripleCurrencySymbol");
9456     UnicodeString actual;
9457     DecimalFormat dFormat(u"¤¤¤ 0", status);
9458     if (U_FAILURE(status)) {
9459         dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9460         return;
9461     }
9462     dFormat.setCurrency(u"USD");
9463     UnicodeString result;
9464     dFormat.getPositivePrefix(result);
9465     assertEquals("Triple-currency should give long name on getPositivePrefix",
9466                 "US dollars ", result);
9467 }
9468 
9469 
Test13763_FieldPositionIteratorOffset()9470 void NumberFormatTest::Test13763_FieldPositionIteratorOffset() {
9471     IcuTestErrorCode status(*this, "Test13763_FieldPositionIteratorOffset");
9472     FieldPositionIterator fpi;
9473     UnicodeString result(u"foo\U0001F4FBbar"); // 8 code units
9474     LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9475     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9476     nf->format(5142.3, result, &fpi, status);
9477 
9478     int32_t expected[] = {
9479       UNUM_GROUPING_SEPARATOR_FIELD, 9, 10,
9480       UNUM_INTEGER_FIELD, 8, 13,
9481       UNUM_DECIMAL_SEPARATOR_FIELD, 13, 14,
9482       UNUM_FRACTION_FIELD, 14, 15,
9483     };
9484     int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
9485     expectPositions(fpi, expected, tupleCount, result);
9486 }
9487 
Test13777_ParseLongNameNonCurrencyMode()9488 void NumberFormatTest::Test13777_ParseLongNameNonCurrencyMode() {
9489     IcuTestErrorCode status(*this, "Test13777_ParseLongNameNonCurrencyMode");
9490 
9491     LocalPointer<NumberFormat> df(
9492         NumberFormat::createInstance("en-us", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9493     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9494     expect2(*df, 1.5, u"1.50 US dollars");
9495 }
9496 
Test13804_EmptyStringsWhenParsing()9497 void NumberFormatTest::Test13804_EmptyStringsWhenParsing() {
9498     IcuTestErrorCode status(*this, "Test13804_EmptyStringsWhenParsing");
9499 
9500     DecimalFormatSymbols dfs("en", status);
9501     if (status.errIfFailureAndReset()) {
9502         return;
9503     }
9504     dfs.setSymbol(DecimalFormatSymbols::kCurrencySymbol, u"", FALSE);
9505     dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"", FALSE);
9506     dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u"", FALSE);
9507     dfs.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, u"", FALSE);
9508     dfs.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, u"", FALSE);
9509     dfs.setSymbol(DecimalFormatSymbols::kThreeDigitSymbol, u"", FALSE);
9510     dfs.setSymbol(DecimalFormatSymbols::kFourDigitSymbol, u"", FALSE);
9511     dfs.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, u"", FALSE);
9512     dfs.setSymbol(DecimalFormatSymbols::kSixDigitSymbol, u"", FALSE);
9513     dfs.setSymbol(DecimalFormatSymbols::kSevenDigitSymbol, u"", FALSE);
9514     dfs.setSymbol(DecimalFormatSymbols::kEightDigitSymbol, u"", FALSE);
9515     dfs.setSymbol(DecimalFormatSymbols::kNineDigitSymbol, u"", FALSE);
9516     dfs.setSymbol(DecimalFormatSymbols::kExponentMultiplicationSymbol, u"", FALSE);
9517     dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"", FALSE);
9518     dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u"", FALSE);
9519     dfs.setSymbol(DecimalFormatSymbols::kInfinitySymbol, u"", FALSE);
9520     dfs.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, u"", FALSE);
9521     dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"", FALSE);
9522     dfs.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, u"", FALSE);
9523     dfs.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, u"", FALSE);
9524     dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, u"", FALSE);
9525     dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, FALSE, u"");
9526     dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, TRUE, u"");
9527     dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u"", FALSE);
9528     dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u"", FALSE);
9529     dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"", FALSE);
9530 
9531     DecimalFormat df("0", dfs, status);
9532     if (status.errIfFailureAndReset()) {
9533         return;
9534     }
9535     df.setGroupingUsed(TRUE);
9536     df.setScientificNotation(TRUE);
9537     df.setLenient(TRUE); // enable all matchers
9538     {
9539         UnicodeString result;
9540         df.format(0, result); // should not crash or hit infinite loop
9541     }
9542     const char16_t* samples[] = {
9543             u"",
9544             u"123",
9545             u"$123",
9546             u"-",
9547             u"+",
9548             u"44%",
9549             u"1E+2.3"
9550     };
9551     for (auto& sample : samples) {
9552         logln(UnicodeString(u"Attempting parse on: ") + sample);
9553         status.setScope(sample);
9554         // We don't care about the results, only that we don't crash and don't loop.
9555         Formattable result;
9556         ParsePosition ppos(0);
9557         df.parse(sample, result, ppos);
9558         ppos = ParsePosition(0);
9559         LocalPointer<CurrencyAmount> curramt(df.parseCurrency(sample, ppos));
9560         status.errIfFailureAndReset();
9561     }
9562 
9563     // Test with a nonempty exponent separator symbol to cover more code
9564     dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"E", FALSE);
9565     df.setDecimalFormatSymbols(dfs);
9566     {
9567         Formattable result;
9568         ParsePosition ppos(0);
9569         df.parse(u"1E+2.3", result, ppos);
9570     }
9571 }
9572 
Test20037_ScientificIntegerOverflow()9573 void NumberFormatTest::Test20037_ScientificIntegerOverflow() {
9574     IcuTestErrorCode status(*this, "Test20037_ScientificIntegerOverflow");
9575 
9576     LocalPointer<NumberFormat> nf(NumberFormat::createInstance(status));
9577     if (U_FAILURE(status)) {
9578         dataerrln("Unable to create NumberFormat instance.");
9579         return;
9580     }
9581     Formattable result;
9582 
9583     // Test overflow of exponent
9584     nf->parse(u"1E-2147483648", result, status);
9585     StringPiece sp = result.getDecimalNumber(status);
9586     assertEquals(u"Should snap to zero",
9587                  u"0",
9588                  {sp.data(), sp.length(), US_INV});
9589 
9590     // Test edge case overflow of exponent
9591     result = Formattable();
9592     nf->parse(u"1E-2147483647E-1", result, status);
9593     sp = result.getDecimalNumber(status);
9594     assertEquals(u"Should not overflow and should parse only the first exponent",
9595                  u"1E-2147483647",
9596                  {sp.data(), sp.length(), US_INV});
9597 
9598     // Test edge case overflow of exponent
9599     result = Formattable();
9600     nf->parse(u".0003e-2147483644", result, status);
9601     sp = result.getDecimalNumber(status);
9602     assertEquals(u"Should not overflow",
9603                  u"3E-2147483648",
9604                  {sp.data(), sp.length(), US_INV});
9605 
9606     // Test largest parseable exponent
9607     result = Formattable();
9608     nf->parse(u"9876e2147483643", result, status);
9609     sp = result.getDecimalNumber(status);
9610     assertEquals(u"Should not overflow",
9611                  u"9.876E+2147483646",
9612                  {sp.data(), sp.length(), US_INV});
9613 
9614     // Test max value as well
9615     const char16_t* infinityInputs[] = {
9616             u"9876e2147483644",
9617             u"9876e2147483645",
9618             u"9876e2147483646",
9619             u"9876e2147483647",
9620             u"9876e2147483648",
9621             u"9876e2147483649",
9622     };
9623     for (const auto& input : infinityInputs) {
9624         result = Formattable();
9625         nf->parse(input, result, status);
9626         sp = result.getDecimalNumber(status);
9627         assertEquals(UnicodeString("Should become Infinity: ") + input,
9628                     u"Infinity",
9629                     {sp.data(), sp.length(), US_INV});
9630     }
9631 }
9632 
Test13840_ParseLongStringCrash()9633 void NumberFormatTest::Test13840_ParseLongStringCrash() {
9634     IcuTestErrorCode status(*this, "Test13840_ParseLongStringCrash");
9635 
9636     LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9637     if (status.errIfFailureAndReset()) { return; }
9638 
9639     Formattable result;
9640     static const char16_t* bigString =
9641         u"111111111111111111111111111111111111111111111111111111111111111111111"
9642         u"111111111111111111111111111111111111111111111111111111111111111111111"
9643         u"111111111111111111111111111111111111111111111111111111111111111111111"
9644         u"111111111111111111111111111111111111111111111111111111111111111111111"
9645         u"111111111111111111111111111111111111111111111111111111111111111111111"
9646         u"111111111111111111111111111111111111111111111111111111111111111111111";
9647     nf->parse(bigString, result, status);
9648 
9649     // Normalize the input string:
9650     CharString expectedChars;
9651     expectedChars.appendInvariantChars(bigString, status);
9652     DecimalQuantity expectedDQ;
9653     expectedDQ.setToDecNumber(expectedChars.toStringPiece(), status);
9654     UnicodeString expectedUString = expectedDQ.toScientificString();
9655 
9656     // Get the output string:
9657     StringPiece actualChars = result.getDecimalNumber(status);
9658     UnicodeString actualUString = UnicodeString(actualChars.data(), actualChars.length(), US_INV);
9659 
9660     assertEquals("Should round-trip without crashing", expectedUString, actualUString);
9661 }
9662 
Test13850_EmptyStringCurrency()9663 void NumberFormatTest::Test13850_EmptyStringCurrency() {
9664     IcuTestErrorCode status(*this, "Test13840_EmptyStringCurrency");
9665 
9666     struct TestCase {
9667         const char16_t* currencyArg;
9668         UErrorCode expectedError;
9669     } cases[] = {
9670         {u"", U_USING_FALLBACK_WARNING},
9671         {u"U", U_ILLEGAL_ARGUMENT_ERROR},
9672         {u"Us", U_ILLEGAL_ARGUMENT_ERROR},
9673         {nullptr, U_USING_FALLBACK_WARNING},
9674         {u"U$D", U_INVARIANT_CONVERSION_ERROR},
9675         {u"Xxx", U_USING_FALLBACK_WARNING}
9676     };
9677     for (const auto& cas : cases) {
9678         UnicodeString message(u"with currency arg: ");
9679         if (cas.currencyArg == nullptr) {
9680             message += u"nullptr";
9681         } else {
9682             message += UnicodeString(cas.currencyArg);
9683         }
9684         status.setScope(message);
9685         LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-US", status), status);
9686         if (status.errIfFailureAndReset()) { return; }
9687         UnicodeString actual;
9688         nf->format(1, actual, status);
9689         status.errIfFailureAndReset();
9690         assertEquals(u"Should format with US currency " + message, u"$1.00", actual);
9691         nf->setCurrency(cas.currencyArg, status);
9692         if (status.expectErrorAndReset(cas.expectedError)) {
9693             // If an error occurred, do not check formatting.
9694             continue;
9695         }
9696         nf->format(1, actual.remove(), status);
9697         assertEquals(u"Should unset the currency " + message, u"\u00A41.00", actual);
9698         status.errIfFailureAndReset();
9699     }
9700 }
9701 
Test20348_CurrencyPrefixOverride()9702 void NumberFormatTest::Test20348_CurrencyPrefixOverride() {
9703     IcuTestErrorCode status(*this, "Test20348_CurrencyPrefixOverride");
9704     LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9705         NumberFormat::createCurrencyInstance("en", status)));
9706     if (status.errIfFailureAndReset()) { return; }
9707     UnicodeString result;
9708     assertEquals("Initial pattern",
9709         u"¤#,##0.00", fmt->toPattern(result.remove()));
9710     assertEquals("Initial prefix",
9711         u"¤", fmt->getPositivePrefix(result.remove()));
9712     assertEquals("Initial suffix",
9713         u"-¤", fmt->getNegativePrefix(result.remove()));
9714     assertEquals("Initial format",
9715         u"\u00A4100.00", fmt->format(100, result.remove(), NULL, status));
9716 
9717     fmt->setPositivePrefix(u"$");
9718     assertEquals("Set positive prefix pattern",
9719         u"$#,##0.00;-\u00A4#,##0.00", fmt->toPattern(result.remove()));
9720     assertEquals("Set positive prefix prefix",
9721         u"$", fmt->getPositivePrefix(result.remove()));
9722     assertEquals("Set positive prefix suffix",
9723         u"-¤", fmt->getNegativePrefix(result.remove()));
9724     assertEquals("Set positive prefix format",
9725         u"$100.00", fmt->format(100, result.remove(), NULL, status));
9726 
9727     fmt->setNegativePrefix(u"-$");
9728     assertEquals("Set negative prefix pattern",
9729         u"$#,##0.00;'-'$#,##0.00", fmt->toPattern(result.remove()));
9730     assertEquals("Set negative prefix prefix",
9731         u"$", fmt->getPositivePrefix(result.remove()));
9732     assertEquals("Set negative prefix suffix",
9733         u"-$", fmt->getNegativePrefix(result.remove()));
9734     assertEquals("Set negative prefix format",
9735         u"$100.00", fmt->format(100, result.remove(), NULL, status));
9736 }
9737 
Test20956_MonetarySymbolGetters()9738 void NumberFormatTest::Test20956_MonetarySymbolGetters() {
9739     IcuTestErrorCode status(*this, "Test20956_MonetarySymbolGetters");
9740     LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9741         NumberFormat::createCurrencyInstance("et", status)));
9742     if (status.errDataIfFailureAndReset()) {
9743         return;
9744     }
9745 
9746     decimalFormat->setCurrency(u"EEK");
9747 
9748     const DecimalFormatSymbols* decimalFormatSymbols = decimalFormat->getDecimalFormatSymbols();
9749     assertEquals("MONETARY DECIMAL SEPARATOR",
9750         u".",
9751         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
9752     assertEquals("DECIMAL SEPARATOR",
9753         u",",
9754         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol));
9755     assertEquals("MONETARY GROUPING SEPARATOR",
9756         u" ",
9757         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol));
9758     assertEquals("GROUPING SEPARATOR",
9759         u" ",
9760         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
9761     assertEquals("CURRENCY SYMBOL",
9762         u"kr",
9763         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
9764 
9765     UnicodeString sb;
9766     decimalFormat->format(12345.12, sb, status);
9767     assertEquals("OUTPUT", u"12 345.12 kr", sb);
9768 }
9769 
Test20358_GroupingInPattern()9770 void NumberFormatTest::Test20358_GroupingInPattern() {
9771     IcuTestErrorCode status(*this, "Test20358_GroupingInPattern");
9772     LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9773         NumberFormat::createInstance("en", status)));
9774     if (status.errIfFailureAndReset()) { return; }
9775     UnicodeString result;
9776     assertEquals("Initial pattern",
9777         u"#,##0.###", fmt->toPattern(result.remove()));
9778     assertTrue("Initial grouping",
9779         fmt->isGroupingUsed());
9780     assertEquals("Initial format",
9781         u"54,321", fmt->format(54321, result.remove(), NULL, status));
9782 
9783     fmt->setGroupingUsed(false);
9784     assertEquals("Set grouping false",
9785         u"0.###", fmt->toPattern(result.remove()));
9786     assertFalse("Set grouping false grouping",
9787         fmt->isGroupingUsed());
9788     assertEquals("Set grouping false format",
9789         u"54321", fmt->format(54321, result.remove(), NULL, status));
9790 
9791     fmt->setGroupingUsed(true);
9792     assertEquals("Set grouping true",
9793         u"#,##0.###", fmt->toPattern(result.remove()));
9794     assertTrue("Set grouping true grouping",
9795         fmt->isGroupingUsed());
9796     assertEquals("Set grouping true format",
9797         u"54,321", fmt->format(54321, result.remove(), NULL, status));
9798 }
9799 
Test13731_DefaultCurrency()9800 void NumberFormatTest::Test13731_DefaultCurrency() {
9801     IcuTestErrorCode status(*this, "Test13731_DefaultCurrency");
9802     UnicodeString result;
9803     {
9804         LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9805             "en", UNumberFormatStyle::UNUM_CURRENCY, status), status);
9806         if (status.errIfFailureAndReset()) { return; }
9807         assertEquals("symbol", u"¤1.10",
9808             nf->format(1.1, result.remove(), status));
9809         assertEquals("currency", u"XXX", nf->getCurrency());
9810     }
9811     {
9812         LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9813             "en", UNumberFormatStyle::UNUM_CURRENCY_ISO, status), status);
9814         if (status.errIfFailureAndReset()) { return; }
9815         assertEquals("iso_code", u"XXX 1.10",
9816             nf->format(1.1, result.remove(), status));
9817         assertEquals("currency", u"XXX", nf->getCurrency());
9818     }
9819     {
9820         LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9821             "en", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9822         if (status.errIfFailureAndReset()) { return; }
9823         assertEquals("plural", u"1.10 (unknown currency)",
9824             nf->format(1.1, result.remove(), status));
9825         assertEquals("currency", u"XXX", nf->getCurrency());
9826     }
9827 }
9828 
Test20499_CurrencyVisibleDigitsPlural()9829 void NumberFormatTest::Test20499_CurrencyVisibleDigitsPlural() {
9830     IcuTestErrorCode status(*this, "Test20499_CurrencyVisibleDigitsPlural");
9831     LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9832         "ro-RO", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9833     const char16_t* expected = u"24,00 lei românești";
9834     for (int32_t i=0; i<5; i++) {
9835         UnicodeString actual;
9836         nf->format(24, actual, status);
9837         assertEquals(UnicodeString(u"iteration ") + Int64ToUnicodeString(i),
9838             expected, actual);
9839     }
9840 }
9841 
Test13735_GroupingSizeGetter()9842 void NumberFormatTest::Test13735_GroupingSizeGetter() {
9843     IcuTestErrorCode status(*this, "Test13735_GroupingSizeGetter");
9844     {
9845         DecimalFormat df("0", {"en", status}, status);
9846         assertEquals("pat 0: ", 0, df.getGroupingSize());
9847         df.setGroupingUsed(false);
9848         assertEquals("pat 0 then disabled: ", 0, df.getGroupingSize());
9849         df.setGroupingUsed(true);
9850         assertEquals("pat 0 then enabled: ", 0, df.getGroupingSize());
9851     }
9852     {
9853         DecimalFormat df("#,##0", {"en", status}, status);
9854         assertEquals("pat #,##0: ", 3, df.getGroupingSize());
9855         df.setGroupingUsed(false);
9856         assertEquals("pat #,##0 then disabled: ", 3, df.getGroupingSize());
9857         df.setGroupingUsed(true);
9858         assertEquals("pat #,##0 then enabled: ", 3, df.getGroupingSize());
9859     }
9860 }
9861 
Test13734_StrictFlexibleWhitespace()9862 void NumberFormatTest::Test13734_StrictFlexibleWhitespace() {
9863     IcuTestErrorCode status(*this, "Test13734_StrictFlexibleWhitespace");
9864     {
9865         DecimalFormat df("+0", {"en", status}, status);
9866         df.setLenient(FALSE);
9867         Formattable result;
9868         ParsePosition ppos;
9869         df.parse("+  33", result, ppos);
9870         assertEquals("ppos : ", 0, ppos.getIndex());
9871         assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9872     }
9873     {
9874         DecimalFormat df("+ 0", {"en", status}, status);
9875         df.setLenient(FALSE);
9876         Formattable result;
9877         ParsePosition ppos;
9878         df.parse("+  33", result, ppos);
9879         assertEquals("ppos : ", 0, ppos.getIndex());
9880         assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9881     }
9882 }
9883 
Test20961_CurrencyPluralPattern()9884 void NumberFormatTest::Test20961_CurrencyPluralPattern() {
9885     IcuTestErrorCode status(*this, "Test20961_CurrencyPluralPattern");
9886     {
9887         LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9888             NumberFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9889         if (status.errDataIfFailureAndReset()) {
9890             return;
9891         }
9892         UnicodeString result;
9893         decimalFormat->toPattern(result);
9894         assertEquals("Currency pattern", u"#,##0.00 ¤¤¤", result);
9895     }
9896 }
9897 
Test21134_ToNumberFormatter()9898 void NumberFormatTest::Test21134_ToNumberFormatter() {
9899     IcuTestErrorCode status(*this, "Test21134_ToNumberFormatter");
9900     LocalizedNumberFormatter outer1;
9901     LocalizedNumberFormatter outer2;
9902     LocalPointer<LocalizedNumberFormatter> outer3;
9903     {
9904         // Case 1: new formatter object
9905         DecimalFormat inner(u"a0b", {"en", status}, status);
9906         if (auto ptr = inner.toNumberFormatter(status)) {
9907             // Copy assignment
9908             outer1 = *ptr;
9909         } else {
9910             status.errIfFailureAndReset();
9911             return;
9912         }
9913     }
9914     {
9915         // Case 2: compiled formatter object (used at least 3 times)
9916         DecimalFormat inner(u"c0d", {"en", status}, status);
9917         UnicodeString dummy;
9918         inner.format(100, dummy);
9919         inner.format(100, dummy);
9920         inner.format(100, dummy);
9921         if (auto ptr = inner.toNumberFormatter(status)) {
9922             // Copy assignment
9923             outer2 = *ptr;
9924         } else {
9925             status.errIfFailureAndReset();
9926             return;
9927         }
9928     }
9929     {
9930         // Case 3: currency plural info (different code path)
9931         LocalPointer<DecimalFormat> inner(static_cast<DecimalFormat*>(
9932             DecimalFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9933         if (auto ptr = inner->toNumberFormatter(status)) {
9934             // Copy constructor
9935             outer3.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(*ptr), status);
9936         } else {
9937             status.errIfFailureAndReset();
9938             return;
9939         }
9940     }
9941     auto result1 = outer1.formatDouble(99, status);
9942     assertEquals("Using NumberFormatter from DecimalFormat, new version",
9943         u"a99b",
9944         result1.toTempString(status));
9945     auto result2 = outer2.formatDouble(99, status);
9946     assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9947         u"c99d",
9948         result2.toTempString(status));
9949     auto result3 = outer3->formatDouble(99, status);
9950     assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9951         u"99.00 US dollars",
9952         result3.toTempString(status));
9953 }
9954 
Test13733_StrictAndLenient()9955 void NumberFormatTest::Test13733_StrictAndLenient() {
9956     IcuTestErrorCode status(*this, "Test13733_StrictAndLenient");
9957 
9958     static const struct TestCase {
9959         const char16_t* inputString;
9960         const char16_t* patternString;
9961         int64_t expectedStrictParse;
9962         int64_t expectedLenientParse;
9963     } cases[] = { {u"CA$ 12", u"¤ 0", 12, 12},
9964                   {u"CA$12", u"¤0", 12, 12},
9965                   {u"CAD 12", u"¤¤ 0", 12, 12},
9966                   {u"12 CAD", u"0 ¤¤", 12, 12},
9967                   {u"12 Canadian dollars", u"0 ¤¤¤", 12, 12},
9968                   {u"$12 ", u"¤¤¤¤0", 12, 12},
9969                   {u"12$", u"0¤¤¤¤", 12, 12},
9970                   {u"CA$ 12", u"¤0", 0, 12},
9971                   {u"CA$ 12", u"0 ¤¤", 0, 12},
9972                   {u"CA$ 12", u"0 ¤¤¤", 0, 12},
9973                   {u"CA$ 12", u"¤¤¤¤0", 0, 12},
9974                   {u"CA$ 12", u"0¤¤¤¤", 0, 12},
9975                   {u"CA$12", u"¤ 0", 0, 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"CAD 12", u"¤0", 0, 12},
9981                   {u"CAD 12", u"0 ¤¤", 0, 12},
9982                   {u"CAD 12", u"0 ¤¤¤", 0, 12},
9983                   {u"CAD 12", u"¤¤¤¤0", 0, 12},
9984                   {u"CAD 12", u"0¤¤¤¤", 0, 12},
9985                   {u"12 CAD", u"¤ 0", 0, 12},
9986                   {u"12 CAD", u"¤0", 0, 12},
9987                   {u"12 CAD", u"¤¤ 0", 0, 12},
9988                   {u"12 CAD", u"¤¤¤¤0", 0, 12},
9989                   {u"12 CAD", u"0¤¤¤¤", 0, 12},
9990                   {u"12 Canadian dollars", u"¤ 0", 0, 12},
9991                   {u"12 Canadian dollars", u"¤0", 0, 12},
9992                   {u"12 Canadian dollars", u"¤¤ 0", 0, 12},
9993                   {u"12 Canadian dollars", u"¤¤¤¤0", 0, 12},
9994                   {u"12 Canadian dollars", u"0¤¤¤¤", 0, 12},
9995                   {u"$12 ", u"¤ 0", 0, 12},
9996                   {u"$12 ", u"¤¤ 0", 0, 12},
9997                   {u"$12 ", u"0 ¤¤", 0, 12},
9998                   {u"$12 ", u"0 ¤¤¤", 0, 12},
9999                   {u"$12 ", u"0¤¤¤¤", 0, 12},
10000                   {u"12$", 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     for (auto& cas : cases) {
10007         UnicodeString inputString(cas.inputString);
10008         UnicodeString patternString(cas.patternString);
10009         int64_t parsedStrictValue = 0;
10010         int64_t parsedLenientValue = 0;
10011         ParsePosition ppos;
10012 
10013         DecimalFormatSymbols dfs(Locale::getEnglish(), status);
10014         if (status.errDataIfFailureAndReset()) {
10015             return;
10016         }
10017         DecimalFormat df(patternString, dfs, status);
10018         if (status.errDataIfFailureAndReset()) {
10019             return;
10020         }
10021         df.setLenient(FALSE);
10022         LocalPointer<CurrencyAmount> ca_strict(df.parseCurrency(inputString, ppos));
10023         if (ca_strict != nullptr) {
10024             parsedStrictValue = ca_strict->getNumber().getInt64();
10025         }
10026         assertEquals("Strict parse of " + inputString + " using " + patternString,
10027             parsedStrictValue, cas.expectedStrictParse);
10028 
10029         ppos.setIndex(0);
10030         df.setLenient(TRUE);
10031         LocalPointer<CurrencyAmount> ca_lenient(df.parseCurrency(inputString, ppos));
10032         Formattable parsedNumber_lenient = ca_lenient->getNumber();
10033         if (ca_lenient != nullptr) {
10034             parsedLenientValue = ca_lenient->getNumber().getInt64();
10035         }
10036         assertEquals("Lenient parse of " + inputString + " using " + patternString,
10037             parsedLenientValue, cas.expectedLenientParse);
10038     }
10039 }
10040 
Test21232_ParseTimeout()10041 void NumberFormatTest::Test21232_ParseTimeout() {
10042     IcuTestErrorCode status(*this, "Test21232_ParseTimeout");
10043 
10044     DecimalFormat df(status);
10045     if (status.errDataIfFailureAndReset()) {
10046         return;
10047     }
10048 
10049     UnicodeString input = u"4444444444444444444444444444444444444444";
10050     if (quick) {
10051         for (int32_t i = 0; i < 5; i++) {
10052             input.append(input);
10053         }
10054         assertEquals("Somewhat long input of digits", 1280, input.length());
10055     } else {
10056         for (int32_t i = 0; i < 12; i++) {
10057             input.append(input);
10058         }
10059         assertEquals("Very long input of digits", 163840, input.length());
10060     }
10061     Formattable result;
10062     df.parse(input, result, status);
10063     // Should not hang
10064 }
10065 
10066 #endif /* #if !UCONFIG_NO_FORMATTING */
10067