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