1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8 /* Modification History:
9 * Date Name Description
10 * 07/15/99 helena Ported to HPUX 10/11 CC.
11 */
12
13 #include "unicode/utypes.h"
14
15 #if !UCONFIG_NO_FORMATTING
16
17 #include "numfmtst.h"
18 #include "unicode/currpinf.h"
19 #include "unicode/dcfmtsym.h"
20 #include "unicode/decimfmt.h"
21 #include "unicode/localpointer.h"
22 #include "unicode/ucurr.h"
23 #include "unicode/ustring.h"
24 #include "unicode/measfmt.h"
25 #include "unicode/curramt.h"
26 #include "unicode/strenum.h"
27 #include "textfile.h"
28 #include "tokiter.h"
29 #include "charstr.h"
30 #include "cstr.h"
31 #include "putilimp.h"
32 #include "winnmtst.h"
33 #include <cmath>
34 #include <float.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include "cmemory.h"
38 #include "cstring.h"
39 #include "unicode/numsys.h"
40 #include "fmtableimp.h"
41 #include "numberformattesttuple.h"
42 #include "unicode/msgfmt.h"
43 #include "number_decimalquantity.h"
44 #include "unicode/numberformatter.h"
45
46 #if (U_PLATFORM == U_PF_AIX) || (U_PLATFORM == U_PF_OS390)
47 // These should not be macros. If they are,
48 // replace them with std::isnan and std::isinf
49 #if defined(isnan)
50 #undef isnan
51 namespace std {
isnan(double x)52 bool isnan(double x) {
53 return _isnan(x);
54 }
55 }
56 #endif
57 #if defined(isinf)
58 #undef isinf
59 namespace std {
isinf(double x)60 bool isinf(double x) {
61 return _isinf(x);
62 }
63 }
64 #endif
65 #endif
66
67 using icu::number::impl::DecimalQuantity;
68 using namespace icu::number;
69
70 //#define NUMFMTST_CACHE_DEBUG 1
71 #include "stdio.h" /* for sprintf */
72 // #include "iostream" // for cout
73
74 //#define NUMFMTST_DEBUG 1
75
76 static const UChar EUR[] = {69,85,82,0}; // "EUR"
77 static const UChar ISO_CURRENCY_USD[] = {0x55, 0x53, 0x44, 0}; // "USD"
78
79
80 // *****************************************************************************
81 // class NumberFormatTest
82 // *****************************************************************************
83
84 #define CHECK(status,str) UPRV_BLOCK_MACRO_BEGIN { \
85 if (U_FAILURE(status)) { \
86 errcheckln(status, UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \
87 return; \
88 } \
89 } UPRV_BLOCK_MACRO_END
90 #define CHECK_DATA(status,str) UPRV_BLOCK_MACRO_BEGIN { \
91 if (U_FAILURE(status)) { \
92 dataerrln(UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \
93 return; \
94 } \
95 } UPRV_BLOCK_MACRO_END
96
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)97 void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
98 {
99 TESTCASE_AUTO_BEGIN;
100 TESTCASE_AUTO(TestCurrencySign);
101 TESTCASE_AUTO(TestCurrency);
102 TESTCASE_AUTO(TestParse);
103 TESTCASE_AUTO(TestRounding487);
104 TESTCASE_AUTO(TestQuotes);
105 TESTCASE_AUTO(TestExponential);
106 TESTCASE_AUTO(TestPatterns);
107 TESTCASE_AUTO(Test20186_SpacesAroundSemicolon);
108
109 // Upgrade to alphaWorks - liu 5/99
110 TESTCASE_AUTO(TestExponent);
111 TESTCASE_AUTO(TestScientific);
112 TESTCASE_AUTO(TestPad);
113 TESTCASE_AUTO(TestPatterns2);
114 TESTCASE_AUTO(TestSecondaryGrouping);
115 TESTCASE_AUTO(TestSurrogateSupport);
116 TESTCASE_AUTO(TestAPI);
117
118 TESTCASE_AUTO(TestCurrencyObject);
119 TESTCASE_AUTO(TestCurrencyPatterns);
120 //TESTCASE_AUTO(TestDigitList);
121 TESTCASE_AUTO(TestWhiteSpaceParsing);
122 TESTCASE_AUTO(TestComplexCurrency); // This test removed because CLDR no longer uses choice formats in currency symbols.
123 TESTCASE_AUTO(TestRegCurrency);
124 TESTCASE_AUTO(TestSymbolsWithBadLocale);
125 TESTCASE_AUTO(TestAdoptDecimalFormatSymbols);
126
127 TESTCASE_AUTO(TestScientific2);
128 TESTCASE_AUTO(TestScientificGrouping);
129 TESTCASE_AUTO(TestInt64);
130
131 TESTCASE_AUTO(TestPerMill);
132 TESTCASE_AUTO(TestIllegalPatterns);
133 TESTCASE_AUTO(TestCases);
134
135 TESTCASE_AUTO(TestCurrencyNames);
136 TESTCASE_AUTO(TestCurrencyVariants);
137 TESTCASE_AUTO(TestCurrencyAmount);
138 TESTCASE_AUTO(TestCurrencyUnit);
139 TESTCASE_AUTO(TestCoverage);
140 TESTCASE_AUTO(TestLocalizedPatternSymbolCoverage);
141 TESTCASE_AUTO(TestJB3832);
142 TESTCASE_AUTO(TestHost);
143 TESTCASE_AUTO(TestHostClone);
144 TESTCASE_AUTO(TestCurrencyFormat);
145 TESTCASE_AUTO(TestRounding);
146 TESTCASE_AUTO(TestNonpositiveMultiplier);
147 TESTCASE_AUTO(TestNumberingSystems);
148 TESTCASE_AUTO(TestSpaceParsing);
149 TESTCASE_AUTO(TestMultiCurrencySign);
150 TESTCASE_AUTO(TestCurrencyFormatForMixParsing);
151 TESTCASE_AUTO(TestMismatchedCurrencyFormatFail);
152 TESTCASE_AUTO(TestDecimalFormatCurrencyParse);
153 TESTCASE_AUTO(TestCurrencyIsoPluralFormat);
154 TESTCASE_AUTO(TestCurrencyParsing);
155 TESTCASE_AUTO(TestParseCurrencyInUCurr);
156 TESTCASE_AUTO(TestFormatAttributes);
157 TESTCASE_AUTO(TestFieldPositionIterator);
158 TESTCASE_AUTO(TestDecimal);
159 TESTCASE_AUTO(TestCurrencyFractionDigits);
160 TESTCASE_AUTO(TestExponentParse);
161 TESTCASE_AUTO(TestExplicitParents);
162 TESTCASE_AUTO(TestLenientParse);
163 TESTCASE_AUTO(TestAvailableNumberingSystems);
164 TESTCASE_AUTO(TestRoundingPattern);
165 TESTCASE_AUTO(Test9087);
166 TESTCASE_AUTO(TestFormatFastpaths);
167 TESTCASE_AUTO(TestFormattableSize);
168 TESTCASE_AUTO(TestUFormattable);
169 TESTCASE_AUTO(TestSignificantDigits);
170 TESTCASE_AUTO(TestShowZero);
171 TESTCASE_AUTO(TestCompatibleCurrencies);
172 TESTCASE_AUTO(TestBug9936);
173 TESTCASE_AUTO(TestParseNegativeWithFaLocale);
174 TESTCASE_AUTO(TestParseNegativeWithAlternateMinusSign);
175 TESTCASE_AUTO(TestCustomCurrencySignAndSeparator);
176 TESTCASE_AUTO(TestParseSignsAndMarks);
177 TESTCASE_AUTO(Test10419RoundingWith0FractionDigits);
178 TESTCASE_AUTO(Test10468ApplyPattern);
179 TESTCASE_AUTO(TestRoundingScientific10542);
180 TESTCASE_AUTO(TestZeroScientific10547);
181 TESTCASE_AUTO(TestAccountingCurrency);
182 TESTCASE_AUTO(TestCurrencyFormatForMissingLocale);
183 TESTCASE_AUTO(TestEquality);
184 TESTCASE_AUTO(TestCurrencyUsage);
185 TESTCASE_AUTO(TestDoubleLimit11439);
186 TESTCASE_AUTO(TestGetAffixes);
187 TESTCASE_AUTO(TestToPatternScientific11648);
188 TESTCASE_AUTO(TestBenchmark);
189 TESTCASE_AUTO(TestCtorApplyPatternDifference);
190 TESTCASE_AUTO(TestFractionalDigitsForCurrency);
191 TESTCASE_AUTO(TestFormatCurrencyPlural);
192 TESTCASE_AUTO(Test11868);
193 TESTCASE_AUTO(Test11739_ParseLongCurrency);
194 TESTCASE_AUTO(Test13035_MultiCodePointPaddingInPattern);
195 TESTCASE_AUTO(Test13737_ParseScientificStrict);
196 TESTCASE_AUTO(Test10727_RoundingZero);
197 TESTCASE_AUTO(Test11376_getAndSetPositivePrefix);
198 TESTCASE_AUTO(Test11475_signRecognition);
199 TESTCASE_AUTO(Test11640_getAffixes);
200 TESTCASE_AUTO(Test11649_toPatternWithMultiCurrency);
201 TESTCASE_AUTO(Test13327_numberingSystemBufferOverflow);
202 TESTCASE_AUTO(Test13391_chakmaParsing);
203 TESTCASE_AUTO(Test11735_ExceptionIssue);
204 TESTCASE_AUTO(Test11035_FormatCurrencyAmount);
205 TESTCASE_AUTO(Test11318_DoubleConversion);
206 TESTCASE_AUTO(TestParsePercentRegression);
207 TESTCASE_AUTO(TestMultiplierWithScale);
208 TESTCASE_AUTO(TestFastFormatInt32);
209 TESTCASE_AUTO(Test11646_Equality);
210 TESTCASE_AUTO(TestParseNaN);
211 TESTCASE_AUTO(TestFormatFailIfMoreThanMaxDigits);
212 TESTCASE_AUTO(TestParseCaseSensitive);
213 TESTCASE_AUTO(TestParseNoExponent);
214 TESTCASE_AUTO(TestSignAlwaysShown);
215 TESTCASE_AUTO(TestMinimumGroupingDigits);
216 TESTCASE_AUTO(Test11897_LocalizedPatternSeparator);
217 TESTCASE_AUTO(Test13055_PercentageRounding);
218 TESTCASE_AUTO(Test11839);
219 TESTCASE_AUTO(Test10354);
220 TESTCASE_AUTO(Test11645_ApplyPatternEquality);
221 TESTCASE_AUTO(Test12567);
222 TESTCASE_AUTO(Test11626_CustomizeCurrencyPluralInfo);
223 TESTCASE_AUTO(Test20073_StrictPercentParseErrorIndex);
224 TESTCASE_AUTO(Test13056_GroupingSize);
225 TESTCASE_AUTO(Test11025_CurrencyPadding);
226 TESTCASE_AUTO(Test11648_ExpDecFormatMalPattern);
227 TESTCASE_AUTO(Test11649_DecFmtCurrencies);
228 TESTCASE_AUTO(Test13148_ParseGroupingSeparators);
229 TESTCASE_AUTO(Test12753_PatternDecimalPoint);
230 TESTCASE_AUTO(Test11647_PatternCurrencySymbols);
231 TESTCASE_AUTO(Test11913_BigDecimal);
232 TESTCASE_AUTO(Test11020_RoundingInScientificNotation);
233 TESTCASE_AUTO(Test11640_TripleCurrencySymbol);
234 TESTCASE_AUTO(Test13763_FieldPositionIteratorOffset);
235 TESTCASE_AUTO(Test13777_ParseLongNameNonCurrencyMode);
236 TESTCASE_AUTO(Test13804_EmptyStringsWhenParsing);
237 TESTCASE_AUTO(Test20037_ScientificIntegerOverflow);
238 TESTCASE_AUTO(Test13840_ParseLongStringCrash);
239 TESTCASE_AUTO(Test13850_EmptyStringCurrency);
240 TESTCASE_AUTO(Test20348_CurrencyPrefixOverride);
241 TESTCASE_AUTO(Test20956_MonetarySymbolGetters);
242 TESTCASE_AUTO(Test20358_GroupingInPattern);
243 TESTCASE_AUTO(Test13731_DefaultCurrency);
244 TESTCASE_AUTO(Test20499_CurrencyVisibleDigitsPlural);
245 TESTCASE_AUTO(Test13735_GroupingSizeGetter);
246 TESTCASE_AUTO(Test13734_StrictFlexibleWhitespace);
247 TESTCASE_AUTO(Test20961_CurrencyPluralPattern);
248 TESTCASE_AUTO(Test21134_ToNumberFormatter);
249 TESTCASE_AUTO(Test13733_StrictAndLenient);
250 TESTCASE_AUTO(Test21232_ParseTimeout);
251 TESTCASE_AUTO_END;
252 }
253
254 // -------------------------------------
255
256 // Test API (increase code coverage)
257 void
TestAPI(void)258 NumberFormatTest::TestAPI(void)
259 {
260 logln("Test API");
261 UErrorCode status = U_ZERO_ERROR;
262 NumberFormat *test = NumberFormat::createInstance("root", status);
263 if(U_FAILURE(status)) {
264 dataerrln("unable to create format object - %s", u_errorName(status));
265 }
266 if(test != NULL) {
267 test->setMinimumIntegerDigits(10);
268 test->setMaximumIntegerDigits(1);
269
270 test->setMinimumFractionDigits(10);
271 test->setMaximumFractionDigits(1);
272
273 UnicodeString result;
274 FieldPosition pos;
275 Formattable bla("Paja Patak"); // Donald Duck for non Serbian speakers
276 test->format(bla, result, pos, status);
277 if(U_SUCCESS(status)) {
278 errln("Yuck... Formatted a duck... As a number!");
279 } else {
280 status = U_ZERO_ERROR;
281 }
282
283 result.remove();
284 int64_t ll = 12;
285 test->format(ll, result);
286 assertEquals("format int64_t error", u"2.0", result);
287
288 test->setMinimumIntegerDigits(4);
289 test->setMinimumFractionDigits(4);
290
291 result.remove();
292 test->format(ll, result);
293 assertEquals("format int64_t error", u"0,012.0000", result);
294
295 ParsePosition ppos;
296 LocalPointer<CurrencyAmount> currAmt(test->parseCurrency("",ppos));
297 // old test for (U_FAILURE(status)) was bogus here, method does not set status!
298 if (ppos.getIndex()) {
299 errln("Parsed empty string as currency");
300 }
301
302 delete test;
303 }
304 }
305
306 class StubNumberFormat :public NumberFormat{
307 public:
StubNumberFormat()308 StubNumberFormat(){}
format(double,UnicodeString & appendTo,FieldPosition &) const309 virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const {
310 return appendTo;
311 }
format(int32_t,UnicodeString & appendTo,FieldPosition &) const312 virtual UnicodeString& format(int32_t ,UnicodeString& appendTo,FieldPosition& ) const {
313 return appendTo.append((UChar)0x0033);
314 }
format(int64_t number,UnicodeString & appendTo,FieldPosition & pos) const315 virtual UnicodeString& format(int64_t number,UnicodeString& appendTo,FieldPosition& pos) const {
316 return NumberFormat::format(number, appendTo, pos);
317 }
format(const Formattable &,UnicodeString & appendTo,FieldPosition &,UErrorCode &) const318 virtual UnicodeString& format(const Formattable& , UnicodeString& appendTo, FieldPosition& , UErrorCode& ) const {
319 return appendTo;
320 }
parse(const UnicodeString &,Formattable &,ParsePosition &) const321 virtual void parse(const UnicodeString& ,
322 Formattable& ,
323 ParsePosition& ) const {}
parse(const UnicodeString &,Formattable &,UErrorCode &) const324 virtual void parse( const UnicodeString& ,
325 Formattable& ,
326 UErrorCode& ) const {}
getDynamicClassID(void) const327 virtual UClassID getDynamicClassID(void) const {
328 static char classID = 0;
329 return (UClassID)&classID;
330 }
clone() const331 virtual StubNumberFormat* clone() const {return NULL;}
332 };
333
334 void
TestCoverage(void)335 NumberFormatTest::TestCoverage(void){
336 StubNumberFormat stub;
337 UnicodeString agent("agent");
338 FieldPosition pos;
339 int64_t num = 4;
340 if (stub.format(num, agent, pos) != UnicodeString("agent3")){
341 errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)");
342 }
343 }
344
TestLocalizedPatternSymbolCoverage()345 void NumberFormatTest::TestLocalizedPatternSymbolCoverage() {
346 IcuTestErrorCode errorCode(*this, "TestLocalizedPatternSymbolCoverage");
347 // Ticket #12961: DecimalFormat::toLocalizedPattern() is not working as designed.
348 DecimalFormatSymbols dfs(errorCode);
349 dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u'⁖');
350 dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'⁘');
351 dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u'⁙');
352 dfs.setSymbol(DecimalFormatSymbols::kDigitSymbol, u'▰');
353 dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u'໐');
354 dfs.setSymbol(DecimalFormatSymbols::kSignificantDigitSymbol, u'⁕');
355 dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u'†');
356 dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u'‡');
357 dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u'⁜');
358 dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u'‱');
359 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"⁑⁑"); // tests multi-char sequence
360 dfs.setSymbol(DecimalFormatSymbols::kPadEscapeSymbol, u'⁂');
361
362 {
363 UnicodeString standardPattern(u"#,##0.05+%;#,##0.05-%");
364 UnicodeString localizedPattern(u"▰⁖▰▰໐⁘໐໕†⁜⁙▰⁖▰▰໐⁘໐໕‡⁜");
365
366 DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
367 df1.applyPattern(standardPattern, errorCode);
368 DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
369 df2.applyLocalizedPattern(localizedPattern, errorCode);
370 assertTrue("DecimalFormat instances should be equal", df1 == df2);
371 UnicodeString p2;
372 assertEquals("toPattern should match on localizedPattern instance",
373 standardPattern, df2.toPattern(p2));
374 UnicodeString lp1;
375 assertEquals("toLocalizedPattern should match on standardPattern instance",
376 localizedPattern, df1.toLocalizedPattern(lp1));
377 }
378
379 {
380 UnicodeString standardPattern(u"* @@@E0‰");
381 UnicodeString localizedPattern(u"⁂ ⁕⁕⁕⁑⁑໐‱");
382
383 DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
384 df1.applyPattern(standardPattern, errorCode);
385 DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
386 df2.applyLocalizedPattern(localizedPattern, errorCode);
387 assertTrue("DecimalFormat instances should be equal", df1 == df2);
388 UnicodeString p2;
389 assertEquals("toPattern should match on localizedPattern instance",
390 standardPattern, df2.toPattern(p2));
391 UnicodeString lp1;
392 assertEquals("toLocalizedPattern should match on standardPattern instance",
393 localizedPattern, df1.toLocalizedPattern(lp1));
394 }
395 }
396
397 // Test various patterns
398 void
TestPatterns(void)399 NumberFormatTest::TestPatterns(void)
400 {
401 UErrorCode status = U_ZERO_ERROR;
402 DecimalFormatSymbols sym(Locale::getUS(), status);
403 if (U_FAILURE(status)) { errcheckln(status, "FAIL: Could not construct DecimalFormatSymbols - %s", u_errorName(status)); return; }
404
405 const char* pat[] = { "#.#", "#.", ".#", "#" };
406 int32_t pat_length = UPRV_LENGTHOF(pat);
407 const char* newpat[] = { "0.#", "0.", "#.0", "0" };
408 const char* num[] = { "0", "0.", ".0", "0" };
409 for (int32_t i=0; i<pat_length; ++i)
410 {
411 status = U_ZERO_ERROR;
412 DecimalFormat fmt(pat[i], sym, status);
413 if (U_FAILURE(status)) { errln((UnicodeString)"FAIL: DecimalFormat constructor failed for " + pat[i]); continue; }
414 UnicodeString newp; fmt.toPattern(newp);
415 if (!(newp == newpat[i]))
416 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
417 "; " + newp + " seen instead");
418
419 UnicodeString s; (*(NumberFormat*)&fmt).format((int32_t)0, s);
420 if (!(s == num[i]))
421 {
422 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
423 "; " + s + " seen instead");
424 logln((UnicodeString)"Min integer digits = " + fmt.getMinimumIntegerDigits());
425 }
426 }
427 }
428
Test20186_SpacesAroundSemicolon()429 void NumberFormatTest::Test20186_SpacesAroundSemicolon() {
430 IcuTestErrorCode status(*this, "Test20186_SpacesAroundSemicolon");
431 DecimalFormat df(u"0.00 ; -0.00", {"en-us", status}, status);
432 expect2(df, 1, u"1.00 ");
433 expect2(df, -1, u" -1.00");
434
435 df = DecimalFormat(u"0.00;", {"en-us", status}, status);
436 expect2(df, 1, u"1.00");
437 expect2(df, -1, u"-1.00");
438
439 df = DecimalFormat(u"0.00;0.00", {"en-us", status}, status);
440 expect2(df, 1, u"1.00");
441 expect(df, -1, u"1.00"); // parses as 1, not -1
442
443 df = DecimalFormat(u" 0.00 ; -0.00 ", {"en-us", status}, status);
444 expect2(df, 1, u" 1.00 ");
445 expect2(df, -1, u" -1.00 ");
446 }
447
448 /*
449 icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
450 icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
451 icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
452 */
453 /*
454 void
455 NumberFormatTest::TestDigitList(void)
456 {
457 // API coverage for DigitList
458 DigitList list1;
459 list1.append('1');
460 list1.fDecimalAt = 1;
461 DigitList list2;
462 list2.set((int32_t)1);
463 if (list1 != list2) {
464 errln("digitlist append, operator!= or set failed ");
465 }
466 if (!(list1 == list2)) {
467 errln("digitlist append, operator== or set failed ");
468 }
469 }
470 */
471
472 // -------------------------------------
473
474 // Test exponential pattern
475 void
TestExponential(void)476 NumberFormatTest::TestExponential(void)
477 {
478 UErrorCode status = U_ZERO_ERROR;
479 DecimalFormatSymbols sym(Locale::getUS(), status);
480 if (U_FAILURE(status)) { errcheckln(status, "FAIL: Bad status returned by DecimalFormatSymbols ct - %s", u_errorName(status)); return; }
481 const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
482 int32_t pat_length = UPRV_LENGTHOF(pat);
483
484 // The following #if statements allow this test to be built and run on
485 // platforms that do not have standard IEEE numerics. For example,
486 // S/390 doubles have an exponent range of -78 to +75. For the
487 // following #if statements to work, float.h must define
488 // DBL_MAX_10_EXP to be a compile-time constant.
489
490 // This section may be expanded as needed.
491
492 #if DBL_MAX_10_EXP > 300
493 double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
494 int32_t val_length = UPRV_LENGTHOF(val);
495 const char* valFormat[] =
496 {
497 // 0.####E0
498 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
499 // 00.000E00
500 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
501 // ##0.######E000
502 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
503 // 0.###E0;[0.###E0]
504 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
505 };
506 double valParse[] =
507 {
508 0.01234, 123460000, 1.23E300, -3.1416E-271,
509 0.01234, 123460000, 1.23E300, -3.1416E-271,
510 0.01234, 123456800, 1.23E300, -3.141593E-271,
511 0.01234, 123500000, 1.23E300, -3.142E-271,
512 };
513 #elif DBL_MAX_10_EXP > 70
514 double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
515 int32_t val_length = UPRV_LENGTHOF(val);
516 char* valFormat[] =
517 {
518 // 0.####E0
519 "1.234E-2", "1.2346E8", "1.23E70", "-3.1416E-71",
520 // 00.000E00
521 "12.340E-03", "12.346E07", "12.300E69", "-31.416E-72",
522 // ##0.######E000
523 "12.34E-003", "123.4568E006", "12.3E069", "-31.41593E-072",
524 // 0.###E0;[0.###E0]
525 "1.234E-2", "1.235E8", "1.23E70", "[3.142E-71]"
526 };
527 double valParse[] =
528 {
529 0.01234, 123460000, 1.23E70, -3.1416E-71,
530 0.01234, 123460000, 1.23E70, -3.1416E-71,
531 0.01234, 123456800, 1.23E70, -3.141593E-71,
532 0.01234, 123500000, 1.23E70, -3.142E-71,
533 };
534 #else
535 // Don't test double conversion
536 double* val = 0;
537 int32_t val_length = 0;
538 char** valFormat = 0;
539 double* valParse = 0;
540 logln("Warning: Skipping double conversion tests");
541 #endif
542
543 int32_t lval[] = { 0, -1, 1, 123456789 };
544 int32_t lval_length = UPRV_LENGTHOF(lval);
545 const char* lvalFormat[] =
546 {
547 // 0.####E0
548 "0E0", "-1E0", "1E0", "1.2346E8",
549 // 00.000E00
550 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
551 // ##0.######E000
552 "0E000", "-1E000", "1E000", "123.4568E006",
553 // 0.###E0;[0.###E0]
554 "0E0", "[1E0]", "1E0", "1.235E8"
555 };
556 int32_t lvalParse[] =
557 {
558 0, -1, 1, 123460000,
559 0, -1, 1, 123460000,
560 0, -1, 1, 123456800,
561 0, -1, 1, 123500000,
562 };
563 int32_t ival = 0, ilval = 0;
564 for (int32_t p=0; p<pat_length; ++p)
565 {
566 DecimalFormat fmt(pat[p], sym, status);
567 if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormat ct"); continue; }
568 UnicodeString pattern;
569 logln((UnicodeString)"Pattern \"" + pat[p] + "\" -toPattern-> \"" +
570 fmt.toPattern(pattern) + "\"");
571 int32_t v;
572 for (v=0; v<val_length; ++v)
573 {
574 UnicodeString s; (*(NumberFormat*)&fmt).format(val[v], s);
575 logln((UnicodeString)" " + val[v] + " -format-> " + s);
576 if (s != valFormat[v+ival])
577 errln((UnicodeString)"FAIL: Expected " + valFormat[v+ival]);
578
579 ParsePosition pos(0);
580 Formattable af;
581 fmt.parse(s, af, pos);
582 double a;
583 UBool useEpsilon = FALSE;
584 if (af.getType() == Formattable::kLong)
585 a = af.getLong();
586 else if (af.getType() == Formattable::kDouble) {
587 a = af.getDouble();
588 #if U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400
589 // S/390 will show a failure like this:
590 //| -3.141592652999999e-271 -format-> -3.1416E-271
591 //| -parse-> -3.1416e-271
592 //| FAIL: Expected -3.141599999999999e-271
593 // To compensate, we use an epsilon-based equality
594 // test on S/390 only. We don't want to do this in
595 // general because it's less exacting.
596 useEpsilon = TRUE;
597 #endif
598 }
599 else {
600 errln(UnicodeString("FAIL: Non-numeric Formattable returned: ") + pattern + " " + s);
601 continue;
602 }
603 if (pos.getIndex() == s.length())
604 {
605 logln((UnicodeString)" -parse-> " + a);
606 // Use epsilon comparison as necessary
607 if ((useEpsilon &&
608 (uprv_fabs(a - valParse[v+ival]) / a > (2*DBL_EPSILON))) ||
609 (!useEpsilon && a != valParse[v+ival]))
610 {
611 errln((UnicodeString)"FAIL: Expected " + valParse[v+ival] + " but got " + a
612 + " on input " + s);
613 }
614 }
615 else {
616 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
617 errln((UnicodeString)" should be (" + s.length() + " chars) -> " + valParse[v+ival]);
618 }
619 }
620 for (v=0; v<lval_length; ++v)
621 {
622 UnicodeString s;
623 (*(NumberFormat*)&fmt).format(lval[v], s);
624 logln((UnicodeString)" " + lval[v] + "L -format-> " + s);
625 if (s != lvalFormat[v+ilval])
626 errln((UnicodeString)"ERROR: Expected " + lvalFormat[v+ilval] + " Got: " + s);
627
628 ParsePosition pos(0);
629 Formattable af;
630 fmt.parse(s, af, pos);
631 if (af.getType() == Formattable::kLong ||
632 af.getType() == Formattable::kInt64) {
633 UErrorCode status = U_ZERO_ERROR;
634 int32_t a = af.getLong(status);
635 if (pos.getIndex() == s.length())
636 {
637 logln((UnicodeString)" -parse-> " + a);
638 if (a != lvalParse[v+ilval])
639 errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval] + " but got " + a);
640 }
641 else
642 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
643 }
644 else
645 errln((UnicodeString)"FAIL: Non-long Formattable returned for " + s
646 + " Double: " + af.getDouble()
647 + ", Long: " + af.getLong());
648 }
649 ival += val_length;
650 ilval += lval_length;
651 }
652 }
653
654 void
TestScientific2()655 NumberFormatTest::TestScientific2() {
656 // jb 2552
657 UErrorCode status = U_ZERO_ERROR;
658 DecimalFormat* fmt = (DecimalFormat*)NumberFormat::createCurrencyInstance("en_US", status);
659 if (U_SUCCESS(status)) {
660 double num = 12.34;
661 expect(*fmt, num, "$12.34");
662 fmt->setScientificNotation(TRUE);
663 expect(*fmt, num, "$1.23E1");
664 fmt->setScientificNotation(FALSE);
665 expect(*fmt, num, "$12.34");
666 }
667 delete fmt;
668 }
669
670 void
TestScientificGrouping()671 NumberFormatTest::TestScientificGrouping() {
672 // jb 2552
673 UErrorCode status = U_ZERO_ERROR;
674 DecimalFormat fmt("##0.00E0",status);
675 if (assertSuccess("", status, true, __FILE__, __LINE__)) {
676 expect(fmt, .01234, "12.3E-3");
677 expect(fmt, .1234, "123E-3");
678 expect(fmt, 1.234, "1.23E0");
679 expect(fmt, 12.34, "12.3E0");
680 expect(fmt, 123.4, "123E0");
681 expect(fmt, 1234., "1.23E3");
682 }
683 }
684
685 /*static void setFromString(DigitList& dl, const char* str) {
686 char c;
687 UBool decimalSet = FALSE;
688 dl.clear();
689 while ((c = *str++)) {
690 if (c == '-') {
691 dl.fIsPositive = FALSE;
692 } else if (c == '+') {
693 dl.fIsPositive = TRUE;
694 } else if (c == '.') {
695 dl.fDecimalAt = dl.fCount;
696 decimalSet = TRUE;
697 } else {
698 dl.append(c);
699 }
700 }
701 if (!decimalSet) {
702 dl.fDecimalAt = dl.fCount;
703 }
704 }*/
705
706 void
TestInt64()707 NumberFormatTest::TestInt64() {
708 UErrorCode status = U_ZERO_ERROR;
709 DecimalFormat fmt("#.#E0",status);
710 if (U_FAILURE(status)) {
711 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
712 return;
713 }
714 fmt.setMaximumFractionDigits(20);
715 if (U_SUCCESS(status)) {
716 expect(fmt, (Formattable)(int64_t)0, "0E0");
717 expect(fmt, (Formattable)(int64_t)-1, "-1E0");
718 expect(fmt, (Formattable)(int64_t)1, "1E0");
719 expect(fmt, (Formattable)(int64_t)2147483647, "2.147483647E9");
720 expect(fmt, (Formattable)((int64_t)-2147483647-1), "-2.147483648E9");
721 expect(fmt, (Formattable)(int64_t)U_INT64_MAX, "9.223372036854775807E18");
722 expect(fmt, (Formattable)(int64_t)U_INT64_MIN, "-9.223372036854775808E18");
723 }
724
725 // also test digitlist
726 /* int64_t int64max = U_INT64_MAX;
727 int64_t int64min = U_INT64_MIN;
728 const char* int64maxstr = "9223372036854775807";
729 const char* int64minstr = "-9223372036854775808";
730 UnicodeString fail("fail: ");
731
732 // test max int64 value
733 DigitList dl;
734 setFromString(dl, int64maxstr);
735 {
736 if (!dl.fitsIntoInt64(FALSE)) {
737 errln(fail + int64maxstr + " didn't fit");
738 }
739 int64_t int64Value = dl.getInt64();
740 if (int64Value != int64max) {
741 errln(fail + int64maxstr);
742 }
743 dl.set(int64Value);
744 int64Value = dl.getInt64();
745 if (int64Value != int64max) {
746 errln(fail + int64maxstr);
747 }
748 }
749 // test negative of max int64 value (1 shy of min int64 value)
750 dl.fIsPositive = FALSE;
751 {
752 if (!dl.fitsIntoInt64(FALSE)) {
753 errln(fail + "-" + int64maxstr + " didn't fit");
754 }
755 int64_t int64Value = dl.getInt64();
756 if (int64Value != -int64max) {
757 errln(fail + "-" + int64maxstr);
758 }
759 dl.set(int64Value);
760 int64Value = dl.getInt64();
761 if (int64Value != -int64max) {
762 errln(fail + "-" + int64maxstr);
763 }
764 }
765 // test min int64 value
766 setFromString(dl, int64minstr);
767 {
768 if (!dl.fitsIntoInt64(FALSE)) {
769 errln(fail + "-" + int64minstr + " didn't fit");
770 }
771 int64_t int64Value = dl.getInt64();
772 if (int64Value != int64min) {
773 errln(fail + int64minstr);
774 }
775 dl.set(int64Value);
776 int64Value = dl.getInt64();
777 if (int64Value != int64min) {
778 errln(fail + int64minstr);
779 }
780 }
781 // test negative of min int 64 value (1 more than max int64 value)
782 dl.fIsPositive = TRUE; // won't fit
783 {
784 if (dl.fitsIntoInt64(FALSE)) {
785 errln(fail + "-(" + int64minstr + ") didn't fit");
786 }
787 }*/
788 }
789
790 // -------------------------------------
791
792 // Test the handling of quotes
793 void
TestQuotes(void)794 NumberFormatTest::TestQuotes(void)
795 {
796 UErrorCode status = U_ZERO_ERROR;
797 UnicodeString *pat;
798 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), status);
799 if (U_FAILURE(status)) {
800 errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
801 delete sym;
802 return;
803 }
804 pat = new UnicodeString("a'fo''o'b#");
805 DecimalFormat *fmt = new DecimalFormat(*pat, *sym, status);
806 UnicodeString s;
807 ((NumberFormat*)fmt)->format((int32_t)123, s);
808 logln((UnicodeString)"Pattern \"" + *pat + "\"");
809 logln((UnicodeString)" Format 123 -> " + escape(s));
810 if (!(s=="afo'ob123"))
811 errln((UnicodeString)"FAIL: Expected afo'ob123");
812
813 s.truncate(0);
814 delete fmt;
815 delete pat;
816
817 pat = new UnicodeString("a''b#");
818 fmt = new DecimalFormat(*pat, *sym, status);
819 ((NumberFormat*)fmt)->format((int32_t)123, s);
820 logln((UnicodeString)"Pattern \"" + *pat + "\"");
821 logln((UnicodeString)" Format 123 -> " + escape(s));
822 if (!(s=="a'b123"))
823 errln((UnicodeString)"FAIL: Expected a'b123");
824 delete fmt;
825 delete pat;
826 delete sym;
827 }
828
829 /**
830 * Test the handling of the currency symbol in patterns.
831 */
832 void
TestCurrencySign(void)833 NumberFormatTest::TestCurrencySign(void)
834 {
835 UErrorCode status = U_ZERO_ERROR;
836 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale::getUS(), status);
837 UnicodeString pat;
838 UChar currency = 0x00A4;
839 if (U_FAILURE(status)) {
840 errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
841 delete sym;
842 return;
843 }
844 // "\xA4#,##0.00;-\xA4#,##0.00"
845 pat.append(currency).append("#,##0.00;-").
846 append(currency).append("#,##0.00");
847 DecimalFormat *fmt = new DecimalFormat(pat, *sym, status);
848 UnicodeString s; ((NumberFormat*)fmt)->format(1234.56, s);
849 pat.truncate(0);
850 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
851 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
852 if (s != "$1,234.56") dataerrln((UnicodeString)"FAIL: Expected $1,234.56");
853 s.truncate(0);
854 ((NumberFormat*)fmt)->format(- 1234.56, s);
855 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
856 if (s != "-$1,234.56") dataerrln((UnicodeString)"FAIL: Expected -$1,234.56");
857 delete fmt;
858 pat.truncate(0);
859 // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
860 pat.append(currency).append(currency).
861 append(" #,##0.00;").
862 append(currency).append(currency).
863 append(" -#,##0.00");
864 fmt = new DecimalFormat(pat, *sym, status);
865 s.truncate(0);
866 ((NumberFormat*)fmt)->format(1234.56, s);
867 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
868 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
869 if (s != "USD 1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD 1,234.56");
870 s.truncate(0);
871 ((NumberFormat*)fmt)->format(-1234.56, s);
872 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
873 if (s != "USD -1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD -1,234.56");
874 delete fmt;
875 delete sym;
876 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + u_errorName(status));
877 }
878
879 // -------------------------------------
880
toHexString(int32_t i)881 static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
882
883 UnicodeString&
escape(UnicodeString & s)884 NumberFormatTest::escape(UnicodeString& s)
885 {
886 UnicodeString buf;
887 for (int32_t i=0; i<s.length(); ++i)
888 {
889 UChar c = s[(int32_t)i];
890 if (c <= (UChar)0x7F) buf += c;
891 else {
892 buf += (UChar)0x5c; buf += (UChar)0x55;
893 buf += toHexString((c & 0xF000) >> 12);
894 buf += toHexString((c & 0x0F00) >> 8);
895 buf += toHexString((c & 0x00F0) >> 4);
896 buf += toHexString(c & 0x000F);
897 }
898 }
899 return (s = buf);
900 }
901
902
903 // -------------------------------------
904 static const char* testCases[][2]= {
905 /* locale ID */ /* expected */
906 {"ca_ES@currency=ESP", "\\u20A7\\u00A01.150" },
907 {"de_LU@currency=LUF", "1,150\\u00A0F" },
908 {"el_GR@currency=GRD", "1.150,50\\u00A0\\u0394\\u03C1\\u03C7" },
909 {"en_BE@currency=BEF", "1.150,50\\u00A0BEF" },
910 {"es_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
911 {"eu_ES@currency=ESP", "\\u20A7\\u00A01.150" },
912 {"gl_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
913 {"it_IT@currency=ITL", "ITL\\u00A01.150" },
914 {"pt_PT@currency=PTE", "1,150$50\\u00A0\\u200B"}, // per cldrbug 7670
915 {"en_US@currency=JPY", "\\u00A51,150"},
916 {"en_US@currency=jpy", "\\u00A51,150"},
917 {"en-US-u-cu-jpy", "\\u00A51,150"}
918 };
919 /**
920 * Test localized currency patterns.
921 */
922 void
TestCurrency(void)923 NumberFormatTest::TestCurrency(void)
924 {
925 UErrorCode status = U_ZERO_ERROR;
926 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
927 if (U_FAILURE(status)) {
928 dataerrln("Error calling NumberFormat::createCurrencyInstance()");
929 return;
930 }
931
932 UnicodeString s; currencyFmt->format(1.50, s);
933 logln((UnicodeString)"Un pauvre ici a..........." + s);
934 if (!(s==CharsToUnicodeString("1,50\\u00A0$\\u00A0CA")))
935 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$<nbsp>CA but got " + s);
936 delete currencyFmt;
937 s.truncate(0);
938 char loc[256]={0};
939 int len = uloc_canonicalize("de_DE@currency=DEM", loc, 256, &status);
940 (void)len; // Suppress unused variable warning.
941 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
942 currencyFmt->format(1.50, s);
943 logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
944 if (!(s==CharsToUnicodeString("1,50\\u00A0DM")))
945 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM but got " + s);
946 delete currencyFmt;
947 s.truncate(0);
948 len = uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status);
949 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
950 currencyFmt->format(1.50, s);
951 logln((UnicodeString)"Un pauvre en France a....." + s);
952 if (!(s==CharsToUnicodeString("1,50\\u00A0F")))
953 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>F");
954 delete currencyFmt;
955 if (U_FAILURE(status))
956 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
957
958 for(int i=0; i < UPRV_LENGTHOF(testCases); i++){
959 status = U_ZERO_ERROR;
960 const char *localeID = testCases[i][0];
961 UnicodeString expected(testCases[i][1], -1, US_INV);
962 expected = expected.unescape();
963 s.truncate(0);
964 char loc[256]={0};
965 uloc_canonicalize(localeID, loc, 256, &status);
966 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
967 if(U_FAILURE(status)){
968 errln("Could not create currency formatter for locale %s",localeID);
969 continue;
970 }
971 currencyFmt->format(1150.50, s);
972 if(s!=expected){
973 errln(UnicodeString("FAIL: Expected: ")+expected
974 + UnicodeString(" Got: ") + s
975 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
976 }
977 if (U_FAILURE(status)){
978 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
979 }
980 delete currencyFmt;
981 }
982 }
983
984 // -------------------------------------
985
986 /**
987 * Test the Currency object handling, new as of ICU 2.2.
988 */
TestCurrencyObject()989 void NumberFormatTest::TestCurrencyObject() {
990 UErrorCode ec = U_ZERO_ERROR;
991 NumberFormat* fmt =
992 NumberFormat::createCurrencyInstance(Locale::getUS(), ec);
993
994 if (U_FAILURE(ec)) {
995 dataerrln("FAIL: getCurrencyInstance(US) - %s", u_errorName(ec));
996 delete fmt;
997 return;
998 }
999
1000 Locale null("", "", "");
1001
1002 expectCurrency(*fmt, null, 1234.56, "$1,234.56");
1003
1004 expectCurrency(*fmt, Locale::getFrance(),
1005 1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro
1006
1007 expectCurrency(*fmt, Locale::getJapan(),
1008 1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
1009
1010 expectCurrency(*fmt, Locale("fr", "CH", ""),
1011 1234.56, "CHF 1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
1012
1013 expectCurrency(*fmt, Locale::getUS(),
1014 1234.56, "$1,234.56");
1015
1016 delete fmt;
1017 fmt = NumberFormat::createCurrencyInstance(Locale::getFrance(), ec);
1018
1019 if (U_FAILURE(ec)) {
1020 errln("FAIL: getCurrencyInstance(FRANCE)");
1021 delete fmt;
1022 return;
1023 }
1024
1025 expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC"));
1026
1027 expectCurrency(*fmt, Locale::getJapan(),
1028 1234.56, CharsToUnicodeString("1\\u202F235 JPY")); // Yen
1029
1030 expectCurrency(*fmt, Locale("fr", "CH", ""),
1031 1234.56, CharsToUnicodeString("1\\u202F234,56 CHF")); // no more 0.05 rounding here, see cldrbug 5548
1032
1033 expectCurrency(*fmt, Locale::getUS(),
1034 1234.56, CharsToUnicodeString("1\\u202F234,56 $US"));
1035
1036 expectCurrency(*fmt, Locale::getFrance(),
1037 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC")); // Euro
1038
1039 delete fmt;
1040 }
1041
1042 // -------------------------------------
1043
1044 /**
1045 * Do rudimentary testing of parsing.
1046 */
1047 void
TestParse(void)1048 NumberFormatTest::TestParse(void)
1049 {
1050 UErrorCode status = U_ZERO_ERROR;
1051 UnicodeString arg("0");
1052 DecimalFormat* format = new DecimalFormat("00", status);
1053 //try {
1054 Formattable n; format->parse(arg, n, status);
1055 logln((UnicodeString)"parse(" + arg + ") = " + n.getLong());
1056 if (n.getType() != Formattable::kLong ||
1057 n.getLong() != 0) errln((UnicodeString)"FAIL: Expected 0");
1058 delete format;
1059 if (U_FAILURE(status)) errcheckln(status, (UnicodeString)"FAIL: Status " + u_errorName(status));
1060 //}
1061 //catch(Exception e) {
1062 // errln((UnicodeString)"Exception caught: " + e);
1063 //}
1064 }
1065
1066 // -------------------------------------
1067
1068 static const char *lenientAffixTestCases[] = {
1069 "(1)",
1070 "( 1)",
1071 "(1 )",
1072 "( 1 )"
1073 };
1074
1075 static const char *lenientMinusTestCases[] = {
1076 "-5",
1077 "\\u22125",
1078 "\\u27965"
1079 };
1080
1081 static const char *lenientCurrencyTestCases[] = {
1082 "$1,000",
1083 "$ 1,000",
1084 "$1000",
1085 "$ 1000",
1086 "$1 000.00",
1087 "$ 1 000.00",
1088 "$ 1\\u00A0000.00",
1089 "1000.00"
1090 };
1091
1092 // changed from () to - per cldrbug 5674
1093 static const char *lenientNegativeCurrencyTestCases[] = {
1094 "-$1,000",
1095 "-$ 1,000",
1096 "-$1000",
1097 "-$ 1000",
1098 "-$1 000.00",
1099 "-$ 1 000.00",
1100 "- $ 1,000.00 ",
1101 "-$ 1\\u00A0000.00",
1102 "-1000.00"
1103 };
1104
1105 static const char *lenientPercentTestCases[] = {
1106 "25%",
1107 " 25%",
1108 " 25 %",
1109 "25 %",
1110 "25\\u00A0%",
1111 "25"
1112 };
1113
1114 static const char *lenientNegativePercentTestCases[] = {
1115 "-25%",
1116 " -25%",
1117 " - 25%",
1118 "- 25 %",
1119 " - 25 %",
1120 "-25 %",
1121 "-25\\u00A0%",
1122 "-25",
1123 "- 25"
1124 };
1125
1126 static const char *strictFailureTestCases[] = {
1127 " 1000",
1128 "10,00",
1129 "1,000,.0"
1130 };
1131
1132 /**
1133 * Test lenient parsing.
1134 */
1135 void
TestLenientParse(void)1136 NumberFormatTest::TestLenientParse(void)
1137 {
1138 UErrorCode status = U_ZERO_ERROR;
1139 DecimalFormat *format = new DecimalFormat("(#,##0)", status);
1140 Formattable n;
1141
1142 if (format == NULL || U_FAILURE(status)) {
1143 dataerrln("Unable to create DecimalFormat (#,##0) - %s", u_errorName(status));
1144 } else {
1145 format->setLenient(TRUE);
1146 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientAffixTestCases); t += 1) {
1147 UnicodeString testCase = ctou(lenientAffixTestCases[t]);
1148
1149 format->parse(testCase, n, status);
1150 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1151
1152 if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
1153 n.getLong() != 1) {
1154 dataerrln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t]
1155 + (UnicodeString) "\"; error code = " + u_errorName(status));
1156 status = U_ZERO_ERROR;
1157 }
1158 }
1159 delete format;
1160 }
1161
1162 Locale en_US("en_US");
1163 Locale sv_SE("sv_SE");
1164
1165 NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, UNUM_DECIMAL, status);
1166
1167 if (mFormat == NULL || U_FAILURE(status)) {
1168 dataerrln("Unable to create NumberFormat (sv_SE, UNUM_DECIMAL) - %s", u_errorName(status));
1169 } else {
1170 mFormat->setLenient(TRUE);
1171 for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1172 UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1173
1174 mFormat->parse(testCase, n, status);
1175 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1176
1177 if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1178 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1179 + (UnicodeString) "\"; error code = " + u_errorName(status));
1180 status = U_ZERO_ERROR;
1181 }
1182 }
1183 delete mFormat;
1184 }
1185
1186 mFormat = NumberFormat::createInstance(en_US, UNUM_DECIMAL, status);
1187
1188 if (mFormat == NULL || U_FAILURE(status)) {
1189 dataerrln("Unable to create NumberFormat (en_US, UNUM_DECIMAL) - %s", u_errorName(status));
1190 } else {
1191 mFormat->setLenient(TRUE);
1192 for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1193 UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1194
1195 mFormat->parse(testCase, n, status);
1196 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1197
1198 if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1199 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1200 + (UnicodeString) "\"; error code = " + u_errorName(status));
1201 status = U_ZERO_ERROR;
1202 }
1203 }
1204 delete mFormat;
1205 }
1206
1207 NumberFormat *cFormat = NumberFormat::createInstance(en_US, UNUM_CURRENCY, status);
1208
1209 if (cFormat == NULL || U_FAILURE(status)) {
1210 dataerrln("Unable to create NumberFormat (en_US, UNUM_CURRENCY) - %s", u_errorName(status));
1211 } else {
1212 cFormat->setLenient(TRUE);
1213 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientCurrencyTestCases); t += 1) {
1214 UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
1215
1216 cFormat->parse(testCase, n, status);
1217 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1218
1219 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1220 n.getLong() != 1000) {
1221 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t]
1222 + (UnicodeString) "\"; error code = " + u_errorName(status));
1223 status = U_ZERO_ERROR;
1224 }
1225 }
1226
1227 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativeCurrencyTestCases); t += 1) {
1228 UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
1229
1230 cFormat->parse(testCase, n, status);
1231 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1232
1233 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1234 n.getLong() != -1000) {
1235 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t]
1236 + (UnicodeString) "\"; error code = " + u_errorName(status));
1237 status = U_ZERO_ERROR;
1238 }
1239 }
1240
1241 delete cFormat;
1242 }
1243
1244 NumberFormat *pFormat = NumberFormat::createPercentInstance(en_US, status);
1245
1246 if (pFormat == NULL || U_FAILURE(status)) {
1247 dataerrln("Unable to create NumberFormat::createPercentInstance (en_US) - %s", u_errorName(status));
1248 } else {
1249 pFormat->setLenient(TRUE);
1250 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientPercentTestCases); t += 1) {
1251 UnicodeString testCase = ctou(lenientPercentTestCases[t]);
1252
1253 pFormat->parse(testCase, n, status);
1254 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1255
1256 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1257 n.getDouble() != 0.25) {
1258 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t]
1259 + (UnicodeString) "\"; error code = " + u_errorName(status)
1260 + "; got: " + n.getDouble(status));
1261 status = U_ZERO_ERROR;
1262 }
1263 }
1264
1265 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativePercentTestCases); t += 1) {
1266 UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
1267
1268 pFormat->parse(testCase, n, status);
1269 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1270
1271 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1272 n.getDouble() != -0.25) {
1273 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t]
1274 + (UnicodeString) "\"; error code = " + u_errorName(status)
1275 + "; got: " + n.getDouble(status));
1276 status = U_ZERO_ERROR;
1277 }
1278 }
1279
1280 delete pFormat;
1281 }
1282
1283 // Test cases that should fail with a strict parse and pass with a
1284 // lenient parse.
1285 NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);
1286
1287 if (nFormat == NULL || U_FAILURE(status)) {
1288 dataerrln("Unable to create NumberFormat (en_US) - %s", u_errorName(status));
1289 } else {
1290 // first, make sure that they fail with a strict parse
1291 for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1292 UnicodeString testCase = ctou(strictFailureTestCases[t]);
1293
1294 nFormat->parse(testCase, n, status);
1295 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1296
1297 if (! U_FAILURE(status)) {
1298 errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t]
1299 + (UnicodeString) "\"; error code = " + u_errorName(status));
1300 }
1301
1302 status = U_ZERO_ERROR;
1303 }
1304
1305 // then, make sure that they pass with a lenient parse
1306 nFormat->setLenient(TRUE);
1307 for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1308 UnicodeString testCase = ctou(strictFailureTestCases[t]);
1309
1310 nFormat->parse(testCase, n, status);
1311 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1312
1313 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1314 n.getLong() != 1000) {
1315 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t]
1316 + (UnicodeString) "\"; error code = " + u_errorName(status));
1317 status = U_ZERO_ERROR;
1318 }
1319 }
1320
1321 delete nFormat;
1322 }
1323 }
1324
1325 // -------------------------------------
1326
1327 /**
1328 * Test proper rounding by the format method.
1329 */
1330 void
TestRounding487(void)1331 NumberFormatTest::TestRounding487(void)
1332 {
1333 UErrorCode status = U_ZERO_ERROR;
1334 NumberFormat *nf = NumberFormat::createInstance(status);
1335 if (U_FAILURE(status)) {
1336 dataerrln("Error calling NumberFormat::createInstance()");
1337 return;
1338 }
1339
1340 roundingTest(*nf, 0.00159999, 4, "0.0016");
1341 roundingTest(*nf, 0.00995, 4, "0.01");
1342
1343 roundingTest(*nf, 12.3995, 3, "12.4");
1344
1345 roundingTest(*nf, 12.4999, 0, "12");
1346 roundingTest(*nf, - 19.5, 0, "-20");
1347 delete nf;
1348 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
1349 }
1350
1351 /**
1352 * Test the functioning of the secondary grouping value.
1353 */
TestSecondaryGrouping(void)1354 void NumberFormatTest::TestSecondaryGrouping(void) {
1355 UErrorCode status = U_ZERO_ERROR;
1356 DecimalFormatSymbols US(Locale::getUS(), status);
1357 CHECK(status, "DecimalFormatSymbols ct");
1358
1359 DecimalFormat f("#,##,###", US, status);
1360 CHECK(status, "DecimalFormat ct");
1361
1362 expect2(f, (int32_t)123456789L, "12,34,56,789");
1363 expectPat(f, "#,##,##0");
1364 f.applyPattern("#,###", status);
1365 CHECK(status, "applyPattern");
1366
1367 f.setSecondaryGroupingSize(4);
1368 expect2(f, (int32_t)123456789L, "12,3456,789");
1369 expectPat(f, "#,####,##0");
1370 NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
1371 CHECK_DATA(status, "createInstance(hi_IN)");
1372
1373 UnicodeString out;
1374 int32_t l = (int32_t)1876543210L;
1375 g->format(l, out);
1376 delete g;
1377 // expect "1,87,65,43,210", but with Hindi digits
1378 // 01234567890123
1379 UBool ok = TRUE;
1380 if (out.length() != 14) {
1381 ok = FALSE;
1382 } else {
1383 for (int32_t i=0; i<out.length(); ++i) {
1384 UBool expectGroup = FALSE;
1385 switch (i) {
1386 case 1:
1387 case 4:
1388 case 7:
1389 case 10:
1390 expectGroup = TRUE;
1391 break;
1392 }
1393 // Later -- fix this to get the actual grouping
1394 // character from the resource bundle.
1395 UBool isGroup = (out.charAt(i) == 0x002C);
1396 if (isGroup != expectGroup) {
1397 ok = FALSE;
1398 break;
1399 }
1400 }
1401 }
1402 if (!ok) {
1403 errln((UnicodeString)"FAIL Expected " + l +
1404 " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
1405 escape(out) + "\"");
1406 } else {
1407 logln((UnicodeString)"Ok " + l +
1408 " x hi_IN -> \"" +
1409 escape(out) + "\"");
1410 }
1411 }
1412
TestWhiteSpaceParsing(void)1413 void NumberFormatTest::TestWhiteSpaceParsing(void) {
1414 UErrorCode ec = U_ZERO_ERROR;
1415 DecimalFormatSymbols US(Locale::getUS(), ec);
1416 DecimalFormat fmt("a b#0c ", US, ec);
1417 if (U_FAILURE(ec)) {
1418 errcheckln(ec, "FAIL: Constructor - %s", u_errorName(ec));
1419 return;
1420 }
1421 // From ICU 62, flexible whitespace needs lenient mode
1422 fmt.setLenient(TRUE);
1423 int32_t n = 1234;
1424 expect(fmt, "a b1234c ", n);
1425 expect(fmt, "a b1234c ", n);
1426 }
1427
1428 /**
1429 * Test currencies whose display name is a ChoiceFormat.
1430 */
TestComplexCurrency()1431 void NumberFormatTest::TestComplexCurrency() {
1432
1433 // UErrorCode ec = U_ZERO_ERROR;
1434 // Locale loc("kn", "IN", "");
1435 // NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
1436 // if (U_SUCCESS(ec)) {
1437 // expect2(*fmt, 1.0, CharsToUnicodeString("Re.\\u00A01.00"));
1438 // Use .00392625 because that's 2^-8. Any value less than 0.005 is fine.
1439 // expect(*fmt, 1.00390625, CharsToUnicodeString("Re.\\u00A01.00")); // tricky
1440 // expect2(*fmt, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
1441 // expect2(*fmt, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
1442 // expect2(*fmt, -1.0, CharsToUnicodeString("-Re.\\u00A01.00"));
1443 // expect2(*fmt, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
1444 // } else {
1445 // errln("FAIL: getCurrencyInstance(kn_IN)");
1446 // }
1447 // delete fmt;
1448
1449 }
1450
1451 // -------------------------------------
1452
1453 void
roundingTest(NumberFormat & nf,double x,int32_t maxFractionDigits,const char * expected)1454 NumberFormatTest::roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)
1455 {
1456 nf.setMaximumFractionDigits(maxFractionDigits);
1457 UnicodeString out; nf.format(x, out);
1458 logln((UnicodeString)"" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
1459 if (!(out==expected)) errln((UnicodeString)"FAIL: Expected " + expected);
1460 }
1461
1462 /**
1463 * Upgrade to alphaWorks
1464 */
TestExponent(void)1465 void NumberFormatTest::TestExponent(void) {
1466 UErrorCode status = U_ZERO_ERROR;
1467 DecimalFormatSymbols US(Locale::getUS(), status);
1468 CHECK(status, "DecimalFormatSymbols constructor");
1469 DecimalFormat fmt1(UnicodeString("0.###E0"), US, status);
1470 CHECK(status, "DecimalFormat(0.###E0)");
1471 DecimalFormat fmt2(UnicodeString("0.###E+0"), US, status);
1472 CHECK(status, "DecimalFormat(0.###E+0)");
1473 int32_t n = 1234;
1474 expect2(fmt1, n, "1.234E3");
1475 expect2(fmt2, n, "1.234E+3");
1476 expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
1477 }
1478
1479 /**
1480 * Upgrade to alphaWorks
1481 */
TestScientific(void)1482 void NumberFormatTest::TestScientific(void) {
1483 UErrorCode status = U_ZERO_ERROR;
1484 DecimalFormatSymbols US(Locale::getUS(), status);
1485 CHECK(status, "DecimalFormatSymbols constructor");
1486
1487 // Test pattern round-trip
1488 const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
1489 "0.###E0;[0.###E0]" };
1490 int32_t PAT_length = UPRV_LENGTHOF(PAT);
1491 int32_t DIGITS[] = {
1492 // min int, max int, min frac, max frac
1493 1, 1, 0, 0, // "#E0"
1494 1, 1, 0, 4, // "0.####E0"
1495 2, 2, 3, 3, // "00.000E00"
1496 1, 3, 0, 4, // "##0.####E000"
1497 1, 1, 0, 3, // "0.###E0;[0.###E0]"
1498 };
1499 for (int32_t i=0; i<PAT_length; ++i) {
1500 UnicodeString pat(PAT[i]);
1501 DecimalFormat df(pat, US, status);
1502 CHECK(status, "DecimalFormat constructor");
1503 UnicodeString pat2;
1504 df.toPattern(pat2);
1505 if (pat == pat2) {
1506 logln(UnicodeString("Ok Pattern rt \"") +
1507 pat + "\" -> \"" +
1508 pat2 + "\"");
1509 } else {
1510 errln(UnicodeString("FAIL Pattern rt \"") +
1511 pat + "\" -> \"" +
1512 pat2 + "\"");
1513 }
1514 // Make sure digit counts match what we expect
1515 if (df.getMinimumIntegerDigits() != DIGITS[4*i] ||
1516 df.getMaximumIntegerDigits() != DIGITS[4*i+1] ||
1517 df.getMinimumFractionDigits() != DIGITS[4*i+2] ||
1518 df.getMaximumFractionDigits() != DIGITS[4*i+3]) {
1519 errln(UnicodeString("FAIL \"" + pat +
1520 "\" min/max int; min/max frac = ") +
1521 df.getMinimumIntegerDigits() + "/" +
1522 df.getMaximumIntegerDigits() + ";" +
1523 df.getMinimumFractionDigits() + "/" +
1524 df.getMaximumFractionDigits() + ", expect " +
1525 DIGITS[4*i] + "/" +
1526 DIGITS[4*i+1] + ";" +
1527 DIGITS[4*i+2] + "/" +
1528 DIGITS[4*i+3]);
1529 }
1530 }
1531
1532
1533 // Test the constructor for default locale. We have to
1534 // manually set the default locale, as there is no
1535 // guarantee that the default locale has the same
1536 // scientific format.
1537 Locale def = Locale::getDefault();
1538 Locale::setDefault(Locale::getUS(), status);
1539 expect2(NumberFormat::createScientificInstance(status),
1540 12345.678901,
1541 "1.2345678901E4", status);
1542 Locale::setDefault(def, status);
1543
1544 expect2(new DecimalFormat("#E0", US, status),
1545 12345.0,
1546 "1.2345E4", status);
1547 expect(new DecimalFormat("0E0", US, status),
1548 12345.0,
1549 "1E4", status);
1550 expect2(NumberFormat::createScientificInstance(Locale::getUS(), status),
1551 12345.678901,
1552 "1.2345678901E4", status);
1553 expect(new DecimalFormat("##0.###E0", US, status),
1554 12345.0,
1555 "12.34E3", status);
1556 expect(new DecimalFormat("##0.###E0", US, status),
1557 12345.00001,
1558 "12.35E3", status);
1559 expect2(new DecimalFormat("##0.####E0", US, status),
1560 (int32_t) 12345,
1561 "12.345E3", status);
1562 expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status),
1563 12345.678901,
1564 "1,2345678901E4", status);
1565 expect(new DecimalFormat("##0.####E0", US, status),
1566 789.12345e-9,
1567 "789.12E-9", status);
1568 expect2(new DecimalFormat("##0.####E0", US, status),
1569 780.e-9,
1570 "780E-9", status);
1571 expect(new DecimalFormat(".###E0", US, status),
1572 45678.0,
1573 ".457E5", status);
1574 expect2(new DecimalFormat(".###E0", US, status),
1575 (int32_t) 0,
1576 ".0E0", status);
1577 /*
1578 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
1579 new DecimalFormat("##E0", US),
1580 new DecimalFormat("####E0", US),
1581 new DecimalFormat("0E0", US),
1582 new DecimalFormat("00E0", US),
1583 new DecimalFormat("000E0", US),
1584 },
1585 new Long(45678000),
1586 new String[] { "4.5678E7",
1587 "45.678E6",
1588 "4567.8E4",
1589 "5E7",
1590 "46E6",
1591 "457E5",
1592 }
1593 );
1594 !
1595 ! Unroll this test into individual tests below...
1596 !
1597 */
1598 expect2(new DecimalFormat("#E0", US, status),
1599 (int32_t) 45678000, "4.5678E7", status);
1600 expect2(new DecimalFormat("##E0", US, status),
1601 (int32_t) 45678000, "45.678E6", status);
1602 expect2(new DecimalFormat("####E0", US, status),
1603 (int32_t) 45678000, "4567.8E4", status);
1604 expect(new DecimalFormat("0E0", US, status),
1605 (int32_t) 45678000, "5E7", status);
1606 expect(new DecimalFormat("00E0", US, status),
1607 (int32_t) 45678000, "46E6", status);
1608 expect(new DecimalFormat("000E0", US, status),
1609 (int32_t) 45678000, "457E5", status);
1610 /*
1611 expect(new DecimalFormat("###E0", US, status),
1612 new Object[] { new Double(0.0000123), "12.3E-6",
1613 new Double(0.000123), "123E-6",
1614 new Double(0.00123), "1.23E-3",
1615 new Double(0.0123), "12.3E-3",
1616 new Double(0.123), "123E-3",
1617 new Double(1.23), "1.23E0",
1618 new Double(12.3), "12.3E0",
1619 new Double(123), "123E0",
1620 new Double(1230), "1.23E3",
1621 });
1622 !
1623 ! Unroll this test into individual tests below...
1624 !
1625 */
1626 expect2(new DecimalFormat("###E0", US, status),
1627 0.0000123, "12.3E-6", status);
1628 expect2(new DecimalFormat("###E0", US, status),
1629 0.000123, "123E-6", status);
1630 expect2(new DecimalFormat("###E0", US, status),
1631 0.00123, "1.23E-3", status);
1632 expect2(new DecimalFormat("###E0", US, status),
1633 0.0123, "12.3E-3", status);
1634 expect2(new DecimalFormat("###E0", US, status),
1635 0.123, "123E-3", status);
1636 expect2(new DecimalFormat("###E0", US, status),
1637 1.23, "1.23E0", status);
1638 expect2(new DecimalFormat("###E0", US, status),
1639 12.3, "12.3E0", status);
1640 expect2(new DecimalFormat("###E0", US, status),
1641 123.0, "123E0", status);
1642 expect2(new DecimalFormat("###E0", US, status),
1643 1230.0, "1.23E3", status);
1644 /*
1645 expect(new DecimalFormat("0.#E+00", US, status),
1646 new Object[] { new Double(0.00012), "1.2E-04",
1647 new Long(12000), "1.2E+04",
1648 });
1649 !
1650 ! Unroll this test into individual tests below...
1651 !
1652 */
1653 expect2(new DecimalFormat("0.#E+00", US, status),
1654 0.00012, "1.2E-04", status);
1655 expect2(new DecimalFormat("0.#E+00", US, status),
1656 (int32_t) 12000, "1.2E+04", status);
1657 }
1658
1659 /**
1660 * Upgrade to alphaWorks
1661 */
TestPad(void)1662 void NumberFormatTest::TestPad(void) {
1663 UErrorCode status = U_ZERO_ERROR;
1664 DecimalFormatSymbols US(Locale::getUS(), status);
1665 CHECK(status, "DecimalFormatSymbols constructor");
1666
1667 expect2(new DecimalFormat("*^##.##", US, status),
1668 int32_t(0), "^^^^0", status);
1669 expect2(new DecimalFormat("*^##.##", US, status),
1670 -1.3, "^-1.3", status);
1671 expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1672 int32_t(0), "0.0E0______ g-m/s^2", status);
1673 expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1674 1.0/3, "333.333E-3_ g-m/s^2", status);
1675 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1676 int32_t(0), "0.0______ g-m/s^2", status);
1677 expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1678 1.0/3, "0.33333__ g-m/s^2", status);
1679
1680 // Test padding before a sign
1681 const char *formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1682 expect2(new DecimalFormat(formatStr, US, status),
1683 int32_t(-10), "xxxxxxxxxx(10.0)", status);
1684 expect2(new DecimalFormat(formatStr, US, status),
1685 int32_t(-1000),"xxxxxxx(1,000.0)", status);
1686 expect2(new DecimalFormat(formatStr, US, status),
1687 int32_t(-1000000),"xxx(1,000,000.0)", status);
1688 expect2(new DecimalFormat(formatStr, US, status),
1689 -100.37, "xxxxxxxx(100.37)", status);
1690 expect2(new DecimalFormat(formatStr, US, status),
1691 -10456.37, "xxxxx(10,456.37)", status);
1692 expect2(new DecimalFormat(formatStr, US, status),
1693 -1120456.37, "xx(1,120,456.37)", status);
1694 expect2(new DecimalFormat(formatStr, US, status),
1695 -112045600.37, "(112,045,600.37)", status);
1696 expect2(new DecimalFormat(formatStr, US, status),
1697 -1252045600.37,"(1,252,045,600.37)", status);
1698
1699 expect2(new DecimalFormat(formatStr, US, status),
1700 int32_t(10), "xxxxxxxxxxxx10.0", status);
1701 expect2(new DecimalFormat(formatStr, US, status),
1702 int32_t(1000),"xxxxxxxxx1,000.0", status);
1703 expect2(new DecimalFormat(formatStr, US, status),
1704 int32_t(1000000),"xxxxx1,000,000.0", status);
1705 expect2(new DecimalFormat(formatStr, US, status),
1706 100.37, "xxxxxxxxxx100.37", status);
1707 expect2(new DecimalFormat(formatStr, US, status),
1708 10456.37, "xxxxxxx10,456.37", status);
1709 expect2(new DecimalFormat(formatStr, US, status),
1710 1120456.37, "xxxx1,120,456.37", status);
1711 expect2(new DecimalFormat(formatStr, US, status),
1712 112045600.37, "xx112,045,600.37", status);
1713 expect2(new DecimalFormat(formatStr, US, status),
1714 10252045600.37,"10,252,045,600.37", status);
1715
1716
1717 // Test padding between a sign and a number
1718 const char *formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1719 expect2(new DecimalFormat(formatStr2, US, status),
1720 int32_t(-10), "(10.0xxxxxxxxxx)", status);
1721 expect2(new DecimalFormat(formatStr2, US, status),
1722 int32_t(-1000),"(1,000.0xxxxxxx)", status);
1723 expect2(new DecimalFormat(formatStr2, US, status),
1724 int32_t(-1000000),"(1,000,000.0xxx)", status);
1725 expect2(new DecimalFormat(formatStr2, US, status),
1726 -100.37, "(100.37xxxxxxxx)", status);
1727 expect2(new DecimalFormat(formatStr2, US, status),
1728 -10456.37, "(10,456.37xxxxx)", status);
1729 expect2(new DecimalFormat(formatStr2, US, status),
1730 -1120456.37, "(1,120,456.37xx)", status);
1731 expect2(new DecimalFormat(formatStr2, US, status),
1732 -112045600.37, "(112,045,600.37)", status);
1733 expect2(new DecimalFormat(formatStr2, US, status),
1734 -1252045600.37,"(1,252,045,600.37)", status);
1735
1736 expect2(new DecimalFormat(formatStr2, US, status),
1737 int32_t(10), "10.0xxxxxxxxxxxx", status);
1738 expect2(new DecimalFormat(formatStr2, US, status),
1739 int32_t(1000),"1,000.0xxxxxxxxx", status);
1740 expect2(new DecimalFormat(formatStr2, US, status),
1741 int32_t(1000000),"1,000,000.0xxxxx", status);
1742 expect2(new DecimalFormat(formatStr2, US, status),
1743 100.37, "100.37xxxxxxxxxx", status);
1744 expect2(new DecimalFormat(formatStr2, US, status),
1745 10456.37, "10,456.37xxxxxxx", status);
1746 expect2(new DecimalFormat(formatStr2, US, status),
1747 1120456.37, "1,120,456.37xxxx", status);
1748 expect2(new DecimalFormat(formatStr2, US, status),
1749 112045600.37, "112,045,600.37xx", status);
1750 expect2(new DecimalFormat(formatStr2, US, status),
1751 10252045600.37,"10,252,045,600.37", status);
1752
1753 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1754 DecimalFormat fmt("#", US, status);
1755 CHECK(status, "DecimalFormat constructor");
1756 UnicodeString padString("P");
1757 fmt.setPadCharacter(padString);
1758 expectPad(fmt, "*P##.##", DecimalFormat::kPadBeforePrefix, 5, padString);
1759 fmt.setPadCharacter((UnicodeString)"^");
1760 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, (UnicodeString)"^");
1761 //commented untill implementation is complete
1762 /* fmt.setPadCharacter((UnicodeString)"^^^");
1763 expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1764 padString.remove();
1765 padString.append((UChar)0x0061);
1766 padString.append((UChar)0x0302);
1767 fmt.setPadCharacter(padString);
1768 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1769 UnicodeString pattern(patternChars);
1770 expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1771 */
1772
1773 }
1774
1775 /**
1776 * Upgrade to alphaWorks
1777 */
TestPatterns2(void)1778 void NumberFormatTest::TestPatterns2(void) {
1779 UErrorCode status = U_ZERO_ERROR;
1780 DecimalFormatSymbols US(Locale::getUS(), status);
1781 CHECK(status, "DecimalFormatSymbols constructor");
1782
1783 DecimalFormat fmt("#", US, status);
1784 CHECK(status, "DecimalFormat constructor");
1785
1786 UChar hat = 0x005E; /*^*/
1787
1788 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, hat);
1789 expectPad(fmt, "$*^#", DecimalFormat::kPadAfterPrefix, 2, hat);
1790 expectPad(fmt, "#*^", DecimalFormat::kPadBeforeSuffix, 1, hat);
1791 expectPad(fmt, "#$*^", DecimalFormat::kPadAfterSuffix, 2, hat);
1792 expectPad(fmt, "$*^$#", ILLEGAL);
1793 expectPad(fmt, "#$*^$", ILLEGAL);
1794 expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix,
1795 12, (UChar)0x0078 /*x*/);
1796 expectPad(fmt, "''#0*x", DecimalFormat::kPadBeforeSuffix,
1797 3, (UChar)0x0078 /*x*/);
1798 expectPad(fmt, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix,
1799 10, (UChar)0x0061 /*a*/);
1800
1801 fmt.applyPattern("AA#,##0.00ZZ", status);
1802 CHECK(status, "applyPattern");
1803 fmt.setPadCharacter(hat);
1804
1805 fmt.setFormatWidth(10);
1806
1807 fmt.setPadPosition(DecimalFormat::kPadBeforePrefix);
1808 expectPat(fmt, "*^AA#,##0.00ZZ");
1809
1810 fmt.setPadPosition(DecimalFormat::kPadBeforeSuffix);
1811 expectPat(fmt, "AA#,##0.00*^ZZ");
1812
1813 fmt.setPadPosition(DecimalFormat::kPadAfterSuffix);
1814 expectPat(fmt, "AA#,##0.00ZZ*^");
1815
1816 // 12 3456789012
1817 UnicodeString exp("AA*^#,##0.00ZZ", "");
1818 fmt.setFormatWidth(12);
1819 fmt.setPadPosition(DecimalFormat::kPadAfterPrefix);
1820 expectPat(fmt, exp);
1821
1822 fmt.setFormatWidth(13);
1823 // 12 34567890123
1824 expectPat(fmt, "AA*^##,##0.00ZZ");
1825
1826 fmt.setFormatWidth(14);
1827 // 12 345678901234
1828 expectPat(fmt, "AA*^###,##0.00ZZ");
1829
1830 fmt.setFormatWidth(15);
1831 // 12 3456789012345
1832 expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1833
1834 fmt.setFormatWidth(16);
1835 // 12 34567890123456
1836 expectPat(fmt, "AA*^#####,##0.00ZZ");
1837 }
1838
TestSurrogateSupport(void)1839 void NumberFormatTest::TestSurrogateSupport(void) {
1840 UErrorCode status = U_ZERO_ERROR;
1841 DecimalFormatSymbols custom(Locale::getUS(), status);
1842 CHECK(status, "DecimalFormatSymbols constructor");
1843
1844 custom.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, "decimal");
1845 custom.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, "plus");
1846 custom.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, " minus ");
1847 custom.setSymbol(DecimalFormatSymbols::kExponentialSymbol, "exponent");
1848
1849 UnicodeString patternStr("*\\U00010000##.##", "");
1850 patternStr = patternStr.unescape();
1851 UnicodeString expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1852 expStr = expStr.unescape();
1853 expect2(new DecimalFormat(patternStr, custom, status),
1854 int32_t(0), expStr, status);
1855
1856 status = U_ZERO_ERROR;
1857 expect2(new DecimalFormat("*^##.##", custom, status),
1858 int32_t(0), "^^^^0", status);
1859 status = U_ZERO_ERROR;
1860 expect2(new DecimalFormat("##.##", custom, status),
1861 -1.3, " minus 1decimal3", status);
1862 status = U_ZERO_ERROR;
1863 expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1864 int32_t(0), "0decimal0exponent0 g-m/s^2", status);
1865 status = U_ZERO_ERROR;
1866 expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1867 1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
1868 status = U_ZERO_ERROR;
1869 expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1870 int32_t(0), "0decimal0 g-m/s^2", status);
1871 status = U_ZERO_ERROR;
1872 expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1873 1.0/3, "0decimal33333 g-m/s^2", status);
1874
1875 UnicodeString zero((UChar32)0x10000);
1876 UnicodeString one((UChar32)0x10001);
1877 UnicodeString two((UChar32)0x10002);
1878 UnicodeString five((UChar32)0x10005);
1879 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
1880 custom.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, one);
1881 custom.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, two);
1882 custom.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, five);
1883 expStr = UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1884 expStr = expStr.unescape();
1885 status = U_ZERO_ERROR;
1886 expect2(new DecimalFormat("##0.000", custom, status),
1887 1.25, expStr, status);
1888
1889 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
1890 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
1891 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
1892 patternStr = UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
1893 patternStr = patternStr.unescape();
1894 expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1895 status = U_ZERO_ERROR;
1896 expect2(new DecimalFormat(patternStr, custom, status),
1897 int32_t(-20), expStr, status);
1898
1899 custom.setSymbol(DecimalFormatSymbols::kPercentSymbol, "percent");
1900 patternStr = "'You''ve lost ' -0.00 %' of your money today'";
1901 patternStr = patternStr.unescape();
1902 expStr = UnicodeString(" minus You've lost minus 2000decimal00 percent of your money today", "");
1903 status = U_ZERO_ERROR;
1904 expect2(new DecimalFormat(patternStr, custom, status),
1905 int32_t(-20), expStr, status);
1906 }
1907
TestCurrencyPatterns(void)1908 void NumberFormatTest::TestCurrencyPatterns(void) {
1909 int32_t i, locCount;
1910 const Locale* locs = NumberFormat::getAvailableLocales(locCount);
1911 for (i=0; i<locCount; ++i) {
1912 UErrorCode ec = U_ZERO_ERROR;
1913 NumberFormat* nf = NumberFormat::createCurrencyInstance(locs[i], ec);
1914 if (U_FAILURE(ec)) {
1915 errln("FAIL: Can't create NumberFormat(%s) - %s", locs[i].getName(), u_errorName(ec));
1916 } else {
1917 // Make sure currency formats do not have a variable number
1918 // of fraction digits
1919 int32_t min = nf->getMinimumFractionDigits();
1920 int32_t max = nf->getMaximumFractionDigits();
1921 if (min != max) {
1922 UnicodeString a, b;
1923 nf->format(1.0, a);
1924 nf->format(1.125, b);
1925 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1926 " min fraction digits != max fraction digits; "
1927 "x 1.0 => " + escape(a) +
1928 "; x 1.125 => " + escape(b));
1929 }
1930
1931 // Make sure EURO currency formats have exactly 2 fraction digits
1932 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
1933 if (df != NULL) {
1934 if (u_strcmp(EUR, df->getCurrency()) == 0) {
1935 if (min != 2 || max != 2) {
1936 UnicodeString a;
1937 nf->format(1.0, a);
1938 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1939 " is a EURO format but it does not have 2 fraction digits; "
1940 "x 1.0 => " +
1941 escape(a));
1942 }
1943 }
1944 }
1945 }
1946 delete nf;
1947 }
1948 }
1949
TestRegCurrency(void)1950 void NumberFormatTest::TestRegCurrency(void) {
1951 #if !UCONFIG_NO_SERVICE
1952 UErrorCode status = U_ZERO_ERROR;
1953 UChar USD[4];
1954 ucurr_forLocale("en_US", USD, 4, &status);
1955 UChar YEN[4];
1956 ucurr_forLocale("ja_JP", YEN, 4, &status);
1957 UChar TMP[4];
1958
1959 if(U_FAILURE(status)) {
1960 errcheckln(status, "Unable to get currency for locale, error %s", u_errorName(status));
1961 return;
1962 }
1963
1964 UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
1965
1966 ucurr_forLocale("en_US", TMP, 4, &status);
1967 if (u_strcmp(YEN, TMP) != 0) {
1968 errln("FAIL: didn't return YEN registered for en_US");
1969 }
1970
1971 int32_t fallbackLen = ucurr_forLocale("en_XX_BAR", TMP, 4, &status);
1972 if (fallbackLen) {
1973 errln("FAIL: tried to fallback en_XX_BAR");
1974 }
1975 status = U_ZERO_ERROR; // reset
1976
1977 if (!ucurr_unregister(enkey, &status)) {
1978 errln("FAIL: couldn't unregister enkey");
1979 }
1980
1981 ucurr_forLocale("en_US", TMP, 4, &status);
1982 if (u_strcmp(USD, TMP) != 0) {
1983 errln("FAIL: didn't return USD for en_US after unregister of en_US");
1984 }
1985 status = U_ZERO_ERROR; // reset
1986
1987 ucurr_forLocale("en_US_BLAH", TMP, 4, &status);
1988 if (u_strcmp(USD, TMP) != 0) {
1989 errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1990 }
1991 status = U_ZERO_ERROR; // reset
1992 #endif
1993 }
1994
TestCurrencyNames(void)1995 void NumberFormatTest::TestCurrencyNames(void) {
1996 // Do a basic check of getName()
1997 // USD { "US$", "US Dollar" } // 04/04/1792-
1998 UErrorCode ec = U_ZERO_ERROR;
1999 static const UChar USD[] = {0x55, 0x53, 0x44, 0}; /*USD*/
2000 static const UChar USX[] = {0x55, 0x53, 0x58, 0}; /*USX*/
2001 static const UChar CAD[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
2002 static const UChar ITL[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
2003 UBool isChoiceFormat;
2004 int32_t len;
2005 const UBool possibleDataError = TRUE;
2006 // Warning: HARD-CODED LOCALE DATA in this test. If it fails, CHECK
2007 // THE LOCALE DATA before diving into the code.
2008 assertEquals("USD.getName(SYMBOL_NAME, en)",
2009 UnicodeString("$"),
2010 UnicodeString(ucurr_getName(USD, "en",
2011 UCURR_SYMBOL_NAME,
2012 &isChoiceFormat, &len, &ec)),
2013 possibleDataError);
2014 assertEquals("USD.getName(NARROW_SYMBOL_NAME, en)",
2015 UnicodeString("$"),
2016 UnicodeString(ucurr_getName(USD, "en",
2017 UCURR_NARROW_SYMBOL_NAME,
2018 &isChoiceFormat, &len, &ec)),
2019 possibleDataError);
2020 assertEquals("USD.getName(LONG_NAME, en)",
2021 UnicodeString("US Dollar"),
2022 UnicodeString(ucurr_getName(USD, "en",
2023 UCURR_LONG_NAME,
2024 &isChoiceFormat, &len, &ec)),
2025 possibleDataError);
2026 assertEquals("CAD.getName(SYMBOL_NAME, en)",
2027 UnicodeString("CA$"),
2028 UnicodeString(ucurr_getName(CAD, "en",
2029 UCURR_SYMBOL_NAME,
2030 &isChoiceFormat, &len, &ec)),
2031 possibleDataError);
2032 assertEquals("CAD.getName(NARROW_SYMBOL_NAME, en)",
2033 UnicodeString("$"),
2034 UnicodeString(ucurr_getName(CAD, "en",
2035 UCURR_NARROW_SYMBOL_NAME,
2036 &isChoiceFormat, &len, &ec)),
2037 possibleDataError);
2038 assertEquals("CAD.getName(SYMBOL_NAME, en_CA)",
2039 UnicodeString("$"),
2040 UnicodeString(ucurr_getName(CAD, "en_CA",
2041 UCURR_SYMBOL_NAME,
2042 &isChoiceFormat, &len, &ec)),
2043 possibleDataError);
2044 assertEquals("USD.getName(SYMBOL_NAME, en_CA)",
2045 UnicodeString("US$"),
2046 UnicodeString(ucurr_getName(USD, "en_CA",
2047 UCURR_SYMBOL_NAME,
2048 &isChoiceFormat, &len, &ec)),
2049 possibleDataError);
2050 assertEquals("USD.getName(NARROW_SYMBOL_NAME, en_CA)",
2051 UnicodeString("$"),
2052 UnicodeString(ucurr_getName(USD, "en_CA",
2053 UCURR_NARROW_SYMBOL_NAME,
2054 &isChoiceFormat, &len, &ec)),
2055 possibleDataError);
2056 assertEquals("USD.getName(SYMBOL_NAME) in en_NZ",
2057 UnicodeString("US$"),
2058 UnicodeString(ucurr_getName(USD, "en_NZ",
2059 UCURR_SYMBOL_NAME,
2060 &isChoiceFormat, &len, &ec)),
2061 possibleDataError);
2062 assertEquals("CAD.getName(SYMBOL_NAME)",
2063 UnicodeString("CA$"),
2064 UnicodeString(ucurr_getName(CAD, "en_NZ",
2065 UCURR_SYMBOL_NAME,
2066 &isChoiceFormat, &len, &ec)),
2067 possibleDataError);
2068 assertEquals("USX.getName(SYMBOL_NAME)",
2069 UnicodeString("USX"),
2070 UnicodeString(ucurr_getName(USX, "en_US",
2071 UCURR_SYMBOL_NAME,
2072 &isChoiceFormat, &len, &ec)),
2073 possibleDataError);
2074 assertEquals("USX.getName(NARROW_SYMBOL_NAME)",
2075 UnicodeString("USX"),
2076 UnicodeString(ucurr_getName(USX, "en_US",
2077 UCURR_NARROW_SYMBOL_NAME,
2078 &isChoiceFormat, &len, &ec)),
2079 possibleDataError);
2080 assertEquals("USX.getName(LONG_NAME)",
2081 UnicodeString("USX"),
2082 UnicodeString(ucurr_getName(USX, "en_US",
2083 UCURR_LONG_NAME,
2084 &isChoiceFormat, &len, &ec)),
2085 possibleDataError);
2086 assertSuccess("ucurr_getName", ec);
2087
2088 ec = U_ZERO_ERROR;
2089
2090 // Test that a default or fallback warning is being returned. JB 4239.
2091 ucurr_getName(CAD, "es_ES", UCURR_LONG_NAME, &isChoiceFormat,
2092 &len, &ec);
2093 assertTrue("ucurr_getName (es_ES fallback)",
2094 U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);
2095
2096 ucurr_getName(CAD, "zh_TW", UCURR_LONG_NAME, &isChoiceFormat,
2097 &len, &ec);
2098 assertTrue("ucurr_getName (zh_TW fallback)",
2099 U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);
2100
2101 ucurr_getName(CAD, "en_US", UCURR_LONG_NAME, &isChoiceFormat,
2102 &len, &ec);
2103 assertTrue("ucurr_getName (en_US default)",
2104 U_USING_DEFAULT_WARNING == ec || U_USING_FALLBACK_WARNING == ec, TRUE);
2105
2106 ucurr_getName(CAD, "ti", UCURR_LONG_NAME, &isChoiceFormat,
2107 &len, &ec);
2108 assertTrue("ucurr_getName (ti default)",
2109 U_USING_DEFAULT_WARNING == ec, TRUE);
2110
2111 // Test that a default warning is being returned when falling back to root. JB 4536.
2112 ucurr_getName(ITL, "cy", UCURR_LONG_NAME, &isChoiceFormat,
2113 &len, &ec);
2114 assertTrue("ucurr_getName (cy default to root)",
2115 U_USING_DEFAULT_WARNING == ec, TRUE);
2116
2117 // TODO add more tests later
2118 }
2119
TestCurrencyVariants()2120 void NumberFormatTest::TestCurrencyVariants(){
2121 IcuTestErrorCode status(*this, "TestCurrencyVariants");
2122
2123 struct TestCase {
2124 const char* locale;
2125 const char16_t* isoCode;
2126 const char16_t* expectedShort;
2127 const char16_t* expectedNarrow;
2128 const char16_t* expectedFormal;
2129 const char16_t* expectedVariant;
2130 UErrorCode expectedNarrowError;
2131 } cases[] = {
2132 {"en-US", u"CAD", u"CA$", u"$", u"CA$", u"CA$", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2133 {"en-US", u"CDF", u"CDF", u"CDF", u"CDF", u"CDF", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2134 {"sw-CD", u"CDF", u"FC", u"FC", u"FC", u"FC", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2135 {"en-US", u"GEL", u"GEL", u"₾", u"GEL", u"GEL", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2136 {"ka-GE", u"GEL", u"₾", u"₾", u"₾", u"₾", U_USING_FALLBACK_WARNING}, // narrow: fallback to ka
2137 {"ka", u"GEL", u"₾", u"₾", u"₾", u"₾", U_ZERO_ERROR}, // no fallback on narrow
2138 {"zh-TW", u"TWD", u"$", u"$", u"NT$", u"$", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2139 {"ccp", u"TRY", u"TRY", u"₺", u"TRY", u"TL", U_ZERO_ERROR}, // no fallback on variant
2140 };
2141 for (const auto& cas : cases) {
2142 status.setScope(cas.isoCode);
2143 UBool choiceFormatIgnored;
2144 int32_t lengthIgnored;
2145 const UChar* actualShort = ucurr_getName(
2146 cas.isoCode,
2147 cas.locale,
2148 UCURR_SYMBOL_NAME,
2149 &choiceFormatIgnored,
2150 &lengthIgnored,
2151 status);
2152 const UChar* actualFormal = ucurr_getName(
2153 cas.isoCode,
2154 cas.locale,
2155 UCURR_FORMAL_SYMBOL_NAME,
2156 &choiceFormatIgnored,
2157 &lengthIgnored,
2158 status);
2159 const UChar* actualVarant = ucurr_getName(
2160 cas.isoCode,
2161 cas.locale,
2162 UCURR_VARIANT_SYMBOL_NAME,
2163 &choiceFormatIgnored,
2164 &lengthIgnored,
2165 status);
2166 status.errIfFailureAndReset();
2167 const UChar* actualNarrow = ucurr_getName(
2168 cas.isoCode,
2169 cas.locale,
2170 UCURR_NARROW_SYMBOL_NAME,
2171 &choiceFormatIgnored,
2172 &lengthIgnored,
2173 status);
2174 status.expectErrorAndReset(cas.expectedNarrowError);
2175 assertEquals(UnicodeString("Short symbol: ") + cas.locale + u": " + cas.isoCode,
2176 cas.expectedShort, actualShort);
2177 assertEquals(UnicodeString("Narrow symbol: ") + cas.locale + u": " + cas.isoCode,
2178 cas.expectedNarrow, actualNarrow);
2179 assertEquals(UnicodeString("Formal symbol: ") + cas.locale + u": " + cas.isoCode,
2180 cas.expectedFormal, actualFormal);
2181 assertEquals(UnicodeString("Variant symbol: ") + cas.locale + u": " + cas.isoCode,
2182 cas.expectedVariant, actualVarant);
2183 }
2184 }
2185
TestCurrencyUnit(void)2186 void NumberFormatTest::TestCurrencyUnit(void){
2187 UErrorCode ec = U_ZERO_ERROR;
2188 static const UChar USD[] = u"USD";
2189 static const char USD8[] = "USD";
2190 static const UChar BAD[] = u"???";
2191 static const UChar BAD2[] = u"??A";
2192 static const UChar XXX[] = u"XXX";
2193 static const char XXX8[] = "XXX";
2194 static const UChar XYZ[] = u"XYZ";
2195 static const char XYZ8[] = "XYZ";
2196 static const UChar INV[] = u"{$%";
2197 static const char INV8[] = "{$%";
2198 static const UChar ZZZ[] = u"zz";
2199 static const char ZZZ8[] = "zz";
2200 static const UChar JPY[] = u"JPY";
2201 static const char JPY8[] = "JPY";
2202 static const UChar jpy[] = u"jpy";
2203 static const char jpy8[] = "jpy";
2204
2205 UChar* EUR = (UChar*) malloc(6);
2206 EUR[0] = u'E';
2207 EUR[1] = u'U';
2208 EUR[2] = u'R';
2209 char* EUR8 = (char*) malloc(3);
2210 EUR8[0] = 'E';
2211 EUR8[1] = 'U';
2212 EUR8[2] = 'R';
2213
2214 CurrencyUnit cu(USD, ec);
2215 assertSuccess("CurrencyUnit", ec);
2216 assertEquals("getISOCurrency()", USD, cu.getISOCurrency());
2217 assertEquals("getSubtype()", USD8, cu.getSubtype());
2218
2219 // Test XYZ, a valid but non-standard currency.
2220 // Note: Country code XY is private-use, so XYZ should remain unallocated.
2221 CurrencyUnit extended(XYZ, ec);
2222 assertSuccess("non-standard", ec);
2223 assertEquals("non-standard", XYZ, extended.getISOCurrency());
2224 assertEquals("non-standard", XYZ8, extended.getSubtype());
2225
2226 CurrencyUnit inv(INV, ec);
2227 assertEquals("non-invariant", U_INVARIANT_CONVERSION_ERROR, ec);
2228 assertEquals("non-invariant", XXX, inv.getISOCurrency());
2229 ec = U_ZERO_ERROR;
2230
2231 CurrencyUnit zzz(ZZZ, ec);
2232 assertEquals("too short", U_ILLEGAL_ARGUMENT_ERROR, ec);
2233 assertEquals("too short", XXX, zzz.getISOCurrency());
2234 ec = U_ZERO_ERROR;
2235
2236 CurrencyUnit eur(EUR, ec);
2237 assertEquals("non-nul-terminated", u"EUR", eur.getISOCurrency());
2238 assertEquals("non-nul-terminated", "EUR", eur.getSubtype());
2239
2240 // Test StringPiece constructor
2241 CurrencyUnit cu8(USD8, ec);
2242 assertEquals("StringPiece constructor", USD, cu8.getISOCurrency());
2243
2244 CurrencyUnit inv8(INV8, ec);
2245 assertEquals("non-invariant 8", U_INVARIANT_CONVERSION_ERROR, ec);
2246 assertEquals("non-invariant 8", XXX, inv8.getISOCurrency());
2247 ec = U_ZERO_ERROR;
2248
2249 CurrencyUnit zzz8(ZZZ8, ec);
2250 assertEquals("too short 8", U_ILLEGAL_ARGUMENT_ERROR, ec);
2251 assertEquals("too short 8", XXX, zzz8.getISOCurrency());
2252 ec = U_ZERO_ERROR;
2253
2254 CurrencyUnit zzz8b({ZZZ8, 3}, ec);
2255 assertEquals("too short 8b", U_ILLEGAL_ARGUMENT_ERROR, ec);
2256 assertEquals("too short 8b", XXX, zzz8b.getISOCurrency());
2257 ec = U_ZERO_ERROR;
2258
2259 CurrencyUnit eur8({EUR8, 3}, ec);
2260 assertEquals("non-nul-terminated 8", u"EUR", eur8.getISOCurrency());
2261 assertEquals("non-nul-terminated 8", "EUR", eur8.getSubtype());
2262
2263 CurrencyUnit cu2(cu);
2264 if (!(cu2 == cu)){
2265 errln("CurrencyUnit copy constructed object should be same");
2266 }
2267
2268 CurrencyUnit * cu3 = cu.clone();
2269 if (!(*cu3 == cu)){
2270 errln("CurrencyUnit cloned object should be same");
2271 }
2272 CurrencyUnit bad(BAD, ec);
2273 assertSuccess("CurrencyUnit", ec);
2274 if (cu.getOffset() == bad.getOffset()) {
2275 errln("Indexes of different currencies should differ.");
2276 }
2277 CurrencyUnit bad2(BAD2, ec);
2278 assertSuccess("CurrencyUnit", ec);
2279 if (bad2.getOffset() != bad.getOffset()) {
2280 errln("Indexes of unrecognized currencies should be the same.");
2281 }
2282 if (bad == bad2) {
2283 errln("Different unrecognized currencies should not be equal.");
2284 }
2285 bad = bad2;
2286 if (bad != bad2) {
2287 errln("Currency unit assignment should be the same.");
2288 }
2289 delete cu3;
2290
2291 // Test default constructor
2292 CurrencyUnit def;
2293 assertEquals("Default currency", XXX, def.getISOCurrency());
2294 assertEquals("Default currency as subtype", XXX8, def.getSubtype());
2295
2296 // Test slicing
2297 MeasureUnit sliced1 = cu;
2298 MeasureUnit sliced2 = cu;
2299 MeasureUnit sliced3 = extended;
2300 assertEquals("Subtype after slicing 1", USD8, sliced1.getSubtype());
2301 assertEquals("Subtype after slicing 2", USD8, sliced2.getSubtype());
2302 assertEquals("Subtype after slicing 3", XYZ8, sliced3.getSubtype());
2303 CurrencyUnit restored1(sliced1, ec);
2304 CurrencyUnit restored2(sliced2, ec);
2305 CurrencyUnit restored3(sliced3, ec);
2306 assertSuccess("Restoring from MeasureUnit", ec);
2307 assertEquals("Subtype after restoring 1", USD8, restored1.getSubtype());
2308 assertEquals("Subtype after restoring 2", USD8, restored2.getSubtype());
2309 assertEquals("Subtype after restoring 3", XYZ8, restored3.getSubtype());
2310 assertEquals("ISO Code after restoring 1", USD, restored1.getISOCurrency());
2311 assertEquals("ISO Code after restoring 2", USD, restored2.getISOCurrency());
2312 assertEquals("ISO Code after restoring 3", XYZ, restored3.getISOCurrency());
2313
2314 // Test copy constructor failure
2315 LocalPointer<MeasureUnit> meter(MeasureUnit::createMeter(ec));
2316 assertSuccess("Creating meter", ec);
2317 CurrencyUnit failure(*meter, ec);
2318 assertEquals("Copying from meter should fail", ec, U_ILLEGAL_ARGUMENT_ERROR);
2319 assertEquals("Copying should not give uninitialized ISO code", u"", failure.getISOCurrency());
2320
2321 // Test equality
2322 ec = U_ZERO_ERROR;
2323 assertFalse("FAIL: USD == JPY", CurrencyUnit(USD, ec) == CurrencyUnit(JPY, ec));
2324 assertTrue("FAIL: USD != USD", CurrencyUnit(USD, ec) == CurrencyUnit(USD, ec));
2325 assertTrue("FAIL: JPY != jpy", CurrencyUnit(JPY, ec) == CurrencyUnit(jpy, ec));
2326 assertTrue("FAIL: jpy != JPY", CurrencyUnit(jpy, ec) == CurrencyUnit(JPY, ec));
2327
2328 // Test equality with system charset instances
2329 assertFalse("FAIL: USD8 == JPY8", CurrencyUnit(USD8, ec) == CurrencyUnit(JPY8, ec));
2330 assertTrue("FAIL: USD8 != USD8", CurrencyUnit(USD8, ec) == CurrencyUnit(USD8, ec));
2331 assertTrue("FAIL: JPY8 != jpy8", CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy8, ec));
2332 assertTrue("FAIL: jpy8 != JPY8", CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY8, ec));
2333
2334 // Test equality between UTF-16 and system charset instances
2335 assertTrue("FAIL: USD != USD8", CurrencyUnit(USD, ec) == CurrencyUnit(USD8, ec));
2336 assertTrue("FAIL: USD8 != USD", CurrencyUnit(USD8, ec) == CurrencyUnit(USD, ec));
2337 assertTrue("FAIL: JPY != jpy8", CurrencyUnit(JPY, ec) == CurrencyUnit(jpy8, ec));
2338 assertTrue("FAIL: JPY8 != jpy", CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy, ec));
2339 assertTrue("FAIL: jpy != JPY8", CurrencyUnit(jpy, ec) == CurrencyUnit(JPY8, ec));
2340 assertTrue("FAIL: jpy8 != JPY", CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY, ec));
2341
2342 free(EUR);
2343 free(EUR8);
2344 }
2345
TestCurrencyAmount(void)2346 void NumberFormatTest::TestCurrencyAmount(void){
2347 UErrorCode ec = U_ZERO_ERROR;
2348 static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
2349 CurrencyAmount ca(9, USD, ec);
2350 assertSuccess("CurrencyAmount", ec);
2351
2352 CurrencyAmount ca2(ca);
2353 if (!(ca2 == ca)){
2354 errln("CurrencyAmount copy constructed object should be same");
2355 }
2356
2357 ca2=ca;
2358 if (!(ca2 == ca)){
2359 errln("CurrencyAmount assigned object should be same");
2360 }
2361
2362 CurrencyAmount *ca3 = ca.clone();
2363 if (!(*ca3 == ca)){
2364 errln("CurrencyAmount cloned object should be same");
2365 }
2366 delete ca3;
2367 }
2368
TestSymbolsWithBadLocale(void)2369 void NumberFormatTest::TestSymbolsWithBadLocale(void) {
2370 Locale locDefault;
2371 static const char *badLocales[] = {
2372 // length < ULOC_FULLNAME_CAPACITY
2373 "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME",
2374
2375 // length > ULOC_FULLNAME_CAPACITY
2376 "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME"
2377 }; // expect U_USING_DEFAULT_WARNING for both
2378
2379 unsigned int i;
2380 for (i = 0; i < UPRV_LENGTHOF(badLocales); i++) {
2381 const char *localeName = badLocales[i];
2382 Locale locBad(localeName);
2383 assertTrue(WHERE, !locBad.isBogus());
2384 UErrorCode status = U_ZERO_ERROR;
2385 UnicodeString intlCurrencySymbol((UChar)0xa4);
2386
2387 intlCurrencySymbol.append((UChar)0xa4);
2388
2389 logln("Current locale is %s", Locale::getDefault().getName());
2390 Locale::setDefault(locBad, status);
2391 logln("Current locale is %s", Locale::getDefault().getName());
2392 DecimalFormatSymbols mySymbols(status);
2393 if (status != U_USING_DEFAULT_WARNING) {
2394 errln("DecimalFormatSymbols should return U_USING_DEFAULT_WARNING.");
2395 }
2396 if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
2397 errln("DecimalFormatSymbols does not have the right locale.", locBad.getName());
2398 }
2399 int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
2400 for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
2401 UnicodeString symbolString = mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum);
2402 logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ") + prettify(symbolString));
2403 if (symbolString.length() == 0
2404 && symbolEnum != (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
2405 && symbolEnum != (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol)
2406 {
2407 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
2408 }
2409 }
2410
2411 status = U_ZERO_ERROR;
2412 Locale::setDefault(locDefault, status);
2413 logln("Current locale is %s", Locale::getDefault().getName());
2414 }
2415 }
2416
2417 /**
2418 * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
2419 * behave the same, except for memory ownership semantics. (No
2420 * version of this test on Java, since Java has only one method.)
2421 */
TestAdoptDecimalFormatSymbols(void)2422 void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
2423 UErrorCode ec = U_ZERO_ERROR;
2424 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2425 if (U_FAILURE(ec)) {
2426 errcheckln(ec, "Fail: DecimalFormatSymbols constructor - %s", u_errorName(ec));
2427 delete sym;
2428 return;
2429 }
2430 UnicodeString pat(" #,##0.00");
2431 pat.insert(0, (UChar)0x00A4);
2432 DecimalFormat fmt(pat, sym, ec);
2433 if (U_FAILURE(ec)) {
2434 errln("Fail: DecimalFormat constructor");
2435 return;
2436 }
2437
2438 UnicodeString str;
2439 fmt.format(2350.75, str);
2440 if (str == "$ 2,350.75") {
2441 logln(str);
2442 } else {
2443 dataerrln("Fail: " + str + ", expected $ 2,350.75");
2444 }
2445
2446 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2447 if (U_FAILURE(ec)) {
2448 errln("Fail: DecimalFormatSymbols constructor");
2449 delete sym;
2450 return;
2451 }
2452 sym->setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2453 fmt.adoptDecimalFormatSymbols(sym);
2454
2455 str.truncate(0);
2456 fmt.format(2350.75, str);
2457 if (str == "Q 2,350.75") {
2458 logln(str);
2459 } else {
2460 dataerrln("Fail: adoptDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2461 }
2462
2463 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2464 if (U_FAILURE(ec)) {
2465 errln("Fail: DecimalFormatSymbols constructor");
2466 delete sym;
2467 return;
2468 }
2469 DecimalFormat fmt2(pat, sym, ec);
2470 if (U_FAILURE(ec)) {
2471 errln("Fail: DecimalFormat constructor");
2472 return;
2473 }
2474
2475 DecimalFormatSymbols sym2(Locale::getUS(), ec);
2476 if (U_FAILURE(ec)) {
2477 errln("Fail: DecimalFormatSymbols constructor");
2478 return;
2479 }
2480 sym2.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2481 fmt2.setDecimalFormatSymbols(sym2);
2482
2483 str.truncate(0);
2484 fmt2.format(2350.75, str);
2485 if (str == "Q 2,350.75") {
2486 logln(str);
2487 } else {
2488 dataerrln("Fail: setDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2489 }
2490 }
2491
TestPerMill()2492 void NumberFormatTest::TestPerMill() {
2493 UErrorCode ec = U_ZERO_ERROR;
2494 UnicodeString str;
2495 DecimalFormat fmt(ctou("###.###\\u2030"), ec);
2496 if (!assertSuccess("DecimalFormat ct", ec)) return;
2497 assertEquals("0.4857 x ###.###\\u2030",
2498 ctou("485.7\\u2030"), fmt.format(0.4857, str), true);
2499
2500 DecimalFormatSymbols sym(Locale::getUS(), ec);
2501 if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2502 return;
2503 }
2504 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
2505 DecimalFormat fmt2("", sym, ec);
2506 if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2507 return;
2508 }
2509 fmt2.applyLocalizedPattern("###.###m", ec);
2510 if (!assertSuccess("setup", ec)) return;
2511 str.truncate(0);
2512 assertEquals("0.4857 x ###.###m",
2513 "485.7m", fmt2.format(0.4857, str));
2514 }
2515
2516 /**
2517 * Generic test for patterns that should be legal/illegal.
2518 */
TestIllegalPatterns()2519 void NumberFormatTest::TestIllegalPatterns() {
2520 // Test cases:
2521 // Prefix with "-:" for illegal patterns
2522 // Prefix with "+:" for legal patterns
2523 const char* DATA[] = {
2524 // Unquoted special characters in the suffix are illegal
2525 "-:000.000|###",
2526 "+:000.000'|###'",
2527 0
2528 };
2529 for (int32_t i=0; DATA[i]; ++i) {
2530 const char* pat=DATA[i];
2531 UBool valid = (*pat) == '+';
2532 pat += 2;
2533 UErrorCode ec = U_ZERO_ERROR;
2534 DecimalFormat fmt(pat, ec); // locale doesn't matter here
2535 if (U_SUCCESS(ec) == valid) {
2536 logln("Ok: pattern \"%s\": %s",
2537 pat, u_errorName(ec));
2538 } else {
2539 errcheckln(ec, "FAIL: pattern \"%s\" should have %s; got %s",
2540 pat, (valid?"succeeded":"failed"),
2541 u_errorName(ec));
2542 }
2543 }
2544 }
2545
2546 //----------------------------------------------------------------------
2547
2548 static const char* KEYWORDS[] = {
2549 /*0*/ "ref=", // <reference pattern to parse numbers>
2550 /*1*/ "loc=", // <locale for formats>
2551 /*2*/ "f:", // <pattern or '-'> <number> <exp. string>
2552 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number>
2553 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string>
2554 /*5*/ "p:", // <pattern or '-'> <string> <exp. number>
2555 /*6*/ "perr:", // <pattern or '-'> <invalid string>
2556 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
2557 /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2558 0
2559 };
2560
2561 /**
2562 * Return an integer representing the next token from this
2563 * iterator. The integer will be an index into the given list, or
2564 * -1 if there are no more tokens, or -2 if the token is not on
2565 * the list.
2566 */
keywordIndex(const UnicodeString & tok)2567 static int32_t keywordIndex(const UnicodeString& tok) {
2568 for (int32_t i=0; KEYWORDS[i]!=0; ++i) {
2569 if (tok==KEYWORDS[i]) {
2570 return i;
2571 }
2572 }
2573 return -1;
2574 }
2575
2576 /**
2577 * Parse a CurrencyAmount using the given NumberFormat, with
2578 * the 'delim' character separating the number and the currency.
2579 */
parseCurrencyAmount(const UnicodeString & str,const NumberFormat & fmt,UChar delim,Formattable & result,UErrorCode & ec)2580 static void parseCurrencyAmount(const UnicodeString& str,
2581 const NumberFormat& fmt,
2582 UChar delim,
2583 Formattable& result,
2584 UErrorCode& ec) {
2585 UnicodeString num, cur;
2586 int32_t i = str.indexOf(delim);
2587 str.extractBetween(0, i, num);
2588 str.extractBetween(i+1, INT32_MAX, cur);
2589 Formattable n;
2590 fmt.parse(num, n, ec);
2591 result.adoptObject(new CurrencyAmount(n, cur.getTerminatedBuffer(), ec));
2592 }
2593
TestCases()2594 void NumberFormatTest::TestCases() {
2595 UErrorCode ec = U_ZERO_ERROR;
2596 TextFile reader("NumberFormatTestCases.txt", "UTF8", ec);
2597 if (U_FAILURE(ec)) {
2598 dataerrln("Couldn't open NumberFormatTestCases.txt");
2599 return;
2600 }
2601 TokenIterator tokens(&reader);
2602
2603 Locale loc("en", "US", "");
2604 DecimalFormat *ref = 0, *fmt = 0;
2605 MeasureFormat *mfmt = 0;
2606 UnicodeString pat, tok, mloc, str, out, where, currAmt;
2607 Formattable n;
2608
2609 for (;;) {
2610 ec = U_ZERO_ERROR;
2611 if (!tokens.next(tok, ec)) {
2612 break;
2613 }
2614 where = UnicodeString("(") + tokens.getLineNumber() + ") ";
2615 int32_t cmd = keywordIndex(tok);
2616 switch (cmd) {
2617 case 0:
2618 // ref= <reference pattern>
2619 if (!tokens.next(tok, ec)) goto error;
2620 delete ref;
2621 ref = new DecimalFormat(tok,
2622 new DecimalFormatSymbols(Locale::getUS(), ec), ec);
2623 if (U_FAILURE(ec)) {
2624 dataerrln("Error constructing DecimalFormat");
2625 goto error;
2626 }
2627 break;
2628 case 1:
2629 // loc= <locale>
2630 if (!tokens.next(tok, ec)) goto error;
2631 loc = Locale::createFromName(CharString().appendInvariantChars(tok, ec).data());
2632 break;
2633 case 2: // f:
2634 case 3: // fp:
2635 case 4: // rt:
2636 case 5: // p:
2637 if (!tokens.next(tok, ec)) goto error;
2638 if (tok != "-") {
2639 pat = tok;
2640 delete fmt;
2641 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc, ec), ec);
2642 if (U_FAILURE(ec)) {
2643 errln("FAIL: " + where + "Pattern \"" + pat + "\": " + u_errorName(ec));
2644 ec = U_ZERO_ERROR;
2645 if (!tokens.next(tok, ec)) goto error;
2646 if (!tokens.next(tok, ec)) goto error;
2647 if (cmd == 3) {
2648 if (!tokens.next(tok, ec)) goto error;
2649 }
2650 continue;
2651 }
2652 }
2653 if (cmd == 2 || cmd == 3 || cmd == 4) {
2654 // f: <pattern or '-'> <number> <exp. string>
2655 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
2656 // rt: <pattern or '-'> <number> <string>
2657 UnicodeString num;
2658 if (!tokens.next(num, ec)) goto error;
2659 if (!tokens.next(str, ec)) goto error;
2660 ref->parse(num, n, ec);
2661 assertSuccess("parse", ec);
2662 assertEquals(where + "\"" + pat + "\".format(" + num + ")",
2663 str, fmt->format(n, out.remove(), ec));
2664 assertSuccess("format", ec);
2665 if (cmd == 3) { // fp:
2666 if (!tokens.next(num, ec)) goto error;
2667 ref->parse(num, n, ec);
2668 assertSuccess("parse", ec);
2669 }
2670 if (cmd != 2) { // != f:
2671 Formattable m;
2672 fmt->parse(str, m, ec);
2673 assertSuccess("parse", ec);
2674 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2675 n, m);
2676 }
2677 }
2678 // p: <pattern or '-'> <string to parse> <exp. number>
2679 else {
2680 UnicodeString expstr;
2681 if (!tokens.next(str, ec)) goto error;
2682 if (!tokens.next(expstr, ec)) goto error;
2683 Formattable exp, n;
2684 ref->parse(expstr, exp, ec);
2685 assertSuccess("parse", ec);
2686 fmt->parse(str, n, ec);
2687 assertSuccess("parse", ec);
2688 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2689 exp, n);
2690 }
2691 break;
2692 case 8: // fpc:
2693 if (!tokens.next(tok, ec)) goto error;
2694 if (tok != "-") {
2695 mloc = tok;
2696 delete mfmt;
2697 mfmt = MeasureFormat::createCurrencyFormat(
2698 Locale::createFromName(
2699 CharString().appendInvariantChars(mloc, ec).data()), ec);
2700 if (U_FAILURE(ec)) {
2701 errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
2702 ec = U_ZERO_ERROR;
2703 if (!tokens.next(tok, ec)) goto error;
2704 if (!tokens.next(tok, ec)) goto error;
2705 if (!tokens.next(tok, ec)) goto error;
2706 continue;
2707 }
2708 } else if (mfmt == NULL) {
2709 errln("FAIL: " + where + "Loc \"" + mloc + "\": skip case using previous locale, no valid MeasureFormat");
2710 if (!tokens.next(tok, ec)) goto error;
2711 if (!tokens.next(tok, ec)) goto error;
2712 if (!tokens.next(tok, ec)) goto error;
2713 continue;
2714 }
2715 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2716 if (!tokens.next(currAmt, ec)) goto error;
2717 if (!tokens.next(str, ec)) goto error;
2718 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2719 if (assertSuccess("parseCurrencyAmount", ec)) {
2720 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
2721 str, mfmt->format(n, out.remove(), ec));
2722 assertSuccess("format", ec);
2723 }
2724 if (!tokens.next(currAmt, ec)) goto error;
2725 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2726 if (assertSuccess("parseCurrencyAmount", ec)) {
2727 Formattable m;
2728
2729 mfmt->parseObject(str, m, ec);
2730 if (assertSuccess("parseCurrency", ec)) {
2731 assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
2732 n, m);
2733 } else {
2734 errln("FAIL: source " + str);
2735 }
2736 }
2737 break;
2738 case 6:
2739 // perr: <pattern or '-'> <invalid string>
2740 errln("FAIL: Under construction");
2741 goto done;
2742 case 7: {
2743 // pat: <pattern> <exp. toPattern, or '-' or 'err'>
2744 UnicodeString testpat;
2745 UnicodeString exppat;
2746 if (!tokens.next(testpat, ec)) goto error;
2747 if (!tokens.next(exppat, ec)) goto error;
2748 UBool err = exppat == "err";
2749 UBool existingPat = FALSE;
2750 if (testpat == "-") {
2751 if (err) {
2752 errln("FAIL: " + where + "Invalid command \"pat: - err\"");
2753 continue;
2754 }
2755 existingPat = TRUE;
2756 testpat = pat;
2757 }
2758 if (exppat == "-") exppat = testpat;
2759 DecimalFormat* f = 0;
2760 UErrorCode ec2 = U_ZERO_ERROR;
2761 if (existingPat) {
2762 f = fmt;
2763 } else {
2764 f = new DecimalFormat(testpat, ec2);
2765 }
2766 if (U_SUCCESS(ec2)) {
2767 if (err) {
2768 errln("FAIL: " + where + "Invalid pattern \"" + testpat +
2769 "\" was accepted");
2770 } else {
2771 UnicodeString pat2;
2772 assertEquals(where + "\"" + testpat + "\".toPattern()",
2773 exppat, f->toPattern(pat2));
2774 }
2775 } else {
2776 if (err) {
2777 logln("Ok: " + where + "Invalid pattern \"" + testpat +
2778 "\" failed: " + u_errorName(ec2));
2779 } else {
2780 errln("FAIL: " + where + "Valid pattern \"" + testpat +
2781 "\" failed: " + u_errorName(ec2));
2782 }
2783 }
2784 if (!existingPat) delete f;
2785 } break;
2786 case -1:
2787 errln("FAIL: " + where + "Unknown command \"" + tok + "\"");
2788 goto done;
2789 }
2790 }
2791 goto done;
2792
2793 error:
2794 if (U_SUCCESS(ec)) {
2795 errln("FAIL: Unexpected EOF");
2796 } else {
2797 errcheckln(ec, "FAIL: " + where + "Unexpected " + u_errorName(ec));
2798 }
2799
2800 done:
2801 delete mfmt;
2802 delete fmt;
2803 delete ref;
2804 }
2805
2806
2807 //----------------------------------------------------------------------
2808 // Support methods
2809 //----------------------------------------------------------------------
2810
equalValue(const Formattable & a,const Formattable & b)2811 UBool NumberFormatTest::equalValue(const Formattable& a, const Formattable& b) {
2812 if (a.getType() == b.getType()) {
2813 return a == b;
2814 }
2815
2816 if (a.getType() == Formattable::kLong) {
2817 if (b.getType() == Formattable::kInt64) {
2818 return a.getLong() == b.getLong();
2819 } else if (b.getType() == Formattable::kDouble) {
2820 return (double) a.getLong() == b.getDouble(); // TODO check use of double instead of long
2821 }
2822 } else if (a.getType() == Formattable::kDouble) {
2823 if (b.getType() == Formattable::kLong) {
2824 return a.getDouble() == (double) b.getLong();
2825 } else if (b.getType() == Formattable::kInt64) {
2826 return a.getDouble() == (double)b.getInt64();
2827 }
2828 } else if (a.getType() == Formattable::kInt64) {
2829 if (b.getType() == Formattable::kLong) {
2830 return a.getInt64() == (int64_t)b.getLong();
2831 } else if (b.getType() == Formattable::kDouble) {
2832 return a.getInt64() == (int64_t)b.getDouble();
2833 }
2834 }
2835 return FALSE;
2836 }
2837
expect3(NumberFormat & fmt,const Formattable & n,const UnicodeString & str)2838 void NumberFormatTest::expect3(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2839 // Don't round-trip format test, since we explicitly do it
2840 expect_rbnf(fmt, n, str, FALSE);
2841 expect_rbnf(fmt, str, n);
2842 }
2843
expect2(NumberFormat & fmt,const Formattable & n,const UnicodeString & str)2844 void NumberFormatTest::expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2845 // Don't round-trip format test, since we explicitly do it
2846 expect(fmt, n, str, FALSE);
2847 expect(fmt, str, n);
2848 }
2849
expect2(NumberFormat * fmt,const Formattable & n,const UnicodeString & exp,UErrorCode status)2850 void NumberFormatTest::expect2(NumberFormat* fmt, const Formattable& n,
2851 const UnicodeString& exp,
2852 UErrorCode status) {
2853 if (fmt == NULL || U_FAILURE(status)) {
2854 dataerrln("FAIL: NumberFormat constructor");
2855 } else {
2856 expect2(*fmt, n, exp);
2857 }
2858 delete fmt;
2859 }
2860
expect(NumberFormat & fmt,const UnicodeString & str,const Formattable & n)2861 void NumberFormatTest::expect(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2862 UErrorCode status = U_ZERO_ERROR;
2863 Formattable num;
2864 fmt.parse(str, num, status);
2865 if (U_FAILURE(status)) {
2866 dataerrln(UnicodeString("FAIL: Parse failed for \"") + str + "\" - " + u_errorName(status));
2867 return;
2868 }
2869 UnicodeString pat;
2870 ((DecimalFormat*) &fmt)->toPattern(pat);
2871 if (equalValue(num, n)) {
2872 logln(UnicodeString("Ok \"") + str + "\" x " +
2873 pat + " = " +
2874 toString(num));
2875 } else {
2876 dataerrln(UnicodeString("FAIL \"") + str + "\" x " +
2877 pat + " = " +
2878 toString(num) + ", expected " + toString(n));
2879 }
2880 }
2881
expect_rbnf(NumberFormat & fmt,const UnicodeString & str,const Formattable & n)2882 void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2883 UErrorCode status = U_ZERO_ERROR;
2884 Formattable num;
2885 fmt.parse(str, num, status);
2886 if (U_FAILURE(status)) {
2887 errln(UnicodeString("FAIL: Parse failed for \"") + str + "\"");
2888 return;
2889 }
2890 if (equalValue(num, n)) {
2891 logln(UnicodeString("Ok \"") + str + " = " +
2892 toString(num));
2893 } else {
2894 errln(UnicodeString("FAIL \"") + str + " = " +
2895 toString(num) + ", expected " + toString(n));
2896 }
2897 }
2898
expect_rbnf(NumberFormat & fmt,const Formattable & n,const UnicodeString & exp,UBool rt)2899 void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const Formattable& n,
2900 const UnicodeString& exp, UBool rt) {
2901 UnicodeString saw;
2902 FieldPosition pos;
2903 UErrorCode status = U_ZERO_ERROR;
2904 fmt.format(n, saw, pos, status);
2905 CHECK(status, "NumberFormat::format");
2906 if (saw == exp) {
2907 logln(UnicodeString("Ok ") + toString(n) +
2908 " = \"" +
2909 escape(saw) + "\"");
2910 // We should be able to round-trip the formatted string =>
2911 // number => string (but not the other way around: number
2912 // => string => number2, might have number2 != number):
2913 if (rt) {
2914 Formattable n2;
2915 fmt.parse(exp, n2, status);
2916 if (U_FAILURE(status)) {
2917 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\"");
2918 return;
2919 }
2920 UnicodeString saw2;
2921 fmt.format(n2, saw2, pos, status);
2922 CHECK(status, "NumberFormat::format");
2923 if (saw2 != exp) {
2924 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2925 " => \"" + saw2 + "\"");
2926 }
2927 }
2928 } else {
2929 errln(UnicodeString("FAIL ") + toString(n) +
2930 " = \"" +
2931 escape(saw) + "\", expected \"" + exp + "\"");
2932 }
2933 }
2934
expect(NumberFormat & fmt,const Formattable & n,const UnicodeString & exp,UBool rt)2935 void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
2936 const UnicodeString& exp, UBool rt) {
2937 UnicodeString saw;
2938 FieldPosition pos;
2939 UErrorCode status = U_ZERO_ERROR;
2940 fmt.format(n, saw, pos, status);
2941 CHECK(status, "NumberFormat::format");
2942 UnicodeString pat;
2943 ((DecimalFormat*) &fmt)->toPattern(pat);
2944 if (saw == exp) {
2945 logln(UnicodeString("Ok ") + toString(n) + " x " +
2946 escape(pat) + " = \"" +
2947 escape(saw) + "\"");
2948 // We should be able to round-trip the formatted string =>
2949 // number => string (but not the other way around: number
2950 // => string => number2, might have number2 != number):
2951 if (rt) {
2952 Formattable n2;
2953 fmt.parse(exp, n2, status);
2954 if (U_FAILURE(status)) {
2955 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\" - " + u_errorName(status));
2956 return;
2957 }
2958 UnicodeString saw2;
2959 fmt.format(n2, saw2, pos, status);
2960 CHECK(status, "NumberFormat::format");
2961 if (saw2 != exp) {
2962 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2963 " => \"" + saw2 + "\"");
2964 }
2965 }
2966 } else {
2967 dataerrln(UnicodeString("FAIL ") + toString(n) + " x " +
2968 escape(pat) + " = \"" +
2969 escape(saw) + "\", expected \"" + exp + "\"");
2970 }
2971 }
2972
expect(NumberFormat * fmt,const Formattable & n,const UnicodeString & exp,UBool rt,UErrorCode status)2973 void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
2974 const UnicodeString& exp, UBool rt,
2975 UErrorCode status) {
2976 if (fmt == NULL || U_FAILURE(status)) {
2977 dataerrln("FAIL: NumberFormat constructor");
2978 } else {
2979 expect(*fmt, n, exp, rt);
2980 }
2981 delete fmt;
2982 }
2983
expectCurrency(NumberFormat & nf,const Locale & locale,double value,const UnicodeString & string)2984 void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
2985 double value, const UnicodeString& string) {
2986 UErrorCode ec = U_ZERO_ERROR;
2987 DecimalFormat& fmt = * (DecimalFormat*) &nf;
2988 const UChar DEFAULT_CURR[] = {45/*-*/,0};
2989 UChar curr[4];
2990 u_strcpy(curr, DEFAULT_CURR);
2991 if (*locale.getLanguage() != 0) {
2992 ucurr_forLocale(locale.getName(), curr, 4, &ec);
2993 assertSuccess("ucurr_forLocale", ec);
2994 fmt.setCurrency(curr, ec);
2995 assertSuccess("DecimalFormat::setCurrency", ec);
2996 fmt.setCurrency(curr); //Deprecated variant, for coverage only
2997 }
2998 UnicodeString s;
2999 fmt.format(value, s);
3000 s.findAndReplace((UChar32)0x00A0, (UChar32)0x0020);
3001
3002 // Default display of the number yields "1234.5599999999999"
3003 // instead of "1234.56". Use a formatter to fix this.
3004 NumberFormat* f =
3005 NumberFormat::createInstance(Locale::getUS(), ec);
3006 UnicodeString v;
3007 if (U_FAILURE(ec)) {
3008 // Oops; bad formatter. Use default op+= display.
3009 v = (UnicodeString)"" + value;
3010 } else {
3011 f->setMaximumFractionDigits(4);
3012 f->setGroupingUsed(FALSE);
3013 f->format(value, v);
3014 }
3015 delete f;
3016
3017 if (s == string) {
3018 logln((UnicodeString)"Ok: " + v + " x " + curr + " => " + prettify(s));
3019 } else {
3020 errln((UnicodeString)"FAIL: " + v + " x " + curr + " => " + prettify(s) +
3021 ", expected " + prettify(string));
3022 }
3023 }
3024
expectPat(DecimalFormat & fmt,const UnicodeString & exp)3025 void NumberFormatTest::expectPat(DecimalFormat& fmt, const UnicodeString& exp) {
3026 UnicodeString pat;
3027 fmt.toPattern(pat);
3028 if (pat == exp) {
3029 logln(UnicodeString("Ok \"") + pat + "\"");
3030 } else {
3031 errln(UnicodeString("FAIL \"") + pat + "\", expected \"" + exp + "\"");
3032 }
3033 }
3034
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos)3035 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3036 int32_t pos) {
3037 expectPad(fmt, pat, pos, 0, (UnicodeString)"");
3038 }
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos,int32_t width,UChar pad)3039 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3040 int32_t pos, int32_t width, UChar pad) {
3041 expectPad(fmt, pat, pos, width, UnicodeString(pad));
3042 }
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos,int32_t width,const UnicodeString & pad)3043 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3044 int32_t pos, int32_t width, const UnicodeString& pad) {
3045 int32_t apos = 0, awidth = 0;
3046 UnicodeString apadStr;
3047 UErrorCode status = U_ZERO_ERROR;
3048 fmt.applyPattern(pat, status);
3049 if (U_SUCCESS(status)) {
3050 apos = fmt.getPadPosition();
3051 awidth = fmt.getFormatWidth();
3052 apadStr=fmt.getPadCharacterString();
3053 } else {
3054 apos = -1;
3055 awidth = width;
3056 apadStr = pad;
3057 }
3058 if (apos == pos && awidth == width && apadStr == pad) {
3059 UnicodeString infoStr;
3060 if (pos == ILLEGAL) {
3061 infoStr = UnicodeString(" width=", "") + awidth + UnicodeString(" pad=", "") + apadStr;
3062 }
3063 logln(UnicodeString("Ok \"") + pat + "\" pos=" + apos + infoStr);
3064 } else {
3065 errln(UnicodeString("FAIL \"") + pat + "\" pos=" + apos +
3066 " width=" + awidth + " pad=" + apadStr +
3067 ", expected " + pos + " " + width + " " + pad);
3068 }
3069 }
3070
3071 // This test is flaky b/c the symbols for CNY and JPY are equivalent in this locale - FIXME
TestCompatibleCurrencies()3072 void NumberFormatTest::TestCompatibleCurrencies() {
3073 /*
3074 static const UChar JPY[] = {0x4A, 0x50, 0x59, 0};
3075 static const UChar CNY[] = {0x43, 0x4E, 0x59, 0};
3076 UErrorCode status = U_ZERO_ERROR;
3077 LocalPointer<NumberFormat> fmt(
3078 NumberFormat::createCurrencyInstance(Locale::getUS(), status));
3079 if (U_FAILURE(status)) {
3080 errln("Could not create number format instance.");
3081 return;
3082 }
3083 logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3084 expectParseCurrency(*fmt, JPY, 1235, "\\u00A51,235");
3085 logln("%s:%d - testing parse of fullwidth yen sign\n", __FILE__, __LINE__);
3086 expectParseCurrency(*fmt, JPY, 1235, "\\uFFE51,235");
3087 logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3088 expectParseCurrency(*fmt, CNY, 1235, "CN\\u00A51,235");
3089
3090 LocalPointer<NumberFormat> fmtTW(
3091 NumberFormat::createCurrencyInstance(Locale::getTaiwan(), status));
3092
3093 logln("%s:%d - testing parse of halfwidth yen sign in TW\n", __FILE__, __LINE__);
3094 expectParseCurrency(*fmtTW, CNY, 1235, "\\u00A51,235");
3095 logln("%s:%d - testing parse of fullwidth yen sign in TW\n", __FILE__, __LINE__);
3096 expectParseCurrency(*fmtTW, CNY, 1235, "\\uFFE51,235");
3097
3098 LocalPointer<NumberFormat> fmtJP(
3099 NumberFormat::createCurrencyInstance(Locale::getJapan(), status));
3100
3101 logln("%s:%d - testing parse of halfwidth yen sign in JP\n", __FILE__, __LINE__);
3102 expectParseCurrency(*fmtJP, JPY, 1235, "\\u00A51,235");
3103 logln("%s:%d - testing parse of fullwidth yen sign in JP\n", __FILE__, __LINE__);
3104 expectParseCurrency(*fmtJP, JPY, 1235, "\\uFFE51,235");
3105
3106 // more..
3107 */
3108 }
3109
expectParseCurrency(const NumberFormat & fmt,const UChar * currency,double amount,const char * text)3110 void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text) {
3111 ParsePosition ppos;
3112 UnicodeString utext = ctou(text);
3113 LocalPointer<CurrencyAmount> currencyAmount(fmt.parseCurrency(utext, ppos));
3114 if (!ppos.getIndex()) {
3115 errln(UnicodeString("Parse of ") + utext + " should have succeeded.");
3116 return;
3117 }
3118 UErrorCode status = U_ZERO_ERROR;
3119
3120 char theInfo[100];
3121 sprintf(theInfo, "For locale %s, string \"%s\", currency ",
3122 fmt.getLocale(ULOC_ACTUAL_LOCALE, status).getBaseName(),
3123 text);
3124 u_austrcpy(theInfo+uprv_strlen(theInfo), currency);
3125
3126 char theOperation[100];
3127
3128 uprv_strcpy(theOperation, theInfo);
3129 uprv_strcat(theOperation, ", check amount:");
3130 assertTrue(theOperation, amount == currencyAmount->getNumber().getDouble(status));
3131
3132 uprv_strcpy(theOperation, theInfo);
3133 uprv_strcat(theOperation, ", check currency:");
3134 assertEquals(theOperation, currency, currencyAmount->getISOCurrency());
3135 }
3136
3137
TestJB3832()3138 void NumberFormatTest::TestJB3832(){
3139 const char* localeID = "pt_PT@currency=PTE";
3140 Locale loc(localeID);
3141 UErrorCode status = U_ZERO_ERROR;
3142 UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0\\u200B")); // per cldrbug 7670
3143 UnicodeString s;
3144 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
3145 if(U_FAILURE(status)){
3146 dataerrln("Could not create currency formatter for locale %s - %s", localeID, u_errorName(status));
3147 return;
3148 }
3149 currencyFmt->format(1150.50, s);
3150 if(s!=expected){
3151 errln(UnicodeString("FAIL: Expected: ")+expected
3152 + UnicodeString(" Got: ") + s
3153 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
3154 }
3155 if (U_FAILURE(status)){
3156 errln("FAIL: Status %s", u_errorName(status));
3157 }
3158 delete currencyFmt;
3159 }
3160
TestHost()3161 void NumberFormatTest::TestHost()
3162 {
3163 #if U_PLATFORM_USES_ONLY_WIN32_API
3164 Win32NumberTest::testLocales(this);
3165 #endif
3166 Locale loc("en_US@compat=host");
3167 for (UNumberFormatStyle k = UNUM_DECIMAL;
3168 k < UNUM_FORMAT_STYLE_COUNT; k = (UNumberFormatStyle)(k+1)) {
3169 UErrorCode status = U_ZERO_ERROR;
3170 LocalPointer<NumberFormat> full(NumberFormat::createInstance(loc, k, status));
3171 if (!NumberFormat::isStyleSupported(k)) {
3172 if (status != U_UNSUPPORTED_ERROR) {
3173 errln("FAIL: expected style %d to be unsupported - %s",
3174 k, u_errorName(status));
3175 }
3176 continue;
3177 }
3178 if (full.isNull() || U_FAILURE(status)) {
3179 dataerrln("FAIL: Can't create number instance of style %d for host - %s",
3180 k, u_errorName(status));
3181 return;
3182 }
3183 UnicodeString result1;
3184 Formattable number(10.00);
3185 full->format(number, result1, status);
3186 if (U_FAILURE(status)) {
3187 errln("FAIL: Can't format for host");
3188 return;
3189 }
3190 Formattable formattable;
3191 full->parse(result1, formattable, status);
3192 if (U_FAILURE(status)) {
3193 errln("FAIL: Can't parse for host");
3194 return;
3195 }
3196 }
3197 }
3198
TestHostClone()3199 void NumberFormatTest::TestHostClone()
3200 {
3201 /*
3202 Verify that a cloned formatter gives the same results
3203 and is useable after the original has been deleted.
3204 */
3205 // This is mainly important on Windows.
3206 UErrorCode status = U_ZERO_ERROR;
3207 Locale loc("en_US@compat=host");
3208 UDate now = Calendar::getNow();
3209 NumberFormat *full = NumberFormat::createInstance(loc, status);
3210 if (full == NULL || U_FAILURE(status)) {
3211 dataerrln("FAIL: Can't create NumberFormat date instance - %s", u_errorName(status));
3212 return;
3213 }
3214 UnicodeString result1;
3215 full->format(now, result1, status);
3216 Format *fullClone = full->clone();
3217 delete full;
3218 full = NULL;
3219
3220 UnicodeString result2;
3221 fullClone->format(now, result2, status);
3222 if (U_FAILURE(status)) {
3223 errln("FAIL: format failure.");
3224 }
3225 if (result1 != result2) {
3226 errln("FAIL: Clone returned different result from non-clone.");
3227 }
3228 delete fullClone;
3229 }
3230
TestCurrencyFormat()3231 void NumberFormatTest::TestCurrencyFormat()
3232 {
3233 // This test is here to increase code coverage.
3234 UErrorCode status = U_ZERO_ERROR;
3235 MeasureFormat *cloneObj;
3236 UnicodeString str;
3237 Formattable toFormat, result;
3238 static const UChar ISO_CODE[4] = {0x0047, 0x0042, 0x0050, 0};
3239
3240 Locale saveDefaultLocale = Locale::getDefault();
3241 Locale::setDefault( Locale::getUK(), status );
3242 if (U_FAILURE(status)) {
3243 errln("couldn't set default Locale!");
3244 return;
3245 }
3246
3247 MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
3248 Locale::setDefault( saveDefaultLocale, status );
3249 if (U_FAILURE(status)){
3250 dataerrln("FAIL: Status %s", u_errorName(status));
3251 return;
3252 }
3253 cloneObj = measureObj->clone();
3254 if (cloneObj == NULL) {
3255 errln("Clone doesn't work");
3256 return;
3257 }
3258 toFormat.adoptObject(new CurrencyAmount(1234.56, ISO_CODE, status));
3259 measureObj->format(toFormat, str, status);
3260 measureObj->parseObject(str, result, status);
3261 if (U_FAILURE(status)){
3262 errln("FAIL: Status %s", u_errorName(status));
3263 }
3264 if (result != toFormat) {
3265 errln("measureObj does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3266 }
3267 status = U_ZERO_ERROR;
3268 str.truncate(0);
3269 cloneObj->format(toFormat, str, status);
3270 cloneObj->parseObject(str, result, status);
3271 if (U_FAILURE(status)){
3272 errln("FAIL: Status %s", u_errorName(status));
3273 }
3274 if (result != toFormat) {
3275 errln("Clone does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3276 }
3277 if (*measureObj != *cloneObj) {
3278 errln("Cloned object is not equal to the original object");
3279 }
3280 delete measureObj;
3281 delete cloneObj;
3282
3283 status = U_USELESS_COLLATOR_ERROR;
3284 if (MeasureFormat::createCurrencyFormat(status) != NULL) {
3285 errln("createCurrencyFormat should have returned NULL.");
3286 }
3287 }
3288
3289 /* Port of ICU4J rounding test. */
TestRounding()3290 void NumberFormatTest::TestRounding() {
3291 UErrorCode status = U_ZERO_ERROR;
3292 DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3293
3294 if (U_FAILURE(status)) {
3295 dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3296 return;
3297 }
3298
3299 int roundingIncrements[]={1, 2, 5, 20, 50, 100};
3300 int testValues[]={0, 300};
3301
3302 for (int j=0; j<2; j++) {
3303 for (int mode=DecimalFormat::kRoundUp;mode<DecimalFormat::kRoundHalfEven;mode++) {
3304 df->setRoundingMode((DecimalFormat::ERoundingMode)mode);
3305 for (int increment=0; increment<6; increment++) {
3306 double base=testValues[j];
3307 double rInc=roundingIncrements[increment];
3308 checkRounding(df, base, 20, rInc);
3309 rInc=1.000000000/rInc;
3310 checkRounding(df, base, 20, rInc);
3311 }
3312 }
3313 }
3314 delete df;
3315 }
3316
TestRoundingPattern()3317 void NumberFormatTest::TestRoundingPattern() {
3318 UErrorCode status = U_ZERO_ERROR;
3319 struct {
3320 UnicodeString pattern;
3321 double testCase;
3322 UnicodeString expected;
3323 } tests[] = {
3324 { (UnicodeString)"##0.65", 1.234, (UnicodeString)"1.30" },
3325 { (UnicodeString)"#50", 1230, (UnicodeString)"1250" }
3326 };
3327 int32_t numOfTests = UPRV_LENGTHOF(tests);
3328 UnicodeString result;
3329
3330 DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3331 if (U_FAILURE(status)) {
3332 dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3333 return;
3334 }
3335
3336 for (int32_t i = 0; i < numOfTests; i++) {
3337 result.remove();
3338
3339 df->applyPattern(tests[i].pattern, status);
3340 if (U_FAILURE(status)) {
3341 errln("Unable to apply pattern to decimal formatter. - %s", u_errorName(status));
3342 }
3343
3344 df->format(tests[i].testCase, result);
3345
3346 if (result != tests[i].expected) {
3347 errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
3348 }
3349 }
3350
3351 delete df;
3352 }
3353
checkRounding(DecimalFormat * df,double base,int iterations,double increment)3354 void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
3355 df->setRoundingIncrement(increment);
3356 double lastParsed=INT32_MIN; //Intger.MIN_VALUE
3357 for (int i=-iterations; i<=iterations;i++) {
3358 double iValue=base+(increment*(i*0.1));
3359 double smallIncrement=0.00000001;
3360 if (iValue!=0) {
3361 smallIncrement*=iValue;
3362 }
3363 //we not only test the value, but some values in a small range around it
3364 lastParsed=checkRound(df, iValue-smallIncrement, lastParsed);
3365 lastParsed=checkRound(df, iValue, lastParsed);
3366 lastParsed=checkRound(df, iValue+smallIncrement, lastParsed);
3367 }
3368 }
3369
checkRound(DecimalFormat * df,double iValue,double lastParsed)3370 double NumberFormatTest::checkRound(DecimalFormat* df, double iValue, double lastParsed) {
3371 UErrorCode status=U_ZERO_ERROR;
3372 UnicodeString formattedDecimal;
3373 double parsed;
3374 Formattable result;
3375 df->format(iValue, formattedDecimal, status);
3376
3377 if (U_FAILURE(status)) {
3378 errln("Error formatting number.");
3379 }
3380
3381 df->parse(formattedDecimal, result, status);
3382
3383 if (U_FAILURE(status)) {
3384 errln("Error parsing number.");
3385 }
3386
3387 parsed=result.getDouble();
3388
3389 if (lastParsed>parsed) {
3390 errln("Rounding wrong direction! %d > %d", lastParsed, parsed);
3391 }
3392
3393 return lastParsed;
3394 }
3395
TestNonpositiveMultiplier()3396 void NumberFormatTest::TestNonpositiveMultiplier() {
3397 UErrorCode status = U_ZERO_ERROR;
3398 DecimalFormatSymbols US(Locale::getUS(), status);
3399 CHECK(status, "DecimalFormatSymbols constructor");
3400 DecimalFormat df(UnicodeString("0"), US, status);
3401 CHECK(status, "DecimalFormat(0)");
3402
3403 // test zero multiplier
3404
3405 int32_t mult = df.getMultiplier();
3406 df.setMultiplier(0);
3407 if (df.getMultiplier() != mult) {
3408 errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
3409 }
3410
3411 // test negative multiplier
3412
3413 df.setMultiplier(-1);
3414 if (df.getMultiplier() != -1) {
3415 errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
3416 return;
3417 }
3418
3419 expect(df, "1122.123", -1122.123);
3420 expect(df, "-1122.123", 1122.123);
3421 expect(df, "1.2", -1.2);
3422 expect(df, "-1.2", 1.2);
3423
3424 // Note: the tests with the final parameter of FALSE will not round trip.
3425 // The initial numeric value will format correctly, after the multiplier.
3426 // Parsing the formatted text will be out-of-range for an int64, however.
3427 // The expect() function could be modified to detect this and fall back
3428 // to looking at the decimal parsed value, but it doesn't.
3429 expect(df, U_INT64_MIN, "9223372036854775808", FALSE);
3430 expect(df, U_INT64_MIN+1, "9223372036854775807");
3431 expect(df, (int64_t)-123, "123");
3432 expect(df, (int64_t)123, "-123");
3433 expect(df, U_INT64_MAX-1, "-9223372036854775806");
3434 expect(df, U_INT64_MAX, "-9223372036854775807");
3435
3436 df.setMultiplier(-2);
3437 expect(df, -(U_INT64_MIN/2)-1, "-9223372036854775806");
3438 expect(df, -(U_INT64_MIN/2), "-9223372036854775808");
3439 expect(df, -(U_INT64_MIN/2)+1, "-9223372036854775810", FALSE);
3440
3441 df.setMultiplier(-7);
3442 expect(df, -(U_INT64_MAX/7)-1, "9223372036854775814", FALSE);
3443 expect(df, -(U_INT64_MAX/7), "9223372036854775807");
3444 expect(df, -(U_INT64_MAX/7)+1, "9223372036854775800");
3445
3446 // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
3447 // (right now the big numbers get turned into doubles and lose tons of accuracy)
3448 //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
3449 //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
3450 //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
3451 //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
3452
3453 // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
3454 //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3455 //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3456 //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3457 //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3458 }
3459
3460 typedef struct {
3461 const char * stringToParse;
3462 int parsedPos;
3463 int errorIndex;
3464 UBool lenient;
3465 } TestSpaceParsingItem;
3466
3467 void
TestSpaceParsing()3468 NumberFormatTest::TestSpaceParsing() {
3469 // the data are:
3470 // the string to be parsed, parsed position, parsed error index
3471 const TestSpaceParsingItem DATA[] = {
3472 {"$124", 4, -1, FALSE},
3473 {"$124 $124", 4, -1, FALSE},
3474 {"$124 ", 4, -1, FALSE},
3475 {"$ 124 ", 0, 1, FALSE},
3476 {"$\\u00A0124 ", 5, -1, FALSE},
3477 {" $ 124 ", 0, 0, FALSE},
3478 {"124$", 0, 4, FALSE},
3479 {"124 $", 0, 3, FALSE},
3480 {"$124", 4, -1, TRUE},
3481 {"$124 $124", 4, -1, TRUE},
3482 {"$124 ", 4, -1, TRUE},
3483 {"$ 124 ", 5, -1, TRUE},
3484 {"$\\u00A0124 ", 5, -1, TRUE},
3485 {" $ 124 ", 6, -1, TRUE},
3486 {"124$", 4, -1, TRUE},
3487 {"124$", 4, -1, TRUE},
3488 {"124 $", 5, -1, TRUE},
3489 {"124 $", 5, -1, TRUE},
3490 };
3491 UErrorCode status = U_ZERO_ERROR;
3492 Locale locale("en_US");
3493 NumberFormat* foo = NumberFormat::createCurrencyInstance(locale, status);
3494
3495 if (U_FAILURE(status)) {
3496 delete foo;
3497 return;
3498 }
3499 for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3500 ParsePosition parsePosition(0);
3501 UnicodeString stringToBeParsed = ctou(DATA[i].stringToParse);
3502 int parsedPosition = DATA[i].parsedPos;
3503 int errorIndex = DATA[i].errorIndex;
3504 foo->setLenient(DATA[i].lenient);
3505 Formattable result;
3506 foo->parse(stringToBeParsed, result, parsePosition);
3507 logln("Parsing: " + stringToBeParsed);
3508 if (parsePosition.getIndex() != parsedPosition ||
3509 parsePosition.getErrorIndex() != errorIndex) {
3510 errln("FAILED parse " + stringToBeParsed + "; lenient: " + DATA[i].lenient + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
3511 }
3512 if (parsePosition.getErrorIndex() == -1 &&
3513 result.getType() == Formattable::kLong &&
3514 result.getLong() != 124) {
3515 errln("FAILED parse " + stringToBeParsed + "; wrong number, expect: 124, got " + result.getLong());
3516 }
3517 }
3518 delete foo;
3519 }
3520
3521 /**
3522 * Test using various numbering systems and numbering system keyword.
3523 */
3524 typedef struct {
3525 const char *localeName;
3526 double value;
3527 UBool isRBNF;
3528 const char *expectedResult;
3529 } TestNumberingSystemItem;
3530
TestNumberingSystems()3531 void NumberFormatTest::TestNumberingSystems() {
3532
3533 const TestNumberingSystemItem DATA[] = {
3534 { "en_US@numbers=thai", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" },
3535 { "en_US@numbers=hebr", 5678.0, TRUE, "\\u05D4\\u05F3\\u05EA\\u05E8\\u05E2\\u05F4\\u05D7" },
3536 { "en_US@numbers=arabext", 1234.567, FALSE, "\\u06F1\\u066c\\u06F2\\u06F3\\u06F4\\u066b\\u06F5\\u06F6\\u06F7" },
3537 { "ar_EG", 1234.567, FALSE, "\\u0661\\u066C\\u0662\\u0663\\u0664\\u066b\\u0665\\u0666\\u0667" },
3538 { "th_TH@numbers=traditional", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" }, // fall back to native per TR35
3539 { "ar_MA", 1234.567, FALSE, "1.234,567" },
3540 { "en_US@numbers=hanidec", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3541 { "ta_IN@numbers=native", 1234.567, FALSE, "\\u0BE7,\\u0BE8\\u0BE9\\u0BEA.\\u0BEB\\u0BEC\\u0BED" },
3542 { "ta_IN@numbers=traditional", 1235.0, TRUE, "\\u0BF2\\u0BE8\\u0BF1\\u0BE9\\u0BF0\\u0BEB" },
3543 { "ta_IN@numbers=finance", 1234.567, FALSE, "1,234.567" }, // fall back to default per TR35
3544 { "zh_TW@numbers=native", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3545 { "zh_TW@numbers=traditional", 1234.567, TRUE, "\\u4E00\\u5343\\u4E8C\\u767E\\u4E09\\u5341\\u56DB\\u9EDE\\u4E94\\u516D\\u4E03" },
3546 { "zh_TW@numbers=finance", 1234.567, TRUE, "\\u58F9\\u4EDF\\u8CB3\\u4F70\\u53C3\\u62FE\\u8086\\u9EDE\\u4F0D\\u9678\\u67D2" },
3547 { NULL, 0, FALSE, NULL }
3548 };
3549
3550 UErrorCode ec;
3551
3552 const TestNumberingSystemItem *item;
3553 for (item = DATA; item->localeName != NULL; item++) {
3554 ec = U_ZERO_ERROR;
3555 Locale loc = Locale::createFromName(item->localeName);
3556
3557 NumberFormat *origFmt = NumberFormat::createInstance(loc,ec);
3558 if (U_FAILURE(ec)) {
3559 dataerrln("FAIL: getInstance(%s) - %s", item->localeName, u_errorName(ec));
3560 continue;
3561 }
3562 // Clone to test ticket #10682
3563 NumberFormat *fmt = origFmt->clone();
3564 delete origFmt;
3565
3566
3567 if (item->isRBNF) {
3568 expect3(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3569 } else {
3570 expect2(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3571 }
3572 delete fmt;
3573 }
3574
3575
3576 // Test bogus keyword value
3577 ec = U_ZERO_ERROR;
3578 Locale loc4 = Locale::createFromName("en_US@numbers=foobar");
3579 NumberFormat* fmt4= NumberFormat::createInstance(loc4, ec);
3580 if ( ec != U_UNSUPPORTED_ERROR ) {
3581 errln("FAIL: getInstance(en_US@numbers=foobar) should have returned U_UNSUPPORTED_ERROR");
3582 delete fmt4;
3583 }
3584
3585 ec = U_ZERO_ERROR;
3586 NumberingSystem *ns = NumberingSystem::createInstance(ec);
3587 if (U_FAILURE(ec)) {
3588 dataerrln("FAIL: NumberingSystem::createInstance(ec); - %s", u_errorName(ec));
3589 }
3590
3591 if ( ns != NULL ) {
3592 ns->getDynamicClassID();
3593 ns->getStaticClassID();
3594 } else {
3595 errln("FAIL: getInstance() returned NULL.");
3596 }
3597
3598 NumberingSystem *ns1 = new NumberingSystem(*ns);
3599 if (ns1 == NULL) {
3600 errln("FAIL: NumberSystem copy constructor returned NULL.");
3601 }
3602
3603 delete ns1;
3604 delete ns;
3605
3606 }
3607
3608
3609 void
TestMultiCurrencySign()3610 NumberFormatTest::TestMultiCurrencySign() {
3611 const char* DATA[][6] = {
3612 // the fields in the following test are:
3613 // locale,
3614 // currency pattern (with negative pattern),
3615 // currency number to be formatted,
3616 // currency format using currency symbol name, such as "$" for USD,
3617 // currency format using currency ISO name, such as "USD",
3618 // currency format using plural name, such as "US dollars".
3619 // for US locale
3620 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1234.56", "$1,234.56", "USD\\u00A01,234.56", "US dollars\\u00A01,234.56"},
3621 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD\\u00A01,234.56", "-US dollars\\u00A01,234.56"},
3622 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD\\u00A01.00", "US dollars\\u00A01.00"},
3623 // for CHINA locale
3624 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\u00A51,234.56", "CNY\\u00A01,234.56", "\\u4EBA\\u6C11\\u5E01\\u00A01,234.56"},
3625 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\u00A51,234.56)", "(CNY\\u00A01,234.56)", "(\\u4EBA\\u6C11\\u5E01\\u00A01,234.56)"},
3626 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\u00A51.00", "CNY\\u00A01.00", "\\u4EBA\\u6C11\\u5E01\\u00A01.00"}
3627 };
3628
3629 const UChar doubleCurrencySign[] = {0xA4, 0xA4, 0};
3630 UnicodeString doubleCurrencyStr(doubleCurrencySign);
3631 const UChar tripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
3632 UnicodeString tripleCurrencyStr(tripleCurrencySign);
3633
3634 for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3635 const char* locale = DATA[i][0];
3636 UnicodeString pat = ctou(DATA[i][1]);
3637 double numberToBeFormat = atof(DATA[i][2]);
3638 UErrorCode status = U_ZERO_ERROR;
3639 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale(locale), status);
3640 if (U_FAILURE(status)) {
3641 delete sym;
3642 continue;
3643 }
3644 for (int j=1; j<=3; ++j) {
3645 // j represents the number of currency sign in the pattern.
3646 if (j == 2) {
3647 pat = pat.findAndReplace(ctou("\\u00A4"), doubleCurrencyStr);
3648 } else if (j == 3) {
3649 pat = pat.findAndReplace(ctou("\\u00A4\\u00A4"), tripleCurrencyStr);
3650 }
3651
3652 DecimalFormat* fmt = new DecimalFormat(pat, new DecimalFormatSymbols(*sym), status);
3653 if (U_FAILURE(status)) {
3654 errln("FAILED init DecimalFormat ");
3655 delete fmt;
3656 continue;
3657 }
3658 UnicodeString s;
3659 ((NumberFormat*) fmt)->format(numberToBeFormat, s);
3660 // DATA[i][3] is the currency format result using a
3661 // single currency sign.
3662 // DATA[i][4] is the currency format result using
3663 // double currency sign.
3664 // DATA[i][5] is the currency format result using
3665 // triple currency sign.
3666 // DATA[i][j+2] is the currency format result using
3667 // 'j' number of currency sign.
3668 UnicodeString currencyFormatResult = ctou(DATA[i][2+j]);
3669 if (s.compare(currencyFormatResult)) {
3670 errln("FAIL format: Expected " + currencyFormatResult + "; Got " + s);
3671 }
3672 // mix style parsing
3673 for (int k=3; k<=5; ++k) {
3674 // DATA[i][3] is the currency format result using a
3675 // single currency sign.
3676 // DATA[i][4] is the currency format result using
3677 // double currency sign.
3678 // DATA[i][5] is the currency format result using
3679 // triple currency sign.
3680 UnicodeString oneCurrencyFormat = ctou(DATA[i][k]);
3681 UErrorCode status = U_ZERO_ERROR;
3682 Formattable parseRes;
3683 fmt->parse(oneCurrencyFormat, parseRes, status);
3684 if (U_FAILURE(status) ||
3685 (parseRes.getType() == Formattable::kDouble &&
3686 parseRes.getDouble() != numberToBeFormat) ||
3687 (parseRes.getType() == Formattable::kLong &&
3688 parseRes.getLong() != numberToBeFormat)) {
3689 errln("FAILED parse " + oneCurrencyFormat + "; (i, j, k): " +
3690 i + ", " + j + ", " + k);
3691 }
3692 }
3693 delete fmt;
3694 }
3695 delete sym;
3696 }
3697 }
3698
3699
3700 void
TestCurrencyFormatForMixParsing()3701 NumberFormatTest::TestCurrencyFormatForMixParsing() {
3702 UErrorCode status = U_ZERO_ERROR;
3703 MeasureFormat* curFmt = MeasureFormat::createCurrencyFormat(Locale("en_US"), status);
3704 if (U_FAILURE(status)) {
3705 delete curFmt;
3706 return;
3707 }
3708 const char* formats[] = {
3709 "$1,234.56", // string to be parsed
3710 "USD1,234.56",
3711 "US dollars1,234.56",
3712 // "1,234.56 US dollars" // Fails in 62 because currency format is not compatible with pattern.
3713 };
3714 const CurrencyAmount* curramt = NULL;
3715 for (uint32_t i = 0; i < UPRV_LENGTHOF(formats); ++i) {
3716 UnicodeString stringToBeParsed = ctou(formats[i]);
3717 logln(UnicodeString("stringToBeParsed: ") + stringToBeParsed);
3718 Formattable result;
3719 UErrorCode status = U_ZERO_ERROR;
3720 curFmt->parseObject(stringToBeParsed, result, status);
3721 if (U_FAILURE(status)) {
3722 errln("FAIL: measure format parsing: '%s' ec: %s", formats[i], u_errorName(status));
3723 } else if (result.getType() != Formattable::kObject ||
3724 (curramt = dynamic_cast<const CurrencyAmount*>(result.getObject())) == NULL ||
3725 curramt->getNumber().getDouble() != 1234.56 ||
3726 UnicodeString(curramt->getISOCurrency()).compare(ISO_CURRENCY_USD)
3727 ) {
3728 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number ");
3729 if (curramt->getNumber().getDouble() != 1234.56) {
3730 errln((UnicodeString)"wong number, expect: 1234.56" + ", got: " + curramt->getNumber().getDouble());
3731 }
3732 if (curramt->getISOCurrency() != ISO_CURRENCY_USD) {
3733 errln((UnicodeString)"wong currency, expect: USD" + ", got: " + curramt->getISOCurrency());
3734 }
3735 }
3736 }
3737 delete curFmt;
3738 }
3739
3740
3741 /** Starting in ICU 62, strict mode is actually strict with currency formats. */
TestMismatchedCurrencyFormatFail()3742 void NumberFormatTest::TestMismatchedCurrencyFormatFail() {
3743 IcuTestErrorCode status(*this, "TestMismatchedCurrencyFormatFail");
3744 LocalPointer<DecimalFormat> df(
3745 dynamic_cast<DecimalFormat*>(DecimalFormat::createCurrencyInstance("en", status)), status);
3746 if (!assertSuccess("createCurrencyInstance() failed.", status, true, __FILE__, __LINE__)) {return;}
3747 UnicodeString pattern;
3748 assertEquals("Test assumes that currency sign is at the beginning",
3749 u"\u00A4#,##0.00",
3750 df->toPattern(pattern));
3751 // Should round-trip on the correct currency format:
3752 expect2(*df, 1.23, u"\u00A41.23");
3753 df->setCurrency(u"EUR", status);
3754 expect2(*df, 1.23, u"\u20AC1.23");
3755 // Should parse with currency in the wrong place in lenient mode
3756 df->setLenient(TRUE);
3757 expect(*df, u"1.23\u20AC", 1.23);
3758 expectParseCurrency(*df, u"EUR", 1.23, "1.23\\u20AC");
3759 // Should NOT parse with currency in the wrong place in STRICT mode
3760 df->setLenient(FALSE);
3761 {
3762 Formattable result;
3763 ErrorCode failStatus;
3764 df->parse(u"1.23\u20AC", result, failStatus);
3765 assertEquals("Should fail to parse", U_INVALID_FORMAT_ERROR, failStatus);
3766 }
3767 {
3768 ParsePosition ppos;
3769 df->parseCurrency(u"1.23\u20AC", ppos);
3770 assertEquals("Should fail to parse currency", 0, ppos.getIndex());
3771 }
3772 }
3773
3774
3775 void
TestDecimalFormatCurrencyParse()3776 NumberFormatTest::TestDecimalFormatCurrencyParse() {
3777 // Locale.US
3778 UErrorCode status = U_ZERO_ERROR;
3779 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale("en_US"), status);
3780 if (U_FAILURE(status)) {
3781 delete sym;
3782 return;
3783 }
3784 UnicodeString pat;
3785 UChar currency = 0x00A4;
3786 // "\xA4#,##0.00;-\xA4#,##0.00"
3787 pat.append(currency).append(currency).append(currency).append("#,##0.00;-").append(currency).append(currency).append(currency).append("#,##0.00");
3788 DecimalFormat* fmt = new DecimalFormat(pat, sym, status);
3789 if (U_FAILURE(status)) {
3790 delete fmt;
3791 errln("failed to new DecimalFormat in TestDecimalFormatCurrencyParse");
3792 return;
3793 }
3794 const char* DATA[][2] = {
3795 // the data are:
3796 // string to be parsed, the parsed result (number)
3797 {"$1.00", "1"},
3798 {"USD1.00", "1"},
3799 {"1.00 US dollar", "1"},
3800 {"$1,234.56", "1234.56"},
3801 {"USD1,234.56", "1234.56"},
3802 {"1,234.56 US dollar", "1234.56"},
3803 };
3804 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3805 fmt->setLenient(TRUE);
3806 for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3807 UnicodeString stringToBeParsed = ctou(DATA[i][0]);
3808 double parsedResult = atof(DATA[i][1]);
3809 UErrorCode status = U_ZERO_ERROR;
3810 Formattable result;
3811 fmt->parse(stringToBeParsed, result, status);
3812 logln((UnicodeString)"Input: " + stringToBeParsed + "; output: " + result.getDouble(status));
3813 if (U_FAILURE(status) ||
3814 (result.getType() == Formattable::kDouble &&
3815 result.getDouble() != parsedResult) ||
3816 (result.getType() == Formattable::kLong &&
3817 result.getLong() != parsedResult)) {
3818 errln((UnicodeString)"FAIL parse: Expected " + parsedResult);
3819 }
3820 }
3821 delete fmt;
3822 }
3823
3824
3825 void
TestCurrencyIsoPluralFormat()3826 NumberFormatTest::TestCurrencyIsoPluralFormat() {
3827 static const char* DATA[][6] = {
3828 // the data are:
3829 // locale,
3830 // currency amount to be formatted,
3831 // currency ISO code to be formatted,
3832 // format result using CURRENCYSTYLE,
3833 // format result using ISOCURRENCYSTYLE,
3834 // format result using PLURALCURRENCYSTYLE,
3835
3836 {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3837 {"en_US", "1234.56", "USD", "$1,234.56", "USD\\u00A01,234.56", "1,234.56 US dollars"},
3838 {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD\\u00A01,234.56", "-1,234.56 US dollars"},
3839 {"zh_CN", "1", "USD", "US$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7F8E\\u5143"},
3840 {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD\\u00A01,234.56", "1,234.56\\u00A0\\u7F8E\\u5143"},
3841 {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A01.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3842 {"zh_CN", "1234.56", "CNY", "\\u00A51,234.56", "CNY\\u00A01,234.56", "1,234.56\\u00A0\\u4EBA\\u6C11\\u5E01"},
3843 {"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3844 {"ru_RU", "2", "RUB", "2,00\\u00A0\\u20BD", "2,00\\u00A0RUB", "2,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3845 {"ru_RU", "5", "RUB", "5,00\\u00A0\\u20BD", "5,00\\u00A0RUB", "5,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3846 // test locale without currency information
3847 {"root", "-1.23", "USD", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"},
3848 // test choice format
3849 {"es_AR", "1", "INR", "INR\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"},
3850 };
3851 static const UNumberFormatStyle currencyStyles[] = {
3852 UNUM_CURRENCY,
3853 UNUM_CURRENCY_ISO,
3854 UNUM_CURRENCY_PLURAL
3855 };
3856
3857 for (int32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3858 const char* localeString = DATA[i][0];
3859 double numberToBeFormat = atof(DATA[i][1]);
3860 const char* currencyISOCode = DATA[i][2];
3861 logln(UnicodeString(u"Locale: ") + localeString + "; amount: " + numberToBeFormat);
3862 Locale locale(localeString);
3863 for (int32_t kIndex = 0; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3864 UNumberFormatStyle k = currencyStyles[kIndex];
3865 logln(UnicodeString(u"UNumberFormatStyle: ") + k);
3866 UErrorCode status = U_ZERO_ERROR;
3867 NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3868 if (U_FAILURE(status)) {
3869 delete numFmt;
3870 dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3871 continue;
3872 }
3873 UChar currencyCode[4];
3874 u_charsToUChars(currencyISOCode, currencyCode, 4);
3875 numFmt->setCurrency(currencyCode, status);
3876 if (U_FAILURE(status)) {
3877 delete numFmt;
3878 errln((UnicodeString)"can not set currency:" + currencyISOCode);
3879 continue;
3880 }
3881
3882 UnicodeString strBuf;
3883 numFmt->format(numberToBeFormat, strBuf);
3884 int resultDataIndex = 3 + kIndex;
3885 // DATA[i][resultDataIndex] is the currency format result
3886 // using 'k' currency style.
3887 UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
3888 if (strBuf.compare(formatResult)) {
3889 errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
3890 }
3891 // test parsing, and test parsing for all currency formats.
3892 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3893 numFmt->setLenient(TRUE);
3894 for (int j = 3; j < 6; ++j) {
3895 // DATA[i][3] is the currency format result using
3896 // CURRENCYSTYLE formatter.
3897 // DATA[i][4] is the currency format result using
3898 // ISOCURRENCYSTYLE formatter.
3899 // DATA[i][5] is the currency format result using
3900 // PLURALCURRENCYSTYLE formatter.
3901 UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
3902 UErrorCode status = U_ZERO_ERROR;
3903 Formattable parseResult;
3904 numFmt->parse(oneCurrencyFormatResult, parseResult, status);
3905 if (U_FAILURE(status) ||
3906 (parseResult.getType() == Formattable::kDouble &&
3907 parseResult.getDouble() != numberToBeFormat) ||
3908 (parseResult.getType() == Formattable::kLong &&
3909 parseResult.getLong() != numberToBeFormat)) {
3910 errln((UnicodeString)"FAIL: getCurrencyFormat of locale " +
3911 localeString + " failed roundtripping the number");
3912 if (parseResult.getType() == Formattable::kDouble) {
3913 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getDouble());
3914 } else {
3915 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getLong());
3916 }
3917 }
3918 }
3919 delete numFmt;
3920 }
3921 }
3922 }
3923
3924 void
TestCurrencyParsing()3925 NumberFormatTest::TestCurrencyParsing() {
3926 static const char* DATA[][6] = {
3927 // the data are:
3928 // locale,
3929 // currency amount to be formatted,
3930 // currency ISO code to be formatted,
3931 // format result using CURRENCYSTYLE,
3932 // format result using ISOCURRENCYSTYLE,
3933 // format result using PLURALCURRENCYSTYLE,
3934 {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3935 {"pa_IN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\u0a2f\\u0a42.\\u0a10\\u0a38. \\u0a21\\u0a3e\\u0a32\\u0a30"},
3936 {"es_AR", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 d\\u00f3lar estadounidense"},
3937 {"ar_EG", "1", "USD", "\\u0661\\u066b\\u0660\\u0660\\u00a0US$", "\\u0661\\u066b\\u0660\\u0660\\u00a0USD", "\\u0661\\u066b\\u0660\\u0660 \\u062f\\u0648\\u0644\\u0627\\u0631 \\u0623\\u0645\\u0631\\u064a\\u0643\\u064a"},
3938 {"fa_CA", "1", "USD", "\\u200e$\\u06f1\\u066b\\u06f0\\u06f0", "\\u200eUSD\\u06f1\\u066b\\u06f0\\u06f0", "\\u06f1\\u066b\\u06f0\\u06f0 \\u062f\\u0644\\u0627\\u0631 \\u0627\\u0645\\u0631\\u06cc\\u06a9\\u0627"},
3939 {"he_IL", "1", "USD", "\\u200f1.00\\u00a0$", "\\u200f1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
3940 {"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 ameri\\u010Dkih dolara"},
3941 {"id_ID", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 Dolar Amerika Serikat"},
3942 {"it_IT", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 dollari statunitensi"},
3943 {"ko_KR", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
3944 {"ja_JP", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7c73\\u30c9\\u30eb"},
3945 {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A001.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3946 {"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3947 {"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3948 {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1 \\u65E5\\u5713"},
3949 {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3950 // ICU 62 requires #parseCurrency() to recognize variants when parsing
3951 // {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3952 {"ru_RU", "1", "RUB", "1,00\\u00A0\\u00A0\\u20BD", "1,00\\u00A0\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"}
3953 };
3954 static const UNumberFormatStyle currencyStyles[] = {
3955 UNUM_CURRENCY,
3956 UNUM_CURRENCY_ISO,
3957 UNUM_CURRENCY_PLURAL
3958 };
3959 static const char* currencyStyleNames[] = {
3960 "UNUM_CURRENCY",
3961 "UNUM_CURRENCY_ISO",
3962 "UNUM_CURRENCY_PLURAL"
3963 };
3964
3965 #ifdef NUMFMTST_CACHE_DEBUG
3966 int deadloop = 0;
3967 for (;;) {
3968 printf("loop: %d\n", deadloop++);
3969 #endif
3970 for (uint32_t i=0; i< UPRV_LENGTHOF(DATA); ++i) { /* i = test case # - should be i=0*/
3971 for (int32_t kIndex = 2; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3972 UNumberFormatStyle k = currencyStyles[kIndex]; /* k = style */
3973 const char* localeString = DATA[i][0];
3974 double numberToBeFormat = atof(DATA[i][1]);
3975 const char* currencyISOCode = DATA[i][2];
3976 Locale locale(localeString);
3977 UErrorCode status = U_ZERO_ERROR;
3978 NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3979 logln("#%d NumberFormat(%s, %s) Currency=%s\n",
3980 i, localeString, currencyStyleNames[kIndex],
3981 currencyISOCode);
3982
3983 if (U_FAILURE(status)) {
3984 delete numFmt;
3985 dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3986 continue;
3987 }
3988 UChar currencyCode[4];
3989 u_charsToUChars(currencyISOCode, currencyCode, 4);
3990 numFmt->setCurrency(currencyCode, status);
3991 if (U_FAILURE(status)) {
3992 delete numFmt;
3993 errln((UnicodeString)"can not set currency:" + currencyISOCode);
3994 continue;
3995 }
3996
3997 UnicodeString strBuf;
3998 numFmt->format(numberToBeFormat, strBuf);
3999 int resultDataIndex = 3 + kIndex;
4000 // DATA[i][resultDataIndex] is the currency format result
4001 // using 'k' currency style.
4002 UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
4003 if (strBuf.compare(formatResult)) {
4004 errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
4005 }
4006 // test parsing, and test parsing for all currency formats.
4007 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
4008 numFmt->setLenient(TRUE);
4009 for (int j = 3; j < 6; ++j) {
4010 // DATA[i][3] is the currency format result using
4011 // CURRENCYSTYLE formatter.
4012 // DATA[i][4] is the currency format result using
4013 // ISOCURRENCYSTYLE formatter.
4014 // DATA[i][5] is the currency format result using
4015 // PLURALCURRENCYSTYLE formatter.
4016 UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
4017 UErrorCode status = U_ZERO_ERROR;
4018 Formattable parseResult;
4019 logln("parse(%s)", DATA[i][j]);
4020 numFmt->parse(oneCurrencyFormatResult, parseResult, status);
4021 if (U_FAILURE(status) ||
4022 (parseResult.getType() == Formattable::kDouble &&
4023 parseResult.getDouble() != numberToBeFormat) ||
4024 (parseResult.getType() == Formattable::kLong &&
4025 parseResult.getLong() != numberToBeFormat)) {
4026 errln((UnicodeString)"FAIL: NumberFormat(" + localeString +", " + currencyStyleNames[kIndex] +
4027 "), Currency="+currencyISOCode+", parse("+DATA[i][j]+") returned error " + (UnicodeString)u_errorName(status)+". Testcase: data[" + i + "][" + currencyStyleNames[j-3] +"="+j+"]");
4028 if (parseResult.getType() == Formattable::kDouble) {
4029 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (double): " +parseResult.getDouble());
4030 } else {
4031 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (long): " +parseResult.getLong());
4032 }
4033 errln((UnicodeString)" round-trip would be: " + strBuf);
4034 }
4035 }
4036 delete numFmt;
4037 }
4038 }
4039 #ifdef NUMFMTST_CACHE_DEBUG
4040 }
4041 #endif
4042 }
4043
4044
4045 void
TestParseCurrencyInUCurr()4046 NumberFormatTest::TestParseCurrencyInUCurr() {
4047 const char* DATA[] = {
4048 "1.00 US DOLLAR", // case in-sensitive
4049 "$1.00",
4050 "USD1.00",
4051 "usd1.00", // case in-sensitive: #13696
4052 "US dollar1.00",
4053 "US dollars1.00",
4054 "$1.00",
4055 "A$1.00",
4056 "ADP1.00",
4057 "ADP1.00",
4058 "AED1.00",
4059 "AED1.00",
4060 "AFA1.00",
4061 "AFA1.00",
4062 "AFN1.00",
4063 "ALL1.00",
4064 "AMD1.00",
4065 "ANG1.00",
4066 "AOA1.00",
4067 "AOK1.00",
4068 "AOK1.00",
4069 "AON1.00",
4070 "AON1.00",
4071 "AOR1.00",
4072 "AOR1.00",
4073 "ARS1.00",
4074 "ARA1.00",
4075 "ARA1.00",
4076 "ARP1.00",
4077 "ARP1.00",
4078 "ARS1.00",
4079 "ATS1.00",
4080 "ATS1.00",
4081 "AUD1.00",
4082 "AWG1.00",
4083 "AZM1.00",
4084 "AZM1.00",
4085 "AZN1.00",
4086 "Afghan Afghani (1927\\u20132002)1.00",
4087 "Afghan afghani (1927\\u20132002)1.00",
4088 "Afghan Afghani1.00",
4089 "Afghan Afghanis1.00",
4090 "Albanian Lek1.00",
4091 "Albanian lek1.00",
4092 "Albanian lek\\u00eb1.00",
4093 "Algerian Dinar1.00",
4094 "Algerian dinar1.00",
4095 "Algerian dinars1.00",
4096 "Andorran Peseta1.00",
4097 "Andorran peseta1.00",
4098 "Andorran pesetas1.00",
4099 "Angolan Kwanza (1977\\u20131991)1.00",
4100 "Angolan Readjusted Kwanza (1995\\u20131999)1.00",
4101 "Angolan Kwanza1.00",
4102 "Angolan New Kwanza (1990\\u20132000)1.00",
4103 "Angolan kwanza (1977\\u20131991)1.00",
4104 "Angolan readjusted kwanza (1995\\u20131999)1.00",
4105 "Angolan kwanza1.00",
4106 "Angolan kwanzas (1977\\u20131991)1.00",
4107 "Angolan readjusted kwanzas (1995\\u20131999)1.00",
4108 "Angolan kwanzas1.00",
4109 "Angolan new kwanza (1990\\u20132000)1.00",
4110 "Angolan new kwanzas (1990\\u20132000)1.00",
4111 "Argentine Austral1.00",
4112 "Argentine Peso (1983\\u20131985)1.00",
4113 "Argentine Peso1.00",
4114 "Argentine austral1.00",
4115 "Argentine australs1.00",
4116 "Argentine peso (1983\\u20131985)1.00",
4117 "Argentine peso1.00",
4118 "Argentine pesos (1983\\u20131985)1.00",
4119 "Argentine pesos1.00",
4120 "Armenian Dram1.00",
4121 "Armenian dram1.00",
4122 "Armenian drams1.00",
4123 "Aruban Florin1.00",
4124 "Aruban florin1.00",
4125 "Australian Dollar1.00",
4126 "Australian dollar1.00",
4127 "Australian dollars1.00",
4128 "Austrian Schilling1.00",
4129 "Austrian schilling1.00",
4130 "Austrian schillings1.00",
4131 "Azerbaijani Manat (1993\\u20132006)1.00",
4132 "Azerbaijani Manat1.00",
4133 "Azerbaijani manat (1993\\u20132006)1.00",
4134 "Azerbaijani manat1.00",
4135 "Azerbaijani manats (1993\\u20132006)1.00",
4136 "Azerbaijani manats1.00",
4137 "BAD1.00",
4138 "BAD1.00",
4139 "BAM1.00",
4140 "BBD1.00",
4141 "BDT1.00",
4142 "BEC1.00",
4143 "BEC1.00",
4144 "BEF1.00",
4145 "BEL1.00",
4146 "BEL1.00",
4147 "BGL1.00",
4148 "BGN1.00",
4149 "BGN1.00",
4150 "BHD1.00",
4151 "BIF1.00",
4152 "BMD1.00",
4153 "BND1.00",
4154 "BOB1.00",
4155 "BOP1.00",
4156 "BOP1.00",
4157 "BOV1.00",
4158 "BOV1.00",
4159 "BRB1.00",
4160 "BRB1.00",
4161 "BRC1.00",
4162 "BRC1.00",
4163 "BRE1.00",
4164 "BRE1.00",
4165 "BRL1.00",
4166 "BRN1.00",
4167 "BRN1.00",
4168 "BRR1.00",
4169 "BRR1.00",
4170 "BSD1.00",
4171 "BSD1.00",
4172 "BTN1.00",
4173 "BUK1.00",
4174 "BUK1.00",
4175 "BWP1.00",
4176 "BYB1.00",
4177 "BYB1.00",
4178 "BYR1.00",
4179 "BZD1.00",
4180 "Bahamian Dollar1.00",
4181 "Bahamian dollar1.00",
4182 "Bahamian dollars1.00",
4183 "Bahraini Dinar1.00",
4184 "Bahraini dinar1.00",
4185 "Bahraini dinars1.00",
4186 "Bangladeshi Taka1.00",
4187 "Bangladeshi taka1.00",
4188 "Bangladeshi takas1.00",
4189 "Barbadian Dollar1.00",
4190 "Barbadian dollar1.00",
4191 "Barbadian dollars1.00",
4192 "Belarusian Ruble (1994\\u20131999)1.00",
4193 "Belarusian Ruble1.00",
4194 "Belarusian ruble (1994\\u20131999)1.00",
4195 "Belarusian rubles (1994\\u20131999)1.00",
4196 "Belarusian ruble1.00",
4197 "Belarusian rubles1.00",
4198 "Belgian Franc (convertible)1.00",
4199 "Belgian Franc (financial)1.00",
4200 "Belgian Franc1.00",
4201 "Belgian franc (convertible)1.00",
4202 "Belgian franc (financial)1.00",
4203 "Belgian franc1.00",
4204 "Belgian francs (convertible)1.00",
4205 "Belgian francs (financial)1.00",
4206 "Belgian francs1.00",
4207 "Belize Dollar1.00",
4208 "Belize dollar1.00",
4209 "Belize dollars1.00",
4210 "Bermudan Dollar1.00",
4211 "Bermudan dollar1.00",
4212 "Bermudan dollars1.00",
4213 "Bhutanese Ngultrum1.00",
4214 "Bhutanese ngultrum1.00",
4215 "Bhutanese ngultrums1.00",
4216 "Bolivian Mvdol1.00",
4217 "Bolivian Peso1.00",
4218 "Bolivian mvdol1.00",
4219 "Bolivian mvdols1.00",
4220 "Bolivian peso1.00",
4221 "Bolivian pesos1.00",
4222 "Bolivian Boliviano1.00",
4223 "Bolivian Boliviano1.00",
4224 "Bolivian Bolivianos1.00",
4225 "Bosnia-Herzegovina Convertible Mark1.00",
4226 "Bosnia-Herzegovina Dinar (1992\\u20131994)1.00",
4227 "Bosnia-Herzegovina convertible mark1.00",
4228 "Bosnia-Herzegovina convertible marks1.00",
4229 "Bosnia-Herzegovina dinar (1992\\u20131994)1.00",
4230 "Bosnia-Herzegovina dinars (1992\\u20131994)1.00",
4231 "Botswanan Pula1.00",
4232 "Botswanan pula1.00",
4233 "Botswanan pulas1.00",
4234 "Brazilian New Cruzado (1989\\u20131990)1.00",
4235 "Brazilian Cruzado (1986\\u20131989)1.00",
4236 "Brazilian Cruzeiro (1990\\u20131993)1.00",
4237 "Brazilian New Cruzeiro (1967\\u20131986)1.00",
4238 "Brazilian Cruzeiro (1993\\u20131994)1.00",
4239 "Brazilian Real1.00",
4240 "Brazilian new cruzado (1989\\u20131990)1.00",
4241 "Brazilian new cruzados (1989\\u20131990)1.00",
4242 "Brazilian cruzado (1986\\u20131989)1.00",
4243 "Brazilian cruzados (1986\\u20131989)1.00",
4244 "Brazilian cruzeiro (1990\\u20131993)1.00",
4245 "Brazilian new cruzeiro (1967\\u20131986)1.00",
4246 "Brazilian cruzeiro (1993\\u20131994)1.00",
4247 "Brazilian cruzeiros (1990\\u20131993)1.00",
4248 "Brazilian new cruzeiros (1967\\u20131986)1.00",
4249 "Brazilian cruzeiros (1993\\u20131994)1.00",
4250 "Brazilian real1.00",
4251 "Brazilian reals1.00",
4252 "British Pound1.00",
4253 "British pound1.00",
4254 "British pounds1.00",
4255 "Brunei Dollar1.00",
4256 "Brunei dollar1.00",
4257 "Brunei dollars1.00",
4258 "Bulgarian Hard Lev1.00",
4259 "Bulgarian Lev1.00",
4260 "Bulgarian Leva1.00",
4261 "Bulgarian hard lev1.00",
4262 "Bulgarian hard leva1.00",
4263 "Bulgarian lev1.00",
4264 "Burmese Kyat1.00",
4265 "Burmese kyat1.00",
4266 "Burmese kyats1.00",
4267 "Burundian Franc1.00",
4268 "Burundian franc1.00",
4269 "Burundian francs1.00",
4270 "CA$1.00",
4271 "CAD1.00",
4272 "CDF1.00",
4273 "CDF1.00",
4274 "West African CFA Franc1.00",
4275 "Central African CFA Franc1.00",
4276 "West African CFA franc1.00",
4277 "Central African CFA franc1.00",
4278 "West African CFA francs1.00",
4279 "Central African CFA francs1.00",
4280 "CFP Franc1.00",
4281 "CFP franc1.00",
4282 "CFP francs1.00",
4283 "CFPF1.00",
4284 "CHE1.00",
4285 "CHE1.00",
4286 "CHF1.00",
4287 "CHW1.00",
4288 "CHW1.00",
4289 "CLF1.00",
4290 "CLF1.00",
4291 "CLP1.00",
4292 "CNY1.00",
4293 "COP1.00",
4294 "COU1.00",
4295 "COU1.00",
4296 "CRC1.00",
4297 "CSD1.00",
4298 "CSD1.00",
4299 "CSK1.00",
4300 "CSK1.00",
4301 "CUP1.00",
4302 "CUP1.00",
4303 "CVE1.00",
4304 "CYP1.00",
4305 "CZK1.00",
4306 "Cambodian Riel1.00",
4307 "Cambodian riel1.00",
4308 "Cambodian riels1.00",
4309 "Canadian Dollar1.00",
4310 "Canadian dollar1.00",
4311 "Canadian dollars1.00",
4312 "Cape Verdean Escudo1.00",
4313 "Cape Verdean escudo1.00",
4314 "Cape Verdean escudos1.00",
4315 "Cayman Islands Dollar1.00",
4316 "Cayman Islands dollar1.00",
4317 "Cayman Islands dollars1.00",
4318 "Chilean Peso1.00",
4319 "Chilean Unit of Account (UF)1.00",
4320 "Chilean peso1.00",
4321 "Chilean pesos1.00",
4322 "Chilean unit of account (UF)1.00",
4323 "Chilean units of account (UF)1.00",
4324 "Chinese Yuan1.00",
4325 "Chinese yuan1.00",
4326 "Colombian Peso1.00",
4327 "Colombian peso1.00",
4328 "Colombian pesos1.00",
4329 "Comorian Franc1.00",
4330 "Comorian franc1.00",
4331 "Comorian francs1.00",
4332 "Congolese Franc1.00",
4333 "Congolese franc1.00",
4334 "Congolese francs1.00",
4335 "Costa Rican Col\\u00f3n1.00",
4336 "Costa Rican col\\u00f3n1.00",
4337 "Costa Rican col\\u00f3ns1.00",
4338 "Croatian Dinar1.00",
4339 "Croatian Kuna1.00",
4340 "Croatian dinar1.00",
4341 "Croatian dinars1.00",
4342 "Croatian kuna1.00",
4343 "Croatian kunas1.00",
4344 "Cuban Peso1.00",
4345 "Cuban peso1.00",
4346 "Cuban pesos1.00",
4347 "Cypriot Pound1.00",
4348 "Cypriot pound1.00",
4349 "Cypriot pounds1.00",
4350 "Czech Koruna1.00",
4351 "Czech koruna1.00",
4352 "Czech korunas1.00",
4353 "Czechoslovak Hard Koruna1.00",
4354 "Czechoslovak hard koruna1.00",
4355 "Czechoslovak hard korunas1.00",
4356 "DDM1.00",
4357 "DDM1.00",
4358 "DEM1.00",
4359 "DEM1.00",
4360 "DJF1.00",
4361 "DKK1.00",
4362 "DOP1.00",
4363 "DZD1.00",
4364 "Danish Krone1.00",
4365 "Danish krone1.00",
4366 "Danish kroner1.00",
4367 "German Mark1.00",
4368 "German mark1.00",
4369 "German marks1.00",
4370 "Djiboutian Franc1.00",
4371 "Djiboutian franc1.00",
4372 "Djiboutian francs1.00",
4373 "Dominican Peso1.00",
4374 "Dominican peso1.00",
4375 "Dominican pesos1.00",
4376 "EC$1.00",
4377 "ECS1.00",
4378 "ECS1.00",
4379 "ECV1.00",
4380 "ECV1.00",
4381 "EEK1.00",
4382 "EEK1.00",
4383 "EGP1.00",
4384 "EGP1.00",
4385 "ERN1.00",
4386 "ERN1.00",
4387 "ESA1.00",
4388 "ESA1.00",
4389 "ESB1.00",
4390 "ESB1.00",
4391 "ESP1.00",
4392 "ETB1.00",
4393 "EUR1.00",
4394 "East Caribbean Dollar1.00",
4395 "East Caribbean dollar1.00",
4396 "East Caribbean dollars1.00",
4397 "East German Mark1.00",
4398 "East German mark1.00",
4399 "East German marks1.00",
4400 "Ecuadorian Sucre1.00",
4401 "Ecuadorian Unit of Constant Value1.00",
4402 "Ecuadorian sucre1.00",
4403 "Ecuadorian sucres1.00",
4404 "Ecuadorian unit of constant value1.00",
4405 "Ecuadorian units of constant value1.00",
4406 "Egyptian Pound1.00",
4407 "Egyptian pound1.00",
4408 "Egyptian pounds1.00",
4409 "Salvadoran Col\\u00f3n1.00",
4410 "Salvadoran col\\u00f3n1.00",
4411 "Salvadoran colones1.00",
4412 "Equatorial Guinean Ekwele1.00",
4413 "Equatorial Guinean ekwele1.00",
4414 "Eritrean Nakfa1.00",
4415 "Eritrean nakfa1.00",
4416 "Eritrean nakfas1.00",
4417 "Estonian Kroon1.00",
4418 "Estonian kroon1.00",
4419 "Estonian kroons1.00",
4420 "Ethiopian Birr1.00",
4421 "Ethiopian birr1.00",
4422 "Ethiopian birrs1.00",
4423 "Euro1.00",
4424 "European Composite Unit1.00",
4425 "European Currency Unit1.00",
4426 "European Monetary Unit1.00",
4427 "European Unit of Account (XBC)1.00",
4428 "European Unit of Account (XBD)1.00",
4429 "European composite unit1.00",
4430 "European composite units1.00",
4431 "European currency unit1.00",
4432 "European currency units1.00",
4433 "European monetary unit1.00",
4434 "European monetary units1.00",
4435 "European unit of account (XBC)1.00",
4436 "European unit of account (XBD)1.00",
4437 "European units of account (XBC)1.00",
4438 "European units of account (XBD)1.00",
4439 "FIM1.00",
4440 "FIM1.00",
4441 "FJD1.00",
4442 "FKP1.00",
4443 "FKP1.00",
4444 "FRF1.00",
4445 "FRF1.00",
4446 "Falkland Islands Pound1.00",
4447 "Falkland Islands pound1.00",
4448 "Falkland Islands pounds1.00",
4449 "Fijian Dollar1.00",
4450 "Fijian dollar1.00",
4451 "Fijian dollars1.00",
4452 "Finnish Markka1.00",
4453 "Finnish markka1.00",
4454 "Finnish markkas1.00",
4455 "CHF1.00",
4456 "French Franc1.00",
4457 "French Gold Franc1.00",
4458 "French UIC-Franc1.00",
4459 "French UIC-franc1.00",
4460 "French UIC-francs1.00",
4461 "French franc1.00",
4462 "French francs1.00",
4463 "French gold franc1.00",
4464 "French gold francs1.00",
4465 "GBP1.00",
4466 "GEK1.00",
4467 "GEK1.00",
4468 "GEL1.00",
4469 "GHC1.00",
4470 "GHC1.00",
4471 "GHS1.00",
4472 "GIP1.00",
4473 "GIP1.00",
4474 "GMD1.00",
4475 "GMD1.00",
4476 "GNF1.00",
4477 "GNS1.00",
4478 "GNS1.00",
4479 "GQE1.00",
4480 "GQE1.00",
4481 "GRD1.00",
4482 "GRD1.00",
4483 "GTQ1.00",
4484 "GWE1.00",
4485 "GWE1.00",
4486 "GWP1.00",
4487 "GWP1.00",
4488 "GYD1.00",
4489 "Gambian Dalasi1.00",
4490 "Gambian dalasi1.00",
4491 "Gambian dalasis1.00",
4492 "Georgian Kupon Larit1.00",
4493 "Georgian Lari1.00",
4494 "Georgian kupon larit1.00",
4495 "Georgian kupon larits1.00",
4496 "Georgian lari1.00",
4497 "Georgian laris1.00",
4498 "Ghanaian Cedi (1979\\u20132007)1.00",
4499 "Ghanaian Cedi1.00",
4500 "Ghanaian cedi (1979\\u20132007)1.00",
4501 "Ghanaian cedi1.00",
4502 "Ghanaian cedis (1979\\u20132007)1.00",
4503 "Ghanaian cedis1.00",
4504 "Gibraltar Pound1.00",
4505 "Gibraltar pound1.00",
4506 "Gibraltar pounds1.00",
4507 "Gold1.00",
4508 "Gold1.00",
4509 "Greek Drachma1.00",
4510 "Greek drachma1.00",
4511 "Greek drachmas1.00",
4512 "Guatemalan Quetzal1.00",
4513 "Guatemalan quetzal1.00",
4514 "Guatemalan quetzals1.00",
4515 "Guinean Franc1.00",
4516 "Guinean Syli1.00",
4517 "Guinean franc1.00",
4518 "Guinean francs1.00",
4519 "Guinean syli1.00",
4520 "Guinean sylis1.00",
4521 "Guinea-Bissau Peso1.00",
4522 "Guinea-Bissau peso1.00",
4523 "Guinea-Bissau pesos1.00",
4524 "Guyanaese Dollar1.00",
4525 "Guyanaese dollar1.00",
4526 "Guyanaese dollars1.00",
4527 "HK$1.00",
4528 "HKD1.00",
4529 "HNL1.00",
4530 "HRD1.00",
4531 "HRD1.00",
4532 "HRK1.00",
4533 "HRK1.00",
4534 "HTG1.00",
4535 "HTG1.00",
4536 "HUF1.00",
4537 "Haitian Gourde1.00",
4538 "Haitian gourde1.00",
4539 "Haitian gourdes1.00",
4540 "Honduran Lempira1.00",
4541 "Honduran lempira1.00",
4542 "Honduran lempiras1.00",
4543 "Hong Kong Dollar1.00",
4544 "Hong Kong dollar1.00",
4545 "Hong Kong dollars1.00",
4546 "Hungarian Forint1.00",
4547 "Hungarian forint1.00",
4548 "Hungarian forints1.00",
4549 "IDR1.00",
4550 "IEP1.00",
4551 "ILP1.00",
4552 "ILP1.00",
4553 "ILS1.00",
4554 "INR1.00",
4555 "IQD1.00",
4556 "IRR1.00",
4557 "ISK1.00",
4558 "ISK1.00",
4559 "ITL1.00",
4560 "Icelandic Kr\\u00f3na1.00",
4561 "Icelandic kr\\u00f3na1.00",
4562 "Icelandic kr\\u00f3nur1.00",
4563 "Indian Rupee1.00",
4564 "Indian rupee1.00",
4565 "Indian rupees1.00",
4566 "Indonesian Rupiah1.00",
4567 "Indonesian rupiah1.00",
4568 "Indonesian rupiahs1.00",
4569 "Iranian Rial1.00",
4570 "Iranian rial1.00",
4571 "Iranian rials1.00",
4572 "Iraqi Dinar1.00",
4573 "Iraqi dinar1.00",
4574 "Iraqi dinars1.00",
4575 "Irish Pound1.00",
4576 "Irish pound1.00",
4577 "Irish pounds1.00",
4578 "Israeli Pound1.00",
4579 "Israeli new shekel1.00",
4580 "Israeli pound1.00",
4581 "Israeli pounds1.00",
4582 "Italian Lira1.00",
4583 "Italian lira1.00",
4584 "Italian liras1.00",
4585 "JMD1.00",
4586 "JOD1.00",
4587 "JPY1.00",
4588 "Jamaican Dollar1.00",
4589 "Jamaican dollar1.00",
4590 "Jamaican dollars1.00",
4591 "Japanese Yen1.00",
4592 "Japanese yen1.00",
4593 "Jordanian Dinar1.00",
4594 "Jordanian dinar1.00",
4595 "Jordanian dinars1.00",
4596 "KES1.00",
4597 "KGS1.00",
4598 "KHR1.00",
4599 "KMF1.00",
4600 "KPW1.00",
4601 "KPW1.00",
4602 "KRW1.00",
4603 "KWD1.00",
4604 "KYD1.00",
4605 "KYD1.00",
4606 "KZT1.00",
4607 "Kazakhstani Tenge1.00",
4608 "Kazakhstani tenge1.00",
4609 "Kazakhstani tenges1.00",
4610 "Kenyan Shilling1.00",
4611 "Kenyan shilling1.00",
4612 "Kenyan shillings1.00",
4613 "Kuwaiti Dinar1.00",
4614 "Kuwaiti dinar1.00",
4615 "Kuwaiti dinars1.00",
4616 "Kyrgystani Som1.00",
4617 "Kyrgystani som1.00",
4618 "Kyrgystani soms1.00",
4619 "HNL1.00",
4620 "LAK1.00",
4621 "LAK1.00",
4622 "LBP1.00",
4623 "LKR1.00",
4624 "LRD1.00",
4625 "LRD1.00",
4626 "LSL1.00",
4627 "LTL1.00",
4628 "LTL1.00",
4629 "LTT1.00",
4630 "LTT1.00",
4631 "LUC1.00",
4632 "LUC1.00",
4633 "LUF1.00",
4634 "LUF1.00",
4635 "LUL1.00",
4636 "LUL1.00",
4637 "LVL1.00",
4638 "LVL1.00",
4639 "LVR1.00",
4640 "LVR1.00",
4641 "LYD1.00",
4642 "Laotian Kip1.00",
4643 "Laotian kip1.00",
4644 "Laotian kips1.00",
4645 "Latvian Lats1.00",
4646 "Latvian Ruble1.00",
4647 "Latvian lats1.00",
4648 "Latvian lati1.00",
4649 "Latvian ruble1.00",
4650 "Latvian rubles1.00",
4651 "Lebanese Pound1.00",
4652 "Lebanese pound1.00",
4653 "Lebanese pounds1.00",
4654 "Lesotho Loti1.00",
4655 "Lesotho loti1.00",
4656 "Lesotho lotis1.00",
4657 "Liberian Dollar1.00",
4658 "Liberian dollar1.00",
4659 "Liberian dollars1.00",
4660 "Libyan Dinar1.00",
4661 "Libyan dinar1.00",
4662 "Libyan dinars1.00",
4663 "Lithuanian Litas1.00",
4664 "Lithuanian Talonas1.00",
4665 "Lithuanian litas1.00",
4666 "Lithuanian litai1.00",
4667 "Lithuanian talonas1.00",
4668 "Lithuanian talonases1.00",
4669 "Luxembourgian Convertible Franc1.00",
4670 "Luxembourg Financial Franc1.00",
4671 "Luxembourgian Franc1.00",
4672 "Luxembourgian convertible franc1.00",
4673 "Luxembourgian convertible francs1.00",
4674 "Luxembourg financial franc1.00",
4675 "Luxembourg financial francs1.00",
4676 "Luxembourgian franc1.00",
4677 "Luxembourgian francs1.00",
4678 "MAD1.00",
4679 "MAD1.00",
4680 "MAF1.00",
4681 "MAF1.00",
4682 "MDL1.00",
4683 "MDL1.00",
4684 "MX$1.00",
4685 "MGA1.00",
4686 "MGA1.00",
4687 "MGF1.00",
4688 "MGF1.00",
4689 "MKD1.00",
4690 "MLF1.00",
4691 "MLF1.00",
4692 "MMK1.00",
4693 "MMK1.00",
4694 "MNT1.00",
4695 "MOP1.00",
4696 "MOP1.00",
4697 "MRO1.00",
4698 "MTL1.00",
4699 "MTP1.00",
4700 "MTP1.00",
4701 "MUR1.00",
4702 "MUR1.00",
4703 "MVR1.00",
4704 "MVR1.00",
4705 "MWK1.00",
4706 "MXN1.00",
4707 "MXP1.00",
4708 "MXP1.00",
4709 "MXV1.00",
4710 "MXV1.00",
4711 "MYR1.00",
4712 "MZE1.00",
4713 "MZE1.00",
4714 "MZM1.00",
4715 "MZN1.00",
4716 "Macanese Pataca1.00",
4717 "Macanese pataca1.00",
4718 "Macanese patacas1.00",
4719 "Macedonian Denar1.00",
4720 "Macedonian denar1.00",
4721 "Macedonian denari1.00",
4722 "Malagasy Ariaries1.00",
4723 "Malagasy Ariary1.00",
4724 "Malagasy Ariary1.00",
4725 "Malagasy Franc1.00",
4726 "Malagasy franc1.00",
4727 "Malagasy francs1.00",
4728 "Malawian Kwacha1.00",
4729 "Malawian Kwacha1.00",
4730 "Malawian Kwachas1.00",
4731 "Malaysian Ringgit1.00",
4732 "Malaysian ringgit1.00",
4733 "Malaysian ringgits1.00",
4734 "Maldivian Rufiyaa1.00",
4735 "Maldivian rufiyaa1.00",
4736 "Maldivian rufiyaas1.00",
4737 "Malian Franc1.00",
4738 "Malian franc1.00",
4739 "Malian francs1.00",
4740 "Maltese Lira1.00",
4741 "Maltese Pound1.00",
4742 "Maltese lira1.00",
4743 "Maltese lira1.00",
4744 "Maltese pound1.00",
4745 "Maltese pounds1.00",
4746 "Mauritanian Ouguiya1.00",
4747 "Mauritanian ouguiya1.00",
4748 "Mauritanian ouguiyas1.00",
4749 "Mauritian Rupee1.00",
4750 "Mauritian rupee1.00",
4751 "Mauritian rupees1.00",
4752 "Mexican Peso1.00",
4753 "Mexican Silver Peso (1861\\u20131992)1.00",
4754 "Mexican Investment Unit1.00",
4755 "Mexican peso1.00",
4756 "Mexican pesos1.00",
4757 "Mexican silver peso (1861\\u20131992)1.00",
4758 "Mexican silver pesos (1861\\u20131992)1.00",
4759 "Mexican investment unit1.00",
4760 "Mexican investment units1.00",
4761 "Moldovan Leu1.00",
4762 "Moldovan leu1.00",
4763 "Moldovan lei1.00",
4764 "Mongolian Tugrik1.00",
4765 "Mongolian tugrik1.00",
4766 "Mongolian tugriks1.00",
4767 "Moroccan Dirham1.00",
4768 "Moroccan Franc1.00",
4769 "Moroccan dirham1.00",
4770 "Moroccan dirhams1.00",
4771 "Moroccan franc1.00",
4772 "Moroccan francs1.00",
4773 "Mozambican Escudo1.00",
4774 "Mozambican Metical1.00",
4775 "Mozambican escudo1.00",
4776 "Mozambican escudos1.00",
4777 "Mozambican metical1.00",
4778 "Mozambican meticals1.00",
4779 "Myanmar Kyat1.00",
4780 "Myanmar kyat1.00",
4781 "Myanmar kyats1.00",
4782 "NAD1.00",
4783 "NGN1.00",
4784 "NIC1.00",
4785 "NIO1.00",
4786 "NIO1.00",
4787 "NLG1.00",
4788 "NLG1.00",
4789 "NOK1.00",
4790 "NPR1.00",
4791 "NT$1.00",
4792 "NZ$1.00",
4793 "NZD1.00",
4794 "Namibian Dollar1.00",
4795 "Namibian dollar1.00",
4796 "Namibian dollars1.00",
4797 "Nepalese Rupee1.00",
4798 "Nepalese rupee1.00",
4799 "Nepalese rupees1.00",
4800 "Netherlands Antillean Guilder1.00",
4801 "Netherlands Antillean guilder1.00",
4802 "Netherlands Antillean guilders1.00",
4803 "Dutch Guilder1.00",
4804 "Dutch guilder1.00",
4805 "Dutch guilders1.00",
4806 "Israeli New Shekel1.00",
4807 "Israeli New Shekels1.00",
4808 "New Zealand Dollar1.00",
4809 "New Zealand dollar1.00",
4810 "New Zealand dollars1.00",
4811 "Nicaraguan C\\u00f3rdoba1.00",
4812 "Nicaraguan C\\u00f3rdoba (1988\\u20131991)1.00",
4813 "Nicaraguan c\\u00f3rdoba1.00",
4814 "Nicaraguan c\\u00f3rdobas1.00",
4815 "Nicaraguan c\\u00f3rdoba (1988\\u20131991)1.00",
4816 "Nicaraguan c\\u00f3rdobas (1988\\u20131991)1.00",
4817 "Nigerian Naira1.00",
4818 "Nigerian naira1.00",
4819 "Nigerian nairas1.00",
4820 "North Korean Won1.00",
4821 "North Korean won1.00",
4822 "North Korean won1.00",
4823 "Norwegian Krone1.00",
4824 "Norwegian krone1.00",
4825 "Norwegian kroner1.00",
4826 "OMR1.00",
4827 "Mozambican Metical (1980\\u20132006)1.00",
4828 "Mozambican metical (1980\\u20132006)1.00",
4829 "Mozambican meticals (1980\\u20132006)1.00",
4830 "Romanian Lei (1952\\u20132006)1.00",
4831 "Romanian Leu (1952\\u20132006)1.00",
4832 "Romanian leu (1952\\u20132006)1.00",
4833 "Serbian Dinar (2002\\u20132006)1.00",
4834 "Serbian dinar (2002\\u20132006)1.00",
4835 "Serbian dinars (2002\\u20132006)1.00",
4836 "Sudanese Dinar (1992\\u20132007)1.00",
4837 "Sudanese Pound (1957\\u20131998)1.00",
4838 "Sudanese dinar (1992\\u20132007)1.00",
4839 "Sudanese dinars (1992\\u20132007)1.00",
4840 "Sudanese pound (1957\\u20131998)1.00",
4841 "Sudanese pounds (1957\\u20131998)1.00",
4842 "Turkish Lira (1922\\u20132005)1.00",
4843 "Turkish Lira (1922\\u20132005)1.00",
4844 "Omani Rial1.00",
4845 "Omani rial1.00",
4846 "Omani rials1.00",
4847 "PAB1.00",
4848 "PAB1.00",
4849 "PEI1.00",
4850 "PEI1.00",
4851 "PEN1.00",
4852 "PEN1.00",
4853 "PES1.00",
4854 "PES1.00",
4855 "PGK1.00",
4856 "PGK1.00",
4857 "PHP1.00",
4858 "PKR1.00",
4859 "PLN1.00",
4860 "PLZ1.00",
4861 "PLZ1.00",
4862 "PTE1.00",
4863 "PTE1.00",
4864 "PYG1.00",
4865 "Pakistani Rupee1.00",
4866 "Pakistani rupee1.00",
4867 "Pakistani rupees1.00",
4868 "Palladium1.00",
4869 "Palladium1.00",
4870 "Panamanian Balboa1.00",
4871 "Panamanian balboa1.00",
4872 "Panamanian balboas1.00",
4873 "Papua New Guinean Kina1.00",
4874 "Papua New Guinean kina1.00",
4875 "Papua New Guinean kina1.00",
4876 "Paraguayan Guarani1.00",
4877 "Paraguayan guarani1.00",
4878 "Paraguayan guaranis1.00",
4879 "Peruvian Inti1.00",
4880 "Peruvian Sol1.00",
4881 "Peruvian Sol (1863\\u20131965)1.00",
4882 "Peruvian inti1.00",
4883 "Peruvian intis1.00",
4884 "Peruvian sol1.00",
4885 "Peruvian soles1.00",
4886 "Peruvian sol (1863\\u20131965)1.00",
4887 "Peruvian soles (1863\\u20131965)1.00",
4888 "Philippine Piso1.00",
4889 "Philippine piso1.00",
4890 "Philippine pisos1.00",
4891 "Platinum1.00",
4892 "Platinum1.00",
4893 "Polish Zloty (1950\\u20131995)1.00",
4894 "Polish Zloty1.00",
4895 "Polish zlotys1.00",
4896 "Polish zloty (PLZ)1.00",
4897 "Polish zloty1.00",
4898 "Polish zlotys (PLZ)1.00",
4899 "Portuguese Escudo1.00",
4900 "Portuguese Guinea Escudo1.00",
4901 "Portuguese Guinea escudo1.00",
4902 "Portuguese Guinea escudos1.00",
4903 "Portuguese escudo1.00",
4904 "Portuguese escudos1.00",
4905 "GTQ1.00",
4906 "QAR1.00",
4907 "Qatari Rial1.00",
4908 "Qatari rial1.00",
4909 "Qatari rials1.00",
4910 "RHD1.00",
4911 "RHD1.00",
4912 "RINET Funds1.00",
4913 "RINET Funds1.00",
4914 "CN\\u00a51.00",
4915 "ROL1.00",
4916 "ROL1.00",
4917 "RON1.00",
4918 "RON1.00",
4919 "RSD1.00",
4920 "RSD1.00",
4921 "RUB1.00",
4922 "RUR1.00",
4923 "RUR1.00",
4924 "RWF1.00",
4925 "RWF1.00",
4926 "Rhodesian Dollar1.00",
4927 "Rhodesian dollar1.00",
4928 "Rhodesian dollars1.00",
4929 "Romanian Leu1.00",
4930 "Romanian lei1.00",
4931 "Romanian leu1.00",
4932 "Russian Ruble (1991\\u20131998)1.00",
4933 "Russian Ruble1.00",
4934 "Russian ruble (1991\\u20131998)1.00",
4935 "Russian ruble1.00",
4936 "Russian rubles (1991\\u20131998)1.00",
4937 "Russian rubles1.00",
4938 "Rwandan Franc1.00",
4939 "Rwandan franc1.00",
4940 "Rwandan francs1.00",
4941 "SAR1.00",
4942 "SBD1.00",
4943 "SCR1.00",
4944 "SDD1.00",
4945 "SDD1.00",
4946 "SDG1.00",
4947 "SDG1.00",
4948 "SDP1.00",
4949 "SDP1.00",
4950 "SEK1.00",
4951 "SGD1.00",
4952 "SHP1.00",
4953 "SHP1.00",
4954 "SIT1.00",
4955 "SIT1.00",
4956 "SKK1.00",
4957 "SLL1.00",
4958 "SLL1.00",
4959 "SOS1.00",
4960 "SRD1.00",
4961 "SRD1.00",
4962 "SRG1.00",
4963 "STD1.00",
4964 "SUR1.00",
4965 "SUR1.00",
4966 "SVC1.00",
4967 "SVC1.00",
4968 "SYP1.00",
4969 "SZL1.00",
4970 "St. Helena Pound1.00",
4971 "St. Helena pound1.00",
4972 "St. Helena pounds1.00",
4973 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra1.00",
4974 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra1.00",
4975 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras1.00",
4976 "Saudi Riyal1.00",
4977 "Saudi riyal1.00",
4978 "Saudi riyals1.00",
4979 "Serbian Dinar1.00",
4980 "Serbian dinar1.00",
4981 "Serbian dinars1.00",
4982 "Seychellois Rupee1.00",
4983 "Seychellois rupee1.00",
4984 "Seychellois rupees1.00",
4985 "Sierra Leonean Leone1.00",
4986 "Sierra Leonean leone1.00",
4987 "Sierra Leonean leones1.00",
4988 "Silver1.00",
4989 "Silver1.00",
4990 "Singapore Dollar1.00",
4991 "Singapore dollar1.00",
4992 "Singapore dollars1.00",
4993 "Slovak Koruna1.00",
4994 "Slovak koruna1.00",
4995 "Slovak korunas1.00",
4996 "Slovenian Tolar1.00",
4997 "Slovenian tolar1.00",
4998 "Slovenian tolars1.00",
4999 "Solomon Islands Dollar1.00",
5000 "Solomon Islands dollar1.00",
5001 "Solomon Islands dollars1.00",
5002 "Somali Shilling1.00",
5003 "Somali shilling1.00",
5004 "Somali shillings1.00",
5005 "South African Rand (financial)1.00",
5006 "South African Rand1.00",
5007 "South African rand (financial)1.00",
5008 "South African rand1.00",
5009 "South African rands (financial)1.00",
5010 "South African rand1.00",
5011 "South Korean Won1.00",
5012 "South Korean won1.00",
5013 "South Korean won1.00",
5014 "Soviet Rouble1.00",
5015 "Soviet rouble1.00",
5016 "Soviet roubles1.00",
5017 "Spanish Peseta (A account)1.00",
5018 "Spanish Peseta (convertible account)1.00",
5019 "Spanish Peseta1.00",
5020 "Spanish peseta (A account)1.00",
5021 "Spanish peseta (convertible account)1.00",
5022 "Spanish peseta1.00",
5023 "Spanish pesetas (A account)1.00",
5024 "Spanish pesetas (convertible account)1.00",
5025 "Spanish pesetas1.00",
5026 "Special Drawing Rights1.00",
5027 "Sri Lankan Rupee1.00",
5028 "Sri Lankan rupee1.00",
5029 "Sri Lankan rupees1.00",
5030 "Sudanese Pound1.00",
5031 "Sudanese pound1.00",
5032 "Sudanese pounds1.00",
5033 "Surinamese Dollar1.00",
5034 "Surinamese dollar1.00",
5035 "Surinamese dollars1.00",
5036 "Surinamese Guilder1.00",
5037 "Surinamese guilder1.00",
5038 "Surinamese guilders1.00",
5039 "Swazi Lilangeni1.00",
5040 "Swazi lilangeni1.00",
5041 "Swazi emalangeni1.00",
5042 "Swedish Krona1.00",
5043 "Swedish krona1.00",
5044 "Swedish kronor1.00",
5045 "Swiss Franc1.00",
5046 "Swiss franc1.00",
5047 "Swiss francs1.00",
5048 "Syrian Pound1.00",
5049 "Syrian pound1.00",
5050 "Syrian pounds1.00",
5051 "THB1.00",
5052 "TJR1.00",
5053 "TJR1.00",
5054 "TJS1.00",
5055 "TJS1.00",
5056 "TMM1.00",
5057 "TMM1.00",
5058 "TND1.00",
5059 "TND1.00",
5060 "TOP1.00",
5061 "TPE1.00",
5062 "TPE1.00",
5063 "TRL1.00",
5064 "TRY1.00",
5065 "TRY1.00",
5066 "TTD1.00",
5067 "TWD1.00",
5068 "TZS1.00",
5069 "New Taiwan Dollar1.00",
5070 "New Taiwan dollar1.00",
5071 "New Taiwan dollars1.00",
5072 "Tajikistani Ruble1.00",
5073 "Tajikistani Somoni1.00",
5074 "Tajikistani ruble1.00",
5075 "Tajikistani rubles1.00",
5076 "Tajikistani somoni1.00",
5077 "Tajikistani somonis1.00",
5078 "Tanzanian Shilling1.00",
5079 "Tanzanian shilling1.00",
5080 "Tanzanian shillings1.00",
5081 "Testing Currency Code1.00",
5082 "Testing Currency Code1.00",
5083 "Thai Baht1.00",
5084 "Thai baht1.00",
5085 "Thai baht1.00",
5086 "Timorese Escudo1.00",
5087 "Timorese escudo1.00",
5088 "Timorese escudos1.00",
5089 "Tongan Pa\\u02bbanga1.00",
5090 "Tongan pa\\u02bbanga1.00",
5091 "Tongan pa\\u02bbanga1.00",
5092 "Trinidad & Tobago Dollar1.00",
5093 "Trinidad & Tobago dollar1.00",
5094 "Trinidad & Tobago dollars1.00",
5095 "Tunisian Dinar1.00",
5096 "Tunisian dinar1.00",
5097 "Tunisian dinars1.00",
5098 "Turkish Lira1.00",
5099 "Turkish Lira1.00",
5100 "Turkish lira1.00",
5101 "Turkmenistani Manat1.00",
5102 "Turkmenistani manat1.00",
5103 "Turkmenistani manat1.00",
5104 "UAE dirham1.00",
5105 "UAE dirhams1.00",
5106 "UAH1.00",
5107 "UAK1.00",
5108 "UAK1.00",
5109 "UGS1.00",
5110 "UGS1.00",
5111 "UGX1.00",
5112 "US Dollar (Next day)1.00",
5113 "US Dollar (Same day)1.00",
5114 "US Dollar1.00",
5115 "US dollar (next day)1.00",
5116 "US dollar (same day)1.00",
5117 "US dollar1.00",
5118 "US dollars (next day)1.00",
5119 "US dollars (same day)1.00",
5120 "US dollars1.00",
5121 "USD1.00",
5122 "USN1.00",
5123 "USN1.00",
5124 "USS1.00",
5125 "USS1.00",
5126 "UYI1.00",
5127 "UYI1.00",
5128 "UYP1.00",
5129 "UYP1.00",
5130 "UYU1.00",
5131 "UZS1.00",
5132 "UZS1.00",
5133 "Ugandan Shilling (1966\\u20131987)1.00",
5134 "Ugandan Shilling1.00",
5135 "Ugandan shilling (1966\\u20131987)1.00",
5136 "Ugandan shilling1.00",
5137 "Ugandan shillings (1966\\u20131987)1.00",
5138 "Ugandan shillings1.00",
5139 "Ukrainian Hryvnia1.00",
5140 "Ukrainian Karbovanets1.00",
5141 "Ukrainian hryvnia1.00",
5142 "Ukrainian hryvnias1.00",
5143 "Ukrainian karbovanets1.00",
5144 "Ukrainian karbovantsiv1.00",
5145 "Colombian Real Value Unit1.00",
5146 "United Arab Emirates Dirham1.00",
5147 "Unknown Currency1.00",
5148 "Uruguayan Peso (1975\\u20131993)1.00",
5149 "Uruguayan Peso1.00",
5150 "Uruguayan Peso (Indexed Units)1.00",
5151 "Uruguayan peso (1975\\u20131993)1.00",
5152 "Uruguayan peso (indexed units)1.00",
5153 "Uruguayan peso1.00",
5154 "Uruguayan pesos (1975\\u20131993)1.00",
5155 "Uruguayan pesos (indexed units)1.00",
5156 "Uruguayan pesos1.00",
5157 "Uzbekistani Som1.00",
5158 "Uzbekistani som1.00",
5159 "Uzbekistani som1.00",
5160 "VEB1.00",
5161 "VEF1.00",
5162 "VND1.00",
5163 "VUV1.00",
5164 "Vanuatu Vatu1.00",
5165 "Vanuatu vatu1.00",
5166 "Vanuatu vatus1.00",
5167 "Venezuelan Bol\\u00edvar1.00",
5168 "Venezuelan Bol\\u00edvar (1871\\u20132008)1.00",
5169 "Venezuelan bol\\u00edvar1.00",
5170 "Venezuelan bol\\u00edvars1.00",
5171 "Venezuelan bol\\u00edvar (1871\\u20132008)1.00",
5172 "Venezuelan bol\\u00edvars (1871\\u20132008)1.00",
5173 "Vietnamese Dong1.00",
5174 "Vietnamese dong1.00",
5175 "Vietnamese dong1.00",
5176 "WIR Euro1.00",
5177 "WIR Franc1.00",
5178 "WIR euro1.00",
5179 "WIR euros1.00",
5180 "WIR franc1.00",
5181 "WIR francs1.00",
5182 "WST1.00",
5183 "WST1.00",
5184 "Samoan Tala1.00",
5185 "Samoan tala1.00",
5186 "Samoan tala1.00",
5187 "XAF1.00",
5188 "XAF1.00",
5189 "XAG1.00",
5190 "XAG1.00",
5191 "XAU1.00",
5192 "XAU1.00",
5193 "XBA1.00",
5194 "XBA1.00",
5195 "XBB1.00",
5196 "XBB1.00",
5197 "XBC1.00",
5198 "XBC1.00",
5199 "XBD1.00",
5200 "XBD1.00",
5201 "XCD1.00",
5202 "XDR1.00",
5203 "XDR1.00",
5204 "XEU1.00",
5205 "XEU1.00",
5206 "XFO1.00",
5207 "XFO1.00",
5208 "XFU1.00",
5209 "XFU1.00",
5210 "XOF1.00",
5211 "XOF1.00",
5212 "XPD1.00",
5213 "XPD1.00",
5214 "XPF1.00",
5215 "XPT1.00",
5216 "XPT1.00",
5217 "XRE1.00",
5218 "XRE1.00",
5219 "XTS1.00",
5220 "XTS1.00",
5221 "XXX1.00",
5222 "XXX1.00",
5223 "YDD1.00",
5224 "YDD1.00",
5225 "YER1.00",
5226 "YUD1.00",
5227 "YUD1.00",
5228 "YUM1.00",
5229 "YUM1.00",
5230 "YUN1.00",
5231 "YUN1.00",
5232 "Yemeni Dinar1.00",
5233 "Yemeni Rial1.00",
5234 "Yemeni dinar1.00",
5235 "Yemeni dinars1.00",
5236 "Yemeni rial1.00",
5237 "Yemeni rials1.00",
5238 "Yugoslavian Convertible Dinar (1990\\u20131992)1.00",
5239 "Yugoslavian Hard Dinar (1966\\u20131990)1.00",
5240 "Yugoslavian New Dinar (1994\\u20132002)1.00",
5241 "Yugoslavian convertible dinar (1990\\u20131992)1.00",
5242 "Yugoslavian convertible dinars (1990\\u20131992)1.00",
5243 "Yugoslavian hard dinar (1966\\u20131990)1.00",
5244 "Yugoslavian hard dinars (1966\\u20131990)1.00",
5245 "Yugoslavian new dinar (1994\\u20132002)1.00",
5246 "Yugoslavian new dinars (1994\\u20132002)1.00",
5247 "ZAL1.00",
5248 "ZAL1.00",
5249 "ZAR1.00",
5250 "ZMK1.00",
5251 "ZMK1.00",
5252 "ZRN1.00",
5253 "ZRN1.00",
5254 "ZRZ1.00",
5255 "ZRZ1.00",
5256 "ZWD1.00",
5257 "Zairean New Zaire (1993\\u20131998)1.00",
5258 "Zairean Zaire (1971\\u20131993)1.00",
5259 "Zairean new zaire (1993\\u20131998)1.00",
5260 "Zairean new zaires (1993\\u20131998)1.00",
5261 "Zairean zaire (1971\\u20131993)1.00",
5262 "Zairean zaires (1971\\u20131993)1.00",
5263 "Zambian Kwacha1.00",
5264 "Zambian kwacha1.00",
5265 "Zambian kwachas1.00",
5266 "Zimbabwean Dollar (1980\\u20132008)1.00",
5267 "Zimbabwean dollar (1980\\u20132008)1.00",
5268 "Zimbabwean dollars (1980\\u20132008)1.00",
5269 "euro1.00",
5270 "euros1.00",
5271 "Turkish lira (1922\\u20132005)1.00",
5272 "special drawing rights1.00",
5273 "Colombian real value unit1.00",
5274 "Colombian real value units1.00",
5275 "unknown currency1.00",
5276 "\\u00a31.00",
5277 "\\u00a51.00",
5278 "\\u20ab1.00",
5279 "\\u20aa1.00",
5280 "\\u20ac1.00",
5281 "\\u20b91.00",
5282 //
5283 // Following has extra text, should be parsed correctly too
5284 "$1.00 random",
5285 "USD1.00 random",
5286 "1.00 US dollar random",
5287 "1.00 US dollars random",
5288 "1.00 Afghan Afghani random",
5289 "1.00 Afghan Afghani random",
5290 "1.00 Afghan Afghanis (1927\\u20131992) random",
5291 "1.00 Afghan Afghanis random",
5292 "1.00 Albanian Lek random",
5293 "1.00 Albanian lek random",
5294 "1.00 Albanian lek\\u00eb random",
5295 "1.00 Algerian Dinar random",
5296 "1.00 Algerian dinar random",
5297 "1.00 Algerian dinars random",
5298 "1.00 Andorran Peseta random",
5299 "1.00 Andorran peseta random",
5300 "1.00 Andorran pesetas random",
5301 "1.00 Angolan Kwanza (1977\\u20131990) random",
5302 "1.00 Angolan Readjusted Kwanza (1995\\u20131999) random",
5303 "1.00 Angolan Kwanza random",
5304 "1.00 Angolan New Kwanza (1990\\u20132000) random",
5305 "1.00 Angolan kwanza (1977\\u20131991) random",
5306 "1.00 Angolan readjusted kwanza (1995\\u20131999) random",
5307 "1.00 Angolan kwanza random",
5308 "1.00 Angolan kwanzas (1977\\u20131991) random",
5309 "1.00 Angolan readjusted kwanzas (1995\\u20131999) random",
5310 "1.00 Angolan kwanzas random",
5311 "1.00 Angolan new kwanza (1990\\u20132000) random",
5312 "1.00 Angolan new kwanzas (1990\\u20132000) random",
5313 "1.00 Argentine Austral random",
5314 "1.00 Argentine Peso (1983\\u20131985) random",
5315 "1.00 Argentine Peso random",
5316 "1.00 Argentine austral random",
5317 "1.00 Argentine australs random",
5318 "1.00 Argentine peso (1983\\u20131985) random",
5319 "1.00 Argentine peso random",
5320 "1.00 Argentine pesos (1983\\u20131985) random",
5321 "1.00 Argentine pesos random",
5322 "1.00 Armenian Dram random",
5323 "1.00 Armenian dram random",
5324 "1.00 Armenian drams random",
5325 "1.00 Aruban Florin random",
5326 "1.00 Aruban florin random",
5327 "1.00 Australian Dollar random",
5328 "1.00 Australian dollar random",
5329 "1.00 Australian dollars random",
5330 "1.00 Austrian Schilling random",
5331 "1.00 Austrian schilling random",
5332 "1.00 Austrian schillings random",
5333 "1.00 Azerbaijani Manat (1993\\u20132006) random",
5334 "1.00 Azerbaijani Manat random",
5335 "1.00 Azerbaijani manat (1993\\u20132006) random",
5336 "1.00 Azerbaijani manat random",
5337 "1.00 Azerbaijani manats (1993\\u20132006) random",
5338 "1.00 Azerbaijani manats random",
5339 "1.00 Bahamian Dollar random",
5340 "1.00 Bahamian dollar random",
5341 "1.00 Bahamian dollars random",
5342 "1.00 Bahraini Dinar random",
5343 "1.00 Bahraini dinar random",
5344 "1.00 Bahraini dinars random",
5345 "1.00 Bangladeshi Taka random",
5346 "1.00 Bangladeshi taka random",
5347 "1.00 Bangladeshi takas random",
5348 "1.00 Barbadian Dollar random",
5349 "1.00 Barbadian dollar random",
5350 "1.00 Barbadian dollars random",
5351 "1.00 Belarusian Ruble (1994\\u20131999) random",
5352 "1.00 Belarusian Ruble random",
5353 "1.00 Belarusian ruble (1994\\u20131999) random",
5354 "1.00 Belarusian rubles (1994\\u20131999) random",
5355 "1.00 Belarusian ruble random",
5356 "1.00 Belarusian rubles random",
5357 "1.00 Belgian Franc (convertible) random",
5358 "1.00 Belgian Franc (financial) random",
5359 "1.00 Belgian Franc random",
5360 "1.00 Belgian franc (convertible) random",
5361 "1.00 Belgian franc (financial) random",
5362 "1.00 Belgian franc random",
5363 "1.00 Belgian francs (convertible) random",
5364 "1.00 Belgian francs (financial) random",
5365 "1.00 Belgian francs random",
5366 "1.00 Belize Dollar random",
5367 "1.00 Belize dollar random",
5368 "1.00 Belize dollars random",
5369 "1.00 Bermudan Dollar random",
5370 "1.00 Bermudan dollar random",
5371 "1.00 Bermudan dollars random",
5372 "1.00 Bhutanese Ngultrum random",
5373 "1.00 Bhutanese ngultrum random",
5374 "1.00 Bhutanese ngultrums random",
5375 "1.00 Bolivian Mvdol random",
5376 "1.00 Bolivian Peso random",
5377 "1.00 Bolivian mvdol random",
5378 "1.00 Bolivian mvdols random",
5379 "1.00 Bolivian peso random",
5380 "1.00 Bolivian pesos random",
5381 "1.00 Bolivian Boliviano random",
5382 "1.00 Bolivian Boliviano random",
5383 "1.00 Bolivian Bolivianos random",
5384 "1.00 Bosnia-Herzegovina Convertible Mark random",
5385 "1.00 Bosnia-Herzegovina Dinar (1992\\u20131994) random",
5386 "1.00 Bosnia-Herzegovina convertible mark random",
5387 "1.00 Bosnia-Herzegovina convertible marks random",
5388 "1.00 Bosnia-Herzegovina dinar (1992\\u20131994) random",
5389 "1.00 Bosnia-Herzegovina dinars (1992\\u20131994) random",
5390 "1.00 Botswanan Pula random",
5391 "1.00 Botswanan pula random",
5392 "1.00 Botswanan pulas random",
5393 "1.00 Brazilian New Cruzado (1989\\u20131990) random",
5394 "1.00 Brazilian Cruzado (1986\\u20131989) random",
5395 "1.00 Brazilian Cruzeiro (1990\\u20131993) random",
5396 "1.00 Brazilian New Cruzeiro (1967\\u20131986) random",
5397 "1.00 Brazilian Cruzeiro (1993\\u20131994) random",
5398 "1.00 Brazilian Real random",
5399 "1.00 Brazilian new cruzado (1989\\u20131990) random",
5400 "1.00 Brazilian new cruzados (1989\\u20131990) random",
5401 "1.00 Brazilian cruzado (1986\\u20131989) random",
5402 "1.00 Brazilian cruzados (1986\\u20131989) random",
5403 "1.00 Brazilian cruzeiro (1990\\u20131993) random",
5404 "1.00 Brazilian new cruzeiro (1967\\u20131986) random",
5405 "1.00 Brazilian cruzeiro (1993\\u20131994) random",
5406 "1.00 Brazilian cruzeiros (1990\\u20131993) random",
5407 "1.00 Brazilian new cruzeiros (1967\\u20131986) random",
5408 "1.00 Brazilian cruzeiros (1993\\u20131994) random",
5409 "1.00 Brazilian real random",
5410 "1.00 Brazilian reals random",
5411 "1.00 British Pound random",
5412 "1.00 British pound random",
5413 "1.00 British pounds random",
5414 "1.00 Brunei Dollar random",
5415 "1.00 Brunei dollar random",
5416 "1.00 Brunei dollars random",
5417 "1.00 Bulgarian Hard Lev random",
5418 "1.00 Bulgarian Lev random",
5419 "1.00 Bulgarian Leva random",
5420 "1.00 Bulgarian hard lev random",
5421 "1.00 Bulgarian hard leva random",
5422 "1.00 Bulgarian lev random",
5423 "1.00 Burmese Kyat random",
5424 "1.00 Burmese kyat random",
5425 "1.00 Burmese kyats random",
5426 "1.00 Burundian Franc random",
5427 "1.00 Burundian franc random",
5428 "1.00 Burundian francs random",
5429 "1.00 Cambodian Riel random",
5430 "1.00 Cambodian riel random",
5431 "1.00 Cambodian riels random",
5432 "1.00 Canadian Dollar random",
5433 "1.00 Canadian dollar random",
5434 "1.00 Canadian dollars random",
5435 "1.00 Cape Verdean Escudo random",
5436 "1.00 Cape Verdean escudo random",
5437 "1.00 Cape Verdean escudos random",
5438 "1.00 Cayman Islands Dollar random",
5439 "1.00 Cayman Islands dollar random",
5440 "1.00 Cayman Islands dollars random",
5441 "1.00 Chilean Peso random",
5442 "1.00 Chilean Unit of Account (UF) random",
5443 "1.00 Chilean peso random",
5444 "1.00 Chilean pesos random",
5445 "1.00 Chilean unit of account (UF) random",
5446 "1.00 Chilean units of account (UF) random",
5447 "1.00 Chinese Yuan random",
5448 "1.00 Chinese yuan random",
5449 "1.00 Colombian Peso random",
5450 "1.00 Colombian peso random",
5451 "1.00 Colombian pesos random",
5452 "1.00 Comorian Franc random",
5453 "1.00 Comorian franc random",
5454 "1.00 Comorian francs random",
5455 "1.00 Congolese Franc Congolais random",
5456 "1.00 Congolese franc Congolais random",
5457 "1.00 Congolese francs Congolais random",
5458 "1.00 Costa Rican Col\\u00f3n random",
5459 "1.00 Costa Rican col\\u00f3n random",
5460 "1.00 Costa Rican col\\u00f3ns random",
5461 "1.00 Croatian Dinar random",
5462 "1.00 Croatian Kuna random",
5463 "1.00 Croatian dinar random",
5464 "1.00 Croatian dinars random",
5465 "1.00 Croatian kuna random",
5466 "1.00 Croatian kunas random",
5467 "1.00 Cuban Peso random",
5468 "1.00 Cuban peso random",
5469 "1.00 Cuban pesos random",
5470 "1.00 Cypriot Pound random",
5471 "1.00 Cypriot pound random",
5472 "1.00 Cypriot pounds random",
5473 "1.00 Czech Koruna random",
5474 "1.00 Czech koruna random",
5475 "1.00 Czech korunas random",
5476 "1.00 Czechoslovak Hard Koruna random",
5477 "1.00 Czechoslovak hard koruna random",
5478 "1.00 Czechoslovak hard korunas random",
5479 "1.00 Danish Krone random",
5480 "1.00 Danish krone random",
5481 "1.00 Danish kroner random",
5482 "1.00 German Mark random",
5483 "1.00 German mark random",
5484 "1.00 German marks random",
5485 "1.00 Djiboutian Franc random",
5486 "1.00 Djiboutian franc random",
5487 "1.00 Djiboutian francs random",
5488 "1.00 Dominican Peso random",
5489 "1.00 Dominican peso random",
5490 "1.00 Dominican pesos random",
5491 "1.00 East Caribbean Dollar random",
5492 "1.00 East Caribbean dollar random",
5493 "1.00 East Caribbean dollars random",
5494 "1.00 East German Mark random",
5495 "1.00 East German mark random",
5496 "1.00 East German marks random",
5497 "1.00 Ecuadorian Sucre random",
5498 "1.00 Ecuadorian Unit of Constant Value random",
5499 "1.00 Ecuadorian sucre random",
5500 "1.00 Ecuadorian sucres random",
5501 "1.00 Ecuadorian unit of constant value random",
5502 "1.00 Ecuadorian units of constant value random",
5503 "1.00 Egyptian Pound random",
5504 "1.00 Egyptian pound random",
5505 "1.00 Egyptian pounds random",
5506 "1.00 Salvadoran Col\\u00f3n random",
5507 "1.00 Salvadoran col\\u00f3n random",
5508 "1.00 Salvadoran colones random",
5509 "1.00 Equatorial Guinean Ekwele random",
5510 "1.00 Equatorial Guinean ekwele random",
5511 "1.00 Eritrean Nakfa random",
5512 "1.00 Eritrean nakfa random",
5513 "1.00 Eritrean nakfas random",
5514 "1.00 Estonian Kroon random",
5515 "1.00 Estonian kroon random",
5516 "1.00 Estonian kroons random",
5517 "1.00 Ethiopian Birr random",
5518 "1.00 Ethiopian birr random",
5519 "1.00 Ethiopian birrs random",
5520 "1.00 European Composite Unit random",
5521 "1.00 European Currency Unit random",
5522 "1.00 European Monetary Unit random",
5523 "1.00 European Unit of Account (XBC) random",
5524 "1.00 European Unit of Account (XBD) random",
5525 "1.00 European composite unit random",
5526 "1.00 European composite units random",
5527 "1.00 European currency unit random",
5528 "1.00 European currency units random",
5529 "1.00 European monetary unit random",
5530 "1.00 European monetary units random",
5531 "1.00 European unit of account (XBC) random",
5532 "1.00 European unit of account (XBD) random",
5533 "1.00 European units of account (XBC) random",
5534 "1.00 European units of account (XBD) random",
5535 "1.00 Falkland Islands Pound random",
5536 "1.00 Falkland Islands pound random",
5537 "1.00 Falkland Islands pounds random",
5538 "1.00 Fijian Dollar random",
5539 "1.00 Fijian dollar random",
5540 "1.00 Fijian dollars random",
5541 "1.00 Finnish Markka random",
5542 "1.00 Finnish markka random",
5543 "1.00 Finnish markkas random",
5544 "1.00 French Franc random",
5545 "1.00 French Gold Franc random",
5546 "1.00 French UIC-Franc random",
5547 "1.00 French UIC-franc random",
5548 "1.00 French UIC-francs random",
5549 "1.00 French franc random",
5550 "1.00 French francs random",
5551 "1.00 French gold franc random",
5552 "1.00 French gold francs random",
5553 "1.00 Gambian Dalasi random",
5554 "1.00 Gambian dalasi random",
5555 "1.00 Gambian dalasis random",
5556 "1.00 Georgian Kupon Larit random",
5557 "1.00 Georgian Lari random",
5558 "1.00 Georgian kupon larit random",
5559 "1.00 Georgian kupon larits random",
5560 "1.00 Georgian lari random",
5561 "1.00 Georgian laris random",
5562 "1.00 Ghanaian Cedi (1979\\u20132007) random",
5563 "1.00 Ghanaian Cedi random",
5564 "1.00 Ghanaian cedi (1979\\u20132007) random",
5565 "1.00 Ghanaian cedi random",
5566 "1.00 Ghanaian cedis (1979\\u20132007) random",
5567 "1.00 Ghanaian cedis random",
5568 "1.00 Gibraltar Pound random",
5569 "1.00 Gibraltar pound random",
5570 "1.00 Gibraltar pounds random",
5571 "1.00 Gold random",
5572 "1.00 Gold random",
5573 "1.00 Greek Drachma random",
5574 "1.00 Greek drachma random",
5575 "1.00 Greek drachmas random",
5576 "1.00 Guatemalan Quetzal random",
5577 "1.00 Guatemalan quetzal random",
5578 "1.00 Guatemalan quetzals random",
5579 "1.00 Guinean Franc random",
5580 "1.00 Guinean Syli random",
5581 "1.00 Guinean franc random",
5582 "1.00 Guinean francs random",
5583 "1.00 Guinean syli random",
5584 "1.00 Guinean sylis random",
5585 "1.00 Guinea-Bissau Peso random",
5586 "1.00 Guinea-Bissau peso random",
5587 "1.00 Guinea-Bissau pesos random",
5588 "1.00 Guyanaese Dollar random",
5589 "1.00 Guyanaese dollar random",
5590 "1.00 Guyanaese dollars random",
5591 "1.00 Haitian Gourde random",
5592 "1.00 Haitian gourde random",
5593 "1.00 Haitian gourdes random",
5594 "1.00 Honduran Lempira random",
5595 "1.00 Honduran lempira random",
5596 "1.00 Honduran lempiras random",
5597 "1.00 Hong Kong Dollar random",
5598 "1.00 Hong Kong dollar random",
5599 "1.00 Hong Kong dollars random",
5600 "1.00 Hungarian Forint random",
5601 "1.00 Hungarian forint random",
5602 "1.00 Hungarian forints random",
5603 "1.00 Icelandic Kr\\u00f3na random",
5604 "1.00 Icelandic kr\\u00f3na random",
5605 "1.00 Icelandic kr\\u00f3nur random",
5606 "1.00 Indian Rupee random",
5607 "1.00 Indian rupee random",
5608 "1.00 Indian rupees random",
5609 "1.00 Indonesian Rupiah random",
5610 "1.00 Indonesian rupiah random",
5611 "1.00 Indonesian rupiahs random",
5612 "1.00 Iranian Rial random",
5613 "1.00 Iranian rial random",
5614 "1.00 Iranian rials random",
5615 "1.00 Iraqi Dinar random",
5616 "1.00 Iraqi dinar random",
5617 "1.00 Iraqi dinars random",
5618 "1.00 Irish Pound random",
5619 "1.00 Irish pound random",
5620 "1.00 Irish pounds random",
5621 "1.00 Israeli Pound random",
5622 "1.00 Israeli new shekel random",
5623 "1.00 Israeli pound random",
5624 "1.00 Israeli pounds random",
5625 "1.00 Italian Lira random",
5626 "1.00 Italian lira random",
5627 "1.00 Italian liras random",
5628 "1.00 Jamaican Dollar random",
5629 "1.00 Jamaican dollar random",
5630 "1.00 Jamaican dollars random",
5631 "1.00 Japanese Yen random",
5632 "1.00 Japanese yen random",
5633 "1.00 Jordanian Dinar random",
5634 "1.00 Jordanian dinar random",
5635 "1.00 Jordanian dinars random",
5636 "1.00 Kazakhstani Tenge random",
5637 "1.00 Kazakhstani tenge random",
5638 "1.00 Kazakhstani tenges random",
5639 "1.00 Kenyan Shilling random",
5640 "1.00 Kenyan shilling random",
5641 "1.00 Kenyan shillings random",
5642 "1.00 Kuwaiti Dinar random",
5643 "1.00 Kuwaiti dinar random",
5644 "1.00 Kuwaiti dinars random",
5645 "1.00 Kyrgystani Som random",
5646 "1.00 Kyrgystani som random",
5647 "1.00 Kyrgystani soms random",
5648 "1.00 Laotian Kip random",
5649 "1.00 Laotian kip random",
5650 "1.00 Laotian kips random",
5651 "1.00 Latvian Lats random",
5652 "1.00 Latvian Ruble random",
5653 "1.00 Latvian lats random",
5654 "1.00 Latvian lati random",
5655 "1.00 Latvian ruble random",
5656 "1.00 Latvian rubles random",
5657 "1.00 Lebanese Pound random",
5658 "1.00 Lebanese pound random",
5659 "1.00 Lebanese pounds random",
5660 "1.00 Lesotho Loti random",
5661 "1.00 Lesotho loti random",
5662 "1.00 Lesotho lotis random",
5663 "1.00 Liberian Dollar random",
5664 "1.00 Liberian dollar random",
5665 "1.00 Liberian dollars random",
5666 "1.00 Libyan Dinar random",
5667 "1.00 Libyan dinar random",
5668 "1.00 Libyan dinars random",
5669 "1.00 Lithuanian Litas random",
5670 "1.00 Lithuanian Talonas random",
5671 "1.00 Lithuanian litas random",
5672 "1.00 Lithuanian litai random",
5673 "1.00 Lithuanian talonas random",
5674 "1.00 Lithuanian talonases random",
5675 "1.00 Luxembourgian Convertible Franc random",
5676 "1.00 Luxembourg Financial Franc random",
5677 "1.00 Luxembourgian Franc random",
5678 "1.00 Luxembourgian convertible franc random",
5679 "1.00 Luxembourgian convertible francs random",
5680 "1.00 Luxembourg financial franc random",
5681 "1.00 Luxembourg financial francs random",
5682 "1.00 Luxembourgian franc random",
5683 "1.00 Luxembourgian francs random",
5684 "1.00 Macanese Pataca random",
5685 "1.00 Macanese pataca random",
5686 "1.00 Macanese patacas random",
5687 "1.00 Macedonian Denar random",
5688 "1.00 Macedonian denar random",
5689 "1.00 Macedonian denari random",
5690 "1.00 Malagasy Ariaries random",
5691 "1.00 Malagasy Ariary random",
5692 "1.00 Malagasy Ariary random",
5693 "1.00 Malagasy Franc random",
5694 "1.00 Malagasy franc random",
5695 "1.00 Malagasy francs random",
5696 "1.00 Malawian Kwacha random",
5697 "1.00 Malawian Kwacha random",
5698 "1.00 Malawian Kwachas random",
5699 "1.00 Malaysian Ringgit random",
5700 "1.00 Malaysian ringgit random",
5701 "1.00 Malaysian ringgits random",
5702 "1.00 Maldivian Rufiyaa random",
5703 "1.00 Maldivian rufiyaa random",
5704 "1.00 Maldivian rufiyaas random",
5705 "1.00 Malian Franc random",
5706 "1.00 Malian franc random",
5707 "1.00 Malian francs random",
5708 "1.00 Maltese Lira random",
5709 "1.00 Maltese Pound random",
5710 "1.00 Maltese lira random",
5711 "1.00 Maltese liras random",
5712 "1.00 Maltese pound random",
5713 "1.00 Maltese pounds random",
5714 "1.00 Mauritanian Ouguiya random",
5715 "1.00 Mauritanian ouguiya random",
5716 "1.00 Mauritanian ouguiyas random",
5717 "1.00 Mauritian Rupee random",
5718 "1.00 Mauritian rupee random",
5719 "1.00 Mauritian rupees random",
5720 "1.00 Mexican Peso random",
5721 "1.00 Mexican Silver Peso (1861\\u20131992) random",
5722 "1.00 Mexican Investment Unit random",
5723 "1.00 Mexican peso random",
5724 "1.00 Mexican pesos random",
5725 "1.00 Mexican silver peso (1861\\u20131992) random",
5726 "1.00 Mexican silver pesos (1861\\u20131992) random",
5727 "1.00 Mexican investment unit random",
5728 "1.00 Mexican investment units random",
5729 "1.00 Moldovan Leu random",
5730 "1.00 Moldovan leu random",
5731 "1.00 Moldovan lei random",
5732 "1.00 Mongolian Tugrik random",
5733 "1.00 Mongolian tugrik random",
5734 "1.00 Mongolian tugriks random",
5735 "1.00 Moroccan Dirham random",
5736 "1.00 Moroccan Franc random",
5737 "1.00 Moroccan dirham random",
5738 "1.00 Moroccan dirhams random",
5739 "1.00 Moroccan franc random",
5740 "1.00 Moroccan francs random",
5741 "1.00 Mozambican Escudo random",
5742 "1.00 Mozambican Metical random",
5743 "1.00 Mozambican escudo random",
5744 "1.00 Mozambican escudos random",
5745 "1.00 Mozambican metical random",
5746 "1.00 Mozambican meticals random",
5747 "1.00 Myanmar Kyat random",
5748 "1.00 Myanmar kyat random",
5749 "1.00 Myanmar kyats random",
5750 "1.00 Namibian Dollar random",
5751 "1.00 Namibian dollar random",
5752 "1.00 Namibian dollars random",
5753 "1.00 Nepalese Rupee random",
5754 "1.00 Nepalese rupee random",
5755 "1.00 Nepalese rupees random",
5756 "1.00 Netherlands Antillean Guilder random",
5757 "1.00 Netherlands Antillean guilder random",
5758 "1.00 Netherlands Antillean guilders random",
5759 "1.00 Dutch Guilder random",
5760 "1.00 Dutch guilder random",
5761 "1.00 Dutch guilders random",
5762 "1.00 Israeli New Shekel random",
5763 "1.00 Israeli new shekels random",
5764 "1.00 New Zealand Dollar random",
5765 "1.00 New Zealand dollar random",
5766 "1.00 New Zealand dollars random",
5767 "1.00 Nicaraguan C\\u00f3rdoba random",
5768 "1.00 Nicaraguan C\\u00f3rdoba (1988\\u20131991) random",
5769 "1.00 Nicaraguan c\\u00f3rdoba random",
5770 "1.00 Nicaraguan c\\u00f3rdoba random",
5771 "1.00 Nicaraguan c\\u00f3rdoba (1988\\u20131991) random",
5772 "1.00 Nicaraguan c\\u00f3rdobas (1988\\u20131991) random",
5773 "1.00 Nigerian Naira random",
5774 "1.00 Nigerian naira random",
5775 "1.00 Nigerian nairas random",
5776 "1.00 North Korean Won random",
5777 "1.00 North Korean won random",
5778 "1.00 North Korean won random",
5779 "1.00 Norwegian Krone random",
5780 "1.00 Norwegian krone random",
5781 "1.00 Norwegian kroner random",
5782 "1.00 Mozambican Metical (1980\\u20132006) random",
5783 "1.00 Mozambican metical (1980\\u20132006) random",
5784 "1.00 Mozambican meticals (1980\\u20132006) random",
5785 "1.00 Romanian Lei (1952\\u20132006) random",
5786 "1.00 Romanian Leu (1952\\u20132006) random",
5787 "1.00 Romanian leu (1952\\u20132006) random",
5788 "1.00 Serbian Dinar (2002\\u20132006) random",
5789 "1.00 Serbian dinar (2002\\u20132006) random",
5790 "1.00 Serbian dinars (2002\\u20132006) random",
5791 "1.00 Sudanese Dinar (1992\\u20132007) random",
5792 "1.00 Sudanese Pound (1957\\u20131998) random",
5793 "1.00 Sudanese dinar (1992\\u20132007) random",
5794 "1.00 Sudanese dinars (1992\\u20132007) random",
5795 "1.00 Sudanese pound (1957\\u20131998) random",
5796 "1.00 Sudanese pounds (1957\\u20131998) random",
5797 "1.00 Turkish Lira (1922\\u20132005) random",
5798 "1.00 Turkish Lira (1922\\u20132005) random",
5799 "1.00 Omani Rial random",
5800 "1.00 Omani rial random",
5801 "1.00 Omani rials random",
5802 "1.00 Pakistani Rupee random",
5803 "1.00 Pakistani rupee random",
5804 "1.00 Pakistani rupees random",
5805 "1.00 Palladium random",
5806 "1.00 Palladium random",
5807 "1.00 Panamanian Balboa random",
5808 "1.00 Panamanian balboa random",
5809 "1.00 Panamanian balboas random",
5810 "1.00 Papua New Guinean Kina random",
5811 "1.00 Papua New Guinean kina random",
5812 "1.00 Papua New Guinean kina random",
5813 "1.00 Paraguayan Guarani random",
5814 "1.00 Paraguayan guarani random",
5815 "1.00 Paraguayan guaranis random",
5816 "1.00 Peruvian Inti random",
5817 "1.00 Peruvian Sol random",
5818 "1.00 Peruvian Sol (1863\\u20131965) random",
5819 "1.00 Peruvian inti random",
5820 "1.00 Peruvian intis random",
5821 "1.00 Peruvian sol random",
5822 "1.00 Peruvian soles random",
5823 "1.00 Peruvian sol (1863\\u20131965) random",
5824 "1.00 Peruvian soles (1863\\u20131965) random",
5825 "1.00 Philippine Piso random",
5826 "1.00 Philippine piso random",
5827 "1.00 Philippine pisos random",
5828 "1.00 Platinum random",
5829 "1.00 Platinum random",
5830 "1.00 Polish Zloty (1950\\u20131995) random",
5831 "1.00 Polish Zloty random",
5832 "1.00 Polish zlotys random",
5833 "1.00 Polish zloty (PLZ) random",
5834 "1.00 Polish zloty random",
5835 "1.00 Polish zlotys (PLZ) random",
5836 "1.00 Portuguese Escudo random",
5837 "1.00 Portuguese Guinea Escudo random",
5838 "1.00 Portuguese Guinea escudo random",
5839 "1.00 Portuguese Guinea escudos random",
5840 "1.00 Portuguese escudo random",
5841 "1.00 Portuguese escudos random",
5842 "1.00 Qatari Rial random",
5843 "1.00 Qatari rial random",
5844 "1.00 Qatari rials random",
5845 "1.00 RINET Funds random",
5846 "1.00 RINET Funds random",
5847 "1.00 Rhodesian Dollar random",
5848 "1.00 Rhodesian dollar random",
5849 "1.00 Rhodesian dollars random",
5850 "1.00 Romanian Leu random",
5851 "1.00 Romanian lei random",
5852 "1.00 Romanian leu random",
5853 "1.00 Russian Ruble (1991\\u20131998) random",
5854 "1.00 Russian Ruble random",
5855 "1.00 Russian ruble (1991\\u20131998) random",
5856 "1.00 Russian ruble random",
5857 "1.00 Russian rubles (1991\\u20131998) random",
5858 "1.00 Russian rubles random",
5859 "1.00 Rwandan Franc random",
5860 "1.00 Rwandan franc random",
5861 "1.00 Rwandan francs random",
5862 "1.00 St. Helena Pound random",
5863 "1.00 St. Helena pound random",
5864 "1.00 St. Helena pounds random",
5865 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra random",
5866 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra random",
5867 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras random",
5868 "1.00 Saudi Riyal random",
5869 "1.00 Saudi riyal random",
5870 "1.00 Saudi riyals random",
5871 "1.00 Serbian Dinar random",
5872 "1.00 Serbian dinar random",
5873 "1.00 Serbian dinars random",
5874 "1.00 Seychellois Rupee random",
5875 "1.00 Seychellois rupee random",
5876 "1.00 Seychellois rupees random",
5877 "1.00 Sierra Leonean Leone random",
5878 "1.00 Sierra Leonean leone random",
5879 "1.00 Sierra Leonean leones random",
5880 "1.00 Singapore Dollar random",
5881 "1.00 Singapore dollar random",
5882 "1.00 Singapore dollars random",
5883 "1.00 Slovak Koruna random",
5884 "1.00 Slovak koruna random",
5885 "1.00 Slovak korunas random",
5886 "1.00 Slovenian Tolar random",
5887 "1.00 Slovenian tolar random",
5888 "1.00 Slovenian tolars random",
5889 "1.00 Solomon Islands Dollar random",
5890 "1.00 Solomon Islands dollar random",
5891 "1.00 Solomon Islands dollars random",
5892 "1.00 Somali Shilling random",
5893 "1.00 Somali shilling random",
5894 "1.00 Somali shillings random",
5895 "1.00 South African Rand (financial) random",
5896 "1.00 South African Rand random",
5897 "1.00 South African rand (financial) random",
5898 "1.00 South African rand random",
5899 "1.00 South African rands (financial) random",
5900 "1.00 South African rand random",
5901 "1.00 South Korean Won random",
5902 "1.00 South Korean won random",
5903 "1.00 South Korean won random",
5904 "1.00 Soviet Rouble random",
5905 "1.00 Soviet rouble random",
5906 "1.00 Soviet roubles random",
5907 "1.00 Spanish Peseta (A account) random",
5908 "1.00 Spanish Peseta (convertible account) random",
5909 "1.00 Spanish Peseta random",
5910 "1.00 Spanish peseta (A account) random",
5911 "1.00 Spanish peseta (convertible account) random",
5912 "1.00 Spanish peseta random",
5913 "1.00 Spanish pesetas (A account) random",
5914 "1.00 Spanish pesetas (convertible account) random",
5915 "1.00 Spanish pesetas random",
5916 "1.00 Special Drawing Rights random",
5917 "1.00 Sri Lankan Rupee random",
5918 "1.00 Sri Lankan rupee random",
5919 "1.00 Sri Lankan rupees random",
5920 "1.00 Sudanese Pound random",
5921 "1.00 Sudanese pound random",
5922 "1.00 Sudanese pounds random",
5923 "1.00 Surinamese Dollar random",
5924 "1.00 Surinamese dollar random",
5925 "1.00 Surinamese dollars random",
5926 "1.00 Surinamese Guilder random",
5927 "1.00 Surinamese guilder random",
5928 "1.00 Surinamese guilders random",
5929 "1.00 Swazi Lilangeni random",
5930 "1.00 Swazi lilangeni random",
5931 "1.00 Swazi emalangeni random",
5932 "1.00 Swedish Krona random",
5933 "1.00 Swedish krona random",
5934 "1.00 Swedish kronor random",
5935 "1.00 Swiss Franc random",
5936 "1.00 Swiss franc random",
5937 "1.00 Swiss francs random",
5938 "1.00 Syrian Pound random",
5939 "1.00 Syrian pound random",
5940 "1.00 Syrian pounds random",
5941 "1.00 New Taiwan Dollar random",
5942 "1.00 New Taiwan dollar random",
5943 "1.00 New Taiwan dollars random",
5944 "1.00 Tajikistani Ruble random",
5945 "1.00 Tajikistani Somoni random",
5946 "1.00 Tajikistani ruble random",
5947 "1.00 Tajikistani rubles random",
5948 "1.00 Tajikistani somoni random",
5949 "1.00 Tajikistani somonis random",
5950 "1.00 Tanzanian Shilling random",
5951 "1.00 Tanzanian shilling random",
5952 "1.00 Tanzanian shillings random",
5953 "1.00 Testing Currency Code random",
5954 "1.00 Testing Currency Code random",
5955 "1.00 Thai Baht random",
5956 "1.00 Thai baht random",
5957 "1.00 Thai baht random",
5958 "1.00 Timorese Escudo random",
5959 "1.00 Timorese escudo random",
5960 "1.00 Timorese escudos random",
5961 "1.00 Trinidad & Tobago Dollar random",
5962 "1.00 Trinidad & Tobago dollar random",
5963 "1.00 Trinidad & Tobago dollars random",
5964 "1.00 Tunisian Dinar random",
5965 "1.00 Tunisian dinar random",
5966 "1.00 Tunisian dinars random",
5967 "1.00 Turkish Lira random",
5968 "1.00 Turkish Lira random",
5969 "1.00 Turkish lira random",
5970 "1.00 Turkmenistani Manat random",
5971 "1.00 Turkmenistani manat random",
5972 "1.00 Turkmenistani manat random",
5973 "1.00 US Dollar (Next day) random",
5974 "1.00 US Dollar (Same day) random",
5975 "1.00 US Dollar random",
5976 "1.00 US dollar (next day) random",
5977 "1.00 US dollar (same day) random",
5978 "1.00 US dollar random",
5979 "1.00 US dollars (next day) random",
5980 "1.00 US dollars (same day) random",
5981 "1.00 US dollars random",
5982 "1.00 Ugandan Shilling (1966\\u20131987) random",
5983 "1.00 Ugandan Shilling random",
5984 "1.00 Ugandan shilling (1966\\u20131987) random",
5985 "1.00 Ugandan shilling random",
5986 "1.00 Ugandan shillings (1966\\u20131987) random",
5987 "1.00 Ugandan shillings random",
5988 "1.00 Ukrainian Hryvnia random",
5989 "1.00 Ukrainian Karbovanets random",
5990 "1.00 Ukrainian hryvnia random",
5991 "1.00 Ukrainian hryvnias random",
5992 "1.00 Ukrainian karbovanets random",
5993 "1.00 Ukrainian karbovantsiv random",
5994 "1.00 Colombian Real Value Unit random",
5995 "1.00 United Arab Emirates Dirham random",
5996 "1.00 Unknown Currency random",
5997 "1.00 Uruguayan Peso (1975\\u20131993) random",
5998 "1.00 Uruguayan Peso random",
5999 "1.00 Uruguayan Peso (Indexed Units) random",
6000 "1.00 Uruguayan peso (1975\\u20131993) random",
6001 "1.00 Uruguayan peso (indexed units) random",
6002 "1.00 Uruguayan peso random",
6003 "1.00 Uruguayan pesos (1975\\u20131993) random",
6004 "1.00 Uruguayan pesos (indexed units) random",
6005 "1.00 Uzbekistani Som random",
6006 "1.00 Uzbekistani som random",
6007 "1.00 Uzbekistani som random",
6008 "1.00 Vanuatu Vatu random",
6009 "1.00 Vanuatu vatu random",
6010 "1.00 Vanuatu vatus random",
6011 "1.00 Venezuelan Bol\\u00edvar random",
6012 "1.00 Venezuelan Bol\\u00edvar (1871\\u20132008) random",
6013 "1.00 Venezuelan bol\\u00edvar random",
6014 "1.00 Venezuelan bol\\u00edvars random",
6015 "1.00 Venezuelan bol\\u00edvar (1871\\u20132008) random",
6016 "1.00 Venezuelan bol\\u00edvars (1871\\u20132008) random",
6017 "1.00 Vietnamese Dong random",
6018 "1.00 Vietnamese dong random",
6019 "1.00 Vietnamese dong random",
6020 "1.00 WIR Euro random",
6021 "1.00 WIR Franc random",
6022 "1.00 WIR euro random",
6023 "1.00 WIR euros random",
6024 "1.00 WIR franc random",
6025 "1.00 WIR francs random",
6026 "1.00 Samoan Tala random",
6027 "1.00 Samoan tala random",
6028 "1.00 Samoan tala random",
6029 "1.00 Yemeni Dinar random",
6030 "1.00 Yemeni Rial random",
6031 "1.00 Yemeni dinar random",
6032 "1.00 Yemeni dinars random",
6033 "1.00 Yemeni rial random",
6034 "1.00 Yemeni rials random",
6035 "1.00 Yugoslavian Convertible Dinar (1990\\u20131992) random",
6036 "1.00 Yugoslavian Hard Dinar (1966\\u20131990) random",
6037 "1.00 Yugoslavian New Dinar (1994\\u20132002) random",
6038 "1.00 Yugoslavian convertible dinar (1990\\u20131992) random",
6039 "1.00 Yugoslavian convertible dinars (1990\\u20131992) random",
6040 "1.00 Yugoslavian hard dinar (1966\\u20131990) random",
6041 "1.00 Yugoslavian hard dinars (1966\\u20131990) random",
6042 "1.00 Yugoslavian new dinar (1994\\u20132002) random",
6043 "1.00 Yugoslavian new dinars (1994\\u20132002) random",
6044 "1.00 Zairean New Zaire (1993\\u20131998) random",
6045 "1.00 Zairean Zaire (1971\\u20131993) random",
6046 "1.00 Zairean new zaire (1993\\u20131998) random",
6047 "1.00 Zairean new zaires (1993\\u20131998) random",
6048 "1.00 Zairean zaire (1971\\u20131993) random",
6049 "1.00 Zairean zaires (1971\\u20131993) random",
6050 "1.00 Zambian Kwacha random",
6051 "1.00 Zambian kwacha random",
6052 "1.00 Zambian kwachas random",
6053 "1.00 Zimbabwean Dollar (1980\\u20132008) random",
6054 "1.00 Zimbabwean dollar (1980\\u20132008) random",
6055 "1.00 Zimbabwean dollars (1980\\u20132008) random",
6056 "1.00 euro random",
6057 "1.00 euros random",
6058 "1.00 Turkish lira (1922\\u20132005) random",
6059 "1.00 special drawing rights random",
6060 "1.00 Colombian real value unit random",
6061 "1.00 Colombian real value units random",
6062 "1.00 unknown currency random",
6063 };
6064
6065 const char* WRONG_DATA[] = {
6066 // Following are missing one last char in the currency name
6067 "1.00 Nicaraguan Cordob",
6068 "1.00 Namibian Dolla",
6069 "1.00 Namibian dolla",
6070 "1.00 Nepalese Rupe",
6071 "1.00 Nepalese rupe",
6072 "1.00 Netherlands Antillean Guilde",
6073 "1.00 Netherlands Antillean guilde",
6074 "1.00 Dutch Guilde",
6075 "1.00 Dutch guilde",
6076 "1.00 Israeli New Sheqe",
6077 "1.00 New Zealand Dolla",
6078 "1.00 New Zealand dolla",
6079 "1.00 Nicaraguan cordob",
6080 "1.00 Nigerian Nair",
6081 "1.00 Nigerian nair",
6082 "1.00 North Korean Wo",
6083 "1.00 North Korean wo",
6084 "1.00 Norwegian Kron",
6085 "1.00 Norwegian kron",
6086 "1.00 US dolla",
6087 "1.00",
6088 "A1.00",
6089 "AD1.00",
6090 "AE1.00",
6091 "AF1.00",
6092 "AL1.00",
6093 "AM1.00",
6094 "AN1.00",
6095 "AO1.00",
6096 "AR1.00",
6097 "AT1.00",
6098 "AU1.00",
6099 "AW1.00",
6100 "AZ1.00",
6101 "Afghan Afghan1.00",
6102 "Afghan Afghani (1927\\u201320021.00",
6103 "Afl1.00",
6104 "Albanian Le1.00",
6105 "Algerian Dina1.00",
6106 "Andorran Peset1.00",
6107 "Angolan Kwanz1.00",
6108 "Angolan Kwanza (1977\\u201319901.00",
6109 "Angolan Readjusted Kwanza (1995\\u201319991.00",
6110 "Angolan New Kwanza (1990\\u201320001.00",
6111 "Argentine Austra1.00",
6112 "Argentine Pes1.00",
6113 "Argentine Peso (1983\\u201319851.00",
6114 "Armenian Dra1.00",
6115 "Aruban Flori1.00",
6116 "Australian Dolla1.00",
6117 "Austrian Schillin1.00",
6118 "Azerbaijani Mana1.00",
6119 "Azerbaijani Manat (1993\\u201320061.00",
6120 "B1.00",
6121 "BA1.00",
6122 "BB1.00",
6123 "BE1.00",
6124 "BG1.00",
6125 "BH1.00",
6126 "BI1.00",
6127 "BM1.00",
6128 "BN1.00",
6129 "BO1.00",
6130 "BR1.00",
6131 "BS1.00",
6132 "BT1.00",
6133 "BU1.00",
6134 "BW1.00",
6135 "BY1.00",
6136 "BZ1.00",
6137 "Bahamian Dolla1.00",
6138 "Bahraini Dina1.00",
6139 "Bangladeshi Tak1.00",
6140 "Barbadian Dolla1.00",
6141 "Bds1.00",
6142 "Belarusian Ruble (1994\\u201319991.00",
6143 "Belarusian Rubl1.00",
6144 "Belgian Fran1.00",
6145 "Belgian Franc (convertible1.00",
6146 "Belgian Franc (financial1.00",
6147 "Belize Dolla1.00",
6148 "Bermudan Dolla1.00",
6149 "Bhutanese Ngultru1.00",
6150 "Bolivian Mvdo1.00",
6151 "Bolivian Pes1.00",
6152 "Bolivian Bolivian1.00",
6153 "Bosnia-Herzegovina Convertible Mar1.00",
6154 "Bosnia-Herzegovina Dina1.00",
6155 "Botswanan Pul1.00",
6156 "Brazilian Cruzad1.00",
6157 "Brazilian Cruzado Nov1.00",
6158 "Brazilian Cruzeir1.00",
6159 "Brazilian Cruzeiro (1990\\u201319931.00",
6160 "Brazilian New Cruzeiro (1967\\u201319861.00",
6161 "Brazilian Rea1.00",
6162 "British Pound Sterlin1.00",
6163 "Brunei Dolla1.00",
6164 "Bulgarian Hard Le1.00",
6165 "Bulgarian Le1.00",
6166 "Burmese Kya1.00",
6167 "Burundian Fran1.00",
6168 "C1.00",
6169 "CA1.00",
6170 "CD1.00",
6171 "CFP Fran1.00",
6172 "CFP1.00",
6173 "CH1.00",
6174 "CL1.00",
6175 "CN1.00",
6176 "CO1.00",
6177 "CS1.00",
6178 "CU1.00",
6179 "CV1.00",
6180 "CY1.00",
6181 "CZ1.00",
6182 "Cambodian Rie1.00",
6183 "Canadian Dolla1.00",
6184 "Cape Verdean Escud1.00",
6185 "Cayman Islands Dolla1.00",
6186 "Chilean Pes1.00",
6187 "Chilean Unit of Accoun1.00",
6188 "Chinese Yua1.00",
6189 "Colombian Pes1.00",
6190 "Comoro Fran1.00",
6191 "Congolese Fran1.00",
6192 "Costa Rican Col\\u00f31.00",
6193 "Croatian Dina1.00",
6194 "Croatian Kun1.00",
6195 "Cuban Pes1.00",
6196 "Cypriot Poun1.00",
6197 "Czech Republic Korun1.00",
6198 "Czechoslovak Hard Korun1.00",
6199 "D1.00",
6200 "DD1.00",
6201 "DE1.00",
6202 "DJ1.00",
6203 "DK1.00",
6204 "DO1.00",
6205 "DZ1.00",
6206 "Danish Kron1.00",
6207 "German Mar1.00",
6208 "Djiboutian Fran1.00",
6209 "Dk1.00",
6210 "Dominican Pes1.00",
6211 "EC1.00",
6212 "EE1.00",
6213 "EG1.00",
6214 "EQ1.00",
6215 "ER1.00",
6216 "ES1.00",
6217 "ET1.00",
6218 "EU1.00",
6219 "East Caribbean Dolla1.00",
6220 "East German Ostmar1.00",
6221 "Ecuadorian Sucr1.00",
6222 "Ecuadorian Unit of Constant Valu1.00",
6223 "Egyptian Poun1.00",
6224 "Ekwel1.00",
6225 "Salvadoran Col\\u00f31.00",
6226 "Equatorial Guinean Ekwel1.00",
6227 "Eritrean Nakf1.00",
6228 "Es1.00",
6229 "Estonian Kroo1.00",
6230 "Ethiopian Bir1.00",
6231 "Eur1.00",
6232 "European Composite Uni1.00",
6233 "European Currency Uni1.00",
6234 "European Monetary Uni1.00",
6235 "European Unit of Account (XBC1.00",
6236 "European Unit of Account (XBD1.00",
6237 "F1.00",
6238 "FB1.00",
6239 "FI1.00",
6240 "FJ1.00",
6241 "FK1.00",
6242 "FR1.00",
6243 "Falkland Islands Poun1.00",
6244 "Fd1.00",
6245 "Fijian Dolla1.00",
6246 "Finnish Markk1.00",
6247 "Fr1.00",
6248 "French Fran1.00",
6249 "French Gold Fran1.00",
6250 "French UIC-Fran1.00",
6251 "G1.00",
6252 "GB1.00",
6253 "GE1.00",
6254 "GH1.00",
6255 "GI1.00",
6256 "GM1.00",
6257 "GN1.00",
6258 "GQ1.00",
6259 "GR1.00",
6260 "GT1.00",
6261 "GW1.00",
6262 "GY1.00",
6263 "Gambian Dalas1.00",
6264 "Georgian Kupon Lari1.00",
6265 "Georgian Lar1.00",
6266 "Ghanaian Ced1.00",
6267 "Ghanaian Cedi (1979\\u201320071.00",
6268 "Gibraltar Poun1.00",
6269 "Gol1.00",
6270 "Greek Drachm1.00",
6271 "Guatemalan Quetza1.00",
6272 "Guinean Fran1.00",
6273 "Guinean Syl1.00",
6274 "Guinea-Bissau Pes1.00",
6275 "Guyanaese Dolla1.00",
6276 "HK1.00",
6277 "HN1.00",
6278 "HR1.00",
6279 "HT1.00",
6280 "HU1.00",
6281 "Haitian Gourd1.00",
6282 "Honduran Lempir1.00",
6283 "Hong Kong Dolla1.00",
6284 "Hungarian Forin1.00",
6285 "I1.00",
6286 "IE1.00",
6287 "IL1.00",
6288 "IN1.00",
6289 "IQ1.00",
6290 "IR1.00",
6291 "IS1.00",
6292 "IT1.00",
6293 "Icelandic Kron1.00",
6294 "Indian Rupe1.00",
6295 "Indonesian Rupia1.00",
6296 "Iranian Ria1.00",
6297 "Iraqi Dina1.00",
6298 "Irish Poun1.00",
6299 "Israeli Poun1.00",
6300 "Italian Lir1.00",
6301 "J1.00",
6302 "JM1.00",
6303 "JO1.00",
6304 "JP1.00",
6305 "Jamaican Dolla1.00",
6306 "Japanese Ye1.00",
6307 "Jordanian Dina1.00",
6308 "K S1.00",
6309 "K1.00",
6310 "KE1.00",
6311 "KG1.00",
6312 "KH1.00",
6313 "KP1.00",
6314 "KR1.00",
6315 "KW1.00",
6316 "KY1.00",
6317 "KZ1.00",
6318 "Kazakhstani Teng1.00",
6319 "Kenyan Shillin1.00",
6320 "Kuwaiti Dina1.00",
6321 "Kyrgystani So1.00",
6322 "LA1.00",
6323 "LB1.00",
6324 "LK1.00",
6325 "LR1.00",
6326 "LT1.00",
6327 "LU1.00",
6328 "LV1.00",
6329 "LY1.00",
6330 "Laotian Ki1.00",
6331 "Latvian Lat1.00",
6332 "Latvian Rubl1.00",
6333 "Lebanese Poun1.00",
6334 "Lesotho Lot1.00",
6335 "Liberian Dolla1.00",
6336 "Libyan Dina1.00",
6337 "Lithuanian Lit1.00",
6338 "Lithuanian Talona1.00",
6339 "Luxembourgian Convertible Fran1.00",
6340 "Luxembourg Financial Fran1.00",
6341 "Luxembourgian Fran1.00",
6342 "MA1.00",
6343 "MD1.00",
6344 "MDe1.00",
6345 "MEX1.00",
6346 "MG1.00",
6347 "ML1.00",
6348 "MM1.00",
6349 "MN1.00",
6350 "MO1.00",
6351 "MR1.00",
6352 "MT1.00",
6353 "MU1.00",
6354 "MV1.00",
6355 "MW1.00",
6356 "MX1.00",
6357 "MY1.00",
6358 "MZ1.00",
6359 "Macanese Patac1.00",
6360 "Macedonian Dena1.00",
6361 "Malagasy Ariar1.00",
6362 "Malagasy Fran1.00",
6363 "Malawian Kwach1.00",
6364 "Malaysian Ringgi1.00",
6365 "Maldivian Rufiya1.00",
6366 "Malian Fran1.00",
6367 "Malot1.00",
6368 "Maltese Lir1.00",
6369 "Maltese Poun1.00",
6370 "Mauritanian Ouguiy1.00",
6371 "Mauritian Rupe1.00",
6372 "Mexican Pes1.00",
6373 "Mexican Silver Peso (1861\\u201319921.00",
6374 "Mexican Investment Uni1.00",
6375 "Moldovan Le1.00",
6376 "Mongolian Tugri1.00",
6377 "Moroccan Dirha1.00",
6378 "Moroccan Fran1.00",
6379 "Mozambican Escud1.00",
6380 "Mozambican Metica1.00",
6381 "Myanmar Kya1.00",
6382 "N1.00",
6383 "NA1.00",
6384 "NAf1.00",
6385 "NG1.00",
6386 "NI1.00",
6387 "NK1.00",
6388 "NL1.00",
6389 "NO1.00",
6390 "NP1.00",
6391 "NT1.00",
6392 "Namibian Dolla1.00",
6393 "Nepalese Rupe1.00",
6394 "Netherlands Antillean Guilde1.00",
6395 "Dutch Guilde1.00",
6396 "Israeli New Sheqe1.00",
6397 "New Zealand Dolla1.00",
6398 "Nicaraguan C\\u00f3rdoba (1988\\u201319911.00",
6399 "Nicaraguan C\\u00f3rdob1.00",
6400 "Nigerian Nair1.00",
6401 "North Korean Wo1.00",
6402 "Norwegian Kron1.00",
6403 "Nr1.00",
6404 "OM1.00",
6405 "Old Mozambican Metica1.00",
6406 "Romanian Leu (1952\\u201320061.00",
6407 "Serbian Dinar (2002\\u201320061.00",
6408 "Sudanese Dinar (1992\\u201320071.00",
6409 "Sudanese Pound (1957\\u201319981.00",
6410 "Turkish Lira (1922\\u201320051.00",
6411 "Omani Ria1.00",
6412 "PA1.00",
6413 "PE1.00",
6414 "PG1.00",
6415 "PH1.00",
6416 "PK1.00",
6417 "PL1.00",
6418 "PT1.00",
6419 "PY1.00",
6420 "Pakistani Rupe1.00",
6421 "Palladiu1.00",
6422 "Panamanian Balbo1.00",
6423 "Papua New Guinean Kin1.00",
6424 "Paraguayan Guaran1.00",
6425 "Peruvian Int1.00",
6426 "Peruvian Sol (1863\\u201319651.00",
6427 "Peruvian Sol Nuev1.00",
6428 "Philippine Pes1.00",
6429 "Platinu1.00",
6430 "Polish Zlot1.00",
6431 "Polish Zloty (1950\\u201319951.00",
6432 "Portuguese Escud1.00",
6433 "Portuguese Guinea Escud1.00",
6434 "Pr1.00",
6435 "QA1.00",
6436 "Qatari Ria1.00",
6437 "RD1.00",
6438 "RH1.00",
6439 "RINET Fund1.00",
6440 "RS1.00",
6441 "RU1.00",
6442 "RW1.00",
6443 "Rb1.00",
6444 "Rhodesian Dolla1.00",
6445 "Romanian Le1.00",
6446 "Russian Rubl1.00",
6447 "Russian Ruble (1991\\u201319981.00",
6448 "Rwandan Fran1.00",
6449 "S1.00",
6450 "SA1.00",
6451 "SB1.00",
6452 "SC1.00",
6453 "SD1.00",
6454 "SE1.00",
6455 "SG1.00",
6456 "SH1.00",
6457 "SI1.00",
6458 "SK1.00",
6459 "SL R1.00",
6460 "SL1.00",
6461 "SO1.00",
6462 "ST1.00",
6463 "SU1.00",
6464 "SV1.00",
6465 "SY1.00",
6466 "SZ1.00",
6467 "St. Helena Poun1.00",
6468 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobr1.00",
6469 "Saudi Riya1.00",
6470 "Serbian Dina1.00",
6471 "Seychellois Rupe1.00",
6472 "Sh1.00",
6473 "Sierra Leonean Leon1.00",
6474 "Silve1.00",
6475 "Singapore Dolla1.00",
6476 "Slovak Korun1.00",
6477 "Slovenian Tola1.00",
6478 "Solomon Islands Dolla1.00",
6479 "Somali Shillin1.00",
6480 "South African Ran1.00",
6481 "South African Rand (financial1.00",
6482 "South Korean Wo1.00",
6483 "Soviet Roubl1.00",
6484 "Spanish Peset1.00",
6485 "Spanish Peseta (A account1.00",
6486 "Spanish Peseta (convertible account1.00",
6487 "Special Drawing Right1.00",
6488 "Sri Lankan Rupe1.00",
6489 "Sudanese Poun1.00",
6490 "Surinamese Dolla1.00",
6491 "Surinamese Guilde1.00",
6492 "Swazi Lilangen1.00",
6493 "Swedish Kron1.00",
6494 "Swiss Fran1.00",
6495 "Syrian Poun1.00",
6496 "T S1.00",
6497 "TH1.00",
6498 "TJ1.00",
6499 "TM1.00",
6500 "TN1.00",
6501 "TO1.00",
6502 "TP1.00",
6503 "TR1.00",
6504 "TT1.00",
6505 "TW1.00",
6506 "TZ1.00",
6507 "New Taiwan Dolla1.00",
6508 "Tajikistani Rubl1.00",
6509 "Tajikistani Somon1.00",
6510 "Tanzanian Shillin1.00",
6511 "Testing Currency Cod1.00",
6512 "Thai Bah1.00",
6513 "Timorese Escud1.00",
6514 "Tongan Pa\\u20bbang1.00",
6515 "Trinidad & Tobago Dolla1.00",
6516 "Tunisian Dina1.00",
6517 "Turkish Lir1.00",
6518 "Turkmenistani Mana1.00",
6519 "U S1.00",
6520 "U1.00",
6521 "UA1.00",
6522 "UG1.00",
6523 "US Dolla1.00",
6524 "US Dollar (Next day1.00",
6525 "US Dollar (Same day1.00",
6526 "US1.00",
6527 "UY1.00",
6528 "UZ1.00",
6529 "Ugandan Shillin1.00",
6530 "Ugandan Shilling (1966\\u201319871.00",
6531 "Ukrainian Hryvni1.00",
6532 "Ukrainian Karbovanet1.00",
6533 "Colombian Real Value Uni1.00",
6534 "United Arab Emirates Dirha1.00",
6535 "Unknown Currenc1.00",
6536 "Ur1.00",
6537 "Uruguay Peso (1975\\u201319931.00",
6538 "Uruguay Peso Uruguay1.00",
6539 "Uruguay Peso (Indexed Units1.00",
6540 "Uzbekistani So1.00",
6541 "V1.00",
6542 "VE1.00",
6543 "VN1.00",
6544 "VU1.00",
6545 "Vanuatu Vat1.00",
6546 "Venezuelan Bol\\u00edva1.00",
6547 "Venezuelan Bol\\u00edvar Fuert1.00",
6548 "Vietnamese Don1.00",
6549 "West African CFA Fran1.00",
6550 "Central African CFA Fran1.00",
6551 "WIR Eur1.00",
6552 "WIR Fran1.00",
6553 "WS1.00",
6554 "Samoa Tal1.00",
6555 "XA1.00",
6556 "XB1.00",
6557 "XC1.00",
6558 "XD1.00",
6559 "XE1.00",
6560 "XF1.00",
6561 "XO1.00",
6562 "XP1.00",
6563 "XR1.00",
6564 "XT1.00",
6565 "XX1.00",
6566 "YD1.00",
6567 "YE1.00",
6568 "YU1.00",
6569 "Yemeni Dina1.00",
6570 "Yemeni Ria1.00",
6571 "Yugoslavian Convertible Dina1.00",
6572 "Yugoslavian Hard Dinar (1966\\u201319901.00",
6573 "Yugoslavian New Dina1.00",
6574 "Z1.00",
6575 "ZA1.00",
6576 "ZM1.00",
6577 "ZR1.00",
6578 "ZW1.00",
6579 "Zairean New Zaire (1993\\u201319981.00",
6580 "Zairean Zair1.00",
6581 "Zambian Kwach1.00",
6582 "Zimbabwean Dollar (1980\\u201320081.00",
6583 "dra1.00",
6584 "lar1.00",
6585 "le1.00",
6586 "man1.00",
6587 "so1.00",
6588 };
6589
6590 Locale locale("en_US");
6591 for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
6592 UnicodeString formatted = ctou(DATA[i]);
6593 UErrorCode status = U_ZERO_ERROR;
6594 LocalPointer<NumberFormat> numFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status), status);
6595 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {
6596 return;
6597 }
6598 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
6599 numFmt->setLenient(TRUE);
6600 ParsePosition parsePos;
6601 LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6602 if (parsePos.getIndex() > 0) {
6603 double doubleVal = currAmt->getNumber().getDouble(status);
6604 if ( doubleVal != 1.0 ) {
6605 errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
6606 }
6607 } else {
6608 errln("Failed to parse as currency: " + formatted);
6609 }
6610 }
6611
6612 for (uint32_t i=0; i<UPRV_LENGTHOF(WRONG_DATA); ++i) {
6613 UnicodeString formatted = ctou(WRONG_DATA[i]);
6614 UErrorCode status = U_ZERO_ERROR;
6615 NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6616 if (numFmt != NULL && U_SUCCESS(status)) {
6617 ParsePosition parsePos;
6618 LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6619 if (parsePos.getIndex() > 0) {
6620 double doubleVal = currAmt->getNumber().getDouble(status);
6621 errln("Parsed as currency, should not have: " + formatted + " -> " + doubleVal);
6622 }
6623 } else {
6624 dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));
6625 delete numFmt;
6626 break;
6627 }
6628 delete numFmt;
6629 }
6630 }
6631
6632 const char* attrString(int32_t);
6633
6634 // UnicodeString s;
6635 // std::string ss;
6636 // std::cout << s.toUTF8String(ss)
expectPositions(FieldPositionIterator & iter,int32_t * values,int32_t tupleCount,const UnicodeString & str)6637 void NumberFormatTest::expectPositions(FieldPositionIterator& iter, int32_t *values, int32_t tupleCount,
6638 const UnicodeString& str) {
6639 UBool found[10];
6640 FieldPosition fp;
6641
6642 if (tupleCount > 10) {
6643 assertTrue("internal error, tupleCount too large", FALSE);
6644 } else {
6645 for (int i = 0; i < tupleCount; ++i) {
6646 found[i] = FALSE;
6647 }
6648 }
6649
6650 logln(str);
6651 while (iter.next(fp)) {
6652 UBool ok = FALSE;
6653 int32_t id = fp.getField();
6654 int32_t start = fp.getBeginIndex();
6655 int32_t limit = fp.getEndIndex();
6656
6657 // is there a logln using printf?
6658 char buf[128];
6659 sprintf(buf, "%24s %3d %3d %3d", attrString(id), id, start, limit);
6660 logln(buf);
6661
6662 for (int i = 0; i < tupleCount; ++i) {
6663 if (found[i]) {
6664 continue;
6665 }
6666 if (values[i*3] == id &&
6667 values[i*3+1] == start &&
6668 values[i*3+2] == limit) {
6669 found[i] = ok = TRUE;
6670 break;
6671 }
6672 }
6673
6674 assertTrue((UnicodeString)"found [" + id + "," + start + "," + limit + "]", ok);
6675 }
6676
6677 // check that all were found
6678 UBool ok = TRUE;
6679 for (int i = 0; i < tupleCount; ++i) {
6680 if (!found[i]) {
6681 ok = FALSE;
6682 assertTrue((UnicodeString) "missing [" + values[i*3] + "," + values[i*3+1] + "," + values[i*3+2] + "]", found[i]);
6683 }
6684 }
6685 assertTrue("no expected values were missing", ok);
6686 }
6687
expectPosition(FieldPosition & pos,int32_t id,int32_t start,int32_t limit,const UnicodeString & str)6688 void NumberFormatTest::expectPosition(FieldPosition& pos, int32_t id, int32_t start, int32_t limit,
6689 const UnicodeString& str) {
6690 logln(str);
6691 assertTrue((UnicodeString)"id " + id + " == " + pos.getField(), id == pos.getField());
6692 assertTrue((UnicodeString)"begin " + start + " == " + pos.getBeginIndex(), start == pos.getBeginIndex());
6693 assertTrue((UnicodeString)"end " + limit + " == " + pos.getEndIndex(), limit == pos.getEndIndex());
6694 }
6695
TestFieldPositionIterator()6696 void NumberFormatTest::TestFieldPositionIterator() {
6697 // bug 7372
6698 UErrorCode status = U_ZERO_ERROR;
6699 FieldPositionIterator iter1;
6700 FieldPositionIterator iter2;
6701 FieldPosition pos;
6702
6703 DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(status);
6704 if (failure(status, "NumberFormat::createInstance", TRUE)) return;
6705
6706 double num = 1234.56;
6707 UnicodeString str1;
6708 UnicodeString str2;
6709
6710 assertTrue((UnicodeString)"self==", iter1 == iter1);
6711 assertTrue((UnicodeString)"iter1==iter2", iter1 == iter2);
6712
6713 decFmt->format(num, str1, &iter1, status);
6714 assertTrue((UnicodeString)"iter1 != iter2", iter1 != iter2);
6715 decFmt->format(num, str2, &iter2, status);
6716 assertTrue((UnicodeString)"iter1 == iter2 (2)", iter1 == iter2);
6717 iter1.next(pos);
6718 assertTrue((UnicodeString)"iter1 != iter2 (2)", iter1 != iter2);
6719 iter2.next(pos);
6720 assertTrue((UnicodeString)"iter1 == iter2 (3)", iter1 == iter2);
6721
6722 // should format ok with no iterator
6723 str2.remove();
6724 decFmt->format(num, str2, NULL, status);
6725 assertEquals("null fpiter", str1, str2);
6726
6727 delete decFmt;
6728 }
6729
TestFormatAttributes()6730 void NumberFormatTest::TestFormatAttributes() {
6731 Locale locale("en_US");
6732 UErrorCode status = U_ZERO_ERROR;
6733 DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6734 if (failure(status, "NumberFormat::createInstance", TRUE)) return;
6735 double val = 12345.67;
6736
6737 {
6738 int32_t expected[] = {
6739 UNUM_CURRENCY_FIELD, 0, 1,
6740 UNUM_GROUPING_SEPARATOR_FIELD, 3, 4,
6741 UNUM_INTEGER_FIELD, 1, 7,
6742 UNUM_DECIMAL_SEPARATOR_FIELD, 7, 8,
6743 UNUM_FRACTION_FIELD, 8, 10,
6744 };
6745 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6746
6747 FieldPositionIterator posIter;
6748 UnicodeString result;
6749 decFmt->format(val, result, &posIter, status);
6750 expectPositions(posIter, expected, tupleCount, result);
6751 }
6752 {
6753 FieldPosition fp(UNUM_INTEGER_FIELD);
6754 UnicodeString result;
6755 decFmt->format(val, result, fp);
6756 expectPosition(fp, UNUM_INTEGER_FIELD, 1, 7, result);
6757 }
6758 {
6759 FieldPosition fp(UNUM_FRACTION_FIELD);
6760 UnicodeString result;
6761 decFmt->format(val, result, fp);
6762 expectPosition(fp, UNUM_FRACTION_FIELD, 8, 10, result);
6763 }
6764 delete decFmt;
6765
6766 decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_SCIENTIFIC, status);
6767 val = -0.0000123;
6768 {
6769 int32_t expected[] = {
6770 UNUM_SIGN_FIELD, 0, 1,
6771 UNUM_INTEGER_FIELD, 1, 2,
6772 UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3,
6773 UNUM_FRACTION_FIELD, 3, 5,
6774 UNUM_EXPONENT_SYMBOL_FIELD, 5, 6,
6775 UNUM_EXPONENT_SIGN_FIELD, 6, 7,
6776 UNUM_EXPONENT_FIELD, 7, 8
6777 };
6778 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6779
6780 FieldPositionIterator posIter;
6781 UnicodeString result;
6782 decFmt->format(val, result, &posIter, status);
6783 expectPositions(posIter, expected, tupleCount, result);
6784 }
6785 {
6786 FieldPosition fp(UNUM_INTEGER_FIELD);
6787 UnicodeString result;
6788 decFmt->format(val, result, fp);
6789 expectPosition(fp, UNUM_INTEGER_FIELD, 1, 2, result);
6790 }
6791 {
6792 FieldPosition fp(UNUM_FRACTION_FIELD);
6793 UnicodeString result;
6794 decFmt->format(val, result, fp);
6795 expectPosition(fp, UNUM_FRACTION_FIELD, 3, 5, result);
6796 }
6797 delete decFmt;
6798
6799 fflush(stderr);
6800 }
6801
attrString(int32_t attrId)6802 const char* attrString(int32_t attrId) {
6803 switch (attrId) {
6804 case UNUM_INTEGER_FIELD: return "integer";
6805 case UNUM_FRACTION_FIELD: return "fraction";
6806 case UNUM_DECIMAL_SEPARATOR_FIELD: return "decimal separator";
6807 case UNUM_EXPONENT_SYMBOL_FIELD: return "exponent symbol";
6808 case UNUM_EXPONENT_SIGN_FIELD: return "exponent sign";
6809 case UNUM_EXPONENT_FIELD: return "exponent";
6810 case UNUM_GROUPING_SEPARATOR_FIELD: return "grouping separator";
6811 case UNUM_CURRENCY_FIELD: return "currency";
6812 case UNUM_PERCENT_FIELD: return "percent";
6813 case UNUM_PERMILL_FIELD: return "permille";
6814 case UNUM_SIGN_FIELD: return "sign";
6815 default: return "";
6816 }
6817 }
6818
6819 //
6820 // Test formatting & parsing of big decimals.
6821 // API test, not a comprehensive test.
6822 // See DecimalFormatTest/DataDrivenTests
6823 //
6824 #define ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \
6825 assertSuccess(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (status)); \
6826 } UPRV_BLOCK_MACRO_END
6827 #define ASSERT_EQUALS(expected, actual) UPRV_BLOCK_MACRO_BEGIN { \
6828 assertEquals(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (expected), (actual)); \
6829 } UPRV_BLOCK_MACRO_END
6830
TestDecimal()6831 void NumberFormatTest::TestDecimal() {
6832 {
6833 UErrorCode status = U_ZERO_ERROR;
6834 Formattable f("12.345678999987654321E666", status);
6835 ASSERT_SUCCESS(status);
6836 StringPiece s = f.getDecimalNumber(status);
6837 ASSERT_SUCCESS(status);
6838 ASSERT_EQUALS("1.2345678999987654321E+667", s.data());
6839 //printf("%s\n", s.data());
6840 }
6841
6842 {
6843 UErrorCode status = U_ZERO_ERROR;
6844 Formattable f1("this is not a number", status);
6845 ASSERT_EQUALS(U_DECIMAL_NUMBER_SYNTAX_ERROR, status);
6846 }
6847
6848 {
6849 UErrorCode status = U_ZERO_ERROR;
6850 Formattable f;
6851 f.setDecimalNumber("123.45", status);
6852 ASSERT_SUCCESS(status);
6853 ASSERT_EQUALS( Formattable::kDouble, f.getType());
6854 ASSERT_EQUALS(123.45, f.getDouble());
6855 ASSERT_EQUALS(123.45, f.getDouble(status));
6856 ASSERT_SUCCESS(status);
6857 ASSERT_EQUALS("123.45", f.getDecimalNumber(status).data());
6858 ASSERT_SUCCESS(status);
6859
6860 f.setDecimalNumber("4.5678E7", status);
6861 int32_t n;
6862 n = f.getLong();
6863 ASSERT_EQUALS(45678000, n);
6864
6865 status = U_ZERO_ERROR;
6866 f.setDecimalNumber("-123", status);
6867 ASSERT_SUCCESS(status);
6868 ASSERT_EQUALS( Formattable::kLong, f.getType());
6869 ASSERT_EQUALS(-123, f.getLong());
6870 ASSERT_EQUALS(-123, f.getLong(status));
6871 ASSERT_SUCCESS(status);
6872 ASSERT_EQUALS("-123", f.getDecimalNumber(status).data());
6873 ASSERT_SUCCESS(status);
6874
6875 status = U_ZERO_ERROR;
6876 f.setDecimalNumber("1234567890123", status); // Number too big for 32 bits
6877 ASSERT_SUCCESS(status);
6878 ASSERT_EQUALS( Formattable::kInt64, f.getType());
6879 ASSERT_EQUALS(1234567890123LL, f.getInt64());
6880 ASSERT_EQUALS(1234567890123LL, f.getInt64(status));
6881 ASSERT_SUCCESS(status);
6882 ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status).data());
6883 ASSERT_SUCCESS(status);
6884 }
6885
6886 {
6887 UErrorCode status = U_ZERO_ERROR;
6888 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6889 if (U_FAILURE(status) || fmtr == NULL) {
6890 dataerrln("Unable to create NumberFormat");
6891 } else {
6892 UnicodeString formattedResult;
6893 StringPiece num("244444444444444444444444444444444444446.4");
6894 fmtr->format(num, formattedResult, NULL, status);
6895 ASSERT_SUCCESS(status);
6896 ASSERT_EQUALS("244,444,444,444,444,444,444,444,444,444,444,444,446.4", formattedResult);
6897 //std::string ss; std::cout << formattedResult.toUTF8String(ss);
6898 delete fmtr;
6899 }
6900 }
6901
6902 {
6903 // Check formatting a DigitList. DigitList is internal, but this is
6904 // a critical interface that must work.
6905 UErrorCode status = U_ZERO_ERROR;
6906 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6907 if (U_FAILURE(status) || fmtr == NULL) {
6908 dataerrln("Unable to create NumberFormat");
6909 } else {
6910 UnicodeString formattedResult;
6911 DecimalQuantity dl;
6912 StringPiece num("123.4566666666666666666666666666666666621E+40");
6913 dl.setToDecNumber(num, status);
6914 ASSERT_SUCCESS(status);
6915 fmtr->format(dl, formattedResult, NULL, status);
6916 ASSERT_SUCCESS(status);
6917 ASSERT_EQUALS("1,234,566,666,666,666,666,666,666,666,666,666,666,621,000", formattedResult);
6918
6919 status = U_ZERO_ERROR;
6920 num.set("666.666");
6921 dl.setToDecNumber(num, status);
6922 FieldPosition pos(NumberFormat::FRACTION_FIELD);
6923 ASSERT_SUCCESS(status);
6924 formattedResult.remove();
6925 fmtr->format(dl, formattedResult, pos, status);
6926 ASSERT_SUCCESS(status);
6927 ASSERT_EQUALS("666.666", formattedResult);
6928 ASSERT_EQUALS(4, pos.getBeginIndex());
6929 ASSERT_EQUALS(7, pos.getEndIndex());
6930 delete fmtr;
6931 }
6932 }
6933
6934 {
6935 // Check a parse with a formatter with a multiplier.
6936 UErrorCode status = U_ZERO_ERROR;
6937 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_PERCENT, status);
6938 if (U_FAILURE(status) || fmtr == NULL) {
6939 dataerrln("Unable to create NumberFormat");
6940 } else {
6941 UnicodeString input = "1.84%";
6942 Formattable result;
6943 fmtr->parse(input, result, status);
6944 ASSERT_SUCCESS(status);
6945 ASSERT_EQUALS("0.0184", result.getDecimalNumber(status).data());
6946 //std::cout << result.getDecimalNumber(status).data();
6947 delete fmtr;
6948 }
6949 }
6950
6951 #if U_PLATFORM != U_PF_CYGWIN || defined(CYGWINMSVC)
6952 /*
6953 * This test fails on Cygwin (1.7.16) using GCC because of a rounding issue with strtod().
6954 * See #9463
6955 */
6956 {
6957 // Check that a parse returns a decimal number with full accuracy
6958 UErrorCode status = U_ZERO_ERROR;
6959 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6960 if (U_FAILURE(status) || fmtr == NULL) {
6961 dataerrln("Unable to create NumberFormat");
6962 } else {
6963 UnicodeString input = "1.002200044400088880000070000";
6964 Formattable result;
6965 fmtr->parse(input, result, status);
6966 ASSERT_SUCCESS(status);
6967 ASSERT_EQUALS(0, strcmp("1.00220004440008888000007", result.getDecimalNumber(status).data()));
6968 ASSERT_EQUALS(1.00220004440008888, result.getDouble());
6969 //std::cout << result.getDecimalNumber(status).data();
6970 delete fmtr;
6971 }
6972 }
6973 #endif
6974
6975 }
6976
TestCurrencyFractionDigits()6977 void NumberFormatTest::TestCurrencyFractionDigits() {
6978 UErrorCode status = U_ZERO_ERROR;
6979 UnicodeString text1, text2;
6980 double value = 99.12345;
6981
6982 // Create currenct instance
6983 NumberFormat* fmt = NumberFormat::createCurrencyInstance("ja_JP", status);
6984 if (U_FAILURE(status) || fmt == NULL) {
6985 dataerrln("Unable to create NumberFormat");
6986 } else {
6987 fmt->format(value, text1);
6988
6989 // Reset the same currency and format the test value again
6990 fmt->setCurrency(fmt->getCurrency(), status);
6991 ASSERT_SUCCESS(status);
6992 fmt->format(value, text2);
6993
6994 if (text1 != text2) {
6995 errln((UnicodeString)"NumberFormat::format() should return the same result - text1="
6996 + text1 + " text2=" + text2);
6997 }
6998 }
6999 delete fmt;
7000 }
7001
TestExponentParse()7002 void NumberFormatTest::TestExponentParse() {
7003
7004 UErrorCode status = U_ZERO_ERROR;
7005 Formattable result;
7006 ParsePosition parsePos(0);
7007
7008 // set the exponent symbol
7009 status = U_ZERO_ERROR;
7010 DecimalFormatSymbols symbols(Locale::getDefault(), status);
7011 if(U_FAILURE(status)) {
7012 dataerrln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (Default)");
7013 return;
7014 }
7015
7016 // create format instance
7017 status = U_ZERO_ERROR;
7018 DecimalFormat fmt(u"#####", symbols, status);
7019 if(U_FAILURE(status)) {
7020 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
7021 }
7022
7023 // parse the text
7024 fmt.parse("5.06e-27", result, parsePos);
7025 if(result.getType() != Formattable::kDouble &&
7026 result.getDouble() != 5.06E-27 &&
7027 parsePos.getIndex() != 8
7028 )
7029 {
7030 errln("ERROR: parse failed - expected 5.06E-27, 8 - returned %d, %i",
7031 result.getDouble(), parsePos.getIndex());
7032 }
7033 }
7034
TestExplicitParents()7035 void NumberFormatTest::TestExplicitParents() {
7036
7037 /* Test that number formats are properly inherited from es_419 */
7038 /* These could be subject to change if the CLDR data changes */
7039 static const char* parentLocaleTests[][2]= {
7040 /* locale ID */ /* expected */
7041 {"es_CO", "1.250,75" },
7042 {"es_ES", "1.250,75" },
7043 {"es_GQ", "1.250,75" },
7044 {"es_MX", "1,250.75" },
7045 {"es_US", "1,250.75" },
7046 {"es_VE", "1.250,75" },
7047 };
7048
7049 UnicodeString s;
7050
7051 for(int i=0; i < UPRV_LENGTHOF(parentLocaleTests); i++){
7052 UErrorCode status = U_ZERO_ERROR;
7053 const char *localeID = parentLocaleTests[i][0];
7054 UnicodeString expected(parentLocaleTests[i][1], -1, US_INV);
7055 expected = expected.unescape();
7056 char loc[256]={0};
7057 uloc_canonicalize(localeID, loc, 256, &status);
7058 NumberFormat *fmt= NumberFormat::createInstance(Locale(loc), status);
7059 if(U_FAILURE(status)){
7060 dataerrln("Could not create number formatter for locale %s - %s",localeID, u_errorName(status));
7061 continue;
7062 }
7063 s.remove();
7064 fmt->format(1250.75, s);
7065 if(s!=expected){
7066 errln(UnicodeString("FAIL: Expected: ")+expected
7067 + UnicodeString(" Got: ") + s
7068 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
7069 }
7070 if (U_FAILURE(status)){
7071 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
7072 }
7073 delete fmt;
7074 }
7075
7076 }
7077
7078 /**
7079 * Test available numbering systems API.
7080 */
TestAvailableNumberingSystems()7081 void NumberFormatTest::TestAvailableNumberingSystems() {
7082 IcuTestErrorCode status(*this, "TestAvailableNumberingSystems");
7083 StringEnumeration *availableNumberingSystems = NumberingSystem::getAvailableNames(status);
7084 CHECK_DATA(status, "NumberingSystem::getAvailableNames()");
7085
7086 int32_t nsCount = availableNumberingSystems->count(status);
7087 if ( nsCount < 74 ) {
7088 errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 74, got %d",nsCount);
7089 }
7090
7091 /* A relatively simple test of the API. We call getAvailableNames() and cycle through */
7092 /* each name returned, attempting to create a numbering system based on that name and */
7093 /* verifying that the name returned from the resulting numbering system is the same */
7094 /* one that we initially thought. */
7095
7096 int32_t len;
7097 const char* prevName = nullptr;
7098 for ( int32_t i = 0 ; i < nsCount ; i++ ) {
7099 const char *nsname = availableNumberingSystems->next(&len,status);
7100 NumberingSystem* ns = NumberingSystem::createInstanceByName(nsname,status);
7101 logln("OK for ns = %s",nsname);
7102 if ( uprv_strcmp(nsname,ns->getName()) ) {
7103 errln("FAIL: Numbering system name didn't match for name = %s\n",nsname);
7104 }
7105 if (prevName != nullptr) {
7106 int comp = uprv_strcmp(prevName, nsname);
7107 assertTrue(
7108 UnicodeString(u"NS names should be in alphabetical order: ")
7109 + prevName + u" vs " + nsname,
7110 // TODO: Why are there duplicates? This doesn't work if comp < 0
7111 comp <= 0);
7112 }
7113 prevName = nsname;
7114
7115 delete ns;
7116 }
7117
7118 LocalPointer<NumberingSystem> dummy(NumberingSystem::createInstanceByName("dummy", status), status);
7119 status.expectErrorAndReset(U_UNSUPPORTED_ERROR);
7120 assertTrue("Non-existent numbering system should return null", dummy.isNull());
7121
7122 delete availableNumberingSystems;
7123 }
7124
7125 void
Test9087(void)7126 NumberFormatTest::Test9087(void)
7127 {
7128 U_STRING_DECL(pattern,"#",1);
7129 U_STRING_INIT(pattern,"#",1);
7130
7131 U_STRING_DECL(infstr,"INF",3);
7132 U_STRING_INIT(infstr,"INF",3);
7133
7134 U_STRING_DECL(nanstr,"NAN",3);
7135 U_STRING_INIT(nanstr,"NAN",3);
7136
7137 UChar outputbuf[50] = {0};
7138 UErrorCode status = U_ZERO_ERROR;
7139 UNumberFormat* fmt = unum_open(UNUM_PATTERN_DECIMAL,pattern,1,NULL,NULL,&status);
7140 if ( U_FAILURE(status) ) {
7141 dataerrln("FAIL: error in unum_open() - %s", u_errorName(status));
7142 return;
7143 }
7144
7145 unum_setSymbol(fmt,UNUM_INFINITY_SYMBOL,infstr,3,&status);
7146 unum_setSymbol(fmt,UNUM_NAN_SYMBOL,nanstr,3,&status);
7147 if ( U_FAILURE(status) ) {
7148 errln("FAIL: error setting symbols");
7149 }
7150
7151 double inf = uprv_getInfinity();
7152
7153 unum_setAttribute(fmt,UNUM_ROUNDING_MODE,UNUM_ROUND_HALFEVEN);
7154 unum_setDoubleAttribute(fmt,UNUM_ROUNDING_INCREMENT,0);
7155
7156 UFieldPosition position = { 0, 0, 0};
7157 unum_formatDouble(fmt,inf,outputbuf,50,&position,&status);
7158
7159 if ( u_strcmp(infstr, outputbuf)) {
7160 errln((UnicodeString)"FAIL: unexpected result for infinity - expected " + infstr + " got " + outputbuf);
7161 }
7162
7163 unum_close(fmt);
7164 }
7165
TestFormatFastpaths()7166 void NumberFormatTest::TestFormatFastpaths() {
7167 // get some additional case
7168 {
7169 UErrorCode status=U_ZERO_ERROR;
7170 DecimalFormat df(UnicodeString(u"0000"),status);
7171 if (U_FAILURE(status)) {
7172 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7173 } else {
7174 int64_t long_number = 1;
7175 UnicodeString expect = "0001";
7176 UnicodeString result;
7177 FieldPosition pos;
7178 df.format(long_number, result, pos);
7179 if(U_FAILURE(status)||expect!=result) {
7180 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s",
7181 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7182 } else {
7183 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
7184 }
7185 }
7186 }
7187 {
7188 UErrorCode status=U_ZERO_ERROR;
7189 DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7190 if (U_FAILURE(status)) {
7191 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7192 } else {
7193 int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
7194 // uint8_t bits[8];
7195 // memcpy(bits,&long_number,8);
7196 // for(int i=0;i<8;i++) {
7197 // logln("bits: %02X", (unsigned int)bits[i]);
7198 // }
7199 UnicodeString expect = "-9223372036854775808";
7200 UnicodeString result;
7201 FieldPosition pos;
7202 df.format(long_number, result, pos);
7203 if(U_FAILURE(status)||expect!=result) {
7204 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775808",
7205 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7206 } else {
7207 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
7208 }
7209 }
7210 }
7211 {
7212 UErrorCode status=U_ZERO_ERROR;
7213 DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7214 if (U_FAILURE(status)) {
7215 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7216 } else {
7217 int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
7218 // uint8_t bits[8];
7219 // memcpy(bits,&long_number,8);
7220 // for(int i=0;i<8;i++) {
7221 // logln("bits: %02X", (unsigned int)bits[i]);
7222 // }
7223 UnicodeString expect = "9223372036854775807";
7224 UnicodeString result;
7225 FieldPosition pos;
7226 df.format(long_number, result, pos);
7227 if(U_FAILURE(status)||expect!=result) {
7228 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on U_INT64_MAX",
7229 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7230 } else {
7231 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
7232 }
7233 }
7234 }
7235 {
7236 UErrorCode status=U_ZERO_ERROR;
7237 DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7238 if (U_FAILURE(status)) {
7239 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7240 } else {
7241 int64_t long_number = 0;
7242 // uint8_t bits[8];
7243 // memcpy(bits,&long_number,8);
7244 // for(int i=0;i<8;i++) {
7245 // logln("bits: %02X", (unsigned int)bits[i]);
7246 // }
7247 UnicodeString expect = "0000000000000000000";
7248 UnicodeString result;
7249 FieldPosition pos;
7250 df.format(long_number, result, pos);
7251 if(U_FAILURE(status)||expect!=result) {
7252 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on 0",
7253 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7254 } else {
7255 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
7256 }
7257 }
7258 }
7259 {
7260 UErrorCode status=U_ZERO_ERROR;
7261 DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7262 if (U_FAILURE(status)) {
7263 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7264 } else {
7265 int64_t long_number = U_INT64_MIN + 1;
7266 UnicodeString expect = "-9223372036854775807";
7267 UnicodeString result;
7268 FieldPosition pos;
7269 df.format(long_number, result, pos);
7270 if(U_FAILURE(status)||expect!=result) {
7271 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775807",
7272 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7273 } else {
7274 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
7275 }
7276 }
7277 }
7278 }
7279
7280
TestFormattableSize(void)7281 void NumberFormatTest::TestFormattableSize(void) {
7282 if(sizeof(Formattable) > 112) {
7283 errln("Error: sizeof(Formattable)=%d, 112=%d\n",
7284 sizeof(Formattable), 112);
7285 } else if(sizeof(Formattable) < 112) {
7286 logln("Warning: sizeof(Formattable)=%d, 112=%d\n",
7287 sizeof(Formattable), 112);
7288 } else {
7289 logln("sizeof(Formattable)=%d, 112=%d\n",
7290 sizeof(Formattable), 112);
7291 }
7292 }
7293
testFormattableAsUFormattable(const char * file,int line,Formattable & f)7294 UBool NumberFormatTest::testFormattableAsUFormattable(const char *file, int line, Formattable &f) {
7295 UnicodeString fileLine = UnicodeString(file)+UnicodeString(":")+line+UnicodeString(": ");
7296
7297 UFormattable *u = f.toUFormattable();
7298 logln();
7299 if (u == NULL) {
7300 errln("%s:%d: Error: f.toUFormattable() retuned NULL.");
7301 return FALSE;
7302 }
7303 logln("%s:%d: comparing Formattable with UFormattable", file, line);
7304 logln(fileLine + toString(f));
7305
7306 UErrorCode status = U_ZERO_ERROR;
7307 UErrorCode valueStatus = U_ZERO_ERROR;
7308 UFormattableType expectUType = UFMT_COUNT; // invalid
7309
7310 UBool triedExact = FALSE; // did we attempt an exact comparison?
7311 UBool exactMatch = FALSE; // was the exact comparison true?
7312
7313 switch( f.getType() ) {
7314 case Formattable::kDate:
7315 expectUType = UFMT_DATE;
7316 exactMatch = (f.getDate()==ufmt_getDate(u, &valueStatus));
7317 triedExact = TRUE;
7318 break;
7319 case Formattable::kDouble:
7320 expectUType = UFMT_DOUBLE;
7321 exactMatch = (f.getDouble()==ufmt_getDouble(u, &valueStatus));
7322 triedExact = TRUE;
7323 break;
7324 case Formattable::kLong:
7325 expectUType = UFMT_LONG;
7326 exactMatch = (f.getLong()==ufmt_getLong(u, &valueStatus));
7327 triedExact = TRUE;
7328 break;
7329 case Formattable::kString:
7330 expectUType = UFMT_STRING;
7331 {
7332 UnicodeString str;
7333 f.getString(str);
7334 int32_t len;
7335 const UChar* uch = ufmt_getUChars(u, &len, &valueStatus);
7336 if(U_SUCCESS(valueStatus)) {
7337 UnicodeString str2(uch, len);
7338 assertTrue("UChar* NULL-terminated", uch[len]==0);
7339 exactMatch = (str == str2);
7340 }
7341 triedExact = TRUE;
7342 }
7343 break;
7344 case Formattable::kArray:
7345 expectUType = UFMT_ARRAY;
7346 triedExact = TRUE;
7347 {
7348 int32_t count = ufmt_getArrayLength(u, &valueStatus);
7349 int32_t count2;
7350 const Formattable *array2 = f.getArray(count2);
7351 exactMatch = assertEquals(fileLine + " array count", count, count2);
7352
7353 if(exactMatch) {
7354 for(int i=0;U_SUCCESS(valueStatus) && i<count;i++) {
7355 UFormattable *uu = ufmt_getArrayItemByIndex(u, i, &valueStatus);
7356 if(*Formattable::fromUFormattable(uu) != (array2[i])) {
7357 errln("%s:%d: operator== did not match at index[%d] - %p vs %p", file, line, i,
7358 (const void*)Formattable::fromUFormattable(uu), (const void*)&(array2[i]));
7359 exactMatch = FALSE;
7360 } else {
7361 if(!testFormattableAsUFormattable("(sub item)",i,*Formattable::fromUFormattable(uu))) {
7362 exactMatch = FALSE;
7363 }
7364 }
7365 }
7366 }
7367 }
7368 break;
7369 case Formattable::kInt64:
7370 expectUType = UFMT_INT64;
7371 exactMatch = (f.getInt64()==ufmt_getInt64(u, &valueStatus));
7372 triedExact = TRUE;
7373 break;
7374 case Formattable::kObject:
7375 expectUType = UFMT_OBJECT;
7376 exactMatch = (f.getObject()==ufmt_getObject(u, &valueStatus));
7377 triedExact = TRUE;
7378 break;
7379 }
7380 UFormattableType uType = ufmt_getType(u, &status);
7381
7382 if(U_FAILURE(status)) {
7383 errln("%s:%d: Error calling ufmt_getType - %s", file, line, u_errorName(status));
7384 return FALSE;
7385 }
7386
7387 if(uType != expectUType) {
7388 errln("%s:%d: got type (%d) expected (%d) from ufmt_getType", file, line, (int) uType, (int) expectUType);
7389 }
7390
7391 if(triedExact) {
7392 if(U_FAILURE(valueStatus)) {
7393 errln("%s:%d: got err %s trying to ufmt_get...() for exact match check", file, line, u_errorName(valueStatus));
7394 } else if(!exactMatch) {
7395 errln("%s:%d: failed exact match for the Formattable type", file, line);
7396 } else {
7397 logln("%s:%d: exact match OK", file, line);
7398 }
7399 } else {
7400 logln("%s:%d: note, did not attempt exact match for this formattable type", file, line);
7401 }
7402
7403 if( assertEquals(fileLine + " isNumeric()", f.isNumeric(), ufmt_isNumeric(u))
7404 && f.isNumeric()) {
7405 UErrorCode convStatus = U_ZERO_ERROR;
7406
7407 if(uType != UFMT_INT64) { // may fail to compare
7408 assertTrue(fileLine + " as doubles ==", f.getDouble(convStatus)==ufmt_getDouble(u, &convStatus));
7409 }
7410
7411 if( assertSuccess(fileLine + " (numeric conversion status)", convStatus) ) {
7412 StringPiece fDecNum = f.getDecimalNumber(convStatus);
7413 #if 1
7414 int32_t len;
7415 const char *decNumChars = ufmt_getDecNumChars(u, &len, &convStatus);
7416 #else
7417 // copy version
7418 char decNumChars[200];
7419 int32_t len = ufmt_getDecNumChars(u, decNumChars, 200, &convStatus);
7420 #endif
7421
7422 if( assertSuccess(fileLine + " (decNumbers conversion)", convStatus) ) {
7423 logln(fileLine + decNumChars);
7424 assertEquals(fileLine + " decNumChars length==", len, fDecNum.length());
7425 assertEquals(fileLine + " decNumChars digits", decNumChars, fDecNum.data());
7426 }
7427
7428 UErrorCode int64ConversionF = U_ZERO_ERROR;
7429 int64_t l = f.getInt64(int64ConversionF);
7430 UErrorCode int64ConversionU = U_ZERO_ERROR;
7431 int64_t r = ufmt_getInt64(u, &int64ConversionU);
7432
7433 if( (l==r)
7434 && ( uType != UFMT_INT64 ) // int64 better not overflow
7435 && (U_INVALID_FORMAT_ERROR==int64ConversionU)
7436 && (U_INVALID_FORMAT_ERROR==int64ConversionF) ) {
7437 logln("%s:%d: OK: 64 bit overflow", file, line);
7438 } else {
7439 assertEquals(fileLine + " as int64 ==", l, r);
7440 assertSuccess(fileLine + " Formattable.getnt64()", int64ConversionF);
7441 assertSuccess(fileLine + " ufmt_getInt64()", int64ConversionU);
7442 }
7443 }
7444 }
7445 return exactMatch || !triedExact;
7446 }
7447
TestUFormattable(void)7448 void NumberFormatTest::TestUFormattable(void) {
7449 {
7450 // test that a default formattable is equal to Formattable()
7451 UErrorCode status = U_ZERO_ERROR;
7452 LocalUFormattablePointer defaultUFormattable(ufmt_open(&status));
7453 assertSuccess("calling umt_open", status);
7454 Formattable defaultFormattable;
7455 assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7456 (defaultFormattable
7457 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7458 assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7459 (defaultFormattable
7460 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7461 assertTrue((UnicodeString)"comparing Formattable() round tripped through UFormattable",
7462 (defaultFormattable
7463 == *(Formattable::fromUFormattable(defaultFormattable.toUFormattable()))));
7464 assertTrue((UnicodeString)"comparing &Formattable() round tripped through UFormattable",
7465 ((&defaultFormattable)
7466 == Formattable::fromUFormattable(defaultFormattable.toUFormattable())));
7467 assertFalse((UnicodeString)"comparing &Formattable() with ufmt_open()",
7468 ((&defaultFormattable)
7469 == Formattable::fromUFormattable(defaultUFormattable.getAlias())));
7470 testFormattableAsUFormattable(__FILE__, __LINE__, defaultFormattable);
7471 }
7472 // test some random Formattables
7473 {
7474 Formattable f(ucal_getNow(), Formattable::kIsDate);
7475 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7476 }
7477 {
7478 Formattable f((double)1.61803398874989484820); // golden ratio
7479 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7480 }
7481 {
7482 Formattable f((int64_t)80994231587905127LL); // weight of the moon, in kilotons http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
7483 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7484 }
7485 {
7486 Formattable f((int32_t)4); // random number, source: http://www.xkcd.com/221/
7487 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7488 }
7489 {
7490 Formattable f("Hello world."); // should be invariant?
7491 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7492 }
7493 {
7494 UErrorCode status2 = U_ZERO_ERROR;
7495 Formattable f(StringPiece("73476730924573500000000.0"), status2); // weight of the moon, kg
7496 assertSuccess("Constructing a StringPiece", status2);
7497 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7498 }
7499 {
7500 UErrorCode status2 = U_ZERO_ERROR;
7501 UObject *obj = new Locale();
7502 Formattable f(obj);
7503 assertSuccess("Constructing a Formattable from a default constructed Locale()", status2);
7504 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7505 }
7506 {
7507 const Formattable array[] = {
7508 Formattable(ucal_getNow(), Formattable::kIsDate),
7509 Formattable((int32_t)4),
7510 Formattable((double)1.234),
7511 };
7512
7513 Formattable fa(array, 3);
7514 testFormattableAsUFormattable(__FILE__, __LINE__, fa);
7515 }
7516 }
7517
TestSignificantDigits(void)7518 void NumberFormatTest::TestSignificantDigits(void) {
7519 double input[] = {
7520 0, 0,
7521 0.1, -0.1,
7522 123, -123,
7523 12345, -12345,
7524 123.45, -123.45,
7525 123.44501, -123.44501,
7526 0.001234, -0.001234,
7527 0.00000000123, -0.00000000123,
7528 0.0000000000000000000123, -0.0000000000000000000123,
7529 1.2, -1.2,
7530 0.0000000012344501, -0.0000000012344501,
7531 123445.01, -123445.01,
7532 12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0,
7533 };
7534 const char* expected[] = {
7535 "0.00", "0.00",
7536 "0.100", "-0.100",
7537 "123", "-123",
7538 "12345", "-12345",
7539 "123.45", "-123.45",
7540 "123.45", "-123.45",
7541 "0.001234", "-0.001234",
7542 "0.00000000123", "-0.00000000123",
7543 "0.0000000000000000000123", "-0.0000000000000000000123",
7544 "1.20", "-1.20",
7545 "0.0000000012345", "-0.0000000012345",
7546 "123450", "-123450",
7547 "12345000000000000000000000000000000", "-12345000000000000000000000000000000",
7548 };
7549
7550 UErrorCode status = U_ZERO_ERROR;
7551 Locale locale("en_US");
7552 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7553 NumberFormat::createInstance(locale, status)));
7554 CHECK_DATA(status,"NumberFormat::createInstance");
7555
7556 numberFormat->setSignificantDigitsUsed(TRUE);
7557 numberFormat->setMinimumSignificantDigits(3);
7558 numberFormat->setMaximumSignificantDigits(5);
7559 numberFormat->setGroupingUsed(false);
7560
7561 UnicodeString result;
7562 UnicodeString expectedResult;
7563 for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
7564 numberFormat->format(input[i], result);
7565 UnicodeString expectedResult(expected[i]);
7566 if (result != expectedResult) {
7567 errln((UnicodeString)"Expected: '" + expectedResult + "' got '" + result);
7568 }
7569 result.remove();
7570 }
7571
7572 // Test for ICU-20063
7573 {
7574 DecimalFormat df({"en-us", status}, status);
7575 df.setSignificantDigitsUsed(TRUE);
7576 expect(df, 9.87654321, u"9.87654");
7577 df.setMaximumSignificantDigits(3);
7578 expect(df, 9.87654321, u"9.88");
7579 // setSignificantDigitsUsed with maxSig only
7580 df.setSignificantDigitsUsed(TRUE);
7581 expect(df, 9.87654321, u"9.88");
7582 df.setMinimumSignificantDigits(2);
7583 expect(df, 9, u"9.0");
7584 // setSignificantDigitsUsed with both minSig and maxSig
7585 df.setSignificantDigitsUsed(TRUE);
7586 expect(df, 9, u"9.0");
7587 // setSignificantDigitsUsed to false: should revert to fraction rounding
7588 df.setSignificantDigitsUsed(FALSE);
7589 expect(df, 9.87654321, u"9.876543");
7590 expect(df, 9, u"9");
7591 df.setSignificantDigitsUsed(TRUE);
7592 df.setMinimumSignificantDigits(2);
7593 expect(df, 9.87654321, u"9.87654");
7594 expect(df, 9, u"9.0");
7595 // setSignificantDigitsUsed with minSig only
7596 df.setSignificantDigitsUsed(TRUE);
7597 expect(df, 9.87654321, u"9.87654");
7598 expect(df, 9, u"9.0");
7599 }
7600 }
7601
TestShowZero()7602 void NumberFormatTest::TestShowZero() {
7603 UErrorCode status = U_ZERO_ERROR;
7604 Locale locale("en_US");
7605 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7606 NumberFormat::createInstance(locale, status)));
7607 CHECK_DATA(status, "NumberFormat::createInstance");
7608
7609 numberFormat->setSignificantDigitsUsed(TRUE);
7610 numberFormat->setMaximumSignificantDigits(3);
7611
7612 UnicodeString result;
7613 numberFormat->format(0.0, result);
7614 if (result != "0") {
7615 errln((UnicodeString)"Expected: 0, got " + result);
7616 }
7617 }
7618
TestBug9936()7619 void NumberFormatTest::TestBug9936() {
7620 UErrorCode status = U_ZERO_ERROR;
7621 Locale locale("en_US");
7622 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7623 NumberFormat::createInstance(locale, status)));
7624 if (U_FAILURE(status)) {
7625 dataerrln("File %s, Line %d: status = %s.\n", __FILE__, __LINE__, u_errorName(status));
7626 return;
7627 }
7628
7629 if (numberFormat->areSignificantDigitsUsed() == TRUE) {
7630 errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
7631 }
7632 numberFormat->setSignificantDigitsUsed(TRUE);
7633 if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7634 errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7635 }
7636
7637 numberFormat->setSignificantDigitsUsed(FALSE);
7638 if (numberFormat->areSignificantDigitsUsed() == TRUE) {
7639 errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
7640 }
7641
7642 numberFormat->setMinimumSignificantDigits(3);
7643 if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7644 errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7645 }
7646
7647 numberFormat->setSignificantDigitsUsed(FALSE);
7648 numberFormat->setMaximumSignificantDigits(6);
7649 if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7650 errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7651 }
7652
7653 }
7654
TestParseNegativeWithFaLocale()7655 void NumberFormatTest::TestParseNegativeWithFaLocale() {
7656 UErrorCode status = U_ZERO_ERROR;
7657 DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status);
7658 CHECK_DATA(status, "NumberFormat::createInstance");
7659 test->setLenient(TRUE);
7660 Formattable af;
7661 ParsePosition ppos;
7662 UnicodeString value("\\u200e-0,5");
7663 value = value.unescape();
7664 test->parse(value, af, ppos);
7665 if (ppos.getIndex() == 0) {
7666 errln("Expected -0,5 to parse for Farsi.");
7667 }
7668 delete test;
7669 }
7670
TestParseNegativeWithAlternateMinusSign()7671 void NumberFormatTest::TestParseNegativeWithAlternateMinusSign() {
7672 UErrorCode status = U_ZERO_ERROR;
7673 DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("en", status);
7674 CHECK_DATA(status, "NumberFormat::createInstance");
7675 test->setLenient(TRUE);
7676 Formattable af;
7677 ParsePosition ppos;
7678 UnicodeString value("\\u208B0.5");
7679 value = value.unescape();
7680 test->parse(value, af, ppos);
7681 if (ppos.getIndex() == 0) {
7682 errln(UnicodeString("Expected ") + value + UnicodeString(" to parse."));
7683 }
7684 delete test;
7685 }
7686
TestCustomCurrencySignAndSeparator()7687 void NumberFormatTest::TestCustomCurrencySignAndSeparator() {
7688 UErrorCode status = U_ZERO_ERROR;
7689 DecimalFormatSymbols custom(Locale::getUS(), status);
7690 CHECK(status, "DecimalFormatSymbols constructor");
7691
7692 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "*");
7693 custom.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, "^");
7694 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, ":");
7695
7696 UnicodeString pat(" #,##0.00");
7697 pat.insert(0, (UChar)0x00A4);
7698
7699 DecimalFormat fmt(pat, custom, status);
7700 CHECK(status, "DecimalFormat constructor");
7701
7702 UnicodeString numstr("* 1^234:56");
7703 expect2(fmt, (Formattable)((double)1234.56), numstr);
7704 }
7705
7706 typedef struct {
7707 const char * locale;
7708 UBool lenient;
7709 UnicodeString numString;
7710 double value;
7711 } SignsAndMarksItem;
7712
7713
TestParseSignsAndMarks()7714 void NumberFormatTest::TestParseSignsAndMarks() {
7715 const SignsAndMarksItem items[] = {
7716 // locale lenient numString value
7717 { "en", FALSE, CharsToUnicodeString("12"), 12 },
7718 { "en", TRUE, CharsToUnicodeString("12"), 12 },
7719 { "en", FALSE, CharsToUnicodeString("-23"), -23 },
7720 { "en", TRUE, CharsToUnicodeString("-23"), -23 },
7721 { "en", TRUE, CharsToUnicodeString("- 23"), -23 },
7722 { "en", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
7723 { "en", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
7724 { "en", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
7725
7726 { "en@numbers=arab", FALSE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7727 { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7728 { "en@numbers=arab", FALSE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7729 { "en@numbers=arab", TRUE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7730 { "en@numbers=arab", TRUE, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
7731 { "en@numbers=arab", FALSE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7732 { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7733 { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
7734
7735 { "en@numbers=arabext", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7736 { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7737 { "en@numbers=arabext", FALSE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7738 { "en@numbers=arabext", TRUE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7739 { "en@numbers=arabext", TRUE, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
7740 { "en@numbers=arabext", FALSE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7741 { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7742 { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
7743
7744 { "he", FALSE, CharsToUnicodeString("12"), 12 },
7745 { "he", TRUE, CharsToUnicodeString("12"), 12 },
7746 { "he", FALSE, CharsToUnicodeString("-23"), -23 },
7747 { "he", TRUE, CharsToUnicodeString("-23"), -23 },
7748 { "he", TRUE, CharsToUnicodeString("- 23"), -23 },
7749 { "he", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
7750 { "he", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
7751 { "he", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
7752
7753 { "ar", FALSE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7754 { "ar", TRUE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7755 { "ar", FALSE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7756 { "ar", TRUE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7757 { "ar", TRUE, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
7758 { "ar", FALSE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7759 { "ar", TRUE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7760 { "ar", TRUE, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
7761
7762 { "ar_MA", FALSE, CharsToUnicodeString("12"), 12 },
7763 { "ar_MA", TRUE, CharsToUnicodeString("12"), 12 },
7764 { "ar_MA", FALSE, CharsToUnicodeString("-23"), -23 },
7765 { "ar_MA", TRUE, CharsToUnicodeString("-23"), -23 },
7766 { "ar_MA", TRUE, CharsToUnicodeString("- 23"), -23 },
7767 { "ar_MA", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
7768 { "ar_MA", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
7769 { "ar_MA", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
7770
7771 { "fa", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7772 { "fa", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7773 { "fa", FALSE, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
7774 { "fa", TRUE, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
7775 { "fa", TRUE, CharsToUnicodeString("\\u2212 \\u06F6\\u06F7"), -67 },
7776 { "fa", FALSE, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
7777 { "fa", TRUE, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
7778 { "fa", TRUE, CharsToUnicodeString("\\u200E\\u2212\\u200E \\u06F6\\u06F7"), -67 },
7779
7780 { "ps", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7781 { "ps", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7782 { "ps", FALSE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7783 { "ps", TRUE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7784 { "ps", TRUE, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
7785 { "ps", FALSE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7786 { "ps", TRUE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7787 { "ps", TRUE, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
7788 { "ps", FALSE, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
7789 { "ps", TRUE, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
7790 { "ps", TRUE, CharsToUnicodeString("-\\u200E \\u06F6\\u06F7"), -67 },
7791 // terminator
7792 { NULL, 0, UnicodeString(""), 0 },
7793 };
7794
7795 const SignsAndMarksItem * itemPtr;
7796 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
7797 UErrorCode status = U_ZERO_ERROR;
7798 NumberFormat *numfmt = NumberFormat::createInstance(Locale(itemPtr->locale), status);
7799 if (U_SUCCESS(status)) {
7800 numfmt->setLenient(itemPtr->lenient);
7801 Formattable fmtobj;
7802 ParsePosition ppos;
7803 numfmt->parse(itemPtr->numString, fmtobj, ppos);
7804 if (ppos.getIndex() == itemPtr->numString.length()) {
7805 double parsedValue = fmtobj.getDouble(status);
7806 if (U_FAILURE(status) || parsedValue != itemPtr->value) {
7807 errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives value " + parsedValue);
7808 }
7809 } else {
7810 errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives position " + ppos.getIndex());
7811 }
7812 } else {
7813 dataerrln("FAIL: NumberFormat::createInstance for locale % gives error %s", itemPtr->locale, u_errorName(status));
7814 }
7815 delete numfmt;
7816 }
7817 }
7818
7819 typedef struct {
7820 DecimalFormat::ERoundingMode mode;
7821 double value;
7822 UnicodeString expected;
7823 } Test10419Data;
7824
7825
7826 // Tests that rounding works right when fractional digits is set to 0.
Test10419RoundingWith0FractionDigits()7827 void NumberFormatTest::Test10419RoundingWith0FractionDigits() {
7828 const Test10419Data items[] = {
7829 { DecimalFormat::kRoundCeiling, 1.488, "2"},
7830 { DecimalFormat::kRoundDown, 1.588, "1"},
7831 { DecimalFormat::kRoundFloor, 1.888, "1"},
7832 { DecimalFormat::kRoundHalfDown, 1.5, "1"},
7833 { DecimalFormat::kRoundHalfEven, 2.5, "2"},
7834 { DecimalFormat::kRoundHalfUp, 2.5, "3"},
7835 { DecimalFormat::kRoundUp, 1.5, "2"},
7836 };
7837 UErrorCode status = U_ZERO_ERROR;
7838 LocalPointer<DecimalFormat> decfmt((DecimalFormat *) NumberFormat::createInstance(Locale("en_US"), status));
7839 if (U_FAILURE(status)) {
7840 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
7841 return;
7842 }
7843 for (int32_t i = 0; i < UPRV_LENGTHOF(items); ++i) {
7844 decfmt->setRoundingMode(items[i].mode);
7845 decfmt->setMaximumFractionDigits(0);
7846 UnicodeString actual;
7847 if (items[i].expected != decfmt->format(items[i].value, actual)) {
7848 errln("Expected " + items[i].expected + ", got " + actual);
7849 }
7850 }
7851 }
7852
Test10468ApplyPattern()7853 void NumberFormatTest::Test10468ApplyPattern() {
7854 // Padding char of fmt is now 'a'
7855 UErrorCode status = U_ZERO_ERROR;
7856 DecimalFormat fmt("'I''ll'*a###.##", status);
7857
7858 if (U_FAILURE(status)) {
7859 errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7860 return;
7861 }
7862
7863 assertEquals("Padding character should be 'a'.", u"a", fmt.getPadCharacterString());
7864
7865 // Padding char of fmt ought to be '*' since that is the default and no
7866 // explicit padding char is specified in the new pattern.
7867 fmt.applyPattern("AA#,##0.00ZZ", status);
7868
7869 // Oops this still prints 'a' even though we changed the pattern.
7870 assertEquals("applyPattern did not clear padding character.", u" ", fmt.getPadCharacterString());
7871 }
7872
TestRoundingScientific10542()7873 void NumberFormatTest::TestRoundingScientific10542() {
7874 UErrorCode status = U_ZERO_ERROR;
7875 DecimalFormat format("0.00E0", status);
7876 if (U_FAILURE(status)) {
7877 errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7878 return;
7879 }
7880
7881 DecimalFormat::ERoundingMode roundingModes[] = {
7882 DecimalFormat::kRoundCeiling,
7883 DecimalFormat::kRoundDown,
7884 DecimalFormat::kRoundFloor,
7885 DecimalFormat::kRoundHalfDown,
7886 DecimalFormat::kRoundHalfEven,
7887 DecimalFormat::kRoundHalfUp,
7888 DecimalFormat::kRoundUp};
7889 const char *descriptions[] = {
7890 "Round Ceiling",
7891 "Round Down",
7892 "Round Floor",
7893 "Round half down",
7894 "Round half even",
7895 "Round half up",
7896 "Round up"};
7897
7898 {
7899 double values[] = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016};
7900 // The order of these expected values correspond to the order of roundingModes and the order of values.
7901 const char *expected[] = {
7902 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.02E-3", "3.02E-3", "3.02E-3",
7903 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7904 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7905 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.02E-3",
7906 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7907 "-3.01E-3", "-3.01E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7908 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.02E-3", "3.02E-3", "3.02E-3"};
7909 verifyRounding(
7910 format,
7911 values,
7912 expected,
7913 roundingModes,
7914 descriptions,
7915 UPRV_LENGTHOF(values),
7916 UPRV_LENGTHOF(roundingModes));
7917 }
7918 {
7919 double values[] = {-3006.0, -3005, -3004, 3014, 3015, 3016};
7920 // The order of these expected values correspond to the order of roundingModes and the order of values.
7921 const char *expected[] = {
7922 "-3.00E3", "-3.00E3", "-3.00E3", "3.02E3", "3.02E3", "3.02E3",
7923 "-3.00E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.01E3",
7924 "-3.01E3", "-3.01E3", "-3.01E3", "3.01E3", "3.01E3", "3.01E3",
7925 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.02E3",
7926 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7927 "-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7928 "-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"};
7929 verifyRounding(
7930 format,
7931 values,
7932 expected,
7933 roundingModes,
7934 descriptions,
7935 UPRV_LENGTHOF(values),
7936 UPRV_LENGTHOF(roundingModes));
7937 }
7938 /* Commented out for now until we decide how rounding to zero should work, +0 vs. -0
7939 {
7940 double values[] = {0.0, -0.0};
7941 // The order of these expected values correspond to the order of roundingModes and the order of values.
7942 const char *expected[] = {
7943 "0.00E0", "-0.00E0",
7944 "0.00E0", "-0.00E0",
7945 "0.00E0", "-0.00E0",
7946 "0.00E0", "-0.00E0",
7947 "0.00E0", "-0.00E0",
7948 "0.00E0", "-0.00E0",
7949 "0.00E0", "-0.00E0"};
7950 verifyRounding(
7951 format,
7952 values,
7953 expected,
7954 roundingModes,
7955 descriptions,
7956 UPRV_LENGTHOF(values),
7957 UPRV_LENGTHOF(roundingModes));
7958 }
7959 */
7960 {
7961
7962 double values[] = {1e25, 1e25 + 1e15, 1e25 - 1e15};
7963 // The order of these expected values correspond to the order of roundingModes and the order of values.
7964 const char *expected[] = {
7965 "1.00E25", "1.01E25", "1.00E25",
7966 "1.00E25", "1.00E25", "9.99E24",
7967 "1.00E25", "1.00E25", "9.99E24",
7968 "1.00E25", "1.00E25", "1.00E25",
7969 "1.00E25", "1.00E25", "1.00E25",
7970 "1.00E25", "1.00E25", "1.00E25",
7971 "1.00E25", "1.01E25", "1.00E25"};
7972 verifyRounding(
7973 format,
7974 values,
7975 expected,
7976 roundingModes,
7977 descriptions,
7978 UPRV_LENGTHOF(values),
7979 UPRV_LENGTHOF(roundingModes));
7980 }
7981 {
7982 double values[] = {-1e25, -1e25 + 1e15, -1e25 - 1e15};
7983 // The order of these expected values correspond to the order of roundingModes and the order of values.
7984 const char *expected[] = {
7985 "-1.00E25", "-9.99E24", "-1.00E25",
7986 "-1.00E25", "-9.99E24", "-1.00E25",
7987 "-1.00E25", "-1.00E25", "-1.01E25",
7988 "-1.00E25", "-1.00E25", "-1.00E25",
7989 "-1.00E25", "-1.00E25", "-1.00E25",
7990 "-1.00E25", "-1.00E25", "-1.00E25",
7991 "-1.00E25", "-1.00E25", "-1.01E25"};
7992 verifyRounding(
7993 format,
7994 values,
7995 expected,
7996 roundingModes,
7997 descriptions,
7998 UPRV_LENGTHOF(values),
7999 UPRV_LENGTHOF(roundingModes));
8000 }
8001 {
8002 double values[] = {1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
8003 // The order of these expected values correspond to the order of roundingModes and the order of values.
8004 const char *expected[] = {
8005 "1.00E-25", "1.01E-25", "1.00E-25",
8006 "1.00E-25", "1.00E-25", "9.99E-26",
8007 "1.00E-25", "1.00E-25", "9.99E-26",
8008 "1.00E-25", "1.00E-25", "1.00E-25",
8009 "1.00E-25", "1.00E-25", "1.00E-25",
8010 "1.00E-25", "1.00E-25", "1.00E-25",
8011 "1.00E-25", "1.01E-25", "1.00E-25"};
8012 verifyRounding(
8013 format,
8014 values,
8015 expected,
8016 roundingModes,
8017 descriptions,
8018 UPRV_LENGTHOF(values),
8019 UPRV_LENGTHOF(roundingModes));
8020 }
8021 {
8022 double values[] = {-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
8023 // The order of these expected values correspond to the order of roundingModes and the order of values.
8024 const char *expected[] = {
8025 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8026 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8027 "-1.00E-25", "-1.00E-25", "-1.01E-25",
8028 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8029 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8030 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8031 "-1.00E-25", "-1.00E-25", "-1.01E-25"};
8032 verifyRounding(
8033 format,
8034 values,
8035 expected,
8036 roundingModes,
8037 descriptions,
8038 UPRV_LENGTHOF(values),
8039 UPRV_LENGTHOF(roundingModes));
8040 }
8041 }
8042
TestZeroScientific10547()8043 void NumberFormatTest::TestZeroScientific10547() {
8044 UErrorCode status = U_ZERO_ERROR;
8045 DecimalFormat fmt("0.00E0", status);
8046 if (!assertSuccess("Format creation", status)) {
8047 return;
8048 }
8049 UnicodeString out;
8050 fmt.format(-0.0, out);
8051 assertEquals("format", "-0.00E0", out, true);
8052 }
8053
verifyRounding(DecimalFormat & format,const double * values,const char * const * expected,const DecimalFormat::ERoundingMode * roundingModes,const char * const * descriptions,int32_t valueSize,int32_t roundingModeSize)8054 void NumberFormatTest::verifyRounding(
8055 DecimalFormat& format,
8056 const double *values,
8057 const char * const *expected,
8058 const DecimalFormat::ERoundingMode *roundingModes,
8059 const char * const *descriptions,
8060 int32_t valueSize,
8061 int32_t roundingModeSize) {
8062 for (int32_t i = 0; i < roundingModeSize; ++i) {
8063 format.setRoundingMode(roundingModes[i]);
8064 for (int32_t j = 0; j < valueSize; j++) {
8065 UnicodeString currentExpected(expected[i * valueSize + j]);
8066 currentExpected = currentExpected.unescape();
8067 UnicodeString actual;
8068 format.format(values[j], actual);
8069 if (currentExpected != actual) {
8070 dataerrln("For %s value %f, expected '%s', got '%s'",
8071 descriptions[i], values[j], CStr(currentExpected)(), CStr(actual)());
8072 }
8073 }
8074 }
8075 }
8076
TestAccountingCurrency()8077 void NumberFormatTest::TestAccountingCurrency() {
8078 UErrorCode status = U_ZERO_ERROR;
8079 UNumberFormatStyle style = UNUM_CURRENCY_ACCOUNTING;
8080
8081 expect(NumberFormat::createInstance("en_US", style, status),
8082 (Formattable)(double)1234.5, "$1,234.50", TRUE, status);
8083 expect(NumberFormat::createInstance("en_US", style, status),
8084 (Formattable)(double)-1234.5, "($1,234.50)", TRUE, status);
8085 expect(NumberFormat::createInstance("en_US", style, status),
8086 (Formattable)(double)0, "$0.00", TRUE, status);
8087 expect(NumberFormat::createInstance("en_US", style, status),
8088 (Formattable)(double)-0.2, "($0.20)", TRUE, status);
8089 expect(NumberFormat::createInstance("ja_JP", style, status),
8090 (Formattable)(double)10000, UnicodeString("\\uFFE510,000").unescape(), TRUE, status);
8091 expect(NumberFormat::createInstance("ja_JP", style, status),
8092 (Formattable)(double)-1000.5, UnicodeString("(\\uFFE51,000)").unescape(), FALSE, status);
8093 expect(NumberFormat::createInstance("de_DE", style, status),
8094 (Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status);
8095 expect(NumberFormat::createInstance("en_ID", style, status),
8096 (Formattable)(double)0, UnicodeString("IDR\\u00A00.00").unescape(), TRUE, status);
8097 expect(NumberFormat::createInstance("en_ID", style, status),
8098 (Formattable)(double)-0.2, UnicodeString("(IDR\\u00A00.20)").unescape(), TRUE, status);
8099 expect(NumberFormat::createInstance("sh_ME", style, status),
8100 (Formattable)(double)0, UnicodeString("0,00\\u00A0\\u20AC").unescape(), TRUE, status);
8101 expect(NumberFormat::createInstance("sh_ME", style, status),
8102 (Formattable)(double)-0.2, UnicodeString("(0,20\\u00A0\\u20AC)").unescape(), TRUE, status);
8103 }
8104
8105 /**
8106 * ICU4J has the behavior explained below, but ICU4C is not affected. Test is added to prevent regression.
8107 *
8108 * en_ID/sh_ME uses language only locales en/sh which requires NumberFormatServiceShim to fill in the currency, but
8109 * prior to ICU-20631, currency was not filled in for accounting, cash and standard, so currency placeholder was
8110 * used instead of the desired locale's currency.
8111 */
TestCurrencyFormatForMissingLocale()8112 void NumberFormatTest::TestCurrencyFormatForMissingLocale() {
8113 IcuTestErrorCode status(*this, "TestCurrencyFormatForMissingLocale");
8114 Locale locale = Locale::createCanonical("sh_ME");
8115
8116 LocalPointer<NumberFormat> curFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status));
8117 // Fail here with missing data.
8118 if (!assertTrue(WHERE, curFmt.isValid(), false, true)) {return;};
8119 assertEquals("Currency instance is not for the desired locale for CURRENCYSTYLE", curFmt->getCurrency(), "EUR");
8120 UnicodeString currBuf;
8121 curFmt->format(-1234.5, currBuf);
8122 assertEquals("NumberFormat format outputs wrong value for CURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", currBuf);
8123
8124 LocalPointer<NumberFormat> accFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_ACCOUNTING, status));
8125 assertEquals("Currency instance is not for the desired locale for ACCOUNTINGCURRENCYSTYLE", accFmt->getCurrency(), "EUR");
8126 UnicodeString accBuf;
8127 accFmt->format(-1234.5, accBuf);
8128 assertEquals("NumberFormat format outputs wrong value for ACCOUNTINGCURRENCYSTYLE", u"(1.234,50\u00A0\u20AC)", accBuf);
8129
8130 LocalPointer<NumberFormat> cashFmt(NumberFormat::createInstance(locale, UNUM_CASH_CURRENCY, status));
8131 assertEquals("Currency instance is not for the desired locale for CASHCURRENCYSTYLE", cashFmt->getCurrency(), "EUR");
8132 UnicodeString cashBuf;
8133 cashFmt->format(-1234.5, cashBuf);
8134 assertEquals("NumberFormat format outputs wrong value for CASHCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", cashBuf);
8135
8136 LocalPointer<NumberFormat> stdFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_STANDARD, status));
8137 assertEquals("Currency instance is not for the desired locale for STANDARDCURRENCYSTYLE", stdFmt->getCurrency(), "EUR");
8138 UnicodeString stdBuf;
8139 stdFmt->format(-1234.5, stdBuf);
8140 assertEquals("NumberFormat format outputs wrong value for STANDARDCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", stdBuf);
8141 }
8142
8143 // for #5186
TestEquality()8144 void NumberFormatTest::TestEquality() {
8145 UErrorCode status = U_ZERO_ERROR;
8146 DecimalFormatSymbols symbols(Locale("root"), status);
8147 if (U_FAILURE(status)) {
8148 dataerrln("Fail: can't create DecimalFormatSymbols for root");
8149 return;
8150 }
8151 UnicodeString pattern("#,##0.###");
8152 DecimalFormat fmtBase(pattern, symbols, status);
8153 if (U_FAILURE(status)) {
8154 dataerrln("Fail: can't create DecimalFormat using root symbols");
8155 return;
8156 }
8157
8158 DecimalFormat* fmtClone = fmtBase.clone();
8159 fmtClone->setFormatWidth(fmtBase.getFormatWidth() + 32);
8160 if (*fmtClone == fmtBase) {
8161 errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth");
8162 }
8163 delete fmtClone;
8164 }
8165
TestCurrencyUsage()8166 void NumberFormatTest::TestCurrencyUsage() {
8167 double agent = 123.567;
8168
8169 UErrorCode status;
8170 DecimalFormat *fmt;
8171
8172 // compare the Currency and Currency Cash Digits
8173 // Note that as of CLDR 26:
8174 // * TWD and PKR switched from 0 decimals to 2; ISK still has 0, so change test to that
8175 // * CAD rounds to .05 in cash mode only
8176 // 1st time for getter/setter, 2nd time for factory method
8177 Locale enUS_ISK("en_US@currency=ISK");
8178
8179 for(int i=0; i<2; i++){
8180 status = U_ZERO_ERROR;
8181 if(i == 0){
8182 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CURRENCY, status);
8183 if (assertSuccess("en_US@currency=ISK/CURRENCY", status, TRUE) == FALSE) {
8184 continue;
8185 }
8186
8187 UnicodeString original;
8188 fmt->format(agent,original);
8189 assertEquals("Test Currency Usage 1", u"ISK\u00A0124", original);
8190
8191 // test the getter here
8192 UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8193 assertEquals("Test usage getter - standard", (int32_t)curUsage, (int32_t)UCURR_USAGE_STANDARD);
8194
8195 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8196 }else{
8197 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CASH_CURRENCY, status);
8198 if (assertSuccess("en_US@currency=ISK/CASH", status, TRUE) == FALSE) {
8199 continue;
8200 }
8201 }
8202
8203 // must be usage = cash
8204 UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8205 assertEquals("Test usage getter - cash", (int32_t)curUsage, (int32_t)UCURR_USAGE_CASH);
8206
8207 UnicodeString cash_currency;
8208 fmt->format(agent,cash_currency);
8209 assertEquals("Test Currency Usage 2", u"ISK\u00A0124", cash_currency);
8210 delete fmt;
8211 }
8212
8213 // compare the Currency and Currency Cash Rounding
8214 // 1st time for getter/setter, 2nd time for factory method
8215 Locale enUS_CAD("en_US@currency=CAD");
8216 for(int i=0; i<2; i++){
8217 status = U_ZERO_ERROR;
8218 if(i == 0){
8219 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8220 if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
8221 continue;
8222 }
8223
8224 UnicodeString original_rounding;
8225 fmt->format(agent, original_rounding);
8226 assertEquals("Test Currency Usage 3", u"CA$123.57", original_rounding);
8227 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8228 }else{
8229 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8230 if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
8231 continue;
8232 }
8233 }
8234
8235 UnicodeString cash_rounding_currency;
8236 fmt->format(agent, cash_rounding_currency);
8237 assertEquals("Test Currency Usage 4", u"CA$123.55", cash_rounding_currency);
8238 delete fmt;
8239 }
8240
8241 // Test the currency change
8242 // 1st time for getter/setter, 2nd time for factory method
8243 const UChar CUR_PKR[] = {0x50, 0x4B, 0x52, 0};
8244 for(int i=0; i<2; i++){
8245 status = U_ZERO_ERROR;
8246 if(i == 0){
8247 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8248 if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
8249 continue;
8250 }
8251 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8252 }else{
8253 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8254 if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
8255 continue;
8256 }
8257 }
8258
8259 UnicodeString cur_original;
8260 fmt->setCurrencyUsage(UCURR_USAGE_STANDARD, &status);
8261 fmt->format(agent, cur_original);
8262 assertEquals("Test Currency Usage 5", u"CA$123.57", cur_original);
8263
8264 fmt->setCurrency(CUR_PKR, status);
8265 assertSuccess("Set currency to PKR", status);
8266
8267 UnicodeString PKR_changed;
8268 fmt->format(agent, PKR_changed);
8269 assertEquals("Test Currency Usage 6", u"PKR\u00A0123.57", PKR_changed);
8270 delete fmt;
8271 }
8272 }
8273
8274
8275 // Check the constant MAX_INT64_IN_DOUBLE.
8276 // The value should convert to a double with no loss of precision.
8277 // A failure may indicate a platform with a different double format, requiring
8278 // a revision to the constant.
8279 //
8280 // Note that this is actually hard to test, because the language standard gives
8281 // compilers considerable flexibility to do unexpected things with rounding and
8282 // with overflow in simple int to/from float conversions. Some compilers will completely optimize
8283 // away a simple round-trip conversion from int64_t -> double -> int64_t.
8284
TestDoubleLimit11439()8285 void NumberFormatTest::TestDoubleLimit11439() {
8286 char buf[50];
8287 for (int64_t num = MAX_INT64_IN_DOUBLE-10; num<=MAX_INT64_IN_DOUBLE; num++) {
8288 sprintf(buf, "%lld", (long long)num);
8289 double fNum = 0.0;
8290 sscanf(buf, "%lf", &fNum);
8291 int64_t rtNum = static_cast<int64_t>(fNum);
8292 if (num != rtNum) {
8293 errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8294 return;
8295 }
8296 }
8297 for (int64_t num = -MAX_INT64_IN_DOUBLE+10; num>=-MAX_INT64_IN_DOUBLE; num--) {
8298 sprintf(buf, "%lld", (long long)num);
8299 double fNum = 0.0;
8300 sscanf(buf, "%lf", &fNum);
8301 int64_t rtNum = static_cast<int64_t>(fNum);
8302 if (num != rtNum) {
8303 errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8304 return;
8305 }
8306 }
8307 }
8308
TestGetAffixes()8309 void NumberFormatTest::TestGetAffixes() {
8310 UErrorCode status = U_ZERO_ERROR;
8311 DecimalFormatSymbols sym("en_US", status);
8312 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8313 pattern = pattern.unescape();
8314 DecimalFormat fmt(pattern, sym, status);
8315 if (U_FAILURE(status)) {
8316 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8317 return;
8318 }
8319 UnicodeString affixStr;
8320 assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8321 assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8322 assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8323 assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8324
8325 // Test equality with affixes. set affix methods can't capture special
8326 // characters which is why equality should fail.
8327 {
8328 DecimalFormat fmtCopy(fmt);
8329 assertTrue("", fmt == fmtCopy);
8330 UnicodeString someAffix;
8331 fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(someAffix));
8332 assertTrue("", fmt != fmtCopy);
8333 }
8334 {
8335 DecimalFormat fmtCopy(fmt);
8336 assertTrue("", fmt == fmtCopy);
8337 UnicodeString someAffix;
8338 fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(someAffix));
8339 assertTrue("", fmt != fmtCopy);
8340 }
8341 {
8342 DecimalFormat fmtCopy(fmt);
8343 assertTrue("", fmt == fmtCopy);
8344 UnicodeString someAffix;
8345 fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(someAffix));
8346 assertTrue("", fmt != fmtCopy);
8347 }
8348 {
8349 DecimalFormat fmtCopy(fmt);
8350 assertTrue("", fmt == fmtCopy);
8351 UnicodeString someAffix;
8352 fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(someAffix));
8353 assertTrue("", fmt != fmtCopy);
8354 }
8355 fmt.setPositivePrefix("Don't");
8356 fmt.setPositiveSuffix("do");
8357 UnicodeString someAffix("be''eet\\u00a4\\u00a4\\u00a4 it.");
8358 someAffix = someAffix.unescape();
8359 fmt.setNegativePrefix(someAffix);
8360 fmt.setNegativeSuffix("%");
8361 assertEquals("", "Don't", fmt.getPositivePrefix(affixStr));
8362 assertEquals("", "do", fmt.getPositiveSuffix(affixStr));
8363 assertEquals("", someAffix, fmt.getNegativePrefix(affixStr));
8364 assertEquals("", "%", fmt.getNegativeSuffix(affixStr));
8365 }
8366
TestToPatternScientific11648()8367 void NumberFormatTest::TestToPatternScientific11648() {
8368 UErrorCode status = U_ZERO_ERROR;
8369 Locale en("en");
8370 DecimalFormatSymbols sym(en, status);
8371 DecimalFormat fmt("0.00", sym, status);
8372 if (U_FAILURE(status)) {
8373 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8374 return;
8375 }
8376 fmt.setScientificNotation(TRUE);
8377 UnicodeString pattern;
8378 assertEquals("", "0.00E0", fmt.toPattern(pattern));
8379 DecimalFormat fmt2(pattern, sym, status);
8380 assertSuccess("", status);
8381 }
8382
TestBenchmark()8383 void NumberFormatTest::TestBenchmark() {
8384 /*
8385 UErrorCode status = U_ZERO_ERROR;
8386 Locale en("en");
8387 DecimalFormatSymbols sym(en, status);
8388 DecimalFormat fmt("0.0000000", new DecimalFormatSymbols(sym), status);
8389 // DecimalFormat fmt("0.00000E0", new DecimalFormatSymbols(sym), status);
8390 // DecimalFormat fmt("0", new DecimalFormatSymbols(sym), status);
8391 FieldPosition fpos(FieldPosition::DONT_CARE);
8392 clock_t start = clock();
8393 for (int32_t i = 0; i < 1000000; ++i) {
8394 UnicodeString append;
8395 fmt.format(3.0, append, fpos, status);
8396 // fmt.format(4.6692016, append, fpos, status);
8397 // fmt.format(1234567.8901, append, fpos, status);
8398 // fmt.format(2.99792458E8, append, fpos, status);
8399 // fmt.format(31, append);
8400 }
8401 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8402 assertSuccess("", status);
8403
8404 UErrorCode status = U_ZERO_ERROR;
8405 MessageFormat fmt("{0, plural, one {I have # friend.} other {I have # friends.}}", status);
8406 FieldPosition fpos(FieldPosition::DONT_CARE);
8407 Formattable one(1.0);
8408 Formattable three(3.0);
8409 clock_t start = clock();
8410 for (int32_t i = 0; i < 500000; ++i) {
8411 UnicodeString append;
8412 fmt.format(&one, 1, append, fpos, status);
8413 UnicodeString append2;
8414 fmt.format(&three, 1, append2, fpos, status);
8415 }
8416 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8417 assertSuccess("", status);
8418
8419 UErrorCode status = U_ZERO_ERROR;
8420 Locale en("en");
8421 Measure measureC(23, MeasureUnit::createCelsius(status), status);
8422 MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
8423 FieldPosition fpos(FieldPosition::DONT_CARE);
8424 clock_t start = clock();
8425 for (int32_t i = 0; i < 1000000; ++i) {
8426 UnicodeString appendTo;
8427 fmt.formatMeasures(
8428 &measureC, 1, appendTo, fpos, status);
8429 }
8430 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8431 assertSuccess("", status);
8432 */
8433 }
8434
TestFractionalDigitsForCurrency()8435 void NumberFormatTest::TestFractionalDigitsForCurrency() {
8436 UErrorCode status = U_ZERO_ERROR;
8437 LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance("en", status));
8438 if (U_FAILURE(status)) {
8439 dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8440 return;
8441 }
8442 UChar JPY[] = {0x4A, 0x50, 0x59, 0x0};
8443 fmt->setCurrency(JPY, status);
8444 if (!assertSuccess("", status)) {
8445 return;
8446 }
8447 assertEquals("", 0, fmt->getMaximumFractionDigits());
8448 }
8449
8450
TestFormatCurrencyPlural()8451 void NumberFormatTest::TestFormatCurrencyPlural() {
8452 UErrorCode status = U_ZERO_ERROR;
8453 Locale locale = Locale::createCanonical("en_US");
8454 NumberFormat *fmt = NumberFormat::createInstance(locale, UNUM_CURRENCY_PLURAL, status);
8455 if (U_FAILURE(status)) {
8456 dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8457 return;
8458 }
8459 UnicodeString formattedNum;
8460 fmt->format(11234.567, formattedNum, NULL, status);
8461 assertEquals("", "11,234.57 US dollars", formattedNum);
8462 delete fmt;
8463 }
8464
TestCtorApplyPatternDifference()8465 void NumberFormatTest::TestCtorApplyPatternDifference() {
8466 UErrorCode status = U_ZERO_ERROR;
8467 DecimalFormatSymbols sym("en_US", status);
8468 UnicodeString pattern("\\u00a40");
8469 DecimalFormat fmt(pattern.unescape(), sym, status);
8470 if (U_FAILURE(status)) {
8471 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8472 return;
8473 }
8474 UnicodeString result;
8475 assertEquals(
8476 "ctor favors precision of currency",
8477 "$5.00",
8478 fmt.format((double)5, result));
8479 result.remove();
8480 fmt.applyPattern(pattern.unescape(), status);
8481 assertEquals(
8482 "applyPattern favors precision of pattern",
8483 "$5",
8484 fmt.format((double)5, result));
8485 }
8486
Test11868()8487 void NumberFormatTest::Test11868() {
8488 double posAmt = 34.567;
8489 double negAmt = -9876.543;
8490
8491 Locale selectedLocale("en_US");
8492 UErrorCode status = U_ZERO_ERROR;
8493
8494 UnicodeString result;
8495 FieldPosition fpCurr(UNUM_CURRENCY_FIELD);
8496 LocalPointer<NumberFormat> fmt(
8497 NumberFormat::createInstance(
8498 selectedLocale, UNUM_CURRENCY_PLURAL, status));
8499 if (!assertSuccess("Format creation", status)) {
8500 return;
8501 }
8502 fmt->format(posAmt, result, fpCurr, status);
8503 assertEquals("", "34.57 US dollars", result);
8504 assertEquals("begin index", 6, fpCurr.getBeginIndex());
8505 assertEquals("end index", 16, fpCurr.getEndIndex());
8506
8507 // Test field position iterator
8508 {
8509 NumberFormatTest_Attributes attributes[] = {
8510 {UNUM_INTEGER_FIELD, 0, 2},
8511 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8512 {UNUM_FRACTION_FIELD, 3, 5},
8513 {UNUM_CURRENCY_FIELD, 6, 16},
8514 {0, -1, 0}};
8515 UnicodeString result;
8516 FieldPositionIterator iter;
8517 fmt->format(posAmt, result, &iter, status);
8518 assertEquals("", "34.57 US dollars", result);
8519 verifyFieldPositionIterator(attributes, iter);
8520 }
8521
8522 result.remove();
8523 fmt->format(negAmt, result, fpCurr, status);
8524 assertEquals("", "-9,876.54 US dollars", result);
8525 assertEquals("begin index", 10, fpCurr.getBeginIndex());
8526 assertEquals("end index", 20, fpCurr.getEndIndex());
8527
8528 // Test field position iterator
8529 {
8530 NumberFormatTest_Attributes attributes[] = {
8531 {UNUM_SIGN_FIELD, 0, 1},
8532 {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
8533 {UNUM_INTEGER_FIELD, 1, 6},
8534 {UNUM_DECIMAL_SEPARATOR_FIELD, 6, 7},
8535 {UNUM_FRACTION_FIELD, 7, 9},
8536 {UNUM_CURRENCY_FIELD, 10, 20},
8537 {0, -1, 0}};
8538 UnicodeString result;
8539 FieldPositionIterator iter;
8540 fmt->format(negAmt, result, &iter, status);
8541 assertEquals("", "-9,876.54 US dollars", result);
8542 verifyFieldPositionIterator(attributes, iter);
8543 }
8544 }
8545
Test10727_RoundingZero()8546 void NumberFormatTest::Test10727_RoundingZero() {
8547 IcuTestErrorCode status(*this, "Test10727_RoundingZero");
8548 DecimalQuantity dq;
8549 dq.setToDouble(-0.0);
8550 assertTrue("", dq.isNegative());
8551 dq.roundToMagnitude(0, UNUM_ROUND_HALFEVEN, status);
8552 assertTrue("", dq.isNegative());
8553 }
8554
Test11739_ParseLongCurrency()8555 void NumberFormatTest::Test11739_ParseLongCurrency() {
8556 IcuTestErrorCode status(*this, "Test11739_ParseLongCurrency");
8557 LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("sr_BA", status));
8558 if (status.errDataIfFailureAndReset()) { return; }
8559 ((DecimalFormat*) nf.getAlias())->applyPattern(u"#,##0.0 ¤¤¤", status);
8560 ParsePosition ppos(0);
8561 LocalPointer<CurrencyAmount> result(nf->parseCurrency(u"1.500 амерички долар", ppos));
8562 assertEquals("Should parse to 1500 USD", -1, ppos.getErrorIndex());
8563 if (ppos.getErrorIndex() != -1) {
8564 return;
8565 }
8566 assertEquals("Should parse to 1500 USD", 1500LL, result->getNumber().getInt64(status));
8567 assertEquals("Should parse to 1500 USD", u"USD", result->getISOCurrency());
8568 }
8569
Test13035_MultiCodePointPaddingInPattern()8570 void NumberFormatTest::Test13035_MultiCodePointPaddingInPattern() {
8571 IcuTestErrorCode status(*this, "Test13035_MultiCodePointPaddingInPattern");
8572 DecimalFormat df(u"a*'நி'###0b", status);
8573 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8574 UnicodeString result;
8575 df.format(12, result.remove());
8576 // TODO(13034): Re-enable this test when support is added in ICU4C.
8577 //assertEquals("Multi-codepoint padding should not be split", u"aநிநி12b", result);
8578 df = DecimalFormat(u"a*\U0001F601###0b", status);
8579 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8580 result = df.format(12, result.remove());
8581 assertEquals("Single-codepoint padding should not be split", u"a\U0001F601\U0001F60112b", result, true);
8582 df = DecimalFormat(u"a*''###0b", status);
8583 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8584 result = df.format(12, result.remove());
8585 assertEquals("Quote should be escapable in padding syntax", "a''12b", result, true);
8586 }
8587
Test13737_ParseScientificStrict()8588 void NumberFormatTest::Test13737_ParseScientificStrict() {
8589 IcuTestErrorCode status(*this, "Test13737_ParseScientificStrict");
8590 LocalPointer<NumberFormat> df(NumberFormat::createScientificInstance("en", status), status);
8591 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8592 df->setLenient(FALSE);
8593 // Parse Test
8594 expect(*df, u"1.2", 1.2);
8595 }
8596
Test11376_getAndSetPositivePrefix()8597 void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
8598 {
8599 const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8600 UErrorCode status = U_ZERO_ERROR;
8601 LocalPointer<NumberFormat> fmt(
8602 NumberFormat::createCurrencyInstance("en", status));
8603 if (!assertSuccess("", status)) {
8604 return;
8605 }
8606 DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8607 dfmt->setCurrency(USD);
8608 UnicodeString result;
8609
8610 // This line should be a no-op. I am setting the positive prefix
8611 // to be the same thing it was before.
8612 dfmt->setPositivePrefix(dfmt->getPositivePrefix(result));
8613
8614 UnicodeString appendTo;
8615 assertEquals("", "$3.78", dfmt->format(3.78, appendTo, status));
8616 assertSuccess("", status);
8617 }
8618 {
8619 const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8620 UErrorCode status = U_ZERO_ERROR;
8621 LocalPointer<NumberFormat> fmt(
8622 NumberFormat::createInstance("en", UNUM_CURRENCY_PLURAL, status));
8623 if (!assertSuccess("", status)) {
8624 return;
8625 }
8626 DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8627 UnicodeString result;
8628 assertEquals("", u" (unknown currency)", dfmt->getPositiveSuffix(result));
8629 dfmt->setCurrency(USD);
8630
8631 // getPositiveSuffix() always returns the suffix for the
8632 // "other" plural category
8633 assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8634 UnicodeString appendTo;
8635 assertEquals("", "3.78 US dollars", dfmt->format(3.78, appendTo, status));
8636 assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8637 dfmt->setPositiveSuffix("booya");
8638 appendTo.remove();
8639 assertEquals("", "3.78booya", dfmt->format(3.78, appendTo, status));
8640 assertEquals("", "booya", dfmt->getPositiveSuffix(result));
8641 }
8642 }
8643
Test11475_signRecognition()8644 void NumberFormatTest::Test11475_signRecognition() {
8645 UErrorCode status = U_ZERO_ERROR;
8646 DecimalFormatSymbols sym("en", status);
8647 UnicodeString result;
8648 {
8649 DecimalFormat fmt("+0.00", sym, status);
8650 if (!assertSuccess("", status)) {
8651 return;
8652 }
8653 NumberFormatTest_Attributes attributes[] = {
8654 {UNUM_SIGN_FIELD, 0, 1},
8655 {UNUM_INTEGER_FIELD, 1, 2},
8656 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8657 {UNUM_FRACTION_FIELD, 3, 5},
8658 {0, -1, 0}};
8659 UnicodeString result;
8660 FieldPositionIterator iter;
8661 fmt.format(2.3, result, &iter, status);
8662 assertEquals("", "+2.30", result);
8663 verifyFieldPositionIterator(attributes, iter);
8664 }
8665 {
8666 DecimalFormat fmt("++0.00+;-(#)--", sym, status);
8667 if (!assertSuccess("", status)) {
8668 return;
8669 }
8670 {
8671 NumberFormatTest_Attributes attributes[] = {
8672 {UNUM_SIGN_FIELD, 0, 2},
8673 {UNUM_INTEGER_FIELD, 2, 3},
8674 {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8675 {UNUM_FRACTION_FIELD, 4, 6},
8676 {UNUM_SIGN_FIELD, 6, 7},
8677 {0, -1, 0}};
8678 UnicodeString result;
8679 FieldPositionIterator iter;
8680 fmt.format(2.3, result, &iter, status);
8681 assertEquals("", "++2.30+", result);
8682 verifyFieldPositionIterator(attributes, iter);
8683 }
8684 {
8685 NumberFormatTest_Attributes attributes[] = {
8686 {UNUM_SIGN_FIELD, 0, 1},
8687 {UNUM_INTEGER_FIELD, 2, 3},
8688 {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8689 {UNUM_FRACTION_FIELD, 4, 6},
8690 {UNUM_SIGN_FIELD, 7, 9},
8691 {0, -1, 0}};
8692 UnicodeString result;
8693 FieldPositionIterator iter;
8694 fmt.format(-2.3, result, &iter, status);
8695 assertEquals("", "-(2.30)--", result);
8696 verifyFieldPositionIterator(attributes, iter);
8697 }
8698 }
8699 }
8700
Test11640_getAffixes()8701 void NumberFormatTest::Test11640_getAffixes() {
8702 UErrorCode status = U_ZERO_ERROR;
8703 DecimalFormatSymbols symbols("en_US", status);
8704 if (!assertSuccess("", status)) {
8705 return;
8706 }
8707 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8708 pattern = pattern.unescape();
8709 DecimalFormat fmt(pattern, symbols, status);
8710 if (!assertSuccess("", status)) {
8711 return;
8712 }
8713 UnicodeString affixStr;
8714 assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8715 assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8716 assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8717 assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8718 }
8719
Test11649_toPatternWithMultiCurrency()8720 void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
8721 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
8722 pattern = pattern.unescape();
8723 UErrorCode status = U_ZERO_ERROR;
8724 DecimalFormat fmt(pattern, status);
8725 if (!assertSuccess("", status)) {
8726 return;
8727 }
8728 static UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8729 fmt.setCurrency(USD);
8730 UnicodeString appendTo;
8731
8732 assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
8733
8734 UnicodeString topattern;
8735 fmt.toPattern(topattern);
8736 DecimalFormat fmt2(topattern, status);
8737 if (!assertSuccess("", status)) {
8738 return;
8739 }
8740 fmt2.setCurrency(USD);
8741
8742 appendTo.remove();
8743 assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
8744 }
8745
Test13327_numberingSystemBufferOverflow()8746 void NumberFormatTest::Test13327_numberingSystemBufferOverflow() {
8747 UErrorCode status = U_ZERO_ERROR;
8748 for (int runId = 0; runId < 2; runId++) {
8749 // Construct a locale string with a very long "numbers" value.
8750 // The first time, make the value length exactly equal to ULOC_KEYWORDS_CAPACITY.
8751 // The second time, make it exceed ULOC_KEYWORDS_CAPACITY.
8752 int extraLength = (runId == 0) ? 0 : 5;
8753
8754 CharString localeId("en@numbers=", status);
8755 for (int i = 0; i < ULOC_KEYWORDS_CAPACITY + extraLength; i++) {
8756 localeId.append('x', status);
8757 }
8758 assertSuccess("Constructing locale string", status);
8759 Locale locale(localeId.data());
8760
8761 LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(locale, status));
8762 assertFalse("Should not be null", ns.getAlias() == nullptr);
8763 assertSuccess("Should create with no error", status);
8764 }
8765 }
8766
Test13391_chakmaParsing()8767 void NumberFormatTest::Test13391_chakmaParsing() {
8768 UErrorCode status = U_ZERO_ERROR;
8769 LocalPointer<DecimalFormat> df(dynamic_cast<DecimalFormat*>(
8770 NumberFormat::createInstance(Locale("ccp"), status)));
8771 if (df == nullptr) {
8772 dataerrln("%s %d Chakma df is null", __FILE__, __LINE__);
8773 return;
8774 }
8775 const UChar* expected = u"\U00011137\U00011138,\U00011139\U0001113A\U0001113B";
8776 UnicodeString actual;
8777 df->format(12345, actual, status);
8778 assertSuccess("Should not fail when formatting in ccp", status);
8779 assertEquals("Should produce expected output in ccp", expected, actual);
8780
8781 Formattable result;
8782 df->parse(expected, result, status);
8783 assertSuccess("Should not fail when parsing in ccp", status);
8784 assertEquals("Should parse to 12345 in ccp", 12345, result);
8785
8786 const UChar* expectedScientific = u"\U00011137.\U00011139E\U00011138";
8787 UnicodeString actualScientific;
8788 df.adoptInstead(static_cast<DecimalFormat*>(
8789 NumberFormat::createScientificInstance(Locale("ccp"), status)));
8790 df->format(130, actualScientific, status);
8791 assertSuccess("Should not fail when formatting scientific in ccp", status);
8792 assertEquals("Should produce expected scientific output in ccp",
8793 expectedScientific, actualScientific);
8794
8795 Formattable resultScientific;
8796 df->parse(expectedScientific, resultScientific, status);
8797 assertSuccess("Should not fail when parsing scientific in ccp", status);
8798 assertEquals("Should parse scientific to 130 in ccp", 130, resultScientific);
8799 }
8800
8801
verifyFieldPositionIterator(NumberFormatTest_Attributes * expected,FieldPositionIterator & iter)8802 void NumberFormatTest::verifyFieldPositionIterator(
8803 NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
8804 int32_t idx = 0;
8805 FieldPosition fp;
8806 while (iter.next(fp)) {
8807 if (expected[idx].spos == -1) {
8808 errln("Iterator should have ended. got %d", fp.getField());
8809 return;
8810 }
8811 assertEquals("id", expected[idx].id, fp.getField());
8812 assertEquals("start", expected[idx].spos, fp.getBeginIndex());
8813 assertEquals("end", expected[idx].epos, fp.getEndIndex());
8814 ++idx;
8815 }
8816 if (expected[idx].spos != -1) {
8817 errln("Premature end of iterator. expected %d", expected[idx].id);
8818 }
8819 }
8820
Test11735_ExceptionIssue()8821 void NumberFormatTest::Test11735_ExceptionIssue() {
8822 IcuTestErrorCode status(*this, "Test11735_ExceptionIssue");
8823 Locale enLocale("en");
8824 DecimalFormatSymbols symbols(enLocale, status);
8825 if (status.isSuccess()) {
8826 DecimalFormat fmt("0", symbols, status);
8827 assertSuccess("Fail: Construct DecimalFormat formatter", status, true, __FILE__, __LINE__);
8828 ParsePosition ppos(0);
8829 fmt.parseCurrency("53.45", ppos); // NPE thrown here in ICU4J.
8830 assertEquals("Issue11735 ppos", 0, ppos.getIndex());
8831 }
8832 }
8833
Test11035_FormatCurrencyAmount()8834 void NumberFormatTest::Test11035_FormatCurrencyAmount() {
8835 UErrorCode status = U_ZERO_ERROR;
8836 double amount = 12345.67;
8837 const char16_t* expected = u"12,345$67 ";
8838
8839 // Test two ways to set a currency via API
8840
8841 Locale loc1 = Locale("pt_PT");
8842 LocalPointer<NumberFormat> fmt1(NumberFormat::createCurrencyInstance(loc1, status),
8843 status);
8844 if (U_FAILURE(status)) {
8845 dataerrln("%s %d NumberFormat instance fmt1 is null", __FILE__, __LINE__);
8846 return;
8847 }
8848 fmt1->setCurrency(u"PTE", status);
8849 assertSuccess("Setting currency on fmt1", status);
8850 UnicodeString actualSetCurrency;
8851 fmt1->format(amount, actualSetCurrency);
8852
8853 Locale loc2 = Locale("pt_PT@currency=PTE");
8854 LocalPointer<NumberFormat> fmt2(NumberFormat::createCurrencyInstance(loc2, status));
8855 assertSuccess("Creating fmt2", status);
8856 UnicodeString actualLocaleString;
8857 fmt2->format(amount, actualLocaleString);
8858
8859 assertEquals("Custom Currency Pattern, Set Currency", expected, actualSetCurrency);
8860 assertEquals("Custom Currency Pattern, Locale String", expected, actualLocaleString);
8861 }
8862
Test11318_DoubleConversion()8863 void NumberFormatTest::Test11318_DoubleConversion() {
8864 IcuTestErrorCode status(*this, "Test11318_DoubleConversion");
8865 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
8866 if (U_FAILURE(status)) {
8867 dataerrln("%s %d Error in NumberFormat instance creation", __FILE__, __LINE__);
8868 return;
8869 }
8870 nf->setMaximumFractionDigits(40);
8871 nf->setMaximumIntegerDigits(40);
8872 UnicodeString appendTo;
8873 nf->format(999999999999999.9, appendTo);
8874 assertEquals("Should render all digits", u"999,999,999,999,999.9", appendTo);
8875 }
8876
TestParsePercentRegression()8877 void NumberFormatTest::TestParsePercentRegression() {
8878 IcuTestErrorCode status(*this, "TestParsePercentRegression");
8879 LocalPointer<DecimalFormat> df1((DecimalFormat*) NumberFormat::createInstance("en", status), status);
8880 LocalPointer<DecimalFormat> df2((DecimalFormat*) NumberFormat::createPercentInstance("en", status), status);
8881 if (status.isFailure()) {return; }
8882 df1->setLenient(TRUE);
8883 df2->setLenient(TRUE);
8884
8885 {
8886 ParsePosition ppos;
8887 Formattable result;
8888 df1->parse("50%", result, ppos);
8889 assertEquals("df1 should accept a number but not the percent sign", 2, ppos.getIndex());
8890 assertEquals("df1 should return the number as 50", 50.0, result.getDouble(status));
8891 }
8892 {
8893 ParsePosition ppos;
8894 Formattable result;
8895 df2->parse("50%", result, ppos);
8896 assertEquals("df2 should accept the percent sign", 3, ppos.getIndex());
8897 assertEquals("df2 should return the number as 0.5", 0.5, result.getDouble(status));
8898 }
8899 {
8900 ParsePosition ppos;
8901 Formattable result;
8902 df2->parse("50", result, ppos);
8903 assertEquals("df2 should return the number as 0.5 even though the percent sign is missing",
8904 0.5,
8905 result.getDouble(status));
8906 }
8907 }
8908
TestMultiplierWithScale()8909 void NumberFormatTest::TestMultiplierWithScale() {
8910 IcuTestErrorCode status(*this, "TestMultiplierWithScale");
8911
8912 // Test magnitude combined with multiplier, as shown in API docs
8913 DecimalFormat df("0", {"en", status}, status);
8914 if (status.isSuccess()) {
8915 df.setMultiplier(5);
8916 df.setMultiplierScale(-1);
8917 expect2(df, 100, u"50"); // round-trip test
8918 }
8919 }
8920
TestFastFormatInt32()8921 void NumberFormatTest::TestFastFormatInt32() {
8922 IcuTestErrorCode status(*this, "TestFastFormatInt32");
8923
8924 // The two simplest formatters, old API and new API.
8925 // Old API should use the fastpath for ints.
8926 LocalizedNumberFormatter lnf = NumberFormatter::withLocale("en");
8927 LocalPointer<NumberFormat> df(NumberFormat::createInstance("en", status), status);
8928 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8929
8930 double nums[] = {
8931 0.0,
8932 -0.0,
8933 NAN,
8934 INFINITY,
8935 0.1,
8936 1.0,
8937 1.1,
8938 2.0,
8939 3.0,
8940 9.0,
8941 10.0,
8942 99.0,
8943 100.0,
8944 999.0,
8945 1000.0,
8946 9999.0,
8947 10000.0,
8948 99999.0,
8949 100000.0,
8950 999999.0,
8951 1000000.0,
8952 static_cast<double>(INT32_MAX) - 1,
8953 static_cast<double>(INT32_MAX),
8954 static_cast<double>(INT32_MAX) + 1,
8955 static_cast<double>(INT32_MIN) - 1,
8956 static_cast<double>(INT32_MIN),
8957 static_cast<double>(INT32_MIN) + 1};
8958
8959 for (auto num : nums) {
8960 UnicodeString expected = lnf.formatDouble(num, status).toString(status);
8961 UnicodeString actual;
8962 df->format(num, actual);
8963 assertEquals(UnicodeString("d = ") + num, expected, actual);
8964 }
8965 }
8966
Test11646_Equality()8967 void NumberFormatTest::Test11646_Equality() {
8968 UErrorCode status = U_ZERO_ERROR;
8969 DecimalFormatSymbols symbols(Locale::getEnglish(), status);
8970 UnicodeString pattern(u"\u00a4\u00a4\u00a4 0.00 %\u00a4\u00a4");
8971 DecimalFormat fmt(pattern, symbols, status);
8972 if (!assertSuccess("", status)) return;
8973
8974 // Test equality with affixes. set affix methods can't capture special
8975 // characters which is why equality should fail.
8976 {
8977 DecimalFormat fmtCopy(fmt);
8978 assertTrue("", fmt == fmtCopy);
8979 UnicodeString positivePrefix;
8980 fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(positivePrefix));
8981 assertFalse("", fmt == fmtCopy);
8982 }
8983 {
8984 DecimalFormat fmtCopy = DecimalFormat(fmt);
8985 assertTrue("", fmt == fmtCopy);
8986 UnicodeString positivePrefix;
8987 fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(positivePrefix));
8988 assertFalse("", fmt == fmtCopy);
8989 }
8990 {
8991 DecimalFormat fmtCopy(fmt);
8992 assertTrue("", fmt == fmtCopy);
8993 UnicodeString negativePrefix;
8994 fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(negativePrefix));
8995 assertFalse("", fmt == fmtCopy);
8996 }
8997 {
8998 DecimalFormat fmtCopy(fmt);
8999 assertTrue("", fmt == fmtCopy);
9000 UnicodeString negativePrefix;
9001 fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(negativePrefix));
9002 assertFalse("", fmt == fmtCopy);
9003 }
9004 }
9005
TestParseNaN()9006 void NumberFormatTest::TestParseNaN() {
9007 IcuTestErrorCode status(*this, "TestParseNaN");
9008
9009 DecimalFormat df("0", { "en", status }, status);
9010 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9011 Formattable parseResult;
9012 df.parse(u"NaN", parseResult, status);
9013 assertEquals("NaN should parse successfully", NAN, parseResult.getDouble());
9014 assertFalse("Result NaN should be positive", std::signbit(parseResult.getDouble()));
9015 UnicodeString formatResult;
9016 df.format(parseResult.getDouble(), formatResult);
9017 assertEquals("NaN should round-trip", u"NaN", formatResult);
9018 }
9019
TestFormatFailIfMoreThanMaxDigits()9020 void NumberFormatTest::TestFormatFailIfMoreThanMaxDigits() {
9021 IcuTestErrorCode status(*this, "TestFormatFailIfMoreThanMaxDigits");
9022
9023 DecimalFormat df("0", {"en-US", status}, status);
9024 if (status.errDataIfFailureAndReset()) {
9025 return;
9026 }
9027 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isFormatFailIfMoreThanMaxDigits());
9028 df.setFormatFailIfMoreThanMaxDigits(TRUE);
9029 assertEquals("Coverage for getter 2", (UBool) TRUE, df.isFormatFailIfMoreThanMaxDigits());
9030 df.setMaximumIntegerDigits(2);
9031 UnicodeString result;
9032 df.format(1234, result, status);
9033 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
9034 }
9035
TestParseCaseSensitive()9036 void NumberFormatTest::TestParseCaseSensitive() {
9037 IcuTestErrorCode status(*this, "TestParseCaseSensitive");
9038
9039 DecimalFormat df(u"0", {"en-US", status}, status);
9040 if (status.errDataIfFailureAndReset()) {
9041 return;
9042 }
9043 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isParseCaseSensitive());
9044 df.setParseCaseSensitive(TRUE);
9045 assertEquals("Coverage for getter 1", (UBool) TRUE, df.isParseCaseSensitive());
9046 Formattable result;
9047 ParsePosition ppos;
9048 df.parse(u"1e2", result, ppos);
9049 assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9050 assertEquals("Result should be 1", 1.0, result.getDouble(status));
9051 }
9052
TestParseNoExponent()9053 void NumberFormatTest::TestParseNoExponent() {
9054 IcuTestErrorCode status(*this, "TestParseNoExponent");
9055
9056 DecimalFormat df(u"0", {"en-US", status}, status);
9057 if (status.errDataIfFailureAndReset()) {
9058 return;
9059 }
9060 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isParseNoExponent());
9061 df.setParseNoExponent(TRUE);
9062 assertEquals("Coverage for getter 1", (UBool) TRUE, df.isParseNoExponent());
9063 Formattable result;
9064 ParsePosition ppos;
9065 df.parse(u"1E2", result, ppos);
9066 assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9067 assertEquals("Result should be 1", 1.0, result.getDouble(status));
9068 }
9069
TestSignAlwaysShown()9070 void NumberFormatTest::TestSignAlwaysShown() {
9071 IcuTestErrorCode status(*this, "TestSignAlwaysShown");
9072
9073 DecimalFormat df(u"0", {"en-US", status}, status);
9074 if (status.errDataIfFailureAndReset()) {
9075 return;
9076 }
9077 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isSignAlwaysShown());
9078 df.setSignAlwaysShown(TRUE);
9079 assertEquals("Coverage for getter 1", (UBool) TRUE, df.isSignAlwaysShown());
9080 UnicodeString result;
9081 df.format(1234, result, status);
9082 status.errIfFailureAndReset();
9083 assertEquals("Should show sign on positive number", u"+1234", result);
9084 }
9085
TestMinimumGroupingDigits()9086 void NumberFormatTest::TestMinimumGroupingDigits() {
9087 IcuTestErrorCode status(*this, "TestMinimumGroupingDigits");
9088
9089 DecimalFormat df(u"#,##0", {"en-US", status}, status);
9090 if (status.errDataIfFailureAndReset()) {
9091 return;
9092 }
9093 assertEquals("Coverage for getter 1", -1, df.getMinimumGroupingDigits());
9094 df.setMinimumGroupingDigits(2);
9095 assertEquals("Coverage for getter 1", 2, df.getMinimumGroupingDigits());
9096 UnicodeString result;
9097 df.format(1234, result, status);
9098 status.errIfFailureAndReset();
9099 assertEquals("Should not have grouping", u"1234", result);
9100 df.format(12345, result.remove(), status);
9101 status.errIfFailureAndReset();
9102 assertEquals("Should have grouping", u"12,345", result);
9103
9104
9105 // Test special values -1, UNUM_MINIMUM_GROUPING_DIGITS_AUTO and
9106 // UNUM_MINIMUM_GROUPING_DIGITS_MIN2
9107 struct TestCase {
9108 const char* locale;
9109 int32_t minGroup;
9110 double input;
9111 const char16_t* expected;
9112 } cases[] = {
9113 { "en-US", 1, 1000, u"1,000" },
9114 { "en-US", 1, 10000, u"10,000" },
9115 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1,000" },
9116 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10,000" },
9117 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9118 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10,000" },
9119
9120 { "es", 1, 1000, u"1.000" },
9121 { "es", 1, 10000, u"10.000" },
9122 { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1000" },
9123 { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10.000" },
9124 { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9125 { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10.000" },
9126 };
9127 for (const auto& cas : cases) {
9128 UnicodeString message = UnicodeString(cas.locale)
9129 + u" " + Int64ToUnicodeString(cas.minGroup)
9130 + u" " + DoubleToUnicodeString(cas.input);
9131 status.setScope(message);
9132 DecimalFormat df(u"#,##0", {cas.locale, status}, status);
9133 if (status.errIfFailureAndReset()) { continue; }
9134 df.setMinimumGroupingDigits(cas.minGroup);
9135 UnicodeString actual;
9136 df.format(cas.input, actual, status);
9137 if (status.errIfFailureAndReset()) { continue; }
9138 assertEquals(message, cas.expected, actual);
9139 }
9140 }
9141
Test11897_LocalizedPatternSeparator()9142 void NumberFormatTest::Test11897_LocalizedPatternSeparator() {
9143 IcuTestErrorCode status(*this, "Test11897_LocalizedPatternSeparator");
9144
9145 // In a locale with a different <list> symbol, like arabic,
9146 // kPatternSeparatorSymbol should still be ';'
9147 {
9148 DecimalFormatSymbols dfs("ar", status);
9149 assertEquals("pattern separator symbol should be ;",
9150 u";",
9151 dfs.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
9152 }
9153
9154 // However, the custom symbol should be used in localized notation
9155 // when set manually via API
9156 {
9157 DecimalFormatSymbols dfs("en", status);
9158 dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u"!", FALSE);
9159 DecimalFormat df(u"0", dfs, status);
9160 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9161 df.applyPattern("a0;b0", status); // should not throw
9162 UnicodeString result;
9163 assertEquals("should apply the normal pattern",
9164 df.getNegativePrefix(result.remove()),
9165 "b");
9166 df.applyLocalizedPattern(u"c0!d0", status); // should not throw
9167 assertEquals("should apply the localized pattern",
9168 df.getNegativePrefix(result.remove()),
9169 "d");
9170 }
9171 }
9172
Test13055_PercentageRounding()9173 void NumberFormatTest::Test13055_PercentageRounding() {
9174 IcuTestErrorCode status(*this, "PercentageRounding");
9175 UnicodeString actual;
9176 LocalPointer<NumberFormat>pFormat(NumberFormat::createPercentInstance("en_US", status));
9177 if (U_FAILURE(status)) {
9178 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9179 return;
9180 }
9181 pFormat->setMaximumFractionDigits(0);
9182 pFormat->setRoundingMode(DecimalFormat::kRoundHalfEven);
9183 pFormat->format(2.155, actual);
9184 assertEquals("Should round percent toward even number", "216%", actual);
9185 }
9186
Test11839()9187 void NumberFormatTest::Test11839() {
9188 IcuTestErrorCode errorCode(*this, "Test11839");
9189 // Ticket #11839: DecimalFormat does not respect custom plus sign
9190 LocalPointer<DecimalFormatSymbols> dfs(new DecimalFormatSymbols(Locale::getEnglish(), errorCode), errorCode);
9191 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9192 dfs->setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"a∸");
9193 dfs->setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"b∔"); // ∔ U+2214 DOT PLUS
9194 DecimalFormat df(u"0.00+;0.00-", dfs.orphan(), errorCode);
9195 UnicodeString result;
9196 df.format(-1.234, result, errorCode);
9197 assertEquals("Locale-specific minus sign should be used", u"1.23a∸", result);
9198 df.format(1.234, result.remove(), errorCode);
9199 assertEquals("Locale-specific plus sign should be used", u"1.23b∔", result);
9200 // Test round-trip with parse
9201 expect2(df, -456, u"456.00a∸");
9202 expect2(df, 456, u"456.00b∔");
9203 }
9204
Test10354()9205 void NumberFormatTest::Test10354() {
9206 IcuTestErrorCode errorCode(*this, "Test10354");
9207 // Ticket #10354: invalid FieldPositionIterator when formatting with empty NaN
9208 DecimalFormatSymbols dfs(errorCode);
9209 UnicodeString empty;
9210 dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, empty);
9211 DecimalFormat df(errorCode);
9212 df.setDecimalFormatSymbols(dfs);
9213 UnicodeString result;
9214 FieldPositionIterator positions;
9215 df.format(NAN, result, &positions, errorCode);
9216 errorCode.errIfFailureAndReset("DecimalFormat.format(NAN, FieldPositionIterator) failed");
9217 FieldPosition fp;
9218 while (positions.next(fp)) {
9219 // Should not loop forever
9220 }
9221 }
9222
Test11645_ApplyPatternEquality()9223 void NumberFormatTest::Test11645_ApplyPatternEquality() {
9224 IcuTestErrorCode status(*this, "Test11645_ApplyPatternEquality");
9225 const char16_t* pattern = u"#,##0.0#";
9226 LocalPointer<DecimalFormat> fmt((DecimalFormat*) NumberFormat::createInstance(status), status);
9227 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9228 fmt->applyPattern(pattern, status);
9229 LocalPointer<DecimalFormat> fmtCopy;
9230
9231 static const int32_t newMultiplier = 37;
9232 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9233 assertFalse("Value before setter", fmtCopy->getMultiplier() == newMultiplier);
9234 fmtCopy->setMultiplier(newMultiplier);
9235 assertEquals("Value after setter", fmtCopy->getMultiplier(), newMultiplier);
9236 fmtCopy->applyPattern(pattern, status);
9237 assertEquals("Value after applyPattern", fmtCopy->getMultiplier(), newMultiplier);
9238 assertFalse("multiplier", *fmt == *fmtCopy);
9239
9240 static const NumberFormat::ERoundingMode newRoundingMode = NumberFormat::ERoundingMode::kRoundCeiling;
9241 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9242 assertFalse("Value before setter", fmtCopy->getRoundingMode() == newRoundingMode);
9243 fmtCopy->setRoundingMode(newRoundingMode);
9244 assertEquals("Value after setter", fmtCopy->getRoundingMode(), newRoundingMode);
9245 fmtCopy->applyPattern(pattern, status);
9246 assertEquals("Value after applyPattern", fmtCopy->getRoundingMode(), newRoundingMode);
9247 assertFalse("roundingMode", *fmt == *fmtCopy);
9248
9249 static const char16_t *const newCurrency = u"EAT";
9250 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9251 assertFalse("Value before setter", fmtCopy->getCurrency() == newCurrency);
9252 fmtCopy->setCurrency(newCurrency);
9253 assertEquals("Value after setter", fmtCopy->getCurrency(), newCurrency);
9254 fmtCopy->applyPattern(pattern, status);
9255 assertEquals("Value after applyPattern", fmtCopy->getCurrency(), newCurrency);
9256 assertFalse("currency", *fmt == *fmtCopy);
9257
9258 static const UCurrencyUsage newCurrencyUsage = UCurrencyUsage::UCURR_USAGE_CASH;
9259 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9260 assertFalse("Value before setter", fmtCopy->getCurrencyUsage() == newCurrencyUsage);
9261 fmtCopy->setCurrencyUsage(newCurrencyUsage, status);
9262 assertEquals("Value after setter", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9263 fmtCopy->applyPattern(pattern, status);
9264 assertEquals("Value after applyPattern", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9265 assertFalse("currencyUsage", *fmt == *fmtCopy);
9266 }
9267
Test12567()9268 void NumberFormatTest::Test12567() {
9269 IcuTestErrorCode errorCode(*this, "Test12567");
9270 // Ticket #12567: DecimalFormat.equals() may not be symmetric
9271 LocalPointer<DecimalFormat> df1((DecimalFormat *)
9272 NumberFormat::createInstance(Locale::getUS(), UNUM_CURRENCY, errorCode));
9273 LocalPointer<DecimalFormat> df2((DecimalFormat *)
9274 NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, errorCode));
9275 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9276 // NOTE: CurrencyPluralInfo equality not tested in C++ because its operator== is not defined.
9277 df1->applyPattern(u"0.00", errorCode);
9278 df2->applyPattern(u"0.00", errorCode);
9279 assertTrue("df1 == df2", *df1 == *df2);
9280 assertTrue("df2 == df1", *df2 == *df1);
9281 df2->setPositivePrefix(u"abc");
9282 assertTrue("df1 != df2", *df1 != *df2);
9283 assertTrue("df2 != df1", *df2 != *df1);
9284 }
9285
Test11626_CustomizeCurrencyPluralInfo()9286 void NumberFormatTest::Test11626_CustomizeCurrencyPluralInfo() {
9287 IcuTestErrorCode errorCode(*this, "Test11626_CustomizeCurrencyPluralInfo");
9288 // Ticket #11626: No unit test demonstrating how to use CurrencyPluralInfo to
9289 // change formatting spelled out currencies
9290 // Use locale sr because it has interesting plural rules.
9291 Locale locale("sr");
9292 LocalPointer<DecimalFormatSymbols> symbols(new DecimalFormatSymbols(locale, errorCode), errorCode);
9293 CurrencyPluralInfo info(locale, errorCode);
9294 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9295 info.setCurrencyPluralPattern(u"one", u"0 qwerty", errorCode);
9296 info.setCurrencyPluralPattern(u"few", u"0 dvorak", errorCode);
9297 DecimalFormat df(u"#", symbols.orphan(), UNUM_CURRENCY_PLURAL, errorCode);
9298 df.setCurrencyPluralInfo(info);
9299 df.setCurrency(u"USD");
9300 df.setMaximumFractionDigits(0);
9301
9302 UnicodeString result;
9303 assertEquals("Plural one", u"1 qwerty", df.format(1, result, errorCode));
9304 assertEquals("Plural few", u"3 dvorak", df.format(3, result.remove(), errorCode));
9305 assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9306
9307 info.setPluralRules(u"few: n is 1; one: n in 2..4", errorCode);
9308 df.setCurrencyPluralInfo(info);
9309 assertEquals("Plural one", u"1 dvorak", df.format(1, result.remove(), errorCode));
9310 assertEquals("Plural few", u"3 qwerty", df.format(3, result.remove(), errorCode));
9311 assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9312 }
9313
Test20073_StrictPercentParseErrorIndex()9314 void NumberFormatTest::Test20073_StrictPercentParseErrorIndex() {
9315 IcuTestErrorCode status(*this, "Test20073_StrictPercentParseErrorIndex");
9316 ParsePosition parsePosition(0);
9317 DecimalFormat df(u"0%", {"en-us", status}, status);
9318 if (U_FAILURE(status)) {
9319 dataerrln("Unable to create DecimalFormat instance.");
9320 return;
9321 }
9322 df.setLenient(FALSE);
9323 Formattable result;
9324 df.parse(u"%2%", result, parsePosition);
9325 assertEquals("", 0, parsePosition.getIndex());
9326 assertEquals("", 0, parsePosition.getErrorIndex());
9327 }
9328
Test13056_GroupingSize()9329 void NumberFormatTest::Test13056_GroupingSize() {
9330 UErrorCode status = U_ZERO_ERROR;
9331 DecimalFormat df(u"#,##0", status);
9332 if (!assertSuccess("", status)) return;
9333 assertEquals("Primary grouping should return 3", 3, df.getGroupingSize());
9334 assertEquals("Secondary grouping should return 0", 0, df.getSecondaryGroupingSize());
9335 df.setSecondaryGroupingSize(3);
9336 assertEquals("Primary grouping should still return 3", 3, df.getGroupingSize());
9337 assertEquals("Secondary grouping should round-trip", 3, df.getSecondaryGroupingSize());
9338 df.setGroupingSize(4);
9339 assertEquals("Primary grouping should return 4", 4, df.getGroupingSize());
9340 assertEquals("Secondary should remember explicit setting and return 3", 3, df.getSecondaryGroupingSize());
9341 }
9342
9343
Test11025_CurrencyPadding()9344 void NumberFormatTest::Test11025_CurrencyPadding() {
9345 UErrorCode status = U_ZERO_ERROR;
9346 UnicodeString pattern(u"¤¤ **####0.00");
9347 DecimalFormatSymbols sym(Locale::getFrance(), status);
9348 if (!assertSuccess("", status)) return;
9349 DecimalFormat fmt(pattern, sym, status);
9350 if (!assertSuccess("", status)) return;
9351 UnicodeString result;
9352 fmt.format(433.0, result);
9353 assertEquals("Number should be padded to 11 characters", "EUR *433,00", result);
9354 }
9355
Test11648_ExpDecFormatMalPattern()9356 void NumberFormatTest::Test11648_ExpDecFormatMalPattern() {
9357 UErrorCode status = U_ZERO_ERROR;
9358
9359 DecimalFormat fmt("0.00", {"en", status}, status);
9360 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9361 fmt.setScientificNotation(TRUE);
9362 UnicodeString pattern;
9363
9364 assertEquals("A valid scientific notation pattern should be produced",
9365 "0.00E0",
9366 fmt.toPattern(pattern));
9367
9368 DecimalFormat fmt2(pattern, status);
9369 assertSuccess("", status);
9370 }
9371
Test11649_DecFmtCurrencies()9372 void NumberFormatTest::Test11649_DecFmtCurrencies() {
9373 IcuTestErrorCode status(*this, "Test11649_DecFmtCurrencies");
9374 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
9375 pattern = pattern.unescape();
9376 DecimalFormat fmt(pattern, status);
9377 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9378 static const UChar USD[] = u"USD";
9379 fmt.setCurrency(USD);
9380 UnicodeString appendTo;
9381
9382 assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
9383 UnicodeString topattern;
9384
9385 assertEquals("", pattern, fmt.toPattern(topattern));
9386 DecimalFormat fmt2(topattern, status);
9387 fmt2.setCurrency(USD);
9388
9389 appendTo.remove();
9390 assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
9391 }
9392
Test13148_ParseGroupingSeparators()9393 void NumberFormatTest::Test13148_ParseGroupingSeparators() {
9394 IcuTestErrorCode status(*this, "Test13148");
9395 LocalPointer<DecimalFormat> fmt(
9396 (DecimalFormat*)NumberFormat::createInstance("en-ZA", status), status);
9397 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9398
9399 DecimalFormatSymbols symbols = *fmt->getDecimalFormatSymbols();
9400
9401 symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'.');
9402 symbols.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u',');
9403 fmt->setDecimalFormatSymbols(symbols);
9404 Formattable number;
9405 fmt->parse(u"300,000", number, status);
9406 assertEquals("Should parse as 300000", 300000LL, number.getInt64(status));
9407 }
9408
Test12753_PatternDecimalPoint()9409 void NumberFormatTest::Test12753_PatternDecimalPoint() {
9410 UErrorCode status = U_ZERO_ERROR;
9411 DecimalFormatSymbols symbols(Locale::getUS(), status);
9412 symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"*", false);
9413 DecimalFormat df(u"0.00", symbols, status);
9414 if (!assertSuccess("", status)) return;
9415 df.setDecimalPatternMatchRequired(true);
9416 Formattable result;
9417 df.parse(u"123",result, status);
9418 assertEquals("Parsing integer succeeded even though setDecimalPatternMatchRequired was set",
9419 U_INVALID_FORMAT_ERROR, status);
9420 }
9421
Test11647_PatternCurrencySymbols()9422 void NumberFormatTest::Test11647_PatternCurrencySymbols() {
9423 UErrorCode status = U_ZERO_ERROR;
9424 DecimalFormat df(status);
9425 df.applyPattern(u"¤¤¤¤#", status);
9426 if (!assertSuccess("", status)) return;
9427 UnicodeString actual;
9428 df.format(123, actual);
9429 assertEquals("Should replace 4 currency signs with U+FFFD", u"\uFFFD123", actual);
9430 }
9431
Test11913_BigDecimal()9432 void NumberFormatTest::Test11913_BigDecimal() {
9433 UErrorCode status = U_ZERO_ERROR;
9434 LocalPointer<NumberFormat> df(NumberFormat::createInstance(Locale::getEnglish(), status), status);
9435 if (!assertSuccess("", status)) return;
9436 UnicodeString result;
9437 df->format(StringPiece("1.23456789E400"), result, nullptr, status);
9438 assertSuccess("", status);
9439 assertEquals("Should format more than 309 digits", u"12,345,678", UnicodeString(result, 0, 10));
9440 assertEquals("Should format more than 309 digits", 534, result.length());
9441 }
9442
Test11020_RoundingInScientificNotation()9443 void NumberFormatTest::Test11020_RoundingInScientificNotation() {
9444 UErrorCode status = U_ZERO_ERROR;
9445 DecimalFormatSymbols sym(Locale::getFrance(), status);
9446 DecimalFormat fmt(u"0.05E0", sym, status);
9447 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9448 assertSuccess("", status);
9449 UnicodeString result;
9450 fmt.format(12301.2, result);
9451 assertEquals("Rounding increment should be applied after magnitude scaling", u"1,25E4", result);
9452 }
9453
Test11640_TripleCurrencySymbol()9454 void NumberFormatTest::Test11640_TripleCurrencySymbol() {
9455 IcuTestErrorCode status(*this, "Test11640_TripleCurrencySymbol");
9456 UnicodeString actual;
9457 DecimalFormat dFormat(u"¤¤¤ 0", status);
9458 if (U_FAILURE(status)) {
9459 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9460 return;
9461 }
9462 dFormat.setCurrency(u"USD");
9463 UnicodeString result;
9464 dFormat.getPositivePrefix(result);
9465 assertEquals("Triple-currency should give long name on getPositivePrefix",
9466 "US dollars ", result);
9467 }
9468
9469
Test13763_FieldPositionIteratorOffset()9470 void NumberFormatTest::Test13763_FieldPositionIteratorOffset() {
9471 IcuTestErrorCode status(*this, "Test13763_FieldPositionIteratorOffset");
9472 FieldPositionIterator fpi;
9473 UnicodeString result(u"foo\U0001F4FBbar"); // 8 code units
9474 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9475 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9476 nf->format(5142.3, result, &fpi, status);
9477
9478 int32_t expected[] = {
9479 UNUM_GROUPING_SEPARATOR_FIELD, 9, 10,
9480 UNUM_INTEGER_FIELD, 8, 13,
9481 UNUM_DECIMAL_SEPARATOR_FIELD, 13, 14,
9482 UNUM_FRACTION_FIELD, 14, 15,
9483 };
9484 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
9485 expectPositions(fpi, expected, tupleCount, result);
9486 }
9487
Test13777_ParseLongNameNonCurrencyMode()9488 void NumberFormatTest::Test13777_ParseLongNameNonCurrencyMode() {
9489 IcuTestErrorCode status(*this, "Test13777_ParseLongNameNonCurrencyMode");
9490
9491 LocalPointer<NumberFormat> df(
9492 NumberFormat::createInstance("en-us", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9493 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9494 expect2(*df, 1.5, u"1.50 US dollars");
9495 }
9496
Test13804_EmptyStringsWhenParsing()9497 void NumberFormatTest::Test13804_EmptyStringsWhenParsing() {
9498 IcuTestErrorCode status(*this, "Test13804_EmptyStringsWhenParsing");
9499
9500 DecimalFormatSymbols dfs("en", status);
9501 if (status.errIfFailureAndReset()) {
9502 return;
9503 }
9504 dfs.setSymbol(DecimalFormatSymbols::kCurrencySymbol, u"", FALSE);
9505 dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"", FALSE);
9506 dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u"", FALSE);
9507 dfs.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, u"", FALSE);
9508 dfs.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, u"", FALSE);
9509 dfs.setSymbol(DecimalFormatSymbols::kThreeDigitSymbol, u"", FALSE);
9510 dfs.setSymbol(DecimalFormatSymbols::kFourDigitSymbol, u"", FALSE);
9511 dfs.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, u"", FALSE);
9512 dfs.setSymbol(DecimalFormatSymbols::kSixDigitSymbol, u"", FALSE);
9513 dfs.setSymbol(DecimalFormatSymbols::kSevenDigitSymbol, u"", FALSE);
9514 dfs.setSymbol(DecimalFormatSymbols::kEightDigitSymbol, u"", FALSE);
9515 dfs.setSymbol(DecimalFormatSymbols::kNineDigitSymbol, u"", FALSE);
9516 dfs.setSymbol(DecimalFormatSymbols::kExponentMultiplicationSymbol, u"", FALSE);
9517 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"", FALSE);
9518 dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u"", FALSE);
9519 dfs.setSymbol(DecimalFormatSymbols::kInfinitySymbol, u"", FALSE);
9520 dfs.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, u"", FALSE);
9521 dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"", FALSE);
9522 dfs.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, u"", FALSE);
9523 dfs.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, u"", FALSE);
9524 dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, u"", FALSE);
9525 dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, FALSE, u"");
9526 dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, TRUE, u"");
9527 dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u"", FALSE);
9528 dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u"", FALSE);
9529 dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"", FALSE);
9530
9531 DecimalFormat df("0", dfs, status);
9532 if (status.errIfFailureAndReset()) {
9533 return;
9534 }
9535 df.setGroupingUsed(TRUE);
9536 df.setScientificNotation(TRUE);
9537 df.setLenient(TRUE); // enable all matchers
9538 {
9539 UnicodeString result;
9540 df.format(0, result); // should not crash or hit infinite loop
9541 }
9542 const char16_t* samples[] = {
9543 u"",
9544 u"123",
9545 u"$123",
9546 u"-",
9547 u"+",
9548 u"44%",
9549 u"1E+2.3"
9550 };
9551 for (auto& sample : samples) {
9552 logln(UnicodeString(u"Attempting parse on: ") + sample);
9553 status.setScope(sample);
9554 // We don't care about the results, only that we don't crash and don't loop.
9555 Formattable result;
9556 ParsePosition ppos(0);
9557 df.parse(sample, result, ppos);
9558 ppos = ParsePosition(0);
9559 LocalPointer<CurrencyAmount> curramt(df.parseCurrency(sample, ppos));
9560 status.errIfFailureAndReset();
9561 }
9562
9563 // Test with a nonempty exponent separator symbol to cover more code
9564 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"E", FALSE);
9565 df.setDecimalFormatSymbols(dfs);
9566 {
9567 Formattable result;
9568 ParsePosition ppos(0);
9569 df.parse(u"1E+2.3", result, ppos);
9570 }
9571 }
9572
Test20037_ScientificIntegerOverflow()9573 void NumberFormatTest::Test20037_ScientificIntegerOverflow() {
9574 IcuTestErrorCode status(*this, "Test20037_ScientificIntegerOverflow");
9575
9576 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(status));
9577 if (U_FAILURE(status)) {
9578 dataerrln("Unable to create NumberFormat instance.");
9579 return;
9580 }
9581 Formattable result;
9582
9583 // Test overflow of exponent
9584 nf->parse(u"1E-2147483648", result, status);
9585 StringPiece sp = result.getDecimalNumber(status);
9586 assertEquals(u"Should snap to zero",
9587 u"0",
9588 {sp.data(), sp.length(), US_INV});
9589
9590 // Test edge case overflow of exponent
9591 result = Formattable();
9592 nf->parse(u"1E-2147483647E-1", result, status);
9593 sp = result.getDecimalNumber(status);
9594 assertEquals(u"Should not overflow and should parse only the first exponent",
9595 u"1E-2147483647",
9596 {sp.data(), sp.length(), US_INV});
9597
9598 // Test edge case overflow of exponent
9599 result = Formattable();
9600 nf->parse(u".0003e-2147483644", result, status);
9601 sp = result.getDecimalNumber(status);
9602 assertEquals(u"Should not overflow",
9603 u"3E-2147483648",
9604 {sp.data(), sp.length(), US_INV});
9605
9606 // Test largest parseable exponent
9607 result = Formattable();
9608 nf->parse(u"9876e2147483643", result, status);
9609 sp = result.getDecimalNumber(status);
9610 assertEquals(u"Should not overflow",
9611 u"9.876E+2147483646",
9612 {sp.data(), sp.length(), US_INV});
9613
9614 // Test max value as well
9615 const char16_t* infinityInputs[] = {
9616 u"9876e2147483644",
9617 u"9876e2147483645",
9618 u"9876e2147483646",
9619 u"9876e2147483647",
9620 u"9876e2147483648",
9621 u"9876e2147483649",
9622 };
9623 for (const auto& input : infinityInputs) {
9624 result = Formattable();
9625 nf->parse(input, result, status);
9626 sp = result.getDecimalNumber(status);
9627 assertEquals(UnicodeString("Should become Infinity: ") + input,
9628 u"Infinity",
9629 {sp.data(), sp.length(), US_INV});
9630 }
9631 }
9632
Test13840_ParseLongStringCrash()9633 void NumberFormatTest::Test13840_ParseLongStringCrash() {
9634 IcuTestErrorCode status(*this, "Test13840_ParseLongStringCrash");
9635
9636 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9637 if (status.errIfFailureAndReset()) { return; }
9638
9639 Formattable result;
9640 static const char16_t* bigString =
9641 u"111111111111111111111111111111111111111111111111111111111111111111111"
9642 u"111111111111111111111111111111111111111111111111111111111111111111111"
9643 u"111111111111111111111111111111111111111111111111111111111111111111111"
9644 u"111111111111111111111111111111111111111111111111111111111111111111111"
9645 u"111111111111111111111111111111111111111111111111111111111111111111111"
9646 u"111111111111111111111111111111111111111111111111111111111111111111111";
9647 nf->parse(bigString, result, status);
9648
9649 // Normalize the input string:
9650 CharString expectedChars;
9651 expectedChars.appendInvariantChars(bigString, status);
9652 DecimalQuantity expectedDQ;
9653 expectedDQ.setToDecNumber(expectedChars.toStringPiece(), status);
9654 UnicodeString expectedUString = expectedDQ.toScientificString();
9655
9656 // Get the output string:
9657 StringPiece actualChars = result.getDecimalNumber(status);
9658 UnicodeString actualUString = UnicodeString(actualChars.data(), actualChars.length(), US_INV);
9659
9660 assertEquals("Should round-trip without crashing", expectedUString, actualUString);
9661 }
9662
Test13850_EmptyStringCurrency()9663 void NumberFormatTest::Test13850_EmptyStringCurrency() {
9664 IcuTestErrorCode status(*this, "Test13840_EmptyStringCurrency");
9665
9666 struct TestCase {
9667 const char16_t* currencyArg;
9668 UErrorCode expectedError;
9669 } cases[] = {
9670 {u"", U_USING_FALLBACK_WARNING},
9671 {u"U", U_ILLEGAL_ARGUMENT_ERROR},
9672 {u"Us", U_ILLEGAL_ARGUMENT_ERROR},
9673 {nullptr, U_USING_FALLBACK_WARNING},
9674 {u"U$D", U_INVARIANT_CONVERSION_ERROR},
9675 {u"Xxx", U_USING_FALLBACK_WARNING}
9676 };
9677 for (const auto& cas : cases) {
9678 UnicodeString message(u"with currency arg: ");
9679 if (cas.currencyArg == nullptr) {
9680 message += u"nullptr";
9681 } else {
9682 message += UnicodeString(cas.currencyArg);
9683 }
9684 status.setScope(message);
9685 LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-US", status), status);
9686 if (status.errIfFailureAndReset()) { return; }
9687 UnicodeString actual;
9688 nf->format(1, actual, status);
9689 status.errIfFailureAndReset();
9690 assertEquals(u"Should format with US currency " + message, u"$1.00", actual);
9691 nf->setCurrency(cas.currencyArg, status);
9692 if (status.expectErrorAndReset(cas.expectedError)) {
9693 // If an error occurred, do not check formatting.
9694 continue;
9695 }
9696 nf->format(1, actual.remove(), status);
9697 assertEquals(u"Should unset the currency " + message, u"\u00A41.00", actual);
9698 status.errIfFailureAndReset();
9699 }
9700 }
9701
Test20348_CurrencyPrefixOverride()9702 void NumberFormatTest::Test20348_CurrencyPrefixOverride() {
9703 IcuTestErrorCode status(*this, "Test20348_CurrencyPrefixOverride");
9704 LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9705 NumberFormat::createCurrencyInstance("en", status)));
9706 if (status.errIfFailureAndReset()) { return; }
9707 UnicodeString result;
9708 assertEquals("Initial pattern",
9709 u"¤#,##0.00", fmt->toPattern(result.remove()));
9710 assertEquals("Initial prefix",
9711 u"¤", fmt->getPositivePrefix(result.remove()));
9712 assertEquals("Initial suffix",
9713 u"-¤", fmt->getNegativePrefix(result.remove()));
9714 assertEquals("Initial format",
9715 u"\u00A4100.00", fmt->format(100, result.remove(), NULL, status));
9716
9717 fmt->setPositivePrefix(u"$");
9718 assertEquals("Set positive prefix pattern",
9719 u"$#,##0.00;-\u00A4#,##0.00", fmt->toPattern(result.remove()));
9720 assertEquals("Set positive prefix prefix",
9721 u"$", fmt->getPositivePrefix(result.remove()));
9722 assertEquals("Set positive prefix suffix",
9723 u"-¤", fmt->getNegativePrefix(result.remove()));
9724 assertEquals("Set positive prefix format",
9725 u"$100.00", fmt->format(100, result.remove(), NULL, status));
9726
9727 fmt->setNegativePrefix(u"-$");
9728 assertEquals("Set negative prefix pattern",
9729 u"$#,##0.00;'-'$#,##0.00", fmt->toPattern(result.remove()));
9730 assertEquals("Set negative prefix prefix",
9731 u"$", fmt->getPositivePrefix(result.remove()));
9732 assertEquals("Set negative prefix suffix",
9733 u"-$", fmt->getNegativePrefix(result.remove()));
9734 assertEquals("Set negative prefix format",
9735 u"$100.00", fmt->format(100, result.remove(), NULL, status));
9736 }
9737
Test20956_MonetarySymbolGetters()9738 void NumberFormatTest::Test20956_MonetarySymbolGetters() {
9739 IcuTestErrorCode status(*this, "Test20956_MonetarySymbolGetters");
9740 LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9741 NumberFormat::createCurrencyInstance("et", status)));
9742 if (status.errDataIfFailureAndReset()) {
9743 return;
9744 }
9745
9746 decimalFormat->setCurrency(u"EEK");
9747
9748 const DecimalFormatSymbols* decimalFormatSymbols = decimalFormat->getDecimalFormatSymbols();
9749 assertEquals("MONETARY DECIMAL SEPARATOR",
9750 u".",
9751 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
9752 assertEquals("DECIMAL SEPARATOR",
9753 u",",
9754 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol));
9755 assertEquals("MONETARY GROUPING SEPARATOR",
9756 u" ",
9757 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol));
9758 assertEquals("GROUPING SEPARATOR",
9759 u" ",
9760 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
9761 assertEquals("CURRENCY SYMBOL",
9762 u"kr",
9763 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
9764
9765 UnicodeString sb;
9766 decimalFormat->format(12345.12, sb, status);
9767 assertEquals("OUTPUT", u"12 345.12 kr", sb);
9768 }
9769
Test20358_GroupingInPattern()9770 void NumberFormatTest::Test20358_GroupingInPattern() {
9771 IcuTestErrorCode status(*this, "Test20358_GroupingInPattern");
9772 LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9773 NumberFormat::createInstance("en", status)));
9774 if (status.errIfFailureAndReset()) { return; }
9775 UnicodeString result;
9776 assertEquals("Initial pattern",
9777 u"#,##0.###", fmt->toPattern(result.remove()));
9778 assertTrue("Initial grouping",
9779 fmt->isGroupingUsed());
9780 assertEquals("Initial format",
9781 u"54,321", fmt->format(54321, result.remove(), NULL, status));
9782
9783 fmt->setGroupingUsed(false);
9784 assertEquals("Set grouping false",
9785 u"0.###", fmt->toPattern(result.remove()));
9786 assertFalse("Set grouping false grouping",
9787 fmt->isGroupingUsed());
9788 assertEquals("Set grouping false format",
9789 u"54321", fmt->format(54321, result.remove(), NULL, status));
9790
9791 fmt->setGroupingUsed(true);
9792 assertEquals("Set grouping true",
9793 u"#,##0.###", fmt->toPattern(result.remove()));
9794 assertTrue("Set grouping true grouping",
9795 fmt->isGroupingUsed());
9796 assertEquals("Set grouping true format",
9797 u"54,321", fmt->format(54321, result.remove(), NULL, status));
9798 }
9799
Test13731_DefaultCurrency()9800 void NumberFormatTest::Test13731_DefaultCurrency() {
9801 IcuTestErrorCode status(*this, "Test13731_DefaultCurrency");
9802 UnicodeString result;
9803 {
9804 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9805 "en", UNumberFormatStyle::UNUM_CURRENCY, status), status);
9806 if (status.errIfFailureAndReset()) { return; }
9807 assertEquals("symbol", u"¤1.10",
9808 nf->format(1.1, result.remove(), status));
9809 assertEquals("currency", u"XXX", nf->getCurrency());
9810 }
9811 {
9812 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9813 "en", UNumberFormatStyle::UNUM_CURRENCY_ISO, status), status);
9814 if (status.errIfFailureAndReset()) { return; }
9815 assertEquals("iso_code", u"XXX 1.10",
9816 nf->format(1.1, result.remove(), status));
9817 assertEquals("currency", u"XXX", nf->getCurrency());
9818 }
9819 {
9820 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9821 "en", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9822 if (status.errIfFailureAndReset()) { return; }
9823 assertEquals("plural", u"1.10 (unknown currency)",
9824 nf->format(1.1, result.remove(), status));
9825 assertEquals("currency", u"XXX", nf->getCurrency());
9826 }
9827 }
9828
Test20499_CurrencyVisibleDigitsPlural()9829 void NumberFormatTest::Test20499_CurrencyVisibleDigitsPlural() {
9830 IcuTestErrorCode status(*this, "Test20499_CurrencyVisibleDigitsPlural");
9831 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9832 "ro-RO", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9833 const char16_t* expected = u"24,00 lei românești";
9834 for (int32_t i=0; i<5; i++) {
9835 UnicodeString actual;
9836 nf->format(24, actual, status);
9837 assertEquals(UnicodeString(u"iteration ") + Int64ToUnicodeString(i),
9838 expected, actual);
9839 }
9840 }
9841
Test13735_GroupingSizeGetter()9842 void NumberFormatTest::Test13735_GroupingSizeGetter() {
9843 IcuTestErrorCode status(*this, "Test13735_GroupingSizeGetter");
9844 {
9845 DecimalFormat df("0", {"en", status}, status);
9846 assertEquals("pat 0: ", 0, df.getGroupingSize());
9847 df.setGroupingUsed(false);
9848 assertEquals("pat 0 then disabled: ", 0, df.getGroupingSize());
9849 df.setGroupingUsed(true);
9850 assertEquals("pat 0 then enabled: ", 0, df.getGroupingSize());
9851 }
9852 {
9853 DecimalFormat df("#,##0", {"en", status}, status);
9854 assertEquals("pat #,##0: ", 3, df.getGroupingSize());
9855 df.setGroupingUsed(false);
9856 assertEquals("pat #,##0 then disabled: ", 3, df.getGroupingSize());
9857 df.setGroupingUsed(true);
9858 assertEquals("pat #,##0 then enabled: ", 3, df.getGroupingSize());
9859 }
9860 }
9861
Test13734_StrictFlexibleWhitespace()9862 void NumberFormatTest::Test13734_StrictFlexibleWhitespace() {
9863 IcuTestErrorCode status(*this, "Test13734_StrictFlexibleWhitespace");
9864 {
9865 DecimalFormat df("+0", {"en", status}, status);
9866 df.setLenient(FALSE);
9867 Formattable result;
9868 ParsePosition ppos;
9869 df.parse("+ 33", result, ppos);
9870 assertEquals("ppos : ", 0, ppos.getIndex());
9871 assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9872 }
9873 {
9874 DecimalFormat df("+ 0", {"en", status}, status);
9875 df.setLenient(FALSE);
9876 Formattable result;
9877 ParsePosition ppos;
9878 df.parse("+ 33", result, ppos);
9879 assertEquals("ppos : ", 0, ppos.getIndex());
9880 assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9881 }
9882 }
9883
Test20961_CurrencyPluralPattern()9884 void NumberFormatTest::Test20961_CurrencyPluralPattern() {
9885 IcuTestErrorCode status(*this, "Test20961_CurrencyPluralPattern");
9886 {
9887 LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9888 NumberFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9889 if (status.errDataIfFailureAndReset()) {
9890 return;
9891 }
9892 UnicodeString result;
9893 decimalFormat->toPattern(result);
9894 assertEquals("Currency pattern", u"#,##0.00 ¤¤¤", result);
9895 }
9896 }
9897
Test21134_ToNumberFormatter()9898 void NumberFormatTest::Test21134_ToNumberFormatter() {
9899 IcuTestErrorCode status(*this, "Test21134_ToNumberFormatter");
9900 LocalizedNumberFormatter outer1;
9901 LocalizedNumberFormatter outer2;
9902 LocalPointer<LocalizedNumberFormatter> outer3;
9903 {
9904 // Case 1: new formatter object
9905 DecimalFormat inner(u"a0b", {"en", status}, status);
9906 if (auto ptr = inner.toNumberFormatter(status)) {
9907 // Copy assignment
9908 outer1 = *ptr;
9909 } else {
9910 status.errIfFailureAndReset();
9911 return;
9912 }
9913 }
9914 {
9915 // Case 2: compiled formatter object (used at least 3 times)
9916 DecimalFormat inner(u"c0d", {"en", status}, status);
9917 UnicodeString dummy;
9918 inner.format(100, dummy);
9919 inner.format(100, dummy);
9920 inner.format(100, dummy);
9921 if (auto ptr = inner.toNumberFormatter(status)) {
9922 // Copy assignment
9923 outer2 = *ptr;
9924 } else {
9925 status.errIfFailureAndReset();
9926 return;
9927 }
9928 }
9929 {
9930 // Case 3: currency plural info (different code path)
9931 LocalPointer<DecimalFormat> inner(static_cast<DecimalFormat*>(
9932 DecimalFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9933 if (auto ptr = inner->toNumberFormatter(status)) {
9934 // Copy constructor
9935 outer3.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(*ptr), status);
9936 } else {
9937 status.errIfFailureAndReset();
9938 return;
9939 }
9940 }
9941 auto result1 = outer1.formatDouble(99, status);
9942 assertEquals("Using NumberFormatter from DecimalFormat, new version",
9943 u"a99b",
9944 result1.toTempString(status));
9945 auto result2 = outer2.formatDouble(99, status);
9946 assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9947 u"c99d",
9948 result2.toTempString(status));
9949 auto result3 = outer3->formatDouble(99, status);
9950 assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9951 u"99.00 US dollars",
9952 result3.toTempString(status));
9953 }
9954
Test13733_StrictAndLenient()9955 void NumberFormatTest::Test13733_StrictAndLenient() {
9956 IcuTestErrorCode status(*this, "Test13733_StrictAndLenient");
9957
9958 static const struct TestCase {
9959 const char16_t* inputString;
9960 const char16_t* patternString;
9961 int64_t expectedStrictParse;
9962 int64_t expectedLenientParse;
9963 } cases[] = { {u"CA$ 12", u"¤ 0", 12, 12},
9964 {u"CA$12", u"¤0", 12, 12},
9965 {u"CAD 12", u"¤¤ 0", 12, 12},
9966 {u"12 CAD", u"0 ¤¤", 12, 12},
9967 {u"12 Canadian dollars", u"0 ¤¤¤", 12, 12},
9968 {u"$12 ", u"¤¤¤¤0", 12, 12},
9969 {u"12$", u"0¤¤¤¤", 12, 12},
9970 {u"CA$ 12", u"¤0", 0, 12},
9971 {u"CA$ 12", u"0 ¤¤", 0, 12},
9972 {u"CA$ 12", u"0 ¤¤¤", 0, 12},
9973 {u"CA$ 12", u"¤¤¤¤0", 0, 12},
9974 {u"CA$ 12", u"0¤¤¤¤", 0, 12},
9975 {u"CA$12", u"¤ 0", 0, 12},
9976 {u"CA$12", u"¤¤ 0", 0, 12},
9977 {u"CA$12", u"0 ¤¤", 0, 12},
9978 {u"CA$12", u"0 ¤¤¤", 0, 12},
9979 {u"CA$12", u"0¤¤¤¤", 0, 12},
9980 {u"CAD 12", u"¤0", 0, 12},
9981 {u"CAD 12", u"0 ¤¤", 0, 12},
9982 {u"CAD 12", u"0 ¤¤¤", 0, 12},
9983 {u"CAD 12", u"¤¤¤¤0", 0, 12},
9984 {u"CAD 12", u"0¤¤¤¤", 0, 12},
9985 {u"12 CAD", u"¤ 0", 0, 12},
9986 {u"12 CAD", u"¤0", 0, 12},
9987 {u"12 CAD", u"¤¤ 0", 0, 12},
9988 {u"12 CAD", u"¤¤¤¤0", 0, 12},
9989 {u"12 CAD", u"0¤¤¤¤", 0, 12},
9990 {u"12 Canadian dollars", u"¤ 0", 0, 12},
9991 {u"12 Canadian dollars", u"¤0", 0, 12},
9992 {u"12 Canadian dollars", u"¤¤ 0", 0, 12},
9993 {u"12 Canadian dollars", u"¤¤¤¤0", 0, 12},
9994 {u"12 Canadian dollars", u"0¤¤¤¤", 0, 12},
9995 {u"$12 ", u"¤ 0", 0, 12},
9996 {u"$12 ", u"¤¤ 0", 0, 12},
9997 {u"$12 ", u"0 ¤¤", 0, 12},
9998 {u"$12 ", u"0 ¤¤¤", 0, 12},
9999 {u"$12 ", u"0¤¤¤¤", 0, 12},
10000 {u"12$", u"¤ 0", 0, 12},
10001 {u"12$", u"¤0", 0, 12},
10002 {u"12$", u"¤¤ 0", 0, 12},
10003 {u"12$", u"0 ¤¤", 0, 12},
10004 {u"12$", u"0 ¤¤¤", 0, 12},
10005 {u"12$", u"¤¤¤¤0", 0, 12} };
10006 for (auto& cas : cases) {
10007 UnicodeString inputString(cas.inputString);
10008 UnicodeString patternString(cas.patternString);
10009 int64_t parsedStrictValue = 0;
10010 int64_t parsedLenientValue = 0;
10011 ParsePosition ppos;
10012
10013 DecimalFormatSymbols dfs(Locale::getEnglish(), status);
10014 if (status.errDataIfFailureAndReset()) {
10015 return;
10016 }
10017 DecimalFormat df(patternString, dfs, status);
10018 if (status.errDataIfFailureAndReset()) {
10019 return;
10020 }
10021 df.setLenient(FALSE);
10022 LocalPointer<CurrencyAmount> ca_strict(df.parseCurrency(inputString, ppos));
10023 if (ca_strict != nullptr) {
10024 parsedStrictValue = ca_strict->getNumber().getInt64();
10025 }
10026 assertEquals("Strict parse of " + inputString + " using " + patternString,
10027 parsedStrictValue, cas.expectedStrictParse);
10028
10029 ppos.setIndex(0);
10030 df.setLenient(TRUE);
10031 LocalPointer<CurrencyAmount> ca_lenient(df.parseCurrency(inputString, ppos));
10032 Formattable parsedNumber_lenient = ca_lenient->getNumber();
10033 if (ca_lenient != nullptr) {
10034 parsedLenientValue = ca_lenient->getNumber().getInt64();
10035 }
10036 assertEquals("Lenient parse of " + inputString + " using " + patternString,
10037 parsedLenientValue, cas.expectedLenientParse);
10038 }
10039 }
10040
Test21232_ParseTimeout()10041 void NumberFormatTest::Test21232_ParseTimeout() {
10042 IcuTestErrorCode status(*this, "Test21232_ParseTimeout");
10043
10044 DecimalFormat df(status);
10045 if (status.errDataIfFailureAndReset()) {
10046 return;
10047 }
10048
10049 UnicodeString input = u"4444444444444444444444444444444444444444";
10050 if (quick) {
10051 for (int32_t i = 0; i < 5; i++) {
10052 input.append(input);
10053 }
10054 assertEquals("Somewhat long input of digits", 1280, input.length());
10055 } else {
10056 for (int32_t i = 0; i < 12; i++) {
10057 input.append(input);
10058 }
10059 assertEquals("Very long input of digits", 163840, input.length());
10060 }
10061 Formattable result;
10062 df.parse(input, result, status);
10063 // Should not hang
10064 }
10065
10066 #endif /* #if !UCONFIG_NO_FORMATTING */
10067