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