• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4  * COPYRIGHT:
5  * Copyright (c) 1997-2016, International Business Machines Corporation and
6  * others. All Rights Reserved.
7  ********************************************************************/
8 /* Modification History:
9 *   Date        Name        Description
10 *   07/15/99    helena      Ported to HPUX 10/11 CC.
11 */
12 
13 #include "unicode/utypes.h"
14 
15 #if !UCONFIG_NO_FORMATTING
16 
17 #include "numfmtst.h"
18 #include "unicode/currpinf.h"
19 #include "unicode/dcfmtsym.h"
20 #include "unicode/decimfmt.h"
21 #include "unicode/localpointer.h"
22 #include "unicode/ucurr.h"
23 #include "unicode/ustring.h"
24 #include "unicode/measfmt.h"
25 #include "unicode/curramt.h"
26 #include "unicode/strenum.h"
27 #include "textfile.h"
28 #include "tokiter.h"
29 #include "charstr.h"
30 #include "cstr.h"
31 #include "putilimp.h"
32 #include "winnmtst.h"
33 #include <cmath>
34 #include <float.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include "cmemory.h"
38 #include "cstring.h"
39 #include "unicode/numsys.h"
40 #include "fmtableimp.h"
41 #include "numberformattesttuple.h"
42 #include "unicode/msgfmt.h"
43 #include "number_decimalquantity.h"
44 #include "unicode/numberformatter.h"
45 
46 #if (U_PLATFORM == U_PF_AIX) || (U_PLATFORM == U_PF_OS390)
47 // These should not be macros. If they are,
48 // replace them with std::isnan and std::isinf
49 #if defined(isnan)
50 #undef isnan
51 namespace std {
isnan(double x)52  bool isnan(double x) {
53    return _isnan(x);
54  }
55 }
56 #endif
57 #if defined(isinf)
58 #undef isinf
59 namespace std {
isinf(double x)60  bool isinf(double x) {
61    return _isinf(x);
62  }
63 }
64 #endif
65 #endif
66 
67 using icu::number::impl::DecimalQuantity;
68 using namespace icu::number;
69 
70 //#define NUMFMTST_CACHE_DEBUG 1
71 #include "stdio.h" /* for sprintf */
72 // #include "iostream"   // for cout
73 
74 //#define NUMFMTST_DEBUG 1
75 
76 static const UChar EUR[] = {69,85,82,0}; // "EUR"
77 static const UChar ISO_CURRENCY_USD[] = {0x55, 0x53, 0x44, 0}; // "USD"
78 
79 
80 // *****************************************************************************
81 // class NumberFormatTest
82 // *****************************************************************************
83 
84 #define CHECK(status,str) UPRV_BLOCK_MACRO_BEGIN { \
85     if (U_FAILURE(status)) { \
86         errcheckln(status, UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \
87         return; \
88     } \
89 } UPRV_BLOCK_MACRO_END
90 #define CHECK_DATA(status,str) UPRV_BLOCK_MACRO_BEGIN { \
91     if (U_FAILURE(status)) { \
92         dataerrln(UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \
93         return; \
94     } \
95 } UPRV_BLOCK_MACRO_END
96 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)97 void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
98 {
99   TESTCASE_AUTO_BEGIN;
100   TESTCASE_AUTO(TestCurrencySign);
101   TESTCASE_AUTO(TestCurrency);
102   TESTCASE_AUTO(TestParse);
103   TESTCASE_AUTO(TestRounding487);
104   TESTCASE_AUTO(TestQuotes);
105   TESTCASE_AUTO(TestExponential);
106   TESTCASE_AUTO(TestPatterns);
107   TESTCASE_AUTO(Test20186_SpacesAroundSemicolon);
108 
109   // Upgrade to alphaWorks - liu 5/99
110   TESTCASE_AUTO(TestExponent);
111   TESTCASE_AUTO(TestScientific);
112   TESTCASE_AUTO(TestPad);
113   TESTCASE_AUTO(TestPatterns2);
114   TESTCASE_AUTO(TestSecondaryGrouping);
115   TESTCASE_AUTO(TestSurrogateSupport);
116   TESTCASE_AUTO(TestAPI);
117 
118   TESTCASE_AUTO(TestCurrencyObject);
119   TESTCASE_AUTO(TestCurrencyPatterns);
120   //TESTCASE_AUTO(TestDigitList);
121   TESTCASE_AUTO(TestWhiteSpaceParsing);
122   TESTCASE_AUTO(TestComplexCurrency);  // This test removed because CLDR no longer uses choice formats in currency symbols.
123   TESTCASE_AUTO(TestRegCurrency);
124   TESTCASE_AUTO(TestSymbolsWithBadLocale);
125   TESTCASE_AUTO(TestAdoptDecimalFormatSymbols);
126 
127   TESTCASE_AUTO(TestScientific2);
128   TESTCASE_AUTO(TestScientificGrouping);
129   TESTCASE_AUTO(TestInt64);
130 
131   TESTCASE_AUTO(TestPerMill);
132   TESTCASE_AUTO(TestIllegalPatterns);
133   TESTCASE_AUTO(TestCases);
134 
135   TESTCASE_AUTO(TestCurrencyNames);
136   TESTCASE_AUTO(TestCurrencyVariants);
137   TESTCASE_AUTO(TestCurrencyAmount);
138   TESTCASE_AUTO(TestCurrencyUnit);
139   TESTCASE_AUTO(TestCoverage);
140   TESTCASE_AUTO(TestLocalizedPatternSymbolCoverage);
141   TESTCASE_AUTO(TestJB3832);
142   TESTCASE_AUTO(TestHost);
143   TESTCASE_AUTO(TestHostClone);
144   TESTCASE_AUTO(TestCurrencyFormat);
145   TESTCASE_AUTO(TestRounding);
146   TESTCASE_AUTO(TestNonpositiveMultiplier);
147   TESTCASE_AUTO(TestNumberingSystems);
148   TESTCASE_AUTO(TestSpaceParsing);
149   TESTCASE_AUTO(TestMultiCurrencySign);
150   TESTCASE_AUTO(TestCurrencyFormatForMixParsing);
151   TESTCASE_AUTO(TestMismatchedCurrencyFormatFail);
152   TESTCASE_AUTO(TestDecimalFormatCurrencyParse);
153   TESTCASE_AUTO(TestCurrencyIsoPluralFormat);
154   TESTCASE_AUTO(TestCurrencyParsing);
155   TESTCASE_AUTO(TestParseCurrencyInUCurr);
156   TESTCASE_AUTO(TestFormatAttributes);
157   TESTCASE_AUTO(TestFieldPositionIterator);
158   TESTCASE_AUTO(TestDecimal);
159   TESTCASE_AUTO(TestCurrencyFractionDigits);
160   TESTCASE_AUTO(TestExponentParse);
161   TESTCASE_AUTO(TestExplicitParents);
162   TESTCASE_AUTO(TestLenientParse);
163   TESTCASE_AUTO(TestAvailableNumberingSystems);
164   TESTCASE_AUTO(TestRoundingPattern);
165   TESTCASE_AUTO(Test9087);
166   TESTCASE_AUTO(TestFormatFastpaths);
167   TESTCASE_AUTO(TestFormattableSize);
168   TESTCASE_AUTO(TestUFormattable);
169   TESTCASE_AUTO(TestSignificantDigits);
170   TESTCASE_AUTO(TestShowZero);
171   TESTCASE_AUTO(TestCompatibleCurrencies);
172   TESTCASE_AUTO(TestBug9936);
173   TESTCASE_AUTO(TestParseNegativeWithFaLocale);
174   TESTCASE_AUTO(TestParseNegativeWithAlternateMinusSign);
175   TESTCASE_AUTO(TestCustomCurrencySignAndSeparator);
176   TESTCASE_AUTO(TestParseSignsAndMarks);
177   TESTCASE_AUTO(Test10419RoundingWith0FractionDigits);
178   TESTCASE_AUTO(Test10468ApplyPattern);
179   TESTCASE_AUTO(TestRoundingScientific10542);
180   TESTCASE_AUTO(TestZeroScientific10547);
181   TESTCASE_AUTO(TestAccountingCurrency);
182   TESTCASE_AUTO(TestCurrencyFormatForMissingLocale);
183   TESTCASE_AUTO(TestEquality);
184   TESTCASE_AUTO(TestCurrencyUsage);
185   TESTCASE_AUTO(TestDoubleLimit11439);
186   TESTCASE_AUTO(TestGetAffixes);
187   TESTCASE_AUTO(TestToPatternScientific11648);
188   TESTCASE_AUTO(TestBenchmark);
189   TESTCASE_AUTO(TestCtorApplyPatternDifference);
190   TESTCASE_AUTO(TestFractionalDigitsForCurrency);
191   TESTCASE_AUTO(TestFormatCurrencyPlural);
192   TESTCASE_AUTO(Test11868);
193   TESTCASE_AUTO(Test11739_ParseLongCurrency);
194   TESTCASE_AUTO(Test13035_MultiCodePointPaddingInPattern);
195   TESTCASE_AUTO(Test13737_ParseScientificStrict);
196   TESTCASE_AUTO(Test10727_RoundingZero);
197   TESTCASE_AUTO(Test11376_getAndSetPositivePrefix);
198   TESTCASE_AUTO(Test11475_signRecognition);
199   TESTCASE_AUTO(Test11640_getAffixes);
200   TESTCASE_AUTO(Test11649_toPatternWithMultiCurrency);
201   TESTCASE_AUTO(Test13327_numberingSystemBufferOverflow);
202   TESTCASE_AUTO(Test13391_chakmaParsing);
203   TESTCASE_AUTO(Test11735_ExceptionIssue);
204   TESTCASE_AUTO(Test11035_FormatCurrencyAmount);
205   TESTCASE_AUTO(Test11318_DoubleConversion);
206   TESTCASE_AUTO(TestParsePercentRegression);
207   TESTCASE_AUTO(TestMultiplierWithScale);
208   TESTCASE_AUTO(TestFastFormatInt32);
209   TESTCASE_AUTO(Test11646_Equality);
210   TESTCASE_AUTO(TestParseNaN);
211   TESTCASE_AUTO(TestFormatFailIfMoreThanMaxDigits);
212   TESTCASE_AUTO(TestParseCaseSensitive);
213   TESTCASE_AUTO(TestParseNoExponent);
214   TESTCASE_AUTO(TestSignAlwaysShown);
215   TESTCASE_AUTO(TestMinimumGroupingDigits);
216   TESTCASE_AUTO(Test11897_LocalizedPatternSeparator);
217   TESTCASE_AUTO(Test13055_PercentageRounding);
218   TESTCASE_AUTO(Test11839);
219   TESTCASE_AUTO(Test10354);
220   TESTCASE_AUTO(Test11645_ApplyPatternEquality);
221   TESTCASE_AUTO(Test12567);
222   TESTCASE_AUTO(Test11626_CustomizeCurrencyPluralInfo);
223   TESTCASE_AUTO(Test20073_StrictPercentParseErrorIndex);
224   TESTCASE_AUTO(Test13056_GroupingSize);
225   TESTCASE_AUTO(Test11025_CurrencyPadding);
226   TESTCASE_AUTO(Test11648_ExpDecFormatMalPattern);
227   TESTCASE_AUTO(Test11649_DecFmtCurrencies);
228   TESTCASE_AUTO(Test13148_ParseGroupingSeparators);
229   TESTCASE_AUTO(Test12753_PatternDecimalPoint);
230   TESTCASE_AUTO(Test11647_PatternCurrencySymbols);
231   TESTCASE_AUTO(Test11913_BigDecimal);
232   TESTCASE_AUTO(Test11020_RoundingInScientificNotation);
233   TESTCASE_AUTO(Test11640_TripleCurrencySymbol);
234   TESTCASE_AUTO(Test13763_FieldPositionIteratorOffset);
235   TESTCASE_AUTO(Test13777_ParseLongNameNonCurrencyMode);
236   TESTCASE_AUTO(Test13804_EmptyStringsWhenParsing);
237   TESTCASE_AUTO(Test20037_ScientificIntegerOverflow);
238   TESTCASE_AUTO(Test13840_ParseLongStringCrash);
239   TESTCASE_AUTO(Test13850_EmptyStringCurrency);
240   TESTCASE_AUTO(Test20348_CurrencyPrefixOverride);
241   TESTCASE_AUTO(Test20956_MonetarySymbolGetters);
242   TESTCASE_AUTO(Test20358_GroupingInPattern);
243   TESTCASE_AUTO(Test13731_DefaultCurrency);
244   TESTCASE_AUTO(Test20499_CurrencyVisibleDigitsPlural);
245   TESTCASE_AUTO(Test13735_GroupingSizeGetter);
246   TESTCASE_AUTO(Test13734_StrictFlexibleWhitespace);
247   TESTCASE_AUTO(Test20961_CurrencyPluralPattern);
248   TESTCASE_AUTO(Test21134_ToNumberFormatter);
249   TESTCASE_AUTO(Test13733_StrictAndLenient);
250   TESTCASE_AUTO(Test20425_IntegerIncrement);
251   TESTCASE_AUTO(Test20425_FractionWithIntegerIncrement);
252   TESTCASE_AUTO(Test21232_ParseTimeout);
253   TESTCASE_AUTO(Test10997_FormatCurrency);
254   TESTCASE_AUTO(Test21556_CurrencyAsDecimal);
255   TESTCASE_AUTO_END;
256 }
257 
258 // -------------------------------------
259 
260 // Test API (increase code coverage)
261 void
TestAPI(void)262 NumberFormatTest::TestAPI(void)
263 {
264   logln("Test API");
265   UErrorCode status = U_ZERO_ERROR;
266   NumberFormat *test = NumberFormat::createInstance("root", status);
267   if(U_FAILURE(status)) {
268     dataerrln("unable to create format object - %s", u_errorName(status));
269   }
270   if(test != NULL) {
271     test->setMinimumIntegerDigits(10);
272     test->setMaximumIntegerDigits(1);
273 
274     test->setMinimumFractionDigits(10);
275     test->setMaximumFractionDigits(1);
276 
277     UnicodeString result;
278     FieldPosition pos;
279     Formattable bla("Paja Patak"); // Donald Duck for non Serbian speakers
280     test->format(bla, result, pos, status);
281     if(U_SUCCESS(status)) {
282       errln("Yuck... Formatted a duck... As a number!");
283     } else {
284       status = U_ZERO_ERROR;
285     }
286 
287     result.remove();
288     int64_t ll = 12;
289     test->format(ll, result);
290     assertEquals("format int64_t error", u"2.0", result);
291 
292     test->setMinimumIntegerDigits(4);
293     test->setMinimumFractionDigits(4);
294 
295     result.remove();
296     test->format(ll, result);
297     assertEquals("format int64_t error", u"0,012.0000", result);
298 
299     ParsePosition ppos;
300     LocalPointer<CurrencyAmount> currAmt(test->parseCurrency("",ppos));
301     // old test for (U_FAILURE(status)) was bogus here, method does not set status!
302     if (ppos.getIndex()) {
303         errln("Parsed empty string as currency");
304     }
305 
306     delete test;
307   }
308 }
309 
310 class StubNumberFormat :public NumberFormat{
311 public:
StubNumberFormat()312     StubNumberFormat(){}
format(double,UnicodeString & appendTo,FieldPosition &) const313     virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const override {
314         return appendTo;
315     }
format(int32_t,UnicodeString & appendTo,FieldPosition &) const316     virtual UnicodeString& format(int32_t ,UnicodeString& appendTo,FieldPosition& ) const override {
317         return appendTo.append((UChar)0x0033);
318     }
format(int64_t number,UnicodeString & appendTo,FieldPosition & pos) const319     virtual UnicodeString& format(int64_t number,UnicodeString& appendTo,FieldPosition& pos) const override {
320         return NumberFormat::format(number, appendTo, pos);
321     }
format(const Formattable &,UnicodeString & appendTo,FieldPosition &,UErrorCode &) const322     virtual UnicodeString& format(const Formattable& , UnicodeString& appendTo, FieldPosition& , UErrorCode& ) const override {
323         return appendTo;
324     }
parse(const UnicodeString &,Formattable &,ParsePosition &) const325     virtual void parse(const UnicodeString& ,
326                     Formattable& ,
327                     ParsePosition& ) const override {}
parse(const UnicodeString &,Formattable &,UErrorCode &) const328     virtual void parse( const UnicodeString& ,
329                         Formattable& ,
330                         UErrorCode& ) const override {}
getDynamicClassID(void) const331     virtual UClassID getDynamicClassID(void) const override {
332         static char classID = 0;
333         return (UClassID)&classID;
334     }
clone() const335     virtual StubNumberFormat* clone() const override {return NULL;}
336 };
337 
338 void
TestCoverage(void)339 NumberFormatTest::TestCoverage(void){
340     StubNumberFormat stub;
341     UnicodeString agent("agent");
342     FieldPosition pos;
343     int64_t num = 4;
344     if (stub.format(num, agent, pos) != UnicodeString("agent3")){
345         errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)");
346     }
347 }
348 
TestLocalizedPatternSymbolCoverage()349 void NumberFormatTest::TestLocalizedPatternSymbolCoverage() {
350     IcuTestErrorCode errorCode(*this, "TestLocalizedPatternSymbolCoverage");
351     // Ticket #12961: DecimalFormat::toLocalizedPattern() is not working as designed.
352     DecimalFormatSymbols dfs(errorCode);
353     dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u'⁖');
354     dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'⁘');
355     dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u'⁙');
356     dfs.setSymbol(DecimalFormatSymbols::kDigitSymbol, u'▰');
357     dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u'໐');
358     dfs.setSymbol(DecimalFormatSymbols::kSignificantDigitSymbol, u'⁕');
359     dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u'†');
360     dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u'‡');
361     dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u'⁜');
362     dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u'‱');
363     dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"⁑⁑"); // tests multi-char sequence
364     dfs.setSymbol(DecimalFormatSymbols::kPadEscapeSymbol, u'⁂');
365 
366     {
367         UnicodeString standardPattern(u"#,##0.05+%;#,##0.05-%");
368         UnicodeString localizedPattern(u"▰⁖▰▰໐⁘໐໕†⁜⁙▰⁖▰▰໐⁘໐໕‡⁜");
369 
370         DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
371         df1.applyPattern(standardPattern, errorCode);
372         DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
373         df2.applyLocalizedPattern(localizedPattern, errorCode);
374         assertTrue("DecimalFormat instances should be equal", df1 == df2);
375         UnicodeString p2;
376         assertEquals("toPattern should match on localizedPattern instance",
377                 standardPattern, df2.toPattern(p2));
378         UnicodeString lp1;
379         assertEquals("toLocalizedPattern should match on standardPattern instance",
380                 localizedPattern, df1.toLocalizedPattern(lp1));
381     }
382 
383     {
384         UnicodeString standardPattern(u"* @@@E0‰");
385         UnicodeString localizedPattern(u"⁂ ⁕⁕⁕⁑⁑໐‱");
386 
387         DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
388         df1.applyPattern(standardPattern, errorCode);
389         DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
390         df2.applyLocalizedPattern(localizedPattern, errorCode);
391         assertTrue("DecimalFormat instances should be equal", df1 == df2);
392         UnicodeString p2;
393         assertEquals("toPattern should match on localizedPattern instance",
394                 standardPattern, df2.toPattern(p2));
395         UnicodeString lp1;
396         assertEquals("toLocalizedPattern should match on standardPattern instance",
397                 localizedPattern, df1.toLocalizedPattern(lp1));
398     }
399 }
400 
401 // Test various patterns
402 void
TestPatterns(void)403 NumberFormatTest::TestPatterns(void)
404 {
405     UErrorCode status = U_ZERO_ERROR;
406     DecimalFormatSymbols sym(Locale::getUS(), status);
407     if (U_FAILURE(status)) { errcheckln(status, "FAIL: Could not construct DecimalFormatSymbols - %s", u_errorName(status)); return; }
408 
409     const char* pat[]    = { "#.#", "#.", ".#", "#" };
410     int32_t pat_length = UPRV_LENGTHOF(pat);
411     const char* newpat[] = { "0.#", "0.", "#.0", "0" };
412     const char* num[]    = { "0",   "0.", ".0", "0" };
413     for (int32_t i=0; i<pat_length; ++i)
414     {
415         status = U_ZERO_ERROR;
416         DecimalFormat fmt(pat[i], sym, status);
417         if (U_FAILURE(status)) { errln((UnicodeString)"FAIL: DecimalFormat constructor failed for " + pat[i]); continue; }
418         UnicodeString newp; fmt.toPattern(newp);
419         if (!(newp == newpat[i]))
420             errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
421                   "; " + newp + " seen instead");
422 
423         UnicodeString s; (*(NumberFormat*)&fmt).format((int32_t)0, s);
424         if (!(s == num[i]))
425         {
426             errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
427                   "; " + s + " seen instead");
428             logln((UnicodeString)"Min integer digits = " + fmt.getMinimumIntegerDigits());
429         }
430     }
431 }
432 
Test20186_SpacesAroundSemicolon()433 void NumberFormatTest::Test20186_SpacesAroundSemicolon() {
434     IcuTestErrorCode status(*this, "Test20186_SpacesAroundSemicolon");
435     DecimalFormat df(u"0.00 ; -0.00", {"en-us", status}, status);
436     expect2(df, 1, u"1.00 ");
437     expect2(df, -1, u" -1.00");
438 
439     df = DecimalFormat(u"0.00;", {"en-us", status}, status);
440     expect2(df, 1, u"1.00");
441     expect2(df, -1, u"-1.00");
442 
443     df = DecimalFormat(u"0.00;0.00", {"en-us", status}, status);
444     expect2(df, 1, u"1.00");
445     expect(df, -1, u"1.00");  // parses as 1, not -1
446 
447     df = DecimalFormat(u" 0.00 ; -0.00 ", {"en-us", status}, status);
448     expect2(df, 1, u" 1.00 ");
449     expect2(df, -1, u" -1.00 ");
450 }
451 
452 /*
453 icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
454 icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
455 icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
456 */
457 /*
458 void
459 NumberFormatTest::TestDigitList(void)
460 {
461   // API coverage for DigitList
462   DigitList list1;
463   list1.append('1');
464   list1.fDecimalAt = 1;
465   DigitList list2;
466   list2.set((int32_t)1);
467   if (list1 != list2) {
468     errln("digitlist append, operator!= or set failed ");
469   }
470   if (!(list1 == list2)) {
471     errln("digitlist append, operator== or set failed ");
472   }
473 }
474 */
475 
476 // -------------------------------------
477 
478 // Test exponential pattern
479 void
TestExponential(void)480 NumberFormatTest::TestExponential(void)
481 {
482     UErrorCode status = U_ZERO_ERROR;
483     DecimalFormatSymbols sym(Locale::getUS(), status);
484     if (U_FAILURE(status)) { errcheckln(status, "FAIL: Bad status returned by DecimalFormatSymbols ct - %s", u_errorName(status)); return; }
485     const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]"  };
486     int32_t pat_length = UPRV_LENGTHOF(pat);
487 
488 // The following #if statements allow this test to be built and run on
489 // platforms that do not have standard IEEE numerics.  For example,
490 // S/390 doubles have an exponent range of -78 to +75.  For the
491 // following #if statements to work, float.h must define
492 // DBL_MAX_10_EXP to be a compile-time constant.
493 
494 // This section may be expanded as needed.
495 
496 #if DBL_MAX_10_EXP > 300
497     double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
498     int32_t val_length = UPRV_LENGTHOF(val);
499     const char* valFormat[] =
500     {
501         // 0.####E0
502         "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
503         // 00.000E00
504         "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
505         // ##0.######E000
506         "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
507         // 0.###E0;[0.###E0]
508         "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
509     };
510     double valParse[] =
511     {
512         0.01234, 123460000, 1.23E300, -3.1416E-271,
513         0.01234, 123460000, 1.23E300, -3.1416E-271,
514         0.01234, 123456800, 1.23E300, -3.141593E-271,
515         0.01234, 123500000, 1.23E300, -3.142E-271,
516     };
517 #elif DBL_MAX_10_EXP > 70
518     double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
519     int32_t val_length = UPRV_LENGTHOF(val);
520     char* valFormat[] =
521     {
522         // 0.####E0
523         "1.234E-2", "1.2346E8", "1.23E70", "-3.1416E-71",
524         // 00.000E00
525         "12.340E-03", "12.346E07", "12.300E69", "-31.416E-72",
526         // ##0.######E000
527         "12.34E-003", "123.4568E006", "12.3E069", "-31.41593E-072",
528         // 0.###E0;[0.###E0]
529         "1.234E-2", "1.235E8", "1.23E70", "[3.142E-71]"
530     };
531     double valParse[] =
532     {
533         0.01234, 123460000, 1.23E70, -3.1416E-71,
534         0.01234, 123460000, 1.23E70, -3.1416E-71,
535         0.01234, 123456800, 1.23E70, -3.141593E-71,
536         0.01234, 123500000, 1.23E70, -3.142E-71,
537     };
538 #else
539     // Don't test double conversion
540     double* val = 0;
541     int32_t val_length = 0;
542     char** valFormat = 0;
543     double* valParse = 0;
544     logln("Warning: Skipping double conversion tests");
545 #endif
546 
547     int32_t lval[] = { 0, -1, 1, 123456789 };
548     int32_t lval_length = UPRV_LENGTHOF(lval);
549     const char* lvalFormat[] =
550     {
551         // 0.####E0
552         "0E0", "-1E0", "1E0", "1.2346E8",
553         // 00.000E00
554         "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
555         // ##0.######E000
556         "0E000", "-1E000", "1E000", "123.4568E006",
557         // 0.###E0;[0.###E0]
558         "0E0", "[1E0]", "1E0", "1.235E8"
559     };
560     int32_t lvalParse[] =
561     {
562         0, -1, 1, 123460000,
563         0, -1, 1, 123460000,
564         0, -1, 1, 123456800,
565         0, -1, 1, 123500000,
566     };
567     int32_t ival = 0, ilval = 0;
568     for (int32_t p=0; p<pat_length; ++p)
569     {
570         DecimalFormat fmt(pat[p], sym, status);
571         if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormat ct"); continue; }
572         UnicodeString pattern;
573         logln((UnicodeString)"Pattern \"" + pat[p] + "\" -toPattern-> \"" +
574           fmt.toPattern(pattern) + "\"");
575         int32_t v;
576         for (v=0; v<val_length; ++v)
577         {
578             UnicodeString s; (*(NumberFormat*)&fmt).format(val[v], s);
579             logln((UnicodeString)" " + val[v] + " -format-> " + s);
580             if (s != valFormat[v+ival])
581                 errln((UnicodeString)"FAIL: Expected " + valFormat[v+ival]);
582 
583             ParsePosition pos(0);
584             Formattable af;
585             fmt.parse(s, af, pos);
586             double a;
587             UBool useEpsilon = FALSE;
588             if (af.getType() == Formattable::kLong)
589                 a = af.getLong();
590             else if (af.getType() == Formattable::kDouble) {
591                 a = af.getDouble();
592 #if U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400
593                 // S/390 will show a failure like this:
594                 //| -3.141592652999999e-271 -format-> -3.1416E-271
595                 //|                          -parse-> -3.1416e-271
596                 //| FAIL: Expected -3.141599999999999e-271
597                 // To compensate, we use an epsilon-based equality
598                 // test on S/390 only.  We don't want to do this in
599                 // general because it's less exacting.
600                 useEpsilon = TRUE;
601 #endif
602             }
603             else {
604                 errln(UnicodeString("FAIL: Non-numeric Formattable returned: ") + pattern + " " + s);
605                 continue;
606             }
607             if (pos.getIndex() == s.length())
608             {
609                 logln((UnicodeString)"  -parse-> " + a);
610                 // Use epsilon comparison as necessary
611                 if ((useEpsilon &&
612                     (uprv_fabs(a - valParse[v+ival]) / a > (2*DBL_EPSILON))) ||
613                     (!useEpsilon && a != valParse[v+ival]))
614                 {
615                     errln((UnicodeString)"FAIL: Expected " + valParse[v+ival] + " but got " + a
616                         + " on input " + s);
617                 }
618             }
619             else {
620                 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
621                 errln((UnicodeString)"  should be (" + s.length() + " chars) -> " + valParse[v+ival]);
622             }
623         }
624         for (v=0; v<lval_length; ++v)
625         {
626             UnicodeString s;
627             (*(NumberFormat*)&fmt).format(lval[v], s);
628             logln((UnicodeString)" " + lval[v] + "L -format-> " + s);
629             if (s != lvalFormat[v+ilval])
630                 errln((UnicodeString)"ERROR: Expected " + lvalFormat[v+ilval] + " Got: " + s);
631 
632             ParsePosition pos(0);
633             Formattable af;
634             fmt.parse(s, af, pos);
635             if (af.getType() == Formattable::kLong ||
636                 af.getType() == Formattable::kInt64) {
637                 UErrorCode status = U_ZERO_ERROR;
638                 int32_t a = af.getLong(status);
639                 if (pos.getIndex() == s.length())
640                 {
641                     logln((UnicodeString)"  -parse-> " + a);
642                     if (a != lvalParse[v+ilval])
643                         errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval] + " but got " + a);
644                 }
645                 else
646                     errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
647             }
648             else
649                 errln((UnicodeString)"FAIL: Non-long Formattable returned for " + s
650                     + " Double: " + af.getDouble()
651                     + ", Long: " + af.getLong());
652         }
653         ival += val_length;
654         ilval += lval_length;
655     }
656 }
657 
658 void
TestScientific2()659 NumberFormatTest::TestScientific2() {
660     // jb 2552
661     UErrorCode status = U_ZERO_ERROR;
662     DecimalFormat* fmt = (DecimalFormat*)NumberFormat::createCurrencyInstance("en_US", status);
663     if (U_SUCCESS(status)) {
664         double num = 12.34;
665         expect(*fmt, num, "$12.34");
666         fmt->setScientificNotation(TRUE);
667         expect(*fmt, num, "$1.23E1");
668         fmt->setScientificNotation(FALSE);
669         expect(*fmt, num, "$12.34");
670     }
671     delete fmt;
672 }
673 
674 void
TestScientificGrouping()675 NumberFormatTest::TestScientificGrouping() {
676     // jb 2552
677     UErrorCode status = U_ZERO_ERROR;
678     DecimalFormat fmt("##0.00E0",status);
679     if (assertSuccess("", status, true, __FILE__, __LINE__)) {
680         expect(fmt, .01234, "12.3E-3");
681         expect(fmt, .1234, "123E-3");
682         expect(fmt, 1.234, "1.23E0");
683         expect(fmt, 12.34, "12.3E0");
684         expect(fmt, 123.4, "123E0");
685         expect(fmt, 1234., "1.23E3");
686     }
687 }
688 
689 /*static void setFromString(DigitList& dl, const char* str) {
690     char c;
691     UBool decimalSet = FALSE;
692     dl.clear();
693     while ((c = *str++)) {
694         if (c == '-') {
695             dl.fIsPositive = FALSE;
696         } else if (c == '+') {
697             dl.fIsPositive = TRUE;
698         } else if (c == '.') {
699             dl.fDecimalAt = dl.fCount;
700             decimalSet = TRUE;
701         } else {
702             dl.append(c);
703         }
704     }
705     if (!decimalSet) {
706         dl.fDecimalAt = dl.fCount;
707     }
708 }*/
709 
710 void
TestInt64()711 NumberFormatTest::TestInt64() {
712     UErrorCode status = U_ZERO_ERROR;
713     DecimalFormat fmt("#.#E0",status);
714     if (U_FAILURE(status)) {
715         dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
716         return;
717     }
718     fmt.setMaximumFractionDigits(20);
719     if (U_SUCCESS(status)) {
720         expect(fmt, (Formattable)(int64_t)0, "0E0");
721         expect(fmt, (Formattable)(int64_t)-1, "-1E0");
722         expect(fmt, (Formattable)(int64_t)1, "1E0");
723         expect(fmt, (Formattable)(int64_t)2147483647, "2.147483647E9");
724         expect(fmt, (Formattable)((int64_t)-2147483647-1), "-2.147483648E9");
725         expect(fmt, (Formattable)(int64_t)U_INT64_MAX, "9.223372036854775807E18");
726         expect(fmt, (Formattable)(int64_t)U_INT64_MIN, "-9.223372036854775808E18");
727     }
728 
729     // also test digitlist
730 /*    int64_t int64max = U_INT64_MAX;
731     int64_t int64min = U_INT64_MIN;
732     const char* int64maxstr = "9223372036854775807";
733     const char* int64minstr = "-9223372036854775808";
734     UnicodeString fail("fail: ");
735 
736     // test max int64 value
737     DigitList dl;
738     setFromString(dl, int64maxstr);
739     {
740         if (!dl.fitsIntoInt64(FALSE)) {
741             errln(fail + int64maxstr + " didn't fit");
742         }
743         int64_t int64Value = dl.getInt64();
744         if (int64Value != int64max) {
745             errln(fail + int64maxstr);
746         }
747         dl.set(int64Value);
748         int64Value = dl.getInt64();
749         if (int64Value != int64max) {
750             errln(fail + int64maxstr);
751         }
752     }
753     // test negative of max int64 value (1 shy of min int64 value)
754     dl.fIsPositive = FALSE;
755     {
756         if (!dl.fitsIntoInt64(FALSE)) {
757             errln(fail + "-" + int64maxstr + " didn't fit");
758         }
759         int64_t int64Value = dl.getInt64();
760         if (int64Value != -int64max) {
761             errln(fail + "-" + int64maxstr);
762         }
763         dl.set(int64Value);
764         int64Value = dl.getInt64();
765         if (int64Value != -int64max) {
766             errln(fail + "-" + int64maxstr);
767         }
768     }
769     // test min int64 value
770     setFromString(dl, int64minstr);
771     {
772         if (!dl.fitsIntoInt64(FALSE)) {
773             errln(fail + "-" + int64minstr + " didn't fit");
774         }
775         int64_t int64Value = dl.getInt64();
776         if (int64Value != int64min) {
777             errln(fail + int64minstr);
778         }
779         dl.set(int64Value);
780         int64Value = dl.getInt64();
781         if (int64Value != int64min) {
782             errln(fail + int64minstr);
783         }
784     }
785     // test negative of min int 64 value (1 more than max int64 value)
786     dl.fIsPositive = TRUE; // won't fit
787     {
788         if (dl.fitsIntoInt64(FALSE)) {
789             errln(fail + "-(" + int64minstr + ") didn't fit");
790         }
791     }*/
792 }
793 
794 // -------------------------------------
795 
796 // Test the handling of quotes
797 void
TestQuotes(void)798 NumberFormatTest::TestQuotes(void)
799 {
800     UErrorCode status = U_ZERO_ERROR;
801     UnicodeString *pat;
802     DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), status);
803     if (U_FAILURE(status)) {
804         errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
805         delete sym;
806         return;
807     }
808     pat = new UnicodeString("a'fo''o'b#");
809     DecimalFormat *fmt = new DecimalFormat(*pat, *sym, status);
810     UnicodeString s;
811     ((NumberFormat*)fmt)->format((int32_t)123, s);
812     logln((UnicodeString)"Pattern \"" + *pat + "\"");
813     logln((UnicodeString)" Format 123 -> " + escape(s));
814     if (!(s=="afo'ob123"))
815         errln((UnicodeString)"FAIL: Expected afo'ob123");
816 
817     s.truncate(0);
818     delete fmt;
819     delete pat;
820 
821     pat = new UnicodeString("a''b#");
822     fmt = new DecimalFormat(*pat, *sym, status);
823     ((NumberFormat*)fmt)->format((int32_t)123, s);
824     logln((UnicodeString)"Pattern \"" + *pat + "\"");
825     logln((UnicodeString)" Format 123 -> " + escape(s));
826     if (!(s=="a'b123"))
827         errln((UnicodeString)"FAIL: Expected a'b123");
828     delete fmt;
829     delete pat;
830     delete sym;
831 }
832 
833 /**
834  * Test the handling of the currency symbol in patterns.
835  */
836 void
TestCurrencySign(void)837 NumberFormatTest::TestCurrencySign(void)
838 {
839     UErrorCode status = U_ZERO_ERROR;
840     DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale::getUS(), status);
841     UnicodeString pat;
842     UChar currency = 0x00A4;
843     if (U_FAILURE(status)) {
844         errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
845         delete sym;
846         return;
847     }
848     // "\xA4#,##0.00;-\xA4#,##0.00"
849     pat.append(currency).append("#,##0.00;-").
850         append(currency).append("#,##0.00");
851     DecimalFormat *fmt = new DecimalFormat(pat, *sym, status);
852     UnicodeString s; ((NumberFormat*)fmt)->format(1234.56, s);
853     pat.truncate(0);
854     logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
855     logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
856     if (s != "$1,234.56") dataerrln((UnicodeString)"FAIL: Expected $1,234.56");
857     s.truncate(0);
858     ((NumberFormat*)fmt)->format(- 1234.56, s);
859     logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
860     if (s != "-$1,234.56") dataerrln((UnicodeString)"FAIL: Expected -$1,234.56");
861     delete fmt;
862     pat.truncate(0);
863     // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
864     pat.append(currency).append(currency).
865         append(" #,##0.00;").
866         append(currency).append(currency).
867         append(" -#,##0.00");
868     fmt = new DecimalFormat(pat, *sym, status);
869     s.truncate(0);
870     ((NumberFormat*)fmt)->format(1234.56, s);
871     logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
872     logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
873     if (s != "USD 1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD 1,234.56");
874     s.truncate(0);
875     ((NumberFormat*)fmt)->format(-1234.56, s);
876     logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
877     if (s != "USD -1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD -1,234.56");
878     delete fmt;
879     delete sym;
880     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + u_errorName(status));
881 }
882 
883 // -------------------------------------
884 
toHexString(int32_t i)885 static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
886 
887 UnicodeString&
escape(UnicodeString & s)888 NumberFormatTest::escape(UnicodeString& s)
889 {
890     UnicodeString buf;
891     for (int32_t i=0; i<s.length(); ++i)
892     {
893         UChar c = s[(int32_t)i];
894         if (c <= (UChar)0x7F) buf += c;
895         else {
896             buf += (UChar)0x5c; buf += (UChar)0x55;
897             buf += toHexString((c & 0xF000) >> 12);
898             buf += toHexString((c & 0x0F00) >> 8);
899             buf += toHexString((c & 0x00F0) >> 4);
900             buf += toHexString(c & 0x000F);
901         }
902     }
903     return (s = buf);
904 }
905 
906 
907 // -------------------------------------
908 static const char* testCases[][2]= {
909      /* locale ID */  /* expected */
910     {"ca_ES@currency=ESP", "\\u20A7\\u00A01.150" },
911     {"de_LU@currency=LUF", "1,150\\u00A0F" },
912     {"el_GR@currency=GRD", "1.150,50\\u00A0\\u0394\\u03C1\\u03C7" },
913     {"en_BE@currency=BEF", "1.150,50\\u00A0BEF" },
914     {"es_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
915     {"eu_ES@currency=ESP", "\\u20A7\\u00A01.150" },
916     {"gl_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
917     {"it_IT@currency=ITL", "ITL\\u00A01.150" },
918     {"pt_PT@currency=PTE", "1,150$50\\u00A0\\u200B"}, // per cldrbug 7670
919     {"en_US@currency=JPY", "\\u00A51,150"},
920     {"en_US@currency=jpy", "\\u00A51,150"},
921     {"en-US-u-cu-jpy", "\\u00A51,150"}
922 };
923 /**
924  * Test localized currency patterns.
925  */
926 void
TestCurrency(void)927 NumberFormatTest::TestCurrency(void)
928 {
929     UErrorCode status = U_ZERO_ERROR;
930     NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
931     if (U_FAILURE(status)) {
932         dataerrln("Error calling NumberFormat::createCurrencyInstance()");
933         return;
934     }
935 
936     UnicodeString s; currencyFmt->format(1.50, s);
937     logln((UnicodeString)"Un pauvre ici a..........." + s);
938     if (!(s==CharsToUnicodeString("1,50\\u00A0$")))
939         errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$ but got " + s);
940     delete currencyFmt;
941     s.truncate(0);
942     char loc[256]={0};
943     int len = uloc_canonicalize("de_DE@currency=DEM", loc, 256, &status);
944     (void)len;  // Suppress unused variable warning.
945     currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
946     currencyFmt->format(1.50, s);
947     logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
948     if (!(s==CharsToUnicodeString("1,50\\u00A0DM")))
949         errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM but got " + s);
950     delete currencyFmt;
951     s.truncate(0);
952     len = uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status);
953     currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
954     currencyFmt->format(1.50, s);
955     logln((UnicodeString)"Un pauvre en France a....." + s);
956     if (!(s==CharsToUnicodeString("1,50\\u00A0F")))
957         errln((UnicodeString)"FAIL: Expected 1,50<nbsp>F");
958     delete currencyFmt;
959     if (U_FAILURE(status))
960         errln((UnicodeString)"FAIL: Status " + (int32_t)status);
961 
962     for(int i=0; i < UPRV_LENGTHOF(testCases); i++){
963         status = U_ZERO_ERROR;
964         const char *localeID = testCases[i][0];
965         UnicodeString expected(testCases[i][1], -1, US_INV);
966         expected = expected.unescape();
967         s.truncate(0);
968         char loc[256]={0};
969         uloc_canonicalize(localeID, loc, 256, &status);
970         currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
971         if(U_FAILURE(status)){
972             errln("Could not create currency formatter for locale %s",localeID);
973             continue;
974         }
975         currencyFmt->format(1150.50, s);
976         if(s!=expected){
977             errln(UnicodeString("FAIL: Expected: ")+expected
978                     + UnicodeString(" Got: ") + s
979                     + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
980         }
981         if (U_FAILURE(status)){
982             errln((UnicodeString)"FAIL: Status " + (int32_t)status);
983         }
984         delete currencyFmt;
985     }
986 }
987 
988 // -------------------------------------
989 
990 /**
991  * Test the Currency object handling, new as of ICU 2.2.
992  */
TestCurrencyObject()993 void NumberFormatTest::TestCurrencyObject() {
994     UErrorCode ec = U_ZERO_ERROR;
995     NumberFormat* fmt =
996         NumberFormat::createCurrencyInstance(Locale::getUS(), ec);
997 
998     if (U_FAILURE(ec)) {
999         dataerrln("FAIL: getCurrencyInstance(US) - %s", u_errorName(ec));
1000         delete fmt;
1001         return;
1002     }
1003 
1004     Locale null("", "", "");
1005 
1006     expectCurrency(*fmt, null, 1234.56, "$1,234.56");
1007 
1008     expectCurrency(*fmt, Locale::getFrance(),
1009                    1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro
1010 
1011     expectCurrency(*fmt, Locale::getJapan(),
1012                    1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
1013 
1014     expectCurrency(*fmt, Locale("fr", "CH", ""),
1015                    1234.56, "CHF 1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
1016 
1017     expectCurrency(*fmt, Locale::getUS(),
1018                    1234.56, "$1,234.56");
1019 
1020     delete fmt;
1021     fmt = NumberFormat::createCurrencyInstance(Locale::getFrance(), ec);
1022 
1023     if (U_FAILURE(ec)) {
1024         errln("FAIL: getCurrencyInstance(FRANCE)");
1025         delete fmt;
1026         return;
1027     }
1028 
1029     expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC"));
1030 
1031     expectCurrency(*fmt, Locale::getJapan(),
1032                    1234.56, CharsToUnicodeString("1\\u202F235 JPY")); // Yen
1033 
1034     expectCurrency(*fmt, Locale("fr", "CH", ""),
1035                    1234.56, CharsToUnicodeString("1\\u202F234,56 CHF")); // no more 0.05 rounding here, see cldrbug 5548
1036 
1037     expectCurrency(*fmt, Locale::getUS(),
1038                    1234.56, CharsToUnicodeString("1\\u202F234,56 $US"));
1039 
1040     expectCurrency(*fmt, Locale::getFrance(),
1041                    1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC")); // Euro
1042 
1043     delete fmt;
1044 }
1045 
1046 // -------------------------------------
1047 
1048 /**
1049  * Do rudimentary testing of parsing.
1050  */
1051 void
TestParse(void)1052 NumberFormatTest::TestParse(void)
1053 {
1054     UErrorCode status = U_ZERO_ERROR;
1055     UnicodeString arg("0");
1056     DecimalFormat* format = new DecimalFormat("00", status);
1057     //try {
1058         Formattable n; format->parse(arg, n, status);
1059         logln((UnicodeString)"parse(" + arg + ") = " + n.getLong());
1060         if (n.getType() != Formattable::kLong ||
1061             n.getLong() != 0) errln((UnicodeString)"FAIL: Expected 0");
1062     delete format;
1063     if (U_FAILURE(status)) errcheckln(status, (UnicodeString)"FAIL: Status " + u_errorName(status));
1064     //}
1065     //catch(Exception e) {
1066     //    errln((UnicodeString)"Exception caught: " + e);
1067     //}
1068 }
1069 
1070 // -------------------------------------
1071 
1072 static const char *lenientAffixTestCases[] = {
1073         "(1)",
1074         "( 1)",
1075         "(1 )",
1076         "( 1 )"
1077 };
1078 
1079 static const char *lenientMinusTestCases[] = {
1080     "-5",
1081     "\\u22125",
1082     "\\u27965"
1083 };
1084 
1085 static const char *lenientCurrencyTestCases[] = {
1086         "$1,000",
1087         "$ 1,000",
1088         "$1000",
1089         "$ 1000",
1090         "$1 000.00",
1091         "$ 1 000.00",
1092         "$ 1\\u00A0000.00",
1093         "1000.00"
1094 };
1095 
1096 // changed from () to - per cldrbug 5674
1097 static const char *lenientNegativeCurrencyTestCases[] = {
1098         "-$1,000",
1099         "-$ 1,000",
1100         "-$1000",
1101         "-$ 1000",
1102         "-$1 000.00",
1103         "-$ 1 000.00",
1104         "- $ 1,000.00 ",
1105         "-$ 1\\u00A0000.00",
1106         "-1000.00"
1107 };
1108 
1109 static const char *lenientPercentTestCases[] = {
1110         "25%",
1111         " 25%",
1112         " 25 %",
1113     	"25 %",
1114 		"25\\u00A0%",
1115 		"25"
1116 };
1117 
1118 static const char *lenientNegativePercentTestCases[] = {
1119 		"-25%",
1120 		" -25%",
1121 		" - 25%",
1122 		"- 25 %",
1123 		" - 25 %",
1124 		"-25 %",
1125 		"-25\\u00A0%",
1126 		"-25",
1127 		"- 25"
1128 };
1129 
1130 static const char *strictFailureTestCases[] = {
1131 		" 1000",
1132 		"10,00",
1133 		"1,000,.0"
1134 };
1135 
1136 /**
1137  * Test lenient parsing.
1138  */
1139 void
TestLenientParse(void)1140 NumberFormatTest::TestLenientParse(void)
1141 {
1142     UErrorCode status = U_ZERO_ERROR;
1143     DecimalFormat *format = new DecimalFormat("(#,##0)", status);
1144     Formattable n;
1145 
1146     if (format == NULL || U_FAILURE(status)) {
1147         dataerrln("Unable to create DecimalFormat (#,##0) - %s", u_errorName(status));
1148     } else {
1149         format->setLenient(TRUE);
1150         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientAffixTestCases); t += 1) {
1151         	UnicodeString testCase = ctou(lenientAffixTestCases[t]);
1152 
1153             format->parse(testCase, n, status);
1154             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1155 
1156             if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
1157             	n.getLong() != 1) {
1158             	dataerrln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t]
1159                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1160             	status = U_ZERO_ERROR;
1161             }
1162        }
1163        delete format;
1164     }
1165 
1166     Locale en_US("en_US");
1167     Locale sv_SE("sv_SE");
1168 
1169     NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, UNUM_DECIMAL, status);
1170 
1171     if (mFormat == NULL || U_FAILURE(status)) {
1172         dataerrln("Unable to create NumberFormat (sv_SE, UNUM_DECIMAL) - %s", u_errorName(status));
1173     } else {
1174         mFormat->setLenient(TRUE);
1175         for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1176             UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1177 
1178             mFormat->parse(testCase, n, status);
1179             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1180 
1181             if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1182                 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1183                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1184                 status = U_ZERO_ERROR;
1185             }
1186         }
1187         delete mFormat;
1188     }
1189 
1190     mFormat = NumberFormat::createInstance(en_US, UNUM_DECIMAL, status);
1191 
1192     if (mFormat == NULL || U_FAILURE(status)) {
1193         dataerrln("Unable to create NumberFormat (en_US, UNUM_DECIMAL) - %s", u_errorName(status));
1194     } else {
1195         mFormat->setLenient(TRUE);
1196         for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1197             UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1198 
1199             mFormat->parse(testCase, n, status);
1200             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1201 
1202             if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1203                 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1204                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1205                 status = U_ZERO_ERROR;
1206             }
1207         }
1208         delete mFormat;
1209     }
1210 
1211     NumberFormat *cFormat = NumberFormat::createInstance(en_US, UNUM_CURRENCY, status);
1212 
1213     if (cFormat == NULL || U_FAILURE(status)) {
1214         dataerrln("Unable to create NumberFormat (en_US, UNUM_CURRENCY) - %s", u_errorName(status));
1215     } else {
1216         cFormat->setLenient(TRUE);
1217         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientCurrencyTestCases); t += 1) {
1218         	UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
1219 
1220             cFormat->parse(testCase, n, status);
1221             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1222 
1223             if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1224             	n.getLong() != 1000) {
1225             	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t]
1226                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1227             	status = U_ZERO_ERROR;
1228             }
1229         }
1230 
1231         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativeCurrencyTestCases); t += 1) {
1232         	UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
1233 
1234             cFormat->parse(testCase, n, status);
1235             logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1236 
1237             if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1238             	n.getLong() != -1000) {
1239             	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t]
1240                       + (UnicodeString) "\"; error code = " + u_errorName(status));
1241             	status = U_ZERO_ERROR;
1242             }
1243         }
1244 
1245         delete cFormat;
1246     }
1247 
1248     NumberFormat *pFormat = NumberFormat::createPercentInstance(en_US, status);
1249 
1250     if (pFormat == NULL || U_FAILURE(status)) {
1251         dataerrln("Unable to create NumberFormat::createPercentInstance (en_US) - %s", u_errorName(status));
1252     } else {
1253         pFormat->setLenient(TRUE);
1254         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientPercentTestCases); t += 1) {
1255         	UnicodeString testCase = ctou(lenientPercentTestCases[t]);
1256 
1257         	pFormat->parse(testCase, n, status);
1258             logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1259 
1260             if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1261             	n.getDouble() != 0.25) {
1262             	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t]
1263                       + (UnicodeString) "\"; error code = " + u_errorName(status)
1264                       + "; got: " + n.getDouble(status));
1265             	status = U_ZERO_ERROR;
1266             }
1267         }
1268 
1269         for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativePercentTestCases); t += 1) {
1270         	UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
1271 
1272         	pFormat->parse(testCase, n, status);
1273             logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1274 
1275             if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1276             	n.getDouble() != -0.25) {
1277             	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t]
1278                       + (UnicodeString) "\"; error code = " + u_errorName(status)
1279                       + "; got: " + n.getDouble(status));
1280             	status = U_ZERO_ERROR;
1281             }
1282         }
1283 
1284         delete pFormat;
1285     }
1286 
1287    // Test cases that should fail with a strict parse and pass with a
1288    // lenient parse.
1289    NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);
1290 
1291    if (nFormat == NULL || U_FAILURE(status)) {
1292        dataerrln("Unable to create NumberFormat (en_US) - %s", u_errorName(status));
1293    } else {
1294        // first, make sure that they fail with a strict parse
1295        for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1296 	       UnicodeString testCase = ctou(strictFailureTestCases[t]);
1297 
1298 	       nFormat->parse(testCase, n, status);
1299 	       logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1300 
1301 	       if (! U_FAILURE(status)) {
1302 		       errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t]
1303                      + (UnicodeString) "\"; error code = " + u_errorName(status));
1304 	       }
1305 
1306 	       status = U_ZERO_ERROR;
1307        }
1308 
1309        // then, make sure that they pass with a lenient parse
1310        nFormat->setLenient(TRUE);
1311        for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1312 	       UnicodeString testCase = ctou(strictFailureTestCases[t]);
1313 
1314 	       nFormat->parse(testCase, n, status);
1315 	       logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1316 
1317 	       if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1318 	            	n.getLong() != 1000) {
1319 		       errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t]
1320                      + (UnicodeString) "\"; error code = " + u_errorName(status));
1321 		       status = U_ZERO_ERROR;
1322 	       }
1323        }
1324 
1325        delete nFormat;
1326    }
1327 }
1328 
1329 // -------------------------------------
1330 
1331 /**
1332  * Test proper rounding by the format method.
1333  */
1334 void
TestRounding487(void)1335 NumberFormatTest::TestRounding487(void)
1336 {
1337     UErrorCode status = U_ZERO_ERROR;
1338     NumberFormat *nf = NumberFormat::createInstance(status);
1339     if (U_FAILURE(status)) {
1340         dataerrln("Error calling NumberFormat::createInstance()");
1341         return;
1342     }
1343 
1344     roundingTest(*nf, 0.00159999, 4, "0.0016");
1345     roundingTest(*nf, 0.00995, 4, "0.01");
1346 
1347     roundingTest(*nf, 12.3995, 3, "12.4");
1348 
1349     roundingTest(*nf, 12.4999, 0, "12");
1350     roundingTest(*nf, - 19.5, 0, "-20");
1351     delete nf;
1352     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
1353 }
1354 
1355 /**
1356  * Test the functioning of the secondary grouping value.
1357  */
TestSecondaryGrouping(void)1358 void NumberFormatTest::TestSecondaryGrouping(void) {
1359     UErrorCode status = U_ZERO_ERROR;
1360     DecimalFormatSymbols US(Locale::getUS(), status);
1361     CHECK(status, "DecimalFormatSymbols ct");
1362 
1363     DecimalFormat f("#,##,###", US, status);
1364     CHECK(status, "DecimalFormat ct");
1365 
1366     expect2(f, (int32_t)123456789L, "12,34,56,789");
1367     expectPat(f, "#,##,##0");
1368     f.applyPattern("#,###", status);
1369     CHECK(status, "applyPattern");
1370 
1371     f.setSecondaryGroupingSize(4);
1372     expect2(f, (int32_t)123456789L, "12,3456,789");
1373     expectPat(f, "#,####,##0");
1374     NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
1375     CHECK_DATA(status, "createInstance(hi_IN)");
1376 
1377     UnicodeString out;
1378     int32_t l = (int32_t)1876543210L;
1379     g->format(l, out);
1380     delete g;
1381     // expect "1,87,65,43,210", but with Hindi digits
1382     //         01234567890123
1383     UBool ok = TRUE;
1384     if (out.length() != 14) {
1385         ok = FALSE;
1386     } else {
1387         for (int32_t i=0; i<out.length(); ++i) {
1388             UBool expectGroup = FALSE;
1389             switch (i) {
1390             case 1:
1391             case 4:
1392             case 7:
1393             case 10:
1394                 expectGroup = TRUE;
1395                 break;
1396             }
1397             // Later -- fix this to get the actual grouping
1398             // character from the resource bundle.
1399             UBool isGroup = (out.charAt(i) == 0x002C);
1400             if (isGroup != expectGroup) {
1401                 ok = FALSE;
1402                 break;
1403             }
1404         }
1405     }
1406     if (!ok) {
1407         errln((UnicodeString)"FAIL  Expected " + l +
1408               " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
1409               escape(out) + "\"");
1410     } else {
1411         logln((UnicodeString)"Ok    " + l +
1412               " x hi_IN -> \"" +
1413               escape(out) + "\"");
1414     }
1415 }
1416 
TestWhiteSpaceParsing(void)1417 void NumberFormatTest::TestWhiteSpaceParsing(void) {
1418     UErrorCode ec = U_ZERO_ERROR;
1419     DecimalFormatSymbols US(Locale::getUS(), ec);
1420     DecimalFormat fmt("a  b#0c  ", US, ec);
1421     if (U_FAILURE(ec)) {
1422         errcheckln(ec, "FAIL: Constructor - %s", u_errorName(ec));
1423         return;
1424     }
1425     // From ICU 62, flexible whitespace needs lenient mode
1426     fmt.setLenient(TRUE);
1427     int32_t n = 1234;
1428     expect(fmt, "a b1234c ", n);
1429     expect(fmt, "a   b1234c   ", n);
1430 }
1431 
1432 /**
1433  * Test currencies whose display name is a ChoiceFormat.
1434  */
TestComplexCurrency()1435 void NumberFormatTest::TestComplexCurrency() {
1436 
1437 //    UErrorCode ec = U_ZERO_ERROR;
1438 //    Locale loc("kn", "IN", "");
1439 //    NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
1440 //    if (U_SUCCESS(ec)) {
1441 //        expect2(*fmt, 1.0, CharsToUnicodeString("Re.\\u00A01.00"));
1442 //        Use .00392625 because that's 2^-8.  Any value less than 0.005 is fine.
1443 //        expect(*fmt, 1.00390625, CharsToUnicodeString("Re.\\u00A01.00")); // tricky
1444 //        expect2(*fmt, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
1445 //        expect2(*fmt, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
1446 //        expect2(*fmt, -1.0, CharsToUnicodeString("-Re.\\u00A01.00"));
1447 //        expect2(*fmt, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
1448 //    } else {
1449 //        errln("FAIL: getCurrencyInstance(kn_IN)");
1450 //    }
1451 //    delete fmt;
1452 
1453 }
1454 
1455 // -------------------------------------
1456 
1457 void
roundingTest(NumberFormat & nf,double x,int32_t maxFractionDigits,const char * expected)1458 NumberFormatTest::roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)
1459 {
1460     nf.setMaximumFractionDigits(maxFractionDigits);
1461     UnicodeString out; nf.format(x, out);
1462     logln((UnicodeString)"" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
1463     if (!(out==expected)) errln((UnicodeString)"FAIL: Expected " + expected);
1464 }
1465 
1466 /**
1467  * Upgrade to alphaWorks
1468  */
TestExponent(void)1469 void NumberFormatTest::TestExponent(void) {
1470     UErrorCode status = U_ZERO_ERROR;
1471     DecimalFormatSymbols US(Locale::getUS(), status);
1472     CHECK(status, "DecimalFormatSymbols constructor");
1473     DecimalFormat fmt1(UnicodeString("0.###E0"), US, status);
1474     CHECK(status, "DecimalFormat(0.###E0)");
1475     DecimalFormat fmt2(UnicodeString("0.###E+0"), US, status);
1476     CHECK(status, "DecimalFormat(0.###E+0)");
1477     int32_t n = 1234;
1478     expect2(fmt1, n, "1.234E3");
1479     expect2(fmt2, n, "1.234E+3");
1480     expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
1481 }
1482 
1483 /**
1484  * Upgrade to alphaWorks
1485  */
TestScientific(void)1486 void NumberFormatTest::TestScientific(void) {
1487     UErrorCode status = U_ZERO_ERROR;
1488     DecimalFormatSymbols US(Locale::getUS(), status);
1489     CHECK(status, "DecimalFormatSymbols constructor");
1490 
1491     // Test pattern round-trip
1492     const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
1493                           "0.###E0;[0.###E0]" };
1494     int32_t PAT_length = UPRV_LENGTHOF(PAT);
1495     int32_t DIGITS[] = {
1496         // min int, max int, min frac, max frac
1497         1, 1, 0, 0, // "#E0"
1498         1, 1, 0, 4, // "0.####E0"
1499         2, 2, 3, 3, // "00.000E00"
1500         1, 3, 0, 4, // "##0.####E000"
1501         1, 1, 0, 3, // "0.###E0;[0.###E0]"
1502     };
1503     for (int32_t i=0; i<PAT_length; ++i) {
1504         UnicodeString pat(PAT[i]);
1505         DecimalFormat df(pat, US, status);
1506         CHECK(status, "DecimalFormat constructor");
1507         UnicodeString pat2;
1508         df.toPattern(pat2);
1509         if (pat == pat2) {
1510             logln(UnicodeString("Ok   Pattern rt \"") +
1511                   pat + "\" -> \"" +
1512                   pat2 + "\"");
1513         } else {
1514             errln(UnicodeString("FAIL Pattern rt \"") +
1515                   pat + "\" -> \"" +
1516                   pat2 + "\"");
1517         }
1518         // Make sure digit counts match what we expect
1519         if (df.getMinimumIntegerDigits() != DIGITS[4*i] ||
1520             df.getMaximumIntegerDigits() != DIGITS[4*i+1] ||
1521             df.getMinimumFractionDigits() != DIGITS[4*i+2] ||
1522             df.getMaximumFractionDigits() != DIGITS[4*i+3]) {
1523             errln(UnicodeString("FAIL \"" + pat +
1524                                 "\" min/max int; min/max frac = ") +
1525                   df.getMinimumIntegerDigits() + "/" +
1526                   df.getMaximumIntegerDigits() + ";" +
1527                   df.getMinimumFractionDigits() + "/" +
1528                   df.getMaximumFractionDigits() + ", expect " +
1529                   DIGITS[4*i] + "/" +
1530                   DIGITS[4*i+1] + ";" +
1531                   DIGITS[4*i+2] + "/" +
1532                   DIGITS[4*i+3]);
1533         }
1534     }
1535 
1536 
1537     // Test the constructor for default locale. We have to
1538     // manually set the default locale, as there is no
1539     // guarantee that the default locale has the same
1540     // scientific format.
1541     Locale def = Locale::getDefault();
1542     Locale::setDefault(Locale::getUS(), status);
1543     expect2(NumberFormat::createScientificInstance(status),
1544            12345.678901,
1545            "1.2345678901E4", status);
1546     Locale::setDefault(def, status);
1547 
1548     expect2(new DecimalFormat("#E0", US, status),
1549            12345.0,
1550            "1.2345E4", status);
1551     expect(new DecimalFormat("0E0", US, status),
1552            12345.0,
1553            "1E4", status);
1554     expect2(NumberFormat::createScientificInstance(Locale::getUS(), status),
1555            12345.678901,
1556            "1.2345678901E4", status);
1557     expect(new DecimalFormat("##0.###E0", US, status),
1558            12345.0,
1559            "12.34E3", status);
1560     expect(new DecimalFormat("##0.###E0", US, status),
1561            12345.00001,
1562            "12.35E3", status);
1563     expect2(new DecimalFormat("##0.####E0", US, status),
1564            (int32_t) 12345,
1565            "12.345E3", status);
1566     expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status),
1567            12345.678901,
1568            "1,2345678901E4", status);
1569     expect(new DecimalFormat("##0.####E0", US, status),
1570            789.12345e-9,
1571            "789.12E-9", status);
1572     expect2(new DecimalFormat("##0.####E0", US, status),
1573            780.e-9,
1574            "780E-9", status);
1575     expect(new DecimalFormat(".###E0", US, status),
1576            45678.0,
1577            ".457E5", status);
1578     expect2(new DecimalFormat(".###E0", US, status),
1579            (int32_t) 0,
1580            ".0E0", status);
1581     /*
1582     expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
1583                                  new DecimalFormat("##E0", US),
1584                                  new DecimalFormat("####E0", US),
1585                                  new DecimalFormat("0E0", US),
1586                                  new DecimalFormat("00E0", US),
1587                                  new DecimalFormat("000E0", US),
1588                                },
1589            new Long(45678000),
1590            new String[] { "4.5678E7",
1591                           "45.678E6",
1592                           "4567.8E4",
1593                           "5E7",
1594                           "46E6",
1595                           "457E5",
1596                         }
1597            );
1598     !
1599     ! Unroll this test into individual tests below...
1600     !
1601     */
1602     expect2(new DecimalFormat("#E0", US, status),
1603            (int32_t) 45678000, "4.5678E7", status);
1604     expect2(new DecimalFormat("##E0", US, status),
1605            (int32_t) 45678000, "45.678E6", status);
1606     expect2(new DecimalFormat("####E0", US, status),
1607            (int32_t) 45678000, "4567.8E4", status);
1608     expect(new DecimalFormat("0E0", US, status),
1609            (int32_t) 45678000, "5E7", status);
1610     expect(new DecimalFormat("00E0", US, status),
1611            (int32_t) 45678000, "46E6", status);
1612     expect(new DecimalFormat("000E0", US, status),
1613            (int32_t) 45678000, "457E5", status);
1614     /*
1615     expect(new DecimalFormat("###E0", US, status),
1616            new Object[] { new Double(0.0000123), "12.3E-6",
1617                           new Double(0.000123), "123E-6",
1618                           new Double(0.00123), "1.23E-3",
1619                           new Double(0.0123), "12.3E-3",
1620                           new Double(0.123), "123E-3",
1621                           new Double(1.23), "1.23E0",
1622                           new Double(12.3), "12.3E0",
1623                           new Double(123), "123E0",
1624                           new Double(1230), "1.23E3",
1625                          });
1626     !
1627     ! Unroll this test into individual tests below...
1628     !
1629     */
1630     expect2(new DecimalFormat("###E0", US, status),
1631            0.0000123, "12.3E-6", status);
1632     expect2(new DecimalFormat("###E0", US, status),
1633            0.000123, "123E-6", status);
1634     expect2(new DecimalFormat("###E0", US, status),
1635            0.00123, "1.23E-3", status);
1636     expect2(new DecimalFormat("###E0", US, status),
1637            0.0123, "12.3E-3", status);
1638     expect2(new DecimalFormat("###E0", US, status),
1639            0.123, "123E-3", status);
1640     expect2(new DecimalFormat("###E0", US, status),
1641            1.23, "1.23E0", status);
1642     expect2(new DecimalFormat("###E0", US, status),
1643            12.3, "12.3E0", status);
1644     expect2(new DecimalFormat("###E0", US, status),
1645            123.0, "123E0", status);
1646     expect2(new DecimalFormat("###E0", US, status),
1647            1230.0, "1.23E3", status);
1648     /*
1649     expect(new DecimalFormat("0.#E+00", US, status),
1650            new Object[] { new Double(0.00012), "1.2E-04",
1651                           new Long(12000),     "1.2E+04",
1652                          });
1653     !
1654     ! Unroll this test into individual tests below...
1655     !
1656     */
1657     expect2(new DecimalFormat("0.#E+00", US, status),
1658            0.00012, "1.2E-04", status);
1659     expect2(new DecimalFormat("0.#E+00", US, status),
1660            (int32_t) 12000, "1.2E+04", status);
1661 }
1662 
1663 /**
1664  * Upgrade to alphaWorks
1665  */
TestPad(void)1666 void NumberFormatTest::TestPad(void) {
1667     UErrorCode status = U_ZERO_ERROR;
1668     DecimalFormatSymbols US(Locale::getUS(), status);
1669     CHECK(status, "DecimalFormatSymbols constructor");
1670 
1671     expect2(new DecimalFormat("*^##.##", US, status),
1672            int32_t(0), "^^^^0", status);
1673     expect2(new DecimalFormat("*^##.##", US, status),
1674            -1.3, "^-1.3", status);
1675     expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1676            int32_t(0), "0.0E0______ g-m/s^2", status);
1677     expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1678            1.0/3, "333.333E-3_ g-m/s^2", status);
1679     expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1680            int32_t(0), "0.0______ g-m/s^2", status);
1681     expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1682            1.0/3, "0.33333__ g-m/s^2", status);
1683 
1684     // Test padding before a sign
1685     const char *formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1686     expect2(new DecimalFormat(formatStr, US, status),
1687            int32_t(-10),  "xxxxxxxxxx(10.0)", status);
1688     expect2(new DecimalFormat(formatStr, US, status),
1689            int32_t(-1000),"xxxxxxx(1,000.0)", status);
1690     expect2(new DecimalFormat(formatStr, US, status),
1691            int32_t(-1000000),"xxx(1,000,000.0)", status);
1692     expect2(new DecimalFormat(formatStr, US, status),
1693            -100.37,       "xxxxxxxx(100.37)", status);
1694     expect2(new DecimalFormat(formatStr, US, status),
1695            -10456.37,     "xxxxx(10,456.37)", status);
1696     expect2(new DecimalFormat(formatStr, US, status),
1697            -1120456.37,   "xx(1,120,456.37)", status);
1698     expect2(new DecimalFormat(formatStr, US, status),
1699            -112045600.37, "(112,045,600.37)", status);
1700     expect2(new DecimalFormat(formatStr, US, status),
1701            -1252045600.37,"(1,252,045,600.37)", status);
1702 
1703     expect2(new DecimalFormat(formatStr, US, status),
1704            int32_t(10),  "xxxxxxxxxxxx10.0", status);
1705     expect2(new DecimalFormat(formatStr, US, status),
1706            int32_t(1000),"xxxxxxxxx1,000.0", status);
1707     expect2(new DecimalFormat(formatStr, US, status),
1708            int32_t(1000000),"xxxxx1,000,000.0", status);
1709     expect2(new DecimalFormat(formatStr, US, status),
1710            100.37,       "xxxxxxxxxx100.37", status);
1711     expect2(new DecimalFormat(formatStr, US, status),
1712            10456.37,     "xxxxxxx10,456.37", status);
1713     expect2(new DecimalFormat(formatStr, US, status),
1714            1120456.37,   "xxxx1,120,456.37", status);
1715     expect2(new DecimalFormat(formatStr, US, status),
1716            112045600.37, "xx112,045,600.37", status);
1717     expect2(new DecimalFormat(formatStr, US, status),
1718            10252045600.37,"10,252,045,600.37", status);
1719 
1720 
1721     // Test padding between a sign and a number
1722     const char *formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1723     expect2(new DecimalFormat(formatStr2, US, status),
1724            int32_t(-10),  "(10.0xxxxxxxxxx)", status);
1725     expect2(new DecimalFormat(formatStr2, US, status),
1726            int32_t(-1000),"(1,000.0xxxxxxx)", status);
1727     expect2(new DecimalFormat(formatStr2, US, status),
1728            int32_t(-1000000),"(1,000,000.0xxx)", status);
1729     expect2(new DecimalFormat(formatStr2, US, status),
1730            -100.37,       "(100.37xxxxxxxx)", status);
1731     expect2(new DecimalFormat(formatStr2, US, status),
1732            -10456.37,     "(10,456.37xxxxx)", status);
1733     expect2(new DecimalFormat(formatStr2, US, status),
1734            -1120456.37,   "(1,120,456.37xx)", status);
1735     expect2(new DecimalFormat(formatStr2, US, status),
1736            -112045600.37, "(112,045,600.37)", status);
1737     expect2(new DecimalFormat(formatStr2, US, status),
1738            -1252045600.37,"(1,252,045,600.37)", status);
1739 
1740     expect2(new DecimalFormat(formatStr2, US, status),
1741            int32_t(10),  "10.0xxxxxxxxxxxx", status);
1742     expect2(new DecimalFormat(formatStr2, US, status),
1743            int32_t(1000),"1,000.0xxxxxxxxx", status);
1744     expect2(new DecimalFormat(formatStr2, US, status),
1745            int32_t(1000000),"1,000,000.0xxxxx", status);
1746     expect2(new DecimalFormat(formatStr2, US, status),
1747            100.37,       "100.37xxxxxxxxxx", status);
1748     expect2(new DecimalFormat(formatStr2, US, status),
1749            10456.37,     "10,456.37xxxxxxx", status);
1750     expect2(new DecimalFormat(formatStr2, US, status),
1751            1120456.37,   "1,120,456.37xxxx", status);
1752     expect2(new DecimalFormat(formatStr2, US, status),
1753            112045600.37, "112,045,600.37xx", status);
1754     expect2(new DecimalFormat(formatStr2, US, status),
1755            10252045600.37,"10,252,045,600.37", status);
1756 
1757     //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1758     DecimalFormat fmt("#", US, status);
1759     CHECK(status, "DecimalFormat constructor");
1760     UnicodeString padString("P");
1761     fmt.setPadCharacter(padString);
1762     expectPad(fmt, "*P##.##", DecimalFormat::kPadBeforePrefix, 5, padString);
1763     fmt.setPadCharacter((UnicodeString)"^");
1764     expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, (UnicodeString)"^");
1765     //commented until implementation is complete
1766   /*  fmt.setPadCharacter((UnicodeString)"^^^");
1767     expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1768     padString.remove();
1769     padString.append((UChar)0x0061);
1770     padString.append((UChar)0x0302);
1771     fmt.setPadCharacter(padString);
1772     UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1773     UnicodeString pattern(patternChars);
1774     expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1775  */
1776 
1777 }
1778 
1779 /**
1780  * Upgrade to alphaWorks
1781  */
TestPatterns2(void)1782 void NumberFormatTest::TestPatterns2(void) {
1783     UErrorCode status = U_ZERO_ERROR;
1784     DecimalFormatSymbols US(Locale::getUS(), status);
1785     CHECK(status, "DecimalFormatSymbols constructor");
1786 
1787     DecimalFormat fmt("#", US, status);
1788     CHECK(status, "DecimalFormat constructor");
1789 
1790     UChar hat = 0x005E; /*^*/
1791 
1792     expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, hat);
1793     expectPad(fmt, "$*^#", DecimalFormat::kPadAfterPrefix, 2, hat);
1794     expectPad(fmt, "#*^", DecimalFormat::kPadBeforeSuffix, 1, hat);
1795     expectPad(fmt, "#$*^", DecimalFormat::kPadAfterSuffix, 2, hat);
1796     expectPad(fmt, "$*^$#", ILLEGAL);
1797     expectPad(fmt, "#$*^$", ILLEGAL);
1798     expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix,
1799               12, (UChar)0x0078 /*x*/);
1800     expectPad(fmt, "''#0*x", DecimalFormat::kPadBeforeSuffix,
1801               3, (UChar)0x0078 /*x*/);
1802     expectPad(fmt, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix,
1803               10, (UChar)0x0061 /*a*/);
1804 
1805     fmt.applyPattern("AA#,##0.00ZZ", status);
1806     CHECK(status, "applyPattern");
1807     fmt.setPadCharacter(hat);
1808 
1809     fmt.setFormatWidth(10);
1810 
1811     fmt.setPadPosition(DecimalFormat::kPadBeforePrefix);
1812     expectPat(fmt, "*^AA#,##0.00ZZ");
1813 
1814     fmt.setPadPosition(DecimalFormat::kPadBeforeSuffix);
1815     expectPat(fmt, "AA#,##0.00*^ZZ");
1816 
1817     fmt.setPadPosition(DecimalFormat::kPadAfterSuffix);
1818     expectPat(fmt, "AA#,##0.00ZZ*^");
1819 
1820     //            12  3456789012
1821     UnicodeString exp("AA*^#,##0.00ZZ", "");
1822     fmt.setFormatWidth(12);
1823     fmt.setPadPosition(DecimalFormat::kPadAfterPrefix);
1824     expectPat(fmt, exp);
1825 
1826     fmt.setFormatWidth(13);
1827     //              12  34567890123
1828     expectPat(fmt, "AA*^##,##0.00ZZ");
1829 
1830     fmt.setFormatWidth(14);
1831     //              12  345678901234
1832     expectPat(fmt, "AA*^###,##0.00ZZ");
1833 
1834     fmt.setFormatWidth(15);
1835     //              12  3456789012345
1836     expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1837 
1838     fmt.setFormatWidth(16);
1839     //              12  34567890123456
1840     expectPat(fmt, "AA*^#####,##0.00ZZ");
1841 }
1842 
TestSurrogateSupport(void)1843 void NumberFormatTest::TestSurrogateSupport(void) {
1844     UErrorCode status = U_ZERO_ERROR;
1845     DecimalFormatSymbols custom(Locale::getUS(), status);
1846     CHECK(status, "DecimalFormatSymbols constructor");
1847 
1848     custom.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, "decimal");
1849     custom.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, "plus");
1850     custom.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, " minus ");
1851     custom.setSymbol(DecimalFormatSymbols::kExponentialSymbol, "exponent");
1852 
1853     UnicodeString patternStr("*\\U00010000##.##", "");
1854     patternStr = patternStr.unescape();
1855     UnicodeString expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1856     expStr = expStr.unescape();
1857     expect2(new DecimalFormat(patternStr, custom, status),
1858            int32_t(0), expStr, status);
1859 
1860     status = U_ZERO_ERROR;
1861     expect2(new DecimalFormat("*^##.##", custom, status),
1862            int32_t(0), "^^^^0", status);
1863     status = U_ZERO_ERROR;
1864     expect2(new DecimalFormat("##.##", custom, status),
1865            -1.3, " minus 1decimal3", status);
1866     status = U_ZERO_ERROR;
1867     expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1868            int32_t(0), "0decimal0exponent0 g-m/s^2", status);
1869     status = U_ZERO_ERROR;
1870     expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1871            1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
1872     status = U_ZERO_ERROR;
1873     expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1874            int32_t(0), "0decimal0 g-m/s^2", status);
1875     status = U_ZERO_ERROR;
1876     expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1877            1.0/3, "0decimal33333 g-m/s^2", status);
1878 
1879     UnicodeString zero((UChar32)0x10000);
1880     UnicodeString one((UChar32)0x10001);
1881     UnicodeString two((UChar32)0x10002);
1882     UnicodeString five((UChar32)0x10005);
1883     custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
1884     custom.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, one);
1885     custom.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, two);
1886     custom.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, five);
1887     expStr = UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1888     expStr = expStr.unescape();
1889     status = U_ZERO_ERROR;
1890     expect2(new DecimalFormat("##0.000", custom, status),
1891            1.25, expStr, status);
1892 
1893     custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
1894     custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
1895     custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
1896     patternStr = UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
1897     patternStr = patternStr.unescape();
1898     expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1899     status = U_ZERO_ERROR;
1900     expect2(new DecimalFormat(patternStr, custom, status),
1901            int32_t(-20), expStr, status);
1902 
1903     custom.setSymbol(DecimalFormatSymbols::kPercentSymbol, "percent");
1904     patternStr = "'You''ve lost ' -0.00 %' of your money today'";
1905     patternStr = patternStr.unescape();
1906     expStr = UnicodeString(" minus You've lost   minus 2000decimal00 percent of your money today", "");
1907     status = U_ZERO_ERROR;
1908     expect2(new DecimalFormat(patternStr, custom, status),
1909            int32_t(-20), expStr, status);
1910 }
1911 
TestCurrencyPatterns(void)1912 void NumberFormatTest::TestCurrencyPatterns(void) {
1913     int32_t i, locCount;
1914     const Locale* locs = NumberFormat::getAvailableLocales(locCount);
1915     for (i=0; i<locCount; ++i) {
1916         UErrorCode ec = U_ZERO_ERROR;
1917         NumberFormat* nf = NumberFormat::createCurrencyInstance(locs[i], ec);
1918         if (U_FAILURE(ec)) {
1919             errln("FAIL: Can't create NumberFormat(%s) - %s", locs[i].getName(), u_errorName(ec));
1920         } else {
1921             // Make sure currency formats do not have a variable number
1922             // of fraction digits
1923             int32_t min = nf->getMinimumFractionDigits();
1924             int32_t max = nf->getMaximumFractionDigits();
1925             if (min != max) {
1926                 UnicodeString a, b;
1927                 nf->format(1.0, a);
1928                 nf->format(1.125, b);
1929                 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1930                       " min fraction digits != max fraction digits; "
1931                       "x 1.0 => " + escape(a) +
1932                       "; x 1.125 => " + escape(b));
1933             }
1934 
1935             // Make sure EURO currency formats have exactly 2 fraction digits
1936             DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
1937             if (df != NULL) {
1938                 if (u_strcmp(EUR, df->getCurrency()) == 0) {
1939                     if (min != 2 || max != 2) {
1940                         UnicodeString a;
1941                         nf->format(1.0, a);
1942                         errln((UnicodeString)"FAIL: " + locs[i].getName() +
1943                               " is a EURO format but it does not have 2 fraction digits; "
1944                               "x 1.0 => " +
1945                               escape(a));
1946                     }
1947                 }
1948             }
1949         }
1950         delete nf;
1951     }
1952 }
1953 
TestRegCurrency(void)1954 void NumberFormatTest::TestRegCurrency(void) {
1955 #if !UCONFIG_NO_SERVICE
1956     UErrorCode status = U_ZERO_ERROR;
1957     UChar USD[4];
1958     ucurr_forLocale("en_US", USD, 4, &status);
1959     UChar YEN[4];
1960     ucurr_forLocale("ja_JP", YEN, 4, &status);
1961     UChar TMP[4];
1962 
1963     if(U_FAILURE(status)) {
1964         errcheckln(status, "Unable to get currency for locale, error %s", u_errorName(status));
1965         return;
1966     }
1967 
1968     UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
1969 
1970     ucurr_forLocale("en_US", TMP, 4, &status);
1971     if (u_strcmp(YEN, TMP) != 0) {
1972         errln("FAIL: didn't return YEN registered for en_US");
1973     }
1974 
1975     int32_t fallbackLen = ucurr_forLocale("en_XX_BAR", TMP, 4, &status);
1976     if (fallbackLen) {
1977         errln("FAIL: tried to fallback en_XX_BAR");
1978     }
1979     status = U_ZERO_ERROR; // reset
1980 
1981     if (!ucurr_unregister(enkey, &status)) {
1982         errln("FAIL: couldn't unregister enkey");
1983     }
1984 
1985     ucurr_forLocale("en_US", TMP, 4, &status);
1986     if (u_strcmp(USD, TMP) != 0) {
1987         errln("FAIL: didn't return USD for en_US after unregister of en_US");
1988     }
1989     status = U_ZERO_ERROR; // reset
1990 
1991     ucurr_forLocale("en_US_BLAH", TMP, 4, &status);
1992     if (u_strcmp(USD, TMP) != 0) {
1993         errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1994     }
1995     status = U_ZERO_ERROR; // reset
1996 #endif
1997 }
1998 
TestCurrencyNames(void)1999 void NumberFormatTest::TestCurrencyNames(void) {
2000     // Do a basic check of getName()
2001     // USD { "US$", "US Dollar"            } // 04/04/1792-
2002     UErrorCode ec = U_ZERO_ERROR;
2003     static const UChar USD[] = {0x55, 0x53, 0x44, 0}; /*USD*/
2004     static const UChar USX[] = {0x55, 0x53, 0x58, 0}; /*USX*/
2005     static const UChar CAD[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
2006     static const UChar ITL[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
2007     UBool isChoiceFormat;
2008     int32_t len;
2009     const UBool possibleDataError = TRUE;
2010     // Warning: HARD-CODED LOCALE DATA in this test.  If it fails, CHECK
2011     // THE LOCALE DATA before diving into the code.
2012     assertEquals("USD.getName(SYMBOL_NAME, en)",
2013                  UnicodeString("$"),
2014                  UnicodeString(ucurr_getName(USD, "en",
2015                                              UCURR_SYMBOL_NAME,
2016                                              &isChoiceFormat, &len, &ec)),
2017                                              possibleDataError);
2018     assertEquals("USD.getName(NARROW_SYMBOL_NAME, en)",
2019                  UnicodeString("$"),
2020                  UnicodeString(ucurr_getName(USD, "en",
2021                                              UCURR_NARROW_SYMBOL_NAME,
2022                                              &isChoiceFormat, &len, &ec)),
2023                                              possibleDataError);
2024     assertEquals("USD.getName(LONG_NAME, en)",
2025                  UnicodeString("US Dollar"),
2026                  UnicodeString(ucurr_getName(USD, "en",
2027                                              UCURR_LONG_NAME,
2028                                              &isChoiceFormat, &len, &ec)),
2029                                              possibleDataError);
2030     assertEquals("CAD.getName(SYMBOL_NAME, en)",
2031                  UnicodeString("CA$"),
2032                  UnicodeString(ucurr_getName(CAD, "en",
2033                                              UCURR_SYMBOL_NAME,
2034                                              &isChoiceFormat, &len, &ec)),
2035                                              possibleDataError);
2036     assertEquals("CAD.getName(NARROW_SYMBOL_NAME, en)",
2037                  UnicodeString("$"),
2038                  UnicodeString(ucurr_getName(CAD, "en",
2039                                              UCURR_NARROW_SYMBOL_NAME,
2040                                              &isChoiceFormat, &len, &ec)),
2041                                              possibleDataError);
2042     assertEquals("CAD.getName(SYMBOL_NAME, en_CA)",
2043                  UnicodeString("$"),
2044                  UnicodeString(ucurr_getName(CAD, "en_CA",
2045                                              UCURR_SYMBOL_NAME,
2046                                              &isChoiceFormat, &len, &ec)),
2047                                              possibleDataError);
2048     assertEquals("USD.getName(SYMBOL_NAME, en_CA)",
2049                  UnicodeString("US$"),
2050                  UnicodeString(ucurr_getName(USD, "en_CA",
2051                                              UCURR_SYMBOL_NAME,
2052                                              &isChoiceFormat, &len, &ec)),
2053                                              possibleDataError);
2054     assertEquals("USD.getName(NARROW_SYMBOL_NAME, en_CA)",
2055                  UnicodeString("$"),
2056                  UnicodeString(ucurr_getName(USD, "en_CA",
2057                                              UCURR_NARROW_SYMBOL_NAME,
2058                                              &isChoiceFormat, &len, &ec)),
2059                                              possibleDataError);
2060     assertEquals("USD.getName(SYMBOL_NAME) in en_NZ",
2061                  UnicodeString("US$"),
2062                  UnicodeString(ucurr_getName(USD, "en_NZ",
2063                                              UCURR_SYMBOL_NAME,
2064                                              &isChoiceFormat, &len, &ec)),
2065                                              possibleDataError);
2066     assertEquals("CAD.getName(SYMBOL_NAME)",
2067                  UnicodeString("CA$"),
2068                  UnicodeString(ucurr_getName(CAD, "en_NZ",
2069                                              UCURR_SYMBOL_NAME,
2070                                              &isChoiceFormat, &len, &ec)),
2071                                              possibleDataError);
2072     assertEquals("USX.getName(SYMBOL_NAME)",
2073                  UnicodeString("USX"),
2074                  UnicodeString(ucurr_getName(USX, "en_US",
2075                                              UCURR_SYMBOL_NAME,
2076                                              &isChoiceFormat, &len, &ec)),
2077                                              possibleDataError);
2078     assertEquals("USX.getName(NARROW_SYMBOL_NAME)",
2079                  UnicodeString("USX"),
2080                  UnicodeString(ucurr_getName(USX, "en_US",
2081                                              UCURR_NARROW_SYMBOL_NAME,
2082                                              &isChoiceFormat, &len, &ec)),
2083                                              possibleDataError);
2084     assertEquals("USX.getName(LONG_NAME)",
2085                  UnicodeString("USX"),
2086                  UnicodeString(ucurr_getName(USX, "en_US",
2087                                              UCURR_LONG_NAME,
2088                                              &isChoiceFormat, &len, &ec)),
2089                                              possibleDataError);
2090     assertSuccess("ucurr_getName", ec);
2091 
2092     ec = U_ZERO_ERROR;
2093 
2094     // Test that a default or fallback warning is being returned. JB 4239.
2095     ucurr_getName(CAD, "es_ES", UCURR_LONG_NAME, &isChoiceFormat,
2096                             &len, &ec);
2097     assertTrue("ucurr_getName (es_ES fallback)",
2098                     U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);
2099 
2100     ucurr_getName(CAD, "zh_TW", UCURR_LONG_NAME, &isChoiceFormat,
2101                             &len, &ec);
2102     assertTrue("ucurr_getName (zh_TW fallback)",
2103                     U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);
2104 
2105     ucurr_getName(CAD, "en_US", UCURR_LONG_NAME, &isChoiceFormat,
2106                             &len, &ec);
2107     assertTrue("ucurr_getName (en_US default)",
2108                     U_USING_DEFAULT_WARNING == ec || U_USING_FALLBACK_WARNING == ec, TRUE);
2109 
2110     ucurr_getName(CAD, "ti", UCURR_LONG_NAME, &isChoiceFormat,
2111                             &len, &ec);
2112     assertTrue("ucurr_getName (ti default)",
2113                     U_USING_DEFAULT_WARNING == ec, TRUE);
2114 
2115     // Test that a default warning is being returned when falling back to root. JB 4536.
2116     ucurr_getName(ITL, "cy", UCURR_LONG_NAME, &isChoiceFormat,
2117                             &len, &ec);
2118     assertTrue("ucurr_getName (cy default to root)",
2119                     U_USING_DEFAULT_WARNING == ec, TRUE);
2120 
2121     // TODO add more tests later
2122 }
2123 
TestCurrencyVariants()2124 void NumberFormatTest::TestCurrencyVariants(){
2125     IcuTestErrorCode status(*this, "TestCurrencyVariants");
2126 
2127     struct TestCase {
2128         const char* locale;
2129         const char16_t* isoCode;
2130         const char16_t* expectedShort;
2131         const char16_t* expectedNarrow;
2132         const char16_t* expectedFormal;
2133         const char16_t* expectedVariant;
2134         UErrorCode expectedNarrowError;
2135     } cases[] = {
2136         {"en-US", u"CAD", u"CA$", u"$", u"CA$", u"CA$", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2137         {"en-US", u"CDF", u"CDF", u"CDF", u"CDF", u"CDF", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2138         {"sw-CD", u"CDF", u"FC", u"FC", u"FC", u"FC", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2139         {"en-US", u"GEL", u"GEL", u"₾", u"GEL", u"GEL", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2140         {"ka-GE", u"GEL", u"₾", u"₾", u"₾", u"₾", U_USING_FALLBACK_WARNING}, // narrow: fallback to ka
2141         {"ka", u"GEL", u"₾", u"₾", u"₾", u"₾", U_ZERO_ERROR}, // no fallback on narrow
2142         {"zh-TW", u"TWD", u"$", u"$", u"NT$", u"$", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2143         {"ccp", u"TRY", u"TRY", u"₺", u"TRY", u"TL", U_ZERO_ERROR}, // no fallback on variant
2144     };
2145     for (const auto& cas : cases) {
2146         status.setScope(cas.isoCode);
2147         UBool choiceFormatIgnored;
2148         int32_t lengthIgnored;
2149         const UChar* actualShort = ucurr_getName(
2150             cas.isoCode,
2151             cas.locale,
2152             UCURR_SYMBOL_NAME,
2153             &choiceFormatIgnored,
2154             &lengthIgnored,
2155             status);
2156         const UChar* actualFormal = ucurr_getName(
2157             cas.isoCode,
2158             cas.locale,
2159             UCURR_FORMAL_SYMBOL_NAME,
2160             &choiceFormatIgnored,
2161             &lengthIgnored,
2162             status);
2163         const UChar* actualVarant = ucurr_getName(
2164             cas.isoCode,
2165             cas.locale,
2166             UCURR_VARIANT_SYMBOL_NAME,
2167             &choiceFormatIgnored,
2168             &lengthIgnored,
2169             status);
2170         status.errIfFailureAndReset();
2171         const UChar* actualNarrow = ucurr_getName(
2172             cas.isoCode,
2173             cas.locale,
2174             UCURR_NARROW_SYMBOL_NAME,
2175             &choiceFormatIgnored,
2176             &lengthIgnored,
2177             status);
2178         status.expectErrorAndReset(cas.expectedNarrowError);
2179         assertEquals(UnicodeString("Short symbol: ") + cas.locale + u": " + cas.isoCode,
2180                 cas.expectedShort, actualShort);
2181         assertEquals(UnicodeString("Narrow symbol: ") + cas.locale + u": " + cas.isoCode,
2182                 cas.expectedNarrow, actualNarrow);
2183         assertEquals(UnicodeString("Formal symbol: ") + cas.locale + u": " + cas.isoCode,
2184                 cas.expectedFormal, actualFormal);
2185         assertEquals(UnicodeString("Variant symbol: ") + cas.locale + u": " + cas.isoCode,
2186                 cas.expectedVariant, actualVarant);
2187     }
2188 }
2189 
TestCurrencyUnit(void)2190 void NumberFormatTest::TestCurrencyUnit(void){
2191     UErrorCode ec = U_ZERO_ERROR;
2192     static const UChar USD[]  = u"USD";
2193     static const char USD8[]  =  "USD";
2194     static const UChar BAD[]  = u"???";
2195     static const UChar BAD2[] = u"??A";
2196     static const UChar XXX[]  = u"XXX";
2197     static const char XXX8[]  =  "XXX";
2198     static const UChar XYZ[]  = u"XYZ";
2199     static const char XYZ8[]  =  "XYZ";
2200     static const UChar INV[]  = u"{$%";
2201     static const char INV8[]  =  "{$%";
2202     static const UChar ZZZ[]  = u"zz";
2203     static const char ZZZ8[]  = "zz";
2204     static const UChar JPY[]  = u"JPY";
2205     static const char JPY8[]  =  "JPY";
2206     static const UChar jpy[]  = u"jpy";
2207     static const char jpy8[]  =  "jpy";
2208 
2209     UChar* EUR = (UChar*) malloc(6);
2210     EUR[0] = u'E';
2211     EUR[1] = u'U';
2212     EUR[2] = u'R';
2213     char* EUR8 = (char*) malloc(3);
2214     EUR8[0] = 'E';
2215     EUR8[1] = 'U';
2216     EUR8[2] = 'R';
2217 
2218     CurrencyUnit cu(USD, ec);
2219     assertSuccess("CurrencyUnit", ec);
2220     assertEquals("getISOCurrency()", USD, cu.getISOCurrency());
2221     assertEquals("getSubtype()", USD8, cu.getSubtype());
2222 
2223     // Test XYZ, a valid but non-standard currency.
2224     // Note: Country code XY is private-use, so XYZ should remain unallocated.
2225     CurrencyUnit extended(XYZ, ec);
2226     assertSuccess("non-standard", ec);
2227     assertEquals("non-standard", XYZ, extended.getISOCurrency());
2228     assertEquals("non-standard", XYZ8, extended.getSubtype());
2229 
2230     CurrencyUnit inv(INV, ec);
2231     assertEquals("non-invariant", U_INVARIANT_CONVERSION_ERROR, ec);
2232     assertEquals("non-invariant", XXX, inv.getISOCurrency());
2233     ec = U_ZERO_ERROR;
2234 
2235     CurrencyUnit zzz(ZZZ, ec);
2236     assertEquals("too short", U_ILLEGAL_ARGUMENT_ERROR, ec);
2237     assertEquals("too short", XXX, zzz.getISOCurrency());
2238     ec = U_ZERO_ERROR;
2239 
2240     CurrencyUnit eur(EUR, ec);
2241     assertEquals("non-nul-terminated", u"EUR", eur.getISOCurrency());
2242     assertEquals("non-nul-terminated", "EUR", eur.getSubtype());
2243 
2244     // Test StringPiece constructor
2245     CurrencyUnit cu8(USD8, ec);
2246     assertEquals("StringPiece constructor", USD, cu8.getISOCurrency());
2247 
2248     CurrencyUnit inv8(INV8, ec);
2249     assertEquals("non-invariant 8", U_INVARIANT_CONVERSION_ERROR, ec);
2250     assertEquals("non-invariant 8", XXX, inv8.getISOCurrency());
2251     ec = U_ZERO_ERROR;
2252 
2253     CurrencyUnit zzz8(ZZZ8, ec);
2254     assertEquals("too short 8", U_ILLEGAL_ARGUMENT_ERROR, ec);
2255     assertEquals("too short 8", XXX, zzz8.getISOCurrency());
2256     ec = U_ZERO_ERROR;
2257 
2258     CurrencyUnit zzz8b({ZZZ8, 3}, ec);
2259     assertEquals("too short 8b", U_ILLEGAL_ARGUMENT_ERROR, ec);
2260     assertEquals("too short 8b", XXX, zzz8b.getISOCurrency());
2261     ec = U_ZERO_ERROR;
2262 
2263     CurrencyUnit eur8({EUR8, 3}, ec);
2264     assertEquals("non-nul-terminated 8", u"EUR", eur8.getISOCurrency());
2265     assertEquals("non-nul-terminated 8", "EUR", eur8.getSubtype());
2266 
2267     CurrencyUnit cu2(cu);
2268     if (!(cu2 == cu)){
2269         errln("CurrencyUnit copy constructed object should be same");
2270     }
2271 
2272     CurrencyUnit * cu3 = cu.clone();
2273     if (!(*cu3 == cu)){
2274         errln("CurrencyUnit cloned object should be same");
2275     }
2276     CurrencyUnit bad(BAD, ec);
2277     assertSuccess("CurrencyUnit", ec);
2278     if (cu.getOffset() == bad.getOffset()) {
2279         errln("Indexes of different currencies should differ.");
2280     }
2281     CurrencyUnit bad2(BAD2, ec);
2282     assertSuccess("CurrencyUnit", ec);
2283     if (bad2.getOffset() != bad.getOffset()) {
2284         errln("Indexes of unrecognized currencies should be the same.");
2285     }
2286     if (bad == bad2) {
2287         errln("Different unrecognized currencies should not be equal.");
2288     }
2289     bad = bad2;
2290     if (bad != bad2) {
2291         errln("Currency unit assignment should be the same.");
2292     }
2293     delete cu3;
2294 
2295     // Test default constructor
2296     CurrencyUnit def;
2297     assertEquals("Default currency", XXX, def.getISOCurrency());
2298     assertEquals("Default currency as subtype", XXX8, def.getSubtype());
2299 
2300     // Test slicing
2301     MeasureUnit sliced1 = cu;
2302     MeasureUnit sliced2 = cu;
2303     MeasureUnit sliced3 = extended;
2304     assertEquals("Subtype after slicing 1", USD8, sliced1.getSubtype());
2305     assertEquals("Subtype after slicing 2", USD8, sliced2.getSubtype());
2306     assertEquals("Subtype after slicing 3", XYZ8, sliced3.getSubtype());
2307     CurrencyUnit restored1(sliced1, ec);
2308     CurrencyUnit restored2(sliced2, ec);
2309     CurrencyUnit restored3(sliced3, ec);
2310     assertSuccess("Restoring from MeasureUnit", ec);
2311     assertEquals("Subtype after restoring 1", USD8, restored1.getSubtype());
2312     assertEquals("Subtype after restoring 2", USD8, restored2.getSubtype());
2313     assertEquals("Subtype after restoring 3", XYZ8, restored3.getSubtype());
2314     assertEquals("ISO Code after restoring 1", USD, restored1.getISOCurrency());
2315     assertEquals("ISO Code after restoring 2", USD, restored2.getISOCurrency());
2316     assertEquals("ISO Code after restoring 3", XYZ, restored3.getISOCurrency());
2317 
2318     // Test copy constructor failure
2319     LocalPointer<MeasureUnit> meter(MeasureUnit::createMeter(ec));
2320     assertSuccess("Creating meter", ec);
2321     CurrencyUnit failure(*meter, ec);
2322     assertEquals("Copying from meter should fail", ec, U_ILLEGAL_ARGUMENT_ERROR);
2323     assertEquals("Copying should not give uninitialized ISO code", u"", failure.getISOCurrency());
2324 
2325     // Test equality
2326     ec = U_ZERO_ERROR;
2327     assertFalse("FAIL: USD == JPY", CurrencyUnit(USD, ec) == CurrencyUnit(JPY, ec));
2328     assertTrue("FAIL: USD != USD",  CurrencyUnit(USD, ec) == CurrencyUnit(USD, ec));
2329     assertTrue("FAIL: JPY != jpy",  CurrencyUnit(JPY, ec) == CurrencyUnit(jpy, ec));
2330     assertTrue("FAIL: jpy != JPY",  CurrencyUnit(jpy, ec) == CurrencyUnit(JPY, ec));
2331 
2332     // Test equality with system charset instances
2333     assertFalse("FAIL: USD8 == JPY8", CurrencyUnit(USD8, ec) == CurrencyUnit(JPY8, ec));
2334     assertTrue("FAIL: USD8 != USD8",  CurrencyUnit(USD8, ec) == CurrencyUnit(USD8, ec));
2335     assertTrue("FAIL: JPY8 != jpy8",  CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy8, ec));
2336     assertTrue("FAIL: jpy8 != JPY8",  CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY8, ec));
2337 
2338     // Test equality between UTF-16 and system charset instances
2339     assertTrue("FAIL: USD != USD8",  CurrencyUnit(USD, ec) == CurrencyUnit(USD8, ec));
2340     assertTrue("FAIL: USD8 != USD",  CurrencyUnit(USD8, ec) == CurrencyUnit(USD, ec));
2341     assertTrue("FAIL: JPY != jpy8",  CurrencyUnit(JPY, ec) == CurrencyUnit(jpy8, ec));
2342     assertTrue("FAIL: JPY8 != jpy",  CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy, ec));
2343     assertTrue("FAIL: jpy != JPY8",  CurrencyUnit(jpy, ec) == CurrencyUnit(JPY8, ec));
2344     assertTrue("FAIL: jpy8 != JPY",  CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY, ec));
2345 
2346     free(EUR);
2347     free(EUR8);
2348 }
2349 
TestCurrencyAmount(void)2350 void NumberFormatTest::TestCurrencyAmount(void){
2351     UErrorCode ec = U_ZERO_ERROR;
2352     static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
2353     CurrencyAmount ca(9, USD, ec);
2354     assertSuccess("CurrencyAmount", ec);
2355 
2356     CurrencyAmount ca2(ca);
2357     if (!(ca2 == ca)){
2358         errln("CurrencyAmount copy constructed object should be same");
2359     }
2360 
2361     ca2=ca;
2362     if (!(ca2 == ca)){
2363         errln("CurrencyAmount assigned object should be same");
2364     }
2365 
2366     CurrencyAmount *ca3 = ca.clone();
2367     if (!(*ca3 == ca)){
2368         errln("CurrencyAmount cloned object should be same");
2369     }
2370     delete ca3;
2371 }
2372 
TestSymbolsWithBadLocale(void)2373 void NumberFormatTest::TestSymbolsWithBadLocale(void) {
2374     Locale locDefault;
2375     static const char *badLocales[] = {
2376         // length < ULOC_FULLNAME_CAPACITY
2377         "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME",
2378 
2379         // length > ULOC_FULLNAME_CAPACITY
2380         "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"
2381     }; // expect U_USING_DEFAULT_WARNING for both
2382 
2383     unsigned int i;
2384     for (i = 0; i < UPRV_LENGTHOF(badLocales); i++) {
2385         const char *localeName = badLocales[i];
2386         Locale locBad(localeName);
2387         assertTrue(WHERE, !locBad.isBogus());
2388         UErrorCode status = U_ZERO_ERROR;
2389         UnicodeString intlCurrencySymbol((UChar)0xa4);
2390 
2391         intlCurrencySymbol.append((UChar)0xa4);
2392 
2393         logln("Current locale is %s", Locale::getDefault().getName());
2394         Locale::setDefault(locBad, status);
2395         logln("Current locale is %s", Locale::getDefault().getName());
2396         DecimalFormatSymbols mySymbols(status);
2397         if (status != U_USING_DEFAULT_WARNING) {
2398             errln("DecimalFormatSymbols should return U_USING_DEFAULT_WARNING.");
2399         }
2400         if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
2401             errln("DecimalFormatSymbols does not have the right locale.", locBad.getName());
2402         }
2403         int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
2404         for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
2405             UnicodeString symbolString = mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum);
2406             logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ") + prettify(symbolString));
2407             if (symbolString.length() == 0
2408                 && symbolEnum != (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
2409                 && symbolEnum != (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol)
2410             {
2411                 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
2412             }
2413         }
2414 
2415         status = U_ZERO_ERROR;
2416         Locale::setDefault(locDefault, status);
2417         logln("Current locale is %s", Locale::getDefault().getName());
2418     }
2419 }
2420 
2421 /**
2422  * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
2423  * behave the same, except for memory ownership semantics. (No
2424  * version of this test on Java, since Java has only one method.)
2425  */
TestAdoptDecimalFormatSymbols(void)2426 void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
2427     UErrorCode ec = U_ZERO_ERROR;
2428     DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2429     if (U_FAILURE(ec)) {
2430         errcheckln(ec, "Fail: DecimalFormatSymbols constructor - %s", u_errorName(ec));
2431         delete sym;
2432         return;
2433     }
2434     UnicodeString pat(" #,##0.00");
2435     pat.insert(0, (UChar)0x00A4);
2436     DecimalFormat fmt(pat, sym, ec);
2437     if (U_FAILURE(ec)) {
2438         errln("Fail: DecimalFormat constructor");
2439         return;
2440     }
2441 
2442     UnicodeString str;
2443     fmt.format(2350.75, str);
2444     if (str == "$ 2,350.75") {
2445         logln(str);
2446     } else {
2447         dataerrln("Fail: " + str + ", expected $ 2,350.75");
2448     }
2449 
2450     sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2451     if (U_FAILURE(ec)) {
2452         errln("Fail: DecimalFormatSymbols constructor");
2453         delete sym;
2454         return;
2455     }
2456     sym->setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2457     fmt.adoptDecimalFormatSymbols(sym);
2458 
2459     str.truncate(0);
2460     fmt.format(2350.75, str);
2461     if (str == "Q 2,350.75") {
2462         logln(str);
2463     } else {
2464         dataerrln("Fail: adoptDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2465     }
2466 
2467     sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2468     if (U_FAILURE(ec)) {
2469         errln("Fail: DecimalFormatSymbols constructor");
2470         delete sym;
2471         return;
2472     }
2473     DecimalFormat fmt2(pat, sym, ec);
2474     if (U_FAILURE(ec)) {
2475         errln("Fail: DecimalFormat constructor");
2476         return;
2477     }
2478 
2479     DecimalFormatSymbols sym2(Locale::getUS(), ec);
2480     if (U_FAILURE(ec)) {
2481         errln("Fail: DecimalFormatSymbols constructor");
2482         return;
2483     }
2484     sym2.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2485     fmt2.setDecimalFormatSymbols(sym2);
2486 
2487     str.truncate(0);
2488     fmt2.format(2350.75, str);
2489     if (str == "Q 2,350.75") {
2490         logln(str);
2491     } else {
2492         dataerrln("Fail: setDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2493     }
2494 }
2495 
TestPerMill()2496 void NumberFormatTest::TestPerMill() {
2497     UErrorCode ec = U_ZERO_ERROR;
2498     UnicodeString str;
2499     DecimalFormat fmt(ctou("###.###\\u2030"), ec);
2500     if (!assertSuccess("DecimalFormat ct", ec)) return;
2501     assertEquals("0.4857 x ###.###\\u2030",
2502                  ctou("485.7\\u2030"), fmt.format(0.4857, str), true);
2503 
2504     DecimalFormatSymbols sym(Locale::getUS(), ec);
2505     if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2506         return;
2507     }
2508     sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
2509     DecimalFormat fmt2("", sym, ec);
2510     if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2511         return;
2512     }
2513     fmt2.applyLocalizedPattern("###.###m", ec);
2514     if (!assertSuccess("setup", ec)) return;
2515     str.truncate(0);
2516     assertEquals("0.4857 x ###.###m",
2517                  "485.7m", fmt2.format(0.4857, str));
2518 }
2519 
2520 /**
2521  * Generic test for patterns that should be legal/illegal.
2522  */
TestIllegalPatterns()2523 void NumberFormatTest::TestIllegalPatterns() {
2524     // Test cases:
2525     // Prefix with "-:" for illegal patterns
2526     // Prefix with "+:" for legal patterns
2527     const char* DATA[] = {
2528         // Unquoted special characters in the suffix are illegal
2529         "-:000.000|###",
2530         "+:000.000'|###'",
2531         0
2532     };
2533     for (int32_t i=0; DATA[i]; ++i) {
2534         const char* pat=DATA[i];
2535         UBool valid = (*pat) == '+';
2536         pat += 2;
2537         UErrorCode ec = U_ZERO_ERROR;
2538         DecimalFormat fmt(pat, ec); // locale doesn't matter here
2539         if (U_SUCCESS(ec) == valid) {
2540             logln("Ok: pattern \"%s\": %s",
2541                   pat, u_errorName(ec));
2542         } else {
2543             errcheckln(ec, "FAIL: pattern \"%s\" should have %s; got %s",
2544                   pat, (valid?"succeeded":"failed"),
2545                   u_errorName(ec));
2546         }
2547     }
2548 }
2549 
2550 //----------------------------------------------------------------------
2551 
2552 static const char* KEYWORDS[] = {
2553     /*0*/ "ref=", // <reference pattern to parse numbers>
2554     /*1*/ "loc=", // <locale for formats>
2555     /*2*/ "f:",   // <pattern or '-'> <number> <exp. string>
2556     /*3*/ "fp:",  // <pattern or '-'> <number> <exp. string> <exp. number>
2557     /*4*/ "rt:",  // <pattern or '-'> <(exp.) number> <(exp.) string>
2558     /*5*/ "p:",   // <pattern or '-'> <string> <exp. number>
2559     /*6*/ "perr:", // <pattern or '-'> <invalid string>
2560     /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
2561     /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2562     0
2563 };
2564 
2565 /**
2566  * Return an integer representing the next token from this
2567  * iterator.  The integer will be an index into the given list, or
2568  * -1 if there are no more tokens, or -2 if the token is not on
2569  * the list.
2570  */
keywordIndex(const UnicodeString & tok)2571 static int32_t keywordIndex(const UnicodeString& tok) {
2572     for (int32_t i=0; KEYWORDS[i]!=0; ++i) {
2573         if (tok==KEYWORDS[i]) {
2574             return i;
2575         }
2576     }
2577     return -1;
2578 }
2579 
2580 /**
2581  * Parse a CurrencyAmount using the given NumberFormat, with
2582  * the 'delim' character separating the number and the currency.
2583  */
parseCurrencyAmount(const UnicodeString & str,const NumberFormat & fmt,UChar delim,Formattable & result,UErrorCode & ec)2584 static void parseCurrencyAmount(const UnicodeString& str,
2585                                 const NumberFormat& fmt,
2586                                 UChar delim,
2587                                 Formattable& result,
2588                                 UErrorCode& ec) {
2589     UnicodeString num, cur;
2590     int32_t i = str.indexOf(delim);
2591     str.extractBetween(0, i, num);
2592     str.extractBetween(i+1, INT32_MAX, cur);
2593     Formattable n;
2594     fmt.parse(num, n, ec);
2595     result.adoptObject(new CurrencyAmount(n, cur.getTerminatedBuffer(), ec));
2596 }
2597 
TestCases()2598 void NumberFormatTest::TestCases() {
2599     UErrorCode ec = U_ZERO_ERROR;
2600     TextFile reader("NumberFormatTestCases.txt", "UTF8", ec);
2601     if (U_FAILURE(ec)) {
2602         dataerrln("Couldn't open NumberFormatTestCases.txt");
2603         return;
2604     }
2605     TokenIterator tokens(&reader);
2606 
2607     Locale loc("en", "US", "");
2608     DecimalFormat *ref = 0, *fmt = 0;
2609     MeasureFormat *mfmt = 0;
2610     UnicodeString pat, tok, mloc, str, out, where, currAmt;
2611     Formattable n;
2612 
2613     for (;;) {
2614         ec = U_ZERO_ERROR;
2615         if (!tokens.next(tok, ec)) {
2616             break;
2617         }
2618         where = UnicodeString("(") + tokens.getLineNumber() + ") ";
2619         int32_t cmd = keywordIndex(tok);
2620         switch (cmd) {
2621         case 0:
2622             // ref= <reference pattern>
2623             if (!tokens.next(tok, ec)) goto error;
2624             delete ref;
2625             ref = new DecimalFormat(tok,
2626                       new DecimalFormatSymbols(Locale::getUS(), ec), ec);
2627             if (U_FAILURE(ec)) {
2628                 dataerrln("Error constructing DecimalFormat");
2629                 goto error;
2630             }
2631             break;
2632         case 1:
2633             // loc= <locale>
2634             if (!tokens.next(tok, ec)) goto error;
2635             loc = Locale::createFromName(CharString().appendInvariantChars(tok, ec).data());
2636             break;
2637         case 2: // f:
2638         case 3: // fp:
2639         case 4: // rt:
2640         case 5: // p:
2641             if (!tokens.next(tok, ec)) goto error;
2642             if (tok != "-") {
2643                 pat = tok;
2644                 delete fmt;
2645                 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc, ec), ec);
2646                 if (U_FAILURE(ec)) {
2647                     errln("FAIL: " + where + "Pattern \"" + pat + "\": " + u_errorName(ec));
2648                     ec = U_ZERO_ERROR;
2649                     if (!tokens.next(tok, ec)) goto error;
2650                     if (!tokens.next(tok, ec)) goto error;
2651                     if (cmd == 3) {
2652                         if (!tokens.next(tok, ec)) goto error;
2653                     }
2654                     continue;
2655                 }
2656             }
2657             if (cmd == 2 || cmd == 3 || cmd == 4) {
2658                 // f: <pattern or '-'> <number> <exp. string>
2659                 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
2660                 // rt: <pattern or '-'> <number> <string>
2661                 UnicodeString num;
2662                 if (!tokens.next(num, ec)) goto error;
2663                 if (!tokens.next(str, ec)) goto error;
2664                 ref->parse(num, n, ec);
2665                 assertSuccess("parse", ec);
2666                 assertEquals(where + "\"" + pat + "\".format(" + num + ")",
2667                              str, fmt->format(n, out.remove(), ec));
2668                 assertSuccess("format", ec);
2669                 if (cmd == 3) { // fp:
2670                     if (!tokens.next(num, ec)) goto error;
2671                     ref->parse(num, n, ec);
2672                     assertSuccess("parse", ec);
2673                 }
2674                 if (cmd != 2) { // != f:
2675                     Formattable m;
2676                     fmt->parse(str, m, ec);
2677                     assertSuccess("parse", ec);
2678                     assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2679                                  n, m);
2680                 }
2681             }
2682             // p: <pattern or '-'> <string to parse> <exp. number>
2683             else {
2684                 UnicodeString expstr;
2685                 if (!tokens.next(str, ec)) goto error;
2686                 if (!tokens.next(expstr, ec)) goto error;
2687                 Formattable exp, n;
2688                 ref->parse(expstr, exp, ec);
2689                 assertSuccess("parse", ec);
2690                 fmt->parse(str, n, ec);
2691                 assertSuccess("parse", ec);
2692                 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2693                              exp, n);
2694             }
2695             break;
2696         case 8: // fpc:
2697             if (!tokens.next(tok, ec)) goto error;
2698             if (tok != "-") {
2699                 mloc = tok;
2700                 delete mfmt;
2701                 mfmt = MeasureFormat::createCurrencyFormat(
2702                     Locale::createFromName(
2703                         CharString().appendInvariantChars(mloc, ec).data()), ec);
2704                 if (U_FAILURE(ec)) {
2705                     errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
2706                     ec = U_ZERO_ERROR;
2707                     if (!tokens.next(tok, ec)) goto error;
2708                     if (!tokens.next(tok, ec)) goto error;
2709                     if (!tokens.next(tok, ec)) goto error;
2710                     continue;
2711                 }
2712             } else if (mfmt == NULL) {
2713                 errln("FAIL: " + where + "Loc \"" + mloc + "\": skip case using previous locale, no valid MeasureFormat");
2714                 if (!tokens.next(tok, ec)) goto error;
2715                 if (!tokens.next(tok, ec)) goto error;
2716                 if (!tokens.next(tok, ec)) goto error;
2717                 continue;
2718             }
2719             // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2720             if (!tokens.next(currAmt, ec)) goto error;
2721             if (!tokens.next(str, ec)) goto error;
2722             parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2723             if (assertSuccess("parseCurrencyAmount", ec)) {
2724                 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
2725                              str, mfmt->format(n, out.remove(), ec));
2726                 assertSuccess("format", ec);
2727             }
2728             if (!tokens.next(currAmt, ec)) goto error;
2729             parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2730             if (assertSuccess("parseCurrencyAmount", ec)) {
2731                 Formattable m;
2732 
2733                 mfmt->parseObject(str, m, ec);
2734                 if (assertSuccess("parseCurrency", ec)) {
2735                     assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
2736                                  n, m);
2737                 } else {
2738                     errln("FAIL: source " + str);
2739                 }
2740             }
2741             break;
2742         case 6:
2743             // perr: <pattern or '-'> <invalid string>
2744             errln("FAIL: Under construction");
2745             goto done;
2746         case 7: {
2747             // pat: <pattern> <exp. toPattern, or '-' or 'err'>
2748             UnicodeString testpat;
2749             UnicodeString exppat;
2750             if (!tokens.next(testpat, ec)) goto error;
2751             if (!tokens.next(exppat, ec)) goto error;
2752             UBool err = exppat == "err";
2753             UBool existingPat = FALSE;
2754             if (testpat == "-") {
2755                 if (err) {
2756                     errln("FAIL: " + where + "Invalid command \"pat: - err\"");
2757                     continue;
2758                 }
2759                 existingPat = TRUE;
2760                 testpat = pat;
2761             }
2762             if (exppat == "-") exppat = testpat;
2763             DecimalFormat* f = 0;
2764             UErrorCode ec2 = U_ZERO_ERROR;
2765             if (existingPat) {
2766                 f = fmt;
2767             } else {
2768                 f = new DecimalFormat(testpat, ec2);
2769             }
2770             if (U_SUCCESS(ec2)) {
2771                 if (err) {
2772                     errln("FAIL: " + where + "Invalid pattern \"" + testpat +
2773                           "\" was accepted");
2774                 } else {
2775                     UnicodeString pat2;
2776                     assertEquals(where + "\"" + testpat + "\".toPattern()",
2777                                  exppat, f->toPattern(pat2));
2778                 }
2779             } else {
2780                 if (err) {
2781                     logln("Ok: " + where + "Invalid pattern \"" + testpat +
2782                           "\" failed: " + u_errorName(ec2));
2783                 } else {
2784                     errln("FAIL: " + where + "Valid pattern \"" + testpat +
2785                           "\" failed: " + u_errorName(ec2));
2786                 }
2787             }
2788             if (!existingPat) delete f;
2789             } break;
2790         case -1:
2791             errln("FAIL: " + where + "Unknown command \"" + tok + "\"");
2792             goto done;
2793         }
2794     }
2795     goto done;
2796 
2797  error:
2798     if (U_SUCCESS(ec)) {
2799         errln("FAIL: Unexpected EOF");
2800     } else {
2801         errcheckln(ec, "FAIL: " + where + "Unexpected " + u_errorName(ec));
2802     }
2803 
2804  done:
2805     delete mfmt;
2806     delete fmt;
2807     delete ref;
2808 }
2809 
2810 
2811 //----------------------------------------------------------------------
2812 // Support methods
2813 //----------------------------------------------------------------------
2814 
equalValue(const Formattable & a,const Formattable & b)2815 UBool NumberFormatTest::equalValue(const Formattable& a, const Formattable& b) {
2816     if (a.getType() == b.getType()) {
2817         return a == b;
2818     }
2819 
2820     if (a.getType() == Formattable::kLong) {
2821         if (b.getType() == Formattable::kInt64) {
2822             return a.getLong() == b.getLong();
2823         } else if (b.getType() == Formattable::kDouble) {
2824             return (double) a.getLong() == b.getDouble(); // TODO check use of double instead of long
2825         }
2826     } else if (a.getType() == Formattable::kDouble) {
2827         if (b.getType() == Formattable::kLong) {
2828             return a.getDouble() == (double) b.getLong();
2829         } else if (b.getType() == Formattable::kInt64) {
2830             return a.getDouble() == (double)b.getInt64();
2831         }
2832     } else if (a.getType() == Formattable::kInt64) {
2833         if (b.getType() == Formattable::kLong) {
2834                 return a.getInt64() == (int64_t)b.getLong();
2835         } else if (b.getType() == Formattable::kDouble) {
2836             return a.getInt64() == (int64_t)b.getDouble();
2837         }
2838     }
2839     return FALSE;
2840 }
2841 
expect3(NumberFormat & fmt,const Formattable & n,const UnicodeString & str)2842 void NumberFormatTest::expect3(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2843     // Don't round-trip format test, since we explicitly do it
2844     expect_rbnf(fmt, n, str, FALSE);
2845     expect_rbnf(fmt, str, n);
2846 }
2847 
expect2(NumberFormat & fmt,const Formattable & n,const UnicodeString & str)2848 void NumberFormatTest::expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2849     // Don't round-trip format test, since we explicitly do it
2850     expect(fmt, n, str, FALSE);
2851     expect(fmt, str, n);
2852 }
2853 
expect2(NumberFormat * fmt,const Formattable & n,const UnicodeString & exp,UErrorCode status)2854 void NumberFormatTest::expect2(NumberFormat* fmt, const Formattable& n,
2855                                const UnicodeString& exp,
2856                                UErrorCode status) {
2857     if (fmt == NULL || U_FAILURE(status)) {
2858         dataerrln("FAIL: NumberFormat constructor");
2859     } else {
2860         expect2(*fmt, n, exp);
2861     }
2862     delete fmt;
2863 }
2864 
expect(NumberFormat & fmt,const UnicodeString & str,const Formattable & n)2865 void NumberFormatTest::expect(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2866     UErrorCode status = U_ZERO_ERROR;
2867     Formattable num;
2868     fmt.parse(str, num, status);
2869     if (U_FAILURE(status)) {
2870         dataerrln(UnicodeString("FAIL: Parse failed for \"") + str + "\" - " + u_errorName(status));
2871         return;
2872     }
2873     UnicodeString pat;
2874     ((DecimalFormat*) &fmt)->toPattern(pat);
2875     if (equalValue(num, n)) {
2876         logln(UnicodeString("Ok   \"") + str + "\" x " +
2877               pat + " = " +
2878               toString(num));
2879     } else {
2880         dataerrln(UnicodeString("FAIL \"") + str + "\" x " +
2881               pat + " = " +
2882               toString(num) + ", expected " + toString(n));
2883     }
2884 }
2885 
expect_rbnf(NumberFormat & fmt,const UnicodeString & str,const Formattable & n)2886 void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2887     UErrorCode status = U_ZERO_ERROR;
2888     Formattable num;
2889     fmt.parse(str, num, status);
2890     if (U_FAILURE(status)) {
2891         errln(UnicodeString("FAIL: Parse failed for \"") + str + "\"");
2892         return;
2893     }
2894     if (equalValue(num, n)) {
2895         logln(UnicodeString("Ok   \"") + str + " = " +
2896               toString(num));
2897     } else {
2898         errln(UnicodeString("FAIL \"") + str + " = " +
2899               toString(num) + ", expected " + toString(n));
2900     }
2901 }
2902 
expect_rbnf(NumberFormat & fmt,const Formattable & n,const UnicodeString & exp,UBool rt)2903 void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const Formattable& n,
2904                               const UnicodeString& exp, UBool rt) {
2905     UnicodeString saw;
2906     FieldPosition pos;
2907     UErrorCode status = U_ZERO_ERROR;
2908     fmt.format(n, saw, pos, status);
2909     CHECK(status, "NumberFormat::format");
2910     if (saw == exp) {
2911         logln(UnicodeString("Ok   ") + toString(n) +
2912               " = \"" +
2913               escape(saw) + "\"");
2914         // We should be able to round-trip the formatted string =>
2915         // number => string (but not the other way around: number
2916         // => string => number2, might have number2 != number):
2917         if (rt) {
2918             Formattable n2;
2919             fmt.parse(exp, n2, status);
2920             if (U_FAILURE(status)) {
2921                 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\"");
2922                 return;
2923             }
2924             UnicodeString saw2;
2925             fmt.format(n2, saw2, pos, status);
2926             CHECK(status, "NumberFormat::format");
2927             if (saw2 != exp) {
2928                 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2929                       " => \"" + saw2 + "\"");
2930             }
2931         }
2932     } else {
2933         errln(UnicodeString("FAIL ") + toString(n) +
2934               " = \"" +
2935               escape(saw) + "\", expected \"" + exp + "\"");
2936     }
2937 }
2938 
expect(NumberFormat & fmt,const Formattable & n,const UnicodeString & exp,UBool rt)2939 void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
2940                               const UnicodeString& exp, UBool rt) {
2941     UnicodeString saw;
2942     FieldPosition pos;
2943     UErrorCode status = U_ZERO_ERROR;
2944     fmt.format(n, saw, pos, status);
2945     CHECK(status, "NumberFormat::format");
2946     UnicodeString pat;
2947     ((DecimalFormat*) &fmt)->toPattern(pat);
2948     if (saw == exp) {
2949         logln(UnicodeString("Ok   ") + toString(n) + " x " +
2950               escape(pat) + " = \"" +
2951               escape(saw) + "\"");
2952         // We should be able to round-trip the formatted string =>
2953         // number => string (but not the other way around: number
2954         // => string => number2, might have number2 != number):
2955         if (rt) {
2956             Formattable n2;
2957             fmt.parse(exp, n2, status);
2958             if (U_FAILURE(status)) {
2959                 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\" - " + u_errorName(status));
2960                 return;
2961             }
2962             UnicodeString saw2;
2963             fmt.format(n2, saw2, pos, status);
2964             CHECK(status, "NumberFormat::format");
2965             if (saw2 != exp) {
2966                 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2967                       " => \"" + saw2 + "\"");
2968             }
2969         }
2970     } else {
2971         dataerrln(UnicodeString("FAIL ") + toString(n) + " x " +
2972               escape(pat) + " = \"" +
2973               escape(saw) + "\", expected \"" + exp + "\"");
2974     }
2975 }
2976 
expect(NumberFormat * fmt,const Formattable & n,const UnicodeString & exp,UBool rt,UErrorCode status)2977 void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
2978                               const UnicodeString& exp, UBool rt,
2979                               UErrorCode status) {
2980     if (fmt == NULL || U_FAILURE(status)) {
2981         dataerrln("FAIL: NumberFormat constructor");
2982     } else {
2983         expect(*fmt, n, exp, rt);
2984     }
2985     delete fmt;
2986 }
2987 
expectCurrency(NumberFormat & nf,const Locale & locale,double value,const UnicodeString & string)2988 void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
2989                                       double value, const UnicodeString& string) {
2990     UErrorCode ec = U_ZERO_ERROR;
2991     DecimalFormat& fmt = * (DecimalFormat*) &nf;
2992     const UChar DEFAULT_CURR[] = {45/*-*/,0};
2993     UChar curr[4];
2994     u_strcpy(curr, DEFAULT_CURR);
2995     if (*locale.getLanguage() != 0) {
2996         ucurr_forLocale(locale.getName(), curr, 4, &ec);
2997         assertSuccess("ucurr_forLocale", ec);
2998         fmt.setCurrency(curr, ec);
2999         assertSuccess("DecimalFormat::setCurrency", ec);
3000         fmt.setCurrency(curr); //Deprecated variant, for coverage only
3001     }
3002     UnicodeString s;
3003     fmt.format(value, s);
3004     s.findAndReplace((UChar32)0x00A0, (UChar32)0x0020);
3005 
3006     // Default display of the number yields "1234.5599999999999"
3007     // instead of "1234.56".  Use a formatter to fix this.
3008     NumberFormat* f =
3009         NumberFormat::createInstance(Locale::getUS(), ec);
3010     UnicodeString v;
3011     if (U_FAILURE(ec)) {
3012         // Oops; bad formatter.  Use default op+= display.
3013         v = (UnicodeString)"" + value;
3014     } else {
3015         f->setMaximumFractionDigits(4);
3016         f->setGroupingUsed(FALSE);
3017         f->format(value, v);
3018     }
3019     delete f;
3020 
3021     if (s == string) {
3022         logln((UnicodeString)"Ok: " + v + " x " + curr + " => " + prettify(s));
3023     } else {
3024         errln((UnicodeString)"FAIL: " + v + " x " + curr + " => " + prettify(s) +
3025               ", expected " + prettify(string));
3026     }
3027 }
3028 
expectPat(DecimalFormat & fmt,const UnicodeString & exp)3029 void NumberFormatTest::expectPat(DecimalFormat& fmt, const UnicodeString& exp) {
3030     UnicodeString pat;
3031     fmt.toPattern(pat);
3032     if (pat == exp) {
3033         logln(UnicodeString("Ok   \"") + pat + "\"");
3034     } else {
3035         errln(UnicodeString("FAIL \"") + pat + "\", expected \"" + exp + "\"");
3036     }
3037 }
3038 
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos)3039 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3040                                  int32_t pos) {
3041     expectPad(fmt, pat, pos, 0, (UnicodeString)"");
3042 }
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos,int32_t width,UChar pad)3043 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3044                                  int32_t pos, int32_t width, UChar pad) {
3045     expectPad(fmt, pat, pos, width, UnicodeString(pad));
3046 }
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos,int32_t width,const UnicodeString & pad)3047 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3048                                  int32_t pos, int32_t width, const UnicodeString& pad) {
3049     int32_t apos = 0, awidth = 0;
3050     UnicodeString apadStr;
3051     UErrorCode status = U_ZERO_ERROR;
3052     fmt.applyPattern(pat, status);
3053     if (U_SUCCESS(status)) {
3054         apos = fmt.getPadPosition();
3055         awidth = fmt.getFormatWidth();
3056         apadStr=fmt.getPadCharacterString();
3057     } else {
3058         apos = -1;
3059         awidth = width;
3060         apadStr = pad;
3061     }
3062     if (apos == pos && awidth == width && apadStr == pad) {
3063         UnicodeString infoStr;
3064         if (pos == ILLEGAL) {
3065             infoStr = UnicodeString(" width=", "") + awidth + UnicodeString(" pad=", "") + apadStr;
3066         }
3067         logln(UnicodeString("Ok   \"") + pat + "\" pos=" + apos + infoStr);
3068     } else {
3069         errln(UnicodeString("FAIL \"") + pat + "\" pos=" + apos +
3070               " width=" + awidth + " pad=" + apadStr +
3071               ", expected " + pos + " " + width + " " + pad);
3072     }
3073 }
3074 
3075 // This test is flaky b/c the symbols for CNY and JPY are equivalent in this locale  - FIXME
TestCompatibleCurrencies()3076 void NumberFormatTest::TestCompatibleCurrencies() {
3077 /*
3078     static const UChar JPY[] = {0x4A, 0x50, 0x59, 0};
3079     static const UChar CNY[] = {0x43, 0x4E, 0x59, 0};
3080     UErrorCode status = U_ZERO_ERROR;
3081     LocalPointer<NumberFormat> fmt(
3082         NumberFormat::createCurrencyInstance(Locale::getUS(), status));
3083     if (U_FAILURE(status)) {
3084         errln("Could not create number format instance.");
3085         return;
3086     }
3087     logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3088     expectParseCurrency(*fmt, JPY, 1235,  "\\u00A51,235");
3089     logln("%s:%d - testing parse of fullwidth yen sign\n", __FILE__, __LINE__);
3090     expectParseCurrency(*fmt, JPY, 1235,  "\\uFFE51,235");
3091     logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3092     expectParseCurrency(*fmt, CNY, 1235,  "CN\\u00A51,235");
3093 
3094     LocalPointer<NumberFormat> fmtTW(
3095         NumberFormat::createCurrencyInstance(Locale::getTaiwan(), status));
3096 
3097     logln("%s:%d - testing parse of halfwidth yen sign in TW\n", __FILE__, __LINE__);
3098     expectParseCurrency(*fmtTW, CNY, 1235,  "\\u00A51,235");
3099     logln("%s:%d - testing parse of fullwidth yen sign in TW\n", __FILE__, __LINE__);
3100     expectParseCurrency(*fmtTW, CNY, 1235,  "\\uFFE51,235");
3101 
3102     LocalPointer<NumberFormat> fmtJP(
3103         NumberFormat::createCurrencyInstance(Locale::getJapan(), status));
3104 
3105     logln("%s:%d - testing parse of halfwidth yen sign in JP\n", __FILE__, __LINE__);
3106     expectParseCurrency(*fmtJP, JPY, 1235,  "\\u00A51,235");
3107     logln("%s:%d - testing parse of fullwidth yen sign in JP\n", __FILE__, __LINE__);
3108     expectParseCurrency(*fmtJP, JPY, 1235,  "\\uFFE51,235");
3109 
3110     // more..
3111 */
3112 }
3113 
expectParseCurrency(const NumberFormat & fmt,const UChar * currency,double amount,const char * text)3114 void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text) {
3115     ParsePosition ppos;
3116     UnicodeString utext = ctou(text);
3117     LocalPointer<CurrencyAmount> currencyAmount(fmt.parseCurrency(utext, ppos));
3118     if (!ppos.getIndex()) {
3119         errln(UnicodeString("Parse of ") + utext + " should have succeeded.");
3120         return;
3121     }
3122     UErrorCode status = U_ZERO_ERROR;
3123 
3124     char theInfo[100];
3125     sprintf(theInfo, "For locale %s, string \"%s\", currency ",
3126             fmt.getLocale(ULOC_ACTUAL_LOCALE, status).getBaseName(),
3127             text);
3128     u_austrcpy(theInfo+uprv_strlen(theInfo), currency);
3129 
3130     char theOperation[100];
3131 
3132     uprv_strcpy(theOperation, theInfo);
3133     uprv_strcat(theOperation, ", check amount:");
3134     assertTrue(theOperation, amount ==  currencyAmount->getNumber().getDouble(status));
3135 
3136     uprv_strcpy(theOperation, theInfo);
3137     uprv_strcat(theOperation, ", check currency:");
3138     assertEquals(theOperation, currency, currencyAmount->getISOCurrency());
3139 }
3140 
3141 
TestJB3832()3142 void NumberFormatTest::TestJB3832(){
3143     const char* localeID = "pt_PT@currency=PTE";
3144     Locale loc(localeID);
3145     UErrorCode status = U_ZERO_ERROR;
3146     UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0\\u200B")); // per cldrbug 7670
3147     UnicodeString s;
3148     NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
3149     if(U_FAILURE(status)){
3150         dataerrln("Could not create currency formatter for locale %s - %s", localeID, u_errorName(status));
3151         return;
3152     }
3153     currencyFmt->format(1150.50, s);
3154     if(s!=expected){
3155         errln(UnicodeString("FAIL: Expected: ")+expected
3156                 + UnicodeString(" Got: ") + s
3157                 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
3158     }
3159     if (U_FAILURE(status)){
3160         errln("FAIL: Status %s", u_errorName(status));
3161     }
3162     delete currencyFmt;
3163 }
3164 
TestHost()3165 void NumberFormatTest::TestHost()
3166 {
3167 #if U_PLATFORM_USES_ONLY_WIN32_API
3168     Win32NumberTest::testLocales(this);
3169 #endif
3170     Locale loc("en_US@compat=host");
3171     for (UNumberFormatStyle k = UNUM_DECIMAL;
3172          k < UNUM_FORMAT_STYLE_COUNT; k = (UNumberFormatStyle)(k+1)) {
3173         UErrorCode status = U_ZERO_ERROR;
3174         LocalPointer<NumberFormat> full(NumberFormat::createInstance(loc, k, status));
3175         if (!NumberFormat::isStyleSupported(k)) {
3176             if (status != U_UNSUPPORTED_ERROR) {
3177                 errln("FAIL: expected style %d to be unsupported - %s",
3178                       k, u_errorName(status));
3179             }
3180             continue;
3181         }
3182         if (full.isNull() || U_FAILURE(status)) {
3183             dataerrln("FAIL: Can't create number instance of style %d for host - %s",
3184                       k, u_errorName(status));
3185             return;
3186         }
3187         UnicodeString result1;
3188         Formattable number(10.00);
3189         full->format(number, result1, status);
3190         if (U_FAILURE(status)) {
3191             errln("FAIL: Can't format for host");
3192             return;
3193         }
3194         Formattable formattable;
3195         full->parse(result1, formattable, status);
3196         if (U_FAILURE(status)) {
3197             errln("FAIL: Can't parse for host");
3198             return;
3199         }
3200     }
3201 }
3202 
TestHostClone()3203 void NumberFormatTest::TestHostClone()
3204 {
3205     /*
3206     Verify that a cloned formatter gives the same results
3207     and is useable after the original has been deleted.
3208     */
3209     // This is mainly important on Windows.
3210     UErrorCode status = U_ZERO_ERROR;
3211     Locale loc("en_US@compat=host");
3212     UDate now = Calendar::getNow();
3213     NumberFormat *full = NumberFormat::createInstance(loc, status);
3214     if (full == NULL || U_FAILURE(status)) {
3215         dataerrln("FAIL: Can't create NumberFormat date instance - %s", u_errorName(status));
3216         return;
3217     }
3218     UnicodeString result1;
3219     full->format(now, result1, status);
3220     Format *fullClone = full->clone();
3221     delete full;
3222     full = NULL;
3223 
3224     UnicodeString result2;
3225     fullClone->format(now, result2, status);
3226     if (U_FAILURE(status)) {
3227         errln("FAIL: format failure.");
3228     }
3229     if (result1 != result2) {
3230         errln("FAIL: Clone returned different result from non-clone.");
3231     }
3232     delete fullClone;
3233 }
3234 
TestCurrencyFormat()3235 void NumberFormatTest::TestCurrencyFormat()
3236 {
3237     // This test is here to increase code coverage.
3238     UErrorCode status = U_ZERO_ERROR;
3239     MeasureFormat *cloneObj;
3240     UnicodeString str;
3241     Formattable toFormat, result;
3242     static const UChar ISO_CODE[4] = {0x0047, 0x0042, 0x0050, 0};
3243 
3244     Locale  saveDefaultLocale = Locale::getDefault();
3245     Locale::setDefault( Locale::getUK(), status );
3246     if (U_FAILURE(status)) {
3247         errln("couldn't set default Locale!");
3248         return;
3249     }
3250 
3251     MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
3252     Locale::setDefault( saveDefaultLocale, status );
3253     if (U_FAILURE(status)){
3254         dataerrln("FAIL: Status %s", u_errorName(status));
3255         return;
3256     }
3257     cloneObj = measureObj->clone();
3258     if (cloneObj == NULL) {
3259         errln("Clone doesn't work");
3260         return;
3261     }
3262     toFormat.adoptObject(new CurrencyAmount(1234.56, ISO_CODE, status));
3263     measureObj->format(toFormat, str, status);
3264     measureObj->parseObject(str, result, status);
3265     if (U_FAILURE(status)){
3266         errln("FAIL: Status %s", u_errorName(status));
3267     }
3268     if (result != toFormat) {
3269         errln("measureObj does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3270     }
3271     status = U_ZERO_ERROR;
3272     str.truncate(0);
3273     cloneObj->format(toFormat, str, status);
3274     cloneObj->parseObject(str, result, status);
3275     if (U_FAILURE(status)){
3276         errln("FAIL: Status %s", u_errorName(status));
3277     }
3278     if (result != toFormat) {
3279         errln("Clone does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3280     }
3281     if (*measureObj != *cloneObj) {
3282         errln("Cloned object is not equal to the original object");
3283     }
3284     delete measureObj;
3285     delete cloneObj;
3286 
3287     status = U_USELESS_COLLATOR_ERROR;
3288     if (MeasureFormat::createCurrencyFormat(status) != NULL) {
3289         errln("createCurrencyFormat should have returned NULL.");
3290     }
3291 }
3292 
3293 /* Port of ICU4J rounding test. */
TestRounding()3294 void NumberFormatTest::TestRounding() {
3295     UErrorCode status = U_ZERO_ERROR;
3296     DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3297 
3298     if (U_FAILURE(status)) {
3299         dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3300         return;
3301     }
3302 
3303     int roundingIncrements[]={1, 2, 5, 20, 50, 100};
3304     int testValues[]={0, 300};
3305 
3306     for (int j=0; j<2; j++) {
3307         for (int mode=DecimalFormat::kRoundUp;mode<DecimalFormat::kRoundHalfEven;mode++) {
3308             df->setRoundingMode((DecimalFormat::ERoundingMode)mode);
3309             for (int increment=0; increment<6; increment++) {
3310                 double base=testValues[j];
3311                 double rInc=roundingIncrements[increment];
3312                 checkRounding(df, base, 20, rInc);
3313                 rInc=1.000000000/rInc;
3314                 checkRounding(df, base, 20, rInc);
3315             }
3316         }
3317     }
3318     delete df;
3319 }
3320 
TestRoundingPattern()3321 void NumberFormatTest::TestRoundingPattern() {
3322     UErrorCode status = U_ZERO_ERROR;
3323     struct {
3324         UnicodeString  pattern;
3325         double        testCase;
3326         UnicodeString expected;
3327     } tests[] = {
3328             { (UnicodeString)"##0.65", 1.234, (UnicodeString)"1.30" },
3329             { (UnicodeString)"#50",    1230,  (UnicodeString)"1250" }
3330     };
3331     int32_t numOfTests = UPRV_LENGTHOF(tests);
3332     UnicodeString result;
3333 
3334     DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3335     if (U_FAILURE(status)) {
3336         dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3337         return;
3338     }
3339 
3340     for (int32_t i = 0; i < numOfTests; i++) {
3341         result.remove();
3342 
3343         df->applyPattern(tests[i].pattern, status);
3344         if (U_FAILURE(status)) {
3345             errln("Unable to apply pattern to decimal formatter. - %s", u_errorName(status));
3346         }
3347 
3348         df->format(tests[i].testCase, result);
3349 
3350         if (result != tests[i].expected) {
3351             errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
3352         }
3353     }
3354 
3355     delete df;
3356 }
3357 
checkRounding(DecimalFormat * df,double base,int iterations,double increment)3358 void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
3359     df->setRoundingIncrement(increment);
3360     double lastParsed=INT32_MIN; //Intger.MIN_VALUE
3361     for (int i=-iterations; i<=iterations;i++) {
3362         double iValue=base+(increment*(i*0.1));
3363         double smallIncrement=0.00000001;
3364         if (iValue!=0) {
3365             smallIncrement*=iValue;
3366         }
3367         //we not only test the value, but some values in a small range around it
3368         lastParsed=checkRound(df, iValue-smallIncrement, lastParsed);
3369         lastParsed=checkRound(df, iValue, lastParsed);
3370         lastParsed=checkRound(df, iValue+smallIncrement, lastParsed);
3371     }
3372 }
3373 
checkRound(DecimalFormat * df,double iValue,double lastParsed)3374 double NumberFormatTest::checkRound(DecimalFormat* df, double iValue, double lastParsed) {
3375     UErrorCode status=U_ZERO_ERROR;
3376     UnicodeString formattedDecimal;
3377     double parsed;
3378     Formattable result;
3379     df->format(iValue, formattedDecimal, status);
3380 
3381     if (U_FAILURE(status)) {
3382         errln("Error formatting number.");
3383     }
3384 
3385     df->parse(formattedDecimal, result, status);
3386 
3387     if (U_FAILURE(status)) {
3388         errln("Error parsing number.");
3389     }
3390 
3391     parsed=result.getDouble();
3392 
3393     if (lastParsed>parsed) {
3394         errln("Rounding wrong direction! %d > %d", lastParsed, parsed);
3395     }
3396 
3397     return lastParsed;
3398 }
3399 
TestNonpositiveMultiplier()3400 void NumberFormatTest::TestNonpositiveMultiplier() {
3401     UErrorCode status = U_ZERO_ERROR;
3402     DecimalFormatSymbols US(Locale::getUS(), status);
3403     CHECK(status, "DecimalFormatSymbols constructor");
3404     DecimalFormat df(UnicodeString("0"), US, status);
3405     CHECK(status, "DecimalFormat(0)");
3406 
3407     // test zero multiplier
3408 
3409     int32_t mult = df.getMultiplier();
3410     df.setMultiplier(0);
3411     if (df.getMultiplier() != mult) {
3412         errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
3413     }
3414 
3415     // test negative multiplier
3416 
3417     df.setMultiplier(-1);
3418     if (df.getMultiplier() != -1) {
3419         errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
3420         return;
3421     }
3422 
3423     expect(df, "1122.123", -1122.123);
3424     expect(df, "-1122.123", 1122.123);
3425     expect(df, "1.2", -1.2);
3426     expect(df, "-1.2", 1.2);
3427 
3428     // Note:  the tests with the final parameter of FALSE will not round trip.
3429     //        The initial numeric value will format correctly, after the multiplier.
3430     //        Parsing the formatted text will be out-of-range for an int64, however.
3431     //        The expect() function could be modified to detect this and fall back
3432     //        to looking at the decimal parsed value, but it doesn't.
3433     expect(df, U_INT64_MIN,    "9223372036854775808", FALSE);
3434     expect(df, U_INT64_MIN+1,  "9223372036854775807");
3435     expect(df, (int64_t)-123,                  "123");
3436     expect(df, (int64_t)123,                  "-123");
3437     expect(df, U_INT64_MAX-1, "-9223372036854775806");
3438     expect(df, U_INT64_MAX,   "-9223372036854775807");
3439 
3440     df.setMultiplier(-2);
3441     expect(df, -(U_INT64_MIN/2)-1, "-9223372036854775806");
3442     expect(df, -(U_INT64_MIN/2),   "-9223372036854775808");
3443     expect(df, -(U_INT64_MIN/2)+1, "-9223372036854775810", FALSE);
3444 
3445     df.setMultiplier(-7);
3446     expect(df, -(U_INT64_MAX/7)-1, "9223372036854775814", FALSE);
3447     expect(df, -(U_INT64_MAX/7),   "9223372036854775807");
3448     expect(df, -(U_INT64_MAX/7)+1, "9223372036854775800");
3449 
3450     // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
3451     // (right now the big numbers get turned into doubles and lose tons of accuracy)
3452     //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
3453     //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
3454     //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
3455     //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
3456 
3457     // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
3458     //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3459     //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3460     //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3461     //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3462 }
3463 
3464 typedef struct {
3465     const char * stringToParse;
3466     int          parsedPos;
3467     int          errorIndex;
3468     UBool        lenient;
3469 } TestSpaceParsingItem;
3470 
3471 void
TestSpaceParsing()3472 NumberFormatTest::TestSpaceParsing() {
3473     // the data are:
3474     // the string to be parsed, parsed position, parsed error index
3475     const TestSpaceParsingItem DATA[] = {
3476         {"$124",           4, -1, FALSE},
3477         {"$124 $124",      4, -1, FALSE},
3478         {"$124 ",          4, -1, FALSE},
3479         {"$ 124 ",         0,  1, FALSE},
3480         {"$\\u00A0124 ",   5, -1, FALSE},
3481         {" $ 124 ",        0,  0, FALSE},
3482         {"124$",           0,  4, FALSE},
3483         {"124 $",          0,  3, FALSE},
3484         {"$124",           4, -1, TRUE},
3485         {"$124 $124",      4, -1, TRUE},
3486         {"$124 ",          4, -1, TRUE},
3487         {"$ 124 ",         5, -1, TRUE},
3488         {"$\\u00A0124 ",   5, -1, TRUE},
3489         {" $ 124 ",        6, -1, TRUE},
3490         {"124$",           4, -1, TRUE},
3491         {"124$",           4, -1, TRUE},
3492         {"124 $",          5, -1, TRUE},
3493         {"124 $",          5, -1, TRUE},
3494     };
3495     UErrorCode status = U_ZERO_ERROR;
3496     Locale locale("en_US");
3497     NumberFormat* foo = NumberFormat::createCurrencyInstance(locale, status);
3498 
3499     if (U_FAILURE(status)) {
3500         delete foo;
3501         return;
3502     }
3503     for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3504         ParsePosition parsePosition(0);
3505         UnicodeString stringToBeParsed = ctou(DATA[i].stringToParse);
3506         int parsedPosition = DATA[i].parsedPos;
3507         int errorIndex = DATA[i].errorIndex;
3508         foo->setLenient(DATA[i].lenient);
3509         Formattable result;
3510         foo->parse(stringToBeParsed, result, parsePosition);
3511         logln("Parsing: " + stringToBeParsed);
3512         if (parsePosition.getIndex() != parsedPosition ||
3513             parsePosition.getErrorIndex() != errorIndex) {
3514             errln("FAILED parse " + stringToBeParsed + "; lenient: " + DATA[i].lenient + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
3515         }
3516         if (parsePosition.getErrorIndex() == -1 &&
3517             result.getType() == Formattable::kLong &&
3518             result.getLong() != 124) {
3519             errln("FAILED parse " + stringToBeParsed + "; wrong number, expect: 124, got " + result.getLong());
3520         }
3521     }
3522     delete foo;
3523 }
3524 
3525 /**
3526  * Test using various numbering systems and numbering system keyword.
3527  */
3528 typedef struct {
3529     const char *localeName;
3530     double      value;
3531     UBool        isRBNF;
3532     const char *expectedResult;
3533 } TestNumberingSystemItem;
3534 
TestNumberingSystems()3535 void NumberFormatTest::TestNumberingSystems() {
3536 
3537     const TestNumberingSystemItem DATA[] = {
3538         { "en_US@numbers=thai", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" },
3539         { "en_US@numbers=hebr", 5678.0, TRUE, "\\u05D4\\u05F3\\u05EA\\u05E8\\u05E2\\u05F4\\u05D7" },
3540         { "en_US@numbers=arabext", 1234.567, FALSE, "\\u06F1\\u066c\\u06F2\\u06F3\\u06F4\\u066b\\u06F5\\u06F6\\u06F7" },
3541         { "ar_EG", 1234.567, FALSE, "\\u0661\\u066C\\u0662\\u0663\\u0664\\u066b\\u0665\\u0666\\u0667" },
3542         { "th_TH@numbers=traditional", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" }, // fall back to native per TR35
3543         { "ar_MA", 1234.567, FALSE, "1.234,567" },
3544         { "en_US@numbers=hanidec", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3545         { "ta_IN@numbers=native", 1234.567, FALSE, "\\u0BE7,\\u0BE8\\u0BE9\\u0BEA.\\u0BEB\\u0BEC\\u0BED" },
3546         { "ta_IN@numbers=traditional", 1235.0, TRUE, "\\u0BF2\\u0BE8\\u0BF1\\u0BE9\\u0BF0\\u0BEB" },
3547         { "ta_IN@numbers=finance", 1234.567, FALSE, "1,234.567" }, // fall back to default per TR35
3548         { "zh_TW@numbers=native", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3549         { "zh_TW@numbers=traditional", 1234.567, TRUE, "\\u4E00\\u5343\\u4E8C\\u767E\\u4E09\\u5341\\u56DB\\u9EDE\\u4E94\\u516D\\u4E03" },
3550         { "zh_TW@numbers=finance", 1234.567, TRUE, "\\u58F9\\u4EDF\\u8CB3\\u4F70\\u53C3\\u62FE\\u8086\\u9EDE\\u4F0D\\u9678\\u67D2" },
3551         { NULL, 0, FALSE, NULL }
3552     };
3553 
3554     UErrorCode ec;
3555 
3556     const TestNumberingSystemItem *item;
3557     for (item = DATA; item->localeName != NULL; item++) {
3558         ec = U_ZERO_ERROR;
3559         Locale loc = Locale::createFromName(item->localeName);
3560 
3561         NumberFormat *origFmt = NumberFormat::createInstance(loc,ec);
3562         if (U_FAILURE(ec)) {
3563             dataerrln("FAIL: getInstance(%s) - %s", item->localeName, u_errorName(ec));
3564             continue;
3565         }
3566         // Clone to test ticket #10682
3567         NumberFormat *fmt = origFmt->clone();
3568         delete origFmt;
3569 
3570 
3571         if (item->isRBNF) {
3572             expect3(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3573         } else {
3574             expect2(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3575         }
3576         delete fmt;
3577     }
3578 
3579 
3580     // Test bogus keyword value
3581     ec = U_ZERO_ERROR;
3582     Locale loc4 = Locale::createFromName("en_US@numbers=foobar");
3583     NumberFormat* fmt4= NumberFormat::createInstance(loc4, ec);
3584     if ( ec != U_UNSUPPORTED_ERROR ) {
3585         errln("FAIL: getInstance(en_US@numbers=foobar) should have returned U_UNSUPPORTED_ERROR");
3586         delete fmt4;
3587     }
3588 
3589     ec = U_ZERO_ERROR;
3590     NumberingSystem *ns = NumberingSystem::createInstance(ec);
3591     if (U_FAILURE(ec)) {
3592         dataerrln("FAIL: NumberingSystem::createInstance(ec); - %s", u_errorName(ec));
3593     }
3594 
3595     if ( ns != NULL ) {
3596         ns->getDynamicClassID();
3597         ns->getStaticClassID();
3598     } else {
3599         errln("FAIL: getInstance() returned NULL.");
3600     }
3601 
3602     NumberingSystem *ns1 = new NumberingSystem(*ns);
3603     if (ns1 == NULL) {
3604         errln("FAIL: NumberSystem copy constructor returned NULL.");
3605     }
3606 
3607     delete ns1;
3608     delete ns;
3609 
3610 }
3611 
3612 
3613 void
TestMultiCurrencySign()3614 NumberFormatTest::TestMultiCurrencySign() {
3615     const char* DATA[][6] = {
3616         // the fields in the following test are:
3617         // locale,
3618         // currency pattern (with negative pattern),
3619         // currency number to be formatted,
3620         // currency format using currency symbol name, such as "$" for USD,
3621         // currency format using currency ISO name, such as "USD",
3622         // currency format using plural name, such as "US dollars".
3623         // for US locale
3624         {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1234.56", "$1,234.56", "USD\\u00A01,234.56", "US dollars\\u00A01,234.56"},
3625         {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD\\u00A01,234.56", "-US dollars\\u00A01,234.56"},
3626         {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD\\u00A01.00", "US dollars\\u00A01.00"},
3627         // for CHINA locale
3628         {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\u00A51,234.56", "CNY\\u00A01,234.56", "\\u4EBA\\u6C11\\u5E01\\u00A01,234.56"},
3629         {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\u00A51,234.56)", "(CNY\\u00A01,234.56)", "(\\u4EBA\\u6C11\\u5E01\\u00A01,234.56)"},
3630         {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\u00A51.00", "CNY\\u00A01.00", "\\u4EBA\\u6C11\\u5E01\\u00A01.00"}
3631     };
3632 
3633     const UChar doubleCurrencySign[] = {0xA4, 0xA4, 0};
3634     UnicodeString doubleCurrencyStr(doubleCurrencySign);
3635     const UChar tripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
3636     UnicodeString tripleCurrencyStr(tripleCurrencySign);
3637 
3638     for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3639         const char* locale = DATA[i][0];
3640         UnicodeString pat = ctou(DATA[i][1]);
3641         double numberToBeFormat = atof(DATA[i][2]);
3642         UErrorCode status = U_ZERO_ERROR;
3643         DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale(locale), status);
3644         if (U_FAILURE(status)) {
3645             delete sym;
3646             continue;
3647         }
3648         for (int j=1; j<=3; ++j) {
3649             // j represents the number of currency sign in the pattern.
3650             if (j == 2) {
3651                 pat = pat.findAndReplace(ctou("\\u00A4"), doubleCurrencyStr);
3652             } else if (j == 3) {
3653                 pat = pat.findAndReplace(ctou("\\u00A4\\u00A4"), tripleCurrencyStr);
3654             }
3655 
3656             DecimalFormat* fmt = new DecimalFormat(pat, new DecimalFormatSymbols(*sym), status);
3657             if (U_FAILURE(status)) {
3658                 errln("FAILED init DecimalFormat ");
3659                 delete fmt;
3660                 continue;
3661             }
3662             UnicodeString s;
3663             ((NumberFormat*) fmt)->format(numberToBeFormat, s);
3664             // DATA[i][3] is the currency format result using a
3665             // single currency sign.
3666             // DATA[i][4] is the currency format result using
3667             // double currency sign.
3668             // DATA[i][5] is the currency format result using
3669             // triple currency sign.
3670             // DATA[i][j+2] is the currency format result using
3671             // 'j' number of currency sign.
3672             UnicodeString currencyFormatResult = ctou(DATA[i][2+j]);
3673             if (s.compare(currencyFormatResult)) {
3674                 errln("FAIL format: Expected " + currencyFormatResult + "; Got " + s);
3675             }
3676             // mix style parsing
3677             for (int k=3; k<=5; ++k) {
3678               // DATA[i][3] is the currency format result using a
3679               // single currency sign.
3680               // DATA[i][4] is the currency format result using
3681               // double currency sign.
3682               // DATA[i][5] is the currency format result using
3683               // triple currency sign.
3684               UnicodeString oneCurrencyFormat = ctou(DATA[i][k]);
3685               UErrorCode status = U_ZERO_ERROR;
3686               Formattable parseRes;
3687               fmt->parse(oneCurrencyFormat, parseRes, status);
3688               if (U_FAILURE(status) ||
3689                   (parseRes.getType() == Formattable::kDouble &&
3690                    parseRes.getDouble() != numberToBeFormat) ||
3691                   (parseRes.getType() == Formattable::kLong &&
3692                    parseRes.getLong() != numberToBeFormat)) {
3693                   errln("FAILED parse " + oneCurrencyFormat + "; (i, j, k): " +
3694                         i + ", " + j + ", " + k);
3695               }
3696             }
3697             delete fmt;
3698         }
3699         delete sym;
3700     }
3701 }
3702 
3703 
3704 void
TestCurrencyFormatForMixParsing()3705 NumberFormatTest::TestCurrencyFormatForMixParsing() {
3706     UErrorCode status = U_ZERO_ERROR;
3707     MeasureFormat* curFmt = MeasureFormat::createCurrencyFormat(Locale("en_US"), status);
3708     if (U_FAILURE(status)) {
3709         delete curFmt;
3710         return;
3711     }
3712     const char* formats[] = {
3713         "$1,234.56",  // string to be parsed
3714         "USD1,234.56",
3715         "US dollars1,234.56",
3716         // "1,234.56 US dollars" // Fails in 62 because currency format is not compatible with pattern.
3717     };
3718     const CurrencyAmount* curramt = NULL;
3719     for (uint32_t i = 0; i < UPRV_LENGTHOF(formats); ++i) {
3720         UnicodeString stringToBeParsed = ctou(formats[i]);
3721         logln(UnicodeString("stringToBeParsed: ") + stringToBeParsed);
3722         Formattable result;
3723         UErrorCode status = U_ZERO_ERROR;
3724         curFmt->parseObject(stringToBeParsed, result, status);
3725         if (U_FAILURE(status)) {
3726           errln("FAIL: measure format parsing: '%s' ec: %s", formats[i], u_errorName(status));
3727         } else if (result.getType() != Formattable::kObject ||
3728             (curramt = dynamic_cast<const CurrencyAmount*>(result.getObject())) == NULL ||
3729             curramt->getNumber().getDouble() != 1234.56 ||
3730             UnicodeString(curramt->getISOCurrency()).compare(ISO_CURRENCY_USD)
3731         ) {
3732             errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number ");
3733             if (curramt->getNumber().getDouble() != 1234.56) {
3734                 errln((UnicodeString)"wong number, expect: 1234.56" + ", got: " + curramt->getNumber().getDouble());
3735             }
3736             if (curramt->getISOCurrency() != ISO_CURRENCY_USD) {
3737                 errln((UnicodeString)"wong currency, expect: USD" + ", got: " + curramt->getISOCurrency());
3738             }
3739         }
3740     }
3741     delete curFmt;
3742 }
3743 
3744 
3745 /** Starting in ICU 62, strict mode is actually strict with currency formats. */
TestMismatchedCurrencyFormatFail()3746 void NumberFormatTest::TestMismatchedCurrencyFormatFail() {
3747     IcuTestErrorCode status(*this, "TestMismatchedCurrencyFormatFail");
3748     LocalPointer<DecimalFormat> df(
3749             dynamic_cast<DecimalFormat*>(DecimalFormat::createCurrencyInstance("en", status)), status);
3750     if (!assertSuccess("createCurrencyInstance() failed.", status, true, __FILE__, __LINE__)) {return;}
3751     UnicodeString pattern;
3752     assertEquals("Test assumes that currency sign is at the beginning",
3753             u"\u00A4#,##0.00",
3754             df->toPattern(pattern));
3755     // Should round-trip on the correct currency format:
3756     expect2(*df, 1.23, u"\u00A41.23");
3757     df->setCurrency(u"EUR", status);
3758     expect2(*df, 1.23, u"\u20AC1.23");
3759     // Should parse with currency in the wrong place in lenient mode
3760     df->setLenient(TRUE);
3761     expect(*df, u"1.23\u20AC", 1.23);
3762     expectParseCurrency(*df, u"EUR", 1.23, "1.23\\u20AC");
3763     // Should NOT parse with currency in the wrong place in STRICT mode
3764     df->setLenient(FALSE);
3765     {
3766         Formattable result;
3767         ErrorCode failStatus;
3768         df->parse(u"1.23\u20AC", result, failStatus);
3769         assertEquals("Should fail to parse", U_INVALID_FORMAT_ERROR, failStatus);
3770     }
3771     {
3772         ParsePosition ppos;
3773         df->parseCurrency(u"1.23\u20AC", ppos);
3774         assertEquals("Should fail to parse currency", 0, ppos.getIndex());
3775     }
3776 }
3777 
3778 
3779 void
TestDecimalFormatCurrencyParse()3780 NumberFormatTest::TestDecimalFormatCurrencyParse() {
3781     // Locale.US
3782     UErrorCode status = U_ZERO_ERROR;
3783     DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale("en_US"), status);
3784     if (U_FAILURE(status)) {
3785         delete sym;
3786         return;
3787     }
3788     UnicodeString pat;
3789     UChar currency = 0x00A4;
3790     // "\xA4#,##0.00;-\xA4#,##0.00"
3791     pat.append(currency).append(currency).append(currency).append("#,##0.00;-").append(currency).append(currency).append(currency).append("#,##0.00");
3792     DecimalFormat* fmt = new DecimalFormat(pat, sym, status);
3793     if (U_FAILURE(status)) {
3794         delete fmt;
3795         errln("failed to new DecimalFormat in TestDecimalFormatCurrencyParse");
3796         return;
3797     }
3798     const char* DATA[][2] = {
3799         // the data are:
3800         // string to be parsed, the parsed result (number)
3801         {"$1.00", "1"},
3802         {"USD1.00", "1"},
3803         {"1.00 US dollar", "1"},
3804         {"$1,234.56", "1234.56"},
3805         {"USD1,234.56", "1234.56"},
3806         {"1,234.56 US dollar", "1234.56"},
3807     };
3808     // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3809     fmt->setLenient(TRUE);
3810     for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3811         UnicodeString stringToBeParsed = ctou(DATA[i][0]);
3812         double parsedResult = atof(DATA[i][1]);
3813         UErrorCode status = U_ZERO_ERROR;
3814         Formattable result;
3815         fmt->parse(stringToBeParsed, result, status);
3816         logln((UnicodeString)"Input: " + stringToBeParsed + "; output: " + result.getDouble(status));
3817         if (U_FAILURE(status) ||
3818             (result.getType() == Formattable::kDouble &&
3819             result.getDouble() != parsedResult) ||
3820             (result.getType() == Formattable::kLong &&
3821             result.getLong() != parsedResult)) {
3822             errln((UnicodeString)"FAIL parse: Expected " + parsedResult);
3823         }
3824     }
3825     delete fmt;
3826 }
3827 
3828 
3829 void
TestCurrencyIsoPluralFormat()3830 NumberFormatTest::TestCurrencyIsoPluralFormat() {
3831     static const char* DATA[][6] = {
3832         // the data are:
3833         // locale,
3834         // currency amount to be formatted,
3835         // currency ISO code to be formatted,
3836         // format result using CURRENCYSTYLE,
3837         // format result using ISOCURRENCYSTYLE,
3838         // format result using PLURALCURRENCYSTYLE,
3839 
3840         {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3841         {"en_US", "1234.56", "USD", "$1,234.56", "USD\\u00A01,234.56", "1,234.56 US dollars"},
3842         {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD\\u00A01,234.56", "-1,234.56 US dollars"},
3843         {"zh_CN", "1", "USD", "US$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7F8E\\u5143"},
3844         {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD\\u00A01,234.56", "1,234.56\\u00A0\\u7F8E\\u5143"},
3845         {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A01.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3846         {"zh_CN", "1234.56", "CNY", "\\u00A51,234.56", "CNY\\u00A01,234.56", "1,234.56\\u00A0\\u4EBA\\u6C11\\u5E01"},
3847         {"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"},
3848         {"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"},
3849         {"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"},
3850         // test locale without currency information
3851         {"root", "-1.23", "USD", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"},
3852         // test choice format
3853         {"es_AR", "1", "INR", "INR\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"},
3854     };
3855     static const UNumberFormatStyle currencyStyles[] = {
3856         UNUM_CURRENCY,
3857         UNUM_CURRENCY_ISO,
3858         UNUM_CURRENCY_PLURAL
3859     };
3860 
3861     for (int32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3862       const char* localeString = DATA[i][0];
3863       double numberToBeFormat = atof(DATA[i][1]);
3864       const char* currencyISOCode = DATA[i][2];
3865       logln(UnicodeString(u"Locale: ") + localeString + "; amount: " + numberToBeFormat);
3866       Locale locale(localeString);
3867       for (int32_t kIndex = 0; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3868         UNumberFormatStyle k = currencyStyles[kIndex];
3869         logln(UnicodeString(u"UNumberFormatStyle: ") + k);
3870         UErrorCode status = U_ZERO_ERROR;
3871         NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3872         if (U_FAILURE(status)) {
3873             delete numFmt;
3874             dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3875             continue;
3876         }
3877         UChar currencyCode[4];
3878         u_charsToUChars(currencyISOCode, currencyCode, 4);
3879         numFmt->setCurrency(currencyCode, status);
3880         if (U_FAILURE(status)) {
3881             delete numFmt;
3882             errln((UnicodeString)"can not set currency:" + currencyISOCode);
3883             continue;
3884         }
3885 
3886         UnicodeString strBuf;
3887         numFmt->format(numberToBeFormat, strBuf);
3888         int resultDataIndex = 3 + kIndex;
3889         // DATA[i][resultDataIndex] is the currency format result
3890         // using 'k' currency style.
3891         UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
3892         if (strBuf.compare(formatResult)) {
3893             errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
3894         }
3895         // test parsing, and test parsing for all currency formats.
3896         // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3897         numFmt->setLenient(TRUE);
3898         for (int j = 3; j < 6; ++j) {
3899             // DATA[i][3] is the currency format result using
3900             // CURRENCYSTYLE formatter.
3901             // DATA[i][4] is the currency format result using
3902             // ISOCURRENCYSTYLE formatter.
3903             // DATA[i][5] is the currency format result using
3904             // PLURALCURRENCYSTYLE formatter.
3905             UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
3906             UErrorCode status = U_ZERO_ERROR;
3907             Formattable parseResult;
3908             numFmt->parse(oneCurrencyFormatResult, parseResult, status);
3909             if (U_FAILURE(status) ||
3910                 (parseResult.getType() == Formattable::kDouble &&
3911                  parseResult.getDouble() != numberToBeFormat) ||
3912                 (parseResult.getType() == Formattable::kLong &&
3913                  parseResult.getLong() != numberToBeFormat)) {
3914                 errln((UnicodeString)"FAIL: getCurrencyFormat of locale " +
3915                       localeString + " failed roundtripping the number");
3916                 if (parseResult.getType() == Formattable::kDouble) {
3917                     errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getDouble());
3918                 } else {
3919                     errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getLong());
3920                 }
3921             }
3922         }
3923         delete numFmt;
3924       }
3925     }
3926 }
3927 
3928 void
TestCurrencyParsing()3929 NumberFormatTest::TestCurrencyParsing() {
3930     static const char* DATA[][6] = {
3931         // the data are:
3932         // locale,
3933         // currency amount to be formatted,
3934         // currency ISO code to be formatted,
3935         // format result using CURRENCYSTYLE,
3936         // format result using ISOCURRENCYSTYLE,
3937         // format result using PLURALCURRENCYSTYLE,
3938         {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3939         {"pa_IN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\u0a2f\\u0a42.\\u0a10\\u0a38. \\u0a21\\u0a3e\\u0a32\\u0a30"},
3940         {"es_AR", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 d\\u00f3lar estadounidense"},
3941         {"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"},
3942         {"fa_CA", "1", "USD", "\\u200e$\\u06f1\\u066b\\u06f0\\u06f0", "\\u200eUSD\\u06f1\\u066b\\u06f0\\u06f0", "\\u06f1\\u066b\\u06f0\\u06f0 \\u062f\\u0644\\u0627\\u0631 \\u0622\\u0645\\u0631\\u06cc\\u06a9\\u0627"},
3943         {"he_IL", "1", "USD", "\\u200f1.00\\u00a0$", "\\u200f1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
3944         {"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 ameri\\u010Dkih dolara"},
3945         {"id_ID", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 Dolar Amerika Serikat"},
3946         {"it_IT", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 dollari statunitensi"},
3947         {"ko_KR", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
3948         {"ja_JP", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7c73\\u30c9\\u30eb"},
3949         {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A001.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3950         {"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3951         {"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3952         {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1 \\u65E5\\u5713"},
3953         {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3954         // ICU 62 requires #parseCurrency() to recognize variants when parsing
3955         // {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3956         {"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"}
3957     };
3958     static const UNumberFormatStyle currencyStyles[] = {
3959         UNUM_CURRENCY,
3960         UNUM_CURRENCY_ISO,
3961         UNUM_CURRENCY_PLURAL
3962     };
3963     static const char* currencyStyleNames[] = {
3964       "UNUM_CURRENCY",
3965       "UNUM_CURRENCY_ISO",
3966       "UNUM_CURRENCY_PLURAL"
3967     };
3968 
3969 #ifdef NUMFMTST_CACHE_DEBUG
3970 int deadloop = 0;
3971 for (;;) {
3972     printf("loop: %d\n", deadloop++);
3973 #endif
3974     for (uint32_t i=0; i< UPRV_LENGTHOF(DATA); ++i) {  /* i = test case #  - should be i=0*/
3975       for (int32_t kIndex = 2; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3976         UNumberFormatStyle k = currencyStyles[kIndex]; /* k = style */
3977         const char* localeString = DATA[i][0];
3978         double numberToBeFormat = atof(DATA[i][1]);
3979         const char* currencyISOCode = DATA[i][2];
3980         Locale locale(localeString);
3981         UErrorCode status = U_ZERO_ERROR;
3982         NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3983         logln("#%d NumberFormat(%s, %s) Currency=%s\n",
3984               i, localeString, currencyStyleNames[kIndex],
3985               currencyISOCode);
3986 
3987         if (U_FAILURE(status)) {
3988             delete numFmt;
3989             dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3990             continue;
3991         }
3992         UChar currencyCode[4];
3993         u_charsToUChars(currencyISOCode, currencyCode, 4);
3994         numFmt->setCurrency(currencyCode, status);
3995         if (U_FAILURE(status)) {
3996             delete numFmt;
3997             errln((UnicodeString)"can not set currency:" + currencyISOCode);
3998             continue;
3999         }
4000 
4001         UnicodeString strBuf;
4002         numFmt->format(numberToBeFormat, strBuf);
4003         int resultDataIndex = 3 + kIndex;
4004         // DATA[i][resultDataIndex] is the currency format result
4005         // using 'k' currency style.
4006         UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
4007         if (strBuf.compare(formatResult)) {
4008             errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
4009         }
4010         // test parsing, and test parsing for all currency formats.
4011         // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
4012         numFmt->setLenient(TRUE);
4013         for (int j = 3; j < 6; ++j) {
4014             // DATA[i][3] is the currency format result using
4015             // CURRENCYSTYLE formatter.
4016             // DATA[i][4] is the currency format result using
4017             // ISOCURRENCYSTYLE formatter.
4018             // DATA[i][5] is the currency format result using
4019             // PLURALCURRENCYSTYLE formatter.
4020             UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
4021             UErrorCode status = U_ZERO_ERROR;
4022             Formattable parseResult;
4023             logln("parse(%s)", DATA[i][j]);
4024             numFmt->parse(oneCurrencyFormatResult, parseResult, status);
4025             if (U_FAILURE(status) ||
4026                 (parseResult.getType() == Formattable::kDouble &&
4027                  parseResult.getDouble() != numberToBeFormat) ||
4028                 (parseResult.getType() == Formattable::kLong &&
4029                  parseResult.getLong() != numberToBeFormat)) {
4030                 errln((UnicodeString)"FAIL: NumberFormat(" + localeString +", " + currencyStyleNames[kIndex] +
4031                       "), Currency="+currencyISOCode+", parse("+DATA[i][j]+") returned error " + (UnicodeString)u_errorName(status)+".  Testcase: data[" + i + "][" + currencyStyleNames[j-3] +"="+j+"]");
4032                 if (parseResult.getType() == Formattable::kDouble) {
4033                     errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (double): " +parseResult.getDouble());
4034                 } else {
4035                     errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (long): " +parseResult.getLong());
4036                 }
4037                 errln((UnicodeString)" round-trip would be: " + strBuf);
4038             }
4039         }
4040         delete numFmt;
4041       }
4042     }
4043 #ifdef NUMFMTST_CACHE_DEBUG
4044 }
4045 #endif
4046 }
4047 
4048 
4049 void
TestParseCurrencyInUCurr()4050 NumberFormatTest::TestParseCurrencyInUCurr() {
4051     const char* DATA[] = {
4052         "1.00 US DOLLAR",  // case in-sensitive
4053         "$1.00",
4054         "USD1.00",
4055         "usd1.00", // case in-sensitive: #13696
4056         "US dollar1.00",
4057         "US dollars1.00",
4058         "$1.00",
4059         "A$1.00",
4060         "ADP1.00",
4061         "ADP1.00",
4062         "AED1.00",
4063         "AED1.00",
4064         "AFA1.00",
4065         "AFA1.00",
4066         "AFN1.00",
4067         "ALL1.00",
4068         "AMD1.00",
4069         "ANG1.00",
4070         "AOA1.00",
4071         "AOK1.00",
4072         "AOK1.00",
4073         "AON1.00",
4074         "AON1.00",
4075         "AOR1.00",
4076         "AOR1.00",
4077         "ARS1.00",
4078         "ARA1.00",
4079         "ARA1.00",
4080         "ARP1.00",
4081         "ARP1.00",
4082         "ARS1.00",
4083         "ATS1.00",
4084         "ATS1.00",
4085         "AUD1.00",
4086         "AWG1.00",
4087         "AZM1.00",
4088         "AZM1.00",
4089         "AZN1.00",
4090         "Afghan Afghani (1927\\u20132002)1.00",
4091         "Afghan afghani (1927\\u20132002)1.00",
4092         "Afghan Afghani1.00",
4093         "Afghan Afghanis1.00",
4094         "Albanian Lek1.00",
4095         "Albanian lek1.00",
4096         "Albanian lek\\u00eb1.00",
4097         "Algerian Dinar1.00",
4098         "Algerian dinar1.00",
4099         "Algerian dinars1.00",
4100         "Andorran Peseta1.00",
4101         "Andorran peseta1.00",
4102         "Andorran pesetas1.00",
4103         "Angolan Kwanza (1977\\u20131991)1.00",
4104         "Angolan Readjusted Kwanza (1995\\u20131999)1.00",
4105         "Angolan Kwanza1.00",
4106         "Angolan New Kwanza (1990\\u20132000)1.00",
4107         "Angolan kwanza (1977\\u20131991)1.00",
4108         "Angolan readjusted kwanza (1995\\u20131999)1.00",
4109         "Angolan kwanza1.00",
4110         "Angolan kwanzas (1977\\u20131991)1.00",
4111         "Angolan readjusted kwanzas (1995\\u20131999)1.00",
4112         "Angolan kwanzas1.00",
4113         "Angolan new kwanza (1990\\u20132000)1.00",
4114         "Angolan new kwanzas (1990\\u20132000)1.00",
4115         "Argentine Austral1.00",
4116         "Argentine Peso (1983\\u20131985)1.00",
4117         "Argentine Peso1.00",
4118         "Argentine austral1.00",
4119         "Argentine australs1.00",
4120         "Argentine peso (1983\\u20131985)1.00",
4121         "Argentine peso1.00",
4122         "Argentine pesos (1983\\u20131985)1.00",
4123         "Argentine pesos1.00",
4124         "Armenian Dram1.00",
4125         "Armenian dram1.00",
4126         "Armenian drams1.00",
4127         "Aruban Florin1.00",
4128         "Aruban florin1.00",
4129         "Australian Dollar1.00",
4130         "Australian dollar1.00",
4131         "Australian dollars1.00",
4132         "Austrian Schilling1.00",
4133         "Austrian schilling1.00",
4134         "Austrian schillings1.00",
4135         "Azerbaijani Manat (1993\\u20132006)1.00",
4136         "Azerbaijani Manat1.00",
4137         "Azerbaijani manat (1993\\u20132006)1.00",
4138         "Azerbaijani manat1.00",
4139         "Azerbaijani manats (1993\\u20132006)1.00",
4140         "Azerbaijani manats1.00",
4141         "BAD1.00",
4142         "BAD1.00",
4143         "BAM1.00",
4144         "BBD1.00",
4145         "BDT1.00",
4146         "BEC1.00",
4147         "BEC1.00",
4148         "BEF1.00",
4149         "BEL1.00",
4150         "BEL1.00",
4151         "BGL1.00",
4152         "BGN1.00",
4153         "BGN1.00",
4154         "BHD1.00",
4155         "BIF1.00",
4156         "BMD1.00",
4157         "BND1.00",
4158         "BOB1.00",
4159         "BOP1.00",
4160         "BOP1.00",
4161         "BOV1.00",
4162         "BOV1.00",
4163         "BRB1.00",
4164         "BRB1.00",
4165         "BRC1.00",
4166         "BRC1.00",
4167         "BRE1.00",
4168         "BRE1.00",
4169         "BRL1.00",
4170         "BRN1.00",
4171         "BRN1.00",
4172         "BRR1.00",
4173         "BRR1.00",
4174         "BSD1.00",
4175         "BSD1.00",
4176         "BTN1.00",
4177         "BUK1.00",
4178         "BUK1.00",
4179         "BWP1.00",
4180         "BYB1.00",
4181         "BYB1.00",
4182         "BYR1.00",
4183         "BZD1.00",
4184         "Bahamian Dollar1.00",
4185         "Bahamian dollar1.00",
4186         "Bahamian dollars1.00",
4187         "Bahraini Dinar1.00",
4188         "Bahraini dinar1.00",
4189         "Bahraini dinars1.00",
4190         "Bangladeshi Taka1.00",
4191         "Bangladeshi taka1.00",
4192         "Bangladeshi takas1.00",
4193         "Barbadian Dollar1.00",
4194         "Barbadian dollar1.00",
4195         "Barbadian dollars1.00",
4196         "Belarusian Ruble (1994\\u20131999)1.00",
4197         "Belarusian Ruble1.00",
4198         "Belarusian ruble (1994\\u20131999)1.00",
4199         "Belarusian rubles (1994\\u20131999)1.00",
4200         "Belarusian ruble1.00",
4201         "Belarusian rubles1.00",
4202         "Belgian Franc (convertible)1.00",
4203         "Belgian Franc (financial)1.00",
4204         "Belgian Franc1.00",
4205         "Belgian franc (convertible)1.00",
4206         "Belgian franc (financial)1.00",
4207         "Belgian franc1.00",
4208         "Belgian francs (convertible)1.00",
4209         "Belgian francs (financial)1.00",
4210         "Belgian francs1.00",
4211         "Belize Dollar1.00",
4212         "Belize dollar1.00",
4213         "Belize dollars1.00",
4214         "Bermudan Dollar1.00",
4215         "Bermudan dollar1.00",
4216         "Bermudan dollars1.00",
4217         "Bhutanese Ngultrum1.00",
4218         "Bhutanese ngultrum1.00",
4219         "Bhutanese ngultrums1.00",
4220         "Bolivian Mvdol1.00",
4221         "Bolivian Peso1.00",
4222         "Bolivian mvdol1.00",
4223         "Bolivian mvdols1.00",
4224         "Bolivian peso1.00",
4225         "Bolivian pesos1.00",
4226         "Bolivian Boliviano1.00",
4227         "Bolivian Boliviano1.00",
4228         "Bolivian Bolivianos1.00",
4229         "Bosnia-Herzegovina Convertible Mark1.00",
4230         "Bosnia-Herzegovina Dinar (1992\\u20131994)1.00",
4231         "Bosnia-Herzegovina convertible mark1.00",
4232         "Bosnia-Herzegovina convertible marks1.00",
4233         "Bosnia-Herzegovina dinar (1992\\u20131994)1.00",
4234         "Bosnia-Herzegovina dinars (1992\\u20131994)1.00",
4235         "Botswanan Pula1.00",
4236         "Botswanan pula1.00",
4237         "Botswanan pulas1.00",
4238         "Brazilian New Cruzado (1989\\u20131990)1.00",
4239         "Brazilian Cruzado (1986\\u20131989)1.00",
4240         "Brazilian Cruzeiro (1990\\u20131993)1.00",
4241         "Brazilian New Cruzeiro (1967\\u20131986)1.00",
4242         "Brazilian Cruzeiro (1993\\u20131994)1.00",
4243         "Brazilian Real1.00",
4244         "Brazilian new cruzado (1989\\u20131990)1.00",
4245         "Brazilian new cruzados (1989\\u20131990)1.00",
4246         "Brazilian cruzado (1986\\u20131989)1.00",
4247         "Brazilian cruzados (1986\\u20131989)1.00",
4248         "Brazilian cruzeiro (1990\\u20131993)1.00",
4249         "Brazilian new cruzeiro (1967\\u20131986)1.00",
4250         "Brazilian cruzeiro (1993\\u20131994)1.00",
4251         "Brazilian cruzeiros (1990\\u20131993)1.00",
4252         "Brazilian new cruzeiros (1967\\u20131986)1.00",
4253         "Brazilian cruzeiros (1993\\u20131994)1.00",
4254         "Brazilian real1.00",
4255         "Brazilian reals1.00",
4256         "British Pound1.00",
4257         "British pound1.00",
4258         "British pounds1.00",
4259         "Brunei Dollar1.00",
4260         "Brunei dollar1.00",
4261         "Brunei dollars1.00",
4262         "Bulgarian Hard Lev1.00",
4263         "Bulgarian Lev1.00",
4264         "Bulgarian Leva1.00",
4265         "Bulgarian hard lev1.00",
4266         "Bulgarian hard leva1.00",
4267         "Bulgarian lev1.00",
4268         "Burmese Kyat1.00",
4269         "Burmese kyat1.00",
4270         "Burmese kyats1.00",
4271         "Burundian Franc1.00",
4272         "Burundian franc1.00",
4273         "Burundian francs1.00",
4274         "CA$1.00",
4275         "CAD1.00",
4276         "CDF1.00",
4277         "CDF1.00",
4278         "West African CFA Franc1.00",
4279         "Central African CFA Franc1.00",
4280         "West African CFA franc1.00",
4281         "Central African CFA franc1.00",
4282         "West African CFA francs1.00",
4283         "Central African CFA francs1.00",
4284         "CFP Franc1.00",
4285         "CFP franc1.00",
4286         "CFP francs1.00",
4287         "CFPF1.00",
4288         "CHE1.00",
4289         "CHE1.00",
4290         "CHF1.00",
4291         "CHW1.00",
4292         "CHW1.00",
4293         "CLF1.00",
4294         "CLF1.00",
4295         "CLP1.00",
4296         "CNY1.00",
4297         "COP1.00",
4298         "COU1.00",
4299         "COU1.00",
4300         "CRC1.00",
4301         "CSD1.00",
4302         "CSD1.00",
4303         "CSK1.00",
4304         "CSK1.00",
4305         "CUP1.00",
4306         "CUP1.00",
4307         "CVE1.00",
4308         "CYP1.00",
4309         "CZK1.00",
4310         "Cambodian Riel1.00",
4311         "Cambodian riel1.00",
4312         "Cambodian riels1.00",
4313         "Canadian Dollar1.00",
4314         "Canadian dollar1.00",
4315         "Canadian dollars1.00",
4316         "Cape Verdean Escudo1.00",
4317         "Cape Verdean escudo1.00",
4318         "Cape Verdean escudos1.00",
4319         "Cayman Islands Dollar1.00",
4320         "Cayman Islands dollar1.00",
4321         "Cayman Islands dollars1.00",
4322         "Chilean Peso1.00",
4323         "Chilean Unit of Account (UF)1.00",
4324         "Chilean peso1.00",
4325         "Chilean pesos1.00",
4326         "Chilean unit of account (UF)1.00",
4327         "Chilean units of account (UF)1.00",
4328         "Chinese Yuan1.00",
4329         "Chinese yuan1.00",
4330         "Colombian Peso1.00",
4331         "Colombian peso1.00",
4332         "Colombian pesos1.00",
4333         "Comorian Franc1.00",
4334         "Comorian franc1.00",
4335         "Comorian francs1.00",
4336         "Congolese Franc1.00",
4337         "Congolese franc1.00",
4338         "Congolese francs1.00",
4339         "Costa Rican Col\\u00f3n1.00",
4340         "Costa Rican col\\u00f3n1.00",
4341         "Costa Rican col\\u00f3ns1.00",
4342         "Croatian Dinar1.00",
4343         "Croatian Kuna1.00",
4344         "Croatian dinar1.00",
4345         "Croatian dinars1.00",
4346         "Croatian kuna1.00",
4347         "Croatian kunas1.00",
4348         "Cuban Peso1.00",
4349         "Cuban peso1.00",
4350         "Cuban pesos1.00",
4351         "Cypriot Pound1.00",
4352         "Cypriot pound1.00",
4353         "Cypriot pounds1.00",
4354         "Czech Koruna1.00",
4355         "Czech koruna1.00",
4356         "Czech korunas1.00",
4357         "Czechoslovak Hard Koruna1.00",
4358         "Czechoslovak hard koruna1.00",
4359         "Czechoslovak hard korunas1.00",
4360         "DDM1.00",
4361         "DDM1.00",
4362         "DEM1.00",
4363         "DEM1.00",
4364         "DJF1.00",
4365         "DKK1.00",
4366         "DOP1.00",
4367         "DZD1.00",
4368         "Danish Krone1.00",
4369         "Danish krone1.00",
4370         "Danish kroner1.00",
4371         "German Mark1.00",
4372         "German mark1.00",
4373         "German marks1.00",
4374         "Djiboutian Franc1.00",
4375         "Djiboutian franc1.00",
4376         "Djiboutian francs1.00",
4377         "Dominican Peso1.00",
4378         "Dominican peso1.00",
4379         "Dominican pesos1.00",
4380         "EC$1.00",
4381         "ECS1.00",
4382         "ECS1.00",
4383         "ECV1.00",
4384         "ECV1.00",
4385         "EEK1.00",
4386         "EEK1.00",
4387         "EGP1.00",
4388         "EGP1.00",
4389         "ERN1.00",
4390         "ERN1.00",
4391         "ESA1.00",
4392         "ESA1.00",
4393         "ESB1.00",
4394         "ESB1.00",
4395         "ESP1.00",
4396         "ETB1.00",
4397         "EUR1.00",
4398         "East Caribbean Dollar1.00",
4399         "East Caribbean dollar1.00",
4400         "East Caribbean dollars1.00",
4401         "East German Mark1.00",
4402         "East German mark1.00",
4403         "East German marks1.00",
4404         "Ecuadorian Sucre1.00",
4405         "Ecuadorian Unit of Constant Value1.00",
4406         "Ecuadorian sucre1.00",
4407         "Ecuadorian sucres1.00",
4408         "Ecuadorian unit of constant value1.00",
4409         "Ecuadorian units of constant value1.00",
4410         "Egyptian Pound1.00",
4411         "Egyptian pound1.00",
4412         "Egyptian pounds1.00",
4413         "Salvadoran Col\\u00f3n1.00",
4414         "Salvadoran col\\u00f3n1.00",
4415         "Salvadoran colones1.00",
4416         "Equatorial Guinean Ekwele1.00",
4417         "Equatorial Guinean ekwele1.00",
4418         "Eritrean Nakfa1.00",
4419         "Eritrean nakfa1.00",
4420         "Eritrean nakfas1.00",
4421         "Estonian Kroon1.00",
4422         "Estonian kroon1.00",
4423         "Estonian kroons1.00",
4424         "Ethiopian Birr1.00",
4425         "Ethiopian birr1.00",
4426         "Ethiopian birrs1.00",
4427         "Euro1.00",
4428         "European Composite Unit1.00",
4429         "European Currency Unit1.00",
4430         "European Monetary Unit1.00",
4431         "European Unit of Account (XBC)1.00",
4432         "European Unit of Account (XBD)1.00",
4433         "European composite unit1.00",
4434         "European composite units1.00",
4435         "European currency unit1.00",
4436         "European currency units1.00",
4437         "European monetary unit1.00",
4438         "European monetary units1.00",
4439         "European unit of account (XBC)1.00",
4440         "European unit of account (XBD)1.00",
4441         "European units of account (XBC)1.00",
4442         "European units of account (XBD)1.00",
4443         "FIM1.00",
4444         "FIM1.00",
4445         "FJD1.00",
4446         "FKP1.00",
4447         "FKP1.00",
4448         "FRF1.00",
4449         "FRF1.00",
4450         "Falkland Islands Pound1.00",
4451         "Falkland Islands pound1.00",
4452         "Falkland Islands pounds1.00",
4453         "Fijian Dollar1.00",
4454         "Fijian dollar1.00",
4455         "Fijian dollars1.00",
4456         "Finnish Markka1.00",
4457         "Finnish markka1.00",
4458         "Finnish markkas1.00",
4459         "CHF1.00",
4460         "French Franc1.00",
4461         "French Gold Franc1.00",
4462         "French UIC-Franc1.00",
4463         "French UIC-franc1.00",
4464         "French UIC-francs1.00",
4465         "French franc1.00",
4466         "French francs1.00",
4467         "French gold franc1.00",
4468         "French gold francs1.00",
4469         "GBP1.00",
4470         "GEK1.00",
4471         "GEK1.00",
4472         "GEL1.00",
4473         "GHC1.00",
4474         "GHC1.00",
4475         "GHS1.00",
4476         "GIP1.00",
4477         "GIP1.00",
4478         "GMD1.00",
4479         "GMD1.00",
4480         "GNF1.00",
4481         "GNS1.00",
4482         "GNS1.00",
4483         "GQE1.00",
4484         "GQE1.00",
4485         "GRD1.00",
4486         "GRD1.00",
4487         "GTQ1.00",
4488         "GWE1.00",
4489         "GWE1.00",
4490         "GWP1.00",
4491         "GWP1.00",
4492         "GYD1.00",
4493         "Gambian Dalasi1.00",
4494         "Gambian dalasi1.00",
4495         "Gambian dalasis1.00",
4496         "Georgian Kupon Larit1.00",
4497         "Georgian Lari1.00",
4498         "Georgian kupon larit1.00",
4499         "Georgian kupon larits1.00",
4500         "Georgian lari1.00",
4501         "Georgian laris1.00",
4502         "Ghanaian Cedi (1979\\u20132007)1.00",
4503         "Ghanaian Cedi1.00",
4504         "Ghanaian cedi (1979\\u20132007)1.00",
4505         "Ghanaian cedi1.00",
4506         "Ghanaian cedis (1979\\u20132007)1.00",
4507         "Ghanaian cedis1.00",
4508         "Gibraltar Pound1.00",
4509         "Gibraltar pound1.00",
4510         "Gibraltar pounds1.00",
4511         "Gold1.00",
4512         "Gold1.00",
4513         "Greek Drachma1.00",
4514         "Greek drachma1.00",
4515         "Greek drachmas1.00",
4516         "Guatemalan Quetzal1.00",
4517         "Guatemalan quetzal1.00",
4518         "Guatemalan quetzals1.00",
4519         "Guinean Franc1.00",
4520         "Guinean Syli1.00",
4521         "Guinean franc1.00",
4522         "Guinean francs1.00",
4523         "Guinean syli1.00",
4524         "Guinean sylis1.00",
4525         "Guinea-Bissau Peso1.00",
4526         "Guinea-Bissau peso1.00",
4527         "Guinea-Bissau pesos1.00",
4528         "Guyanaese Dollar1.00",
4529         "Guyanaese dollar1.00",
4530         "Guyanaese dollars1.00",
4531         "HK$1.00",
4532         "HKD1.00",
4533         "HNL1.00",
4534         "HRD1.00",
4535         "HRD1.00",
4536         "HRK1.00",
4537         "HRK1.00",
4538         "HTG1.00",
4539         "HTG1.00",
4540         "HUF1.00",
4541         "Haitian Gourde1.00",
4542         "Haitian gourde1.00",
4543         "Haitian gourdes1.00",
4544         "Honduran Lempira1.00",
4545         "Honduran lempira1.00",
4546         "Honduran lempiras1.00",
4547         "Hong Kong Dollar1.00",
4548         "Hong Kong dollar1.00",
4549         "Hong Kong dollars1.00",
4550         "Hungarian Forint1.00",
4551         "Hungarian forint1.00",
4552         "Hungarian forints1.00",
4553         "IDR1.00",
4554         "IEP1.00",
4555         "ILP1.00",
4556         "ILP1.00",
4557         "ILS1.00",
4558         "INR1.00",
4559         "IQD1.00",
4560         "IRR1.00",
4561         "ISK1.00",
4562         "ISK1.00",
4563         "ITL1.00",
4564         "Icelandic Kr\\u00f3na1.00",
4565         "Icelandic kr\\u00f3na1.00",
4566         "Icelandic kr\\u00f3nur1.00",
4567         "Indian Rupee1.00",
4568         "Indian rupee1.00",
4569         "Indian rupees1.00",
4570         "Indonesian Rupiah1.00",
4571         "Indonesian rupiah1.00",
4572         "Indonesian rupiahs1.00",
4573         "Iranian Rial1.00",
4574         "Iranian rial1.00",
4575         "Iranian rials1.00",
4576         "Iraqi Dinar1.00",
4577         "Iraqi dinar1.00",
4578         "Iraqi dinars1.00",
4579         "Irish Pound1.00",
4580         "Irish pound1.00",
4581         "Irish pounds1.00",
4582         "Israeli Pound1.00",
4583         "Israeli new shekel1.00",
4584         "Israeli pound1.00",
4585         "Israeli pounds1.00",
4586         "Italian Lira1.00",
4587         "Italian lira1.00",
4588         "Italian liras1.00",
4589         "JMD1.00",
4590         "JOD1.00",
4591         "JPY1.00",
4592         "Jamaican Dollar1.00",
4593         "Jamaican dollar1.00",
4594         "Jamaican dollars1.00",
4595         "Japanese Yen1.00",
4596         "Japanese yen1.00",
4597         "Jordanian Dinar1.00",
4598         "Jordanian dinar1.00",
4599         "Jordanian dinars1.00",
4600         "KES1.00",
4601         "KGS1.00",
4602         "KHR1.00",
4603         "KMF1.00",
4604         "KPW1.00",
4605         "KPW1.00",
4606         "KRW1.00",
4607         "KWD1.00",
4608         "KYD1.00",
4609         "KYD1.00",
4610         "KZT1.00",
4611         "Kazakhstani Tenge1.00",
4612         "Kazakhstani tenge1.00",
4613         "Kazakhstani tenges1.00",
4614         "Kenyan Shilling1.00",
4615         "Kenyan shilling1.00",
4616         "Kenyan shillings1.00",
4617         "Kuwaiti Dinar1.00",
4618         "Kuwaiti dinar1.00",
4619         "Kuwaiti dinars1.00",
4620         "Kyrgystani Som1.00",
4621         "Kyrgystani som1.00",
4622         "Kyrgystani soms1.00",
4623         "HNL1.00",
4624         "LAK1.00",
4625         "LAK1.00",
4626         "LBP1.00",
4627         "LKR1.00",
4628         "LRD1.00",
4629         "LRD1.00",
4630         "LSL1.00",
4631         "LTL1.00",
4632         "LTL1.00",
4633         "LTT1.00",
4634         "LTT1.00",
4635         "LUC1.00",
4636         "LUC1.00",
4637         "LUF1.00",
4638         "LUF1.00",
4639         "LUL1.00",
4640         "LUL1.00",
4641         "LVL1.00",
4642         "LVL1.00",
4643         "LVR1.00",
4644         "LVR1.00",
4645         "LYD1.00",
4646         "Laotian Kip1.00",
4647         "Laotian kip1.00",
4648         "Laotian kips1.00",
4649         "Latvian Lats1.00",
4650         "Latvian Ruble1.00",
4651         "Latvian lats1.00",
4652         "Latvian lati1.00",
4653         "Latvian ruble1.00",
4654         "Latvian rubles1.00",
4655         "Lebanese Pound1.00",
4656         "Lebanese pound1.00",
4657         "Lebanese pounds1.00",
4658         "Lesotho Loti1.00",
4659         "Lesotho loti1.00",
4660         "Lesotho lotis1.00",
4661         "Liberian Dollar1.00",
4662         "Liberian dollar1.00",
4663         "Liberian dollars1.00",
4664         "Libyan Dinar1.00",
4665         "Libyan dinar1.00",
4666         "Libyan dinars1.00",
4667         "Lithuanian Litas1.00",
4668         "Lithuanian Talonas1.00",
4669         "Lithuanian litas1.00",
4670         "Lithuanian litai1.00",
4671         "Lithuanian talonas1.00",
4672         "Lithuanian talonases1.00",
4673         "Luxembourgian Convertible Franc1.00",
4674         "Luxembourg Financial Franc1.00",
4675         "Luxembourgian Franc1.00",
4676         "Luxembourgian convertible franc1.00",
4677         "Luxembourgian convertible francs1.00",
4678         "Luxembourg financial franc1.00",
4679         "Luxembourg financial francs1.00",
4680         "Luxembourgian franc1.00",
4681         "Luxembourgian francs1.00",
4682         "MAD1.00",
4683         "MAD1.00",
4684         "MAF1.00",
4685         "MAF1.00",
4686         "MDL1.00",
4687         "MDL1.00",
4688         "MX$1.00",
4689         "MGA1.00",
4690         "MGA1.00",
4691         "MGF1.00",
4692         "MGF1.00",
4693         "MKD1.00",
4694         "MLF1.00",
4695         "MLF1.00",
4696         "MMK1.00",
4697         "MMK1.00",
4698         "MNT1.00",
4699         "MOP1.00",
4700         "MOP1.00",
4701         "MRO1.00",
4702         "MTL1.00",
4703         "MTP1.00",
4704         "MTP1.00",
4705         "MUR1.00",
4706         "MUR1.00",
4707         "MVR1.00",
4708         "MVR1.00",
4709         "MWK1.00",
4710         "MXN1.00",
4711         "MXP1.00",
4712         "MXP1.00",
4713         "MXV1.00",
4714         "MXV1.00",
4715         "MYR1.00",
4716         "MZE1.00",
4717         "MZE1.00",
4718         "MZM1.00",
4719         "MZN1.00",
4720         "Macanese Pataca1.00",
4721         "Macanese pataca1.00",
4722         "Macanese patacas1.00",
4723         "Macedonian Denar1.00",
4724         "Macedonian denar1.00",
4725         "Macedonian denari1.00",
4726         "Malagasy Ariaries1.00",
4727         "Malagasy Ariary1.00",
4728         "Malagasy Ariary1.00",
4729         "Malagasy Franc1.00",
4730         "Malagasy franc1.00",
4731         "Malagasy francs1.00",
4732         "Malawian Kwacha1.00",
4733         "Malawian Kwacha1.00",
4734         "Malawian Kwachas1.00",
4735         "Malaysian Ringgit1.00",
4736         "Malaysian ringgit1.00",
4737         "Malaysian ringgits1.00",
4738         "Maldivian Rufiyaa1.00",
4739         "Maldivian rufiyaa1.00",
4740         "Maldivian rufiyaas1.00",
4741         "Malian Franc1.00",
4742         "Malian franc1.00",
4743         "Malian francs1.00",
4744         "Maltese Lira1.00",
4745         "Maltese Pound1.00",
4746         "Maltese lira1.00",
4747         "Maltese lira1.00",
4748         "Maltese pound1.00",
4749         "Maltese pounds1.00",
4750         "Mauritanian Ouguiya1.00",
4751         "Mauritanian ouguiya1.00",
4752         "Mauritanian ouguiyas1.00",
4753         "Mauritian Rupee1.00",
4754         "Mauritian rupee1.00",
4755         "Mauritian rupees1.00",
4756         "Mexican Peso1.00",
4757         "Mexican Silver Peso (1861\\u20131992)1.00",
4758         "Mexican Investment Unit1.00",
4759         "Mexican peso1.00",
4760         "Mexican pesos1.00",
4761         "Mexican silver peso (1861\\u20131992)1.00",
4762         "Mexican silver pesos (1861\\u20131992)1.00",
4763         "Mexican investment unit1.00",
4764         "Mexican investment units1.00",
4765         "Moldovan Leu1.00",
4766         "Moldovan leu1.00",
4767         "Moldovan lei1.00",
4768         "Mongolian Tugrik1.00",
4769         "Mongolian tugrik1.00",
4770         "Mongolian tugriks1.00",
4771         "Moroccan Dirham1.00",
4772         "Moroccan Franc1.00",
4773         "Moroccan dirham1.00",
4774         "Moroccan dirhams1.00",
4775         "Moroccan franc1.00",
4776         "Moroccan francs1.00",
4777         "Mozambican Escudo1.00",
4778         "Mozambican Metical1.00",
4779         "Mozambican escudo1.00",
4780         "Mozambican escudos1.00",
4781         "Mozambican metical1.00",
4782         "Mozambican meticals1.00",
4783         "Myanmar Kyat1.00",
4784         "Myanmar kyat1.00",
4785         "Myanmar kyats1.00",
4786         "NAD1.00",
4787         "NGN1.00",
4788         "NIC1.00",
4789         "NIO1.00",
4790         "NIO1.00",
4791         "NLG1.00",
4792         "NLG1.00",
4793         "NOK1.00",
4794         "NPR1.00",
4795         "NT$1.00",
4796         "NZ$1.00",
4797         "NZD1.00",
4798         "Namibian Dollar1.00",
4799         "Namibian dollar1.00",
4800         "Namibian dollars1.00",
4801         "Nepalese Rupee1.00",
4802         "Nepalese rupee1.00",
4803         "Nepalese rupees1.00",
4804         "Netherlands Antillean Guilder1.00",
4805         "Netherlands Antillean guilder1.00",
4806         "Netherlands Antillean guilders1.00",
4807         "Dutch Guilder1.00",
4808         "Dutch guilder1.00",
4809         "Dutch guilders1.00",
4810         "Israeli New Shekel1.00",
4811         "Israeli New Shekels1.00",
4812         "New Zealand Dollar1.00",
4813         "New Zealand dollar1.00",
4814         "New Zealand dollars1.00",
4815         "Nicaraguan C\\u00f3rdoba1.00",
4816         "Nicaraguan C\\u00f3rdoba (1988\\u20131991)1.00",
4817         "Nicaraguan c\\u00f3rdoba1.00",
4818         "Nicaraguan c\\u00f3rdobas1.00",
4819         "Nicaraguan c\\u00f3rdoba (1988\\u20131991)1.00",
4820         "Nicaraguan c\\u00f3rdobas (1988\\u20131991)1.00",
4821         "Nigerian Naira1.00",
4822         "Nigerian naira1.00",
4823         "Nigerian nairas1.00",
4824         "North Korean Won1.00",
4825         "North Korean won1.00",
4826         "North Korean won1.00",
4827         "Norwegian Krone1.00",
4828         "Norwegian krone1.00",
4829         "Norwegian kroner1.00",
4830         "OMR1.00",
4831         "Mozambican Metical (1980\\u20132006)1.00",
4832         "Mozambican metical (1980\\u20132006)1.00",
4833         "Mozambican meticals (1980\\u20132006)1.00",
4834         "Romanian Lei (1952\\u20132006)1.00",
4835         "Romanian Leu (1952\\u20132006)1.00",
4836         "Romanian leu (1952\\u20132006)1.00",
4837         "Serbian Dinar (2002\\u20132006)1.00",
4838         "Serbian dinar (2002\\u20132006)1.00",
4839         "Serbian dinars (2002\\u20132006)1.00",
4840         "Sudanese Dinar (1992\\u20132007)1.00",
4841         "Sudanese Pound (1957\\u20131998)1.00",
4842         "Sudanese dinar (1992\\u20132007)1.00",
4843         "Sudanese dinars (1992\\u20132007)1.00",
4844         "Sudanese pound (1957\\u20131998)1.00",
4845         "Sudanese pounds (1957\\u20131998)1.00",
4846         "Turkish Lira (1922\\u20132005)1.00",
4847         "Turkish Lira (1922\\u20132005)1.00",
4848         "Omani Rial1.00",
4849         "Omani rial1.00",
4850         "Omani rials1.00",
4851         "PAB1.00",
4852         "PAB1.00",
4853         "PEI1.00",
4854         "PEI1.00",
4855         "PEN1.00",
4856         "PEN1.00",
4857         "PES1.00",
4858         "PES1.00",
4859         "PGK1.00",
4860         "PGK1.00",
4861         "PHP1.00",
4862         "PKR1.00",
4863         "PLN1.00",
4864         "PLZ1.00",
4865         "PLZ1.00",
4866         "PTE1.00",
4867         "PTE1.00",
4868         "PYG1.00",
4869         "Pakistani Rupee1.00",
4870         "Pakistani rupee1.00",
4871         "Pakistani rupees1.00",
4872         "Palladium1.00",
4873         "Palladium1.00",
4874         "Panamanian Balboa1.00",
4875         "Panamanian balboa1.00",
4876         "Panamanian balboas1.00",
4877         "Papua New Guinean Kina1.00",
4878         "Papua New Guinean kina1.00",
4879         "Papua New Guinean kina1.00",
4880         "Paraguayan Guarani1.00",
4881         "Paraguayan guarani1.00",
4882         "Paraguayan guaranis1.00",
4883         "Peruvian Inti1.00",
4884         "Peruvian Sol1.00",
4885         "Peruvian Sol (1863\\u20131965)1.00",
4886         "Peruvian inti1.00",
4887         "Peruvian intis1.00",
4888         "Peruvian sol1.00",
4889         "Peruvian soles1.00",
4890         "Peruvian sol (1863\\u20131965)1.00",
4891         "Peruvian soles (1863\\u20131965)1.00",
4892         "Philippine Piso1.00",
4893         "Philippine piso1.00",
4894         "Philippine pisos1.00",
4895         "Platinum1.00",
4896         "Platinum1.00",
4897         "Polish Zloty (1950\\u20131995)1.00",
4898         "Polish Zloty1.00",
4899         "Polish zlotys1.00",
4900         "Polish zloty (PLZ)1.00",
4901         "Polish zloty1.00",
4902         "Polish zlotys (PLZ)1.00",
4903         "Portuguese Escudo1.00",
4904         "Portuguese Guinea Escudo1.00",
4905         "Portuguese Guinea escudo1.00",
4906         "Portuguese Guinea escudos1.00",
4907         "Portuguese escudo1.00",
4908         "Portuguese escudos1.00",
4909         "GTQ1.00",
4910         "QAR1.00",
4911         "Qatari Rial1.00",
4912         "Qatari rial1.00",
4913         "Qatari rials1.00",
4914         "RHD1.00",
4915         "RHD1.00",
4916         "RINET Funds1.00",
4917         "RINET Funds1.00",
4918         "CN\\u00a51.00",
4919         "ROL1.00",
4920         "ROL1.00",
4921         "RON1.00",
4922         "RON1.00",
4923         "RSD1.00",
4924         "RSD1.00",
4925         "RUB1.00",
4926         "RUR1.00",
4927         "RUR1.00",
4928         "RWF1.00",
4929         "RWF1.00",
4930         "Rhodesian Dollar1.00",
4931         "Rhodesian dollar1.00",
4932         "Rhodesian dollars1.00",
4933         "Romanian Leu1.00",
4934         "Romanian lei1.00",
4935         "Romanian leu1.00",
4936         "Russian Ruble (1991\\u20131998)1.00",
4937         "Russian Ruble1.00",
4938         "Russian ruble (1991\\u20131998)1.00",
4939         "Russian ruble1.00",
4940         "Russian rubles (1991\\u20131998)1.00",
4941         "Russian rubles1.00",
4942         "Rwandan Franc1.00",
4943         "Rwandan franc1.00",
4944         "Rwandan francs1.00",
4945         "SAR1.00",
4946         "SBD1.00",
4947         "SCR1.00",
4948         "SDD1.00",
4949         "SDD1.00",
4950         "SDG1.00",
4951         "SDG1.00",
4952         "SDP1.00",
4953         "SDP1.00",
4954         "SEK1.00",
4955         "SGD1.00",
4956         "SHP1.00",
4957         "SHP1.00",
4958         "SIT1.00",
4959         "SIT1.00",
4960         "SKK1.00",
4961         "SLL1.00",
4962         "SLL1.00",
4963         "SOS1.00",
4964         "SRD1.00",
4965         "SRD1.00",
4966         "SRG1.00",
4967         "STD1.00",
4968         "SUR1.00",
4969         "SUR1.00",
4970         "SVC1.00",
4971         "SVC1.00",
4972         "SYP1.00",
4973         "SZL1.00",
4974         "St. Helena Pound1.00",
4975         "St. Helena pound1.00",
4976         "St. Helena pounds1.00",
4977         "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra1.00",
4978         "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra1.00",
4979         "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras1.00",
4980         "Saudi Riyal1.00",
4981         "Saudi riyal1.00",
4982         "Saudi riyals1.00",
4983         "Serbian Dinar1.00",
4984         "Serbian dinar1.00",
4985         "Serbian dinars1.00",
4986         "Seychellois Rupee1.00",
4987         "Seychellois rupee1.00",
4988         "Seychellois rupees1.00",
4989         "Sierra Leonean Leone1.00",
4990         "Sierra Leonean leone1.00",
4991         "Sierra Leonean leones1.00",
4992         "Silver1.00",
4993         "Silver1.00",
4994         "Singapore Dollar1.00",
4995         "Singapore dollar1.00",
4996         "Singapore dollars1.00",
4997         "Slovak Koruna1.00",
4998         "Slovak koruna1.00",
4999         "Slovak korunas1.00",
5000         "Slovenian Tolar1.00",
5001         "Slovenian tolar1.00",
5002         "Slovenian tolars1.00",
5003         "Solomon Islands Dollar1.00",
5004         "Solomon Islands dollar1.00",
5005         "Solomon Islands dollars1.00",
5006         "Somali Shilling1.00",
5007         "Somali shilling1.00",
5008         "Somali shillings1.00",
5009         "South African Rand (financial)1.00",
5010         "South African Rand1.00",
5011         "South African rand (financial)1.00",
5012         "South African rand1.00",
5013         "South African rands (financial)1.00",
5014         "South African rand1.00",
5015         "South Korean Won1.00",
5016         "South Korean won1.00",
5017         "South Korean won1.00",
5018         "Soviet Rouble1.00",
5019         "Soviet rouble1.00",
5020         "Soviet roubles1.00",
5021         "Spanish Peseta (A account)1.00",
5022         "Spanish Peseta (convertible account)1.00",
5023         "Spanish Peseta1.00",
5024         "Spanish peseta (A account)1.00",
5025         "Spanish peseta (convertible account)1.00",
5026         "Spanish peseta1.00",
5027         "Spanish pesetas (A account)1.00",
5028         "Spanish pesetas (convertible account)1.00",
5029         "Spanish pesetas1.00",
5030         "Special Drawing Rights1.00",
5031         "Sri Lankan Rupee1.00",
5032         "Sri Lankan rupee1.00",
5033         "Sri Lankan rupees1.00",
5034         "Sudanese Pound1.00",
5035         "Sudanese pound1.00",
5036         "Sudanese pounds1.00",
5037         "Surinamese Dollar1.00",
5038         "Surinamese dollar1.00",
5039         "Surinamese dollars1.00",
5040         "Surinamese Guilder1.00",
5041         "Surinamese guilder1.00",
5042         "Surinamese guilders1.00",
5043         "Swazi Lilangeni1.00",
5044         "Swazi lilangeni1.00",
5045         "Swazi emalangeni1.00",
5046         "Swedish Krona1.00",
5047         "Swedish krona1.00",
5048         "Swedish kronor1.00",
5049         "Swiss Franc1.00",
5050         "Swiss franc1.00",
5051         "Swiss francs1.00",
5052         "Syrian Pound1.00",
5053         "Syrian pound1.00",
5054         "Syrian pounds1.00",
5055         "THB1.00",
5056         "TJR1.00",
5057         "TJR1.00",
5058         "TJS1.00",
5059         "TJS1.00",
5060         "TMM1.00",
5061         "TMM1.00",
5062         "TND1.00",
5063         "TND1.00",
5064         "TOP1.00",
5065         "TPE1.00",
5066         "TPE1.00",
5067         "TRL1.00",
5068         "TRY1.00",
5069         "TRY1.00",
5070         "TTD1.00",
5071         "TWD1.00",
5072         "TZS1.00",
5073         "New Taiwan Dollar1.00",
5074         "New Taiwan dollar1.00",
5075         "New Taiwan dollars1.00",
5076         "Tajikistani Ruble1.00",
5077         "Tajikistani Somoni1.00",
5078         "Tajikistani ruble1.00",
5079         "Tajikistani rubles1.00",
5080         "Tajikistani somoni1.00",
5081         "Tajikistani somonis1.00",
5082         "Tanzanian Shilling1.00",
5083         "Tanzanian shilling1.00",
5084         "Tanzanian shillings1.00",
5085         "Testing Currency Code1.00",
5086         "Testing Currency Code1.00",
5087         "Thai Baht1.00",
5088         "Thai baht1.00",
5089         "Thai baht1.00",
5090         "Timorese Escudo1.00",
5091         "Timorese escudo1.00",
5092         "Timorese escudos1.00",
5093         "Tongan Pa\\u02bbanga1.00",
5094         "Tongan pa\\u02bbanga1.00",
5095         "Tongan pa\\u02bbanga1.00",
5096         "Trinidad & Tobago Dollar1.00",
5097         "Trinidad & Tobago dollar1.00",
5098         "Trinidad & Tobago dollars1.00",
5099         "Tunisian Dinar1.00",
5100         "Tunisian dinar1.00",
5101         "Tunisian dinars1.00",
5102         "Turkish Lira1.00",
5103         "Turkish Lira1.00",
5104         "Turkish lira1.00",
5105         "Turkmenistani Manat1.00",
5106         "Turkmenistani manat1.00",
5107         "Turkmenistani manat1.00",
5108         "UAE dirham1.00",
5109         "UAE dirhams1.00",
5110         "UAH1.00",
5111         "UAK1.00",
5112         "UAK1.00",
5113         "UGS1.00",
5114         "UGS1.00",
5115         "UGX1.00",
5116         "US Dollar (Next day)1.00",
5117         "US Dollar (Same day)1.00",
5118         "US Dollar1.00",
5119         "US dollar (next day)1.00",
5120         "US dollar (same day)1.00",
5121         "US dollar1.00",
5122         "US dollars (next day)1.00",
5123         "US dollars (same day)1.00",
5124         "US dollars1.00",
5125         "USD1.00",
5126         "USN1.00",
5127         "USN1.00",
5128         "USS1.00",
5129         "USS1.00",
5130         "UYI1.00",
5131         "UYI1.00",
5132         "UYP1.00",
5133         "UYP1.00",
5134         "UYU1.00",
5135         "UZS1.00",
5136         "UZS1.00",
5137         "Ugandan Shilling (1966\\u20131987)1.00",
5138         "Ugandan Shilling1.00",
5139         "Ugandan shilling (1966\\u20131987)1.00",
5140         "Ugandan shilling1.00",
5141         "Ugandan shillings (1966\\u20131987)1.00",
5142         "Ugandan shillings1.00",
5143         "Ukrainian Hryvnia1.00",
5144         "Ukrainian Karbovanets1.00",
5145         "Ukrainian hryvnia1.00",
5146         "Ukrainian hryvnias1.00",
5147         "Ukrainian karbovanets1.00",
5148         "Ukrainian karbovantsiv1.00",
5149         "Colombian Real Value Unit1.00",
5150         "United Arab Emirates Dirham1.00",
5151         "Unknown Currency1.00",
5152         "Uruguayan Peso (1975\\u20131993)1.00",
5153         "Uruguayan Peso1.00",
5154         "Uruguayan Peso (Indexed Units)1.00",
5155         "Uruguayan peso (1975\\u20131993)1.00",
5156         "Uruguayan peso (indexed units)1.00",
5157         "Uruguayan peso1.00",
5158         "Uruguayan pesos (1975\\u20131993)1.00",
5159         "Uruguayan pesos (indexed units)1.00",
5160         "Uruguayan pesos1.00",
5161         "Uzbekistani Som1.00",
5162         "Uzbekistani som1.00",
5163         "Uzbekistani som1.00",
5164         "VEB1.00",
5165         "VEF1.00",
5166         "VND1.00",
5167         "VUV1.00",
5168         "Vanuatu Vatu1.00",
5169         "Vanuatu vatu1.00",
5170         "Vanuatu vatus1.00",
5171         "Venezuelan Bol\\u00edvar1.00",
5172         "Venezuelan Bol\\u00edvar (1871\\u20132008)1.00",
5173         "Venezuelan bol\\u00edvar1.00",
5174         "Venezuelan bol\\u00edvars1.00",
5175         "Venezuelan bol\\u00edvar (1871\\u20132008)1.00",
5176         "Venezuelan bol\\u00edvars (1871\\u20132008)1.00",
5177         "Vietnamese Dong1.00",
5178         "Vietnamese dong1.00",
5179         "Vietnamese dong1.00",
5180         "WIR Euro1.00",
5181         "WIR Franc1.00",
5182         "WIR euro1.00",
5183         "WIR euros1.00",
5184         "WIR franc1.00",
5185         "WIR francs1.00",
5186         "WST1.00",
5187         "WST1.00",
5188         "Samoan Tala1.00",
5189         "Samoan tala1.00",
5190         "Samoan tala1.00",
5191         "XAF1.00",
5192         "XAF1.00",
5193         "XAG1.00",
5194         "XAG1.00",
5195         "XAU1.00",
5196         "XAU1.00",
5197         "XBA1.00",
5198         "XBA1.00",
5199         "XBB1.00",
5200         "XBB1.00",
5201         "XBC1.00",
5202         "XBC1.00",
5203         "XBD1.00",
5204         "XBD1.00",
5205         "XCD1.00",
5206         "XDR1.00",
5207         "XDR1.00",
5208         "XEU1.00",
5209         "XEU1.00",
5210         "XFO1.00",
5211         "XFO1.00",
5212         "XFU1.00",
5213         "XFU1.00",
5214         "XOF1.00",
5215         "XOF1.00",
5216         "XPD1.00",
5217         "XPD1.00",
5218         "XPF1.00",
5219         "XPT1.00",
5220         "XPT1.00",
5221         "XRE1.00",
5222         "XRE1.00",
5223         "XTS1.00",
5224         "XTS1.00",
5225         "XXX1.00",
5226         "XXX1.00",
5227         "YDD1.00",
5228         "YDD1.00",
5229         "YER1.00",
5230         "YUD1.00",
5231         "YUD1.00",
5232         "YUM1.00",
5233         "YUM1.00",
5234         "YUN1.00",
5235         "YUN1.00",
5236         "Yemeni Dinar1.00",
5237         "Yemeni Rial1.00",
5238         "Yemeni dinar1.00",
5239         "Yemeni dinars1.00",
5240         "Yemeni rial1.00",
5241         "Yemeni rials1.00",
5242         "Yugoslavian Convertible Dinar (1990\\u20131992)1.00",
5243         "Yugoslavian Hard Dinar (1966\\u20131990)1.00",
5244         "Yugoslavian New Dinar (1994\\u20132002)1.00",
5245         "Yugoslavian convertible dinar (1990\\u20131992)1.00",
5246         "Yugoslavian convertible dinars (1990\\u20131992)1.00",
5247         "Yugoslavian hard dinar (1966\\u20131990)1.00",
5248         "Yugoslavian hard dinars (1966\\u20131990)1.00",
5249         "Yugoslavian new dinar (1994\\u20132002)1.00",
5250         "Yugoslavian new dinars (1994\\u20132002)1.00",
5251         "ZAL1.00",
5252         "ZAL1.00",
5253         "ZAR1.00",
5254         "ZMK1.00",
5255         "ZMK1.00",
5256         "ZRN1.00",
5257         "ZRN1.00",
5258         "ZRZ1.00",
5259         "ZRZ1.00",
5260         "ZWD1.00",
5261         "Zairean New Zaire (1993\\u20131998)1.00",
5262         "Zairean Zaire (1971\\u20131993)1.00",
5263         "Zairean new zaire (1993\\u20131998)1.00",
5264         "Zairean new zaires (1993\\u20131998)1.00",
5265         "Zairean zaire (1971\\u20131993)1.00",
5266         "Zairean zaires (1971\\u20131993)1.00",
5267         "Zambian Kwacha1.00",
5268         "Zambian kwacha1.00",
5269         "Zambian kwachas1.00",
5270         "Zimbabwean Dollar (1980\\u20132008)1.00",
5271         "Zimbabwean dollar (1980\\u20132008)1.00",
5272         "Zimbabwean dollars (1980\\u20132008)1.00",
5273         "euro1.00",
5274         "euros1.00",
5275         "Turkish lira (1922\\u20132005)1.00",
5276         "special drawing rights1.00",
5277         "Colombian real value unit1.00",
5278         "Colombian real value units1.00",
5279         "unknown currency1.00",
5280         "\\u00a31.00",
5281         "\\u00a51.00",
5282         "\\u20ab1.00",
5283         "\\u20aa1.00",
5284         "\\u20ac1.00",
5285         "\\u20b91.00",
5286         //
5287         // Following has extra text, should be parsed correctly too
5288         "$1.00 random",
5289         "USD1.00 random",
5290         "1.00 US dollar random",
5291         "1.00 US dollars random",
5292         "1.00 Afghan Afghani random",
5293         "1.00 Afghan Afghani random",
5294         "1.00 Afghan Afghanis (1927\\u20131992) random",
5295         "1.00 Afghan Afghanis random",
5296         "1.00 Albanian Lek random",
5297         "1.00 Albanian lek random",
5298         "1.00 Albanian lek\\u00eb random",
5299         "1.00 Algerian Dinar random",
5300         "1.00 Algerian dinar random",
5301         "1.00 Algerian dinars random",
5302         "1.00 Andorran Peseta random",
5303         "1.00 Andorran peseta random",
5304         "1.00 Andorran pesetas random",
5305         "1.00 Angolan Kwanza (1977\\u20131990) random",
5306         "1.00 Angolan Readjusted Kwanza (1995\\u20131999) random",
5307         "1.00 Angolan Kwanza random",
5308         "1.00 Angolan New Kwanza (1990\\u20132000) random",
5309         "1.00 Angolan kwanza (1977\\u20131991) random",
5310         "1.00 Angolan readjusted kwanza (1995\\u20131999) random",
5311         "1.00 Angolan kwanza random",
5312         "1.00 Angolan kwanzas (1977\\u20131991) random",
5313         "1.00 Angolan readjusted kwanzas (1995\\u20131999) random",
5314         "1.00 Angolan kwanzas random",
5315         "1.00 Angolan new kwanza (1990\\u20132000) random",
5316         "1.00 Angolan new kwanzas (1990\\u20132000) random",
5317         "1.00 Argentine Austral random",
5318         "1.00 Argentine Peso (1983\\u20131985) random",
5319         "1.00 Argentine Peso random",
5320         "1.00 Argentine austral random",
5321         "1.00 Argentine australs random",
5322         "1.00 Argentine peso (1983\\u20131985) random",
5323         "1.00 Argentine peso random",
5324         "1.00 Argentine pesos (1983\\u20131985) random",
5325         "1.00 Argentine pesos random",
5326         "1.00 Armenian Dram random",
5327         "1.00 Armenian dram random",
5328         "1.00 Armenian drams random",
5329         "1.00 Aruban Florin random",
5330         "1.00 Aruban florin random",
5331         "1.00 Australian Dollar random",
5332         "1.00 Australian dollar random",
5333         "1.00 Australian dollars random",
5334         "1.00 Austrian Schilling random",
5335         "1.00 Austrian schilling random",
5336         "1.00 Austrian schillings random",
5337         "1.00 Azerbaijani Manat (1993\\u20132006) random",
5338         "1.00 Azerbaijani Manat random",
5339         "1.00 Azerbaijani manat (1993\\u20132006) random",
5340         "1.00 Azerbaijani manat random",
5341         "1.00 Azerbaijani manats (1993\\u20132006) random",
5342         "1.00 Azerbaijani manats random",
5343         "1.00 Bahamian Dollar random",
5344         "1.00 Bahamian dollar random",
5345         "1.00 Bahamian dollars random",
5346         "1.00 Bahraini Dinar random",
5347         "1.00 Bahraini dinar random",
5348         "1.00 Bahraini dinars random",
5349         "1.00 Bangladeshi Taka random",
5350         "1.00 Bangladeshi taka random",
5351         "1.00 Bangladeshi takas random",
5352         "1.00 Barbadian Dollar random",
5353         "1.00 Barbadian dollar random",
5354         "1.00 Barbadian dollars random",
5355         "1.00 Belarusian Ruble (1994\\u20131999) random",
5356         "1.00 Belarusian Ruble random",
5357         "1.00 Belarusian ruble (1994\\u20131999) random",
5358         "1.00 Belarusian rubles (1994\\u20131999) random",
5359         "1.00 Belarusian ruble random",
5360         "1.00 Belarusian rubles random",
5361         "1.00 Belgian Franc (convertible) random",
5362         "1.00 Belgian Franc (financial) random",
5363         "1.00 Belgian Franc random",
5364         "1.00 Belgian franc (convertible) random",
5365         "1.00 Belgian franc (financial) random",
5366         "1.00 Belgian franc random",
5367         "1.00 Belgian francs (convertible) random",
5368         "1.00 Belgian francs (financial) random",
5369         "1.00 Belgian francs random",
5370         "1.00 Belize Dollar random",
5371         "1.00 Belize dollar random",
5372         "1.00 Belize dollars random",
5373         "1.00 Bermudan Dollar random",
5374         "1.00 Bermudan dollar random",
5375         "1.00 Bermudan dollars random",
5376         "1.00 Bhutanese Ngultrum random",
5377         "1.00 Bhutanese ngultrum random",
5378         "1.00 Bhutanese ngultrums random",
5379         "1.00 Bolivian Mvdol random",
5380         "1.00 Bolivian Peso random",
5381         "1.00 Bolivian mvdol random",
5382         "1.00 Bolivian mvdols random",
5383         "1.00 Bolivian peso random",
5384         "1.00 Bolivian pesos random",
5385         "1.00 Bolivian Boliviano random",
5386         "1.00 Bolivian Boliviano random",
5387         "1.00 Bolivian Bolivianos random",
5388         "1.00 Bosnia-Herzegovina Convertible Mark random",
5389         "1.00 Bosnia-Herzegovina Dinar (1992\\u20131994) random",
5390         "1.00 Bosnia-Herzegovina convertible mark random",
5391         "1.00 Bosnia-Herzegovina convertible marks random",
5392         "1.00 Bosnia-Herzegovina dinar (1992\\u20131994) random",
5393         "1.00 Bosnia-Herzegovina dinars (1992\\u20131994) random",
5394         "1.00 Botswanan Pula random",
5395         "1.00 Botswanan pula random",
5396         "1.00 Botswanan pulas random",
5397         "1.00 Brazilian New Cruzado (1989\\u20131990) random",
5398         "1.00 Brazilian Cruzado (1986\\u20131989) random",
5399         "1.00 Brazilian Cruzeiro (1990\\u20131993) random",
5400         "1.00 Brazilian New Cruzeiro (1967\\u20131986) random",
5401         "1.00 Brazilian Cruzeiro (1993\\u20131994) random",
5402         "1.00 Brazilian Real random",
5403         "1.00 Brazilian new cruzado (1989\\u20131990) random",
5404         "1.00 Brazilian new cruzados (1989\\u20131990) random",
5405         "1.00 Brazilian cruzado (1986\\u20131989) random",
5406         "1.00 Brazilian cruzados (1986\\u20131989) random",
5407         "1.00 Brazilian cruzeiro (1990\\u20131993) random",
5408         "1.00 Brazilian new cruzeiro (1967\\u20131986) random",
5409         "1.00 Brazilian cruzeiro (1993\\u20131994) random",
5410         "1.00 Brazilian cruzeiros (1990\\u20131993) random",
5411         "1.00 Brazilian new cruzeiros (1967\\u20131986) random",
5412         "1.00 Brazilian cruzeiros (1993\\u20131994) random",
5413         "1.00 Brazilian real random",
5414         "1.00 Brazilian reals random",
5415         "1.00 British Pound random",
5416         "1.00 British pound random",
5417         "1.00 British pounds random",
5418         "1.00 Brunei Dollar random",
5419         "1.00 Brunei dollar random",
5420         "1.00 Brunei dollars random",
5421         "1.00 Bulgarian Hard Lev random",
5422         "1.00 Bulgarian Lev random",
5423         "1.00 Bulgarian Leva random",
5424         "1.00 Bulgarian hard lev random",
5425         "1.00 Bulgarian hard leva random",
5426         "1.00 Bulgarian lev random",
5427         "1.00 Burmese Kyat random",
5428         "1.00 Burmese kyat random",
5429         "1.00 Burmese kyats random",
5430         "1.00 Burundian Franc random",
5431         "1.00 Burundian franc random",
5432         "1.00 Burundian francs random",
5433         "1.00 Cambodian Riel random",
5434         "1.00 Cambodian riel random",
5435         "1.00 Cambodian riels random",
5436         "1.00 Canadian Dollar random",
5437         "1.00 Canadian dollar random",
5438         "1.00 Canadian dollars random",
5439         "1.00 Cape Verdean Escudo random",
5440         "1.00 Cape Verdean escudo random",
5441         "1.00 Cape Verdean escudos random",
5442         "1.00 Cayman Islands Dollar random",
5443         "1.00 Cayman Islands dollar random",
5444         "1.00 Cayman Islands dollars random",
5445         "1.00 Chilean Peso random",
5446         "1.00 Chilean Unit of Account (UF) random",
5447         "1.00 Chilean peso random",
5448         "1.00 Chilean pesos random",
5449         "1.00 Chilean unit of account (UF) random",
5450         "1.00 Chilean units of account (UF) random",
5451         "1.00 Chinese Yuan random",
5452         "1.00 Chinese yuan random",
5453         "1.00 Colombian Peso random",
5454         "1.00 Colombian peso random",
5455         "1.00 Colombian pesos random",
5456         "1.00 Comorian Franc random",
5457         "1.00 Comorian franc random",
5458         "1.00 Comorian francs random",
5459         "1.00 Congolese Franc Congolais random",
5460         "1.00 Congolese franc Congolais random",
5461         "1.00 Congolese francs Congolais random",
5462         "1.00 Costa Rican Col\\u00f3n random",
5463         "1.00 Costa Rican col\\u00f3n random",
5464         "1.00 Costa Rican col\\u00f3ns random",
5465         "1.00 Croatian Dinar random",
5466         "1.00 Croatian Kuna random",
5467         "1.00 Croatian dinar random",
5468         "1.00 Croatian dinars random",
5469         "1.00 Croatian kuna random",
5470         "1.00 Croatian kunas random",
5471         "1.00 Cuban Peso random",
5472         "1.00 Cuban peso random",
5473         "1.00 Cuban pesos random",
5474         "1.00 Cypriot Pound random",
5475         "1.00 Cypriot pound random",
5476         "1.00 Cypriot pounds random",
5477         "1.00 Czech Koruna random",
5478         "1.00 Czech koruna random",
5479         "1.00 Czech korunas random",
5480         "1.00 Czechoslovak Hard Koruna random",
5481         "1.00 Czechoslovak hard koruna random",
5482         "1.00 Czechoslovak hard korunas random",
5483         "1.00 Danish Krone random",
5484         "1.00 Danish krone random",
5485         "1.00 Danish kroner random",
5486         "1.00 German Mark random",
5487         "1.00 German mark random",
5488         "1.00 German marks random",
5489         "1.00 Djiboutian Franc random",
5490         "1.00 Djiboutian franc random",
5491         "1.00 Djiboutian francs random",
5492         "1.00 Dominican Peso random",
5493         "1.00 Dominican peso random",
5494         "1.00 Dominican pesos random",
5495         "1.00 East Caribbean Dollar random",
5496         "1.00 East Caribbean dollar random",
5497         "1.00 East Caribbean dollars random",
5498         "1.00 East German Mark random",
5499         "1.00 East German mark random",
5500         "1.00 East German marks random",
5501         "1.00 Ecuadorian Sucre random",
5502         "1.00 Ecuadorian Unit of Constant Value random",
5503         "1.00 Ecuadorian sucre random",
5504         "1.00 Ecuadorian sucres random",
5505         "1.00 Ecuadorian unit of constant value random",
5506         "1.00 Ecuadorian units of constant value random",
5507         "1.00 Egyptian Pound random",
5508         "1.00 Egyptian pound random",
5509         "1.00 Egyptian pounds random",
5510         "1.00 Salvadoran Col\\u00f3n random",
5511         "1.00 Salvadoran col\\u00f3n random",
5512         "1.00 Salvadoran colones random",
5513         "1.00 Equatorial Guinean Ekwele random",
5514         "1.00 Equatorial Guinean ekwele random",
5515         "1.00 Eritrean Nakfa random",
5516         "1.00 Eritrean nakfa random",
5517         "1.00 Eritrean nakfas random",
5518         "1.00 Estonian Kroon random",
5519         "1.00 Estonian kroon random",
5520         "1.00 Estonian kroons random",
5521         "1.00 Ethiopian Birr random",
5522         "1.00 Ethiopian birr random",
5523         "1.00 Ethiopian birrs random",
5524         "1.00 European Composite Unit random",
5525         "1.00 European Currency Unit random",
5526         "1.00 European Monetary Unit random",
5527         "1.00 European Unit of Account (XBC) random",
5528         "1.00 European Unit of Account (XBD) random",
5529         "1.00 European composite unit random",
5530         "1.00 European composite units random",
5531         "1.00 European currency unit random",
5532         "1.00 European currency units random",
5533         "1.00 European monetary unit random",
5534         "1.00 European monetary units random",
5535         "1.00 European unit of account (XBC) random",
5536         "1.00 European unit of account (XBD) random",
5537         "1.00 European units of account (XBC) random",
5538         "1.00 European units of account (XBD) random",
5539         "1.00 Falkland Islands Pound random",
5540         "1.00 Falkland Islands pound random",
5541         "1.00 Falkland Islands pounds random",
5542         "1.00 Fijian Dollar random",
5543         "1.00 Fijian dollar random",
5544         "1.00 Fijian dollars random",
5545         "1.00 Finnish Markka random",
5546         "1.00 Finnish markka random",
5547         "1.00 Finnish markkas random",
5548         "1.00 French Franc random",
5549         "1.00 French Gold Franc random",
5550         "1.00 French UIC-Franc random",
5551         "1.00 French UIC-franc random",
5552         "1.00 French UIC-francs random",
5553         "1.00 French franc random",
5554         "1.00 French francs random",
5555         "1.00 French gold franc random",
5556         "1.00 French gold francs random",
5557         "1.00 Gambian Dalasi random",
5558         "1.00 Gambian dalasi random",
5559         "1.00 Gambian dalasis random",
5560         "1.00 Georgian Kupon Larit random",
5561         "1.00 Georgian Lari random",
5562         "1.00 Georgian kupon larit random",
5563         "1.00 Georgian kupon larits random",
5564         "1.00 Georgian lari random",
5565         "1.00 Georgian laris random",
5566         "1.00 Ghanaian Cedi (1979\\u20132007) random",
5567         "1.00 Ghanaian Cedi random",
5568         "1.00 Ghanaian cedi (1979\\u20132007) random",
5569         "1.00 Ghanaian cedi random",
5570         "1.00 Ghanaian cedis (1979\\u20132007) random",
5571         "1.00 Ghanaian cedis random",
5572         "1.00 Gibraltar Pound random",
5573         "1.00 Gibraltar pound random",
5574         "1.00 Gibraltar pounds random",
5575         "1.00 Gold random",
5576         "1.00 Gold random",
5577         "1.00 Greek Drachma random",
5578         "1.00 Greek drachma random",
5579         "1.00 Greek drachmas random",
5580         "1.00 Guatemalan Quetzal random",
5581         "1.00 Guatemalan quetzal random",
5582         "1.00 Guatemalan quetzals random",
5583         "1.00 Guinean Franc random",
5584         "1.00 Guinean Syli random",
5585         "1.00 Guinean franc random",
5586         "1.00 Guinean francs random",
5587         "1.00 Guinean syli random",
5588         "1.00 Guinean sylis random",
5589         "1.00 Guinea-Bissau Peso random",
5590         "1.00 Guinea-Bissau peso random",
5591         "1.00 Guinea-Bissau pesos random",
5592         "1.00 Guyanaese Dollar random",
5593         "1.00 Guyanaese dollar random",
5594         "1.00 Guyanaese dollars random",
5595         "1.00 Haitian Gourde random",
5596         "1.00 Haitian gourde random",
5597         "1.00 Haitian gourdes random",
5598         "1.00 Honduran Lempira random",
5599         "1.00 Honduran lempira random",
5600         "1.00 Honduran lempiras random",
5601         "1.00 Hong Kong Dollar random",
5602         "1.00 Hong Kong dollar random",
5603         "1.00 Hong Kong dollars random",
5604         "1.00 Hungarian Forint random",
5605         "1.00 Hungarian forint random",
5606         "1.00 Hungarian forints random",
5607         "1.00 Icelandic Kr\\u00f3na random",
5608         "1.00 Icelandic kr\\u00f3na random",
5609         "1.00 Icelandic kr\\u00f3nur random",
5610         "1.00 Indian Rupee random",
5611         "1.00 Indian rupee random",
5612         "1.00 Indian rupees random",
5613         "1.00 Indonesian Rupiah random",
5614         "1.00 Indonesian rupiah random",
5615         "1.00 Indonesian rupiahs random",
5616         "1.00 Iranian Rial random",
5617         "1.00 Iranian rial random",
5618         "1.00 Iranian rials random",
5619         "1.00 Iraqi Dinar random",
5620         "1.00 Iraqi dinar random",
5621         "1.00 Iraqi dinars random",
5622         "1.00 Irish Pound random",
5623         "1.00 Irish pound random",
5624         "1.00 Irish pounds random",
5625         "1.00 Israeli Pound random",
5626         "1.00 Israeli new shekel random",
5627         "1.00 Israeli pound random",
5628         "1.00 Israeli pounds random",
5629         "1.00 Italian Lira random",
5630         "1.00 Italian lira random",
5631         "1.00 Italian liras random",
5632         "1.00 Jamaican Dollar random",
5633         "1.00 Jamaican dollar random",
5634         "1.00 Jamaican dollars random",
5635         "1.00 Japanese Yen random",
5636         "1.00 Japanese yen random",
5637         "1.00 Jordanian Dinar random",
5638         "1.00 Jordanian dinar random",
5639         "1.00 Jordanian dinars random",
5640         "1.00 Kazakhstani Tenge random",
5641         "1.00 Kazakhstani tenge random",
5642         "1.00 Kazakhstani tenges random",
5643         "1.00 Kenyan Shilling random",
5644         "1.00 Kenyan shilling random",
5645         "1.00 Kenyan shillings random",
5646         "1.00 Kuwaiti Dinar random",
5647         "1.00 Kuwaiti dinar random",
5648         "1.00 Kuwaiti dinars random",
5649         "1.00 Kyrgystani Som random",
5650         "1.00 Kyrgystani som random",
5651         "1.00 Kyrgystani soms random",
5652         "1.00 Laotian Kip random",
5653         "1.00 Laotian kip random",
5654         "1.00 Laotian kips random",
5655         "1.00 Latvian Lats random",
5656         "1.00 Latvian Ruble random",
5657         "1.00 Latvian lats random",
5658         "1.00 Latvian lati random",
5659         "1.00 Latvian ruble random",
5660         "1.00 Latvian rubles random",
5661         "1.00 Lebanese Pound random",
5662         "1.00 Lebanese pound random",
5663         "1.00 Lebanese pounds random",
5664         "1.00 Lesotho Loti random",
5665         "1.00 Lesotho loti random",
5666         "1.00 Lesotho lotis random",
5667         "1.00 Liberian Dollar random",
5668         "1.00 Liberian dollar random",
5669         "1.00 Liberian dollars random",
5670         "1.00 Libyan Dinar random",
5671         "1.00 Libyan dinar random",
5672         "1.00 Libyan dinars random",
5673         "1.00 Lithuanian Litas random",
5674         "1.00 Lithuanian Talonas random",
5675         "1.00 Lithuanian litas random",
5676         "1.00 Lithuanian litai random",
5677         "1.00 Lithuanian talonas random",
5678         "1.00 Lithuanian talonases random",
5679         "1.00 Luxembourgian Convertible Franc random",
5680         "1.00 Luxembourg Financial Franc random",
5681         "1.00 Luxembourgian Franc random",
5682         "1.00 Luxembourgian convertible franc random",
5683         "1.00 Luxembourgian convertible francs random",
5684         "1.00 Luxembourg financial franc random",
5685         "1.00 Luxembourg financial francs random",
5686         "1.00 Luxembourgian franc random",
5687         "1.00 Luxembourgian francs random",
5688         "1.00 Macanese Pataca random",
5689         "1.00 Macanese pataca random",
5690         "1.00 Macanese patacas random",
5691         "1.00 Macedonian Denar random",
5692         "1.00 Macedonian denar random",
5693         "1.00 Macedonian denari random",
5694         "1.00 Malagasy Ariaries random",
5695         "1.00 Malagasy Ariary random",
5696         "1.00 Malagasy Ariary random",
5697         "1.00 Malagasy Franc random",
5698         "1.00 Malagasy franc random",
5699         "1.00 Malagasy francs random",
5700         "1.00 Malawian Kwacha random",
5701         "1.00 Malawian Kwacha random",
5702         "1.00 Malawian Kwachas random",
5703         "1.00 Malaysian Ringgit random",
5704         "1.00 Malaysian ringgit random",
5705         "1.00 Malaysian ringgits random",
5706         "1.00 Maldivian Rufiyaa random",
5707         "1.00 Maldivian rufiyaa random",
5708         "1.00 Maldivian rufiyaas random",
5709         "1.00 Malian Franc random",
5710         "1.00 Malian franc random",
5711         "1.00 Malian francs random",
5712         "1.00 Maltese Lira random",
5713         "1.00 Maltese Pound random",
5714         "1.00 Maltese lira random",
5715         "1.00 Maltese liras random",
5716         "1.00 Maltese pound random",
5717         "1.00 Maltese pounds random",
5718         "1.00 Mauritanian Ouguiya random",
5719         "1.00 Mauritanian ouguiya random",
5720         "1.00 Mauritanian ouguiyas random",
5721         "1.00 Mauritian Rupee random",
5722         "1.00 Mauritian rupee random",
5723         "1.00 Mauritian rupees random",
5724         "1.00 Mexican Peso random",
5725         "1.00 Mexican Silver Peso (1861\\u20131992) random",
5726         "1.00 Mexican Investment Unit random",
5727         "1.00 Mexican peso random",
5728         "1.00 Mexican pesos random",
5729         "1.00 Mexican silver peso (1861\\u20131992) random",
5730         "1.00 Mexican silver pesos (1861\\u20131992) random",
5731         "1.00 Mexican investment unit random",
5732         "1.00 Mexican investment units random",
5733         "1.00 Moldovan Leu random",
5734         "1.00 Moldovan leu random",
5735         "1.00 Moldovan lei random",
5736         "1.00 Mongolian Tugrik random",
5737         "1.00 Mongolian tugrik random",
5738         "1.00 Mongolian tugriks random",
5739         "1.00 Moroccan Dirham random",
5740         "1.00 Moroccan Franc random",
5741         "1.00 Moroccan dirham random",
5742         "1.00 Moroccan dirhams random",
5743         "1.00 Moroccan franc random",
5744         "1.00 Moroccan francs random",
5745         "1.00 Mozambican Escudo random",
5746         "1.00 Mozambican Metical random",
5747         "1.00 Mozambican escudo random",
5748         "1.00 Mozambican escudos random",
5749         "1.00 Mozambican metical random",
5750         "1.00 Mozambican meticals random",
5751         "1.00 Myanmar Kyat random",
5752         "1.00 Myanmar kyat random",
5753         "1.00 Myanmar kyats random",
5754         "1.00 Namibian Dollar random",
5755         "1.00 Namibian dollar random",
5756         "1.00 Namibian dollars random",
5757         "1.00 Nepalese Rupee random",
5758         "1.00 Nepalese rupee random",
5759         "1.00 Nepalese rupees random",
5760         "1.00 Netherlands Antillean Guilder random",
5761         "1.00 Netherlands Antillean guilder random",
5762         "1.00 Netherlands Antillean guilders random",
5763         "1.00 Dutch Guilder random",
5764         "1.00 Dutch guilder random",
5765         "1.00 Dutch guilders random",
5766         "1.00 Israeli New Shekel random",
5767         "1.00 Israeli new shekels random",
5768         "1.00 New Zealand Dollar random",
5769         "1.00 New Zealand dollar random",
5770         "1.00 New Zealand dollars random",
5771         "1.00 Nicaraguan C\\u00f3rdoba random",
5772         "1.00 Nicaraguan C\\u00f3rdoba (1988\\u20131991) random",
5773         "1.00 Nicaraguan c\\u00f3rdoba random",
5774         "1.00 Nicaraguan c\\u00f3rdoba random",
5775         "1.00 Nicaraguan c\\u00f3rdoba (1988\\u20131991) random",
5776         "1.00 Nicaraguan c\\u00f3rdobas (1988\\u20131991) random",
5777         "1.00 Nigerian Naira random",
5778         "1.00 Nigerian naira random",
5779         "1.00 Nigerian nairas random",
5780         "1.00 North Korean Won random",
5781         "1.00 North Korean won random",
5782         "1.00 North Korean won random",
5783         "1.00 Norwegian Krone random",
5784         "1.00 Norwegian krone random",
5785         "1.00 Norwegian kroner random",
5786         "1.00 Mozambican Metical (1980\\u20132006) random",
5787         "1.00 Mozambican metical (1980\\u20132006) random",
5788         "1.00 Mozambican meticals (1980\\u20132006) random",
5789         "1.00 Romanian Lei (1952\\u20132006) random",
5790         "1.00 Romanian Leu (1952\\u20132006) random",
5791         "1.00 Romanian leu (1952\\u20132006) random",
5792         "1.00 Serbian Dinar (2002\\u20132006) random",
5793         "1.00 Serbian dinar (2002\\u20132006) random",
5794         "1.00 Serbian dinars (2002\\u20132006) random",
5795         "1.00 Sudanese Dinar (1992\\u20132007) random",
5796         "1.00 Sudanese Pound (1957\\u20131998) random",
5797         "1.00 Sudanese dinar (1992\\u20132007) random",
5798         "1.00 Sudanese dinars (1992\\u20132007) random",
5799         "1.00 Sudanese pound (1957\\u20131998) random",
5800         "1.00 Sudanese pounds (1957\\u20131998) random",
5801         "1.00 Turkish Lira (1922\\u20132005) random",
5802         "1.00 Turkish Lira (1922\\u20132005) random",
5803         "1.00 Omani Rial random",
5804         "1.00 Omani rial random",
5805         "1.00 Omani rials random",
5806         "1.00 Pakistani Rupee random",
5807         "1.00 Pakistani rupee random",
5808         "1.00 Pakistani rupees random",
5809         "1.00 Palladium random",
5810         "1.00 Palladium random",
5811         "1.00 Panamanian Balboa random",
5812         "1.00 Panamanian balboa random",
5813         "1.00 Panamanian balboas random",
5814         "1.00 Papua New Guinean Kina random",
5815         "1.00 Papua New Guinean kina random",
5816         "1.00 Papua New Guinean kina random",
5817         "1.00 Paraguayan Guarani random",
5818         "1.00 Paraguayan guarani random",
5819         "1.00 Paraguayan guaranis random",
5820         "1.00 Peruvian Inti random",
5821         "1.00 Peruvian Sol random",
5822         "1.00 Peruvian Sol (1863\\u20131965) random",
5823         "1.00 Peruvian inti random",
5824         "1.00 Peruvian intis random",
5825         "1.00 Peruvian sol random",
5826         "1.00 Peruvian soles random",
5827         "1.00 Peruvian sol (1863\\u20131965) random",
5828         "1.00 Peruvian soles (1863\\u20131965) random",
5829         "1.00 Philippine Piso random",
5830         "1.00 Philippine piso random",
5831         "1.00 Philippine pisos random",
5832         "1.00 Platinum random",
5833         "1.00 Platinum random",
5834         "1.00 Polish Zloty (1950\\u20131995) random",
5835         "1.00 Polish Zloty random",
5836         "1.00 Polish zlotys random",
5837         "1.00 Polish zloty (PLZ) random",
5838         "1.00 Polish zloty random",
5839         "1.00 Polish zlotys (PLZ) random",
5840         "1.00 Portuguese Escudo random",
5841         "1.00 Portuguese Guinea Escudo random",
5842         "1.00 Portuguese Guinea escudo random",
5843         "1.00 Portuguese Guinea escudos random",
5844         "1.00 Portuguese escudo random",
5845         "1.00 Portuguese escudos random",
5846         "1.00 Qatari Rial random",
5847         "1.00 Qatari rial random",
5848         "1.00 Qatari rials random",
5849         "1.00 RINET Funds random",
5850         "1.00 RINET Funds random",
5851         "1.00 Rhodesian Dollar random",
5852         "1.00 Rhodesian dollar random",
5853         "1.00 Rhodesian dollars random",
5854         "1.00 Romanian Leu random",
5855         "1.00 Romanian lei random",
5856         "1.00 Romanian leu random",
5857         "1.00 Russian Ruble (1991\\u20131998) random",
5858         "1.00 Russian Ruble random",
5859         "1.00 Russian ruble (1991\\u20131998) random",
5860         "1.00 Russian ruble random",
5861         "1.00 Russian rubles (1991\\u20131998) random",
5862         "1.00 Russian rubles random",
5863         "1.00 Rwandan Franc random",
5864         "1.00 Rwandan franc random",
5865         "1.00 Rwandan francs random",
5866         "1.00 St. Helena Pound random",
5867         "1.00 St. Helena pound random",
5868         "1.00 St. Helena pounds random",
5869         "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra random",
5870         "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra random",
5871         "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras random",
5872         "1.00 Saudi Riyal random",
5873         "1.00 Saudi riyal random",
5874         "1.00 Saudi riyals random",
5875         "1.00 Serbian Dinar random",
5876         "1.00 Serbian dinar random",
5877         "1.00 Serbian dinars random",
5878         "1.00 Seychellois Rupee random",
5879         "1.00 Seychellois rupee random",
5880         "1.00 Seychellois rupees random",
5881         "1.00 Sierra Leonean Leone random",
5882         "1.00 Sierra Leonean leone random",
5883         "1.00 Sierra Leonean leones random",
5884         "1.00 Singapore Dollar random",
5885         "1.00 Singapore dollar random",
5886         "1.00 Singapore dollars random",
5887         "1.00 Slovak Koruna random",
5888         "1.00 Slovak koruna random",
5889         "1.00 Slovak korunas random",
5890         "1.00 Slovenian Tolar random",
5891         "1.00 Slovenian tolar random",
5892         "1.00 Slovenian tolars random",
5893         "1.00 Solomon Islands Dollar random",
5894         "1.00 Solomon Islands dollar random",
5895         "1.00 Solomon Islands dollars random",
5896         "1.00 Somali Shilling random",
5897         "1.00 Somali shilling random",
5898         "1.00 Somali shillings random",
5899         "1.00 South African Rand (financial) random",
5900         "1.00 South African Rand random",
5901         "1.00 South African rand (financial) random",
5902         "1.00 South African rand random",
5903         "1.00 South African rands (financial) random",
5904         "1.00 South African rand random",
5905         "1.00 South Korean Won random",
5906         "1.00 South Korean won random",
5907         "1.00 South Korean won random",
5908         "1.00 Soviet Rouble random",
5909         "1.00 Soviet rouble random",
5910         "1.00 Soviet roubles random",
5911         "1.00 Spanish Peseta (A account) random",
5912         "1.00 Spanish Peseta (convertible account) random",
5913         "1.00 Spanish Peseta random",
5914         "1.00 Spanish peseta (A account) random",
5915         "1.00 Spanish peseta (convertible account) random",
5916         "1.00 Spanish peseta random",
5917         "1.00 Spanish pesetas (A account) random",
5918         "1.00 Spanish pesetas (convertible account) random",
5919         "1.00 Spanish pesetas random",
5920         "1.00 Special Drawing Rights random",
5921         "1.00 Sri Lankan Rupee random",
5922         "1.00 Sri Lankan rupee random",
5923         "1.00 Sri Lankan rupees random",
5924         "1.00 Sudanese Pound random",
5925         "1.00 Sudanese pound random",
5926         "1.00 Sudanese pounds random",
5927         "1.00 Surinamese Dollar random",
5928         "1.00 Surinamese dollar random",
5929         "1.00 Surinamese dollars random",
5930         "1.00 Surinamese Guilder random",
5931         "1.00 Surinamese guilder random",
5932         "1.00 Surinamese guilders random",
5933         "1.00 Swazi Lilangeni random",
5934         "1.00 Swazi lilangeni random",
5935         "1.00 Swazi emalangeni random",
5936         "1.00 Swedish Krona random",
5937         "1.00 Swedish krona random",
5938         "1.00 Swedish kronor random",
5939         "1.00 Swiss Franc random",
5940         "1.00 Swiss franc random",
5941         "1.00 Swiss francs random",
5942         "1.00 Syrian Pound random",
5943         "1.00 Syrian pound random",
5944         "1.00 Syrian pounds random",
5945         "1.00 New Taiwan Dollar random",
5946         "1.00 New Taiwan dollar random",
5947         "1.00 New Taiwan dollars random",
5948         "1.00 Tajikistani Ruble random",
5949         "1.00 Tajikistani Somoni random",
5950         "1.00 Tajikistani ruble random",
5951         "1.00 Tajikistani rubles random",
5952         "1.00 Tajikistani somoni random",
5953         "1.00 Tajikistani somonis random",
5954         "1.00 Tanzanian Shilling random",
5955         "1.00 Tanzanian shilling random",
5956         "1.00 Tanzanian shillings random",
5957         "1.00 Testing Currency Code random",
5958         "1.00 Testing Currency Code random",
5959         "1.00 Thai Baht random",
5960         "1.00 Thai baht random",
5961         "1.00 Thai baht random",
5962         "1.00 Timorese Escudo random",
5963         "1.00 Timorese escudo random",
5964         "1.00 Timorese escudos random",
5965         "1.00 Trinidad & Tobago Dollar random",
5966         "1.00 Trinidad & Tobago dollar random",
5967         "1.00 Trinidad & Tobago dollars random",
5968         "1.00 Tunisian Dinar random",
5969         "1.00 Tunisian dinar random",
5970         "1.00 Tunisian dinars random",
5971         "1.00 Turkish Lira random",
5972         "1.00 Turkish Lira random",
5973         "1.00 Turkish lira random",
5974         "1.00 Turkmenistani Manat random",
5975         "1.00 Turkmenistani manat random",
5976         "1.00 Turkmenistani manat random",
5977         "1.00 US Dollar (Next day) random",
5978         "1.00 US Dollar (Same day) random",
5979         "1.00 US Dollar random",
5980         "1.00 US dollar (next day) random",
5981         "1.00 US dollar (same day) random",
5982         "1.00 US dollar random",
5983         "1.00 US dollars (next day) random",
5984         "1.00 US dollars (same day) random",
5985         "1.00 US dollars random",
5986         "1.00 Ugandan Shilling (1966\\u20131987) random",
5987         "1.00 Ugandan Shilling random",
5988         "1.00 Ugandan shilling (1966\\u20131987) random",
5989         "1.00 Ugandan shilling random",
5990         "1.00 Ugandan shillings (1966\\u20131987) random",
5991         "1.00 Ugandan shillings random",
5992         "1.00 Ukrainian Hryvnia random",
5993         "1.00 Ukrainian Karbovanets random",
5994         "1.00 Ukrainian hryvnia random",
5995         "1.00 Ukrainian hryvnias random",
5996         "1.00 Ukrainian karbovanets random",
5997         "1.00 Ukrainian karbovantsiv random",
5998         "1.00 Colombian Real Value Unit random",
5999         "1.00 United Arab Emirates Dirham random",
6000         "1.00 Unknown Currency random",
6001         "1.00 Uruguayan Peso (1975\\u20131993) random",
6002         "1.00 Uruguayan Peso random",
6003         "1.00 Uruguayan Peso (Indexed Units) random",
6004         "1.00 Uruguayan peso (1975\\u20131993) random",
6005         "1.00 Uruguayan peso (indexed units) random",
6006         "1.00 Uruguayan peso random",
6007         "1.00 Uruguayan pesos (1975\\u20131993) random",
6008         "1.00 Uruguayan pesos (indexed units) random",
6009         "1.00 Uzbekistani Som random",
6010         "1.00 Uzbekistani som random",
6011         "1.00 Uzbekistani som random",
6012         "1.00 Vanuatu Vatu random",
6013         "1.00 Vanuatu vatu random",
6014         "1.00 Vanuatu vatus random",
6015         "1.00 Venezuelan Bol\\u00edvar random",
6016         "1.00 Venezuelan Bol\\u00edvar (1871\\u20132008) random",
6017         "1.00 Venezuelan bol\\u00edvar random",
6018         "1.00 Venezuelan bol\\u00edvars random",
6019         "1.00 Venezuelan bol\\u00edvar (1871\\u20132008) random",
6020         "1.00 Venezuelan bol\\u00edvars (1871\\u20132008) random",
6021         "1.00 Vietnamese Dong random",
6022         "1.00 Vietnamese dong random",
6023         "1.00 Vietnamese dong random",
6024         "1.00 WIR Euro random",
6025         "1.00 WIR Franc random",
6026         "1.00 WIR euro random",
6027         "1.00 WIR euros random",
6028         "1.00 WIR franc random",
6029         "1.00 WIR francs random",
6030         "1.00 Samoan Tala random",
6031         "1.00 Samoan tala random",
6032         "1.00 Samoan tala random",
6033         "1.00 Yemeni Dinar random",
6034         "1.00 Yemeni Rial random",
6035         "1.00 Yemeni dinar random",
6036         "1.00 Yemeni dinars random",
6037         "1.00 Yemeni rial random",
6038         "1.00 Yemeni rials random",
6039         "1.00 Yugoslavian Convertible Dinar (1990\\u20131992) random",
6040         "1.00 Yugoslavian Hard Dinar (1966\\u20131990) random",
6041         "1.00 Yugoslavian New Dinar (1994\\u20132002) random",
6042         "1.00 Yugoslavian convertible dinar (1990\\u20131992) random",
6043         "1.00 Yugoslavian convertible dinars (1990\\u20131992) random",
6044         "1.00 Yugoslavian hard dinar (1966\\u20131990) random",
6045         "1.00 Yugoslavian hard dinars (1966\\u20131990) random",
6046         "1.00 Yugoslavian new dinar (1994\\u20132002) random",
6047         "1.00 Yugoslavian new dinars (1994\\u20132002) random",
6048         "1.00 Zairean New Zaire (1993\\u20131998) random",
6049         "1.00 Zairean Zaire (1971\\u20131993) random",
6050         "1.00 Zairean new zaire (1993\\u20131998) random",
6051         "1.00 Zairean new zaires (1993\\u20131998) random",
6052         "1.00 Zairean zaire (1971\\u20131993) random",
6053         "1.00 Zairean zaires (1971\\u20131993) random",
6054         "1.00 Zambian Kwacha random",
6055         "1.00 Zambian kwacha random",
6056         "1.00 Zambian kwachas random",
6057         "1.00 Zimbabwean Dollar (1980\\u20132008) random",
6058         "1.00 Zimbabwean dollar (1980\\u20132008) random",
6059         "1.00 Zimbabwean dollars (1980\\u20132008) random",
6060         "1.00 euro random",
6061         "1.00 euros random",
6062         "1.00 Turkish lira (1922\\u20132005) random",
6063         "1.00 special drawing rights random",
6064         "1.00 Colombian real value unit random",
6065         "1.00 Colombian real value units random",
6066         "1.00 unknown currency random",
6067     };
6068 
6069     const char* WRONG_DATA[] = {
6070         // Following are missing one last char in the currency name
6071         "1.00 Nicaraguan Cordob",
6072         "1.00 Namibian Dolla",
6073         "1.00 Namibian dolla",
6074         "1.00 Nepalese Rupe",
6075         "1.00 Nepalese rupe",
6076         "1.00 Netherlands Antillean Guilde",
6077         "1.00 Netherlands Antillean guilde",
6078         "1.00 Dutch Guilde",
6079         "1.00 Dutch guilde",
6080         "1.00 Israeli New Sheqe",
6081         "1.00 New Zealand Dolla",
6082         "1.00 New Zealand dolla",
6083         "1.00 Nicaraguan cordob",
6084         "1.00 Nigerian Nair",
6085         "1.00 Nigerian nair",
6086         "1.00 North Korean Wo",
6087         "1.00 North Korean wo",
6088         "1.00 Norwegian Kron",
6089         "1.00 Norwegian kron",
6090         "1.00 US dolla",
6091         "1.00",
6092         "A1.00",
6093         "AD1.00",
6094         "AE1.00",
6095         "AF1.00",
6096         "AL1.00",
6097         "AM1.00",
6098         "AN1.00",
6099         "AO1.00",
6100         "AR1.00",
6101         "AT1.00",
6102         "AU1.00",
6103         "AW1.00",
6104         "AZ1.00",
6105         "Afghan Afghan1.00",
6106         "Afghan Afghani (1927\\u201320021.00",
6107         "Afl1.00",
6108         "Albanian Le1.00",
6109         "Algerian Dina1.00",
6110         "Andorran Peset1.00",
6111         "Angolan Kwanz1.00",
6112         "Angolan Kwanza (1977\\u201319901.00",
6113         "Angolan Readjusted Kwanza (1995\\u201319991.00",
6114         "Angolan New Kwanza (1990\\u201320001.00",
6115         "Argentine Austra1.00",
6116         "Argentine Pes1.00",
6117         "Argentine Peso (1983\\u201319851.00",
6118         "Armenian Dra1.00",
6119         "Aruban Flori1.00",
6120         "Australian Dolla1.00",
6121         "Austrian Schillin1.00",
6122         "Azerbaijani Mana1.00",
6123         "Azerbaijani Manat (1993\\u201320061.00",
6124         "B1.00",
6125         "BA1.00",
6126         "BB1.00",
6127         "BE1.00",
6128         "BG1.00",
6129         "BH1.00",
6130         "BI1.00",
6131         "BM1.00",
6132         "BN1.00",
6133         "BO1.00",
6134         "BR1.00",
6135         "BS1.00",
6136         "BT1.00",
6137         "BU1.00",
6138         "BW1.00",
6139         "BY1.00",
6140         "BZ1.00",
6141         "Bahamian Dolla1.00",
6142         "Bahraini Dina1.00",
6143         "Bangladeshi Tak1.00",
6144         "Barbadian Dolla1.00",
6145         "Bds1.00",
6146         "Belarusian Ruble (1994\\u201319991.00",
6147         "Belarusian Rubl1.00",
6148         "Belgian Fran1.00",
6149         "Belgian Franc (convertible1.00",
6150         "Belgian Franc (financial1.00",
6151         "Belize Dolla1.00",
6152         "Bermudan Dolla1.00",
6153         "Bhutanese Ngultru1.00",
6154         "Bolivian Mvdo1.00",
6155         "Bolivian Pes1.00",
6156         "Bolivian Bolivian1.00",
6157         "Bosnia-Herzegovina Convertible Mar1.00",
6158         "Bosnia-Herzegovina Dina1.00",
6159         "Botswanan Pul1.00",
6160         "Brazilian Cruzad1.00",
6161         "Brazilian Cruzado Nov1.00",
6162         "Brazilian Cruzeir1.00",
6163         "Brazilian Cruzeiro (1990\\u201319931.00",
6164         "Brazilian New Cruzeiro (1967\\u201319861.00",
6165         "Brazilian Rea1.00",
6166         "British Pound Sterlin1.00",
6167         "Brunei Dolla1.00",
6168         "Bulgarian Hard Le1.00",
6169         "Bulgarian Le1.00",
6170         "Burmese Kya1.00",
6171         "Burundian Fran1.00",
6172         "C1.00",
6173         "CA1.00",
6174         "CD1.00",
6175         "CFP Fran1.00",
6176         "CFP1.00",
6177         "CH1.00",
6178         "CL1.00",
6179         "CN1.00",
6180         "CO1.00",
6181         "CS1.00",
6182         "CU1.00",
6183         "CV1.00",
6184         "CY1.00",
6185         "CZ1.00",
6186         "Cambodian Rie1.00",
6187         "Canadian Dolla1.00",
6188         "Cape Verdean Escud1.00",
6189         "Cayman Islands Dolla1.00",
6190         "Chilean Pes1.00",
6191         "Chilean Unit of Accoun1.00",
6192         "Chinese Yua1.00",
6193         "Colombian Pes1.00",
6194         "Comoro Fran1.00",
6195         "Congolese Fran1.00",
6196         "Costa Rican Col\\u00f31.00",
6197         "Croatian Dina1.00",
6198         "Croatian Kun1.00",
6199         "Cuban Pes1.00",
6200         "Cypriot Poun1.00",
6201         "Czech Republic Korun1.00",
6202         "Czechoslovak Hard Korun1.00",
6203         "D1.00",
6204         "DD1.00",
6205         "DE1.00",
6206         "DJ1.00",
6207         "DK1.00",
6208         "DO1.00",
6209         "DZ1.00",
6210         "Danish Kron1.00",
6211         "German Mar1.00",
6212         "Djiboutian Fran1.00",
6213         "Dk1.00",
6214         "Dominican Pes1.00",
6215         "EC1.00",
6216         "EE1.00",
6217         "EG1.00",
6218         "EQ1.00",
6219         "ER1.00",
6220         "ES1.00",
6221         "ET1.00",
6222         "EU1.00",
6223         "East Caribbean Dolla1.00",
6224         "East German Ostmar1.00",
6225         "Ecuadorian Sucr1.00",
6226         "Ecuadorian Unit of Constant Valu1.00",
6227         "Egyptian Poun1.00",
6228         "Ekwel1.00",
6229         "Salvadoran Col\\u00f31.00",
6230         "Equatorial Guinean Ekwel1.00",
6231         "Eritrean Nakf1.00",
6232         "Es1.00",
6233         "Estonian Kroo1.00",
6234         "Ethiopian Bir1.00",
6235         "Eur1.00",
6236         "European Composite Uni1.00",
6237         "European Currency Uni1.00",
6238         "European Monetary Uni1.00",
6239         "European Unit of Account (XBC1.00",
6240         "European Unit of Account (XBD1.00",
6241         "F1.00",
6242         "FB1.00",
6243         "FI1.00",
6244         "FJ1.00",
6245         "FK1.00",
6246         "FR1.00",
6247         "Falkland Islands Poun1.00",
6248         "Fd1.00",
6249         "Fijian Dolla1.00",
6250         "Finnish Markk1.00",
6251         "Fr1.00",
6252         "French Fran1.00",
6253         "French Gold Fran1.00",
6254         "French UIC-Fran1.00",
6255         "G1.00",
6256         "GB1.00",
6257         "GE1.00",
6258         "GH1.00",
6259         "GI1.00",
6260         "GM1.00",
6261         "GN1.00",
6262         "GQ1.00",
6263         "GR1.00",
6264         "GT1.00",
6265         "GW1.00",
6266         "GY1.00",
6267         "Gambian Dalas1.00",
6268         "Georgian Kupon Lari1.00",
6269         "Georgian Lar1.00",
6270         "Ghanaian Ced1.00",
6271         "Ghanaian Cedi (1979\\u201320071.00",
6272         "Gibraltar Poun1.00",
6273         "Gol1.00",
6274         "Greek Drachm1.00",
6275         "Guatemalan Quetza1.00",
6276         "Guinean Fran1.00",
6277         "Guinean Syl1.00",
6278         "Guinea-Bissau Pes1.00",
6279         "Guyanaese Dolla1.00",
6280         "HK1.00",
6281         "HN1.00",
6282         "HR1.00",
6283         "HT1.00",
6284         "HU1.00",
6285         "Haitian Gourd1.00",
6286         "Honduran Lempir1.00",
6287         "Hong Kong Dolla1.00",
6288         "Hungarian Forin1.00",
6289         "I1.00",
6290         "IE1.00",
6291         "IL1.00",
6292         "IN1.00",
6293         "IQ1.00",
6294         "IR1.00",
6295         "IS1.00",
6296         "IT1.00",
6297         "Icelandic Kron1.00",
6298         "Indian Rupe1.00",
6299         "Indonesian Rupia1.00",
6300         "Iranian Ria1.00",
6301         "Iraqi Dina1.00",
6302         "Irish Poun1.00",
6303         "Israeli Poun1.00",
6304         "Italian Lir1.00",
6305         "J1.00",
6306         "JM1.00",
6307         "JO1.00",
6308         "JP1.00",
6309         "Jamaican Dolla1.00",
6310         "Japanese Ye1.00",
6311         "Jordanian Dina1.00",
6312         "K S1.00",
6313         "K1.00",
6314         "KE1.00",
6315         "KG1.00",
6316         "KH1.00",
6317         "KP1.00",
6318         "KR1.00",
6319         "KW1.00",
6320         "KY1.00",
6321         "KZ1.00",
6322         "Kazakhstani Teng1.00",
6323         "Kenyan Shillin1.00",
6324         "Kuwaiti Dina1.00",
6325         "Kyrgystani So1.00",
6326         "LA1.00",
6327         "LB1.00",
6328         "LK1.00",
6329         "LR1.00",
6330         "LT1.00",
6331         "LU1.00",
6332         "LV1.00",
6333         "LY1.00",
6334         "Laotian Ki1.00",
6335         "Latvian Lat1.00",
6336         "Latvian Rubl1.00",
6337         "Lebanese Poun1.00",
6338         "Lesotho Lot1.00",
6339         "Liberian Dolla1.00",
6340         "Libyan Dina1.00",
6341         "Lithuanian Lit1.00",
6342         "Lithuanian Talona1.00",
6343         "Luxembourgian Convertible Fran1.00",
6344         "Luxembourg Financial Fran1.00",
6345         "Luxembourgian Fran1.00",
6346         "MA1.00",
6347         "MD1.00",
6348         "MDe1.00",
6349         "MEX1.00",
6350         "MG1.00",
6351         "ML1.00",
6352         "MM1.00",
6353         "MN1.00",
6354         "MO1.00",
6355         "MR1.00",
6356         "MT1.00",
6357         "MU1.00",
6358         "MV1.00",
6359         "MW1.00",
6360         "MX1.00",
6361         "MY1.00",
6362         "MZ1.00",
6363         "Macanese Patac1.00",
6364         "Macedonian Dena1.00",
6365         "Malagasy Ariar1.00",
6366         "Malagasy Fran1.00",
6367         "Malawian Kwach1.00",
6368         "Malaysian Ringgi1.00",
6369         "Maldivian Rufiya1.00",
6370         "Malian Fran1.00",
6371         "Malot1.00",
6372         "Maltese Lir1.00",
6373         "Maltese Poun1.00",
6374         "Mauritanian Ouguiy1.00",
6375         "Mauritian Rupe1.00",
6376         "Mexican Pes1.00",
6377         "Mexican Silver Peso (1861\\u201319921.00",
6378         "Mexican Investment Uni1.00",
6379         "Moldovan Le1.00",
6380         "Mongolian Tugri1.00",
6381         "Moroccan Dirha1.00",
6382         "Moroccan Fran1.00",
6383         "Mozambican Escud1.00",
6384         "Mozambican Metica1.00",
6385         "Myanmar Kya1.00",
6386         "N1.00",
6387         "NA1.00",
6388         "NAf1.00",
6389         "NG1.00",
6390         "NI1.00",
6391         "NK1.00",
6392         "NL1.00",
6393         "NO1.00",
6394         "NP1.00",
6395         "NT1.00",
6396         "Namibian Dolla1.00",
6397         "Nepalese Rupe1.00",
6398         "Netherlands Antillean Guilde1.00",
6399         "Dutch Guilde1.00",
6400         "Israeli New Sheqe1.00",
6401         "New Zealand Dolla1.00",
6402         "Nicaraguan C\\u00f3rdoba (1988\\u201319911.00",
6403         "Nicaraguan C\\u00f3rdob1.00",
6404         "Nigerian Nair1.00",
6405         "North Korean Wo1.00",
6406         "Norwegian Kron1.00",
6407         "Nr1.00",
6408         "OM1.00",
6409         "Old Mozambican Metica1.00",
6410         "Romanian Leu (1952\\u201320061.00",
6411         "Serbian Dinar (2002\\u201320061.00",
6412         "Sudanese Dinar (1992\\u201320071.00",
6413         "Sudanese Pound (1957\\u201319981.00",
6414         "Turkish Lira (1922\\u201320051.00",
6415         "Omani Ria1.00",
6416         "PA1.00",
6417         "PE1.00",
6418         "PG1.00",
6419         "PH1.00",
6420         "PK1.00",
6421         "PL1.00",
6422         "PT1.00",
6423         "PY1.00",
6424         "Pakistani Rupe1.00",
6425         "Palladiu1.00",
6426         "Panamanian Balbo1.00",
6427         "Papua New Guinean Kin1.00",
6428         "Paraguayan Guaran1.00",
6429         "Peruvian Int1.00",
6430         "Peruvian Sol (1863\\u201319651.00",
6431         "Peruvian Sol Nuev1.00",
6432         "Philippine Pes1.00",
6433         "Platinu1.00",
6434         "Polish Zlot1.00",
6435         "Polish Zloty (1950\\u201319951.00",
6436         "Portuguese Escud1.00",
6437         "Portuguese Guinea Escud1.00",
6438         "Pr1.00",
6439         "QA1.00",
6440         "Qatari Ria1.00",
6441         "RD1.00",
6442         "RH1.00",
6443         "RINET Fund1.00",
6444         "RS1.00",
6445         "RU1.00",
6446         "RW1.00",
6447         "Rb1.00",
6448         "Rhodesian Dolla1.00",
6449         "Romanian Le1.00",
6450         "Russian Rubl1.00",
6451         "Russian Ruble (1991\\u201319981.00",
6452         "Rwandan Fran1.00",
6453         "S1.00",
6454         "SA1.00",
6455         "SB1.00",
6456         "SC1.00",
6457         "SD1.00",
6458         "SE1.00",
6459         "SG1.00",
6460         "SH1.00",
6461         "SI1.00",
6462         "SK1.00",
6463         "SL R1.00",
6464         "SL1.00",
6465         "SO1.00",
6466         "ST1.00",
6467         "SU1.00",
6468         "SV1.00",
6469         "SY1.00",
6470         "SZ1.00",
6471         "St. Helena Poun1.00",
6472         "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobr1.00",
6473         "Saudi Riya1.00",
6474         "Serbian Dina1.00",
6475         "Seychellois Rupe1.00",
6476         "Sh1.00",
6477         "Sierra Leonean Leon1.00",
6478         "Silve1.00",
6479         "Singapore Dolla1.00",
6480         "Slovak Korun1.00",
6481         "Slovenian Tola1.00",
6482         "Solomon Islands Dolla1.00",
6483         "Somali Shillin1.00",
6484         "South African Ran1.00",
6485         "South African Rand (financial1.00",
6486         "South Korean Wo1.00",
6487         "Soviet Roubl1.00",
6488         "Spanish Peset1.00",
6489         "Spanish Peseta (A account1.00",
6490         "Spanish Peseta (convertible account1.00",
6491         "Special Drawing Right1.00",
6492         "Sri Lankan Rupe1.00",
6493         "Sudanese Poun1.00",
6494         "Surinamese Dolla1.00",
6495         "Surinamese Guilde1.00",
6496         "Swazi Lilangen1.00",
6497         "Swedish Kron1.00",
6498         "Swiss Fran1.00",
6499         "Syrian Poun1.00",
6500         "T S1.00",
6501         "TH1.00",
6502         "TJ1.00",
6503         "TM1.00",
6504         "TN1.00",
6505         "TO1.00",
6506         "TP1.00",
6507         "TR1.00",
6508         "TT1.00",
6509         "TW1.00",
6510         "TZ1.00",
6511         "New Taiwan Dolla1.00",
6512         "Tajikistani Rubl1.00",
6513         "Tajikistani Somon1.00",
6514         "Tanzanian Shillin1.00",
6515         "Testing Currency Cod1.00",
6516         "Thai Bah1.00",
6517         "Timorese Escud1.00",
6518         "Tongan Pa\\u20bbang1.00",
6519         "Trinidad & Tobago Dolla1.00",
6520         "Tunisian Dina1.00",
6521         "Turkish Lir1.00",
6522         "Turkmenistani Mana1.00",
6523         "U S1.00",
6524         "U1.00",
6525         "UA1.00",
6526         "UG1.00",
6527         "US Dolla1.00",
6528         "US Dollar (Next day1.00",
6529         "US Dollar (Same day1.00",
6530         "US1.00",
6531         "UY1.00",
6532         "UZ1.00",
6533         "Ugandan Shillin1.00",
6534         "Ugandan Shilling (1966\\u201319871.00",
6535         "Ukrainian Hryvni1.00",
6536         "Ukrainian Karbovanet1.00",
6537         "Colombian Real Value Uni1.00",
6538         "United Arab Emirates Dirha1.00",
6539         "Unknown Currenc1.00",
6540         "Ur1.00",
6541         "Uruguay Peso (1975\\u201319931.00",
6542         "Uruguay Peso Uruguay1.00",
6543         "Uruguay Peso (Indexed Units1.00",
6544         "Uzbekistani So1.00",
6545         "V1.00",
6546         "VE1.00",
6547         "VN1.00",
6548         "VU1.00",
6549         "Vanuatu Vat1.00",
6550         "Venezuelan Bol\\u00edva1.00",
6551         "Venezuelan Bol\\u00edvar Fuert1.00",
6552         "Vietnamese Don1.00",
6553         "West African CFA Fran1.00",
6554         "Central African CFA Fran1.00",
6555         "WIR Eur1.00",
6556         "WIR Fran1.00",
6557         "WS1.00",
6558         "Samoa Tal1.00",
6559         "XA1.00",
6560         "XB1.00",
6561         "XC1.00",
6562         "XD1.00",
6563         "XE1.00",
6564         "XF1.00",
6565         "XO1.00",
6566         "XP1.00",
6567         "XR1.00",
6568         "XT1.00",
6569         "XX1.00",
6570         "YD1.00",
6571         "YE1.00",
6572         "YU1.00",
6573         "Yemeni Dina1.00",
6574         "Yemeni Ria1.00",
6575         "Yugoslavian Convertible Dina1.00",
6576         "Yugoslavian Hard Dinar (1966\\u201319901.00",
6577         "Yugoslavian New Dina1.00",
6578         "Z1.00",
6579         "ZA1.00",
6580         "ZM1.00",
6581         "ZR1.00",
6582         "ZW1.00",
6583         "Zairean New Zaire (1993\\u201319981.00",
6584         "Zairean Zair1.00",
6585         "Zambian Kwach1.00",
6586         "Zimbabwean Dollar (1980\\u201320081.00",
6587         "dra1.00",
6588         "lar1.00",
6589         "le1.00",
6590         "man1.00",
6591         "so1.00",
6592     };
6593 
6594     Locale locale("en_US");
6595     for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
6596         UnicodeString formatted = ctou(DATA[i]);
6597         UErrorCode status = U_ZERO_ERROR;
6598         LocalPointer<NumberFormat> numFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status), status);
6599         if (!assertSuccess("", status, true, __FILE__, __LINE__)) {
6600             return;
6601         }
6602         // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
6603         numFmt->setLenient(TRUE);
6604         ParsePosition parsePos;
6605         LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6606         if (parsePos.getIndex() > 0) {
6607             double doubleVal = currAmt->getNumber().getDouble(status);
6608             if ( doubleVal != 1.0 ) {
6609                 errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
6610             }
6611         } else {
6612             errln("Failed to parse as currency: " + formatted);
6613         }
6614     }
6615 
6616     for (uint32_t i=0; i<UPRV_LENGTHOF(WRONG_DATA); ++i) {
6617       UnicodeString formatted = ctou(WRONG_DATA[i]);
6618       UErrorCode status = U_ZERO_ERROR;
6619       NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6620       if (numFmt != NULL && U_SUCCESS(status)) {
6621           ParsePosition parsePos;
6622           LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6623           if (parsePos.getIndex() > 0) {
6624               double doubleVal = currAmt->getNumber().getDouble(status);
6625               errln("Parsed as currency, should not have: " + formatted + " -> " + doubleVal);
6626           }
6627       } else {
6628           dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));
6629           delete numFmt;
6630           break;
6631       }
6632       delete numFmt;
6633     }
6634 }
6635 
6636 const char* attrString(int32_t);
6637 
6638 // UnicodeString s;
6639 //  std::string ss;
6640 //  std::cout << s.toUTF8String(ss)
expectPositions(FieldPositionIterator & iter,int32_t * values,int32_t tupleCount,const UnicodeString & str)6641 void NumberFormatTest::expectPositions(FieldPositionIterator& iter, int32_t *values, int32_t tupleCount,
6642                                        const UnicodeString& str)  {
6643   UBool found[10];
6644   FieldPosition fp;
6645 
6646   if (tupleCount > 10) {
6647     assertTrue("internal error, tupleCount too large", FALSE);
6648   } else {
6649     for (int i = 0; i < tupleCount; ++i) {
6650       found[i] = FALSE;
6651     }
6652   }
6653 
6654   logln(str);
6655   while (iter.next(fp)) {
6656     UBool ok = FALSE;
6657     int32_t id = fp.getField();
6658     int32_t start = fp.getBeginIndex();
6659     int32_t limit = fp.getEndIndex();
6660 
6661     // is there a logln using printf?
6662     char buf[128];
6663     sprintf(buf, "%24s %3d %3d %3d", attrString(id), id, start, limit);
6664     logln(buf);
6665 
6666     for (int i = 0; i < tupleCount; ++i) {
6667       if (found[i]) {
6668         continue;
6669       }
6670       if (values[i*3] == id &&
6671           values[i*3+1] == start &&
6672           values[i*3+2] == limit) {
6673         found[i] = ok = TRUE;
6674         break;
6675       }
6676     }
6677 
6678     assertTrue((UnicodeString)"found [" + id + "," + start + "," + limit + "]", ok);
6679   }
6680 
6681   // check that all were found
6682   UBool ok = TRUE;
6683   for (int i = 0; i < tupleCount; ++i) {
6684     if (!found[i]) {
6685       ok = FALSE;
6686       assertTrue((UnicodeString) "missing [" + values[i*3] + "," + values[i*3+1] + "," + values[i*3+2] + "]", found[i]);
6687     }
6688   }
6689   assertTrue("no expected values were missing", ok);
6690 }
6691 
expectPosition(FieldPosition & pos,int32_t id,int32_t start,int32_t limit,const UnicodeString & str)6692 void NumberFormatTest::expectPosition(FieldPosition& pos, int32_t id, int32_t start, int32_t limit,
6693                                        const UnicodeString& str)  {
6694   logln(str);
6695   assertTrue((UnicodeString)"id " + id + " == " + pos.getField(), id == pos.getField());
6696   assertTrue((UnicodeString)"begin " + start + " == " + pos.getBeginIndex(), start == pos.getBeginIndex());
6697   assertTrue((UnicodeString)"end " + limit + " == " + pos.getEndIndex(), limit == pos.getEndIndex());
6698 }
6699 
TestFieldPositionIterator()6700 void NumberFormatTest::TestFieldPositionIterator() {
6701   // bug 7372
6702   UErrorCode status = U_ZERO_ERROR;
6703   FieldPositionIterator iter1;
6704   FieldPositionIterator iter2;
6705   FieldPosition pos;
6706 
6707   DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(status);
6708   if (failure(status, "NumberFormat::createInstance", TRUE)) return;
6709 
6710   double num = 1234.56;
6711   UnicodeString str1;
6712   UnicodeString str2;
6713 
6714   assertTrue((UnicodeString)"self==", iter1 == iter1);
6715   assertTrue((UnicodeString)"iter1==iter2", iter1 == iter2);
6716 
6717   decFmt->format(num, str1, &iter1, status);
6718   assertTrue((UnicodeString)"iter1 != iter2", iter1 != iter2);
6719   decFmt->format(num, str2, &iter2, status);
6720   assertTrue((UnicodeString)"iter1 == iter2 (2)", iter1 == iter2);
6721   iter1.next(pos);
6722   assertTrue((UnicodeString)"iter1 != iter2 (2)", iter1 != iter2);
6723   iter2.next(pos);
6724   assertTrue((UnicodeString)"iter1 == iter2 (3)", iter1 == iter2);
6725 
6726   // should format ok with no iterator
6727   str2.remove();
6728   decFmt->format(num, str2, NULL, status);
6729   assertEquals("null fpiter", str1, str2);
6730 
6731   delete decFmt;
6732 }
6733 
TestFormatAttributes()6734 void NumberFormatTest::TestFormatAttributes() {
6735   Locale locale("en_US");
6736   UErrorCode status = U_ZERO_ERROR;
6737   DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6738     if (failure(status, "NumberFormat::createInstance", TRUE)) return;
6739   double val = 12345.67;
6740 
6741   {
6742     int32_t expected[] = {
6743       UNUM_CURRENCY_FIELD, 0, 1,
6744       UNUM_GROUPING_SEPARATOR_FIELD, 3, 4,
6745       UNUM_INTEGER_FIELD, 1, 7,
6746       UNUM_DECIMAL_SEPARATOR_FIELD, 7, 8,
6747       UNUM_FRACTION_FIELD, 8, 10,
6748     };
6749     int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6750 
6751     FieldPositionIterator posIter;
6752     UnicodeString result;
6753     decFmt->format(val, result, &posIter, status);
6754     expectPositions(posIter, expected, tupleCount, result);
6755   }
6756   {
6757     FieldPosition fp(UNUM_INTEGER_FIELD);
6758     UnicodeString result;
6759     decFmt->format(val, result, fp);
6760     expectPosition(fp, UNUM_INTEGER_FIELD, 1, 7, result);
6761   }
6762   {
6763     FieldPosition fp(UNUM_FRACTION_FIELD);
6764     UnicodeString result;
6765     decFmt->format(val, result, fp);
6766     expectPosition(fp, UNUM_FRACTION_FIELD, 8, 10, result);
6767   }
6768   delete decFmt;
6769 
6770   decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_SCIENTIFIC, status);
6771   val = -0.0000123;
6772   {
6773     int32_t expected[] = {
6774       UNUM_SIGN_FIELD, 0, 1,
6775       UNUM_INTEGER_FIELD, 1, 2,
6776       UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3,
6777       UNUM_FRACTION_FIELD, 3, 5,
6778       UNUM_EXPONENT_SYMBOL_FIELD, 5, 6,
6779       UNUM_EXPONENT_SIGN_FIELD, 6, 7,
6780       UNUM_EXPONENT_FIELD, 7, 8
6781     };
6782     int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6783 
6784     FieldPositionIterator posIter;
6785     UnicodeString result;
6786     decFmt->format(val, result, &posIter, status);
6787     expectPositions(posIter, expected, tupleCount, result);
6788   }
6789   {
6790     FieldPosition fp(UNUM_INTEGER_FIELD);
6791     UnicodeString result;
6792     decFmt->format(val, result, fp);
6793     expectPosition(fp, UNUM_INTEGER_FIELD, 1, 2, result);
6794   }
6795   {
6796     FieldPosition fp(UNUM_FRACTION_FIELD);
6797     UnicodeString result;
6798     decFmt->format(val, result, fp);
6799     expectPosition(fp, UNUM_FRACTION_FIELD, 3, 5, result);
6800   }
6801   delete decFmt;
6802 
6803   fflush(stderr);
6804 }
6805 
attrString(int32_t attrId)6806 const char* attrString(int32_t attrId) {
6807   switch (attrId) {
6808     case UNUM_INTEGER_FIELD: return "integer";
6809     case UNUM_FRACTION_FIELD: return "fraction";
6810     case UNUM_DECIMAL_SEPARATOR_FIELD: return "decimal separator";
6811     case UNUM_EXPONENT_SYMBOL_FIELD: return "exponent symbol";
6812     case UNUM_EXPONENT_SIGN_FIELD: return "exponent sign";
6813     case UNUM_EXPONENT_FIELD: return "exponent";
6814     case UNUM_GROUPING_SEPARATOR_FIELD: return "grouping separator";
6815     case UNUM_CURRENCY_FIELD: return "currency";
6816     case UNUM_PERCENT_FIELD: return "percent";
6817     case UNUM_PERMILL_FIELD: return "permille";
6818     case UNUM_SIGN_FIELD: return "sign";
6819     default: return "";
6820   }
6821 }
6822 
6823 //
6824 //   Test formatting & parsing of big decimals.
6825 //      API test, not a comprehensive test.
6826 //      See DecimalFormatTest/DataDrivenTests
6827 //
6828 #define ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \
6829     assertSuccess(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (status)); \
6830 } UPRV_BLOCK_MACRO_END
6831 #define ASSERT_EQUALS(expected, actual) UPRV_BLOCK_MACRO_BEGIN { \
6832     assertEquals(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (expected), (actual)); \
6833 } UPRV_BLOCK_MACRO_END
6834 
TestDecimal()6835 void NumberFormatTest::TestDecimal() {
6836     {
6837         UErrorCode  status = U_ZERO_ERROR;
6838         Formattable f("12.345678999987654321E666", status);
6839         ASSERT_SUCCESS(status);
6840         StringPiece s = f.getDecimalNumber(status);
6841         ASSERT_SUCCESS(status);
6842         ASSERT_EQUALS("1.2345678999987654321E+667", s.data());
6843         //printf("%s\n", s.data());
6844     }
6845 
6846     {
6847         UErrorCode status = U_ZERO_ERROR;
6848         Formattable f1("this is not a number", status);
6849         ASSERT_EQUALS(U_DECIMAL_NUMBER_SYNTAX_ERROR, status);
6850     }
6851 
6852     {
6853         UErrorCode status = U_ZERO_ERROR;
6854         Formattable f;
6855         f.setDecimalNumber("123.45", status);
6856         ASSERT_SUCCESS(status);
6857         ASSERT_EQUALS( Formattable::kDouble, f.getType());
6858         ASSERT_EQUALS(123.45, f.getDouble());
6859         ASSERT_EQUALS(123.45, f.getDouble(status));
6860         ASSERT_SUCCESS(status);
6861         ASSERT_EQUALS("123.45", f.getDecimalNumber(status).data());
6862         ASSERT_SUCCESS(status);
6863 
6864         f.setDecimalNumber("4.5678E7", status);
6865         int32_t n;
6866         n = f.getLong();
6867         ASSERT_EQUALS(45678000, n);
6868 
6869         status = U_ZERO_ERROR;
6870         f.setDecimalNumber("-123", status);
6871         ASSERT_SUCCESS(status);
6872         ASSERT_EQUALS( Formattable::kLong, f.getType());
6873         ASSERT_EQUALS(-123, f.getLong());
6874         ASSERT_EQUALS(-123, f.getLong(status));
6875         ASSERT_SUCCESS(status);
6876         ASSERT_EQUALS("-123", f.getDecimalNumber(status).data());
6877         ASSERT_SUCCESS(status);
6878 
6879         status = U_ZERO_ERROR;
6880         f.setDecimalNumber("1234567890123", status);  // Number too big for 32 bits
6881         ASSERT_SUCCESS(status);
6882         ASSERT_EQUALS( Formattable::kInt64, f.getType());
6883         ASSERT_EQUALS(1234567890123LL, f.getInt64());
6884         ASSERT_EQUALS(1234567890123LL, f.getInt64(status));
6885         ASSERT_SUCCESS(status);
6886         ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status).data());
6887         ASSERT_SUCCESS(status);
6888     }
6889 
6890     {
6891         UErrorCode status = U_ZERO_ERROR;
6892         NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6893         if (U_FAILURE(status) || fmtr == NULL) {
6894             dataerrln("Unable to create NumberFormat");
6895         } else {
6896             UnicodeString formattedResult;
6897             StringPiece num("244444444444444444444444444444444444446.4");
6898             fmtr->format(num, formattedResult, NULL, status);
6899             ASSERT_SUCCESS(status);
6900             ASSERT_EQUALS("244,444,444,444,444,444,444,444,444,444,444,444,446.4", formattedResult);
6901             //std::string ss; std::cout << formattedResult.toUTF8String(ss);
6902             delete fmtr;
6903         }
6904     }
6905 
6906     {
6907         // Check formatting a DigitList.  DigitList is internal, but this is
6908         // a critical interface that must work.
6909         UErrorCode status = U_ZERO_ERROR;
6910         NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6911         if (U_FAILURE(status) || fmtr == NULL) {
6912             dataerrln("Unable to create NumberFormat");
6913         } else {
6914             UnicodeString formattedResult;
6915             DecimalQuantity dl;
6916             StringPiece num("123.4566666666666666666666666666666666621E+40");
6917             dl.setToDecNumber(num, status);
6918             ASSERT_SUCCESS(status);
6919             fmtr->format(dl, formattedResult, NULL, status);
6920             ASSERT_SUCCESS(status);
6921             ASSERT_EQUALS("1,234,566,666,666,666,666,666,666,666,666,666,666,621,000", formattedResult);
6922 
6923             status = U_ZERO_ERROR;
6924             num.set("666.666");
6925             dl.setToDecNumber(num, status);
6926             FieldPosition pos(NumberFormat::FRACTION_FIELD);
6927             ASSERT_SUCCESS(status);
6928             formattedResult.remove();
6929             fmtr->format(dl, formattedResult, pos, status);
6930             ASSERT_SUCCESS(status);
6931             ASSERT_EQUALS("666.666", formattedResult);
6932             ASSERT_EQUALS(4, pos.getBeginIndex());
6933             ASSERT_EQUALS(7, pos.getEndIndex());
6934             delete fmtr;
6935         }
6936     }
6937 
6938     {
6939         // Check a parse with a formatter with a multiplier.
6940         UErrorCode status = U_ZERO_ERROR;
6941         NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_PERCENT, status);
6942         if (U_FAILURE(status) || fmtr == NULL) {
6943             dataerrln("Unable to create NumberFormat");
6944         } else {
6945             UnicodeString input = "1.84%";
6946             Formattable result;
6947             fmtr->parse(input, result, status);
6948             ASSERT_SUCCESS(status);
6949             ASSERT_EQUALS("0.0184", result.getDecimalNumber(status).data());
6950             //std::cout << result.getDecimalNumber(status).data();
6951             delete fmtr;
6952         }
6953     }
6954 
6955 #if U_PLATFORM != U_PF_CYGWIN || defined(CYGWINMSVC)
6956     /*
6957      * This test fails on Cygwin (1.7.16) using GCC because of a rounding issue with strtod().
6958      * See #9463
6959      */
6960     {
6961         // Check that a parse returns a decimal number with full accuracy
6962         UErrorCode status = U_ZERO_ERROR;
6963         NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6964         if (U_FAILURE(status) || fmtr == NULL) {
6965             dataerrln("Unable to create NumberFormat");
6966         } else {
6967             UnicodeString input = "1.002200044400088880000070000";
6968             Formattable result;
6969             fmtr->parse(input, result, status);
6970             ASSERT_SUCCESS(status);
6971             ASSERT_EQUALS(0, strcmp("1.00220004440008888000007", result.getDecimalNumber(status).data()));
6972             ASSERT_EQUALS(1.00220004440008888,   result.getDouble());
6973             //std::cout << result.getDecimalNumber(status).data();
6974             delete fmtr;
6975         }
6976     }
6977 #endif
6978 
6979 }
6980 
TestCurrencyFractionDigits()6981 void NumberFormatTest::TestCurrencyFractionDigits() {
6982     UErrorCode status = U_ZERO_ERROR;
6983     UnicodeString text1, text2;
6984     double value = 99.12345;
6985 
6986     // Create currenct instance
6987     NumberFormat* fmt = NumberFormat::createCurrencyInstance("ja_JP", status);
6988     if (U_FAILURE(status) || fmt == NULL) {
6989         dataerrln("Unable to create NumberFormat");
6990     } else {
6991         fmt->format(value, text1);
6992 
6993         // Reset the same currency and format the test value again
6994         fmt->setCurrency(fmt->getCurrency(), status);
6995         ASSERT_SUCCESS(status);
6996         fmt->format(value, text2);
6997 
6998         if (text1 != text2) {
6999             errln((UnicodeString)"NumberFormat::format() should return the same result - text1="
7000                 + text1 + " text2=" + text2);
7001         }
7002     }
7003     delete fmt;
7004 }
7005 
TestExponentParse()7006 void NumberFormatTest::TestExponentParse() {
7007 
7008     UErrorCode status = U_ZERO_ERROR;
7009     Formattable result;
7010     ParsePosition parsePos(0);
7011 
7012     // set the exponent symbol
7013     status = U_ZERO_ERROR;
7014     DecimalFormatSymbols symbols(Locale::getDefault(), status);
7015     if(U_FAILURE(status)) {
7016         dataerrln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (Default)");
7017         return;
7018     }
7019 
7020     // create format instance
7021     status = U_ZERO_ERROR;
7022     DecimalFormat fmt(u"#####", symbols, status);
7023     if(U_FAILURE(status)) {
7024         errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
7025     }
7026 
7027     // parse the text
7028     fmt.parse("5.06e-27", result, parsePos);
7029     if(result.getType() != Formattable::kDouble &&
7030        result.getDouble() != 5.06E-27 &&
7031        parsePos.getIndex() != 8
7032        )
7033     {
7034         errln("ERROR: parse failed - expected 5.06E-27, 8  - returned %d, %i",
7035               result.getDouble(), parsePos.getIndex());
7036     }
7037 }
7038 
TestExplicitParents()7039 void NumberFormatTest::TestExplicitParents() {
7040 
7041     /* Test that number formats are properly inherited from es_419 */
7042     /* These could be subject to change if the CLDR data changes */
7043     static const char* parentLocaleTests[][2]= {
7044     /* locale ID */  /* expected */
7045     {"es_CO", "1.250,75" },
7046     {"es_ES", "1.250,75" },
7047     {"es_GQ", "1.250,75" },
7048     {"es_MX", "1,250.75" },
7049     {"es_US", "1,250.75" },
7050     {"es_VE", "1.250,75" },
7051     };
7052 
7053     UnicodeString s;
7054 
7055     for(int i=0; i < UPRV_LENGTHOF(parentLocaleTests); i++){
7056         UErrorCode status = U_ZERO_ERROR;
7057         const char *localeID = parentLocaleTests[i][0];
7058         UnicodeString expected(parentLocaleTests[i][1], -1, US_INV);
7059         expected = expected.unescape();
7060         char loc[256]={0};
7061         uloc_canonicalize(localeID, loc, 256, &status);
7062         NumberFormat *fmt= NumberFormat::createInstance(Locale(loc), status);
7063         if(U_FAILURE(status)){
7064             dataerrln("Could not create number formatter for locale %s - %s",localeID, u_errorName(status));
7065             continue;
7066         }
7067         s.remove();
7068         fmt->format(1250.75, s);
7069         if(s!=expected){
7070             errln(UnicodeString("FAIL: Expected: ")+expected
7071                     + UnicodeString(" Got: ") + s
7072                     + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
7073         }
7074         if (U_FAILURE(status)){
7075             errln((UnicodeString)"FAIL: Status " + (int32_t)status);
7076         }
7077         delete fmt;
7078     }
7079 
7080 }
7081 
7082 /**
7083  * Test available numbering systems API.
7084  */
TestAvailableNumberingSystems()7085 void NumberFormatTest::TestAvailableNumberingSystems() {
7086     IcuTestErrorCode status(*this, "TestAvailableNumberingSystems");
7087     StringEnumeration *availableNumberingSystems = NumberingSystem::getAvailableNames(status);
7088     CHECK_DATA(status, "NumberingSystem::getAvailableNames()");
7089 
7090     int32_t nsCount = availableNumberingSystems->count(status);
7091     if ( nsCount < 74 ) {
7092         errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 74, got %d",nsCount);
7093     }
7094 
7095     /* A relatively simple test of the API.  We call getAvailableNames() and cycle through */
7096     /* each name returned, attempting to create a numbering system based on that name and  */
7097     /* verifying that the name returned from the resulting numbering system is the same    */
7098     /* one that we initially thought.                                                      */
7099 
7100     int32_t len;
7101     const char* prevName = nullptr;
7102     for ( int32_t i = 0 ; i < nsCount ; i++ ) {
7103         const char *nsname = availableNumberingSystems->next(&len,status);
7104         NumberingSystem* ns = NumberingSystem::createInstanceByName(nsname,status);
7105         logln("OK for ns = %s",nsname);
7106         if ( uprv_strcmp(nsname,ns->getName()) ) {
7107             errln("FAIL: Numbering system name didn't match for name = %s\n",nsname);
7108         }
7109         if (prevName != nullptr) {
7110             int comp = uprv_strcmp(prevName, nsname);
7111             assertTrue(
7112                 UnicodeString(u"NS names should be in alphabetical order: ")
7113                     + prevName + u" vs " + nsname,
7114                 // TODO: Why are there duplicates? This doesn't work if comp < 0
7115                 comp <= 0);
7116         }
7117         prevName = nsname;
7118 
7119         delete ns;
7120     }
7121 
7122     LocalPointer<NumberingSystem> dummy(NumberingSystem::createInstanceByName("dummy", status), status);
7123     status.expectErrorAndReset(U_UNSUPPORTED_ERROR);
7124     assertTrue("Non-existent numbering system should return null", dummy.isNull());
7125 
7126     delete availableNumberingSystems;
7127 }
7128 
7129 void
Test9087(void)7130 NumberFormatTest::Test9087(void)
7131 {
7132     U_STRING_DECL(pattern,"#",1);
7133     U_STRING_INIT(pattern,"#",1);
7134 
7135     U_STRING_DECL(infstr,"INF",3);
7136     U_STRING_INIT(infstr,"INF",3);
7137 
7138     U_STRING_DECL(nanstr,"NAN",3);
7139     U_STRING_INIT(nanstr,"NAN",3);
7140 
7141     UChar outputbuf[50] = {0};
7142     UErrorCode status = U_ZERO_ERROR;
7143     UNumberFormat* fmt = unum_open(UNUM_PATTERN_DECIMAL,pattern,1,NULL,NULL,&status);
7144     if ( U_FAILURE(status) ) {
7145         dataerrln("FAIL: error in unum_open() - %s", u_errorName(status));
7146         return;
7147     }
7148 
7149     unum_setSymbol(fmt,UNUM_INFINITY_SYMBOL,infstr,3,&status);
7150     unum_setSymbol(fmt,UNUM_NAN_SYMBOL,nanstr,3,&status);
7151     if ( U_FAILURE(status) ) {
7152         errln("FAIL: error setting symbols");
7153     }
7154 
7155     double inf = uprv_getInfinity();
7156 
7157     unum_setAttribute(fmt,UNUM_ROUNDING_MODE,UNUM_ROUND_HALFEVEN);
7158     unum_setDoubleAttribute(fmt,UNUM_ROUNDING_INCREMENT,0);
7159 
7160     UFieldPosition position = { 0, 0, 0};
7161     unum_formatDouble(fmt,inf,outputbuf,50,&position,&status);
7162 
7163     if ( u_strcmp(infstr, outputbuf)) {
7164         errln((UnicodeString)"FAIL: unexpected result for infinity - expected " + infstr + " got " + outputbuf);
7165     }
7166 
7167     unum_close(fmt);
7168 }
7169 
TestFormatFastpaths()7170 void NumberFormatTest::TestFormatFastpaths() {
7171     // get some additional case
7172     {
7173         UErrorCode status=U_ZERO_ERROR;
7174         DecimalFormat df(UnicodeString(u"0000"),status);
7175         if (U_FAILURE(status)) {
7176             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7177         } else {
7178             int64_t long_number = 1;
7179             UnicodeString expect = "0001";
7180             UnicodeString result;
7181             FieldPosition pos;
7182             df.format(long_number, result, pos);
7183             if(U_FAILURE(status)||expect!=result) {
7184                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s",
7185                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7186              } else {
7187                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
7188             }
7189         }
7190     }
7191     {
7192         UErrorCode status=U_ZERO_ERROR;
7193         DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7194         if (U_FAILURE(status)) {
7195             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7196         } else {
7197             int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
7198             // uint8_t bits[8];
7199             // memcpy(bits,&long_number,8);
7200             // for(int i=0;i<8;i++) {
7201             //   logln("bits: %02X", (unsigned int)bits[i]);
7202             // }
7203             UnicodeString expect = "-9223372036854775808";
7204             UnicodeString result;
7205             FieldPosition pos;
7206             df.format(long_number, result, pos);
7207             if(U_FAILURE(status)||expect!=result) {
7208                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775808",
7209                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7210             } else {
7211                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
7212             }
7213         }
7214     }
7215     {
7216         UErrorCode status=U_ZERO_ERROR;
7217         DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7218         if (U_FAILURE(status)) {
7219             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7220         } else {
7221             int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
7222             // uint8_t bits[8];
7223             // memcpy(bits,&long_number,8);
7224             // for(int i=0;i<8;i++) {
7225             //   logln("bits: %02X", (unsigned int)bits[i]);
7226             // }
7227             UnicodeString expect = "9223372036854775807";
7228             UnicodeString result;
7229             FieldPosition pos;
7230             df.format(long_number, result, pos);
7231             if(U_FAILURE(status)||expect!=result) {
7232                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on U_INT64_MAX",
7233                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7234             } else {
7235                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
7236             }
7237         }
7238     }
7239     {
7240         UErrorCode status=U_ZERO_ERROR;
7241         DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7242         if (U_FAILURE(status)) {
7243             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7244         } else {
7245             int64_t long_number = 0;
7246             // uint8_t bits[8];
7247             // memcpy(bits,&long_number,8);
7248             // for(int i=0;i<8;i++) {
7249             //   logln("bits: %02X", (unsigned int)bits[i]);
7250             // }
7251             UnicodeString expect = "0000000000000000000";
7252             UnicodeString result;
7253             FieldPosition pos;
7254             df.format(long_number, result, pos);
7255             if(U_FAILURE(status)||expect!=result) {
7256                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on 0",
7257                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7258             } else {
7259                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
7260             }
7261         }
7262     }
7263     {
7264         UErrorCode status=U_ZERO_ERROR;
7265         DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7266         if (U_FAILURE(status)) {
7267             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7268         } else {
7269             int64_t long_number = U_INT64_MIN + 1;
7270             UnicodeString expect = "-9223372036854775807";
7271             UnicodeString result;
7272             FieldPosition pos;
7273             df.format(long_number, result, pos);
7274             if(U_FAILURE(status)||expect!=result) {
7275                 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775807",
7276                           __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7277             } else {
7278                 logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
7279             }
7280         }
7281     }
7282 }
7283 
7284 
TestFormattableSize(void)7285 void NumberFormatTest::TestFormattableSize(void) {
7286   if(sizeof(Formattable) > 112) {
7287     errln("Error: sizeof(Formattable)=%d, 112=%d\n",
7288           sizeof(Formattable), 112);
7289   } else if(sizeof(Formattable) < 112) {
7290     logln("Warning: sizeof(Formattable)=%d, 112=%d\n",
7291         sizeof(Formattable), 112);
7292   } else {
7293     logln("sizeof(Formattable)=%d, 112=%d\n",
7294         sizeof(Formattable), 112);
7295   }
7296 }
7297 
testFormattableAsUFormattable(const char * file,int line,Formattable & f)7298 UBool NumberFormatTest::testFormattableAsUFormattable(const char *file, int line, Formattable &f) {
7299   UnicodeString fileLine = UnicodeString(file)+UnicodeString(":")+line+UnicodeString(": ");
7300 
7301   UFormattable *u = f.toUFormattable();
7302   logln();
7303   if (u == NULL) {
7304     errln("%s:%d: Error: f.toUFormattable() retuned NULL.");
7305     return FALSE;
7306   }
7307   logln("%s:%d: comparing Formattable with UFormattable", file, line);
7308   logln(fileLine + toString(f));
7309 
7310   UErrorCode status = U_ZERO_ERROR;
7311   UErrorCode valueStatus = U_ZERO_ERROR;
7312   UFormattableType expectUType = UFMT_COUNT; // invalid
7313 
7314   UBool triedExact = FALSE; // did we attempt an exact comparison?
7315   UBool exactMatch = FALSE; // was the exact comparison true?
7316 
7317   switch( f.getType() ) {
7318   case Formattable::kDate:
7319     expectUType = UFMT_DATE;
7320     exactMatch = (f.getDate()==ufmt_getDate(u, &valueStatus));
7321     triedExact = TRUE;
7322     break;
7323   case Formattable::kDouble:
7324     expectUType = UFMT_DOUBLE;
7325     exactMatch = (f.getDouble()==ufmt_getDouble(u, &valueStatus));
7326     triedExact = TRUE;
7327     break;
7328   case Formattable::kLong:
7329     expectUType = UFMT_LONG;
7330     exactMatch = (f.getLong()==ufmt_getLong(u, &valueStatus));
7331     triedExact = TRUE;
7332     break;
7333   case Formattable::kString:
7334     expectUType = UFMT_STRING;
7335     {
7336       UnicodeString str;
7337       f.getString(str);
7338       int32_t len;
7339       const UChar* uch = ufmt_getUChars(u, &len, &valueStatus);
7340       if(U_SUCCESS(valueStatus)) {
7341         UnicodeString str2(uch, len);
7342         assertTrue("UChar* NULL-terminated", uch[len]==0);
7343         exactMatch = (str == str2);
7344       }
7345       triedExact = TRUE;
7346     }
7347     break;
7348   case Formattable::kArray:
7349     expectUType = UFMT_ARRAY;
7350     triedExact = TRUE;
7351     {
7352       int32_t count = ufmt_getArrayLength(u, &valueStatus);
7353       int32_t count2;
7354       const Formattable *array2 = f.getArray(count2);
7355       exactMatch = assertEquals(fileLine + " array count", count, count2);
7356 
7357       if(exactMatch) {
7358         for(int i=0;U_SUCCESS(valueStatus) && i<count;i++) {
7359           UFormattable *uu = ufmt_getArrayItemByIndex(u, i, &valueStatus);
7360           if(*Formattable::fromUFormattable(uu) != (array2[i])) {
7361             errln("%s:%d: operator== did not match at index[%d] - %p vs %p", file, line, i,
7362                   (const void*)Formattable::fromUFormattable(uu), (const void*)&(array2[i]));
7363             exactMatch = FALSE;
7364           } else {
7365             if(!testFormattableAsUFormattable("(sub item)",i,*Formattable::fromUFormattable(uu))) {
7366               exactMatch = FALSE;
7367             }
7368           }
7369         }
7370       }
7371     }
7372     break;
7373   case Formattable::kInt64:
7374     expectUType = UFMT_INT64;
7375     exactMatch = (f.getInt64()==ufmt_getInt64(u, &valueStatus));
7376     triedExact = TRUE;
7377     break;
7378   case Formattable::kObject:
7379     expectUType = UFMT_OBJECT;
7380     exactMatch = (f.getObject()==ufmt_getObject(u, &valueStatus));
7381     triedExact = TRUE;
7382     break;
7383   }
7384   UFormattableType uType = ufmt_getType(u, &status);
7385 
7386   if(U_FAILURE(status)) {
7387     errln("%s:%d: Error calling ufmt_getType - %s", file, line, u_errorName(status));
7388     return FALSE;
7389   }
7390 
7391   if(uType != expectUType) {
7392     errln("%s:%d: got type (%d) expected (%d) from ufmt_getType", file, line, (int) uType, (int) expectUType);
7393   }
7394 
7395   if(triedExact) {
7396     if(U_FAILURE(valueStatus)) {
7397       errln("%s:%d: got err %s trying to ufmt_get...() for exact match check", file, line, u_errorName(valueStatus));
7398     } else if(!exactMatch) {
7399      errln("%s:%d: failed exact match for the Formattable type", file, line);
7400     } else {
7401       logln("%s:%d: exact match OK", file, line);
7402     }
7403   } else {
7404     logln("%s:%d: note, did not attempt exact match for this formattable type", file, line);
7405   }
7406 
7407   if( assertEquals(fileLine + " isNumeric()", f.isNumeric(), ufmt_isNumeric(u))
7408       && f.isNumeric()) {
7409     UErrorCode convStatus = U_ZERO_ERROR;
7410 
7411     if(uType != UFMT_INT64) { // may fail to compare
7412       assertTrue(fileLine + " as doubles ==", f.getDouble(convStatus)==ufmt_getDouble(u, &convStatus));
7413     }
7414 
7415     if( assertSuccess(fileLine + " (numeric conversion status)", convStatus) ) {
7416       StringPiece fDecNum = f.getDecimalNumber(convStatus);
7417 #if 1
7418       int32_t len;
7419       const char *decNumChars = ufmt_getDecNumChars(u, &len, &convStatus);
7420 #else
7421       // copy version
7422       char decNumChars[200];
7423       int32_t len = ufmt_getDecNumChars(u, decNumChars, 200, &convStatus);
7424 #endif
7425 
7426       if( assertSuccess(fileLine + " (decNumbers conversion)", convStatus) ) {
7427         logln(fileLine + decNumChars);
7428         assertEquals(fileLine + " decNumChars length==", len, fDecNum.length());
7429         assertEquals(fileLine + " decNumChars digits", decNumChars, fDecNum.data());
7430       }
7431 
7432       UErrorCode int64ConversionF = U_ZERO_ERROR;
7433       int64_t l = f.getInt64(int64ConversionF);
7434       UErrorCode int64ConversionU = U_ZERO_ERROR;
7435       int64_t r = ufmt_getInt64(u, &int64ConversionU);
7436 
7437       if( (l==r)
7438           && ( uType != UFMT_INT64 ) // int64 better not overflow
7439           && (U_INVALID_FORMAT_ERROR==int64ConversionU)
7440           && (U_INVALID_FORMAT_ERROR==int64ConversionF) ) {
7441         logln("%s:%d: OK: 64 bit overflow", file, line);
7442       } else {
7443         assertEquals(fileLine + " as int64 ==", l, r);
7444         assertSuccess(fileLine + " Formattable.getnt64()", int64ConversionF);
7445         assertSuccess(fileLine + " ufmt_getInt64()", int64ConversionU);
7446       }
7447     }
7448   }
7449   return exactMatch || !triedExact;
7450 }
7451 
TestUFormattable(void)7452 void NumberFormatTest::TestUFormattable(void) {
7453   {
7454     // test that a default formattable is equal to Formattable()
7455     UErrorCode status = U_ZERO_ERROR;
7456     LocalUFormattablePointer defaultUFormattable(ufmt_open(&status));
7457     assertSuccess("calling umt_open", status);
7458     Formattable defaultFormattable;
7459     assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7460                (defaultFormattable
7461                 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7462     assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7463                (defaultFormattable
7464                 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7465     assertTrue((UnicodeString)"comparing Formattable() round tripped through UFormattable",
7466                (defaultFormattable
7467                 == *(Formattable::fromUFormattable(defaultFormattable.toUFormattable()))));
7468     assertTrue((UnicodeString)"comparing &Formattable() round tripped through UFormattable",
7469                ((&defaultFormattable)
7470                 == Formattable::fromUFormattable(defaultFormattable.toUFormattable())));
7471     assertFalse((UnicodeString)"comparing &Formattable() with ufmt_open()",
7472                ((&defaultFormattable)
7473                 == Formattable::fromUFormattable(defaultUFormattable.getAlias())));
7474     testFormattableAsUFormattable(__FILE__, __LINE__, defaultFormattable);
7475   }
7476   // test some random Formattables
7477   {
7478     Formattable f(ucal_getNow(), Formattable::kIsDate);
7479     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7480   }
7481   {
7482     Formattable f((double)1.61803398874989484820); // golden ratio
7483     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7484   }
7485   {
7486     Formattable f((int64_t)80994231587905127LL); // weight of the moon, in kilotons http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
7487     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7488   }
7489   {
7490     Formattable f((int32_t)4); // random number, source: http://www.xkcd.com/221/
7491     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7492   }
7493   {
7494     Formattable f("Hello world."); // should be invariant?
7495     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7496   }
7497   {
7498     UErrorCode status2 = U_ZERO_ERROR;
7499     Formattable f(StringPiece("73476730924573500000000.0"), status2); // weight of the moon, kg
7500     assertSuccess("Constructing a StringPiece", status2);
7501     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7502   }
7503   {
7504     UErrorCode status2 = U_ZERO_ERROR;
7505     UObject *obj = new Locale();
7506     Formattable f(obj);
7507     assertSuccess("Constructing a Formattable from a default constructed Locale()", status2);
7508     testFormattableAsUFormattable(__FILE__, __LINE__,  f);
7509   }
7510   {
7511     const Formattable array[] = {
7512       Formattable(ucal_getNow(), Formattable::kIsDate),
7513       Formattable((int32_t)4),
7514       Formattable((double)1.234),
7515     };
7516 
7517     Formattable fa(array, 3);
7518     testFormattableAsUFormattable(__FILE__, __LINE__, fa);
7519   }
7520 }
7521 
TestSignificantDigits(void)7522 void NumberFormatTest::TestSignificantDigits(void) {
7523   double input[] = {
7524         0, 0,
7525         0.1, -0.1,
7526         123, -123,
7527         12345, -12345,
7528         123.45, -123.45,
7529         123.44501, -123.44501,
7530         0.001234, -0.001234,
7531         0.00000000123, -0.00000000123,
7532         0.0000000000000000000123, -0.0000000000000000000123,
7533         1.2, -1.2,
7534         0.0000000012344501, -0.0000000012344501,
7535         123445.01, -123445.01,
7536         12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0,
7537     };
7538     const char* expected[] = {
7539         "0.00", "0.00",
7540         "0.100", "-0.100",
7541         "123", "-123",
7542         "12345", "-12345",
7543         "123.45", "-123.45",
7544         "123.45", "-123.45",
7545         "0.001234", "-0.001234",
7546         "0.00000000123", "-0.00000000123",
7547         "0.0000000000000000000123", "-0.0000000000000000000123",
7548         "1.20", "-1.20",
7549         "0.0000000012345", "-0.0000000012345",
7550         "123450", "-123450",
7551         "12345000000000000000000000000000000", "-12345000000000000000000000000000000",
7552     };
7553 
7554     UErrorCode status = U_ZERO_ERROR;
7555     Locale locale("en_US");
7556     LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7557             NumberFormat::createInstance(locale, status)));
7558     CHECK_DATA(status,"NumberFormat::createInstance");
7559 
7560     numberFormat->setSignificantDigitsUsed(TRUE);
7561     numberFormat->setMinimumSignificantDigits(3);
7562     numberFormat->setMaximumSignificantDigits(5);
7563     numberFormat->setGroupingUsed(false);
7564 
7565     UnicodeString result;
7566     UnicodeString expectedResult;
7567     for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
7568         numberFormat->format(input[i], result);
7569         UnicodeString expectedResult(expected[i]);
7570         if (result != expectedResult) {
7571           errln((UnicodeString)"Expected: '" + expectedResult + "' got '" + result);
7572         }
7573         result.remove();
7574     }
7575 
7576     // Test for ICU-20063
7577     {
7578         DecimalFormat df({"en-us", status}, status);
7579         df.setSignificantDigitsUsed(TRUE);
7580         expect(df, 9.87654321, u"9.87654");
7581         df.setMaximumSignificantDigits(3);
7582         expect(df, 9.87654321, u"9.88");
7583         // setSignificantDigitsUsed with maxSig only
7584         df.setSignificantDigitsUsed(TRUE);
7585         expect(df, 9.87654321, u"9.88");
7586         df.setMinimumSignificantDigits(2);
7587         expect(df, 9, u"9.0");
7588         // setSignificantDigitsUsed with both minSig and maxSig
7589         df.setSignificantDigitsUsed(TRUE);
7590         expect(df, 9, u"9.0");
7591         // setSignificantDigitsUsed to false: should revert to fraction rounding
7592         df.setSignificantDigitsUsed(FALSE);
7593         expect(df, 9.87654321, u"9.876543");
7594         expect(df, 9, u"9");
7595         df.setSignificantDigitsUsed(TRUE);
7596         df.setMinimumSignificantDigits(2);
7597         expect(df, 9.87654321, u"9.87654");
7598         expect(df, 9, u"9.0");
7599         // setSignificantDigitsUsed with minSig only
7600         df.setSignificantDigitsUsed(TRUE);
7601         expect(df, 9.87654321, u"9.87654");
7602         expect(df, 9, u"9.0");
7603     }
7604 }
7605 
TestShowZero()7606 void NumberFormatTest::TestShowZero() {
7607     UErrorCode status = U_ZERO_ERROR;
7608     Locale locale("en_US");
7609     LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7610             NumberFormat::createInstance(locale, status)));
7611     CHECK_DATA(status, "NumberFormat::createInstance");
7612 
7613     numberFormat->setSignificantDigitsUsed(TRUE);
7614     numberFormat->setMaximumSignificantDigits(3);
7615 
7616     UnicodeString result;
7617     numberFormat->format(0.0, result);
7618     if (result != "0") {
7619         errln((UnicodeString)"Expected: 0, got " + result);
7620     }
7621 }
7622 
TestBug9936()7623 void NumberFormatTest::TestBug9936() {
7624     UErrorCode status = U_ZERO_ERROR;
7625     Locale locale("en_US");
7626     LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7627             NumberFormat::createInstance(locale, status)));
7628     if (U_FAILURE(status)) {
7629         dataerrln("File %s, Line %d: status = %s.\n", __FILE__, __LINE__, u_errorName(status));
7630         return;
7631     }
7632 
7633     if (numberFormat->areSignificantDigitsUsed() == TRUE) {
7634         errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
7635     }
7636     numberFormat->setSignificantDigitsUsed(TRUE);
7637     if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7638         errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7639     }
7640 
7641     numberFormat->setSignificantDigitsUsed(FALSE);
7642     if (numberFormat->areSignificantDigitsUsed() == TRUE) {
7643         errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
7644     }
7645 
7646     numberFormat->setMinimumSignificantDigits(3);
7647     if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7648         errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7649     }
7650 
7651     numberFormat->setSignificantDigitsUsed(FALSE);
7652     numberFormat->setMaximumSignificantDigits(6);
7653     if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7654         errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7655     }
7656 
7657 }
7658 
TestParseNegativeWithFaLocale()7659 void NumberFormatTest::TestParseNegativeWithFaLocale() {
7660     UErrorCode status = U_ZERO_ERROR;
7661     DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status);
7662     CHECK_DATA(status, "NumberFormat::createInstance");
7663     test->setLenient(TRUE);
7664     Formattable af;
7665     ParsePosition ppos;
7666     UnicodeString value("\\u200e-0,5");
7667     value = value.unescape();
7668     test->parse(value, af, ppos);
7669     if (ppos.getIndex() == 0) {
7670         errln("Expected -0,5 to parse for Farsi.");
7671     }
7672     delete test;
7673 }
7674 
TestParseNegativeWithAlternateMinusSign()7675 void NumberFormatTest::TestParseNegativeWithAlternateMinusSign() {
7676     UErrorCode status = U_ZERO_ERROR;
7677     DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("en", status);
7678     CHECK_DATA(status, "NumberFormat::createInstance");
7679     test->setLenient(TRUE);
7680     Formattable af;
7681     ParsePosition ppos;
7682     UnicodeString value("\\u208B0.5");
7683     value = value.unescape();
7684     test->parse(value, af, ppos);
7685     if (ppos.getIndex() == 0) {
7686         errln(UnicodeString("Expected ") + value + UnicodeString(" to parse."));
7687     }
7688     delete test;
7689 }
7690 
TestCustomCurrencySignAndSeparator()7691 void NumberFormatTest::TestCustomCurrencySignAndSeparator() {
7692     UErrorCode status = U_ZERO_ERROR;
7693     DecimalFormatSymbols custom(Locale::getUS(), status);
7694     CHECK(status, "DecimalFormatSymbols constructor");
7695 
7696     custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "*");
7697     custom.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, "^");
7698     custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, ":");
7699 
7700     UnicodeString pat(" #,##0.00");
7701     pat.insert(0, (UChar)0x00A4);
7702 
7703     DecimalFormat fmt(pat, custom, status);
7704     CHECK(status, "DecimalFormat constructor");
7705 
7706     UnicodeString numstr("* 1^234:56");
7707     expect2(fmt, (Formattable)((double)1234.56), numstr);
7708 }
7709 
7710 typedef struct {
7711     const char *   locale;
7712     UBool          lenient;
7713     UnicodeString  numString;
7714     double         value;
7715 } SignsAndMarksItem;
7716 
7717 
TestParseSignsAndMarks()7718 void NumberFormatTest::TestParseSignsAndMarks() {
7719     const SignsAndMarksItem items[] = {
7720         // locale               lenient numString                                                       value
7721         { "en",                 FALSE,  CharsToUnicodeString("12"),                                      12 },
7722         { "en",                 TRUE,   CharsToUnicodeString("12"),                                      12 },
7723         { "en",                 FALSE,  CharsToUnicodeString("-23"),                                    -23 },
7724         { "en",                 TRUE,   CharsToUnicodeString("-23"),                                    -23 },
7725         { "en",                 TRUE,   CharsToUnicodeString("- 23"),                                   -23 },
7726         { "en",                 FALSE,  CharsToUnicodeString("\\u200E-23"),                             -23 },
7727         { "en",                 TRUE,   CharsToUnicodeString("\\u200E-23"),                             -23 },
7728         { "en",                 TRUE,   CharsToUnicodeString("\\u200E- 23"),                            -23 },
7729 
7730         { "en@numbers=arab",    FALSE,  CharsToUnicodeString("\\u0663\\u0664"),                          34 },
7731         { "en@numbers=arab",    TRUE,   CharsToUnicodeString("\\u0663\\u0664"),                          34 },
7732         { "en@numbers=arab",    FALSE,  CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
7733         { "en@numbers=arab",    TRUE,   CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
7734         { "en@numbers=arab",    TRUE,   CharsToUnicodeString("- \\u0664\\u0665"),                       -45 },
7735         { "en@numbers=arab",    FALSE,  CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
7736         { "en@numbers=arab",    TRUE,   CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
7737         { "en@numbers=arab",    TRUE,   CharsToUnicodeString("\\u200F- \\u0664\\u0665"),                -45 },
7738 
7739         { "en@numbers=arabext", FALSE,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7740         { "en@numbers=arabext", TRUE,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7741         { "en@numbers=arabext", FALSE,  CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
7742         { "en@numbers=arabext", TRUE,   CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
7743         { "en@numbers=arabext", TRUE,   CharsToUnicodeString("- \\u06F6\\u06F7"),                       -67 },
7744         { "en@numbers=arabext", FALSE,  CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
7745         { "en@numbers=arabext", TRUE,   CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
7746         { "en@numbers=arabext", TRUE,   CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"),         -67 },
7747 
7748         { "he",                 FALSE,  CharsToUnicodeString("12"),                                      12 },
7749         { "he",                 TRUE,   CharsToUnicodeString("12"),                                      12 },
7750         { "he",                 FALSE,  CharsToUnicodeString("-23"),                                    -23 },
7751         { "he",                 TRUE,   CharsToUnicodeString("-23"),                                    -23 },
7752         { "he",                 TRUE,   CharsToUnicodeString("- 23"),                                   -23 },
7753         { "he",                 FALSE,  CharsToUnicodeString("\\u200E-23"),                             -23 },
7754         { "he",                 TRUE,   CharsToUnicodeString("\\u200E-23"),                             -23 },
7755         { "he",                 TRUE,   CharsToUnicodeString("\\u200E- 23"),                            -23 },
7756 
7757         { "ar",                 FALSE,  CharsToUnicodeString("\\u0663\\u0664"),                          34 },
7758         { "ar",                 TRUE,   CharsToUnicodeString("\\u0663\\u0664"),                          34 },
7759         { "ar",                 FALSE,  CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
7760         { "ar",                 TRUE,   CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
7761         { "ar",                 TRUE,   CharsToUnicodeString("- \\u0664\\u0665"),                       -45 },
7762         { "ar",                 FALSE,  CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
7763         { "ar",                 TRUE,   CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
7764         { "ar",                 TRUE,   CharsToUnicodeString("\\u200F- \\u0664\\u0665"),                -45 },
7765 
7766         { "ar_MA",              FALSE,  CharsToUnicodeString("12"),                                      12 },
7767         { "ar_MA",              TRUE,   CharsToUnicodeString("12"),                                      12 },
7768         { "ar_MA",              FALSE,  CharsToUnicodeString("-23"),                                    -23 },
7769         { "ar_MA",              TRUE,   CharsToUnicodeString("-23"),                                    -23 },
7770         { "ar_MA",              TRUE,   CharsToUnicodeString("- 23"),                                   -23 },
7771         { "ar_MA",              FALSE,  CharsToUnicodeString("\\u200E-23"),                             -23 },
7772         { "ar_MA",              TRUE,   CharsToUnicodeString("\\u200E-23"),                             -23 },
7773         { "ar_MA",              TRUE,   CharsToUnicodeString("\\u200E- 23"),                            -23 },
7774 
7775         { "fa",                 FALSE,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7776         { "fa",                 TRUE,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7777         { "fa",                 FALSE,  CharsToUnicodeString("\\u2212\\u06F6\\u06F7"),                  -67 },
7778         { "fa",                 TRUE,   CharsToUnicodeString("\\u2212\\u06F6\\u06F7"),                  -67 },
7779         { "fa",                 TRUE,   CharsToUnicodeString("\\u2212 \\u06F6\\u06F7"),                 -67 },
7780         { "fa",                 FALSE,  CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"),    -67 },
7781         { "fa",                 TRUE,   CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"),    -67 },
7782         { "fa",                 TRUE,   CharsToUnicodeString("\\u200E\\u2212\\u200E \\u06F6\\u06F7"),   -67 },
7783 
7784         { "ps",                 FALSE,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7785         { "ps",                 TRUE,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
7786         { "ps",                 FALSE,  CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
7787         { "ps",                 TRUE,   CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
7788         { "ps",                 TRUE,   CharsToUnicodeString("- \\u06F6\\u06F7"),                       -67 },
7789         { "ps",                 FALSE,  CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
7790         { "ps",                 TRUE,   CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
7791         { "ps",                 TRUE,   CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"),         -67 },
7792         { "ps",                 FALSE,  CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"),                 -67 },
7793         { "ps",                 TRUE,   CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"),                 -67 },
7794         { "ps",                 TRUE,   CharsToUnicodeString("-\\u200E \\u06F6\\u06F7"),                -67 },
7795         // terminator
7796         { NULL,                 0,      UnicodeString(""),                                                0 },
7797     };
7798 
7799     const SignsAndMarksItem * itemPtr;
7800     for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
7801         UErrorCode status = U_ZERO_ERROR;
7802         NumberFormat *numfmt = NumberFormat::createInstance(Locale(itemPtr->locale), status);
7803         if (U_SUCCESS(status)) {
7804             numfmt->setLenient(itemPtr->lenient);
7805             Formattable fmtobj;
7806             ParsePosition ppos;
7807             numfmt->parse(itemPtr->numString, fmtobj, ppos);
7808             if (ppos.getIndex() == itemPtr->numString.length()) {
7809                 double parsedValue = fmtobj.getDouble(status);
7810                 if (U_FAILURE(status) || parsedValue != itemPtr->value) {
7811                     errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives value " + parsedValue);
7812                 }
7813             } else {
7814                 errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives position " + ppos.getIndex());
7815             }
7816         } else {
7817             dataerrln("FAIL: NumberFormat::createInstance for locale % gives error %s", itemPtr->locale, u_errorName(status));
7818         }
7819         delete numfmt;
7820     }
7821 }
7822 
7823 typedef struct {
7824   DecimalFormat::ERoundingMode mode;
7825   double value;
7826   UnicodeString expected;
7827 } Test10419Data;
7828 
7829 
7830 // Tests that rounding works right when fractional digits is set to 0.
Test10419RoundingWith0FractionDigits()7831 void NumberFormatTest::Test10419RoundingWith0FractionDigits() {
7832     const Test10419Data items[] = {
7833         { DecimalFormat::kRoundCeiling, 1.488,  "2"},
7834         { DecimalFormat::kRoundDown, 1.588,  "1"},
7835         { DecimalFormat::kRoundFloor, 1.888,  "1"},
7836         { DecimalFormat::kRoundHalfDown, 1.5,  "1"},
7837         { DecimalFormat::kRoundHalfEven, 2.5,  "2"},
7838         { DecimalFormat::kRoundHalfUp, 2.5,  "3"},
7839         { DecimalFormat::kRoundUp, 1.5,  "2"},
7840     };
7841     UErrorCode status = U_ZERO_ERROR;
7842     LocalPointer<DecimalFormat> decfmt((DecimalFormat *) NumberFormat::createInstance(Locale("en_US"), status));
7843     if (U_FAILURE(status)) {
7844         dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
7845         return;
7846     }
7847     for (int32_t i = 0; i < UPRV_LENGTHOF(items); ++i) {
7848         decfmt->setRoundingMode(items[i].mode);
7849         decfmt->setMaximumFractionDigits(0);
7850         UnicodeString actual;
7851         if (items[i].expected != decfmt->format(items[i].value, actual)) {
7852             errln("Expected " + items[i].expected + ", got " + actual);
7853         }
7854     }
7855 }
7856 
Test10468ApplyPattern()7857 void NumberFormatTest::Test10468ApplyPattern() {
7858     // Padding char of fmt is now 'a'
7859     UErrorCode status = U_ZERO_ERROR;
7860     DecimalFormat fmt("'I''ll'*a###.##", status);
7861 
7862     if (U_FAILURE(status)) {
7863         errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7864         return;
7865     }
7866 
7867     assertEquals("Padding character should be 'a'.", u"a", fmt.getPadCharacterString());
7868 
7869     // Padding char of fmt ought to be '*' since that is the default and no
7870     // explicit padding char is specified in the new pattern.
7871     fmt.applyPattern("AA#,##0.00ZZ", status);
7872 
7873     // Oops this still prints 'a' even though we changed the pattern.
7874     assertEquals("applyPattern did not clear padding character.", u" ", fmt.getPadCharacterString());
7875 }
7876 
TestRoundingScientific10542()7877 void NumberFormatTest::TestRoundingScientific10542() {
7878     UErrorCode status = U_ZERO_ERROR;
7879     DecimalFormat format("0.00E0", status);
7880     if (U_FAILURE(status)) {
7881         errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7882         return;
7883     }
7884 
7885     DecimalFormat::ERoundingMode roundingModes[] = {
7886             DecimalFormat::kRoundCeiling,
7887             DecimalFormat::kRoundDown,
7888             DecimalFormat::kRoundFloor,
7889             DecimalFormat::kRoundHalfDown,
7890             DecimalFormat::kRoundHalfEven,
7891             DecimalFormat::kRoundHalfUp,
7892             DecimalFormat::kRoundUp};
7893     const char *descriptions[] = {
7894             "Round Ceiling",
7895             "Round Down",
7896             "Round Floor",
7897             "Round half down",
7898             "Round half even",
7899             "Round half up",
7900             "Round up"};
7901 
7902     {
7903         double values[] = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016};
7904         // The order of these expected values correspond to the order of roundingModes and the order of values.
7905         const char *expected[] = {
7906                 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.02E-3", "3.02E-3", "3.02E-3",
7907                 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7908                 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7909                 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.02E-3",
7910                 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7911                 "-3.01E-3", "-3.01E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7912                 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.02E-3", "3.02E-3", "3.02E-3"};
7913         verifyRounding(
7914                 format,
7915                 values,
7916                 expected,
7917                 roundingModes,
7918                 descriptions,
7919                 UPRV_LENGTHOF(values),
7920                 UPRV_LENGTHOF(roundingModes));
7921     }
7922     {
7923         double values[] = {-3006.0, -3005, -3004, 3014, 3015, 3016};
7924         // The order of these expected values correspond to the order of roundingModes and the order of values.
7925         const char *expected[] = {
7926                 "-3.00E3", "-3.00E3", "-3.00E3", "3.02E3", "3.02E3", "3.02E3",
7927                 "-3.00E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.01E3",
7928                 "-3.01E3", "-3.01E3", "-3.01E3", "3.01E3", "3.01E3", "3.01E3",
7929                 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.02E3",
7930                 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7931                 "-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7932                 "-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"};
7933         verifyRounding(
7934                 format,
7935                 values,
7936                 expected,
7937                 roundingModes,
7938                 descriptions,
7939                 UPRV_LENGTHOF(values),
7940                 UPRV_LENGTHOF(roundingModes));
7941     }
7942 /* Commented out for now until we decide how rounding to zero should work, +0 vs. -0
7943     {
7944         double values[] = {0.0, -0.0};
7945         // The order of these expected values correspond to the order of roundingModes and the order of values.
7946         const char *expected[] = {
7947                 "0.00E0", "-0.00E0",
7948                 "0.00E0", "-0.00E0",
7949                 "0.00E0", "-0.00E0",
7950                 "0.00E0", "-0.00E0",
7951                 "0.00E0", "-0.00E0",
7952                 "0.00E0", "-0.00E0",
7953                 "0.00E0", "-0.00E0"};
7954         verifyRounding(
7955                 format,
7956                 values,
7957                 expected,
7958                 roundingModes,
7959                 descriptions,
7960                 UPRV_LENGTHOF(values),
7961                 UPRV_LENGTHOF(roundingModes));
7962     }
7963 */
7964     {
7965 
7966         double values[] = {1e25, 1e25 + 1e15, 1e25 - 1e15};
7967         // The order of these expected values correspond to the order of roundingModes and the order of values.
7968         const char *expected[] = {
7969                 "1.00E25", "1.01E25", "1.00E25",
7970                 "1.00E25", "1.00E25", "9.99E24",
7971                 "1.00E25", "1.00E25", "9.99E24",
7972                 "1.00E25", "1.00E25", "1.00E25",
7973                 "1.00E25", "1.00E25", "1.00E25",
7974                 "1.00E25", "1.00E25", "1.00E25",
7975                 "1.00E25", "1.01E25", "1.00E25"};
7976         verifyRounding(
7977                 format,
7978                 values,
7979                 expected,
7980                 roundingModes,
7981                 descriptions,
7982                 UPRV_LENGTHOF(values),
7983                 UPRV_LENGTHOF(roundingModes));
7984         }
7985     {
7986         double values[] = {-1e25, -1e25 + 1e15, -1e25 - 1e15};
7987         // The order of these expected values correspond to the order of roundingModes and the order of values.
7988         const char *expected[] = {
7989                 "-1.00E25", "-9.99E24", "-1.00E25",
7990                 "-1.00E25", "-9.99E24", "-1.00E25",
7991                 "-1.00E25", "-1.00E25", "-1.01E25",
7992                 "-1.00E25", "-1.00E25", "-1.00E25",
7993                 "-1.00E25", "-1.00E25", "-1.00E25",
7994                 "-1.00E25", "-1.00E25", "-1.00E25",
7995                 "-1.00E25", "-1.00E25", "-1.01E25"};
7996         verifyRounding(
7997                 format,
7998                 values,
7999                 expected,
8000                 roundingModes,
8001                 descriptions,
8002                 UPRV_LENGTHOF(values),
8003                 UPRV_LENGTHOF(roundingModes));
8004         }
8005     {
8006         double values[] = {1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
8007         // The order of these expected values correspond to the order of roundingModes and the order of values.
8008         const char *expected[] = {
8009                 "1.00E-25", "1.01E-25", "1.00E-25",
8010                 "1.00E-25", "1.00E-25", "9.99E-26",
8011                 "1.00E-25", "1.00E-25", "9.99E-26",
8012                 "1.00E-25", "1.00E-25", "1.00E-25",
8013                 "1.00E-25", "1.00E-25", "1.00E-25",
8014                 "1.00E-25", "1.00E-25", "1.00E-25",
8015                 "1.00E-25", "1.01E-25", "1.00E-25"};
8016         verifyRounding(
8017                 format,
8018                 values,
8019                 expected,
8020                 roundingModes,
8021                 descriptions,
8022                 UPRV_LENGTHOF(values),
8023                 UPRV_LENGTHOF(roundingModes));
8024         }
8025     {
8026         double values[] = {-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
8027         // The order of these expected values correspond to the order of roundingModes and the order of values.
8028         const char *expected[] = {
8029                 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8030                 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8031                 "-1.00E-25", "-1.00E-25", "-1.01E-25",
8032                 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8033                 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8034                 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8035                 "-1.00E-25", "-1.00E-25", "-1.01E-25"};
8036         verifyRounding(
8037                 format,
8038                 values,
8039                 expected,
8040                 roundingModes,
8041                 descriptions,
8042                 UPRV_LENGTHOF(values),
8043                 UPRV_LENGTHOF(roundingModes));
8044     }
8045 }
8046 
TestZeroScientific10547()8047 void NumberFormatTest::TestZeroScientific10547() {
8048     UErrorCode status = U_ZERO_ERROR;
8049     DecimalFormat fmt("0.00E0", status);
8050     if (!assertSuccess("Format creation", status)) {
8051         return;
8052     }
8053     UnicodeString out;
8054     fmt.format(-0.0, out);
8055     assertEquals("format", "-0.00E0", out, true);
8056 }
8057 
verifyRounding(DecimalFormat & format,const double * values,const char * const * expected,const DecimalFormat::ERoundingMode * roundingModes,const char * const * descriptions,int32_t valueSize,int32_t roundingModeSize)8058 void NumberFormatTest::verifyRounding(
8059         DecimalFormat& format,
8060         const double *values,
8061         const char * const *expected,
8062         const DecimalFormat::ERoundingMode *roundingModes,
8063         const char * const *descriptions,
8064         int32_t valueSize,
8065         int32_t roundingModeSize) {
8066     for (int32_t i = 0; i < roundingModeSize; ++i) {
8067         format.setRoundingMode(roundingModes[i]);
8068         for (int32_t j = 0; j < valueSize; j++) {
8069             UnicodeString currentExpected(expected[i * valueSize + j]);
8070             currentExpected = currentExpected.unescape();
8071             UnicodeString actual;
8072             format.format(values[j], actual);
8073             if (currentExpected != actual) {
8074                 dataerrln("For %s value %f, expected '%s', got '%s'",
8075                           descriptions[i], values[j], CStr(currentExpected)(), CStr(actual)());
8076             }
8077         }
8078     }
8079 }
8080 
TestAccountingCurrency()8081 void NumberFormatTest::TestAccountingCurrency() {
8082     UErrorCode status = U_ZERO_ERROR;
8083     UNumberFormatStyle style = UNUM_CURRENCY_ACCOUNTING;
8084 
8085     expect(NumberFormat::createInstance("en_US", style, status),
8086         (Formattable)(double)1234.5, "$1,234.50", TRUE, status);
8087     expect(NumberFormat::createInstance("en_US", style, status),
8088         (Formattable)(double)-1234.5, "($1,234.50)", TRUE, status);
8089     expect(NumberFormat::createInstance("en_US", style, status),
8090         (Formattable)(double)0, "$0.00", TRUE, status);
8091     expect(NumberFormat::createInstance("en_US", style, status),
8092         (Formattable)(double)-0.2, "($0.20)", TRUE, status);
8093     expect(NumberFormat::createInstance("ja_JP", style, status),
8094         (Formattable)(double)10000, UnicodeString("\\uFFE510,000").unescape(), TRUE, status);
8095     expect(NumberFormat::createInstance("ja_JP", style, status),
8096         (Formattable)(double)-1000.5, UnicodeString("(\\uFFE51,000)").unescape(), FALSE, status);
8097     expect(NumberFormat::createInstance("de_DE", style, status),
8098         (Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status);
8099     expect(NumberFormat::createInstance("en_ID", style, status),
8100         (Formattable)(double)0, UnicodeString("IDR\\u00A00.00").unescape(), TRUE, status);
8101     expect(NumberFormat::createInstance("en_ID", style, status),
8102         (Formattable)(double)-0.2, UnicodeString("(IDR\\u00A00.20)").unescape(), TRUE, status);
8103     expect(NumberFormat::createInstance("sh_ME", style, status),
8104         (Formattable)(double)0, UnicodeString("0,00\\u00A0\\u20AC").unescape(), TRUE, status);
8105     expect(NumberFormat::createInstance("sh_ME", style, status),
8106         (Formattable)(double)-0.2, UnicodeString("(0,20\\u00A0\\u20AC)").unescape(), TRUE, status);
8107 }
8108 
8109 /**
8110  * ICU4J has the behavior explained below, but ICU4C is not affected. Test is added to prevent regression.
8111  *
8112  * en_ID/sh_ME uses language only locales en/sh which requires NumberFormatServiceShim to fill in the currency, but
8113  * prior to ICU-20631, currency was not filled in for accounting, cash and standard, so currency placeholder was
8114  * used instead of the desired locale's currency.
8115  */
TestCurrencyFormatForMissingLocale()8116 void NumberFormatTest::TestCurrencyFormatForMissingLocale() {
8117     IcuTestErrorCode status(*this, "TestCurrencyFormatForMissingLocale");
8118     Locale locale = Locale::createCanonical("sh_ME");
8119 
8120     LocalPointer<NumberFormat> curFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status));
8121     // Fail here with missing data.
8122     if (!assertTrue(WHERE, curFmt.isValid(), false, true)) {return;};
8123     assertEquals("Currency instance is not for the desired locale for CURRENCYSTYLE", curFmt->getCurrency(), "EUR");
8124     UnicodeString currBuf;
8125     curFmt->format(-1234.5, currBuf);
8126     assertEquals("NumberFormat format outputs wrong value for CURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", currBuf);
8127 
8128     LocalPointer<NumberFormat> accFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_ACCOUNTING, status));
8129     assertEquals("Currency instance is not for the desired locale for ACCOUNTINGCURRENCYSTYLE", accFmt->getCurrency(), "EUR");
8130     UnicodeString accBuf;
8131     accFmt->format(-1234.5, accBuf);
8132     assertEquals("NumberFormat format outputs wrong value for ACCOUNTINGCURRENCYSTYLE", u"(1.234,50\u00A0\u20AC)", accBuf);
8133 
8134     LocalPointer<NumberFormat> cashFmt(NumberFormat::createInstance(locale, UNUM_CASH_CURRENCY, status));
8135     assertEquals("Currency instance is not for the desired locale for CASHCURRENCYSTYLE", cashFmt->getCurrency(), "EUR");
8136     UnicodeString cashBuf;
8137     cashFmt->format(-1234.5, cashBuf);
8138     assertEquals("NumberFormat format outputs wrong value for CASHCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", cashBuf);
8139 
8140     LocalPointer<NumberFormat> stdFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_STANDARD, status));
8141     assertEquals("Currency instance is not for the desired locale for STANDARDCURRENCYSTYLE", stdFmt->getCurrency(), "EUR");
8142     UnicodeString stdBuf;
8143     stdFmt->format(-1234.5, stdBuf);
8144     assertEquals("NumberFormat format outputs wrong value for STANDARDCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", stdBuf);
8145 }
8146 
8147 // for #5186
TestEquality()8148 void NumberFormatTest::TestEquality() {
8149     UErrorCode status = U_ZERO_ERROR;
8150     DecimalFormatSymbols symbols(Locale("root"), status);
8151     if (U_FAILURE(status)) {
8152     	dataerrln("Fail: can't create DecimalFormatSymbols for root");
8153     	return;
8154     }
8155     UnicodeString pattern("#,##0.###");
8156     DecimalFormat fmtBase(pattern, symbols, status);
8157     if (U_FAILURE(status)) {
8158     	dataerrln("Fail: can't create DecimalFormat using root symbols");
8159     	return;
8160     }
8161 
8162     DecimalFormat* fmtClone = fmtBase.clone();
8163     fmtClone->setFormatWidth(fmtBase.getFormatWidth() + 32);
8164     if (*fmtClone == fmtBase) {
8165         errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth");
8166     }
8167     delete fmtClone;
8168 }
8169 
TestCurrencyUsage()8170 void NumberFormatTest::TestCurrencyUsage() {
8171     double agent = 123.567;
8172 
8173     UErrorCode status;
8174     DecimalFormat *fmt;
8175 
8176     // compare the Currency and Currency Cash Digits
8177     // Note that as of CLDR 26:
8178     // * TWD and PKR switched from 0 decimals to 2; ISK still has 0, so change test to that
8179     // * CAD rounds to .05 in cash mode only
8180     // 1st time for getter/setter, 2nd time for factory method
8181     Locale enUS_ISK("en_US@currency=ISK");
8182 
8183     for(int i=0; i<2; i++){
8184         status = U_ZERO_ERROR;
8185         if(i == 0){
8186             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CURRENCY, status);
8187             if (assertSuccess("en_US@currency=ISK/CURRENCY", status, TRUE) == FALSE) {
8188                 continue;
8189             }
8190 
8191             UnicodeString original;
8192             fmt->format(agent,original);
8193             assertEquals("Test Currency Usage 1", u"ISK\u00A0124", original);
8194 
8195             // test the getter here
8196             UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8197             assertEquals("Test usage getter - standard", (int32_t)curUsage, (int32_t)UCURR_USAGE_STANDARD);
8198 
8199             fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8200         }else{
8201             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CASH_CURRENCY, status);
8202             if (assertSuccess("en_US@currency=ISK/CASH", status, TRUE) == FALSE) {
8203                 continue;
8204             }
8205         }
8206 
8207         // must be usage = cash
8208         UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8209         assertEquals("Test usage getter - cash", (int32_t)curUsage, (int32_t)UCURR_USAGE_CASH);
8210 
8211         UnicodeString cash_currency;
8212         fmt->format(agent,cash_currency);
8213         assertEquals("Test Currency Usage 2", u"ISK\u00A0124", cash_currency);
8214         delete fmt;
8215     }
8216 
8217     // compare the Currency and Currency Cash Rounding
8218     // 1st time for getter/setter, 2nd time for factory method
8219     Locale enUS_CAD("en_US@currency=CAD");
8220     for(int i=0; i<2; i++){
8221         status = U_ZERO_ERROR;
8222         if(i == 0){
8223             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8224             if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
8225                 continue;
8226             }
8227 
8228             UnicodeString original_rounding;
8229             fmt->format(agent, original_rounding);
8230             assertEquals("Test Currency Usage 3", u"CA$123.57", original_rounding);
8231             fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8232         }else{
8233             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8234             if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
8235                 continue;
8236             }
8237         }
8238 
8239         UnicodeString cash_rounding_currency;
8240         fmt->format(agent, cash_rounding_currency);
8241         assertEquals("Test Currency Usage 4", u"CA$123.55", cash_rounding_currency);
8242         delete fmt;
8243     }
8244 
8245     // Test the currency change
8246     // 1st time for getter/setter, 2nd time for factory method
8247     const UChar CUR_PKR[] = {0x50, 0x4B, 0x52, 0};
8248     for(int i=0; i<2; i++){
8249         status = U_ZERO_ERROR;
8250         if(i == 0){
8251             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8252             if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
8253                 continue;
8254             }
8255             fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8256         }else{
8257             fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8258             if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
8259                 continue;
8260             }
8261         }
8262 
8263         UnicodeString cur_original;
8264         fmt->setCurrencyUsage(UCURR_USAGE_STANDARD, &status);
8265         fmt->format(agent, cur_original);
8266         assertEquals("Test Currency Usage 5", u"CA$123.57", cur_original);
8267 
8268         fmt->setCurrency(CUR_PKR, status);
8269         assertSuccess("Set currency to PKR", status);
8270 
8271         UnicodeString PKR_changed;
8272         fmt->format(agent, PKR_changed);
8273         assertEquals("Test Currency Usage 6", u"PKR\u00A0123.57", PKR_changed);
8274         delete fmt;
8275     }
8276 }
8277 
8278 
8279 // Check the constant MAX_INT64_IN_DOUBLE.
8280 // The value should convert to a double with no loss of precision.
8281 // A failure may indicate a platform with a different double format, requiring
8282 // a revision to the constant.
8283 //
8284 // Note that this is actually hard to test, because the language standard gives
8285 //  compilers considerable flexibility to do unexpected things with rounding and
8286 //  with overflow in simple int to/from float conversions. Some compilers will completely optimize
8287 //  away a simple round-trip conversion from int64_t -> double -> int64_t.
8288 
TestDoubleLimit11439()8289 void NumberFormatTest::TestDoubleLimit11439() {
8290     char  buf[50];
8291     for (int64_t num = MAX_INT64_IN_DOUBLE-10; num<=MAX_INT64_IN_DOUBLE; num++) {
8292         sprintf(buf, "%lld", (long long)num);
8293         double fNum = 0.0;
8294         sscanf(buf, "%lf", &fNum);
8295         int64_t rtNum = static_cast<int64_t>(fNum);
8296         if (num != rtNum) {
8297             errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8298             return;
8299         }
8300     }
8301     for (int64_t num = -MAX_INT64_IN_DOUBLE+10; num>=-MAX_INT64_IN_DOUBLE; num--) {
8302         sprintf(buf, "%lld", (long long)num);
8303         double fNum = 0.0;
8304         sscanf(buf, "%lf", &fNum);
8305         int64_t rtNum = static_cast<int64_t>(fNum);
8306         if (num != rtNum) {
8307             errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8308             return;
8309         }
8310     }
8311 }
8312 
TestGetAffixes()8313 void NumberFormatTest::TestGetAffixes() {
8314     UErrorCode status = U_ZERO_ERROR;
8315     DecimalFormatSymbols sym("en_US", status);
8316     UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8317     pattern = pattern.unescape();
8318     DecimalFormat fmt(pattern, sym, status);
8319     if (U_FAILURE(status)) {
8320         dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8321         return;
8322     }
8323     UnicodeString affixStr;
8324     assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8325     assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8326     assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8327     assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8328 
8329     // Test equality with affixes. set affix methods can't capture special
8330     // characters which is why equality should fail.
8331     {
8332         DecimalFormat fmtCopy(fmt);
8333         assertTrue("", fmt == fmtCopy);
8334         UnicodeString someAffix;
8335         fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(someAffix));
8336         assertTrue("", fmt != fmtCopy);
8337     }
8338     {
8339         DecimalFormat fmtCopy(fmt);
8340         assertTrue("", fmt == fmtCopy);
8341         UnicodeString someAffix;
8342         fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(someAffix));
8343         assertTrue("", fmt != fmtCopy);
8344     }
8345     {
8346         DecimalFormat fmtCopy(fmt);
8347         assertTrue("", fmt == fmtCopy);
8348         UnicodeString someAffix;
8349         fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(someAffix));
8350         assertTrue("", fmt != fmtCopy);
8351     }
8352     {
8353         DecimalFormat fmtCopy(fmt);
8354         assertTrue("", fmt == fmtCopy);
8355         UnicodeString someAffix;
8356         fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(someAffix));
8357         assertTrue("", fmt != fmtCopy);
8358     }
8359     fmt.setPositivePrefix("Don't");
8360     fmt.setPositiveSuffix("do");
8361     UnicodeString someAffix("be''eet\\u00a4\\u00a4\\u00a4 it.");
8362     someAffix = someAffix.unescape();
8363     fmt.setNegativePrefix(someAffix);
8364     fmt.setNegativeSuffix("%");
8365     assertEquals("", "Don't", fmt.getPositivePrefix(affixStr));
8366     assertEquals("", "do", fmt.getPositiveSuffix(affixStr));
8367     assertEquals("", someAffix, fmt.getNegativePrefix(affixStr));
8368     assertEquals("", "%", fmt.getNegativeSuffix(affixStr));
8369 }
8370 
TestToPatternScientific11648()8371 void NumberFormatTest::TestToPatternScientific11648() {
8372     UErrorCode status = U_ZERO_ERROR;
8373     Locale en("en");
8374     DecimalFormatSymbols sym(en, status);
8375     DecimalFormat fmt("0.00", sym, status);
8376     if (U_FAILURE(status)) {
8377         dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8378         return;
8379     }
8380     fmt.setScientificNotation(TRUE);
8381     UnicodeString pattern;
8382     assertEquals("", "0.00E0", fmt.toPattern(pattern));
8383     DecimalFormat fmt2(pattern, sym, status);
8384     assertSuccess("", status);
8385 }
8386 
TestBenchmark()8387 void NumberFormatTest::TestBenchmark() {
8388 /*
8389     UErrorCode status = U_ZERO_ERROR;
8390     Locale en("en");
8391     DecimalFormatSymbols sym(en, status);
8392     DecimalFormat fmt("0.0000000", new DecimalFormatSymbols(sym), status);
8393 //    DecimalFormat fmt("0.00000E0", new DecimalFormatSymbols(sym), status);
8394 //    DecimalFormat fmt("0", new DecimalFormatSymbols(sym), status);
8395     FieldPosition fpos(FieldPosition::DONT_CARE);
8396     clock_t start = clock();
8397     for (int32_t i = 0; i < 1000000; ++i) {
8398         UnicodeString append;
8399         fmt.format(3.0, append, fpos, status);
8400 //        fmt.format(4.6692016, append, fpos, status);
8401 //        fmt.format(1234567.8901, append, fpos, status);
8402 //        fmt.format(2.99792458E8, append, fpos, status);
8403 //        fmt.format(31, append);
8404     }
8405     errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8406     assertSuccess("", status);
8407 
8408     UErrorCode status = U_ZERO_ERROR;
8409     MessageFormat fmt("{0, plural, one {I have # friend.} other {I have # friends.}}", status);
8410     FieldPosition fpos(FieldPosition::DONT_CARE);
8411     Formattable one(1.0);
8412     Formattable three(3.0);
8413     clock_t start = clock();
8414     for (int32_t i = 0; i < 500000; ++i) {
8415         UnicodeString append;
8416         fmt.format(&one, 1, append, fpos, status);
8417         UnicodeString append2;
8418         fmt.format(&three, 1, append2, fpos, status);
8419     }
8420     errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8421     assertSuccess("", status);
8422 
8423     UErrorCode status = U_ZERO_ERROR;
8424     Locale en("en");
8425     Measure measureC(23, MeasureUnit::createCelsius(status), status);
8426     MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
8427     FieldPosition fpos(FieldPosition::DONT_CARE);
8428     clock_t start = clock();
8429     for (int32_t i = 0; i < 1000000; ++i) {
8430         UnicodeString appendTo;
8431         fmt.formatMeasures(
8432                 &measureC, 1, appendTo, fpos, status);
8433     }
8434     errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8435     assertSuccess("", status);
8436 */
8437 }
8438 
TestFractionalDigitsForCurrency()8439 void NumberFormatTest::TestFractionalDigitsForCurrency() {
8440     UErrorCode status = U_ZERO_ERROR;
8441     LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance("en", status));
8442     if (U_FAILURE(status)) {
8443         dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8444         return;
8445     }
8446     UChar JPY[] = {0x4A, 0x50, 0x59, 0x0};
8447     fmt->setCurrency(JPY, status);
8448     if (!assertSuccess("", status)) {
8449         return;
8450     }
8451     assertEquals("", 0, fmt->getMaximumFractionDigits());
8452 }
8453 
8454 
TestFormatCurrencyPlural()8455 void NumberFormatTest::TestFormatCurrencyPlural() {
8456     UErrorCode status = U_ZERO_ERROR;
8457     Locale locale = Locale::createCanonical("en_US");
8458     NumberFormat *fmt = NumberFormat::createInstance(locale, UNUM_CURRENCY_PLURAL, status);
8459     if (U_FAILURE(status)) {
8460         dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8461         return;
8462     }
8463    UnicodeString formattedNum;
8464    fmt->format(11234.567, formattedNum, NULL, status);
8465    assertEquals("", "11,234.57 US dollars", formattedNum);
8466    delete fmt;
8467 }
8468 
TestCtorApplyPatternDifference()8469 void NumberFormatTest::TestCtorApplyPatternDifference() {
8470     UErrorCode status = U_ZERO_ERROR;
8471     DecimalFormatSymbols sym("en_US", status);
8472     UnicodeString pattern("\\u00a40");
8473     DecimalFormat fmt(pattern.unescape(), sym, status);
8474     if (U_FAILURE(status)) {
8475         dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8476         return;
8477     }
8478     UnicodeString result;
8479     assertEquals(
8480             "ctor favors precision of currency",
8481             "$5.00",
8482             fmt.format((double)5, result));
8483     result.remove();
8484     fmt.applyPattern(pattern.unescape(), status);
8485     assertEquals(
8486             "applyPattern favors precision of pattern",
8487             "$5",
8488             fmt.format((double)5, result));
8489 }
8490 
Test11868()8491 void NumberFormatTest::Test11868() {
8492     double posAmt = 34.567;
8493     double negAmt = -9876.543;
8494 
8495     Locale selectedLocale("en_US");
8496     UErrorCode status = U_ZERO_ERROR;
8497 
8498     UnicodeString result;
8499     FieldPosition fpCurr(UNUM_CURRENCY_FIELD);
8500     LocalPointer<NumberFormat> fmt(
8501             NumberFormat::createInstance(
8502                     selectedLocale, UNUM_CURRENCY_PLURAL, status));
8503     if (!assertSuccess("Format creation", status)) {
8504         return;
8505     }
8506     fmt->format(posAmt, result, fpCurr, status);
8507     assertEquals("", "34.57 US dollars", result);
8508     assertEquals("begin index", 6, fpCurr.getBeginIndex());
8509     assertEquals("end index", 16, fpCurr.getEndIndex());
8510 
8511     // Test field position iterator
8512     {
8513         NumberFormatTest_Attributes attributes[] = {
8514                 {UNUM_INTEGER_FIELD, 0, 2},
8515                 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8516                 {UNUM_FRACTION_FIELD, 3, 5},
8517                 {UNUM_CURRENCY_FIELD, 6, 16},
8518                 {0, -1, 0}};
8519         UnicodeString result;
8520         FieldPositionIterator iter;
8521         fmt->format(posAmt, result, &iter, status);
8522         assertEquals("", "34.57 US dollars", result);
8523         verifyFieldPositionIterator(attributes, iter);
8524     }
8525 
8526     result.remove();
8527     fmt->format(negAmt, result, fpCurr, status);
8528     assertEquals("", "-9,876.54 US dollars", result);
8529     assertEquals("begin index", 10, fpCurr.getBeginIndex());
8530     assertEquals("end index", 20, fpCurr.getEndIndex());
8531 
8532     // Test field position iterator
8533     {
8534         NumberFormatTest_Attributes attributes[] = {
8535                 {UNUM_SIGN_FIELD, 0, 1},
8536                 {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
8537                 {UNUM_INTEGER_FIELD, 1, 6},
8538                 {UNUM_DECIMAL_SEPARATOR_FIELD, 6, 7},
8539                 {UNUM_FRACTION_FIELD, 7, 9},
8540                 {UNUM_CURRENCY_FIELD, 10, 20},
8541                 {0, -1, 0}};
8542         UnicodeString result;
8543         FieldPositionIterator iter;
8544         fmt->format(negAmt, result, &iter, status);
8545         assertEquals("", "-9,876.54 US dollars", result);
8546         verifyFieldPositionIterator(attributes, iter);
8547     }
8548 }
8549 
Test10727_RoundingZero()8550 void NumberFormatTest::Test10727_RoundingZero() {
8551     IcuTestErrorCode status(*this, "Test10727_RoundingZero");
8552     DecimalQuantity dq;
8553     dq.setToDouble(-0.0);
8554     assertTrue("", dq.isNegative());
8555     dq.roundToMagnitude(0, UNUM_ROUND_HALFEVEN, status);
8556     assertTrue("", dq.isNegative());
8557 }
8558 
Test11739_ParseLongCurrency()8559 void NumberFormatTest::Test11739_ParseLongCurrency() {
8560     IcuTestErrorCode status(*this, "Test11739_ParseLongCurrency");
8561     LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("sr_BA", status));
8562     if (status.errDataIfFailureAndReset()) { return; }
8563     ((DecimalFormat*) nf.getAlias())->applyPattern(u"#,##0.0 ¤¤¤", status);
8564     ParsePosition ppos(0);
8565     LocalPointer<CurrencyAmount> result(nf->parseCurrency(u"1.500 амерички долар", ppos));
8566     assertEquals("Should parse to 1500 USD", -1, ppos.getErrorIndex());
8567     if (ppos.getErrorIndex() != -1) {
8568         return;
8569     }
8570     assertEquals("Should parse to 1500 USD", 1500LL, result->getNumber().getInt64(status));
8571     assertEquals("Should parse to 1500 USD", u"USD", result->getISOCurrency());
8572 }
8573 
Test13035_MultiCodePointPaddingInPattern()8574 void NumberFormatTest::Test13035_MultiCodePointPaddingInPattern() {
8575     IcuTestErrorCode status(*this, "Test13035_MultiCodePointPaddingInPattern");
8576     DecimalFormat df(u"a*'நி'###0b", status);
8577     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8578     UnicodeString result;
8579     df.format(12, result.remove());
8580     // TODO(13034): Re-enable this test when support is added in ICU4C.
8581     //assertEquals("Multi-codepoint padding should not be split", u"aநிநி12b", result);
8582     df = DecimalFormat(u"a*\U0001F601###0b", status);
8583     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8584     result = df.format(12, result.remove());
8585     assertEquals("Single-codepoint padding should not be split", u"a\U0001F601\U0001F60112b", result, true);
8586     df = DecimalFormat(u"a*''###0b", status);
8587     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8588     result = df.format(12, result.remove());
8589     assertEquals("Quote should be escapable in padding syntax", "a''12b", result, true);
8590 }
8591 
Test13737_ParseScientificStrict()8592 void NumberFormatTest::Test13737_ParseScientificStrict() {
8593     IcuTestErrorCode status(*this, "Test13737_ParseScientificStrict");
8594     LocalPointer<NumberFormat> df(NumberFormat::createScientificInstance("en", status), status);
8595     if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8596     df->setLenient(FALSE);
8597     // Parse Test
8598     expect(*df, u"1.2", 1.2);
8599 }
8600 
Test11376_getAndSetPositivePrefix()8601 void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
8602     {
8603         const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8604         UErrorCode status = U_ZERO_ERROR;
8605         LocalPointer<NumberFormat> fmt(
8606                 NumberFormat::createCurrencyInstance("en", status));
8607         if (!assertSuccess("", status)) {
8608             return;
8609         }
8610         DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8611         dfmt->setCurrency(USD);
8612         UnicodeString result;
8613 
8614         // This line should be a no-op. I am setting the positive prefix
8615         // to be the same thing it was before.
8616         dfmt->setPositivePrefix(dfmt->getPositivePrefix(result));
8617 
8618         UnicodeString appendTo;
8619         assertEquals("", "$3.78", dfmt->format(3.78, appendTo, status));
8620         assertSuccess("", status);
8621     }
8622     {
8623         const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8624         UErrorCode status = U_ZERO_ERROR;
8625         LocalPointer<NumberFormat> fmt(
8626                 NumberFormat::createInstance("en", UNUM_CURRENCY_PLURAL, status));
8627         if (!assertSuccess("", status)) {
8628             return;
8629         }
8630         DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8631         UnicodeString result;
8632         assertEquals("", u" (unknown currency)", dfmt->getPositiveSuffix(result));
8633         dfmt->setCurrency(USD);
8634 
8635         // getPositiveSuffix() always returns the suffix for the
8636         // "other" plural category
8637         assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8638         UnicodeString appendTo;
8639         assertEquals("", "3.78 US dollars", dfmt->format(3.78, appendTo, status));
8640         assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8641         dfmt->setPositiveSuffix("booya");
8642         appendTo.remove();
8643         assertEquals("", "3.78booya", dfmt->format(3.78, appendTo, status));
8644         assertEquals("", "booya", dfmt->getPositiveSuffix(result));
8645     }
8646 }
8647 
Test11475_signRecognition()8648 void NumberFormatTest::Test11475_signRecognition() {
8649     UErrorCode status = U_ZERO_ERROR;
8650     DecimalFormatSymbols sym("en", status);
8651     UnicodeString result;
8652     {
8653         DecimalFormat fmt("+0.00", sym, status);
8654         if (!assertSuccess("", status)) {
8655             return;
8656         }
8657         NumberFormatTest_Attributes attributes[] = {
8658                 {UNUM_SIGN_FIELD, 0, 1},
8659                 {UNUM_INTEGER_FIELD, 1, 2},
8660                 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8661                 {UNUM_FRACTION_FIELD, 3, 5},
8662                 {0, -1, 0}};
8663         UnicodeString result;
8664         FieldPositionIterator iter;
8665         fmt.format(2.3, result, &iter, status);
8666         assertEquals("", "+2.30", result);
8667         verifyFieldPositionIterator(attributes, iter);
8668     }
8669     {
8670         DecimalFormat fmt("++0.00+;-(#)--", sym, status);
8671         if (!assertSuccess("", status)) {
8672             return;
8673         }
8674         {
8675             NumberFormatTest_Attributes attributes[] = {
8676                     {UNUM_SIGN_FIELD, 0, 2},
8677                     {UNUM_INTEGER_FIELD, 2, 3},
8678                     {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8679                     {UNUM_FRACTION_FIELD, 4, 6},
8680                     {UNUM_SIGN_FIELD, 6, 7},
8681                     {0, -1, 0}};
8682             UnicodeString result;
8683             FieldPositionIterator iter;
8684             fmt.format(2.3, result, &iter, status);
8685             assertEquals("", "++2.30+", result);
8686             verifyFieldPositionIterator(attributes, iter);
8687         }
8688         {
8689             NumberFormatTest_Attributes attributes[] = {
8690                     {UNUM_SIGN_FIELD, 0, 1},
8691                     {UNUM_INTEGER_FIELD, 2, 3},
8692                     {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8693                     {UNUM_FRACTION_FIELD, 4, 6},
8694                     {UNUM_SIGN_FIELD, 7, 9},
8695                     {0, -1, 0}};
8696             UnicodeString result;
8697             FieldPositionIterator iter;
8698             fmt.format(-2.3, result, &iter, status);
8699             assertEquals("", "-(2.30)--", result);
8700             verifyFieldPositionIterator(attributes, iter);
8701         }
8702     }
8703 }
8704 
Test11640_getAffixes()8705 void NumberFormatTest::Test11640_getAffixes() {
8706     UErrorCode status = U_ZERO_ERROR;
8707     DecimalFormatSymbols symbols("en_US", status);
8708     if (!assertSuccess("", status)) {
8709         return;
8710     }
8711     UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8712     pattern = pattern.unescape();
8713     DecimalFormat fmt(pattern, symbols, status);
8714     if (!assertSuccess("", status)) {
8715         return;
8716     }
8717     UnicodeString affixStr;
8718     assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8719     assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8720     assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8721     assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8722 }
8723 
Test11649_toPatternWithMultiCurrency()8724 void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
8725     UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
8726     pattern = pattern.unescape();
8727     UErrorCode status = U_ZERO_ERROR;
8728     DecimalFormat fmt(pattern, status);
8729     if (!assertSuccess("", status)) {
8730         return;
8731     }
8732     static UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8733     fmt.setCurrency(USD);
8734     UnicodeString appendTo;
8735 
8736     assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
8737 
8738     UnicodeString topattern;
8739     fmt.toPattern(topattern);
8740     DecimalFormat fmt2(topattern, status);
8741     if (!assertSuccess("", status)) {
8742         return;
8743     }
8744     fmt2.setCurrency(USD);
8745 
8746     appendTo.remove();
8747     assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
8748 }
8749 
Test13327_numberingSystemBufferOverflow()8750 void NumberFormatTest::Test13327_numberingSystemBufferOverflow() {
8751     UErrorCode status = U_ZERO_ERROR;
8752     for (int runId = 0; runId < 2; runId++) {
8753         // Construct a locale string with a very long "numbers" value.
8754         // The first time, make the value length exactly equal to ULOC_KEYWORDS_CAPACITY.
8755         // The second time, make it exceed ULOC_KEYWORDS_CAPACITY.
8756         int extraLength = (runId == 0) ? 0 : 5;
8757 
8758         CharString localeId("en@numbers=", status);
8759         for (int i = 0; i < ULOC_KEYWORDS_CAPACITY + extraLength; i++) {
8760             localeId.append('x', status);
8761         }
8762         assertSuccess("Constructing locale string", status);
8763         Locale locale(localeId.data());
8764 
8765         LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(locale, status));
8766         assertFalse("Should not be null", ns.getAlias() == nullptr);
8767         assertSuccess("Should create with no error", status);
8768     }
8769 }
8770 
Test13391_chakmaParsing()8771 void NumberFormatTest::Test13391_chakmaParsing() {
8772     UErrorCode status = U_ZERO_ERROR;
8773     LocalPointer<DecimalFormat> df(dynamic_cast<DecimalFormat*>(
8774         NumberFormat::createInstance(Locale("ccp"), status)));
8775     if (df == nullptr) {
8776         dataerrln("%s %d Chakma df is null",  __FILE__, __LINE__);
8777         return;
8778     }
8779     const UChar* expected = u"\U00011137\U00011138,\U00011139\U0001113A\U0001113B";
8780     UnicodeString actual;
8781     df->format(12345, actual, status);
8782     assertSuccess("Should not fail when formatting in ccp", status);
8783     assertEquals("Should produce expected output in ccp", expected, actual);
8784 
8785     Formattable result;
8786     df->parse(expected, result, status);
8787     assertSuccess("Should not fail when parsing in ccp", status);
8788     assertEquals("Should parse to 12345 in ccp", 12345, result);
8789 
8790     const UChar* expectedScientific = u"\U00011137.\U00011139E\U00011138";
8791     UnicodeString actualScientific;
8792     df.adoptInstead(static_cast<DecimalFormat*>(
8793         NumberFormat::createScientificInstance(Locale("ccp"), status)));
8794     df->format(130, actualScientific, status);
8795     assertSuccess("Should not fail when formatting scientific in ccp", status);
8796     assertEquals("Should produce expected scientific output in ccp",
8797         expectedScientific, actualScientific);
8798 
8799     Formattable resultScientific;
8800     df->parse(expectedScientific, resultScientific, status);
8801     assertSuccess("Should not fail when parsing scientific in ccp", status);
8802     assertEquals("Should parse scientific to 130 in ccp", 130, resultScientific);
8803 }
8804 
8805 
verifyFieldPositionIterator(NumberFormatTest_Attributes * expected,FieldPositionIterator & iter)8806 void NumberFormatTest::verifyFieldPositionIterator(
8807         NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
8808     int32_t idx = 0;
8809     FieldPosition fp;
8810     while (iter.next(fp)) {
8811         if (expected[idx].spos == -1) {
8812             errln("Iterator should have ended. got %d", fp.getField());
8813             return;
8814         }
8815         assertEquals("id", expected[idx].id, fp.getField());
8816         assertEquals("start", expected[idx].spos, fp.getBeginIndex());
8817         assertEquals("end", expected[idx].epos, fp.getEndIndex());
8818         ++idx;
8819     }
8820     if (expected[idx].spos != -1) {
8821         errln("Premature end of iterator. expected %d", expected[idx].id);
8822     }
8823 }
8824 
Test11735_ExceptionIssue()8825 void NumberFormatTest::Test11735_ExceptionIssue() {
8826     IcuTestErrorCode status(*this, "Test11735_ExceptionIssue");
8827     Locale enLocale("en");
8828     DecimalFormatSymbols symbols(enLocale, status);
8829     if (status.isSuccess()) {
8830         DecimalFormat fmt("0", symbols, status);
8831         assertSuccess("Fail: Construct DecimalFormat formatter", status, true, __FILE__, __LINE__);
8832         ParsePosition ppos(0);
8833         fmt.parseCurrency("53.45", ppos);  // NPE thrown here in ICU4J.
8834         assertEquals("Issue11735 ppos", 0, ppos.getIndex());
8835     }
8836 }
8837 
Test11035_FormatCurrencyAmount()8838 void NumberFormatTest::Test11035_FormatCurrencyAmount() {
8839     UErrorCode status = U_ZERO_ERROR;
8840     double amount = 12345.67;
8841     const char16_t* expected = u"12,345$67 ​";
8842 
8843     // Test two ways to set a currency via API
8844 
8845     Locale loc1 = Locale("pt_PT");
8846     LocalPointer<NumberFormat> fmt1(NumberFormat::createCurrencyInstance(loc1, status),
8847                                     status);
8848     if (U_FAILURE(status)) {
8849       dataerrln("%s %d NumberFormat instance fmt1 is null",  __FILE__, __LINE__);
8850       return;
8851     }
8852     fmt1->setCurrency(u"PTE", status);
8853     assertSuccess("Setting currency on fmt1", status);
8854     UnicodeString actualSetCurrency;
8855     fmt1->format(amount, actualSetCurrency);
8856 
8857     Locale loc2 = Locale("pt_PT@currency=PTE");
8858     LocalPointer<NumberFormat> fmt2(NumberFormat::createCurrencyInstance(loc2, status));
8859     assertSuccess("Creating fmt2", status);
8860     UnicodeString actualLocaleString;
8861     fmt2->format(amount, actualLocaleString);
8862 
8863     assertEquals("Custom Currency Pattern, Set Currency", expected, actualSetCurrency);
8864     assertEquals("Custom Currency Pattern, Locale String", expected, actualLocaleString);
8865 }
8866 
Test11318_DoubleConversion()8867 void NumberFormatTest::Test11318_DoubleConversion() {
8868     IcuTestErrorCode status(*this, "Test11318_DoubleConversion");
8869     LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
8870     if (U_FAILURE(status)) {
8871       dataerrln("%s %d Error in NumberFormat instance creation",  __FILE__, __LINE__);
8872       return;
8873     }
8874     nf->setMaximumFractionDigits(40);
8875     nf->setMaximumIntegerDigits(40);
8876     UnicodeString appendTo;
8877     nf->format(999999999999999.9, appendTo);
8878     assertEquals("Should render all digits", u"999,999,999,999,999.9", appendTo);
8879 }
8880 
TestParsePercentRegression()8881 void NumberFormatTest::TestParsePercentRegression() {
8882     IcuTestErrorCode status(*this, "TestParsePercentRegression");
8883     LocalPointer<DecimalFormat> df1((DecimalFormat*) NumberFormat::createInstance("en", status), status);
8884     LocalPointer<DecimalFormat> df2((DecimalFormat*) NumberFormat::createPercentInstance("en", status), status);
8885     if (status.isFailure()) {return; }
8886     df1->setLenient(TRUE);
8887     df2->setLenient(TRUE);
8888 
8889     {
8890         ParsePosition ppos;
8891         Formattable result;
8892         df1->parse("50%", result, ppos);
8893         assertEquals("df1 should accept a number but not the percent sign", 2, ppos.getIndex());
8894         assertEquals("df1 should return the number as 50", 50.0, result.getDouble(status));
8895     }
8896     {
8897         ParsePosition ppos;
8898         Formattable result;
8899         df2->parse("50%", result, ppos);
8900         assertEquals("df2 should accept the percent sign", 3, ppos.getIndex());
8901         assertEquals("df2 should return the number as 0.5", 0.5, result.getDouble(status));
8902     }
8903     {
8904         ParsePosition ppos;
8905         Formattable result;
8906         df2->parse("50", result, ppos);
8907         assertEquals("df2 should return the number as 0.5 even though the percent sign is missing",
8908                 0.5,
8909                 result.getDouble(status));
8910     }
8911 }
8912 
TestMultiplierWithScale()8913 void NumberFormatTest::TestMultiplierWithScale() {
8914     IcuTestErrorCode status(*this, "TestMultiplierWithScale");
8915 
8916     // Test magnitude combined with multiplier, as shown in API docs
8917     DecimalFormat df("0", {"en", status}, status);
8918     if (status.isSuccess()) {
8919         df.setMultiplier(5);
8920         df.setMultiplierScale(-1);
8921         expect2(df, 100, u"50"); // round-trip test
8922     }
8923 }
8924 
TestFastFormatInt32()8925 void NumberFormatTest::TestFastFormatInt32() {
8926     IcuTestErrorCode status(*this, "TestFastFormatInt32");
8927 
8928     // The two simplest formatters, old API and new API.
8929     // Old API should use the fastpath for ints.
8930     LocalizedNumberFormatter lnf = NumberFormatter::withLocale("en");
8931     LocalPointer<NumberFormat> df(NumberFormat::createInstance("en", status), status);
8932     if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8933 
8934     double nums[] = {
8935             0.0,
8936             -0.0,
8937             NAN,
8938             INFINITY,
8939             0.1,
8940             1.0,
8941             1.1,
8942             2.0,
8943             3.0,
8944             9.0,
8945             10.0,
8946             99.0,
8947             100.0,
8948             999.0,
8949             1000.0,
8950             9999.0,
8951             10000.0,
8952             99999.0,
8953             100000.0,
8954             999999.0,
8955             1000000.0,
8956             static_cast<double>(INT32_MAX) - 1,
8957             static_cast<double>(INT32_MAX),
8958             static_cast<double>(INT32_MAX) + 1,
8959             static_cast<double>(INT32_MIN) - 1,
8960             static_cast<double>(INT32_MIN),
8961             static_cast<double>(INT32_MIN) + 1};
8962 
8963     for (auto num : nums) {
8964         UnicodeString expected = lnf.formatDouble(num, status).toString(status);
8965         UnicodeString actual;
8966         df->format(num, actual);
8967         assertEquals(UnicodeString("d = ") + num, expected, actual);
8968     }
8969 }
8970 
Test11646_Equality()8971 void NumberFormatTest::Test11646_Equality() {
8972     UErrorCode status = U_ZERO_ERROR;
8973     DecimalFormatSymbols symbols(Locale::getEnglish(), status);
8974     UnicodeString pattern(u"\u00a4\u00a4\u00a4 0.00 %\u00a4\u00a4");
8975     DecimalFormat fmt(pattern, symbols, status);
8976     if (!assertSuccess("", status)) return;
8977 
8978     // Test equality with affixes. set affix methods can't capture special
8979     // characters which is why equality should fail.
8980     {
8981         DecimalFormat fmtCopy(fmt);
8982         assertTrue("", fmt == fmtCopy);
8983         UnicodeString positivePrefix;
8984         fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(positivePrefix));
8985         assertFalse("", fmt == fmtCopy);
8986     }
8987     {
8988         DecimalFormat fmtCopy = DecimalFormat(fmt);
8989         assertTrue("", fmt == fmtCopy);
8990         UnicodeString positivePrefix;
8991         fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(positivePrefix));
8992         assertFalse("", fmt == fmtCopy);
8993     }
8994     {
8995         DecimalFormat fmtCopy(fmt);
8996         assertTrue("", fmt == fmtCopy);
8997         UnicodeString negativePrefix;
8998         fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(negativePrefix));
8999         assertFalse("", fmt == fmtCopy);
9000     }
9001     {
9002         DecimalFormat fmtCopy(fmt);
9003         assertTrue("", fmt == fmtCopy);
9004         UnicodeString negativePrefix;
9005         fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(negativePrefix));
9006         assertFalse("", fmt == fmtCopy);
9007     }
9008 }
9009 
TestParseNaN()9010 void NumberFormatTest::TestParseNaN() {
9011     IcuTestErrorCode status(*this, "TestParseNaN");
9012 
9013     DecimalFormat df("0", { "en", status }, status);
9014     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9015     Formattable parseResult;
9016     df.parse(u"NaN", parseResult, status);
9017     assertEquals("NaN should parse successfully", NAN, parseResult.getDouble());
9018     assertFalse("Result NaN should be positive", std::signbit(parseResult.getDouble()));
9019     UnicodeString formatResult;
9020     df.format(parseResult.getDouble(), formatResult);
9021     assertEquals("NaN should round-trip", u"NaN", formatResult);
9022 }
9023 
TestFormatFailIfMoreThanMaxDigits()9024 void NumberFormatTest::TestFormatFailIfMoreThanMaxDigits() {
9025     IcuTestErrorCode status(*this, "TestFormatFailIfMoreThanMaxDigits");
9026 
9027     DecimalFormat df("0", {"en-US", status}, status);
9028     if (status.errDataIfFailureAndReset()) {
9029         return;
9030     }
9031     assertEquals("Coverage for getter 1", (UBool) FALSE, df.isFormatFailIfMoreThanMaxDigits());
9032     df.setFormatFailIfMoreThanMaxDigits(TRUE);
9033     assertEquals("Coverage for getter 2", (UBool) TRUE, df.isFormatFailIfMoreThanMaxDigits());
9034     df.setMaximumIntegerDigits(2);
9035     UnicodeString result;
9036     df.format(1234, result, status);
9037     status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
9038 }
9039 
TestParseCaseSensitive()9040 void NumberFormatTest::TestParseCaseSensitive() {
9041     IcuTestErrorCode status(*this, "TestParseCaseSensitive");
9042 
9043     DecimalFormat df(u"0", {"en-US", status}, status);
9044     if (status.errDataIfFailureAndReset()) {
9045         return;
9046     }
9047     assertEquals("Coverage for getter 1", (UBool) FALSE, df.isParseCaseSensitive());
9048     df.setParseCaseSensitive(TRUE);
9049     assertEquals("Coverage for getter 1", (UBool) TRUE, df.isParseCaseSensitive());
9050     Formattable result;
9051     ParsePosition ppos;
9052     df.parse(u"1e2", result, ppos);
9053     assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9054     assertEquals("Result should be 1", 1.0, result.getDouble(status));
9055 }
9056 
TestParseNoExponent()9057 void NumberFormatTest::TestParseNoExponent() {
9058     IcuTestErrorCode status(*this, "TestParseNoExponent");
9059 
9060     DecimalFormat df(u"0", {"en-US", status}, status);
9061     if (status.errDataIfFailureAndReset()) {
9062         return;
9063     }
9064     assertEquals("Coverage for getter 1", (UBool) FALSE, df.isParseNoExponent());
9065     df.setParseNoExponent(TRUE);
9066     assertEquals("Coverage for getter 1", (UBool) TRUE, df.isParseNoExponent());
9067     Formattable result;
9068     ParsePosition ppos;
9069     df.parse(u"1E2", result, ppos);
9070     assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9071     assertEquals("Result should be 1", 1.0, result.getDouble(status));
9072 }
9073 
TestSignAlwaysShown()9074 void NumberFormatTest::TestSignAlwaysShown() {
9075     IcuTestErrorCode status(*this, "TestSignAlwaysShown");
9076 
9077     DecimalFormat df(u"0", {"en-US", status}, status);
9078     if (status.errDataIfFailureAndReset()) {
9079         return;
9080     }
9081     assertEquals("Coverage for getter 1", (UBool) FALSE, df.isSignAlwaysShown());
9082     df.setSignAlwaysShown(TRUE);
9083     assertEquals("Coverage for getter 1", (UBool) TRUE, df.isSignAlwaysShown());
9084     UnicodeString result;
9085     df.format(1234, result, status);
9086     status.errIfFailureAndReset();
9087     assertEquals("Should show sign on positive number", u"+1234", result);
9088 }
9089 
TestMinimumGroupingDigits()9090 void NumberFormatTest::TestMinimumGroupingDigits() {
9091     IcuTestErrorCode status(*this, "TestMinimumGroupingDigits");
9092 
9093     DecimalFormat df(u"#,##0", {"en-US", status}, status);
9094     if (status.errDataIfFailureAndReset()) {
9095         return;
9096     }
9097     assertEquals("Coverage for getter 1", -1, df.getMinimumGroupingDigits());
9098     df.setMinimumGroupingDigits(2);
9099     assertEquals("Coverage for getter 1", 2, df.getMinimumGroupingDigits());
9100     UnicodeString result;
9101     df.format(1234, result, status);
9102     status.errIfFailureAndReset();
9103     assertEquals("Should not have grouping", u"1234", result);
9104     df.format(12345, result.remove(), status);
9105     status.errIfFailureAndReset();
9106     assertEquals("Should have grouping", u"12,345", result);
9107 
9108 
9109     // Test special values -1, UNUM_MINIMUM_GROUPING_DIGITS_AUTO and
9110     // UNUM_MINIMUM_GROUPING_DIGITS_MIN2
9111     struct TestCase {
9112         const char* locale;
9113         int32_t minGroup;
9114         double input;
9115         const char16_t* expected;
9116     } cases[] = {
9117         { "en-US", 1, 1000, u"1,000" },
9118         { "en-US", 1, 10000, u"10,000" },
9119         { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1,000" },
9120         { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10,000" },
9121         { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9122         { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10,000" },
9123 
9124         { "es", 1, 1000, u"1.000" },
9125         { "es", 1, 10000, u"10.000" },
9126         { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1000" },
9127         { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10.000" },
9128         { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9129         { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10.000" },
9130     };
9131     for (const auto& cas : cases) {
9132         UnicodeString message = UnicodeString(cas.locale)
9133             + u" " + Int64ToUnicodeString(cas.minGroup)
9134             + u" " + DoubleToUnicodeString(cas.input);
9135         status.setScope(message);
9136         DecimalFormat df(u"#,##0", {cas.locale, status}, status);
9137         if (status.errIfFailureAndReset()) { continue; }
9138         df.setMinimumGroupingDigits(cas.minGroup);
9139         UnicodeString actual;
9140         df.format(cas.input, actual, status);
9141         if (status.errIfFailureAndReset()) { continue; }
9142         assertEquals(message, cas.expected, actual);
9143     }
9144 }
9145 
Test11897_LocalizedPatternSeparator()9146 void NumberFormatTest::Test11897_LocalizedPatternSeparator() {
9147     IcuTestErrorCode status(*this, "Test11897_LocalizedPatternSeparator");
9148 
9149     // In a locale with a different <list> symbol, like arabic,
9150     // kPatternSeparatorSymbol should still be ';'
9151     {
9152         DecimalFormatSymbols dfs("ar", status);
9153         assertEquals("pattern separator symbol should be ;",
9154                 u";",
9155                 dfs.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
9156     }
9157 
9158     // However, the custom symbol should be used in localized notation
9159     // when set manually via API
9160     {
9161         DecimalFormatSymbols dfs("en", status);
9162         dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u"!", FALSE);
9163         DecimalFormat df(u"0", dfs, status);
9164         if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9165         df.applyPattern("a0;b0", status); // should not throw
9166         UnicodeString result;
9167         assertEquals("should apply the normal pattern",
9168                 df.getNegativePrefix(result.remove()),
9169                 "b");
9170         df.applyLocalizedPattern(u"c0!d0", status); // should not throw
9171         assertEquals("should apply the localized pattern",
9172                 df.getNegativePrefix(result.remove()),
9173                 "d");
9174     }
9175 }
9176 
Test13055_PercentageRounding()9177 void NumberFormatTest::Test13055_PercentageRounding() {
9178   IcuTestErrorCode status(*this, "PercentageRounding");
9179   UnicodeString actual;
9180   LocalPointer<NumberFormat>pFormat(NumberFormat::createPercentInstance("en_US", status));
9181   if (U_FAILURE(status)) {
9182       dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9183       return;
9184   }
9185   pFormat->setMaximumFractionDigits(0);
9186   pFormat->setRoundingMode(DecimalFormat::kRoundHalfEven);
9187   pFormat->format(2.155, actual);
9188   assertEquals("Should round percent toward even number", "216%", actual);
9189 }
9190 
Test11839()9191 void NumberFormatTest::Test11839() {
9192     IcuTestErrorCode errorCode(*this, "Test11839");
9193     // Ticket #11839: DecimalFormat does not respect custom plus sign
9194     LocalPointer<DecimalFormatSymbols> dfs(new DecimalFormatSymbols(Locale::getEnglish(), errorCode), errorCode);
9195     if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9196     dfs->setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"a∸");
9197     dfs->setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"b∔"); //  ∔  U+2214 DOT PLUS
9198     DecimalFormat df(u"0.00+;0.00-", dfs.orphan(), errorCode);
9199     UnicodeString result;
9200     df.format(-1.234, result, errorCode);
9201     assertEquals("Locale-specific minus sign should be used", u"1.23a∸", result);
9202     df.format(1.234, result.remove(), errorCode);
9203     assertEquals("Locale-specific plus sign should be used", u"1.23b∔", result);
9204     // Test round-trip with parse
9205     expect2(df, -456, u"456.00a∸");
9206     expect2(df, 456, u"456.00b∔");
9207 }
9208 
Test10354()9209 void NumberFormatTest::Test10354() {
9210     IcuTestErrorCode errorCode(*this, "Test10354");
9211     // Ticket #10354: invalid FieldPositionIterator when formatting with empty NaN
9212     DecimalFormatSymbols dfs(errorCode);
9213     UnicodeString empty;
9214     dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, empty);
9215     DecimalFormat df(errorCode);
9216     df.setDecimalFormatSymbols(dfs);
9217     UnicodeString result;
9218     FieldPositionIterator positions;
9219     df.format(NAN, result, &positions, errorCode);
9220     errorCode.errIfFailureAndReset("DecimalFormat.format(NAN, FieldPositionIterator) failed");
9221     FieldPosition fp;
9222     while (positions.next(fp)) {
9223         // Should not loop forever
9224     }
9225 }
9226 
Test11645_ApplyPatternEquality()9227 void NumberFormatTest::Test11645_ApplyPatternEquality() {
9228     IcuTestErrorCode status(*this, "Test11645_ApplyPatternEquality");
9229     const char16_t* pattern = u"#,##0.0#";
9230     LocalPointer<DecimalFormat> fmt((DecimalFormat*) NumberFormat::createInstance(status), status);
9231     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9232     fmt->applyPattern(pattern, status);
9233     LocalPointer<DecimalFormat> fmtCopy;
9234 
9235     static const int32_t newMultiplier = 37;
9236     fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9237     assertFalse("Value before setter", fmtCopy->getMultiplier() == newMultiplier);
9238     fmtCopy->setMultiplier(newMultiplier);
9239     assertEquals("Value after setter", fmtCopy->getMultiplier(), newMultiplier);
9240     fmtCopy->applyPattern(pattern, status);
9241     assertEquals("Value after applyPattern", fmtCopy->getMultiplier(), newMultiplier);
9242     assertFalse("multiplier", *fmt == *fmtCopy);
9243 
9244     static const NumberFormat::ERoundingMode newRoundingMode = NumberFormat::ERoundingMode::kRoundCeiling;
9245     fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9246     assertFalse("Value before setter", fmtCopy->getRoundingMode() == newRoundingMode);
9247     fmtCopy->setRoundingMode(newRoundingMode);
9248     assertEquals("Value after setter", fmtCopy->getRoundingMode(), newRoundingMode);
9249     fmtCopy->applyPattern(pattern, status);
9250     assertEquals("Value after applyPattern", fmtCopy->getRoundingMode(), newRoundingMode);
9251     assertFalse("roundingMode", *fmt == *fmtCopy);
9252 
9253     static const char16_t *const newCurrency = u"EAT";
9254     fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9255     assertFalse("Value before setter", fmtCopy->getCurrency() == newCurrency);
9256     fmtCopy->setCurrency(newCurrency);
9257     assertEquals("Value after setter", fmtCopy->getCurrency(), newCurrency);
9258     fmtCopy->applyPattern(pattern, status);
9259     assertEquals("Value after applyPattern", fmtCopy->getCurrency(), newCurrency);
9260     assertFalse("currency", *fmt == *fmtCopy);
9261 
9262     static const UCurrencyUsage newCurrencyUsage = UCurrencyUsage::UCURR_USAGE_CASH;
9263     fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9264     assertFalse("Value before setter", fmtCopy->getCurrencyUsage() == newCurrencyUsage);
9265     fmtCopy->setCurrencyUsage(newCurrencyUsage, status);
9266     assertEquals("Value after setter", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9267     fmtCopy->applyPattern(pattern, status);
9268     assertEquals("Value after applyPattern", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9269     assertFalse("currencyUsage", *fmt == *fmtCopy);
9270 }
9271 
Test12567()9272 void NumberFormatTest::Test12567() {
9273     IcuTestErrorCode errorCode(*this, "Test12567");
9274     // Ticket #12567: DecimalFormat.equals() may not be symmetric
9275     LocalPointer<DecimalFormat> df1((DecimalFormat *)
9276         NumberFormat::createInstance(Locale::getUS(), UNUM_CURRENCY, errorCode));
9277     LocalPointer<DecimalFormat> df2((DecimalFormat *)
9278         NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, errorCode));
9279     if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9280     // NOTE: CurrencyPluralInfo equality not tested in C++ because its operator== is not defined.
9281     df1->applyPattern(u"0.00", errorCode);
9282     df2->applyPattern(u"0.00", errorCode);
9283     assertTrue("df1 == df2", *df1 == *df2);
9284     assertTrue("df2 == df1", *df2 == *df1);
9285     df2->setPositivePrefix(u"abc");
9286     assertTrue("df1 != df2", *df1 != *df2);
9287     assertTrue("df2 != df1", *df2 != *df1);
9288 }
9289 
Test11626_CustomizeCurrencyPluralInfo()9290 void NumberFormatTest::Test11626_CustomizeCurrencyPluralInfo() {
9291     IcuTestErrorCode errorCode(*this, "Test11626_CustomizeCurrencyPluralInfo");
9292     // Ticket #11626: No unit test demonstrating how to use CurrencyPluralInfo to
9293     // change formatting spelled out currencies
9294     // Use locale sr because it has interesting plural rules.
9295     Locale locale("sr");
9296     LocalPointer<DecimalFormatSymbols> symbols(new DecimalFormatSymbols(locale, errorCode), errorCode);
9297     CurrencyPluralInfo info(locale, errorCode);
9298     if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9299     info.setCurrencyPluralPattern(u"one", u"0 qwerty", errorCode);
9300     info.setCurrencyPluralPattern(u"few", u"0 dvorak", errorCode);
9301     DecimalFormat df(u"#", symbols.orphan(), UNUM_CURRENCY_PLURAL, errorCode);
9302     df.setCurrencyPluralInfo(info);
9303     df.setCurrency(u"USD");
9304     df.setMaximumFractionDigits(0);
9305 
9306     UnicodeString result;
9307     assertEquals("Plural one", u"1 qwerty", df.format(1, result, errorCode));
9308     assertEquals("Plural few", u"3 dvorak", df.format(3, result.remove(), errorCode));
9309     assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9310 
9311     info.setPluralRules(u"few: n is 1; one: n in 2..4", errorCode);
9312     df.setCurrencyPluralInfo(info);
9313     assertEquals("Plural one", u"1 dvorak", df.format(1, result.remove(), errorCode));
9314     assertEquals("Plural few", u"3 qwerty", df.format(3, result.remove(), errorCode));
9315     assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9316 }
9317 
Test20073_StrictPercentParseErrorIndex()9318 void NumberFormatTest::Test20073_StrictPercentParseErrorIndex() {
9319     IcuTestErrorCode status(*this, "Test20073_StrictPercentParseErrorIndex");
9320     ParsePosition parsePosition(0);
9321     DecimalFormat df(u"0%", {"en-us", status}, status);
9322     if (U_FAILURE(status)) {
9323         dataerrln("Unable to create DecimalFormat instance.");
9324         return;
9325     }
9326     df.setLenient(FALSE);
9327     Formattable result;
9328     df.parse(u"%2%", result, parsePosition);
9329     assertEquals("", 0, parsePosition.getIndex());
9330     assertEquals("", 0, parsePosition.getErrorIndex());
9331 }
9332 
Test13056_GroupingSize()9333 void NumberFormatTest::Test13056_GroupingSize() {
9334     UErrorCode status = U_ZERO_ERROR;
9335     DecimalFormat df(u"#,##0", status);
9336     if (!assertSuccess("", status)) return;
9337     assertEquals("Primary grouping should return 3", 3, df.getGroupingSize());
9338     assertEquals("Secondary grouping should return 0", 0, df.getSecondaryGroupingSize());
9339     df.setSecondaryGroupingSize(3);
9340     assertEquals("Primary grouping should still return 3", 3, df.getGroupingSize());
9341     assertEquals("Secondary grouping should round-trip", 3, df.getSecondaryGroupingSize());
9342     df.setGroupingSize(4);
9343     assertEquals("Primary grouping should return 4", 4, df.getGroupingSize());
9344     assertEquals("Secondary should remember explicit setting and return 3", 3, df.getSecondaryGroupingSize());
9345 }
9346 
9347 
Test11025_CurrencyPadding()9348 void NumberFormatTest::Test11025_CurrencyPadding() {
9349     UErrorCode status = U_ZERO_ERROR;
9350     UnicodeString pattern(u"¤¤ **####0.00");
9351     DecimalFormatSymbols sym(Locale::getFrance(), status);
9352     if (!assertSuccess("", status)) return;
9353     DecimalFormat fmt(pattern, sym, status);
9354     if (!assertSuccess("", status)) return;
9355     UnicodeString result;
9356     fmt.format(433.0, result);
9357     assertEquals("Number should be padded to 11 characters", "EUR *433,00", result);
9358 }
9359 
Test11648_ExpDecFormatMalPattern()9360 void NumberFormatTest::Test11648_ExpDecFormatMalPattern() {
9361     UErrorCode status = U_ZERO_ERROR;
9362 
9363     DecimalFormat fmt("0.00", {"en", status}, status);
9364     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9365     fmt.setScientificNotation(TRUE);
9366     UnicodeString pattern;
9367 
9368     assertEquals("A valid scientific notation pattern should be produced",
9369             "0.00E0",
9370             fmt.toPattern(pattern));
9371 
9372     DecimalFormat fmt2(pattern, status);
9373     assertSuccess("", status);
9374 }
9375 
Test11649_DecFmtCurrencies()9376 void NumberFormatTest::Test11649_DecFmtCurrencies() {
9377     IcuTestErrorCode status(*this, "Test11649_DecFmtCurrencies");
9378     UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
9379     pattern = pattern.unescape();
9380     DecimalFormat fmt(pattern, status);
9381     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9382     static const UChar USD[] = u"USD";
9383     fmt.setCurrency(USD);
9384     UnicodeString appendTo;
9385 
9386     assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
9387     UnicodeString topattern;
9388 
9389     assertEquals("", pattern, fmt.toPattern(topattern));
9390     DecimalFormat fmt2(topattern, status);
9391     fmt2.setCurrency(USD);
9392 
9393     appendTo.remove();
9394     assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
9395 }
9396 
Test13148_ParseGroupingSeparators()9397 void NumberFormatTest::Test13148_ParseGroupingSeparators() {
9398   IcuTestErrorCode status(*this, "Test13148");
9399   LocalPointer<DecimalFormat> fmt(
9400       (DecimalFormat*)NumberFormat::createInstance("en-ZA", status), status);
9401   if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9402 
9403   DecimalFormatSymbols symbols = *fmt->getDecimalFormatSymbols();
9404 
9405   symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'.');
9406   symbols.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u',');
9407   fmt->setDecimalFormatSymbols(symbols);
9408   Formattable number;
9409   fmt->parse(u"300,000", number, status);
9410   assertEquals("Should parse as 300000", 300000LL, number.getInt64(status));
9411 }
9412 
Test12753_PatternDecimalPoint()9413 void NumberFormatTest::Test12753_PatternDecimalPoint() {
9414     UErrorCode status = U_ZERO_ERROR;
9415     DecimalFormatSymbols symbols(Locale::getUS(), status);
9416     symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"*", false);
9417     DecimalFormat df(u"0.00", symbols, status);
9418     if (!assertSuccess("", status)) return;
9419     df.setDecimalPatternMatchRequired(true);
9420     Formattable result;
9421     df.parse(u"123",result, status);
9422     assertEquals("Parsing integer succeeded even though setDecimalPatternMatchRequired was set",
9423                  U_INVALID_FORMAT_ERROR, status);
9424     }
9425 
Test11647_PatternCurrencySymbols()9426  void NumberFormatTest::Test11647_PatternCurrencySymbols() {
9427     UErrorCode status = U_ZERO_ERROR;
9428     DecimalFormat df(status);
9429     df.applyPattern(u"¤¤¤¤#", status);
9430     if (!assertSuccess("", status)) return;
9431     UnicodeString actual;
9432     df.format(123, actual);
9433     assertEquals("Should replace 4 currency signs with U+FFFD", u"\uFFFD123", actual);
9434 }
9435 
Test11913_BigDecimal()9436 void NumberFormatTest::Test11913_BigDecimal() {
9437     UErrorCode status = U_ZERO_ERROR;
9438     LocalPointer<NumberFormat> df(NumberFormat::createInstance(Locale::getEnglish(), status), status);
9439     if (!assertSuccess("", status)) return;
9440     UnicodeString result;
9441     df->format(StringPiece("1.23456789E400"), result, nullptr, status);
9442     assertSuccess("", status);
9443     assertEquals("Should format more than 309 digits", u"12,345,678", UnicodeString(result, 0, 10));
9444     assertEquals("Should format more than 309 digits", 534, result.length());
9445 }
9446 
Test11020_RoundingInScientificNotation()9447 void NumberFormatTest::Test11020_RoundingInScientificNotation() {
9448     UErrorCode status = U_ZERO_ERROR;
9449     DecimalFormatSymbols sym(Locale::getFrance(), status);
9450     DecimalFormat fmt(u"0.05E0", sym, status);
9451     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9452     assertSuccess("", status);
9453     UnicodeString result;
9454     fmt.format(12301.2, result);
9455     assertEquals("Rounding increment should be applied after magnitude scaling", u"1,25E4", result);
9456 }
9457 
Test11640_TripleCurrencySymbol()9458 void NumberFormatTest::Test11640_TripleCurrencySymbol() {
9459     IcuTestErrorCode status(*this, "Test11640_TripleCurrencySymbol");
9460     UnicodeString actual;
9461     DecimalFormat dFormat(u"¤¤¤ 0", status);
9462     if (U_FAILURE(status)) {
9463         dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9464         return;
9465     }
9466     dFormat.setCurrency(u"USD");
9467     UnicodeString result;
9468     dFormat.getPositivePrefix(result);
9469     assertEquals("Triple-currency should give long name on getPositivePrefix",
9470                 "US dollars ", result);
9471 }
9472 
9473 
Test13763_FieldPositionIteratorOffset()9474 void NumberFormatTest::Test13763_FieldPositionIteratorOffset() {
9475     IcuTestErrorCode status(*this, "Test13763_FieldPositionIteratorOffset");
9476     FieldPositionIterator fpi;
9477     UnicodeString result(u"foo\U0001F4FBbar"); // 8 code units
9478     LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9479     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9480     nf->format(5142.3, result, &fpi, status);
9481 
9482     int32_t expected[] = {
9483       UNUM_GROUPING_SEPARATOR_FIELD, 9, 10,
9484       UNUM_INTEGER_FIELD, 8, 13,
9485       UNUM_DECIMAL_SEPARATOR_FIELD, 13, 14,
9486       UNUM_FRACTION_FIELD, 14, 15,
9487     };
9488     int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
9489     expectPositions(fpi, expected, tupleCount, result);
9490 }
9491 
Test13777_ParseLongNameNonCurrencyMode()9492 void NumberFormatTest::Test13777_ParseLongNameNonCurrencyMode() {
9493     IcuTestErrorCode status(*this, "Test13777_ParseLongNameNonCurrencyMode");
9494 
9495     LocalPointer<NumberFormat> df(
9496         NumberFormat::createInstance("en-us", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9497     if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9498     expect2(*df, 1.5, u"1.50 US dollars");
9499 }
9500 
Test13804_EmptyStringsWhenParsing()9501 void NumberFormatTest::Test13804_EmptyStringsWhenParsing() {
9502     IcuTestErrorCode status(*this, "Test13804_EmptyStringsWhenParsing");
9503 
9504     DecimalFormatSymbols dfs("en", status);
9505     if (status.errIfFailureAndReset()) {
9506         return;
9507     }
9508     dfs.setSymbol(DecimalFormatSymbols::kCurrencySymbol, u"", FALSE);
9509     dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"", FALSE);
9510     dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u"", FALSE);
9511     dfs.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, u"", FALSE);
9512     dfs.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, u"", FALSE);
9513     dfs.setSymbol(DecimalFormatSymbols::kThreeDigitSymbol, u"", FALSE);
9514     dfs.setSymbol(DecimalFormatSymbols::kFourDigitSymbol, u"", FALSE);
9515     dfs.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, u"", FALSE);
9516     dfs.setSymbol(DecimalFormatSymbols::kSixDigitSymbol, u"", FALSE);
9517     dfs.setSymbol(DecimalFormatSymbols::kSevenDigitSymbol, u"", FALSE);
9518     dfs.setSymbol(DecimalFormatSymbols::kEightDigitSymbol, u"", FALSE);
9519     dfs.setSymbol(DecimalFormatSymbols::kNineDigitSymbol, u"", FALSE);
9520     dfs.setSymbol(DecimalFormatSymbols::kExponentMultiplicationSymbol, u"", FALSE);
9521     dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"", FALSE);
9522     dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u"", FALSE);
9523     dfs.setSymbol(DecimalFormatSymbols::kInfinitySymbol, u"", FALSE);
9524     dfs.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, u"", FALSE);
9525     dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"", FALSE);
9526     dfs.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, u"", FALSE);
9527     dfs.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, u"", FALSE);
9528     dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, u"", FALSE);
9529     dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, FALSE, u"");
9530     dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, TRUE, u"");
9531     dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u"", FALSE);
9532     dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u"", FALSE);
9533     dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"", FALSE);
9534 
9535     DecimalFormat df("0", dfs, status);
9536     if (status.errIfFailureAndReset()) {
9537         return;
9538     }
9539     df.setGroupingUsed(TRUE);
9540     df.setScientificNotation(TRUE);
9541     df.setLenient(TRUE); // enable all matchers
9542     {
9543         UnicodeString result;
9544         df.format(0, result); // should not crash or hit infinite loop
9545     }
9546     const char16_t* samples[] = {
9547             u"",
9548             u"123",
9549             u"$123",
9550             u"-",
9551             u"+",
9552             u"44%",
9553             u"1E+2.3"
9554     };
9555     for (auto& sample : samples) {
9556         logln(UnicodeString(u"Attempting parse on: ") + sample);
9557         status.setScope(sample);
9558         // We don't care about the results, only that we don't crash and don't loop.
9559         Formattable result;
9560         ParsePosition ppos(0);
9561         df.parse(sample, result, ppos);
9562         ppos = ParsePosition(0);
9563         LocalPointer<CurrencyAmount> curramt(df.parseCurrency(sample, ppos));
9564         status.errIfFailureAndReset();
9565     }
9566 
9567     // Test with a nonempty exponent separator symbol to cover more code
9568     dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"E", FALSE);
9569     df.setDecimalFormatSymbols(dfs);
9570     {
9571         Formattable result;
9572         ParsePosition ppos(0);
9573         df.parse(u"1E+2.3", result, ppos);
9574     }
9575 }
9576 
Test20037_ScientificIntegerOverflow()9577 void NumberFormatTest::Test20037_ScientificIntegerOverflow() {
9578     IcuTestErrorCode status(*this, "Test20037_ScientificIntegerOverflow");
9579 
9580     LocalPointer<NumberFormat> nf(NumberFormat::createInstance(status));
9581     if (U_FAILURE(status)) {
9582         dataerrln("Unable to create NumberFormat instance.");
9583         return;
9584     }
9585     Formattable result;
9586 
9587     // Test overflow of exponent
9588     nf->parse(u"1E-2147483648", result, status);
9589     StringPiece sp = result.getDecimalNumber(status);
9590     assertEquals(u"Should snap to zero",
9591                  u"0",
9592                  {sp.data(), sp.length(), US_INV});
9593 
9594     // Test edge case overflow of exponent
9595     result = Formattable();
9596     nf->parse(u"1E-2147483647E-1", result, status);
9597     sp = result.getDecimalNumber(status);
9598     assertEquals(u"Should not overflow and should parse only the first exponent",
9599                  u"1E-2147483647",
9600                  {sp.data(), sp.length(), US_INV});
9601 
9602     // Test edge case overflow of exponent
9603     result = Formattable();
9604     nf->parse(u".0003e-2147483644", result, status);
9605     sp = result.getDecimalNumber(status);
9606     assertEquals(u"Should not overflow",
9607                  u"3E-2147483648",
9608                  {sp.data(), sp.length(), US_INV});
9609 
9610     // Test largest parseable exponent
9611     result = Formattable();
9612     nf->parse(u"9876e2147483643", result, status);
9613     sp = result.getDecimalNumber(status);
9614     assertEquals(u"Should not overflow",
9615                  u"9.876E+2147483646",
9616                  {sp.data(), sp.length(), US_INV});
9617 
9618     // Test max value as well
9619     const char16_t* infinityInputs[] = {
9620             u"9876e2147483644",
9621             u"9876e2147483645",
9622             u"9876e2147483646",
9623             u"9876e2147483647",
9624             u"9876e2147483648",
9625             u"9876e2147483649",
9626     };
9627     for (const auto& input : infinityInputs) {
9628         result = Formattable();
9629         nf->parse(input, result, status);
9630         sp = result.getDecimalNumber(status);
9631         assertEquals(UnicodeString("Should become Infinity: ") + input,
9632                     u"Infinity",
9633                     {sp.data(), sp.length(), US_INV});
9634     }
9635 }
9636 
Test13840_ParseLongStringCrash()9637 void NumberFormatTest::Test13840_ParseLongStringCrash() {
9638     IcuTestErrorCode status(*this, "Test13840_ParseLongStringCrash");
9639 
9640     LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9641     if (status.errIfFailureAndReset()) { return; }
9642 
9643     Formattable result;
9644     static const char16_t* bigString =
9645         u"111111111111111111111111111111111111111111111111111111111111111111111"
9646         u"111111111111111111111111111111111111111111111111111111111111111111111"
9647         u"111111111111111111111111111111111111111111111111111111111111111111111"
9648         u"111111111111111111111111111111111111111111111111111111111111111111111"
9649         u"111111111111111111111111111111111111111111111111111111111111111111111"
9650         u"111111111111111111111111111111111111111111111111111111111111111111111";
9651     nf->parse(bigString, result, status);
9652 
9653     // Normalize the input string:
9654     CharString expectedChars;
9655     expectedChars.appendInvariantChars(bigString, status);
9656     DecimalQuantity expectedDQ;
9657     expectedDQ.setToDecNumber(expectedChars.toStringPiece(), status);
9658     UnicodeString expectedUString = expectedDQ.toScientificString();
9659 
9660     // Get the output string:
9661     StringPiece actualChars = result.getDecimalNumber(status);
9662     UnicodeString actualUString = UnicodeString(actualChars.data(), actualChars.length(), US_INV);
9663 
9664     assertEquals("Should round-trip without crashing", expectedUString, actualUString);
9665 }
9666 
Test13850_EmptyStringCurrency()9667 void NumberFormatTest::Test13850_EmptyStringCurrency() {
9668     IcuTestErrorCode status(*this, "Test13840_EmptyStringCurrency");
9669 
9670     struct TestCase {
9671         const char16_t* currencyArg;
9672         UErrorCode expectedError;
9673     } cases[] = {
9674         {u"", U_USING_FALLBACK_WARNING},
9675         {u"U", U_ILLEGAL_ARGUMENT_ERROR},
9676         {u"Us", U_ILLEGAL_ARGUMENT_ERROR},
9677         {nullptr, U_USING_FALLBACK_WARNING},
9678         {u"U$D", U_INVARIANT_CONVERSION_ERROR},
9679         {u"Xxx", U_USING_FALLBACK_WARNING}
9680     };
9681     for (const auto& cas : cases) {
9682         UnicodeString message(u"with currency arg: ");
9683         if (cas.currencyArg == nullptr) {
9684             message += u"nullptr";
9685         } else {
9686             message += UnicodeString(cas.currencyArg);
9687         }
9688         status.setScope(message);
9689         LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-US", status), status);
9690         if (status.errIfFailureAndReset()) { return; }
9691         UnicodeString actual;
9692         nf->format(1, actual, status);
9693         status.errIfFailureAndReset();
9694         assertEquals(u"Should format with US currency " + message, u"$1.00", actual);
9695         nf->setCurrency(cas.currencyArg, status);
9696         if (status.expectErrorAndReset(cas.expectedError)) {
9697             // If an error occurred, do not check formatting.
9698             continue;
9699         }
9700         nf->format(1, actual.remove(), status);
9701         assertEquals(u"Should unset the currency " + message, u"\u00A41.00", actual);
9702         status.errIfFailureAndReset();
9703     }
9704 }
9705 
Test20348_CurrencyPrefixOverride()9706 void NumberFormatTest::Test20348_CurrencyPrefixOverride() {
9707     IcuTestErrorCode status(*this, "Test20348_CurrencyPrefixOverride");
9708     LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9709         NumberFormat::createCurrencyInstance("en", status)));
9710     if (status.errIfFailureAndReset()) { return; }
9711     UnicodeString result;
9712     assertEquals("Initial pattern",
9713         u"¤#,##0.00", fmt->toPattern(result.remove()));
9714     assertEquals("Initial prefix",
9715         u"¤", fmt->getPositivePrefix(result.remove()));
9716     assertEquals("Initial suffix",
9717         u"-¤", fmt->getNegativePrefix(result.remove()));
9718     assertEquals("Initial format",
9719         u"\u00A4100.00", fmt->format(100, result.remove(), NULL, status));
9720 
9721     fmt->setPositivePrefix(u"$");
9722     assertEquals("Set positive prefix pattern",
9723         u"$#,##0.00;-\u00A4#,##0.00", fmt->toPattern(result.remove()));
9724     assertEquals("Set positive prefix prefix",
9725         u"$", fmt->getPositivePrefix(result.remove()));
9726     assertEquals("Set positive prefix suffix",
9727         u"-¤", fmt->getNegativePrefix(result.remove()));
9728     assertEquals("Set positive prefix format",
9729         u"$100.00", fmt->format(100, result.remove(), NULL, status));
9730 
9731     fmt->setNegativePrefix(u"-$");
9732     assertEquals("Set negative prefix pattern",
9733         u"$#,##0.00;'-'$#,##0.00", fmt->toPattern(result.remove()));
9734     assertEquals("Set negative prefix prefix",
9735         u"$", fmt->getPositivePrefix(result.remove()));
9736     assertEquals("Set negative prefix suffix",
9737         u"-$", fmt->getNegativePrefix(result.remove()));
9738     assertEquals("Set negative prefix format",
9739         u"$100.00", fmt->format(100, result.remove(), NULL, status));
9740 }
9741 
Test20956_MonetarySymbolGetters()9742 void NumberFormatTest::Test20956_MonetarySymbolGetters() {
9743     IcuTestErrorCode status(*this, "Test20956_MonetarySymbolGetters");
9744     LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9745         NumberFormat::createCurrencyInstance("et", status)));
9746     if (status.errDataIfFailureAndReset()) {
9747         return;
9748     }
9749 
9750     decimalFormat->setCurrency(u"EEK");
9751 
9752     const DecimalFormatSymbols* decimalFormatSymbols = decimalFormat->getDecimalFormatSymbols();
9753     assertEquals("MONETARY DECIMAL SEPARATOR",
9754         u".",
9755         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
9756     assertEquals("DECIMAL SEPARATOR",
9757         u",",
9758         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol));
9759     assertEquals("MONETARY GROUPING SEPARATOR",
9760         u" ",
9761         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol));
9762     assertEquals("GROUPING SEPARATOR",
9763         u" ",
9764         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
9765     assertEquals("CURRENCY SYMBOL",
9766         u"kr",
9767         decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
9768 
9769     UnicodeString sb;
9770     decimalFormat->format(12345.12, sb, status);
9771     assertEquals("OUTPUT", u"12 345.12 kr", sb);
9772 }
9773 
Test20358_GroupingInPattern()9774 void NumberFormatTest::Test20358_GroupingInPattern() {
9775     IcuTestErrorCode status(*this, "Test20358_GroupingInPattern");
9776     LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9777         NumberFormat::createInstance("en", status)));
9778     if (status.errIfFailureAndReset()) { return; }
9779     UnicodeString result;
9780     assertEquals("Initial pattern",
9781         u"#,##0.###", fmt->toPattern(result.remove()));
9782     assertTrue("Initial grouping",
9783         fmt->isGroupingUsed());
9784     assertEquals("Initial format",
9785         u"54,321", fmt->format(54321, result.remove(), NULL, status));
9786 
9787     fmt->setGroupingUsed(false);
9788     assertEquals("Set grouping false",
9789         u"0.###", fmt->toPattern(result.remove()));
9790     assertFalse("Set grouping false grouping",
9791         fmt->isGroupingUsed());
9792     assertEquals("Set grouping false format",
9793         u"54321", fmt->format(54321, result.remove(), NULL, status));
9794 
9795     fmt->setGroupingUsed(true);
9796     assertEquals("Set grouping true",
9797         u"#,##0.###", fmt->toPattern(result.remove()));
9798     assertTrue("Set grouping true grouping",
9799         fmt->isGroupingUsed());
9800     assertEquals("Set grouping true format",
9801         u"54,321", fmt->format(54321, result.remove(), NULL, status));
9802 }
9803 
Test13731_DefaultCurrency()9804 void NumberFormatTest::Test13731_DefaultCurrency() {
9805     IcuTestErrorCode status(*this, "Test13731_DefaultCurrency");
9806     UnicodeString result;
9807     {
9808         LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9809             "en", UNumberFormatStyle::UNUM_CURRENCY, status), status);
9810         if (status.errIfFailureAndReset()) { return; }
9811         assertEquals("symbol", u"¤1.10",
9812             nf->format(1.1, result.remove(), status));
9813         assertEquals("currency", u"XXX", nf->getCurrency());
9814     }
9815     {
9816         LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9817             "en", UNumberFormatStyle::UNUM_CURRENCY_ISO, status), status);
9818         if (status.errIfFailureAndReset()) { return; }
9819         assertEquals("iso_code", u"XXX 1.10",
9820             nf->format(1.1, result.remove(), status));
9821         assertEquals("currency", u"XXX", nf->getCurrency());
9822     }
9823     {
9824         LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9825             "en", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9826         if (status.errIfFailureAndReset()) { return; }
9827         assertEquals("plural", u"1.10 (unknown currency)",
9828             nf->format(1.1, result.remove(), status));
9829         assertEquals("currency", u"XXX", nf->getCurrency());
9830     }
9831 }
9832 
Test20499_CurrencyVisibleDigitsPlural()9833 void NumberFormatTest::Test20499_CurrencyVisibleDigitsPlural() {
9834     IcuTestErrorCode status(*this, "Test20499_CurrencyVisibleDigitsPlural");
9835     LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9836         "ro-RO", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9837     const char16_t* expected = u"24,00 lei românești";
9838     for (int32_t i=0; i<5; i++) {
9839         UnicodeString actual;
9840         nf->format(24, actual, status);
9841         assertEquals(UnicodeString(u"iteration ") + Int64ToUnicodeString(i),
9842             expected, actual);
9843     }
9844 }
9845 
Test13735_GroupingSizeGetter()9846 void NumberFormatTest::Test13735_GroupingSizeGetter() {
9847     IcuTestErrorCode status(*this, "Test13735_GroupingSizeGetter");
9848     {
9849         DecimalFormat df("0", {"en", status}, status);
9850         assertEquals("pat 0: ", 0, df.getGroupingSize());
9851         df.setGroupingUsed(false);
9852         assertEquals("pat 0 then disabled: ", 0, df.getGroupingSize());
9853         df.setGroupingUsed(true);
9854         assertEquals("pat 0 then enabled: ", 0, df.getGroupingSize());
9855     }
9856     {
9857         DecimalFormat df("#,##0", {"en", status}, status);
9858         assertEquals("pat #,##0: ", 3, df.getGroupingSize());
9859         df.setGroupingUsed(false);
9860         assertEquals("pat #,##0 then disabled: ", 3, df.getGroupingSize());
9861         df.setGroupingUsed(true);
9862         assertEquals("pat #,##0 then enabled: ", 3, df.getGroupingSize());
9863     }
9864 }
9865 
Test13734_StrictFlexibleWhitespace()9866 void NumberFormatTest::Test13734_StrictFlexibleWhitespace() {
9867     IcuTestErrorCode status(*this, "Test13734_StrictFlexibleWhitespace");
9868     {
9869         DecimalFormat df("+0", {"en", status}, status);
9870         df.setLenient(FALSE);
9871         Formattable result;
9872         ParsePosition ppos;
9873         df.parse("+  33", result, ppos);
9874         assertEquals("ppos : ", 0, ppos.getIndex());
9875         assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9876     }
9877     {
9878         DecimalFormat df("+ 0", {"en", status}, status);
9879         df.setLenient(FALSE);
9880         Formattable result;
9881         ParsePosition ppos;
9882         df.parse("+  33", result, ppos);
9883         assertEquals("ppos : ", 0, ppos.getIndex());
9884         assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9885     }
9886 }
9887 
Test20961_CurrencyPluralPattern()9888 void NumberFormatTest::Test20961_CurrencyPluralPattern() {
9889     IcuTestErrorCode status(*this, "Test20961_CurrencyPluralPattern");
9890     {
9891         LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9892             NumberFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9893         if (status.errDataIfFailureAndReset()) {
9894             return;
9895         }
9896         UnicodeString result;
9897         decimalFormat->toPattern(result);
9898         assertEquals("Currency pattern", u"#,##0.00 ¤¤¤", result);
9899     }
9900 }
9901 
Test21134_ToNumberFormatter()9902 void NumberFormatTest::Test21134_ToNumberFormatter() {
9903     IcuTestErrorCode status(*this, "Test21134_ToNumberFormatter");
9904     LocalizedNumberFormatter outer1;
9905     LocalizedNumberFormatter outer2;
9906     LocalPointer<LocalizedNumberFormatter> outer3;
9907     {
9908         // Case 1: new formatter object
9909         DecimalFormat inner(u"a0b", {"en", status}, status);
9910         if (auto ptr = inner.toNumberFormatter(status)) {
9911             // Copy assignment
9912             outer1 = *ptr;
9913         } else {
9914             status.errIfFailureAndReset();
9915             return;
9916         }
9917     }
9918     {
9919         // Case 2: compiled formatter object (used at least 3 times)
9920         DecimalFormat inner(u"c0d", {"en", status}, status);
9921         UnicodeString dummy;
9922         inner.format(100, dummy);
9923         inner.format(100, dummy);
9924         inner.format(100, dummy);
9925         if (auto ptr = inner.toNumberFormatter(status)) {
9926             // Copy assignment
9927             outer2 = *ptr;
9928         } else {
9929             status.errIfFailureAndReset();
9930             return;
9931         }
9932     }
9933     {
9934         // Case 3: currency plural info (different code path)
9935         LocalPointer<DecimalFormat> inner(static_cast<DecimalFormat*>(
9936             DecimalFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9937         if (auto ptr = inner->toNumberFormatter(status)) {
9938             // Copy constructor
9939             outer3.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(*ptr), status);
9940         } else {
9941             status.errIfFailureAndReset();
9942             return;
9943         }
9944     }
9945     auto result1 = outer1.formatDouble(99, status);
9946     assertEquals("Using NumberFormatter from DecimalFormat, new version",
9947         u"a99b",
9948         result1.toTempString(status));
9949     auto result2 = outer2.formatDouble(99, status);
9950     assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9951         u"c99d",
9952         result2.toTempString(status));
9953     auto result3 = outer3->formatDouble(99, status);
9954     assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9955         u"99.00 US dollars",
9956         result3.toTempString(status));
9957 }
9958 
Test13733_StrictAndLenient()9959 void NumberFormatTest::Test13733_StrictAndLenient() {
9960     IcuTestErrorCode status(*this, "Test13733_StrictAndLenient");
9961 
9962     static const struct TestCase {
9963         const char16_t* inputString;
9964         const char16_t* patternString;
9965         int64_t expectedStrictParse;
9966         int64_t expectedLenientParse;
9967     } cases[] = { {u"CA$ 12", u"¤ 0", 12, 12},
9968                   {u"CA$12", u"¤0", 12, 12},
9969                   {u"CAD 12", u"¤¤ 0", 12, 12},
9970                   {u"12 CAD", u"0 ¤¤", 12, 12},
9971                   {u"12 Canadian dollars", u"0 ¤¤¤", 12, 12},
9972                   {u"$12 ", u"¤¤¤¤0", 12, 12},
9973                   {u"12$", u"0¤¤¤¤", 12, 12},
9974                   {u"CA$ 12", u"¤0", 0, 12},
9975                   {u"CA$ 12", u"0 ¤¤", 0, 12},
9976                   {u"CA$ 12", u"0 ¤¤¤", 0, 12},
9977                   {u"CA$ 12", u"¤¤¤¤0", 0, 12},
9978                   {u"CA$ 12", u"0¤¤¤¤", 0, 12},
9979                   {u"CA$12", u"¤ 0", 0, 12},
9980                   {u"CA$12", u"¤¤ 0", 0, 12},
9981                   {u"CA$12", u"0 ¤¤", 0, 12},
9982                   {u"CA$12", u"0 ¤¤¤", 0, 12},
9983                   {u"CA$12", u"0¤¤¤¤", 0, 12},
9984                   {u"CAD 12", u"¤0", 0, 12},
9985                   {u"CAD 12", u"0 ¤¤", 0, 12},
9986                   {u"CAD 12", u"0 ¤¤¤", 0, 12},
9987                   {u"CAD 12", u"¤¤¤¤0", 0, 12},
9988                   {u"CAD 12", u"0¤¤¤¤", 0, 12},
9989                   {u"12 CAD", u"¤ 0", 0, 12},
9990                   {u"12 CAD", u"¤0", 0, 12},
9991                   {u"12 CAD", u"¤¤ 0", 0, 12},
9992                   {u"12 CAD", u"¤¤¤¤0", 0, 12},
9993                   {u"12 CAD", u"0¤¤¤¤", 0, 12},
9994                   {u"12 Canadian dollars", u"¤ 0", 0, 12},
9995                   {u"12 Canadian dollars", u"¤0", 0, 12},
9996                   {u"12 Canadian dollars", u"¤¤ 0", 0, 12},
9997                   {u"12 Canadian dollars", u"¤¤¤¤0", 0, 12},
9998                   {u"12 Canadian dollars", u"0¤¤¤¤", 0, 12},
9999                   {u"$12 ", u"¤ 0", 0, 12},
10000                   {u"$12 ", u"¤¤ 0", 0, 12},
10001                   {u"$12 ", u"0 ¤¤", 0, 12},
10002                   {u"$12 ", u"0 ¤¤¤", 0, 12},
10003                   {u"$12 ", u"0¤¤¤¤", 0, 12},
10004                   {u"12$", u"¤ 0", 0, 12},
10005                   {u"12$", u"¤0", 0, 12},
10006                   {u"12$", u"¤¤ 0", 0, 12},
10007                   {u"12$", u"0 ¤¤", 0, 12},
10008                   {u"12$", u"0 ¤¤¤", 0, 12},
10009                   {u"12$", u"¤¤¤¤0", 0, 12} };
10010     for (auto& cas : cases) {
10011         UnicodeString inputString(cas.inputString);
10012         UnicodeString patternString(cas.patternString);
10013         int64_t parsedStrictValue = 0;
10014         int64_t parsedLenientValue = 0;
10015         ParsePosition ppos;
10016 
10017         DecimalFormatSymbols dfs(Locale::getEnglish(), status);
10018         if (status.errDataIfFailureAndReset()) {
10019             return;
10020         }
10021         DecimalFormat df(patternString, dfs, status);
10022         if (status.errDataIfFailureAndReset()) {
10023             return;
10024         }
10025         df.setLenient(FALSE);
10026         LocalPointer<CurrencyAmount> ca_strict(df.parseCurrency(inputString, ppos));
10027         if (ca_strict != nullptr) {
10028             parsedStrictValue = ca_strict->getNumber().getInt64();
10029         }
10030         assertEquals("Strict parse of " + inputString + " using " + patternString,
10031             parsedStrictValue, cas.expectedStrictParse);
10032 
10033         ppos.setIndex(0);
10034         df.setLenient(TRUE);
10035         LocalPointer<CurrencyAmount> ca_lenient(df.parseCurrency(inputString, ppos));
10036         Formattable parsedNumber_lenient = ca_lenient->getNumber();
10037         if (ca_lenient != nullptr) {
10038             parsedLenientValue = ca_lenient->getNumber().getInt64();
10039         }
10040         assertEquals("Lenient parse of " + inputString + " using " + patternString,
10041             parsedLenientValue, cas.expectedLenientParse);
10042     }
10043 }
10044 
Test20425_IntegerIncrement()10045 void NumberFormatTest::Test20425_IntegerIncrement() {
10046     IcuTestErrorCode status(*this, "Test20425_IntegerIncrement");
10047 
10048     DecimalFormat df("##00", status);
10049     df.setRoundingIncrement(1);
10050     UnicodeString actual;
10051     df.format(1235.5, actual, status);
10052     assertEquals("Should round to integer", u"1236", actual);
10053 }
10054 
Test20425_FractionWithIntegerIncrement()10055 void NumberFormatTest::Test20425_FractionWithIntegerIncrement() {
10056     IcuTestErrorCode status(*this, "Test20425_FractionWithIntegerIncrement");
10057 
10058     DecimalFormat df("0.0", status);
10059     df.setRoundingIncrement(1);
10060     UnicodeString actual;
10061     df.format(8.6, actual, status);
10062     assertEquals("Should have a fraction digit", u"9.0", actual);
10063 }
10064 
Test21232_ParseTimeout()10065 void NumberFormatTest::Test21232_ParseTimeout() {
10066     IcuTestErrorCode status(*this, "Test21232_ParseTimeout");
10067 
10068     DecimalFormat df(status);
10069     if (status.errDataIfFailureAndReset()) {
10070         return;
10071     }
10072 
10073     UnicodeString input = u"4444444444444444444444444444444444444444";
10074     if (quick) {
10075         for (int32_t i = 0; i < 5; i++) {
10076             input.append(input);
10077         }
10078         assertEquals("Somewhat long input of digits", 1280, input.length());
10079     } else {
10080         for (int32_t i = 0; i < 12; i++) {
10081             input.append(input);
10082         }
10083         assertEquals("Very long input of digits", 163840, input.length());
10084     }
10085     Formattable result;
10086     df.parse(input, result, status);
10087     // Should not hang
10088 }
10089 
Test10997_FormatCurrency()10090 void NumberFormatTest::Test10997_FormatCurrency() {
10091     IcuTestErrorCode status(*this, "Test10997_FormatCurrency");
10092 
10093     LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance(Locale::getUS(), status));
10094     if (status.errDataIfFailureAndReset()) {
10095         return;
10096     }
10097     fmt->setMinimumFractionDigits(4);
10098     fmt->setMaximumFractionDigits(4);
10099 
10100     FieldPosition fp;
10101 
10102     UnicodeString str;
10103     Formattable usdAmnt(new CurrencyAmount(123.45, u"USD", status));
10104     fmt->format(usdAmnt, str, fp, status);
10105     assertEquals("minFrac 4 should be respected in default currency", u"$123.4500", str);
10106 
10107     UnicodeString str2;
10108     Formattable eurAmnt(new CurrencyAmount(123.45, u"EUR", status));
10109     fmt->format(eurAmnt, str2, fp, status);
10110     assertEquals("minFrac 4 should be respected in different currency", u"€123.4500", str2);
10111 }
10112 
Test21556_CurrencyAsDecimal()10113 void NumberFormatTest::Test21556_CurrencyAsDecimal() {
10114     IcuTestErrorCode status(*this, "Test21556_CurrencyAsDecimal");
10115 
10116     {
10117         DecimalFormat df(u"a0¤00b", status);
10118         if (status.errDataIfFailureAndReset()) {
10119             return;
10120         }
10121         df.setCurrency(u"EUR", status);
10122         UnicodeString result;
10123         FieldPosition fp(UNUM_CURRENCY_FIELD);
10124         df.format(3.141, result, fp);
10125         assertEquals("Basic test: format", u"a3€14b", result);
10126         UnicodeString pattern;
10127         assertEquals("Basic test: toPattern", u"a0¤00b", df.toPattern(pattern));
10128         assertEquals("Basic test: field position begin", 2, fp.getBeginIndex());
10129         assertEquals("Basic test: field position end", 3, fp.getEndIndex());
10130     }
10131 
10132     {
10133         LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-GB", status));
10134         DecimalFormat* df = static_cast<DecimalFormat*>(nf.getAlias());
10135         df->applyPattern(u"a0¤00b", status);
10136         UnicodeString result;
10137         FieldPosition fp(UNUM_CURRENCY_FIELD);
10138         df->format(3.141, result, fp);
10139         assertEquals("Via applyPattern: format", u"a3£14b", result);
10140         UnicodeString pattern;
10141         assertEquals("Via applyPattern: toPattern", u"a0¤00b", df->toPattern(pattern));
10142         assertEquals("Via applyPattern: field position begin", 2, fp.getBeginIndex());
10143         assertEquals("Via applyPattern: field position end", 3, fp.getEndIndex());
10144     }
10145 }
10146 
10147 #endif /* #if !UCONFIG_NO_FORMATTING */
10148