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