1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8 /* Modification History:
9 * Date Name Description
10 * 07/15/99 helena Ported to HPUX 10/11 CC.
11 */
12
13 #include "unicode/utypes.h"
14
15 #if !UCONFIG_NO_FORMATTING
16
17 #include "numfmtst.h"
18 #include "unicode/currpinf.h"
19 #include "unicode/dcfmtsym.h"
20 #include "unicode/decimfmt.h"
21 #include "unicode/localpointer.h"
22 #include "unicode/ucurr.h"
23 #include "unicode/ustring.h"
24 #include "unicode/measfmt.h"
25 #include "unicode/curramt.h"
26 #include "unicode/strenum.h"
27 #include "textfile.h"
28 #include "tokiter.h"
29 #include "charstr.h"
30 #include "cstr.h"
31 #include "putilimp.h"
32 #include "winnmtst.h"
33 #include <cmath>
34 #include <float.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include "cmemory.h"
38 #include "cstring.h"
39 #include "unicode/numsys.h"
40 #include "fmtableimp.h"
41 #include "numberformattesttuple.h"
42 #include "unicode/msgfmt.h"
43 #include "number_decimalquantity.h"
44 #include "unicode/numberformatter.h"
45
46 #if (U_PLATFORM == U_PF_AIX) || (U_PLATFORM == U_PF_OS390)
47 // These should not be macros. If they are,
48 // replace them with std::isnan and std::isinf
49 #if defined(isnan)
50 #undef isnan
51 namespace std {
isnan(double x)52 bool isnan(double x) {
53 return _isnan(x);
54 }
55 }
56 #endif
57 #if defined(isinf)
58 #undef isinf
59 namespace std {
isinf(double x)60 bool isinf(double x) {
61 return _isinf(x);
62 }
63 }
64 #endif
65 #endif
66
67 using icu::number::impl::DecimalQuantity;
68 using namespace icu::number;
69
70 //#define NUMFMTST_CACHE_DEBUG 1
71 #include "stdio.h" /* for sprintf */
72 // #include "iostream" // for cout
73
74 //#define NUMFMTST_DEBUG 1
75
76 static const UChar EUR[] = {69,85,82,0}; // "EUR"
77 static const UChar ISO_CURRENCY_USD[] = {0x55, 0x53, 0x44, 0}; // "USD"
78
79
80 // *****************************************************************************
81 // class NumberFormatTest
82 // *****************************************************************************
83
84 #define CHECK(status,str) UPRV_BLOCK_MACRO_BEGIN { \
85 if (U_FAILURE(status)) { \
86 errcheckln(status, UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \
87 return; \
88 } \
89 } UPRV_BLOCK_MACRO_END
90 #define CHECK_DATA(status,str) UPRV_BLOCK_MACRO_BEGIN { \
91 if (U_FAILURE(status)) { \
92 dataerrln(UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \
93 return; \
94 } \
95 } UPRV_BLOCK_MACRO_END
96
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)97 void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
98 {
99 TESTCASE_AUTO_BEGIN;
100 TESTCASE_AUTO(TestCurrencySign);
101 TESTCASE_AUTO(TestCurrency);
102 TESTCASE_AUTO(TestParse);
103 TESTCASE_AUTO(TestRounding487);
104 TESTCASE_AUTO(TestQuotes);
105 TESTCASE_AUTO(TestExponential);
106 TESTCASE_AUTO(TestPatterns);
107 TESTCASE_AUTO(Test20186_SpacesAroundSemicolon);
108
109 // Upgrade to alphaWorks - liu 5/99
110 TESTCASE_AUTO(TestExponent);
111 TESTCASE_AUTO(TestScientific);
112 TESTCASE_AUTO(TestPad);
113 TESTCASE_AUTO(TestPatterns2);
114 TESTCASE_AUTO(TestSecondaryGrouping);
115 TESTCASE_AUTO(TestSurrogateSupport);
116 TESTCASE_AUTO(TestAPI);
117
118 TESTCASE_AUTO(TestCurrencyObject);
119 TESTCASE_AUTO(TestCurrencyPatterns);
120 //TESTCASE_AUTO(TestDigitList);
121 TESTCASE_AUTO(TestWhiteSpaceParsing);
122 TESTCASE_AUTO(TestComplexCurrency); // This test removed because CLDR no longer uses choice formats in currency symbols.
123 TESTCASE_AUTO(TestRegCurrency);
124 TESTCASE_AUTO(TestSymbolsWithBadLocale);
125 TESTCASE_AUTO(TestAdoptDecimalFormatSymbols);
126
127 TESTCASE_AUTO(TestScientific2);
128 TESTCASE_AUTO(TestScientificGrouping);
129 TESTCASE_AUTO(TestInt64);
130
131 TESTCASE_AUTO(TestPerMill);
132 TESTCASE_AUTO(TestIllegalPatterns);
133 TESTCASE_AUTO(TestCases);
134
135 TESTCASE_AUTO(TestCurrencyNames);
136 TESTCASE_AUTO(TestCurrencyVariants);
137 TESTCASE_AUTO(TestCurrencyAmount);
138 TESTCASE_AUTO(TestCurrencyUnit);
139 TESTCASE_AUTO(TestCoverage);
140 TESTCASE_AUTO(TestLocalizedPatternSymbolCoverage);
141 TESTCASE_AUTO(TestJB3832);
142 TESTCASE_AUTO(TestHost);
143 TESTCASE_AUTO(TestHostClone);
144 TESTCASE_AUTO(TestCurrencyFormat);
145 TESTCASE_AUTO(TestRounding);
146 TESTCASE_AUTO(TestNonpositiveMultiplier);
147 TESTCASE_AUTO(TestNumberingSystems);
148 TESTCASE_AUTO(TestSpaceParsing);
149 TESTCASE_AUTO(TestMultiCurrencySign);
150 TESTCASE_AUTO(TestCurrencyFormatForMixParsing);
151 TESTCASE_AUTO(TestMismatchedCurrencyFormatFail);
152 TESTCASE_AUTO(TestDecimalFormatCurrencyParse);
153 TESTCASE_AUTO(TestCurrencyIsoPluralFormat);
154 TESTCASE_AUTO(TestCurrencyParsing);
155 TESTCASE_AUTO(TestParseCurrencyInUCurr);
156 TESTCASE_AUTO(TestFormatAttributes);
157 TESTCASE_AUTO(TestFieldPositionIterator);
158 TESTCASE_AUTO(TestDecimal);
159 TESTCASE_AUTO(TestCurrencyFractionDigits);
160 TESTCASE_AUTO(TestExponentParse);
161 TESTCASE_AUTO(TestExplicitParents);
162 TESTCASE_AUTO(TestLenientParse);
163 TESTCASE_AUTO(TestAvailableNumberingSystems);
164 TESTCASE_AUTO(TestRoundingPattern);
165 TESTCASE_AUTO(Test9087);
166 TESTCASE_AUTO(TestFormatFastpaths);
167 TESTCASE_AUTO(TestFormattableSize);
168 TESTCASE_AUTO(TestUFormattable);
169 TESTCASE_AUTO(TestSignificantDigits);
170 TESTCASE_AUTO(TestShowZero);
171 TESTCASE_AUTO(TestCompatibleCurrencies);
172 TESTCASE_AUTO(TestBug9936);
173 TESTCASE_AUTO(TestParseNegativeWithFaLocale);
174 TESTCASE_AUTO(TestParseNegativeWithAlternateMinusSign);
175 TESTCASE_AUTO(TestCustomCurrencySignAndSeparator);
176 TESTCASE_AUTO(TestParseSignsAndMarks);
177 TESTCASE_AUTO(Test10419RoundingWith0FractionDigits);
178 TESTCASE_AUTO(Test10468ApplyPattern);
179 TESTCASE_AUTO(TestRoundingScientific10542);
180 TESTCASE_AUTO(TestZeroScientific10547);
181 TESTCASE_AUTO(TestAccountingCurrency);
182 TESTCASE_AUTO(TestCurrencyFormatForMissingLocale);
183 TESTCASE_AUTO(TestEquality);
184 TESTCASE_AUTO(TestCurrencyUsage);
185 TESTCASE_AUTO(TestDoubleLimit11439);
186 TESTCASE_AUTO(TestGetAffixes);
187 TESTCASE_AUTO(TestToPatternScientific11648);
188 TESTCASE_AUTO(TestBenchmark);
189 TESTCASE_AUTO(TestCtorApplyPatternDifference);
190 TESTCASE_AUTO(TestFractionalDigitsForCurrency);
191 TESTCASE_AUTO(TestFormatCurrencyPlural);
192 TESTCASE_AUTO(Test11868);
193 TESTCASE_AUTO(Test11739_ParseLongCurrency);
194 TESTCASE_AUTO(Test13035_MultiCodePointPaddingInPattern);
195 TESTCASE_AUTO(Test13737_ParseScientificStrict);
196 TESTCASE_AUTO(Test10727_RoundingZero);
197 TESTCASE_AUTO(Test11376_getAndSetPositivePrefix);
198 TESTCASE_AUTO(Test11475_signRecognition);
199 TESTCASE_AUTO(Test11640_getAffixes);
200 TESTCASE_AUTO(Test11649_toPatternWithMultiCurrency);
201 TESTCASE_AUTO(Test13327_numberingSystemBufferOverflow);
202 TESTCASE_AUTO(Test13391_chakmaParsing);
203 TESTCASE_AUTO(Test11735_ExceptionIssue);
204 TESTCASE_AUTO(Test11035_FormatCurrencyAmount);
205 TESTCASE_AUTO(Test11318_DoubleConversion);
206 TESTCASE_AUTO(TestParsePercentRegression);
207 TESTCASE_AUTO(TestMultiplierWithScale);
208 TESTCASE_AUTO(TestFastFormatInt32);
209 TESTCASE_AUTO(Test11646_Equality);
210 TESTCASE_AUTO(TestParseNaN);
211 TESTCASE_AUTO(TestFormatFailIfMoreThanMaxDigits);
212 TESTCASE_AUTO(TestParseCaseSensitive);
213 TESTCASE_AUTO(TestParseNoExponent);
214 TESTCASE_AUTO(TestSignAlwaysShown);
215 TESTCASE_AUTO(TestMinimumGroupingDigits);
216 TESTCASE_AUTO(Test11897_LocalizedPatternSeparator);
217 TESTCASE_AUTO(Test13055_PercentageRounding);
218 TESTCASE_AUTO(Test11839);
219 TESTCASE_AUTO(Test10354);
220 TESTCASE_AUTO(Test11645_ApplyPatternEquality);
221 TESTCASE_AUTO(Test12567);
222 TESTCASE_AUTO(Test11626_CustomizeCurrencyPluralInfo);
223 TESTCASE_AUTO(Test20073_StrictPercentParseErrorIndex);
224 TESTCASE_AUTO(Test13056_GroupingSize);
225 TESTCASE_AUTO(Test11025_CurrencyPadding);
226 TESTCASE_AUTO(Test11648_ExpDecFormatMalPattern);
227 TESTCASE_AUTO(Test11649_DecFmtCurrencies);
228 TESTCASE_AUTO(Test13148_ParseGroupingSeparators);
229 TESTCASE_AUTO(Test12753_PatternDecimalPoint);
230 TESTCASE_AUTO(Test11647_PatternCurrencySymbols);
231 TESTCASE_AUTO(Test11913_BigDecimal);
232 TESTCASE_AUTO(Test11020_RoundingInScientificNotation);
233 TESTCASE_AUTO(Test11640_TripleCurrencySymbol);
234 TESTCASE_AUTO(Test13763_FieldPositionIteratorOffset);
235 TESTCASE_AUTO(Test13777_ParseLongNameNonCurrencyMode);
236 TESTCASE_AUTO(Test13804_EmptyStringsWhenParsing);
237 TESTCASE_AUTO(Test20037_ScientificIntegerOverflow);
238 TESTCASE_AUTO(Test13840_ParseLongStringCrash);
239 TESTCASE_AUTO(Test13850_EmptyStringCurrency);
240 TESTCASE_AUTO(Test20348_CurrencyPrefixOverride);
241 TESTCASE_AUTO(Test20956_MonetarySymbolGetters);
242 TESTCASE_AUTO(Test20358_GroupingInPattern);
243 TESTCASE_AUTO(Test13731_DefaultCurrency);
244 TESTCASE_AUTO(Test20499_CurrencyVisibleDigitsPlural);
245 TESTCASE_AUTO(Test13735_GroupingSizeGetter);
246 TESTCASE_AUTO(Test13734_StrictFlexibleWhitespace);
247 TESTCASE_AUTO(Test20961_CurrencyPluralPattern);
248 TESTCASE_AUTO(Test21134_ToNumberFormatter);
249 TESTCASE_AUTO(Test13733_StrictAndLenient);
250 TESTCASE_AUTO(Test21232_ParseTimeout);
251 TESTCASE_AUTO(Test10997_FormatCurrency);
252 TESTCASE_AUTO_END;
253 }
254
255 // -------------------------------------
256
257 // Test API (increase code coverage)
258 void
TestAPI(void)259 NumberFormatTest::TestAPI(void)
260 {
261 logln("Test API");
262 UErrorCode status = U_ZERO_ERROR;
263 NumberFormat *test = NumberFormat::createInstance("root", status);
264 if(U_FAILURE(status)) {
265 dataerrln("unable to create format object - %s", u_errorName(status));
266 }
267 if(test != NULL) {
268 test->setMinimumIntegerDigits(10);
269 test->setMaximumIntegerDigits(1);
270
271 test->setMinimumFractionDigits(10);
272 test->setMaximumFractionDigits(1);
273
274 UnicodeString result;
275 FieldPosition pos;
276 Formattable bla("Paja Patak"); // Donald Duck for non Serbian speakers
277 test->format(bla, result, pos, status);
278 if(U_SUCCESS(status)) {
279 errln("Yuck... Formatted a duck... As a number!");
280 } else {
281 status = U_ZERO_ERROR;
282 }
283
284 result.remove();
285 int64_t ll = 12;
286 test->format(ll, result);
287 assertEquals("format int64_t error", u"2.0", result);
288
289 test->setMinimumIntegerDigits(4);
290 test->setMinimumFractionDigits(4);
291
292 result.remove();
293 test->format(ll, result);
294 assertEquals("format int64_t error", u"0,012.0000", result);
295
296 ParsePosition ppos;
297 LocalPointer<CurrencyAmount> currAmt(test->parseCurrency("",ppos));
298 // old test for (U_FAILURE(status)) was bogus here, method does not set status!
299 if (ppos.getIndex()) {
300 errln("Parsed empty string as currency");
301 }
302
303 delete test;
304 }
305 }
306
307 class StubNumberFormat :public NumberFormat{
308 public:
StubNumberFormat()309 StubNumberFormat(){}
format(double,UnicodeString & appendTo,FieldPosition &) const310 virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const {
311 return appendTo;
312 }
format(int32_t,UnicodeString & appendTo,FieldPosition &) const313 virtual UnicodeString& format(int32_t ,UnicodeString& appendTo,FieldPosition& ) const {
314 return appendTo.append((UChar)0x0033);
315 }
format(int64_t number,UnicodeString & appendTo,FieldPosition & pos) const316 virtual UnicodeString& format(int64_t number,UnicodeString& appendTo,FieldPosition& pos) const {
317 return NumberFormat::format(number, appendTo, pos);
318 }
format(const Formattable &,UnicodeString & appendTo,FieldPosition &,UErrorCode &) const319 virtual UnicodeString& format(const Formattable& , UnicodeString& appendTo, FieldPosition& , UErrorCode& ) const {
320 return appendTo;
321 }
parse(const UnicodeString &,Formattable &,ParsePosition &) const322 virtual void parse(const UnicodeString& ,
323 Formattable& ,
324 ParsePosition& ) const {}
parse(const UnicodeString &,Formattable &,UErrorCode &) const325 virtual void parse( const UnicodeString& ,
326 Formattable& ,
327 UErrorCode& ) const {}
getDynamicClassID(void) const328 virtual UClassID getDynamicClassID(void) const {
329 static char classID = 0;
330 return (UClassID)&classID;
331 }
clone() const332 virtual StubNumberFormat* clone() const {return NULL;}
333 };
334
335 void
TestCoverage(void)336 NumberFormatTest::TestCoverage(void){
337 StubNumberFormat stub;
338 UnicodeString agent("agent");
339 FieldPosition pos;
340 int64_t num = 4;
341 if (stub.format(num, agent, pos) != UnicodeString("agent3")){
342 errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)");
343 }
344 }
345
TestLocalizedPatternSymbolCoverage()346 void NumberFormatTest::TestLocalizedPatternSymbolCoverage() {
347 IcuTestErrorCode errorCode(*this, "TestLocalizedPatternSymbolCoverage");
348 // Ticket #12961: DecimalFormat::toLocalizedPattern() is not working as designed.
349 DecimalFormatSymbols dfs(errorCode);
350 dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u'⁖');
351 dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'⁘');
352 dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u'⁙');
353 dfs.setSymbol(DecimalFormatSymbols::kDigitSymbol, u'▰');
354 dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u'໐');
355 dfs.setSymbol(DecimalFormatSymbols::kSignificantDigitSymbol, u'⁕');
356 dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u'†');
357 dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u'‡');
358 dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u'⁜');
359 dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u'‱');
360 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"⁑⁑"); // tests multi-char sequence
361 dfs.setSymbol(DecimalFormatSymbols::kPadEscapeSymbol, u'⁂');
362
363 {
364 UnicodeString standardPattern(u"#,##0.05+%;#,##0.05-%");
365 UnicodeString localizedPattern(u"▰⁖▰▰໐⁘໐໕†⁜⁙▰⁖▰▰໐⁘໐໕‡⁜");
366
367 DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
368 df1.applyPattern(standardPattern, errorCode);
369 DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
370 df2.applyLocalizedPattern(localizedPattern, errorCode);
371 assertTrue("DecimalFormat instances should be equal", df1 == df2);
372 UnicodeString p2;
373 assertEquals("toPattern should match on localizedPattern instance",
374 standardPattern, df2.toPattern(p2));
375 UnicodeString lp1;
376 assertEquals("toLocalizedPattern should match on standardPattern instance",
377 localizedPattern, df1.toLocalizedPattern(lp1));
378 }
379
380 {
381 UnicodeString standardPattern(u"* @@@E0‰");
382 UnicodeString localizedPattern(u"⁂ ⁕⁕⁕⁑⁑໐‱");
383
384 DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
385 df1.applyPattern(standardPattern, errorCode);
386 DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
387 df2.applyLocalizedPattern(localizedPattern, errorCode);
388 assertTrue("DecimalFormat instances should be equal", df1 == df2);
389 UnicodeString p2;
390 assertEquals("toPattern should match on localizedPattern instance",
391 standardPattern, df2.toPattern(p2));
392 UnicodeString lp1;
393 assertEquals("toLocalizedPattern should match on standardPattern instance",
394 localizedPattern, df1.toLocalizedPattern(lp1));
395 }
396 }
397
398 // Test various patterns
399 void
TestPatterns(void)400 NumberFormatTest::TestPatterns(void)
401 {
402 UErrorCode status = U_ZERO_ERROR;
403 DecimalFormatSymbols sym(Locale::getUS(), status);
404 if (U_FAILURE(status)) { errcheckln(status, "FAIL: Could not construct DecimalFormatSymbols - %s", u_errorName(status)); return; }
405
406 const char* pat[] = { "#.#", "#.", ".#", "#" };
407 int32_t pat_length = UPRV_LENGTHOF(pat);
408 const char* newpat[] = { "0.#", "0.", "#.0", "0" };
409 const char* num[] = { "0", "0.", ".0", "0" };
410 for (int32_t i=0; i<pat_length; ++i)
411 {
412 status = U_ZERO_ERROR;
413 DecimalFormat fmt(pat[i], sym, status);
414 if (U_FAILURE(status)) { errln((UnicodeString)"FAIL: DecimalFormat constructor failed for " + pat[i]); continue; }
415 UnicodeString newp; fmt.toPattern(newp);
416 if (!(newp == newpat[i]))
417 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
418 "; " + newp + " seen instead");
419
420 UnicodeString s; (*(NumberFormat*)&fmt).format((int32_t)0, s);
421 if (!(s == num[i]))
422 {
423 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
424 "; " + s + " seen instead");
425 logln((UnicodeString)"Min integer digits = " + fmt.getMinimumIntegerDigits());
426 }
427 }
428 }
429
Test20186_SpacesAroundSemicolon()430 void NumberFormatTest::Test20186_SpacesAroundSemicolon() {
431 IcuTestErrorCode status(*this, "Test20186_SpacesAroundSemicolon");
432 DecimalFormat df(u"0.00 ; -0.00", {"en-us", status}, status);
433 expect2(df, 1, u"1.00 ");
434 expect2(df, -1, u" -1.00");
435
436 df = DecimalFormat(u"0.00;", {"en-us", status}, status);
437 expect2(df, 1, u"1.00");
438 expect2(df, -1, u"-1.00");
439
440 df = DecimalFormat(u"0.00;0.00", {"en-us", status}, status);
441 expect2(df, 1, u"1.00");
442 expect(df, -1, u"1.00"); // parses as 1, not -1
443
444 df = DecimalFormat(u" 0.00 ; -0.00 ", {"en-us", status}, status);
445 expect2(df, 1, u" 1.00 ");
446 expect2(df, -1, u" -1.00 ");
447 }
448
449 /*
450 icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
451 icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
452 icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
453 */
454 /*
455 void
456 NumberFormatTest::TestDigitList(void)
457 {
458 // API coverage for DigitList
459 DigitList list1;
460 list1.append('1');
461 list1.fDecimalAt = 1;
462 DigitList list2;
463 list2.set((int32_t)1);
464 if (list1 != list2) {
465 errln("digitlist append, operator!= or set failed ");
466 }
467 if (!(list1 == list2)) {
468 errln("digitlist append, operator== or set failed ");
469 }
470 }
471 */
472
473 // -------------------------------------
474
475 // Test exponential pattern
476 void
TestExponential(void)477 NumberFormatTest::TestExponential(void)
478 {
479 UErrorCode status = U_ZERO_ERROR;
480 DecimalFormatSymbols sym(Locale::getUS(), status);
481 if (U_FAILURE(status)) { errcheckln(status, "FAIL: Bad status returned by DecimalFormatSymbols ct - %s", u_errorName(status)); return; }
482 const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
483 int32_t pat_length = UPRV_LENGTHOF(pat);
484
485 // The following #if statements allow this test to be built and run on
486 // platforms that do not have standard IEEE numerics. For example,
487 // S/390 doubles have an exponent range of -78 to +75. For the
488 // following #if statements to work, float.h must define
489 // DBL_MAX_10_EXP to be a compile-time constant.
490
491 // This section may be expanded as needed.
492
493 #if DBL_MAX_10_EXP > 300
494 double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
495 int32_t val_length = UPRV_LENGTHOF(val);
496 const char* valFormat[] =
497 {
498 // 0.####E0
499 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
500 // 00.000E00
501 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
502 // ##0.######E000
503 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
504 // 0.###E0;[0.###E0]
505 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
506 };
507 double valParse[] =
508 {
509 0.01234, 123460000, 1.23E300, -3.1416E-271,
510 0.01234, 123460000, 1.23E300, -3.1416E-271,
511 0.01234, 123456800, 1.23E300, -3.141593E-271,
512 0.01234, 123500000, 1.23E300, -3.142E-271,
513 };
514 #elif DBL_MAX_10_EXP > 70
515 double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
516 int32_t val_length = UPRV_LENGTHOF(val);
517 char* valFormat[] =
518 {
519 // 0.####E0
520 "1.234E-2", "1.2346E8", "1.23E70", "-3.1416E-71",
521 // 00.000E00
522 "12.340E-03", "12.346E07", "12.300E69", "-31.416E-72",
523 // ##0.######E000
524 "12.34E-003", "123.4568E006", "12.3E069", "-31.41593E-072",
525 // 0.###E0;[0.###E0]
526 "1.234E-2", "1.235E8", "1.23E70", "[3.142E-71]"
527 };
528 double valParse[] =
529 {
530 0.01234, 123460000, 1.23E70, -3.1416E-71,
531 0.01234, 123460000, 1.23E70, -3.1416E-71,
532 0.01234, 123456800, 1.23E70, -3.141593E-71,
533 0.01234, 123500000, 1.23E70, -3.142E-71,
534 };
535 #else
536 // Don't test double conversion
537 double* val = 0;
538 int32_t val_length = 0;
539 char** valFormat = 0;
540 double* valParse = 0;
541 logln("Warning: Skipping double conversion tests");
542 #endif
543
544 int32_t lval[] = { 0, -1, 1, 123456789 };
545 int32_t lval_length = UPRV_LENGTHOF(lval);
546 const char* lvalFormat[] =
547 {
548 // 0.####E0
549 "0E0", "-1E0", "1E0", "1.2346E8",
550 // 00.000E00
551 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
552 // ##0.######E000
553 "0E000", "-1E000", "1E000", "123.4568E006",
554 // 0.###E0;[0.###E0]
555 "0E0", "[1E0]", "1E0", "1.235E8"
556 };
557 int32_t lvalParse[] =
558 {
559 0, -1, 1, 123460000,
560 0, -1, 1, 123460000,
561 0, -1, 1, 123456800,
562 0, -1, 1, 123500000,
563 };
564 int32_t ival = 0, ilval = 0;
565 for (int32_t p=0; p<pat_length; ++p)
566 {
567 DecimalFormat fmt(pat[p], sym, status);
568 if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormat ct"); continue; }
569 UnicodeString pattern;
570 logln((UnicodeString)"Pattern \"" + pat[p] + "\" -toPattern-> \"" +
571 fmt.toPattern(pattern) + "\"");
572 int32_t v;
573 for (v=0; v<val_length; ++v)
574 {
575 UnicodeString s; (*(NumberFormat*)&fmt).format(val[v], s);
576 logln((UnicodeString)" " + val[v] + " -format-> " + s);
577 if (s != valFormat[v+ival])
578 errln((UnicodeString)"FAIL: Expected " + valFormat[v+ival]);
579
580 ParsePosition pos(0);
581 Formattable af;
582 fmt.parse(s, af, pos);
583 double a;
584 UBool useEpsilon = FALSE;
585 if (af.getType() == Formattable::kLong)
586 a = af.getLong();
587 else if (af.getType() == Formattable::kDouble) {
588 a = af.getDouble();
589 #if U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400
590 // S/390 will show a failure like this:
591 //| -3.141592652999999e-271 -format-> -3.1416E-271
592 //| -parse-> -3.1416e-271
593 //| FAIL: Expected -3.141599999999999e-271
594 // To compensate, we use an epsilon-based equality
595 // test on S/390 only. We don't want to do this in
596 // general because it's less exacting.
597 useEpsilon = TRUE;
598 #endif
599 }
600 else {
601 errln(UnicodeString("FAIL: Non-numeric Formattable returned: ") + pattern + " " + s);
602 continue;
603 }
604 if (pos.getIndex() == s.length())
605 {
606 logln((UnicodeString)" -parse-> " + a);
607 // Use epsilon comparison as necessary
608 if ((useEpsilon &&
609 (uprv_fabs(a - valParse[v+ival]) / a > (2*DBL_EPSILON))) ||
610 (!useEpsilon && a != valParse[v+ival]))
611 {
612 errln((UnicodeString)"FAIL: Expected " + valParse[v+ival] + " but got " + a
613 + " on input " + s);
614 }
615 }
616 else {
617 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
618 errln((UnicodeString)" should be (" + s.length() + " chars) -> " + valParse[v+ival]);
619 }
620 }
621 for (v=0; v<lval_length; ++v)
622 {
623 UnicodeString s;
624 (*(NumberFormat*)&fmt).format(lval[v], s);
625 logln((UnicodeString)" " + lval[v] + "L -format-> " + s);
626 if (s != lvalFormat[v+ilval])
627 errln((UnicodeString)"ERROR: Expected " + lvalFormat[v+ilval] + " Got: " + s);
628
629 ParsePosition pos(0);
630 Formattable af;
631 fmt.parse(s, af, pos);
632 if (af.getType() == Formattable::kLong ||
633 af.getType() == Formattable::kInt64) {
634 UErrorCode status = U_ZERO_ERROR;
635 int32_t a = af.getLong(status);
636 if (pos.getIndex() == s.length())
637 {
638 logln((UnicodeString)" -parse-> " + a);
639 if (a != lvalParse[v+ilval])
640 errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval] + " but got " + a);
641 }
642 else
643 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
644 }
645 else
646 errln((UnicodeString)"FAIL: Non-long Formattable returned for " + s
647 + " Double: " + af.getDouble()
648 + ", Long: " + af.getLong());
649 }
650 ival += val_length;
651 ilval += lval_length;
652 }
653 }
654
655 void
TestScientific2()656 NumberFormatTest::TestScientific2() {
657 // jb 2552
658 UErrorCode status = U_ZERO_ERROR;
659 DecimalFormat* fmt = (DecimalFormat*)NumberFormat::createCurrencyInstance("en_US", status);
660 if (U_SUCCESS(status)) {
661 double num = 12.34;
662 expect(*fmt, num, "$12.34");
663 fmt->setScientificNotation(TRUE);
664 expect(*fmt, num, "$1.23E1");
665 fmt->setScientificNotation(FALSE);
666 expect(*fmt, num, "$12.34");
667 }
668 delete fmt;
669 }
670
671 void
TestScientificGrouping()672 NumberFormatTest::TestScientificGrouping() {
673 // jb 2552
674 UErrorCode status = U_ZERO_ERROR;
675 DecimalFormat fmt("##0.00E0",status);
676 if (assertSuccess("", status, true, __FILE__, __LINE__)) {
677 expect(fmt, .01234, "12.3E-3");
678 expect(fmt, .1234, "123E-3");
679 expect(fmt, 1.234, "1.23E0");
680 expect(fmt, 12.34, "12.3E0");
681 expect(fmt, 123.4, "123E0");
682 expect(fmt, 1234., "1.23E3");
683 }
684 }
685
686 /*static void setFromString(DigitList& dl, const char* str) {
687 char c;
688 UBool decimalSet = FALSE;
689 dl.clear();
690 while ((c = *str++)) {
691 if (c == '-') {
692 dl.fIsPositive = FALSE;
693 } else if (c == '+') {
694 dl.fIsPositive = TRUE;
695 } else if (c == '.') {
696 dl.fDecimalAt = dl.fCount;
697 decimalSet = TRUE;
698 } else {
699 dl.append(c);
700 }
701 }
702 if (!decimalSet) {
703 dl.fDecimalAt = dl.fCount;
704 }
705 }*/
706
707 void
TestInt64()708 NumberFormatTest::TestInt64() {
709 UErrorCode status = U_ZERO_ERROR;
710 DecimalFormat fmt("#.#E0",status);
711 if (U_FAILURE(status)) {
712 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
713 return;
714 }
715 fmt.setMaximumFractionDigits(20);
716 if (U_SUCCESS(status)) {
717 expect(fmt, (Formattable)(int64_t)0, "0E0");
718 expect(fmt, (Formattable)(int64_t)-1, "-1E0");
719 expect(fmt, (Formattable)(int64_t)1, "1E0");
720 expect(fmt, (Formattable)(int64_t)2147483647, "2.147483647E9");
721 expect(fmt, (Formattable)((int64_t)-2147483647-1), "-2.147483648E9");
722 expect(fmt, (Formattable)(int64_t)U_INT64_MAX, "9.223372036854775807E18");
723 expect(fmt, (Formattable)(int64_t)U_INT64_MIN, "-9.223372036854775808E18");
724 }
725
726 // also test digitlist
727 /* int64_t int64max = U_INT64_MAX;
728 int64_t int64min = U_INT64_MIN;
729 const char* int64maxstr = "9223372036854775807";
730 const char* int64minstr = "-9223372036854775808";
731 UnicodeString fail("fail: ");
732
733 // test max int64 value
734 DigitList dl;
735 setFromString(dl, int64maxstr);
736 {
737 if (!dl.fitsIntoInt64(FALSE)) {
738 errln(fail + int64maxstr + " didn't fit");
739 }
740 int64_t int64Value = dl.getInt64();
741 if (int64Value != int64max) {
742 errln(fail + int64maxstr);
743 }
744 dl.set(int64Value);
745 int64Value = dl.getInt64();
746 if (int64Value != int64max) {
747 errln(fail + int64maxstr);
748 }
749 }
750 // test negative of max int64 value (1 shy of min int64 value)
751 dl.fIsPositive = FALSE;
752 {
753 if (!dl.fitsIntoInt64(FALSE)) {
754 errln(fail + "-" + int64maxstr + " didn't fit");
755 }
756 int64_t int64Value = dl.getInt64();
757 if (int64Value != -int64max) {
758 errln(fail + "-" + int64maxstr);
759 }
760 dl.set(int64Value);
761 int64Value = dl.getInt64();
762 if (int64Value != -int64max) {
763 errln(fail + "-" + int64maxstr);
764 }
765 }
766 // test min int64 value
767 setFromString(dl, int64minstr);
768 {
769 if (!dl.fitsIntoInt64(FALSE)) {
770 errln(fail + "-" + int64minstr + " didn't fit");
771 }
772 int64_t int64Value = dl.getInt64();
773 if (int64Value != int64min) {
774 errln(fail + int64minstr);
775 }
776 dl.set(int64Value);
777 int64Value = dl.getInt64();
778 if (int64Value != int64min) {
779 errln(fail + int64minstr);
780 }
781 }
782 // test negative of min int 64 value (1 more than max int64 value)
783 dl.fIsPositive = TRUE; // won't fit
784 {
785 if (dl.fitsIntoInt64(FALSE)) {
786 errln(fail + "-(" + int64minstr + ") didn't fit");
787 }
788 }*/
789 }
790
791 // -------------------------------------
792
793 // Test the handling of quotes
794 void
TestQuotes(void)795 NumberFormatTest::TestQuotes(void)
796 {
797 UErrorCode status = U_ZERO_ERROR;
798 UnicodeString *pat;
799 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), status);
800 if (U_FAILURE(status)) {
801 errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
802 delete sym;
803 return;
804 }
805 pat = new UnicodeString("a'fo''o'b#");
806 DecimalFormat *fmt = new DecimalFormat(*pat, *sym, status);
807 UnicodeString s;
808 ((NumberFormat*)fmt)->format((int32_t)123, s);
809 logln((UnicodeString)"Pattern \"" + *pat + "\"");
810 logln((UnicodeString)" Format 123 -> " + escape(s));
811 if (!(s=="afo'ob123"))
812 errln((UnicodeString)"FAIL: Expected afo'ob123");
813
814 s.truncate(0);
815 delete fmt;
816 delete pat;
817
818 pat = new UnicodeString("a''b#");
819 fmt = new DecimalFormat(*pat, *sym, status);
820 ((NumberFormat*)fmt)->format((int32_t)123, s);
821 logln((UnicodeString)"Pattern \"" + *pat + "\"");
822 logln((UnicodeString)" Format 123 -> " + escape(s));
823 if (!(s=="a'b123"))
824 errln((UnicodeString)"FAIL: Expected a'b123");
825 delete fmt;
826 delete pat;
827 delete sym;
828 }
829
830 /**
831 * Test the handling of the currency symbol in patterns.
832 */
833 void
TestCurrencySign(void)834 NumberFormatTest::TestCurrencySign(void)
835 {
836 UErrorCode status = U_ZERO_ERROR;
837 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale::getUS(), status);
838 UnicodeString pat;
839 UChar currency = 0x00A4;
840 if (U_FAILURE(status)) {
841 errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
842 delete sym;
843 return;
844 }
845 // "\xA4#,##0.00;-\xA4#,##0.00"
846 pat.append(currency).append("#,##0.00;-").
847 append(currency).append("#,##0.00");
848 DecimalFormat *fmt = new DecimalFormat(pat, *sym, status);
849 UnicodeString s; ((NumberFormat*)fmt)->format(1234.56, s);
850 pat.truncate(0);
851 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
852 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
853 if (s != "$1,234.56") dataerrln((UnicodeString)"FAIL: Expected $1,234.56");
854 s.truncate(0);
855 ((NumberFormat*)fmt)->format(- 1234.56, s);
856 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
857 if (s != "-$1,234.56") dataerrln((UnicodeString)"FAIL: Expected -$1,234.56");
858 delete fmt;
859 pat.truncate(0);
860 // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
861 pat.append(currency).append(currency).
862 append(" #,##0.00;").
863 append(currency).append(currency).
864 append(" -#,##0.00");
865 fmt = new DecimalFormat(pat, *sym, status);
866 s.truncate(0);
867 ((NumberFormat*)fmt)->format(1234.56, s);
868 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
869 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
870 if (s != "USD 1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD 1,234.56");
871 s.truncate(0);
872 ((NumberFormat*)fmt)->format(-1234.56, s);
873 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
874 if (s != "USD -1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD -1,234.56");
875 delete fmt;
876 delete sym;
877 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + u_errorName(status));
878 }
879
880 // -------------------------------------
881
toHexString(int32_t i)882 static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
883
884 UnicodeString&
escape(UnicodeString & s)885 NumberFormatTest::escape(UnicodeString& s)
886 {
887 UnicodeString buf;
888 for (int32_t i=0; i<s.length(); ++i)
889 {
890 UChar c = s[(int32_t)i];
891 if (c <= (UChar)0x7F) buf += c;
892 else {
893 buf += (UChar)0x5c; buf += (UChar)0x55;
894 buf += toHexString((c & 0xF000) >> 12);
895 buf += toHexString((c & 0x0F00) >> 8);
896 buf += toHexString((c & 0x00F0) >> 4);
897 buf += toHexString(c & 0x000F);
898 }
899 }
900 return (s = buf);
901 }
902
903
904 // -------------------------------------
905 static const char* testCases[][2]= {
906 /* locale ID */ /* expected */
907 {"ca_ES@currency=ESP", "\\u20A7\\u00A01.150" },
908 {"de_LU@currency=LUF", "1,150\\u00A0F" },
909 {"el_GR@currency=GRD", "1.150,50\\u00A0\\u0394\\u03C1\\u03C7" },
910 {"en_BE@currency=BEF", "1.150,50\\u00A0BEF" },
911 {"es_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
912 {"eu_ES@currency=ESP", "\\u20A7\\u00A01.150" },
913 {"gl_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
914 {"it_IT@currency=ITL", "ITL\\u00A01.150" },
915 {"pt_PT@currency=PTE", "1,150$50\\u00A0\\u200B"}, // per cldrbug 7670
916 {"en_US@currency=JPY", "\\u00A51,150"},
917 {"en_US@currency=jpy", "\\u00A51,150"},
918 {"en-US-u-cu-jpy", "\\u00A51,150"}
919 };
920 /**
921 * Test localized currency patterns.
922 */
923 void
TestCurrency(void)924 NumberFormatTest::TestCurrency(void)
925 {
926 UErrorCode status = U_ZERO_ERROR;
927 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
928 if (U_FAILURE(status)) {
929 dataerrln("Error calling NumberFormat::createCurrencyInstance()");
930 return;
931 }
932
933 UnicodeString s; currencyFmt->format(1.50, s);
934 logln((UnicodeString)"Un pauvre ici a..........." + s);
935 if (!(s==CharsToUnicodeString("1,50\\u00A0$\\u00A0CA")))
936 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$<nbsp>CA but got " + s);
937 delete currencyFmt;
938 s.truncate(0);
939 char loc[256]={0};
940 int len = uloc_canonicalize("de_DE@currency=DEM", loc, 256, &status);
941 (void)len; // Suppress unused variable warning.
942 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
943 currencyFmt->format(1.50, s);
944 logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
945 if (!(s==CharsToUnicodeString("1,50\\u00A0DM")))
946 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM but got " + s);
947 delete currencyFmt;
948 s.truncate(0);
949 len = uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status);
950 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
951 currencyFmt->format(1.50, s);
952 logln((UnicodeString)"Un pauvre en France a....." + s);
953 if (!(s==CharsToUnicodeString("1,50\\u00A0F")))
954 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>F");
955 delete currencyFmt;
956 if (U_FAILURE(status))
957 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
958
959 for(int i=0; i < UPRV_LENGTHOF(testCases); i++){
960 status = U_ZERO_ERROR;
961 const char *localeID = testCases[i][0];
962 UnicodeString expected(testCases[i][1], -1, US_INV);
963 expected = expected.unescape();
964 s.truncate(0);
965 char loc[256]={0};
966 uloc_canonicalize(localeID, loc, 256, &status);
967 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
968 if(U_FAILURE(status)){
969 errln("Could not create currency formatter for locale %s",localeID);
970 continue;
971 }
972 currencyFmt->format(1150.50, s);
973 if(s!=expected){
974 errln(UnicodeString("FAIL: Expected: ")+expected
975 + UnicodeString(" Got: ") + s
976 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
977 }
978 if (U_FAILURE(status)){
979 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
980 }
981 delete currencyFmt;
982 }
983 }
984
985 // -------------------------------------
986
987 /**
988 * Test the Currency object handling, new as of ICU 2.2.
989 */
TestCurrencyObject()990 void NumberFormatTest::TestCurrencyObject() {
991 UErrorCode ec = U_ZERO_ERROR;
992 NumberFormat* fmt =
993 NumberFormat::createCurrencyInstance(Locale::getUS(), ec);
994
995 if (U_FAILURE(ec)) {
996 dataerrln("FAIL: getCurrencyInstance(US) - %s", u_errorName(ec));
997 delete fmt;
998 return;
999 }
1000
1001 Locale null("", "", "");
1002
1003 expectCurrency(*fmt, null, 1234.56, "$1,234.56");
1004
1005 expectCurrency(*fmt, Locale::getFrance(),
1006 1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro
1007
1008 expectCurrency(*fmt, Locale::getJapan(),
1009 1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
1010
1011 expectCurrency(*fmt, Locale("fr", "CH", ""),
1012 1234.56, "CHF 1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
1013
1014 expectCurrency(*fmt, Locale::getUS(),
1015 1234.56, "$1,234.56");
1016
1017 delete fmt;
1018 fmt = NumberFormat::createCurrencyInstance(Locale::getFrance(), ec);
1019
1020 if (U_FAILURE(ec)) {
1021 errln("FAIL: getCurrencyInstance(FRANCE)");
1022 delete fmt;
1023 return;
1024 }
1025
1026 expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC"));
1027
1028 expectCurrency(*fmt, Locale::getJapan(),
1029 1234.56, CharsToUnicodeString("1\\u202F235 JPY")); // Yen
1030
1031 expectCurrency(*fmt, Locale("fr", "CH", ""),
1032 1234.56, CharsToUnicodeString("1\\u202F234,56 CHF")); // no more 0.05 rounding here, see cldrbug 5548
1033
1034 expectCurrency(*fmt, Locale::getUS(),
1035 1234.56, CharsToUnicodeString("1\\u202F234,56 $US"));
1036
1037 expectCurrency(*fmt, Locale::getFrance(),
1038 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC")); // Euro
1039
1040 delete fmt;
1041 }
1042
1043 // -------------------------------------
1044
1045 /**
1046 * Do rudimentary testing of parsing.
1047 */
1048 void
TestParse(void)1049 NumberFormatTest::TestParse(void)
1050 {
1051 UErrorCode status = U_ZERO_ERROR;
1052 UnicodeString arg("0");
1053 DecimalFormat* format = new DecimalFormat("00", status);
1054 //try {
1055 Formattable n; format->parse(arg, n, status);
1056 logln((UnicodeString)"parse(" + arg + ") = " + n.getLong());
1057 if (n.getType() != Formattable::kLong ||
1058 n.getLong() != 0) errln((UnicodeString)"FAIL: Expected 0");
1059 delete format;
1060 if (U_FAILURE(status)) errcheckln(status, (UnicodeString)"FAIL: Status " + u_errorName(status));
1061 //}
1062 //catch(Exception e) {
1063 // errln((UnicodeString)"Exception caught: " + e);
1064 //}
1065 }
1066
1067 // -------------------------------------
1068
1069 static const char *lenientAffixTestCases[] = {
1070 "(1)",
1071 "( 1)",
1072 "(1 )",
1073 "( 1 )"
1074 };
1075
1076 static const char *lenientMinusTestCases[] = {
1077 "-5",
1078 "\\u22125",
1079 "\\u27965"
1080 };
1081
1082 static const char *lenientCurrencyTestCases[] = {
1083 "$1,000",
1084 "$ 1,000",
1085 "$1000",
1086 "$ 1000",
1087 "$1 000.00",
1088 "$ 1 000.00",
1089 "$ 1\\u00A0000.00",
1090 "1000.00"
1091 };
1092
1093 // changed from () to - per cldrbug 5674
1094 static const char *lenientNegativeCurrencyTestCases[] = {
1095 "-$1,000",
1096 "-$ 1,000",
1097 "-$1000",
1098 "-$ 1000",
1099 "-$1 000.00",
1100 "-$ 1 000.00",
1101 "- $ 1,000.00 ",
1102 "-$ 1\\u00A0000.00",
1103 "-1000.00"
1104 };
1105
1106 static const char *lenientPercentTestCases[] = {
1107 "25%",
1108 " 25%",
1109 " 25 %",
1110 "25 %",
1111 "25\\u00A0%",
1112 "25"
1113 };
1114
1115 static const char *lenientNegativePercentTestCases[] = {
1116 "-25%",
1117 " -25%",
1118 " - 25%",
1119 "- 25 %",
1120 " - 25 %",
1121 "-25 %",
1122 "-25\\u00A0%",
1123 "-25",
1124 "- 25"
1125 };
1126
1127 static const char *strictFailureTestCases[] = {
1128 " 1000",
1129 "10,00",
1130 "1,000,.0"
1131 };
1132
1133 /**
1134 * Test lenient parsing.
1135 */
1136 void
TestLenientParse(void)1137 NumberFormatTest::TestLenientParse(void)
1138 {
1139 UErrorCode status = U_ZERO_ERROR;
1140 DecimalFormat *format = new DecimalFormat("(#,##0)", status);
1141 Formattable n;
1142
1143 if (format == NULL || U_FAILURE(status)) {
1144 dataerrln("Unable to create DecimalFormat (#,##0) - %s", u_errorName(status));
1145 } else {
1146 format->setLenient(TRUE);
1147 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientAffixTestCases); t += 1) {
1148 UnicodeString testCase = ctou(lenientAffixTestCases[t]);
1149
1150 format->parse(testCase, n, status);
1151 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1152
1153 if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
1154 n.getLong() != 1) {
1155 dataerrln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t]
1156 + (UnicodeString) "\"; error code = " + u_errorName(status));
1157 status = U_ZERO_ERROR;
1158 }
1159 }
1160 delete format;
1161 }
1162
1163 Locale en_US("en_US");
1164 Locale sv_SE("sv_SE");
1165
1166 NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, UNUM_DECIMAL, status);
1167
1168 if (mFormat == NULL || U_FAILURE(status)) {
1169 dataerrln("Unable to create NumberFormat (sv_SE, UNUM_DECIMAL) - %s", u_errorName(status));
1170 } else {
1171 mFormat->setLenient(TRUE);
1172 for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1173 UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1174
1175 mFormat->parse(testCase, n, status);
1176 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1177
1178 if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1179 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1180 + (UnicodeString) "\"; error code = " + u_errorName(status));
1181 status = U_ZERO_ERROR;
1182 }
1183 }
1184 delete mFormat;
1185 }
1186
1187 mFormat = NumberFormat::createInstance(en_US, UNUM_DECIMAL, status);
1188
1189 if (mFormat == NULL || U_FAILURE(status)) {
1190 dataerrln("Unable to create NumberFormat (en_US, UNUM_DECIMAL) - %s", u_errorName(status));
1191 } else {
1192 mFormat->setLenient(TRUE);
1193 for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1194 UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1195
1196 mFormat->parse(testCase, n, status);
1197 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1198
1199 if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1200 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1201 + (UnicodeString) "\"; error code = " + u_errorName(status));
1202 status = U_ZERO_ERROR;
1203 }
1204 }
1205 delete mFormat;
1206 }
1207
1208 NumberFormat *cFormat = NumberFormat::createInstance(en_US, UNUM_CURRENCY, status);
1209
1210 if (cFormat == NULL || U_FAILURE(status)) {
1211 dataerrln("Unable to create NumberFormat (en_US, UNUM_CURRENCY) - %s", u_errorName(status));
1212 } else {
1213 cFormat->setLenient(TRUE);
1214 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientCurrencyTestCases); t += 1) {
1215 UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
1216
1217 cFormat->parse(testCase, n, status);
1218 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1219
1220 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1221 n.getLong() != 1000) {
1222 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t]
1223 + (UnicodeString) "\"; error code = " + u_errorName(status));
1224 status = U_ZERO_ERROR;
1225 }
1226 }
1227
1228 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativeCurrencyTestCases); t += 1) {
1229 UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
1230
1231 cFormat->parse(testCase, n, status);
1232 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1233
1234 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1235 n.getLong() != -1000) {
1236 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t]
1237 + (UnicodeString) "\"; error code = " + u_errorName(status));
1238 status = U_ZERO_ERROR;
1239 }
1240 }
1241
1242 delete cFormat;
1243 }
1244
1245 NumberFormat *pFormat = NumberFormat::createPercentInstance(en_US, status);
1246
1247 if (pFormat == NULL || U_FAILURE(status)) {
1248 dataerrln("Unable to create NumberFormat::createPercentInstance (en_US) - %s", u_errorName(status));
1249 } else {
1250 pFormat->setLenient(TRUE);
1251 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientPercentTestCases); t += 1) {
1252 UnicodeString testCase = ctou(lenientPercentTestCases[t]);
1253
1254 pFormat->parse(testCase, n, status);
1255 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1256
1257 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1258 n.getDouble() != 0.25) {
1259 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t]
1260 + (UnicodeString) "\"; error code = " + u_errorName(status)
1261 + "; got: " + n.getDouble(status));
1262 status = U_ZERO_ERROR;
1263 }
1264 }
1265
1266 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativePercentTestCases); t += 1) {
1267 UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
1268
1269 pFormat->parse(testCase, n, status);
1270 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1271
1272 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1273 n.getDouble() != -0.25) {
1274 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t]
1275 + (UnicodeString) "\"; error code = " + u_errorName(status)
1276 + "; got: " + n.getDouble(status));
1277 status = U_ZERO_ERROR;
1278 }
1279 }
1280
1281 delete pFormat;
1282 }
1283
1284 // Test cases that should fail with a strict parse and pass with a
1285 // lenient parse.
1286 NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);
1287
1288 if (nFormat == NULL || U_FAILURE(status)) {
1289 dataerrln("Unable to create NumberFormat (en_US) - %s", u_errorName(status));
1290 } else {
1291 // first, make sure that they fail with a strict parse
1292 for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1293 UnicodeString testCase = ctou(strictFailureTestCases[t]);
1294
1295 nFormat->parse(testCase, n, status);
1296 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1297
1298 if (! U_FAILURE(status)) {
1299 errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t]
1300 + (UnicodeString) "\"; error code = " + u_errorName(status));
1301 }
1302
1303 status = U_ZERO_ERROR;
1304 }
1305
1306 // then, make sure that they pass with a lenient parse
1307 nFormat->setLenient(TRUE);
1308 for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1309 UnicodeString testCase = ctou(strictFailureTestCases[t]);
1310
1311 nFormat->parse(testCase, n, status);
1312 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1313
1314 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1315 n.getLong() != 1000) {
1316 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t]
1317 + (UnicodeString) "\"; error code = " + u_errorName(status));
1318 status = U_ZERO_ERROR;
1319 }
1320 }
1321
1322 delete nFormat;
1323 }
1324 }
1325
1326 // -------------------------------------
1327
1328 /**
1329 * Test proper rounding by the format method.
1330 */
1331 void
TestRounding487(void)1332 NumberFormatTest::TestRounding487(void)
1333 {
1334 UErrorCode status = U_ZERO_ERROR;
1335 NumberFormat *nf = NumberFormat::createInstance(status);
1336 if (U_FAILURE(status)) {
1337 dataerrln("Error calling NumberFormat::createInstance()");
1338 return;
1339 }
1340
1341 roundingTest(*nf, 0.00159999, 4, "0.0016");
1342 roundingTest(*nf, 0.00995, 4, "0.01");
1343
1344 roundingTest(*nf, 12.3995, 3, "12.4");
1345
1346 roundingTest(*nf, 12.4999, 0, "12");
1347 roundingTest(*nf, - 19.5, 0, "-20");
1348 delete nf;
1349 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
1350 }
1351
1352 /**
1353 * Test the functioning of the secondary grouping value.
1354 */
TestSecondaryGrouping(void)1355 void NumberFormatTest::TestSecondaryGrouping(void) {
1356 UErrorCode status = U_ZERO_ERROR;
1357 DecimalFormatSymbols US(Locale::getUS(), status);
1358 CHECK(status, "DecimalFormatSymbols ct");
1359
1360 DecimalFormat f("#,##,###", US, status);
1361 CHECK(status, "DecimalFormat ct");
1362
1363 expect2(f, (int32_t)123456789L, "12,34,56,789");
1364 expectPat(f, "#,##,##0");
1365 f.applyPattern("#,###", status);
1366 CHECK(status, "applyPattern");
1367
1368 f.setSecondaryGroupingSize(4);
1369 expect2(f, (int32_t)123456789L, "12,3456,789");
1370 expectPat(f, "#,####,##0");
1371 NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
1372 CHECK_DATA(status, "createInstance(hi_IN)");
1373
1374 UnicodeString out;
1375 int32_t l = (int32_t)1876543210L;
1376 g->format(l, out);
1377 delete g;
1378 // expect "1,87,65,43,210", but with Hindi digits
1379 // 01234567890123
1380 UBool ok = TRUE;
1381 if (out.length() != 14) {
1382 ok = FALSE;
1383 } else {
1384 for (int32_t i=0; i<out.length(); ++i) {
1385 UBool expectGroup = FALSE;
1386 switch (i) {
1387 case 1:
1388 case 4:
1389 case 7:
1390 case 10:
1391 expectGroup = TRUE;
1392 break;
1393 }
1394 // Later -- fix this to get the actual grouping
1395 // character from the resource bundle.
1396 UBool isGroup = (out.charAt(i) == 0x002C);
1397 if (isGroup != expectGroup) {
1398 ok = FALSE;
1399 break;
1400 }
1401 }
1402 }
1403 if (!ok) {
1404 errln((UnicodeString)"FAIL Expected " + l +
1405 " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
1406 escape(out) + "\"");
1407 } else {
1408 logln((UnicodeString)"Ok " + l +
1409 " x hi_IN -> \"" +
1410 escape(out) + "\"");
1411 }
1412 }
1413
TestWhiteSpaceParsing(void)1414 void NumberFormatTest::TestWhiteSpaceParsing(void) {
1415 UErrorCode ec = U_ZERO_ERROR;
1416 DecimalFormatSymbols US(Locale::getUS(), ec);
1417 DecimalFormat fmt("a b#0c ", US, ec);
1418 if (U_FAILURE(ec)) {
1419 errcheckln(ec, "FAIL: Constructor - %s", u_errorName(ec));
1420 return;
1421 }
1422 // From ICU 62, flexible whitespace needs lenient mode
1423 fmt.setLenient(TRUE);
1424 int32_t n = 1234;
1425 expect(fmt, "a b1234c ", n);
1426 expect(fmt, "a b1234c ", n);
1427 }
1428
1429 /**
1430 * Test currencies whose display name is a ChoiceFormat.
1431 */
TestComplexCurrency()1432 void NumberFormatTest::TestComplexCurrency() {
1433
1434 // UErrorCode ec = U_ZERO_ERROR;
1435 // Locale loc("kn", "IN", "");
1436 // NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
1437 // if (U_SUCCESS(ec)) {
1438 // expect2(*fmt, 1.0, CharsToUnicodeString("Re.\\u00A01.00"));
1439 // Use .00392625 because that's 2^-8. Any value less than 0.005 is fine.
1440 // expect(*fmt, 1.00390625, CharsToUnicodeString("Re.\\u00A01.00")); // tricky
1441 // expect2(*fmt, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
1442 // expect2(*fmt, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
1443 // expect2(*fmt, -1.0, CharsToUnicodeString("-Re.\\u00A01.00"));
1444 // expect2(*fmt, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
1445 // } else {
1446 // errln("FAIL: getCurrencyInstance(kn_IN)");
1447 // }
1448 // delete fmt;
1449
1450 }
1451
1452 // -------------------------------------
1453
1454 void
roundingTest(NumberFormat & nf,double x,int32_t maxFractionDigits,const char * expected)1455 NumberFormatTest::roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)
1456 {
1457 nf.setMaximumFractionDigits(maxFractionDigits);
1458 UnicodeString out; nf.format(x, out);
1459 logln((UnicodeString)"" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
1460 if (!(out==expected)) errln((UnicodeString)"FAIL: Expected " + expected);
1461 }
1462
1463 /**
1464 * Upgrade to alphaWorks
1465 */
TestExponent(void)1466 void NumberFormatTest::TestExponent(void) {
1467 UErrorCode status = U_ZERO_ERROR;
1468 DecimalFormatSymbols US(Locale::getUS(), status);
1469 CHECK(status, "DecimalFormatSymbols constructor");
1470 DecimalFormat fmt1(UnicodeString("0.###E0"), US, status);
1471 CHECK(status, "DecimalFormat(0.###E0)");
1472 DecimalFormat fmt2(UnicodeString("0.###E+0"), US, status);
1473 CHECK(status, "DecimalFormat(0.###E+0)");
1474 int32_t n = 1234;
1475 expect2(fmt1, n, "1.234E3");
1476 expect2(fmt2, n, "1.234E+3");
1477 expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
1478 }
1479
1480 /**
1481 * Upgrade to alphaWorks
1482 */
TestScientific(void)1483 void NumberFormatTest::TestScientific(void) {
1484 UErrorCode status = U_ZERO_ERROR;
1485 DecimalFormatSymbols US(Locale::getUS(), status);
1486 CHECK(status, "DecimalFormatSymbols constructor");
1487
1488 // Test pattern round-trip
1489 const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
1490 "0.###E0;[0.###E0]" };
1491 int32_t PAT_length = UPRV_LENGTHOF(PAT);
1492 int32_t DIGITS[] = {
1493 // min int, max int, min frac, max frac
1494 1, 1, 0, 0, // "#E0"
1495 1, 1, 0, 4, // "0.####E0"
1496 2, 2, 3, 3, // "00.000E00"
1497 1, 3, 0, 4, // "##0.####E000"
1498 1, 1, 0, 3, // "0.###E0;[0.###E0]"
1499 };
1500 for (int32_t i=0; i<PAT_length; ++i) {
1501 UnicodeString pat(PAT[i]);
1502 DecimalFormat df(pat, US, status);
1503 CHECK(status, "DecimalFormat constructor");
1504 UnicodeString pat2;
1505 df.toPattern(pat2);
1506 if (pat == pat2) {
1507 logln(UnicodeString("Ok Pattern rt \"") +
1508 pat + "\" -> \"" +
1509 pat2 + "\"");
1510 } else {
1511 errln(UnicodeString("FAIL Pattern rt \"") +
1512 pat + "\" -> \"" +
1513 pat2 + "\"");
1514 }
1515 // Make sure digit counts match what we expect
1516 if (df.getMinimumIntegerDigits() != DIGITS[4*i] ||
1517 df.getMaximumIntegerDigits() != DIGITS[4*i+1] ||
1518 df.getMinimumFractionDigits() != DIGITS[4*i+2] ||
1519 df.getMaximumFractionDigits() != DIGITS[4*i+3]) {
1520 errln(UnicodeString("FAIL \"" + pat +
1521 "\" min/max int; min/max frac = ") +
1522 df.getMinimumIntegerDigits() + "/" +
1523 df.getMaximumIntegerDigits() + ";" +
1524 df.getMinimumFractionDigits() + "/" +
1525 df.getMaximumFractionDigits() + ", expect " +
1526 DIGITS[4*i] + "/" +
1527 DIGITS[4*i+1] + ";" +
1528 DIGITS[4*i+2] + "/" +
1529 DIGITS[4*i+3]);
1530 }
1531 }
1532
1533
1534 // Test the constructor for default locale. We have to
1535 // manually set the default locale, as there is no
1536 // guarantee that the default locale has the same
1537 // scientific format.
1538 Locale def = Locale::getDefault();
1539 Locale::setDefault(Locale::getUS(), status);
1540 expect2(NumberFormat::createScientificInstance(status),
1541 12345.678901,
1542 "1.2345678901E4", status);
1543 Locale::setDefault(def, status);
1544
1545 expect2(new DecimalFormat("#E0", US, status),
1546 12345.0,
1547 "1.2345E4", status);
1548 expect(new DecimalFormat("0E0", US, status),
1549 12345.0,
1550 "1E4", status);
1551 expect2(NumberFormat::createScientificInstance(Locale::getUS(), status),
1552 12345.678901,
1553 "1.2345678901E4", status);
1554 expect(new DecimalFormat("##0.###E0", US, status),
1555 12345.0,
1556 "12.34E3", status);
1557 expect(new DecimalFormat("##0.###E0", US, status),
1558 12345.00001,
1559 "12.35E3", status);
1560 expect2(new DecimalFormat("##0.####E0", US, status),
1561 (int32_t) 12345,
1562 "12.345E3", status);
1563 expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status),
1564 12345.678901,
1565 "1,2345678901E4", status);
1566 expect(new DecimalFormat("##0.####E0", US, status),
1567 789.12345e-9,
1568 "789.12E-9", status);
1569 expect2(new DecimalFormat("##0.####E0", US, status),
1570 780.e-9,
1571 "780E-9", status);
1572 expect(new DecimalFormat(".###E0", US, status),
1573 45678.0,
1574 ".457E5", status);
1575 expect2(new DecimalFormat(".###E0", US, status),
1576 (int32_t) 0,
1577 ".0E0", status);
1578 /*
1579 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
1580 new DecimalFormat("##E0", US),
1581 new DecimalFormat("####E0", US),
1582 new DecimalFormat("0E0", US),
1583 new DecimalFormat("00E0", US),
1584 new DecimalFormat("000E0", US),
1585 },
1586 new Long(45678000),
1587 new String[] { "4.5678E7",
1588 "45.678E6",
1589 "4567.8E4",
1590 "5E7",
1591 "46E6",
1592 "457E5",
1593 }
1594 );
1595 !
1596 ! Unroll this test into individual tests below...
1597 !
1598 */
1599 expect2(new DecimalFormat("#E0", US, status),
1600 (int32_t) 45678000, "4.5678E7", status);
1601 expect2(new DecimalFormat("##E0", US, status),
1602 (int32_t) 45678000, "45.678E6", status);
1603 expect2(new DecimalFormat("####E0", US, status),
1604 (int32_t) 45678000, "4567.8E4", status);
1605 expect(new DecimalFormat("0E0", US, status),
1606 (int32_t) 45678000, "5E7", status);
1607 expect(new DecimalFormat("00E0", US, status),
1608 (int32_t) 45678000, "46E6", status);
1609 expect(new DecimalFormat("000E0", US, status),
1610 (int32_t) 45678000, "457E5", status);
1611 /*
1612 expect(new DecimalFormat("###E0", US, status),
1613 new Object[] { new Double(0.0000123), "12.3E-6",
1614 new Double(0.000123), "123E-6",
1615 new Double(0.00123), "1.23E-3",
1616 new Double(0.0123), "12.3E-3",
1617 new Double(0.123), "123E-3",
1618 new Double(1.23), "1.23E0",
1619 new Double(12.3), "12.3E0",
1620 new Double(123), "123E0",
1621 new Double(1230), "1.23E3",
1622 });
1623 !
1624 ! Unroll this test into individual tests below...
1625 !
1626 */
1627 expect2(new DecimalFormat("###E0", US, status),
1628 0.0000123, "12.3E-6", status);
1629 expect2(new DecimalFormat("###E0", US, status),
1630 0.000123, "123E-6", status);
1631 expect2(new DecimalFormat("###E0", US, status),
1632 0.00123, "1.23E-3", status);
1633 expect2(new DecimalFormat("###E0", US, status),
1634 0.0123, "12.3E-3", status);
1635 expect2(new DecimalFormat("###E0", US, status),
1636 0.123, "123E-3", status);
1637 expect2(new DecimalFormat("###E0", US, status),
1638 1.23, "1.23E0", status);
1639 expect2(new DecimalFormat("###E0", US, status),
1640 12.3, "12.3E0", status);
1641 expect2(new DecimalFormat("###E0", US, status),
1642 123.0, "123E0", status);
1643 expect2(new DecimalFormat("###E0", US, status),
1644 1230.0, "1.23E3", status);
1645 /*
1646 expect(new DecimalFormat("0.#E+00", US, status),
1647 new Object[] { new Double(0.00012), "1.2E-04",
1648 new Long(12000), "1.2E+04",
1649 });
1650 !
1651 ! Unroll this test into individual tests below...
1652 !
1653 */
1654 expect2(new DecimalFormat("0.#E+00", US, status),
1655 0.00012, "1.2E-04", status);
1656 expect2(new DecimalFormat("0.#E+00", US, status),
1657 (int32_t) 12000, "1.2E+04", status);
1658 }
1659
1660 /**
1661 * Upgrade to alphaWorks
1662 */
TestPad(void)1663 void NumberFormatTest::TestPad(void) {
1664 UErrorCode status = U_ZERO_ERROR;
1665 DecimalFormatSymbols US(Locale::getUS(), status);
1666 CHECK(status, "DecimalFormatSymbols constructor");
1667
1668 expect2(new DecimalFormat("*^##.##", US, status),
1669 int32_t(0), "^^^^0", status);
1670 expect2(new DecimalFormat("*^##.##", US, status),
1671 -1.3, "^-1.3", status);
1672 expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1673 int32_t(0), "0.0E0______ g-m/s^2", status);
1674 expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1675 1.0/3, "333.333E-3_ g-m/s^2", status);
1676 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1677 int32_t(0), "0.0______ g-m/s^2", status);
1678 expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1679 1.0/3, "0.33333__ g-m/s^2", status);
1680
1681 // Test padding before a sign
1682 const char *formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1683 expect2(new DecimalFormat(formatStr, US, status),
1684 int32_t(-10), "xxxxxxxxxx(10.0)", status);
1685 expect2(new DecimalFormat(formatStr, US, status),
1686 int32_t(-1000),"xxxxxxx(1,000.0)", status);
1687 expect2(new DecimalFormat(formatStr, US, status),
1688 int32_t(-1000000),"xxx(1,000,000.0)", status);
1689 expect2(new DecimalFormat(formatStr, US, status),
1690 -100.37, "xxxxxxxx(100.37)", status);
1691 expect2(new DecimalFormat(formatStr, US, status),
1692 -10456.37, "xxxxx(10,456.37)", status);
1693 expect2(new DecimalFormat(formatStr, US, status),
1694 -1120456.37, "xx(1,120,456.37)", status);
1695 expect2(new DecimalFormat(formatStr, US, status),
1696 -112045600.37, "(112,045,600.37)", status);
1697 expect2(new DecimalFormat(formatStr, US, status),
1698 -1252045600.37,"(1,252,045,600.37)", status);
1699
1700 expect2(new DecimalFormat(formatStr, US, status),
1701 int32_t(10), "xxxxxxxxxxxx10.0", status);
1702 expect2(new DecimalFormat(formatStr, US, status),
1703 int32_t(1000),"xxxxxxxxx1,000.0", status);
1704 expect2(new DecimalFormat(formatStr, US, status),
1705 int32_t(1000000),"xxxxx1,000,000.0", status);
1706 expect2(new DecimalFormat(formatStr, US, status),
1707 100.37, "xxxxxxxxxx100.37", status);
1708 expect2(new DecimalFormat(formatStr, US, status),
1709 10456.37, "xxxxxxx10,456.37", status);
1710 expect2(new DecimalFormat(formatStr, US, status),
1711 1120456.37, "xxxx1,120,456.37", status);
1712 expect2(new DecimalFormat(formatStr, US, status),
1713 112045600.37, "xx112,045,600.37", status);
1714 expect2(new DecimalFormat(formatStr, US, status),
1715 10252045600.37,"10,252,045,600.37", status);
1716
1717
1718 // Test padding between a sign and a number
1719 const char *formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1720 expect2(new DecimalFormat(formatStr2, US, status),
1721 int32_t(-10), "(10.0xxxxxxxxxx)", status);
1722 expect2(new DecimalFormat(formatStr2, US, status),
1723 int32_t(-1000),"(1,000.0xxxxxxx)", status);
1724 expect2(new DecimalFormat(formatStr2, US, status),
1725 int32_t(-1000000),"(1,000,000.0xxx)", status);
1726 expect2(new DecimalFormat(formatStr2, US, status),
1727 -100.37, "(100.37xxxxxxxx)", status);
1728 expect2(new DecimalFormat(formatStr2, US, status),
1729 -10456.37, "(10,456.37xxxxx)", status);
1730 expect2(new DecimalFormat(formatStr2, US, status),
1731 -1120456.37, "(1,120,456.37xx)", status);
1732 expect2(new DecimalFormat(formatStr2, US, status),
1733 -112045600.37, "(112,045,600.37)", status);
1734 expect2(new DecimalFormat(formatStr2, US, status),
1735 -1252045600.37,"(1,252,045,600.37)", status);
1736
1737 expect2(new DecimalFormat(formatStr2, US, status),
1738 int32_t(10), "10.0xxxxxxxxxxxx", status);
1739 expect2(new DecimalFormat(formatStr2, US, status),
1740 int32_t(1000),"1,000.0xxxxxxxxx", status);
1741 expect2(new DecimalFormat(formatStr2, US, status),
1742 int32_t(1000000),"1,000,000.0xxxxx", status);
1743 expect2(new DecimalFormat(formatStr2, US, status),
1744 100.37, "100.37xxxxxxxxxx", status);
1745 expect2(new DecimalFormat(formatStr2, US, status),
1746 10456.37, "10,456.37xxxxxxx", status);
1747 expect2(new DecimalFormat(formatStr2, US, status),
1748 1120456.37, "1,120,456.37xxxx", status);
1749 expect2(new DecimalFormat(formatStr2, US, status),
1750 112045600.37, "112,045,600.37xx", status);
1751 expect2(new DecimalFormat(formatStr2, US, status),
1752 10252045600.37,"10,252,045,600.37", status);
1753
1754 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1755 DecimalFormat fmt("#", US, status);
1756 CHECK(status, "DecimalFormat constructor");
1757 UnicodeString padString("P");
1758 fmt.setPadCharacter(padString);
1759 expectPad(fmt, "*P##.##", DecimalFormat::kPadBeforePrefix, 5, padString);
1760 fmt.setPadCharacter((UnicodeString)"^");
1761 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, (UnicodeString)"^");
1762 //commented untill implementation is complete
1763 /* fmt.setPadCharacter((UnicodeString)"^^^");
1764 expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1765 padString.remove();
1766 padString.append((UChar)0x0061);
1767 padString.append((UChar)0x0302);
1768 fmt.setPadCharacter(padString);
1769 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1770 UnicodeString pattern(patternChars);
1771 expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1772 */
1773
1774 }
1775
1776 /**
1777 * Upgrade to alphaWorks
1778 */
TestPatterns2(void)1779 void NumberFormatTest::TestPatterns2(void) {
1780 UErrorCode status = U_ZERO_ERROR;
1781 DecimalFormatSymbols US(Locale::getUS(), status);
1782 CHECK(status, "DecimalFormatSymbols constructor");
1783
1784 DecimalFormat fmt("#", US, status);
1785 CHECK(status, "DecimalFormat constructor");
1786
1787 UChar hat = 0x005E; /*^*/
1788
1789 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, hat);
1790 expectPad(fmt, "$*^#", DecimalFormat::kPadAfterPrefix, 2, hat);
1791 expectPad(fmt, "#*^", DecimalFormat::kPadBeforeSuffix, 1, hat);
1792 expectPad(fmt, "#$*^", DecimalFormat::kPadAfterSuffix, 2, hat);
1793 expectPad(fmt, "$*^$#", ILLEGAL);
1794 expectPad(fmt, "#$*^$", ILLEGAL);
1795 expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix,
1796 12, (UChar)0x0078 /*x*/);
1797 expectPad(fmt, "''#0*x", DecimalFormat::kPadBeforeSuffix,
1798 3, (UChar)0x0078 /*x*/);
1799 expectPad(fmt, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix,
1800 10, (UChar)0x0061 /*a*/);
1801
1802 fmt.applyPattern("AA#,##0.00ZZ", status);
1803 CHECK(status, "applyPattern");
1804 fmt.setPadCharacter(hat);
1805
1806 fmt.setFormatWidth(10);
1807
1808 fmt.setPadPosition(DecimalFormat::kPadBeforePrefix);
1809 expectPat(fmt, "*^AA#,##0.00ZZ");
1810
1811 fmt.setPadPosition(DecimalFormat::kPadBeforeSuffix);
1812 expectPat(fmt, "AA#,##0.00*^ZZ");
1813
1814 fmt.setPadPosition(DecimalFormat::kPadAfterSuffix);
1815 expectPat(fmt, "AA#,##0.00ZZ*^");
1816
1817 // 12 3456789012
1818 UnicodeString exp("AA*^#,##0.00ZZ", "");
1819 fmt.setFormatWidth(12);
1820 fmt.setPadPosition(DecimalFormat::kPadAfterPrefix);
1821 expectPat(fmt, exp);
1822
1823 fmt.setFormatWidth(13);
1824 // 12 34567890123
1825 expectPat(fmt, "AA*^##,##0.00ZZ");
1826
1827 fmt.setFormatWidth(14);
1828 // 12 345678901234
1829 expectPat(fmt, "AA*^###,##0.00ZZ");
1830
1831 fmt.setFormatWidth(15);
1832 // 12 3456789012345
1833 expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1834
1835 fmt.setFormatWidth(16);
1836 // 12 34567890123456
1837 expectPat(fmt, "AA*^#####,##0.00ZZ");
1838 }
1839
TestSurrogateSupport(void)1840 void NumberFormatTest::TestSurrogateSupport(void) {
1841 UErrorCode status = U_ZERO_ERROR;
1842 DecimalFormatSymbols custom(Locale::getUS(), status);
1843 CHECK(status, "DecimalFormatSymbols constructor");
1844
1845 custom.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, "decimal");
1846 custom.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, "plus");
1847 custom.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, " minus ");
1848 custom.setSymbol(DecimalFormatSymbols::kExponentialSymbol, "exponent");
1849
1850 UnicodeString patternStr("*\\U00010000##.##", "");
1851 patternStr = patternStr.unescape();
1852 UnicodeString expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1853 expStr = expStr.unescape();
1854 expect2(new DecimalFormat(patternStr, custom, status),
1855 int32_t(0), expStr, status);
1856
1857 status = U_ZERO_ERROR;
1858 expect2(new DecimalFormat("*^##.##", custom, status),
1859 int32_t(0), "^^^^0", status);
1860 status = U_ZERO_ERROR;
1861 expect2(new DecimalFormat("##.##", custom, status),
1862 -1.3, " minus 1decimal3", status);
1863 status = U_ZERO_ERROR;
1864 expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1865 int32_t(0), "0decimal0exponent0 g-m/s^2", status);
1866 status = U_ZERO_ERROR;
1867 expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1868 1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
1869 status = U_ZERO_ERROR;
1870 expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1871 int32_t(0), "0decimal0 g-m/s^2", status);
1872 status = U_ZERO_ERROR;
1873 expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1874 1.0/3, "0decimal33333 g-m/s^2", status);
1875
1876 UnicodeString zero((UChar32)0x10000);
1877 UnicodeString one((UChar32)0x10001);
1878 UnicodeString two((UChar32)0x10002);
1879 UnicodeString five((UChar32)0x10005);
1880 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
1881 custom.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, one);
1882 custom.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, two);
1883 custom.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, five);
1884 expStr = UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1885 expStr = expStr.unescape();
1886 status = U_ZERO_ERROR;
1887 expect2(new DecimalFormat("##0.000", custom, status),
1888 1.25, expStr, status);
1889
1890 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
1891 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
1892 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
1893 patternStr = UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
1894 patternStr = patternStr.unescape();
1895 expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1896 status = U_ZERO_ERROR;
1897 expect2(new DecimalFormat(patternStr, custom, status),
1898 int32_t(-20), expStr, status);
1899
1900 custom.setSymbol(DecimalFormatSymbols::kPercentSymbol, "percent");
1901 patternStr = "'You''ve lost ' -0.00 %' of your money today'";
1902 patternStr = patternStr.unescape();
1903 expStr = UnicodeString(" minus You've lost minus 2000decimal00 percent of your money today", "");
1904 status = U_ZERO_ERROR;
1905 expect2(new DecimalFormat(patternStr, custom, status),
1906 int32_t(-20), expStr, status);
1907 }
1908
TestCurrencyPatterns(void)1909 void NumberFormatTest::TestCurrencyPatterns(void) {
1910 int32_t i, locCount;
1911 const Locale* locs = NumberFormat::getAvailableLocales(locCount);
1912 for (i=0; i<locCount; ++i) {
1913 UErrorCode ec = U_ZERO_ERROR;
1914 NumberFormat* nf = NumberFormat::createCurrencyInstance(locs[i], ec);
1915 if (U_FAILURE(ec)) {
1916 errln("FAIL: Can't create NumberFormat(%s) - %s", locs[i].getName(), u_errorName(ec));
1917 } else {
1918 // Make sure currency formats do not have a variable number
1919 // of fraction digits
1920 int32_t min = nf->getMinimumFractionDigits();
1921 int32_t max = nf->getMaximumFractionDigits();
1922 if (min != max) {
1923 UnicodeString a, b;
1924 nf->format(1.0, a);
1925 nf->format(1.125, b);
1926 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1927 " min fraction digits != max fraction digits; "
1928 "x 1.0 => " + escape(a) +
1929 "; x 1.125 => " + escape(b));
1930 }
1931
1932 // Make sure EURO currency formats have exactly 2 fraction digits
1933 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
1934 if (df != NULL) {
1935 if (u_strcmp(EUR, df->getCurrency()) == 0) {
1936 if (min != 2 || max != 2) {
1937 UnicodeString a;
1938 nf->format(1.0, a);
1939 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1940 " is a EURO format but it does not have 2 fraction digits; "
1941 "x 1.0 => " +
1942 escape(a));
1943 }
1944 }
1945 }
1946 }
1947 delete nf;
1948 }
1949 }
1950
TestRegCurrency(void)1951 void NumberFormatTest::TestRegCurrency(void) {
1952 #if !UCONFIG_NO_SERVICE
1953 UErrorCode status = U_ZERO_ERROR;
1954 UChar USD[4];
1955 ucurr_forLocale("en_US", USD, 4, &status);
1956 UChar YEN[4];
1957 ucurr_forLocale("ja_JP", YEN, 4, &status);
1958 UChar TMP[4];
1959
1960 if(U_FAILURE(status)) {
1961 errcheckln(status, "Unable to get currency for locale, error %s", u_errorName(status));
1962 return;
1963 }
1964
1965 UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
1966
1967 ucurr_forLocale("en_US", TMP, 4, &status);
1968 if (u_strcmp(YEN, TMP) != 0) {
1969 errln("FAIL: didn't return YEN registered for en_US");
1970 }
1971
1972 int32_t fallbackLen = ucurr_forLocale("en_XX_BAR", TMP, 4, &status);
1973 if (fallbackLen) {
1974 errln("FAIL: tried to fallback en_XX_BAR");
1975 }
1976 status = U_ZERO_ERROR; // reset
1977
1978 if (!ucurr_unregister(enkey, &status)) {
1979 errln("FAIL: couldn't unregister enkey");
1980 }
1981
1982 ucurr_forLocale("en_US", TMP, 4, &status);
1983 if (u_strcmp(USD, TMP) != 0) {
1984 errln("FAIL: didn't return USD for en_US after unregister of en_US");
1985 }
1986 status = U_ZERO_ERROR; // reset
1987
1988 ucurr_forLocale("en_US_BLAH", TMP, 4, &status);
1989 if (u_strcmp(USD, TMP) != 0) {
1990 errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1991 }
1992 status = U_ZERO_ERROR; // reset
1993 #endif
1994 }
1995
TestCurrencyNames(void)1996 void NumberFormatTest::TestCurrencyNames(void) {
1997 // Do a basic check of getName()
1998 // USD { "US$", "US Dollar" } // 04/04/1792-
1999 UErrorCode ec = U_ZERO_ERROR;
2000 static const UChar USD[] = {0x55, 0x53, 0x44, 0}; /*USD*/
2001 static const UChar USX[] = {0x55, 0x53, 0x58, 0}; /*USX*/
2002 static const UChar CAD[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
2003 static const UChar ITL[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
2004 UBool isChoiceFormat;
2005 int32_t len;
2006 const UBool possibleDataError = TRUE;
2007 // Warning: HARD-CODED LOCALE DATA in this test. If it fails, CHECK
2008 // THE LOCALE DATA before diving into the code.
2009 assertEquals("USD.getName(SYMBOL_NAME, en)",
2010 UnicodeString("$"),
2011 UnicodeString(ucurr_getName(USD, "en",
2012 UCURR_SYMBOL_NAME,
2013 &isChoiceFormat, &len, &ec)),
2014 possibleDataError);
2015 assertEquals("USD.getName(NARROW_SYMBOL_NAME, en)",
2016 UnicodeString("$"),
2017 UnicodeString(ucurr_getName(USD, "en",
2018 UCURR_NARROW_SYMBOL_NAME,
2019 &isChoiceFormat, &len, &ec)),
2020 possibleDataError);
2021 assertEquals("USD.getName(LONG_NAME, en)",
2022 UnicodeString("US Dollar"),
2023 UnicodeString(ucurr_getName(USD, "en",
2024 UCURR_LONG_NAME,
2025 &isChoiceFormat, &len, &ec)),
2026 possibleDataError);
2027 assertEquals("CAD.getName(SYMBOL_NAME, en)",
2028 UnicodeString("CA$"),
2029 UnicodeString(ucurr_getName(CAD, "en",
2030 UCURR_SYMBOL_NAME,
2031 &isChoiceFormat, &len, &ec)),
2032 possibleDataError);
2033 assertEquals("CAD.getName(NARROW_SYMBOL_NAME, en)",
2034 UnicodeString("$"),
2035 UnicodeString(ucurr_getName(CAD, "en",
2036 UCURR_NARROW_SYMBOL_NAME,
2037 &isChoiceFormat, &len, &ec)),
2038 possibleDataError);
2039 assertEquals("CAD.getName(SYMBOL_NAME, en_CA)",
2040 UnicodeString("$"),
2041 UnicodeString(ucurr_getName(CAD, "en_CA",
2042 UCURR_SYMBOL_NAME,
2043 &isChoiceFormat, &len, &ec)),
2044 possibleDataError);
2045 assertEquals("USD.getName(SYMBOL_NAME, en_CA)",
2046 UnicodeString("US$"),
2047 UnicodeString(ucurr_getName(USD, "en_CA",
2048 UCURR_SYMBOL_NAME,
2049 &isChoiceFormat, &len, &ec)),
2050 possibleDataError);
2051 assertEquals("USD.getName(NARROW_SYMBOL_NAME, en_CA)",
2052 UnicodeString("$"),
2053 UnicodeString(ucurr_getName(USD, "en_CA",
2054 UCURR_NARROW_SYMBOL_NAME,
2055 &isChoiceFormat, &len, &ec)),
2056 possibleDataError);
2057 assertEquals("USD.getName(SYMBOL_NAME) in en_NZ",
2058 UnicodeString("US$"),
2059 UnicodeString(ucurr_getName(USD, "en_NZ",
2060 UCURR_SYMBOL_NAME,
2061 &isChoiceFormat, &len, &ec)),
2062 possibleDataError);
2063 assertEquals("CAD.getName(SYMBOL_NAME)",
2064 UnicodeString("CA$"),
2065 UnicodeString(ucurr_getName(CAD, "en_NZ",
2066 UCURR_SYMBOL_NAME,
2067 &isChoiceFormat, &len, &ec)),
2068 possibleDataError);
2069 assertEquals("USX.getName(SYMBOL_NAME)",
2070 UnicodeString("USX"),
2071 UnicodeString(ucurr_getName(USX, "en_US",
2072 UCURR_SYMBOL_NAME,
2073 &isChoiceFormat, &len, &ec)),
2074 possibleDataError);
2075 assertEquals("USX.getName(NARROW_SYMBOL_NAME)",
2076 UnicodeString("USX"),
2077 UnicodeString(ucurr_getName(USX, "en_US",
2078 UCURR_NARROW_SYMBOL_NAME,
2079 &isChoiceFormat, &len, &ec)),
2080 possibleDataError);
2081 assertEquals("USX.getName(LONG_NAME)",
2082 UnicodeString("USX"),
2083 UnicodeString(ucurr_getName(USX, "en_US",
2084 UCURR_LONG_NAME,
2085 &isChoiceFormat, &len, &ec)),
2086 possibleDataError);
2087 assertSuccess("ucurr_getName", ec);
2088
2089 ec = U_ZERO_ERROR;
2090
2091 // Test that a default or fallback warning is being returned. JB 4239.
2092 ucurr_getName(CAD, "es_ES", UCURR_LONG_NAME, &isChoiceFormat,
2093 &len, &ec);
2094 assertTrue("ucurr_getName (es_ES fallback)",
2095 U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);
2096
2097 ucurr_getName(CAD, "zh_TW", UCURR_LONG_NAME, &isChoiceFormat,
2098 &len, &ec);
2099 assertTrue("ucurr_getName (zh_TW fallback)",
2100 U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);
2101
2102 ucurr_getName(CAD, "en_US", UCURR_LONG_NAME, &isChoiceFormat,
2103 &len, &ec);
2104 assertTrue("ucurr_getName (en_US default)",
2105 U_USING_DEFAULT_WARNING == ec || U_USING_FALLBACK_WARNING == ec, TRUE);
2106
2107 ucurr_getName(CAD, "ti", UCURR_LONG_NAME, &isChoiceFormat,
2108 &len, &ec);
2109 assertTrue("ucurr_getName (ti default)",
2110 U_USING_DEFAULT_WARNING == ec, TRUE);
2111
2112 // Test that a default warning is being returned when falling back to root. JB 4536.
2113 ucurr_getName(ITL, "cy", UCURR_LONG_NAME, &isChoiceFormat,
2114 &len, &ec);
2115 assertTrue("ucurr_getName (cy default to root)",
2116 U_USING_DEFAULT_WARNING == ec, TRUE);
2117
2118 // TODO add more tests later
2119 }
2120
TestCurrencyVariants()2121 void NumberFormatTest::TestCurrencyVariants(){
2122 IcuTestErrorCode status(*this, "TestCurrencyVariants");
2123
2124 struct TestCase {
2125 const char* locale;
2126 const char16_t* isoCode;
2127 const char16_t* expectedShort;
2128 const char16_t* expectedNarrow;
2129 const char16_t* expectedFormal;
2130 const char16_t* expectedVariant;
2131 UErrorCode expectedNarrowError;
2132 } cases[] = {
2133 {"en-US", u"CAD", u"CA$", u"$", u"CA$", u"CA$", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2134 {"en-US", u"CDF", u"CDF", u"CDF", u"CDF", u"CDF", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2135 {"sw-CD", u"CDF", u"FC", u"FC", u"FC", u"FC", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2136 {"en-US", u"GEL", u"GEL", u"₾", u"GEL", u"GEL", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2137 {"ka-GE", u"GEL", u"₾", u"₾", u"₾", u"₾", U_USING_FALLBACK_WARNING}, // narrow: fallback to ka
2138 {"ka", u"GEL", u"₾", u"₾", u"₾", u"₾", U_ZERO_ERROR}, // no fallback on narrow
2139 {"zh-TW", u"TWD", u"$", u"$", u"NT$", u"$", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2140 {"ccp", u"TRY", u"TRY", u"₺", u"TRY", u"TL", U_ZERO_ERROR}, // no fallback on variant
2141 };
2142 for (const auto& cas : cases) {
2143 status.setScope(cas.isoCode);
2144 UBool choiceFormatIgnored;
2145 int32_t lengthIgnored;
2146 const UChar* actualShort = ucurr_getName(
2147 cas.isoCode,
2148 cas.locale,
2149 UCURR_SYMBOL_NAME,
2150 &choiceFormatIgnored,
2151 &lengthIgnored,
2152 status);
2153 const UChar* actualFormal = ucurr_getName(
2154 cas.isoCode,
2155 cas.locale,
2156 UCURR_FORMAL_SYMBOL_NAME,
2157 &choiceFormatIgnored,
2158 &lengthIgnored,
2159 status);
2160 const UChar* actualVarant = ucurr_getName(
2161 cas.isoCode,
2162 cas.locale,
2163 UCURR_VARIANT_SYMBOL_NAME,
2164 &choiceFormatIgnored,
2165 &lengthIgnored,
2166 status);
2167 status.errIfFailureAndReset();
2168 const UChar* actualNarrow = ucurr_getName(
2169 cas.isoCode,
2170 cas.locale,
2171 UCURR_NARROW_SYMBOL_NAME,
2172 &choiceFormatIgnored,
2173 &lengthIgnored,
2174 status);
2175 status.expectErrorAndReset(cas.expectedNarrowError);
2176 assertEquals(UnicodeString("Short symbol: ") + cas.locale + u": " + cas.isoCode,
2177 cas.expectedShort, actualShort);
2178 assertEquals(UnicodeString("Narrow symbol: ") + cas.locale + u": " + cas.isoCode,
2179 cas.expectedNarrow, actualNarrow);
2180 assertEquals(UnicodeString("Formal symbol: ") + cas.locale + u": " + cas.isoCode,
2181 cas.expectedFormal, actualFormal);
2182 assertEquals(UnicodeString("Variant symbol: ") + cas.locale + u": " + cas.isoCode,
2183 cas.expectedVariant, actualVarant);
2184 }
2185 }
2186
TestCurrencyUnit(void)2187 void NumberFormatTest::TestCurrencyUnit(void){
2188 UErrorCode ec = U_ZERO_ERROR;
2189 static const UChar USD[] = u"USD";
2190 static const char USD8[] = "USD";
2191 static const UChar BAD[] = u"???";
2192 static const UChar BAD2[] = u"??A";
2193 static const UChar XXX[] = u"XXX";
2194 static const char XXX8[] = "XXX";
2195 static const UChar XYZ[] = u"XYZ";
2196 static const char XYZ8[] = "XYZ";
2197 static const UChar INV[] = u"{$%";
2198 static const char INV8[] = "{$%";
2199 static const UChar ZZZ[] = u"zz";
2200 static const char ZZZ8[] = "zz";
2201 static const UChar JPY[] = u"JPY";
2202 static const char JPY8[] = "JPY";
2203 static const UChar jpy[] = u"jpy";
2204 static const char jpy8[] = "jpy";
2205
2206 UChar* EUR = (UChar*) malloc(6);
2207 EUR[0] = u'E';
2208 EUR[1] = u'U';
2209 EUR[2] = u'R';
2210 char* EUR8 = (char*) malloc(3);
2211 EUR8[0] = 'E';
2212 EUR8[1] = 'U';
2213 EUR8[2] = 'R';
2214
2215 CurrencyUnit cu(USD, ec);
2216 assertSuccess("CurrencyUnit", ec);
2217 assertEquals("getISOCurrency()", USD, cu.getISOCurrency());
2218 assertEquals("getSubtype()", USD8, cu.getSubtype());
2219
2220 // Test XYZ, a valid but non-standard currency.
2221 // Note: Country code XY is private-use, so XYZ should remain unallocated.
2222 CurrencyUnit extended(XYZ, ec);
2223 assertSuccess("non-standard", ec);
2224 assertEquals("non-standard", XYZ, extended.getISOCurrency());
2225 assertEquals("non-standard", XYZ8, extended.getSubtype());
2226
2227 CurrencyUnit inv(INV, ec);
2228 assertEquals("non-invariant", U_INVARIANT_CONVERSION_ERROR, ec);
2229 assertEquals("non-invariant", XXX, inv.getISOCurrency());
2230 ec = U_ZERO_ERROR;
2231
2232 CurrencyUnit zzz(ZZZ, ec);
2233 assertEquals("too short", U_ILLEGAL_ARGUMENT_ERROR, ec);
2234 assertEquals("too short", XXX, zzz.getISOCurrency());
2235 ec = U_ZERO_ERROR;
2236
2237 CurrencyUnit eur(EUR, ec);
2238 assertEquals("non-nul-terminated", u"EUR", eur.getISOCurrency());
2239 assertEquals("non-nul-terminated", "EUR", eur.getSubtype());
2240
2241 // Test StringPiece constructor
2242 CurrencyUnit cu8(USD8, ec);
2243 assertEquals("StringPiece constructor", USD, cu8.getISOCurrency());
2244
2245 CurrencyUnit inv8(INV8, ec);
2246 assertEquals("non-invariant 8", U_INVARIANT_CONVERSION_ERROR, ec);
2247 assertEquals("non-invariant 8", XXX, inv8.getISOCurrency());
2248 ec = U_ZERO_ERROR;
2249
2250 CurrencyUnit zzz8(ZZZ8, ec);
2251 assertEquals("too short 8", U_ILLEGAL_ARGUMENT_ERROR, ec);
2252 assertEquals("too short 8", XXX, zzz8.getISOCurrency());
2253 ec = U_ZERO_ERROR;
2254
2255 CurrencyUnit zzz8b({ZZZ8, 3}, ec);
2256 assertEquals("too short 8b", U_ILLEGAL_ARGUMENT_ERROR, ec);
2257 assertEquals("too short 8b", XXX, zzz8b.getISOCurrency());
2258 ec = U_ZERO_ERROR;
2259
2260 CurrencyUnit eur8({EUR8, 3}, ec);
2261 assertEquals("non-nul-terminated 8", u"EUR", eur8.getISOCurrency());
2262 assertEquals("non-nul-terminated 8", "EUR", eur8.getSubtype());
2263
2264 CurrencyUnit cu2(cu);
2265 if (!(cu2 == cu)){
2266 errln("CurrencyUnit copy constructed object should be same");
2267 }
2268
2269 CurrencyUnit * cu3 = cu.clone();
2270 if (!(*cu3 == cu)){
2271 errln("CurrencyUnit cloned object should be same");
2272 }
2273 CurrencyUnit bad(BAD, ec);
2274 assertSuccess("CurrencyUnit", ec);
2275 if (cu.getOffset() == bad.getOffset()) {
2276 errln("Indexes of different currencies should differ.");
2277 }
2278 CurrencyUnit bad2(BAD2, ec);
2279 assertSuccess("CurrencyUnit", ec);
2280 if (bad2.getOffset() != bad.getOffset()) {
2281 errln("Indexes of unrecognized currencies should be the same.");
2282 }
2283 if (bad == bad2) {
2284 errln("Different unrecognized currencies should not be equal.");
2285 }
2286 bad = bad2;
2287 if (bad != bad2) {
2288 errln("Currency unit assignment should be the same.");
2289 }
2290 delete cu3;
2291
2292 // Test default constructor
2293 CurrencyUnit def;
2294 assertEquals("Default currency", XXX, def.getISOCurrency());
2295 assertEquals("Default currency as subtype", XXX8, def.getSubtype());
2296
2297 // Test slicing
2298 MeasureUnit sliced1 = cu;
2299 MeasureUnit sliced2 = cu;
2300 MeasureUnit sliced3 = extended;
2301 assertEquals("Subtype after slicing 1", USD8, sliced1.getSubtype());
2302 assertEquals("Subtype after slicing 2", USD8, sliced2.getSubtype());
2303 assertEquals("Subtype after slicing 3", XYZ8, sliced3.getSubtype());
2304 CurrencyUnit restored1(sliced1, ec);
2305 CurrencyUnit restored2(sliced2, ec);
2306 CurrencyUnit restored3(sliced3, ec);
2307 assertSuccess("Restoring from MeasureUnit", ec);
2308 assertEquals("Subtype after restoring 1", USD8, restored1.getSubtype());
2309 assertEquals("Subtype after restoring 2", USD8, restored2.getSubtype());
2310 assertEquals("Subtype after restoring 3", XYZ8, restored3.getSubtype());
2311 assertEquals("ISO Code after restoring 1", USD, restored1.getISOCurrency());
2312 assertEquals("ISO Code after restoring 2", USD, restored2.getISOCurrency());
2313 assertEquals("ISO Code after restoring 3", XYZ, restored3.getISOCurrency());
2314
2315 // Test copy constructor failure
2316 LocalPointer<MeasureUnit> meter(MeasureUnit::createMeter(ec));
2317 assertSuccess("Creating meter", ec);
2318 CurrencyUnit failure(*meter, ec);
2319 assertEquals("Copying from meter should fail", ec, U_ILLEGAL_ARGUMENT_ERROR);
2320 assertEquals("Copying should not give uninitialized ISO code", u"", failure.getISOCurrency());
2321
2322 // Test equality
2323 ec = U_ZERO_ERROR;
2324 assertFalse("FAIL: USD == JPY", CurrencyUnit(USD, ec) == CurrencyUnit(JPY, ec));
2325 assertTrue("FAIL: USD != USD", CurrencyUnit(USD, ec) == CurrencyUnit(USD, ec));
2326 assertTrue("FAIL: JPY != jpy", CurrencyUnit(JPY, ec) == CurrencyUnit(jpy, ec));
2327 assertTrue("FAIL: jpy != JPY", CurrencyUnit(jpy, ec) == CurrencyUnit(JPY, ec));
2328
2329 // Test equality with system charset instances
2330 assertFalse("FAIL: USD8 == JPY8", CurrencyUnit(USD8, ec) == CurrencyUnit(JPY8, ec));
2331 assertTrue("FAIL: USD8 != USD8", CurrencyUnit(USD8, ec) == CurrencyUnit(USD8, ec));
2332 assertTrue("FAIL: JPY8 != jpy8", CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy8, ec));
2333 assertTrue("FAIL: jpy8 != JPY8", CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY8, ec));
2334
2335 // Test equality between UTF-16 and system charset instances
2336 assertTrue("FAIL: USD != USD8", CurrencyUnit(USD, ec) == CurrencyUnit(USD8, ec));
2337 assertTrue("FAIL: USD8 != USD", CurrencyUnit(USD8, ec) == CurrencyUnit(USD, ec));
2338 assertTrue("FAIL: JPY != jpy8", CurrencyUnit(JPY, ec) == CurrencyUnit(jpy8, ec));
2339 assertTrue("FAIL: JPY8 != jpy", CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy, ec));
2340 assertTrue("FAIL: jpy != JPY8", CurrencyUnit(jpy, ec) == CurrencyUnit(JPY8, ec));
2341 assertTrue("FAIL: jpy8 != JPY", CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY, ec));
2342
2343 free(EUR);
2344 free(EUR8);
2345 }
2346
TestCurrencyAmount(void)2347 void NumberFormatTest::TestCurrencyAmount(void){
2348 UErrorCode ec = U_ZERO_ERROR;
2349 static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
2350 CurrencyAmount ca(9, USD, ec);
2351 assertSuccess("CurrencyAmount", ec);
2352
2353 CurrencyAmount ca2(ca);
2354 if (!(ca2 == ca)){
2355 errln("CurrencyAmount copy constructed object should be same");
2356 }
2357
2358 ca2=ca;
2359 if (!(ca2 == ca)){
2360 errln("CurrencyAmount assigned object should be same");
2361 }
2362
2363 CurrencyAmount *ca3 = ca.clone();
2364 if (!(*ca3 == ca)){
2365 errln("CurrencyAmount cloned object should be same");
2366 }
2367 delete ca3;
2368 }
2369
TestSymbolsWithBadLocale(void)2370 void NumberFormatTest::TestSymbolsWithBadLocale(void) {
2371 Locale locDefault;
2372 static const char *badLocales[] = {
2373 // length < ULOC_FULLNAME_CAPACITY
2374 "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME",
2375
2376 // length > ULOC_FULLNAME_CAPACITY
2377 "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME"
2378 }; // expect U_USING_DEFAULT_WARNING for both
2379
2380 unsigned int i;
2381 for (i = 0; i < UPRV_LENGTHOF(badLocales); i++) {
2382 const char *localeName = badLocales[i];
2383 Locale locBad(localeName);
2384 assertTrue(WHERE, !locBad.isBogus());
2385 UErrorCode status = U_ZERO_ERROR;
2386 UnicodeString intlCurrencySymbol((UChar)0xa4);
2387
2388 intlCurrencySymbol.append((UChar)0xa4);
2389
2390 logln("Current locale is %s", Locale::getDefault().getName());
2391 Locale::setDefault(locBad, status);
2392 logln("Current locale is %s", Locale::getDefault().getName());
2393 DecimalFormatSymbols mySymbols(status);
2394 if (status != U_USING_DEFAULT_WARNING) {
2395 errln("DecimalFormatSymbols should return U_USING_DEFAULT_WARNING.");
2396 }
2397 if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
2398 errln("DecimalFormatSymbols does not have the right locale.", locBad.getName());
2399 }
2400 int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
2401 for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
2402 UnicodeString symbolString = mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum);
2403 logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ") + prettify(symbolString));
2404 if (symbolString.length() == 0
2405 && symbolEnum != (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
2406 && symbolEnum != (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol)
2407 {
2408 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
2409 }
2410 }
2411
2412 status = U_ZERO_ERROR;
2413 Locale::setDefault(locDefault, status);
2414 logln("Current locale is %s", Locale::getDefault().getName());
2415 }
2416 }
2417
2418 /**
2419 * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
2420 * behave the same, except for memory ownership semantics. (No
2421 * version of this test on Java, since Java has only one method.)
2422 */
TestAdoptDecimalFormatSymbols(void)2423 void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
2424 UErrorCode ec = U_ZERO_ERROR;
2425 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2426 if (U_FAILURE(ec)) {
2427 errcheckln(ec, "Fail: DecimalFormatSymbols constructor - %s", u_errorName(ec));
2428 delete sym;
2429 return;
2430 }
2431 UnicodeString pat(" #,##0.00");
2432 pat.insert(0, (UChar)0x00A4);
2433 DecimalFormat fmt(pat, sym, ec);
2434 if (U_FAILURE(ec)) {
2435 errln("Fail: DecimalFormat constructor");
2436 return;
2437 }
2438
2439 UnicodeString str;
2440 fmt.format(2350.75, str);
2441 if (str == "$ 2,350.75") {
2442 logln(str);
2443 } else {
2444 dataerrln("Fail: " + str + ", expected $ 2,350.75");
2445 }
2446
2447 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2448 if (U_FAILURE(ec)) {
2449 errln("Fail: DecimalFormatSymbols constructor");
2450 delete sym;
2451 return;
2452 }
2453 sym->setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2454 fmt.adoptDecimalFormatSymbols(sym);
2455
2456 str.truncate(0);
2457 fmt.format(2350.75, str);
2458 if (str == "Q 2,350.75") {
2459 logln(str);
2460 } else {
2461 dataerrln("Fail: adoptDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2462 }
2463
2464 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2465 if (U_FAILURE(ec)) {
2466 errln("Fail: DecimalFormatSymbols constructor");
2467 delete sym;
2468 return;
2469 }
2470 DecimalFormat fmt2(pat, sym, ec);
2471 if (U_FAILURE(ec)) {
2472 errln("Fail: DecimalFormat constructor");
2473 return;
2474 }
2475
2476 DecimalFormatSymbols sym2(Locale::getUS(), ec);
2477 if (U_FAILURE(ec)) {
2478 errln("Fail: DecimalFormatSymbols constructor");
2479 return;
2480 }
2481 sym2.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2482 fmt2.setDecimalFormatSymbols(sym2);
2483
2484 str.truncate(0);
2485 fmt2.format(2350.75, str);
2486 if (str == "Q 2,350.75") {
2487 logln(str);
2488 } else {
2489 dataerrln("Fail: setDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2490 }
2491 }
2492
TestPerMill()2493 void NumberFormatTest::TestPerMill() {
2494 UErrorCode ec = U_ZERO_ERROR;
2495 UnicodeString str;
2496 DecimalFormat fmt(ctou("###.###\\u2030"), ec);
2497 if (!assertSuccess("DecimalFormat ct", ec)) return;
2498 assertEquals("0.4857 x ###.###\\u2030",
2499 ctou("485.7\\u2030"), fmt.format(0.4857, str), true);
2500
2501 DecimalFormatSymbols sym(Locale::getUS(), ec);
2502 if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2503 return;
2504 }
2505 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
2506 DecimalFormat fmt2("", sym, ec);
2507 if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2508 return;
2509 }
2510 fmt2.applyLocalizedPattern("###.###m", ec);
2511 if (!assertSuccess("setup", ec)) return;
2512 str.truncate(0);
2513 assertEquals("0.4857 x ###.###m",
2514 "485.7m", fmt2.format(0.4857, str));
2515 }
2516
2517 /**
2518 * Generic test for patterns that should be legal/illegal.
2519 */
TestIllegalPatterns()2520 void NumberFormatTest::TestIllegalPatterns() {
2521 // Test cases:
2522 // Prefix with "-:" for illegal patterns
2523 // Prefix with "+:" for legal patterns
2524 const char* DATA[] = {
2525 // Unquoted special characters in the suffix are illegal
2526 "-:000.000|###",
2527 "+:000.000'|###'",
2528 0
2529 };
2530 for (int32_t i=0; DATA[i]; ++i) {
2531 const char* pat=DATA[i];
2532 UBool valid = (*pat) == '+';
2533 pat += 2;
2534 UErrorCode ec = U_ZERO_ERROR;
2535 DecimalFormat fmt(pat, ec); // locale doesn't matter here
2536 if (U_SUCCESS(ec) == valid) {
2537 logln("Ok: pattern \"%s\": %s",
2538 pat, u_errorName(ec));
2539 } else {
2540 errcheckln(ec, "FAIL: pattern \"%s\" should have %s; got %s",
2541 pat, (valid?"succeeded":"failed"),
2542 u_errorName(ec));
2543 }
2544 }
2545 }
2546
2547 //----------------------------------------------------------------------
2548
2549 static const char* KEYWORDS[] = {
2550 /*0*/ "ref=", // <reference pattern to parse numbers>
2551 /*1*/ "loc=", // <locale for formats>
2552 /*2*/ "f:", // <pattern or '-'> <number> <exp. string>
2553 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number>
2554 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string>
2555 /*5*/ "p:", // <pattern or '-'> <string> <exp. number>
2556 /*6*/ "perr:", // <pattern or '-'> <invalid string>
2557 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
2558 /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2559 0
2560 };
2561
2562 /**
2563 * Return an integer representing the next token from this
2564 * iterator. The integer will be an index into the given list, or
2565 * -1 if there are no more tokens, or -2 if the token is not on
2566 * the list.
2567 */
keywordIndex(const UnicodeString & tok)2568 static int32_t keywordIndex(const UnicodeString& tok) {
2569 for (int32_t i=0; KEYWORDS[i]!=0; ++i) {
2570 if (tok==KEYWORDS[i]) {
2571 return i;
2572 }
2573 }
2574 return -1;
2575 }
2576
2577 /**
2578 * Parse a CurrencyAmount using the given NumberFormat, with
2579 * the 'delim' character separating the number and the currency.
2580 */
parseCurrencyAmount(const UnicodeString & str,const NumberFormat & fmt,UChar delim,Formattable & result,UErrorCode & ec)2581 static void parseCurrencyAmount(const UnicodeString& str,
2582 const NumberFormat& fmt,
2583 UChar delim,
2584 Formattable& result,
2585 UErrorCode& ec) {
2586 UnicodeString num, cur;
2587 int32_t i = str.indexOf(delim);
2588 str.extractBetween(0, i, num);
2589 str.extractBetween(i+1, INT32_MAX, cur);
2590 Formattable n;
2591 fmt.parse(num, n, ec);
2592 result.adoptObject(new CurrencyAmount(n, cur.getTerminatedBuffer(), ec));
2593 }
2594
TestCases()2595 void NumberFormatTest::TestCases() {
2596 UErrorCode ec = U_ZERO_ERROR;
2597 TextFile reader("NumberFormatTestCases.txt", "UTF8", ec);
2598 if (U_FAILURE(ec)) {
2599 dataerrln("Couldn't open NumberFormatTestCases.txt");
2600 return;
2601 }
2602 TokenIterator tokens(&reader);
2603
2604 Locale loc("en", "US", "");
2605 DecimalFormat *ref = 0, *fmt = 0;
2606 MeasureFormat *mfmt = 0;
2607 UnicodeString pat, tok, mloc, str, out, where, currAmt;
2608 Formattable n;
2609
2610 for (;;) {
2611 ec = U_ZERO_ERROR;
2612 if (!tokens.next(tok, ec)) {
2613 break;
2614 }
2615 where = UnicodeString("(") + tokens.getLineNumber() + ") ";
2616 int32_t cmd = keywordIndex(tok);
2617 switch (cmd) {
2618 case 0:
2619 // ref= <reference pattern>
2620 if (!tokens.next(tok, ec)) goto error;
2621 delete ref;
2622 ref = new DecimalFormat(tok,
2623 new DecimalFormatSymbols(Locale::getUS(), ec), ec);
2624 if (U_FAILURE(ec)) {
2625 dataerrln("Error constructing DecimalFormat");
2626 goto error;
2627 }
2628 break;
2629 case 1:
2630 // loc= <locale>
2631 if (!tokens.next(tok, ec)) goto error;
2632 loc = Locale::createFromName(CharString().appendInvariantChars(tok, ec).data());
2633 break;
2634 case 2: // f:
2635 case 3: // fp:
2636 case 4: // rt:
2637 case 5: // p:
2638 if (!tokens.next(tok, ec)) goto error;
2639 if (tok != "-") {
2640 pat = tok;
2641 delete fmt;
2642 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc, ec), ec);
2643 if (U_FAILURE(ec)) {
2644 errln("FAIL: " + where + "Pattern \"" + pat + "\": " + u_errorName(ec));
2645 ec = U_ZERO_ERROR;
2646 if (!tokens.next(tok, ec)) goto error;
2647 if (!tokens.next(tok, ec)) goto error;
2648 if (cmd == 3) {
2649 if (!tokens.next(tok, ec)) goto error;
2650 }
2651 continue;
2652 }
2653 }
2654 if (cmd == 2 || cmd == 3 || cmd == 4) {
2655 // f: <pattern or '-'> <number> <exp. string>
2656 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
2657 // rt: <pattern or '-'> <number> <string>
2658 UnicodeString num;
2659 if (!tokens.next(num, ec)) goto error;
2660 if (!tokens.next(str, ec)) goto error;
2661 ref->parse(num, n, ec);
2662 assertSuccess("parse", ec);
2663 assertEquals(where + "\"" + pat + "\".format(" + num + ")",
2664 str, fmt->format(n, out.remove(), ec));
2665 assertSuccess("format", ec);
2666 if (cmd == 3) { // fp:
2667 if (!tokens.next(num, ec)) goto error;
2668 ref->parse(num, n, ec);
2669 assertSuccess("parse", ec);
2670 }
2671 if (cmd != 2) { // != f:
2672 Formattable m;
2673 fmt->parse(str, m, ec);
2674 assertSuccess("parse", ec);
2675 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2676 n, m);
2677 }
2678 }
2679 // p: <pattern or '-'> <string to parse> <exp. number>
2680 else {
2681 UnicodeString expstr;
2682 if (!tokens.next(str, ec)) goto error;
2683 if (!tokens.next(expstr, ec)) goto error;
2684 Formattable exp, n;
2685 ref->parse(expstr, exp, ec);
2686 assertSuccess("parse", ec);
2687 fmt->parse(str, n, ec);
2688 assertSuccess("parse", ec);
2689 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2690 exp, n);
2691 }
2692 break;
2693 case 8: // fpc:
2694 if (!tokens.next(tok, ec)) goto error;
2695 if (tok != "-") {
2696 mloc = tok;
2697 delete mfmt;
2698 mfmt = MeasureFormat::createCurrencyFormat(
2699 Locale::createFromName(
2700 CharString().appendInvariantChars(mloc, ec).data()), ec);
2701 if (U_FAILURE(ec)) {
2702 errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
2703 ec = U_ZERO_ERROR;
2704 if (!tokens.next(tok, ec)) goto error;
2705 if (!tokens.next(tok, ec)) goto error;
2706 if (!tokens.next(tok, ec)) goto error;
2707 continue;
2708 }
2709 } else if (mfmt == NULL) {
2710 errln("FAIL: " + where + "Loc \"" + mloc + "\": skip case using previous locale, no valid MeasureFormat");
2711 if (!tokens.next(tok, ec)) goto error;
2712 if (!tokens.next(tok, ec)) goto error;
2713 if (!tokens.next(tok, ec)) goto error;
2714 continue;
2715 }
2716 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2717 if (!tokens.next(currAmt, ec)) goto error;
2718 if (!tokens.next(str, ec)) goto error;
2719 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2720 if (assertSuccess("parseCurrencyAmount", ec)) {
2721 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
2722 str, mfmt->format(n, out.remove(), ec));
2723 assertSuccess("format", ec);
2724 }
2725 if (!tokens.next(currAmt, ec)) goto error;
2726 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2727 if (assertSuccess("parseCurrencyAmount", ec)) {
2728 Formattable m;
2729
2730 mfmt->parseObject(str, m, ec);
2731 if (assertSuccess("parseCurrency", ec)) {
2732 assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
2733 n, m);
2734 } else {
2735 errln("FAIL: source " + str);
2736 }
2737 }
2738 break;
2739 case 6:
2740 // perr: <pattern or '-'> <invalid string>
2741 errln("FAIL: Under construction");
2742 goto done;
2743 case 7: {
2744 // pat: <pattern> <exp. toPattern, or '-' or 'err'>
2745 UnicodeString testpat;
2746 UnicodeString exppat;
2747 if (!tokens.next(testpat, ec)) goto error;
2748 if (!tokens.next(exppat, ec)) goto error;
2749 UBool err = exppat == "err";
2750 UBool existingPat = FALSE;
2751 if (testpat == "-") {
2752 if (err) {
2753 errln("FAIL: " + where + "Invalid command \"pat: - err\"");
2754 continue;
2755 }
2756 existingPat = TRUE;
2757 testpat = pat;
2758 }
2759 if (exppat == "-") exppat = testpat;
2760 DecimalFormat* f = 0;
2761 UErrorCode ec2 = U_ZERO_ERROR;
2762 if (existingPat) {
2763 f = fmt;
2764 } else {
2765 f = new DecimalFormat(testpat, ec2);
2766 }
2767 if (U_SUCCESS(ec2)) {
2768 if (err) {
2769 errln("FAIL: " + where + "Invalid pattern \"" + testpat +
2770 "\" was accepted");
2771 } else {
2772 UnicodeString pat2;
2773 assertEquals(where + "\"" + testpat + "\".toPattern()",
2774 exppat, f->toPattern(pat2));
2775 }
2776 } else {
2777 if (err) {
2778 logln("Ok: " + where + "Invalid pattern \"" + testpat +
2779 "\" failed: " + u_errorName(ec2));
2780 } else {
2781 errln("FAIL: " + where + "Valid pattern \"" + testpat +
2782 "\" failed: " + u_errorName(ec2));
2783 }
2784 }
2785 if (!existingPat) delete f;
2786 } break;
2787 case -1:
2788 errln("FAIL: " + where + "Unknown command \"" + tok + "\"");
2789 goto done;
2790 }
2791 }
2792 goto done;
2793
2794 error:
2795 if (U_SUCCESS(ec)) {
2796 errln("FAIL: Unexpected EOF");
2797 } else {
2798 errcheckln(ec, "FAIL: " + where + "Unexpected " + u_errorName(ec));
2799 }
2800
2801 done:
2802 delete mfmt;
2803 delete fmt;
2804 delete ref;
2805 }
2806
2807
2808 //----------------------------------------------------------------------
2809 // Support methods
2810 //----------------------------------------------------------------------
2811
equalValue(const Formattable & a,const Formattable & b)2812 UBool NumberFormatTest::equalValue(const Formattable& a, const Formattable& b) {
2813 if (a.getType() == b.getType()) {
2814 return a == b;
2815 }
2816
2817 if (a.getType() == Formattable::kLong) {
2818 if (b.getType() == Formattable::kInt64) {
2819 return a.getLong() == b.getLong();
2820 } else if (b.getType() == Formattable::kDouble) {
2821 return (double) a.getLong() == b.getDouble(); // TODO check use of double instead of long
2822 }
2823 } else if (a.getType() == Formattable::kDouble) {
2824 if (b.getType() == Formattable::kLong) {
2825 return a.getDouble() == (double) b.getLong();
2826 } else if (b.getType() == Formattable::kInt64) {
2827 return a.getDouble() == (double)b.getInt64();
2828 }
2829 } else if (a.getType() == Formattable::kInt64) {
2830 if (b.getType() == Formattable::kLong) {
2831 return a.getInt64() == (int64_t)b.getLong();
2832 } else if (b.getType() == Formattable::kDouble) {
2833 return a.getInt64() == (int64_t)b.getDouble();
2834 }
2835 }
2836 return FALSE;
2837 }
2838
expect3(NumberFormat & fmt,const Formattable & n,const UnicodeString & str)2839 void NumberFormatTest::expect3(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2840 // Don't round-trip format test, since we explicitly do it
2841 expect_rbnf(fmt, n, str, FALSE);
2842 expect_rbnf(fmt, str, n);
2843 }
2844
expect2(NumberFormat & fmt,const Formattable & n,const UnicodeString & str)2845 void NumberFormatTest::expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2846 // Don't round-trip format test, since we explicitly do it
2847 expect(fmt, n, str, FALSE);
2848 expect(fmt, str, n);
2849 }
2850
expect2(NumberFormat * fmt,const Formattable & n,const UnicodeString & exp,UErrorCode status)2851 void NumberFormatTest::expect2(NumberFormat* fmt, const Formattable& n,
2852 const UnicodeString& exp,
2853 UErrorCode status) {
2854 if (fmt == NULL || U_FAILURE(status)) {
2855 dataerrln("FAIL: NumberFormat constructor");
2856 } else {
2857 expect2(*fmt, n, exp);
2858 }
2859 delete fmt;
2860 }
2861
expect(NumberFormat & fmt,const UnicodeString & str,const Formattable & n)2862 void NumberFormatTest::expect(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2863 UErrorCode status = U_ZERO_ERROR;
2864 Formattable num;
2865 fmt.parse(str, num, status);
2866 if (U_FAILURE(status)) {
2867 dataerrln(UnicodeString("FAIL: Parse failed for \"") + str + "\" - " + u_errorName(status));
2868 return;
2869 }
2870 UnicodeString pat;
2871 ((DecimalFormat*) &fmt)->toPattern(pat);
2872 if (equalValue(num, n)) {
2873 logln(UnicodeString("Ok \"") + str + "\" x " +
2874 pat + " = " +
2875 toString(num));
2876 } else {
2877 dataerrln(UnicodeString("FAIL \"") + str + "\" x " +
2878 pat + " = " +
2879 toString(num) + ", expected " + toString(n));
2880 }
2881 }
2882
expect_rbnf(NumberFormat & fmt,const UnicodeString & str,const Formattable & n)2883 void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2884 UErrorCode status = U_ZERO_ERROR;
2885 Formattable num;
2886 fmt.parse(str, num, status);
2887 if (U_FAILURE(status)) {
2888 errln(UnicodeString("FAIL: Parse failed for \"") + str + "\"");
2889 return;
2890 }
2891 if (equalValue(num, n)) {
2892 logln(UnicodeString("Ok \"") + str + " = " +
2893 toString(num));
2894 } else {
2895 errln(UnicodeString("FAIL \"") + str + " = " +
2896 toString(num) + ", expected " + toString(n));
2897 }
2898 }
2899
expect_rbnf(NumberFormat & fmt,const Formattable & n,const UnicodeString & exp,UBool rt)2900 void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const Formattable& n,
2901 const UnicodeString& exp, UBool rt) {
2902 UnicodeString saw;
2903 FieldPosition pos;
2904 UErrorCode status = U_ZERO_ERROR;
2905 fmt.format(n, saw, pos, status);
2906 CHECK(status, "NumberFormat::format");
2907 if (saw == exp) {
2908 logln(UnicodeString("Ok ") + toString(n) +
2909 " = \"" +
2910 escape(saw) + "\"");
2911 // We should be able to round-trip the formatted string =>
2912 // number => string (but not the other way around: number
2913 // => string => number2, might have number2 != number):
2914 if (rt) {
2915 Formattable n2;
2916 fmt.parse(exp, n2, status);
2917 if (U_FAILURE(status)) {
2918 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\"");
2919 return;
2920 }
2921 UnicodeString saw2;
2922 fmt.format(n2, saw2, pos, status);
2923 CHECK(status, "NumberFormat::format");
2924 if (saw2 != exp) {
2925 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2926 " => \"" + saw2 + "\"");
2927 }
2928 }
2929 } else {
2930 errln(UnicodeString("FAIL ") + toString(n) +
2931 " = \"" +
2932 escape(saw) + "\", expected \"" + exp + "\"");
2933 }
2934 }
2935
expect(NumberFormat & fmt,const Formattable & n,const UnicodeString & exp,UBool rt)2936 void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
2937 const UnicodeString& exp, UBool rt) {
2938 UnicodeString saw;
2939 FieldPosition pos;
2940 UErrorCode status = U_ZERO_ERROR;
2941 fmt.format(n, saw, pos, status);
2942 CHECK(status, "NumberFormat::format");
2943 UnicodeString pat;
2944 ((DecimalFormat*) &fmt)->toPattern(pat);
2945 if (saw == exp) {
2946 logln(UnicodeString("Ok ") + toString(n) + " x " +
2947 escape(pat) + " = \"" +
2948 escape(saw) + "\"");
2949 // We should be able to round-trip the formatted string =>
2950 // number => string (but not the other way around: number
2951 // => string => number2, might have number2 != number):
2952 if (rt) {
2953 Formattable n2;
2954 fmt.parse(exp, n2, status);
2955 if (U_FAILURE(status)) {
2956 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\" - " + u_errorName(status));
2957 return;
2958 }
2959 UnicodeString saw2;
2960 fmt.format(n2, saw2, pos, status);
2961 CHECK(status, "NumberFormat::format");
2962 if (saw2 != exp) {
2963 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2964 " => \"" + saw2 + "\"");
2965 }
2966 }
2967 } else {
2968 dataerrln(UnicodeString("FAIL ") + toString(n) + " x " +
2969 escape(pat) + " = \"" +
2970 escape(saw) + "\", expected \"" + exp + "\"");
2971 }
2972 }
2973
expect(NumberFormat * fmt,const Formattable & n,const UnicodeString & exp,UBool rt,UErrorCode status)2974 void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
2975 const UnicodeString& exp, UBool rt,
2976 UErrorCode status) {
2977 if (fmt == NULL || U_FAILURE(status)) {
2978 dataerrln("FAIL: NumberFormat constructor");
2979 } else {
2980 expect(*fmt, n, exp, rt);
2981 }
2982 delete fmt;
2983 }
2984
expectCurrency(NumberFormat & nf,const Locale & locale,double value,const UnicodeString & string)2985 void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
2986 double value, const UnicodeString& string) {
2987 UErrorCode ec = U_ZERO_ERROR;
2988 DecimalFormat& fmt = * (DecimalFormat*) &nf;
2989 const UChar DEFAULT_CURR[] = {45/*-*/,0};
2990 UChar curr[4];
2991 u_strcpy(curr, DEFAULT_CURR);
2992 if (*locale.getLanguage() != 0) {
2993 ucurr_forLocale(locale.getName(), curr, 4, &ec);
2994 assertSuccess("ucurr_forLocale", ec);
2995 fmt.setCurrency(curr, ec);
2996 assertSuccess("DecimalFormat::setCurrency", ec);
2997 fmt.setCurrency(curr); //Deprecated variant, for coverage only
2998 }
2999 UnicodeString s;
3000 fmt.format(value, s);
3001 s.findAndReplace((UChar32)0x00A0, (UChar32)0x0020);
3002
3003 // Default display of the number yields "1234.5599999999999"
3004 // instead of "1234.56". Use a formatter to fix this.
3005 NumberFormat* f =
3006 NumberFormat::createInstance(Locale::getUS(), ec);
3007 UnicodeString v;
3008 if (U_FAILURE(ec)) {
3009 // Oops; bad formatter. Use default op+= display.
3010 v = (UnicodeString)"" + value;
3011 } else {
3012 f->setMaximumFractionDigits(4);
3013 f->setGroupingUsed(FALSE);
3014 f->format(value, v);
3015 }
3016 delete f;
3017
3018 if (s == string) {
3019 logln((UnicodeString)"Ok: " + v + " x " + curr + " => " + prettify(s));
3020 } else {
3021 errln((UnicodeString)"FAIL: " + v + " x " + curr + " => " + prettify(s) +
3022 ", expected " + prettify(string));
3023 }
3024 }
3025
expectPat(DecimalFormat & fmt,const UnicodeString & exp)3026 void NumberFormatTest::expectPat(DecimalFormat& fmt, const UnicodeString& exp) {
3027 UnicodeString pat;
3028 fmt.toPattern(pat);
3029 if (pat == exp) {
3030 logln(UnicodeString("Ok \"") + pat + "\"");
3031 } else {
3032 errln(UnicodeString("FAIL \"") + pat + "\", expected \"" + exp + "\"");
3033 }
3034 }
3035
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos)3036 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3037 int32_t pos) {
3038 expectPad(fmt, pat, pos, 0, (UnicodeString)"");
3039 }
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos,int32_t width,UChar pad)3040 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3041 int32_t pos, int32_t width, UChar pad) {
3042 expectPad(fmt, pat, pos, width, UnicodeString(pad));
3043 }
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos,int32_t width,const UnicodeString & pad)3044 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3045 int32_t pos, int32_t width, const UnicodeString& pad) {
3046 int32_t apos = 0, awidth = 0;
3047 UnicodeString apadStr;
3048 UErrorCode status = U_ZERO_ERROR;
3049 fmt.applyPattern(pat, status);
3050 if (U_SUCCESS(status)) {
3051 apos = fmt.getPadPosition();
3052 awidth = fmt.getFormatWidth();
3053 apadStr=fmt.getPadCharacterString();
3054 } else {
3055 apos = -1;
3056 awidth = width;
3057 apadStr = pad;
3058 }
3059 if (apos == pos && awidth == width && apadStr == pad) {
3060 UnicodeString infoStr;
3061 if (pos == ILLEGAL) {
3062 infoStr = UnicodeString(" width=", "") + awidth + UnicodeString(" pad=", "") + apadStr;
3063 }
3064 logln(UnicodeString("Ok \"") + pat + "\" pos=" + apos + infoStr);
3065 } else {
3066 errln(UnicodeString("FAIL \"") + pat + "\" pos=" + apos +
3067 " width=" + awidth + " pad=" + apadStr +
3068 ", expected " + pos + " " + width + " " + pad);
3069 }
3070 }
3071
3072 // This test is flaky b/c the symbols for CNY and JPY are equivalent in this locale - FIXME
TestCompatibleCurrencies()3073 void NumberFormatTest::TestCompatibleCurrencies() {
3074 /*
3075 static const UChar JPY[] = {0x4A, 0x50, 0x59, 0};
3076 static const UChar CNY[] = {0x43, 0x4E, 0x59, 0};
3077 UErrorCode status = U_ZERO_ERROR;
3078 LocalPointer<NumberFormat> fmt(
3079 NumberFormat::createCurrencyInstance(Locale::getUS(), status));
3080 if (U_FAILURE(status)) {
3081 errln("Could not create number format instance.");
3082 return;
3083 }
3084 logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3085 expectParseCurrency(*fmt, JPY, 1235, "\\u00A51,235");
3086 logln("%s:%d - testing parse of fullwidth yen sign\n", __FILE__, __LINE__);
3087 expectParseCurrency(*fmt, JPY, 1235, "\\uFFE51,235");
3088 logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3089 expectParseCurrency(*fmt, CNY, 1235, "CN\\u00A51,235");
3090
3091 LocalPointer<NumberFormat> fmtTW(
3092 NumberFormat::createCurrencyInstance(Locale::getTaiwan(), status));
3093
3094 logln("%s:%d - testing parse of halfwidth yen sign in TW\n", __FILE__, __LINE__);
3095 expectParseCurrency(*fmtTW, CNY, 1235, "\\u00A51,235");
3096 logln("%s:%d - testing parse of fullwidth yen sign in TW\n", __FILE__, __LINE__);
3097 expectParseCurrency(*fmtTW, CNY, 1235, "\\uFFE51,235");
3098
3099 LocalPointer<NumberFormat> fmtJP(
3100 NumberFormat::createCurrencyInstance(Locale::getJapan(), status));
3101
3102 logln("%s:%d - testing parse of halfwidth yen sign in JP\n", __FILE__, __LINE__);
3103 expectParseCurrency(*fmtJP, JPY, 1235, "\\u00A51,235");
3104 logln("%s:%d - testing parse of fullwidth yen sign in JP\n", __FILE__, __LINE__);
3105 expectParseCurrency(*fmtJP, JPY, 1235, "\\uFFE51,235");
3106
3107 // more..
3108 */
3109 }
3110
expectParseCurrency(const NumberFormat & fmt,const UChar * currency,double amount,const char * text)3111 void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text) {
3112 ParsePosition ppos;
3113 UnicodeString utext = ctou(text);
3114 LocalPointer<CurrencyAmount> currencyAmount(fmt.parseCurrency(utext, ppos));
3115 if (!ppos.getIndex()) {
3116 errln(UnicodeString("Parse of ") + utext + " should have succeeded.");
3117 return;
3118 }
3119 UErrorCode status = U_ZERO_ERROR;
3120
3121 char theInfo[100];
3122 sprintf(theInfo, "For locale %s, string \"%s\", currency ",
3123 fmt.getLocale(ULOC_ACTUAL_LOCALE, status).getBaseName(),
3124 text);
3125 u_austrcpy(theInfo+uprv_strlen(theInfo), currency);
3126
3127 char theOperation[100];
3128
3129 uprv_strcpy(theOperation, theInfo);
3130 uprv_strcat(theOperation, ", check amount:");
3131 assertTrue(theOperation, amount == currencyAmount->getNumber().getDouble(status));
3132
3133 uprv_strcpy(theOperation, theInfo);
3134 uprv_strcat(theOperation, ", check currency:");
3135 assertEquals(theOperation, currency, currencyAmount->getISOCurrency());
3136 }
3137
3138
TestJB3832()3139 void NumberFormatTest::TestJB3832(){
3140 const char* localeID = "pt_PT@currency=PTE";
3141 Locale loc(localeID);
3142 UErrorCode status = U_ZERO_ERROR;
3143 UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0\\u200B")); // per cldrbug 7670
3144 UnicodeString s;
3145 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
3146 if(U_FAILURE(status)){
3147 dataerrln("Could not create currency formatter for locale %s - %s", localeID, u_errorName(status));
3148 return;
3149 }
3150 currencyFmt->format(1150.50, s);
3151 if(s!=expected){
3152 errln(UnicodeString("FAIL: Expected: ")+expected
3153 + UnicodeString(" Got: ") + s
3154 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
3155 }
3156 if (U_FAILURE(status)){
3157 errln("FAIL: Status %s", u_errorName(status));
3158 }
3159 delete currencyFmt;
3160 }
3161
TestHost()3162 void NumberFormatTest::TestHost()
3163 {
3164 #if U_PLATFORM_USES_ONLY_WIN32_API
3165 Win32NumberTest::testLocales(this);
3166 #endif
3167 Locale loc("en_US@compat=host");
3168 for (UNumberFormatStyle k = UNUM_DECIMAL;
3169 k < UNUM_FORMAT_STYLE_COUNT; k = (UNumberFormatStyle)(k+1)) {
3170 UErrorCode status = U_ZERO_ERROR;
3171 LocalPointer<NumberFormat> full(NumberFormat::createInstance(loc, k, status));
3172 if (!NumberFormat::isStyleSupported(k)) {
3173 if (status != U_UNSUPPORTED_ERROR) {
3174 errln("FAIL: expected style %d to be unsupported - %s",
3175 k, u_errorName(status));
3176 }
3177 continue;
3178 }
3179 if (full.isNull() || U_FAILURE(status)) {
3180 dataerrln("FAIL: Can't create number instance of style %d for host - %s",
3181 k, u_errorName(status));
3182 return;
3183 }
3184 UnicodeString result1;
3185 Formattable number(10.00);
3186 full->format(number, result1, status);
3187 if (U_FAILURE(status)) {
3188 errln("FAIL: Can't format for host");
3189 return;
3190 }
3191 Formattable formattable;
3192 full->parse(result1, formattable, status);
3193 if (U_FAILURE(status)) {
3194 errln("FAIL: Can't parse for host");
3195 return;
3196 }
3197 }
3198 }
3199
TestHostClone()3200 void NumberFormatTest::TestHostClone()
3201 {
3202 /*
3203 Verify that a cloned formatter gives the same results
3204 and is useable after the original has been deleted.
3205 */
3206 // This is mainly important on Windows.
3207 UErrorCode status = U_ZERO_ERROR;
3208 Locale loc("en_US@compat=host");
3209 UDate now = Calendar::getNow();
3210 NumberFormat *full = NumberFormat::createInstance(loc, status);
3211 if (full == NULL || U_FAILURE(status)) {
3212 dataerrln("FAIL: Can't create NumberFormat date instance - %s", u_errorName(status));
3213 return;
3214 }
3215 UnicodeString result1;
3216 full->format(now, result1, status);
3217 Format *fullClone = full->clone();
3218 delete full;
3219 full = NULL;
3220
3221 UnicodeString result2;
3222 fullClone->format(now, result2, status);
3223 if (U_FAILURE(status)) {
3224 errln("FAIL: format failure.");
3225 }
3226 if (result1 != result2) {
3227 errln("FAIL: Clone returned different result from non-clone.");
3228 }
3229 delete fullClone;
3230 }
3231
TestCurrencyFormat()3232 void NumberFormatTest::TestCurrencyFormat()
3233 {
3234 // This test is here to increase code coverage.
3235 UErrorCode status = U_ZERO_ERROR;
3236 MeasureFormat *cloneObj;
3237 UnicodeString str;
3238 Formattable toFormat, result;
3239 static const UChar ISO_CODE[4] = {0x0047, 0x0042, 0x0050, 0};
3240
3241 Locale saveDefaultLocale = Locale::getDefault();
3242 Locale::setDefault( Locale::getUK(), status );
3243 if (U_FAILURE(status)) {
3244 errln("couldn't set default Locale!");
3245 return;
3246 }
3247
3248 MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
3249 Locale::setDefault( saveDefaultLocale, status );
3250 if (U_FAILURE(status)){
3251 dataerrln("FAIL: Status %s", u_errorName(status));
3252 return;
3253 }
3254 cloneObj = measureObj->clone();
3255 if (cloneObj == NULL) {
3256 errln("Clone doesn't work");
3257 return;
3258 }
3259 toFormat.adoptObject(new CurrencyAmount(1234.56, ISO_CODE, status));
3260 measureObj->format(toFormat, str, status);
3261 measureObj->parseObject(str, result, status);
3262 if (U_FAILURE(status)){
3263 errln("FAIL: Status %s", u_errorName(status));
3264 }
3265 if (result != toFormat) {
3266 errln("measureObj does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3267 }
3268 status = U_ZERO_ERROR;
3269 str.truncate(0);
3270 cloneObj->format(toFormat, str, status);
3271 cloneObj->parseObject(str, result, status);
3272 if (U_FAILURE(status)){
3273 errln("FAIL: Status %s", u_errorName(status));
3274 }
3275 if (result != toFormat) {
3276 errln("Clone does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3277 }
3278 if (*measureObj != *cloneObj) {
3279 errln("Cloned object is not equal to the original object");
3280 }
3281 delete measureObj;
3282 delete cloneObj;
3283
3284 status = U_USELESS_COLLATOR_ERROR;
3285 if (MeasureFormat::createCurrencyFormat(status) != NULL) {
3286 errln("createCurrencyFormat should have returned NULL.");
3287 }
3288 }
3289
3290 /* Port of ICU4J rounding test. */
TestRounding()3291 void NumberFormatTest::TestRounding() {
3292 UErrorCode status = U_ZERO_ERROR;
3293 DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3294
3295 if (U_FAILURE(status)) {
3296 dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3297 return;
3298 }
3299
3300 int roundingIncrements[]={1, 2, 5, 20, 50, 100};
3301 int testValues[]={0, 300};
3302
3303 for (int j=0; j<2; j++) {
3304 for (int mode=DecimalFormat::kRoundUp;mode<DecimalFormat::kRoundHalfEven;mode++) {
3305 df->setRoundingMode((DecimalFormat::ERoundingMode)mode);
3306 for (int increment=0; increment<6; increment++) {
3307 double base=testValues[j];
3308 double rInc=roundingIncrements[increment];
3309 checkRounding(df, base, 20, rInc);
3310 rInc=1.000000000/rInc;
3311 checkRounding(df, base, 20, rInc);
3312 }
3313 }
3314 }
3315 delete df;
3316 }
3317
TestRoundingPattern()3318 void NumberFormatTest::TestRoundingPattern() {
3319 UErrorCode status = U_ZERO_ERROR;
3320 struct {
3321 UnicodeString pattern;
3322 double testCase;
3323 UnicodeString expected;
3324 } tests[] = {
3325 { (UnicodeString)"##0.65", 1.234, (UnicodeString)"1.30" },
3326 { (UnicodeString)"#50", 1230, (UnicodeString)"1250" }
3327 };
3328 int32_t numOfTests = UPRV_LENGTHOF(tests);
3329 UnicodeString result;
3330
3331 DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3332 if (U_FAILURE(status)) {
3333 dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3334 return;
3335 }
3336
3337 for (int32_t i = 0; i < numOfTests; i++) {
3338 result.remove();
3339
3340 df->applyPattern(tests[i].pattern, status);
3341 if (U_FAILURE(status)) {
3342 errln("Unable to apply pattern to decimal formatter. - %s", u_errorName(status));
3343 }
3344
3345 df->format(tests[i].testCase, result);
3346
3347 if (result != tests[i].expected) {
3348 errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
3349 }
3350 }
3351
3352 delete df;
3353 }
3354
checkRounding(DecimalFormat * df,double base,int iterations,double increment)3355 void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
3356 df->setRoundingIncrement(increment);
3357 double lastParsed=INT32_MIN; //Intger.MIN_VALUE
3358 for (int i=-iterations; i<=iterations;i++) {
3359 double iValue=base+(increment*(i*0.1));
3360 double smallIncrement=0.00000001;
3361 if (iValue!=0) {
3362 smallIncrement*=iValue;
3363 }
3364 //we not only test the value, but some values in a small range around it
3365 lastParsed=checkRound(df, iValue-smallIncrement, lastParsed);
3366 lastParsed=checkRound(df, iValue, lastParsed);
3367 lastParsed=checkRound(df, iValue+smallIncrement, lastParsed);
3368 }
3369 }
3370
checkRound(DecimalFormat * df,double iValue,double lastParsed)3371 double NumberFormatTest::checkRound(DecimalFormat* df, double iValue, double lastParsed) {
3372 UErrorCode status=U_ZERO_ERROR;
3373 UnicodeString formattedDecimal;
3374 double parsed;
3375 Formattable result;
3376 df->format(iValue, formattedDecimal, status);
3377
3378 if (U_FAILURE(status)) {
3379 errln("Error formatting number.");
3380 }
3381
3382 df->parse(formattedDecimal, result, status);
3383
3384 if (U_FAILURE(status)) {
3385 errln("Error parsing number.");
3386 }
3387
3388 parsed=result.getDouble();
3389
3390 if (lastParsed>parsed) {
3391 errln("Rounding wrong direction! %d > %d", lastParsed, parsed);
3392 }
3393
3394 return lastParsed;
3395 }
3396
TestNonpositiveMultiplier()3397 void NumberFormatTest::TestNonpositiveMultiplier() {
3398 UErrorCode status = U_ZERO_ERROR;
3399 DecimalFormatSymbols US(Locale::getUS(), status);
3400 CHECK(status, "DecimalFormatSymbols constructor");
3401 DecimalFormat df(UnicodeString("0"), US, status);
3402 CHECK(status, "DecimalFormat(0)");
3403
3404 // test zero multiplier
3405
3406 int32_t mult = df.getMultiplier();
3407 df.setMultiplier(0);
3408 if (df.getMultiplier() != mult) {
3409 errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
3410 }
3411
3412 // test negative multiplier
3413
3414 df.setMultiplier(-1);
3415 if (df.getMultiplier() != -1) {
3416 errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
3417 return;
3418 }
3419
3420 expect(df, "1122.123", -1122.123);
3421 expect(df, "-1122.123", 1122.123);
3422 expect(df, "1.2", -1.2);
3423 expect(df, "-1.2", 1.2);
3424
3425 // Note: the tests with the final parameter of FALSE will not round trip.
3426 // The initial numeric value will format correctly, after the multiplier.
3427 // Parsing the formatted text will be out-of-range for an int64, however.
3428 // The expect() function could be modified to detect this and fall back
3429 // to looking at the decimal parsed value, but it doesn't.
3430 expect(df, U_INT64_MIN, "9223372036854775808", FALSE);
3431 expect(df, U_INT64_MIN+1, "9223372036854775807");
3432 expect(df, (int64_t)-123, "123");
3433 expect(df, (int64_t)123, "-123");
3434 expect(df, U_INT64_MAX-1, "-9223372036854775806");
3435 expect(df, U_INT64_MAX, "-9223372036854775807");
3436
3437 df.setMultiplier(-2);
3438 expect(df, -(U_INT64_MIN/2)-1, "-9223372036854775806");
3439 expect(df, -(U_INT64_MIN/2), "-9223372036854775808");
3440 expect(df, -(U_INT64_MIN/2)+1, "-9223372036854775810", FALSE);
3441
3442 df.setMultiplier(-7);
3443 expect(df, -(U_INT64_MAX/7)-1, "9223372036854775814", FALSE);
3444 expect(df, -(U_INT64_MAX/7), "9223372036854775807");
3445 expect(df, -(U_INT64_MAX/7)+1, "9223372036854775800");
3446
3447 // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
3448 // (right now the big numbers get turned into doubles and lose tons of accuracy)
3449 //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
3450 //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
3451 //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
3452 //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
3453
3454 // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
3455 //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3456 //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3457 //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3458 //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3459 }
3460
3461 typedef struct {
3462 const char * stringToParse;
3463 int parsedPos;
3464 int errorIndex;
3465 UBool lenient;
3466 } TestSpaceParsingItem;
3467
3468 void
TestSpaceParsing()3469 NumberFormatTest::TestSpaceParsing() {
3470 // the data are:
3471 // the string to be parsed, parsed position, parsed error index
3472 const TestSpaceParsingItem DATA[] = {
3473 {"$124", 4, -1, FALSE},
3474 {"$124 $124", 4, -1, FALSE},
3475 {"$124 ", 4, -1, FALSE},
3476 {"$ 124 ", 0, 1, FALSE},
3477 {"$\\u00A0124 ", 5, -1, FALSE},
3478 {" $ 124 ", 0, 0, FALSE},
3479 {"124$", 0, 4, FALSE},
3480 {"124 $", 0, 3, FALSE},
3481 {"$124", 4, -1, TRUE},
3482 {"$124 $124", 4, -1, TRUE},
3483 {"$124 ", 4, -1, TRUE},
3484 {"$ 124 ", 5, -1, TRUE},
3485 {"$\\u00A0124 ", 5, -1, TRUE},
3486 {" $ 124 ", 6, -1, TRUE},
3487 {"124$", 4, -1, TRUE},
3488 {"124$", 4, -1, TRUE},
3489 {"124 $", 5, -1, TRUE},
3490 {"124 $", 5, -1, TRUE},
3491 };
3492 UErrorCode status = U_ZERO_ERROR;
3493 Locale locale("en_US");
3494 NumberFormat* foo = NumberFormat::createCurrencyInstance(locale, status);
3495
3496 if (U_FAILURE(status)) {
3497 delete foo;
3498 return;
3499 }
3500 for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3501 ParsePosition parsePosition(0);
3502 UnicodeString stringToBeParsed = ctou(DATA[i].stringToParse);
3503 int parsedPosition = DATA[i].parsedPos;
3504 int errorIndex = DATA[i].errorIndex;
3505 foo->setLenient(DATA[i].lenient);
3506 Formattable result;
3507 foo->parse(stringToBeParsed, result, parsePosition);
3508 logln("Parsing: " + stringToBeParsed);
3509 if (parsePosition.getIndex() != parsedPosition ||
3510 parsePosition.getErrorIndex() != errorIndex) {
3511 errln("FAILED parse " + stringToBeParsed + "; lenient: " + DATA[i].lenient + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
3512 }
3513 if (parsePosition.getErrorIndex() == -1 &&
3514 result.getType() == Formattable::kLong &&
3515 result.getLong() != 124) {
3516 errln("FAILED parse " + stringToBeParsed + "; wrong number, expect: 124, got " + result.getLong());
3517 }
3518 }
3519 delete foo;
3520 }
3521
3522 /**
3523 * Test using various numbering systems and numbering system keyword.
3524 */
3525 typedef struct {
3526 const char *localeName;
3527 double value;
3528 UBool isRBNF;
3529 const char *expectedResult;
3530 } TestNumberingSystemItem;
3531
TestNumberingSystems()3532 void NumberFormatTest::TestNumberingSystems() {
3533
3534 const TestNumberingSystemItem DATA[] = {
3535 { "en_US@numbers=thai", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" },
3536 { "en_US@numbers=hebr", 5678.0, TRUE, "\\u05D4\\u05F3\\u05EA\\u05E8\\u05E2\\u05F4\\u05D7" },
3537 { "en_US@numbers=arabext", 1234.567, FALSE, "\\u06F1\\u066c\\u06F2\\u06F3\\u06F4\\u066b\\u06F5\\u06F6\\u06F7" },
3538 { "ar_EG", 1234.567, FALSE, "\\u0661\\u066C\\u0662\\u0663\\u0664\\u066b\\u0665\\u0666\\u0667" },
3539 { "th_TH@numbers=traditional", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" }, // fall back to native per TR35
3540 { "ar_MA", 1234.567, FALSE, "1.234,567" },
3541 { "en_US@numbers=hanidec", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3542 { "ta_IN@numbers=native", 1234.567, FALSE, "\\u0BE7,\\u0BE8\\u0BE9\\u0BEA.\\u0BEB\\u0BEC\\u0BED" },
3543 { "ta_IN@numbers=traditional", 1235.0, TRUE, "\\u0BF2\\u0BE8\\u0BF1\\u0BE9\\u0BF0\\u0BEB" },
3544 { "ta_IN@numbers=finance", 1234.567, FALSE, "1,234.567" }, // fall back to default per TR35
3545 { "zh_TW@numbers=native", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3546 { "zh_TW@numbers=traditional", 1234.567, TRUE, "\\u4E00\\u5343\\u4E8C\\u767E\\u4E09\\u5341\\u56DB\\u9EDE\\u4E94\\u516D\\u4E03" },
3547 { "zh_TW@numbers=finance", 1234.567, TRUE, "\\u58F9\\u4EDF\\u8CB3\\u4F70\\u53C3\\u62FE\\u8086\\u9EDE\\u4F0D\\u9678\\u67D2" },
3548 { NULL, 0, FALSE, NULL }
3549 };
3550
3551 UErrorCode ec;
3552
3553 const TestNumberingSystemItem *item;
3554 for (item = DATA; item->localeName != NULL; item++) {
3555 ec = U_ZERO_ERROR;
3556 Locale loc = Locale::createFromName(item->localeName);
3557
3558 NumberFormat *origFmt = NumberFormat::createInstance(loc,ec);
3559 if (U_FAILURE(ec)) {
3560 dataerrln("FAIL: getInstance(%s) - %s", item->localeName, u_errorName(ec));
3561 continue;
3562 }
3563 // Clone to test ticket #10682
3564 NumberFormat *fmt = origFmt->clone();
3565 delete origFmt;
3566
3567
3568 if (item->isRBNF) {
3569 expect3(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3570 } else {
3571 expect2(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3572 }
3573 delete fmt;
3574 }
3575
3576
3577 // Test bogus keyword value
3578 ec = U_ZERO_ERROR;
3579 Locale loc4 = Locale::createFromName("en_US@numbers=foobar");
3580 NumberFormat* fmt4= NumberFormat::createInstance(loc4, ec);
3581 if ( ec != U_UNSUPPORTED_ERROR ) {
3582 errln("FAIL: getInstance(en_US@numbers=foobar) should have returned U_UNSUPPORTED_ERROR");
3583 delete fmt4;
3584 }
3585
3586 ec = U_ZERO_ERROR;
3587 NumberingSystem *ns = NumberingSystem::createInstance(ec);
3588 if (U_FAILURE(ec)) {
3589 dataerrln("FAIL: NumberingSystem::createInstance(ec); - %s", u_errorName(ec));
3590 }
3591
3592 if ( ns != NULL ) {
3593 ns->getDynamicClassID();
3594 ns->getStaticClassID();
3595 } else {
3596 errln("FAIL: getInstance() returned NULL.");
3597 }
3598
3599 NumberingSystem *ns1 = new NumberingSystem(*ns);
3600 if (ns1 == NULL) {
3601 errln("FAIL: NumberSystem copy constructor returned NULL.");
3602 }
3603
3604 delete ns1;
3605 delete ns;
3606
3607 }
3608
3609
3610 void
TestMultiCurrencySign()3611 NumberFormatTest::TestMultiCurrencySign() {
3612 const char* DATA[][6] = {
3613 // the fields in the following test are:
3614 // locale,
3615 // currency pattern (with negative pattern),
3616 // currency number to be formatted,
3617 // currency format using currency symbol name, such as "$" for USD,
3618 // currency format using currency ISO name, such as "USD",
3619 // currency format using plural name, such as "US dollars".
3620 // for US locale
3621 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1234.56", "$1,234.56", "USD\\u00A01,234.56", "US dollars\\u00A01,234.56"},
3622 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD\\u00A01,234.56", "-US dollars\\u00A01,234.56"},
3623 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD\\u00A01.00", "US dollars\\u00A01.00"},
3624 // for CHINA locale
3625 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\u00A51,234.56", "CNY\\u00A01,234.56", "\\u4EBA\\u6C11\\u5E01\\u00A01,234.56"},
3626 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\u00A51,234.56)", "(CNY\\u00A01,234.56)", "(\\u4EBA\\u6C11\\u5E01\\u00A01,234.56)"},
3627 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\u00A51.00", "CNY\\u00A01.00", "\\u4EBA\\u6C11\\u5E01\\u00A01.00"}
3628 };
3629
3630 const UChar doubleCurrencySign[] = {0xA4, 0xA4, 0};
3631 UnicodeString doubleCurrencyStr(doubleCurrencySign);
3632 const UChar tripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
3633 UnicodeString tripleCurrencyStr(tripleCurrencySign);
3634
3635 for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3636 const char* locale = DATA[i][0];
3637 UnicodeString pat = ctou(DATA[i][1]);
3638 double numberToBeFormat = atof(DATA[i][2]);
3639 UErrorCode status = U_ZERO_ERROR;
3640 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale(locale), status);
3641 if (U_FAILURE(status)) {
3642 delete sym;
3643 continue;
3644 }
3645 for (int j=1; j<=3; ++j) {
3646 // j represents the number of currency sign in the pattern.
3647 if (j == 2) {
3648 pat = pat.findAndReplace(ctou("\\u00A4"), doubleCurrencyStr);
3649 } else if (j == 3) {
3650 pat = pat.findAndReplace(ctou("\\u00A4\\u00A4"), tripleCurrencyStr);
3651 }
3652
3653 DecimalFormat* fmt = new DecimalFormat(pat, new DecimalFormatSymbols(*sym), status);
3654 if (U_FAILURE(status)) {
3655 errln("FAILED init DecimalFormat ");
3656 delete fmt;
3657 continue;
3658 }
3659 UnicodeString s;
3660 ((NumberFormat*) fmt)->format(numberToBeFormat, s);
3661 // DATA[i][3] is the currency format result using a
3662 // single currency sign.
3663 // DATA[i][4] is the currency format result using
3664 // double currency sign.
3665 // DATA[i][5] is the currency format result using
3666 // triple currency sign.
3667 // DATA[i][j+2] is the currency format result using
3668 // 'j' number of currency sign.
3669 UnicodeString currencyFormatResult = ctou(DATA[i][2+j]);
3670 if (s.compare(currencyFormatResult)) {
3671 errln("FAIL format: Expected " + currencyFormatResult + "; Got " + s);
3672 }
3673 // mix style parsing
3674 for (int k=3; k<=5; ++k) {
3675 // DATA[i][3] is the currency format result using a
3676 // single currency sign.
3677 // DATA[i][4] is the currency format result using
3678 // double currency sign.
3679 // DATA[i][5] is the currency format result using
3680 // triple currency sign.
3681 UnicodeString oneCurrencyFormat = ctou(DATA[i][k]);
3682 UErrorCode status = U_ZERO_ERROR;
3683 Formattable parseRes;
3684 fmt->parse(oneCurrencyFormat, parseRes, status);
3685 if (U_FAILURE(status) ||
3686 (parseRes.getType() == Formattable::kDouble &&
3687 parseRes.getDouble() != numberToBeFormat) ||
3688 (parseRes.getType() == Formattable::kLong &&
3689 parseRes.getLong() != numberToBeFormat)) {
3690 errln("FAILED parse " + oneCurrencyFormat + "; (i, j, k): " +
3691 i + ", " + j + ", " + k);
3692 }
3693 }
3694 delete fmt;
3695 }
3696 delete sym;
3697 }
3698 }
3699
3700
3701 void
TestCurrencyFormatForMixParsing()3702 NumberFormatTest::TestCurrencyFormatForMixParsing() {
3703 UErrorCode status = U_ZERO_ERROR;
3704 MeasureFormat* curFmt = MeasureFormat::createCurrencyFormat(Locale("en_US"), status);
3705 if (U_FAILURE(status)) {
3706 delete curFmt;
3707 return;
3708 }
3709 const char* formats[] = {
3710 "$1,234.56", // string to be parsed
3711 "USD1,234.56",
3712 "US dollars1,234.56",
3713 // "1,234.56 US dollars" // Fails in 62 because currency format is not compatible with pattern.
3714 };
3715 const CurrencyAmount* curramt = NULL;
3716 for (uint32_t i = 0; i < UPRV_LENGTHOF(formats); ++i) {
3717 UnicodeString stringToBeParsed = ctou(formats[i]);
3718 logln(UnicodeString("stringToBeParsed: ") + stringToBeParsed);
3719 Formattable result;
3720 UErrorCode status = U_ZERO_ERROR;
3721 curFmt->parseObject(stringToBeParsed, result, status);
3722 if (U_FAILURE(status)) {
3723 errln("FAIL: measure format parsing: '%s' ec: %s", formats[i], u_errorName(status));
3724 } else if (result.getType() != Formattable::kObject ||
3725 (curramt = dynamic_cast<const CurrencyAmount*>(result.getObject())) == NULL ||
3726 curramt->getNumber().getDouble() != 1234.56 ||
3727 UnicodeString(curramt->getISOCurrency()).compare(ISO_CURRENCY_USD)
3728 ) {
3729 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number ");
3730 if (curramt->getNumber().getDouble() != 1234.56) {
3731 errln((UnicodeString)"wong number, expect: 1234.56" + ", got: " + curramt->getNumber().getDouble());
3732 }
3733 if (curramt->getISOCurrency() != ISO_CURRENCY_USD) {
3734 errln((UnicodeString)"wong currency, expect: USD" + ", got: " + curramt->getISOCurrency());
3735 }
3736 }
3737 }
3738 delete curFmt;
3739 }
3740
3741
3742 /** Starting in ICU 62, strict mode is actually strict with currency formats. */
TestMismatchedCurrencyFormatFail()3743 void NumberFormatTest::TestMismatchedCurrencyFormatFail() {
3744 IcuTestErrorCode status(*this, "TestMismatchedCurrencyFormatFail");
3745 LocalPointer<DecimalFormat> df(
3746 dynamic_cast<DecimalFormat*>(DecimalFormat::createCurrencyInstance("en", status)), status);
3747 if (!assertSuccess("createCurrencyInstance() failed.", status, true, __FILE__, __LINE__)) {return;}
3748 UnicodeString pattern;
3749 assertEquals("Test assumes that currency sign is at the beginning",
3750 u"\u00A4#,##0.00",
3751 df->toPattern(pattern));
3752 // Should round-trip on the correct currency format:
3753 expect2(*df, 1.23, u"\u00A41.23");
3754 df->setCurrency(u"EUR", status);
3755 expect2(*df, 1.23, u"\u20AC1.23");
3756 // Should parse with currency in the wrong place in lenient mode
3757 df->setLenient(TRUE);
3758 expect(*df, u"1.23\u20AC", 1.23);
3759 expectParseCurrency(*df, u"EUR", 1.23, "1.23\\u20AC");
3760 // Should NOT parse with currency in the wrong place in STRICT mode
3761 df->setLenient(FALSE);
3762 {
3763 Formattable result;
3764 ErrorCode failStatus;
3765 df->parse(u"1.23\u20AC", result, failStatus);
3766 assertEquals("Should fail to parse", U_INVALID_FORMAT_ERROR, failStatus);
3767 }
3768 {
3769 ParsePosition ppos;
3770 df->parseCurrency(u"1.23\u20AC", ppos);
3771 assertEquals("Should fail to parse currency", 0, ppos.getIndex());
3772 }
3773 }
3774
3775
3776 void
TestDecimalFormatCurrencyParse()3777 NumberFormatTest::TestDecimalFormatCurrencyParse() {
3778 // Locale.US
3779 UErrorCode status = U_ZERO_ERROR;
3780 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale("en_US"), status);
3781 if (U_FAILURE(status)) {
3782 delete sym;
3783 return;
3784 }
3785 UnicodeString pat;
3786 UChar currency = 0x00A4;
3787 // "\xA4#,##0.00;-\xA4#,##0.00"
3788 pat.append(currency).append(currency).append(currency).append("#,##0.00;-").append(currency).append(currency).append(currency).append("#,##0.00");
3789 DecimalFormat* fmt = new DecimalFormat(pat, sym, status);
3790 if (U_FAILURE(status)) {
3791 delete fmt;
3792 errln("failed to new DecimalFormat in TestDecimalFormatCurrencyParse");
3793 return;
3794 }
3795 const char* DATA[][2] = {
3796 // the data are:
3797 // string to be parsed, the parsed result (number)
3798 {"$1.00", "1"},
3799 {"USD1.00", "1"},
3800 {"1.00 US dollar", "1"},
3801 {"$1,234.56", "1234.56"},
3802 {"USD1,234.56", "1234.56"},
3803 {"1,234.56 US dollar", "1234.56"},
3804 };
3805 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3806 fmt->setLenient(TRUE);
3807 for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3808 UnicodeString stringToBeParsed = ctou(DATA[i][0]);
3809 double parsedResult = atof(DATA[i][1]);
3810 UErrorCode status = U_ZERO_ERROR;
3811 Formattable result;
3812 fmt->parse(stringToBeParsed, result, status);
3813 logln((UnicodeString)"Input: " + stringToBeParsed + "; output: " + result.getDouble(status));
3814 if (U_FAILURE(status) ||
3815 (result.getType() == Formattable::kDouble &&
3816 result.getDouble() != parsedResult) ||
3817 (result.getType() == Formattable::kLong &&
3818 result.getLong() != parsedResult)) {
3819 errln((UnicodeString)"FAIL parse: Expected " + parsedResult);
3820 }
3821 }
3822 delete fmt;
3823 }
3824
3825
3826 void
TestCurrencyIsoPluralFormat()3827 NumberFormatTest::TestCurrencyIsoPluralFormat() {
3828 static const char* DATA[][6] = {
3829 // the data are:
3830 // locale,
3831 // currency amount to be formatted,
3832 // currency ISO code to be formatted,
3833 // format result using CURRENCYSTYLE,
3834 // format result using ISOCURRENCYSTYLE,
3835 // format result using PLURALCURRENCYSTYLE,
3836
3837 {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3838 {"en_US", "1234.56", "USD", "$1,234.56", "USD\\u00A01,234.56", "1,234.56 US dollars"},
3839 {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD\\u00A01,234.56", "-1,234.56 US dollars"},
3840 {"zh_CN", "1", "USD", "US$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7F8E\\u5143"},
3841 {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD\\u00A01,234.56", "1,234.56\\u00A0\\u7F8E\\u5143"},
3842 {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A01.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3843 {"zh_CN", "1234.56", "CNY", "\\u00A51,234.56", "CNY\\u00A01,234.56", "1,234.56\\u00A0\\u4EBA\\u6C11\\u5E01"},
3844 {"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3845 {"ru_RU", "2", "RUB", "2,00\\u00A0\\u20BD", "2,00\\u00A0RUB", "2,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3846 {"ru_RU", "5", "RUB", "5,00\\u00A0\\u20BD", "5,00\\u00A0RUB", "5,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3847 // test locale without currency information
3848 {"root", "-1.23", "USD", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"},
3849 // test choice format
3850 {"es_AR", "1", "INR", "INR\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"},
3851 };
3852 static const UNumberFormatStyle currencyStyles[] = {
3853 UNUM_CURRENCY,
3854 UNUM_CURRENCY_ISO,
3855 UNUM_CURRENCY_PLURAL
3856 };
3857
3858 for (int32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3859 const char* localeString = DATA[i][0];
3860 double numberToBeFormat = atof(DATA[i][1]);
3861 const char* currencyISOCode = DATA[i][2];
3862 logln(UnicodeString(u"Locale: ") + localeString + "; amount: " + numberToBeFormat);
3863 Locale locale(localeString);
3864 for (int32_t kIndex = 0; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3865 UNumberFormatStyle k = currencyStyles[kIndex];
3866 logln(UnicodeString(u"UNumberFormatStyle: ") + k);
3867 UErrorCode status = U_ZERO_ERROR;
3868 NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3869 if (U_FAILURE(status)) {
3870 delete numFmt;
3871 dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3872 continue;
3873 }
3874 UChar currencyCode[4];
3875 u_charsToUChars(currencyISOCode, currencyCode, 4);
3876 numFmt->setCurrency(currencyCode, status);
3877 if (U_FAILURE(status)) {
3878 delete numFmt;
3879 errln((UnicodeString)"can not set currency:" + currencyISOCode);
3880 continue;
3881 }
3882
3883 UnicodeString strBuf;
3884 numFmt->format(numberToBeFormat, strBuf);
3885 int resultDataIndex = 3 + kIndex;
3886 // DATA[i][resultDataIndex] is the currency format result
3887 // using 'k' currency style.
3888 UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
3889 if (strBuf.compare(formatResult)) {
3890 errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
3891 }
3892 // test parsing, and test parsing for all currency formats.
3893 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3894 numFmt->setLenient(TRUE);
3895 for (int j = 3; j < 6; ++j) {
3896 // DATA[i][3] is the currency format result using
3897 // CURRENCYSTYLE formatter.
3898 // DATA[i][4] is the currency format result using
3899 // ISOCURRENCYSTYLE formatter.
3900 // DATA[i][5] is the currency format result using
3901 // PLURALCURRENCYSTYLE formatter.
3902 UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
3903 UErrorCode status = U_ZERO_ERROR;
3904 Formattable parseResult;
3905 numFmt->parse(oneCurrencyFormatResult, parseResult, status);
3906 if (U_FAILURE(status) ||
3907 (parseResult.getType() == Formattable::kDouble &&
3908 parseResult.getDouble() != numberToBeFormat) ||
3909 (parseResult.getType() == Formattable::kLong &&
3910 parseResult.getLong() != numberToBeFormat)) {
3911 errln((UnicodeString)"FAIL: getCurrencyFormat of locale " +
3912 localeString + " failed roundtripping the number");
3913 if (parseResult.getType() == Formattable::kDouble) {
3914 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getDouble());
3915 } else {
3916 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getLong());
3917 }
3918 }
3919 }
3920 delete numFmt;
3921 }
3922 }
3923 }
3924
3925 void
TestCurrencyParsing()3926 NumberFormatTest::TestCurrencyParsing() {
3927 static const char* DATA[][6] = {
3928 // the data are:
3929 // locale,
3930 // currency amount to be formatted,
3931 // currency ISO code to be formatted,
3932 // format result using CURRENCYSTYLE,
3933 // format result using ISOCURRENCYSTYLE,
3934 // format result using PLURALCURRENCYSTYLE,
3935 {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3936 {"pa_IN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\u0a2f\\u0a42.\\u0a10\\u0a38. \\u0a21\\u0a3e\\u0a32\\u0a30"},
3937 {"es_AR", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 d\\u00f3lar estadounidense"},
3938 {"ar_EG", "1", "USD", "\\u0661\\u066b\\u0660\\u0660\\u00a0US$", "\\u0661\\u066b\\u0660\\u0660\\u00a0USD", "\\u0661\\u066b\\u0660\\u0660 \\u062f\\u0648\\u0644\\u0627\\u0631 \\u0623\\u0645\\u0631\\u064a\\u0643\\u064a"},
3939 {"fa_CA", "1", "USD", "\\u200e$\\u06f1\\u066b\\u06f0\\u06f0", "\\u200eUSD\\u06f1\\u066b\\u06f0\\u06f0", "\\u06f1\\u066b\\u06f0\\u06f0 \\u062f\\u0644\\u0627\\u0631 \\u0627\\u0645\\u0631\\u06cc\\u06a9\\u0627"},
3940 {"he_IL", "1", "USD", "\\u200f1.00\\u00a0$", "\\u200f1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
3941 {"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 ameri\\u010Dkih dolara"},
3942 {"id_ID", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 Dolar Amerika Serikat"},
3943 {"it_IT", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 dollari statunitensi"},
3944 {"ko_KR", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
3945 {"ja_JP", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7c73\\u30c9\\u30eb"},
3946 {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A001.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3947 {"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3948 {"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3949 {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1 \\u65E5\\u5713"},
3950 {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3951 // ICU 62 requires #parseCurrency() to recognize variants when parsing
3952 // {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3953 {"ru_RU", "1", "RUB", "1,00\\u00A0\\u00A0\\u20BD", "1,00\\u00A0\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"}
3954 };
3955 static const UNumberFormatStyle currencyStyles[] = {
3956 UNUM_CURRENCY,
3957 UNUM_CURRENCY_ISO,
3958 UNUM_CURRENCY_PLURAL
3959 };
3960 static const char* currencyStyleNames[] = {
3961 "UNUM_CURRENCY",
3962 "UNUM_CURRENCY_ISO",
3963 "UNUM_CURRENCY_PLURAL"
3964 };
3965
3966 #ifdef NUMFMTST_CACHE_DEBUG
3967 int deadloop = 0;
3968 for (;;) {
3969 printf("loop: %d\n", deadloop++);
3970 #endif
3971 for (uint32_t i=0; i< UPRV_LENGTHOF(DATA); ++i) { /* i = test case # - should be i=0*/
3972 for (int32_t kIndex = 2; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3973 UNumberFormatStyle k = currencyStyles[kIndex]; /* k = style */
3974 const char* localeString = DATA[i][0];
3975 double numberToBeFormat = atof(DATA[i][1]);
3976 const char* currencyISOCode = DATA[i][2];
3977 Locale locale(localeString);
3978 UErrorCode status = U_ZERO_ERROR;
3979 NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3980 logln("#%d NumberFormat(%s, %s) Currency=%s\n",
3981 i, localeString, currencyStyleNames[kIndex],
3982 currencyISOCode);
3983
3984 if (U_FAILURE(status)) {
3985 delete numFmt;
3986 dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3987 continue;
3988 }
3989 UChar currencyCode[4];
3990 u_charsToUChars(currencyISOCode, currencyCode, 4);
3991 numFmt->setCurrency(currencyCode, status);
3992 if (U_FAILURE(status)) {
3993 delete numFmt;
3994 errln((UnicodeString)"can not set currency:" + currencyISOCode);
3995 continue;
3996 }
3997
3998 UnicodeString strBuf;
3999 numFmt->format(numberToBeFormat, strBuf);
4000 int resultDataIndex = 3 + kIndex;
4001 // DATA[i][resultDataIndex] is the currency format result
4002 // using 'k' currency style.
4003 UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
4004 if (strBuf.compare(formatResult)) {
4005 errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
4006 }
4007 // test parsing, and test parsing for all currency formats.
4008 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
4009 numFmt->setLenient(TRUE);
4010 for (int j = 3; j < 6; ++j) {
4011 // DATA[i][3] is the currency format result using
4012 // CURRENCYSTYLE formatter.
4013 // DATA[i][4] is the currency format result using
4014 // ISOCURRENCYSTYLE formatter.
4015 // DATA[i][5] is the currency format result using
4016 // PLURALCURRENCYSTYLE formatter.
4017 UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
4018 UErrorCode status = U_ZERO_ERROR;
4019 Formattable parseResult;
4020 logln("parse(%s)", DATA[i][j]);
4021 numFmt->parse(oneCurrencyFormatResult, parseResult, status);
4022 if (U_FAILURE(status) ||
4023 (parseResult.getType() == Formattable::kDouble &&
4024 parseResult.getDouble() != numberToBeFormat) ||
4025 (parseResult.getType() == Formattable::kLong &&
4026 parseResult.getLong() != numberToBeFormat)) {
4027 errln((UnicodeString)"FAIL: NumberFormat(" + localeString +", " + currencyStyleNames[kIndex] +
4028 "), Currency="+currencyISOCode+", parse("+DATA[i][j]+") returned error " + (UnicodeString)u_errorName(status)+". Testcase: data[" + i + "][" + currencyStyleNames[j-3] +"="+j+"]");
4029 if (parseResult.getType() == Formattable::kDouble) {
4030 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (double): " +parseResult.getDouble());
4031 } else {
4032 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (long): " +parseResult.getLong());
4033 }
4034 errln((UnicodeString)" round-trip would be: " + strBuf);
4035 }
4036 }
4037 delete numFmt;
4038 }
4039 }
4040 #ifdef NUMFMTST_CACHE_DEBUG
4041 }
4042 #endif
4043 }
4044
4045
4046 void
TestParseCurrencyInUCurr()4047 NumberFormatTest::TestParseCurrencyInUCurr() {
4048 const char* DATA[] = {
4049 "1.00 US DOLLAR", // case in-sensitive
4050 "$1.00",
4051 "USD1.00",
4052 "usd1.00", // case in-sensitive: #13696
4053 "US dollar1.00",
4054 "US dollars1.00",
4055 "$1.00",
4056 "A$1.00",
4057 "ADP1.00",
4058 "ADP1.00",
4059 "AED1.00",
4060 "AED1.00",
4061 "AFA1.00",
4062 "AFA1.00",
4063 "AFN1.00",
4064 "ALL1.00",
4065 "AMD1.00",
4066 "ANG1.00",
4067 "AOA1.00",
4068 "AOK1.00",
4069 "AOK1.00",
4070 "AON1.00",
4071 "AON1.00",
4072 "AOR1.00",
4073 "AOR1.00",
4074 "ARS1.00",
4075 "ARA1.00",
4076 "ARA1.00",
4077 "ARP1.00",
4078 "ARP1.00",
4079 "ARS1.00",
4080 "ATS1.00",
4081 "ATS1.00",
4082 "AUD1.00",
4083 "AWG1.00",
4084 "AZM1.00",
4085 "AZM1.00",
4086 "AZN1.00",
4087 "Afghan Afghani (1927\\u20132002)1.00",
4088 "Afghan afghani (1927\\u20132002)1.00",
4089 "Afghan Afghani1.00",
4090 "Afghan Afghanis1.00",
4091 "Albanian Lek1.00",
4092 "Albanian lek1.00",
4093 "Albanian lek\\u00eb1.00",
4094 "Algerian Dinar1.00",
4095 "Algerian dinar1.00",
4096 "Algerian dinars1.00",
4097 "Andorran Peseta1.00",
4098 "Andorran peseta1.00",
4099 "Andorran pesetas1.00",
4100 "Angolan Kwanza (1977\\u20131991)1.00",
4101 "Angolan Readjusted Kwanza (1995\\u20131999)1.00",
4102 "Angolan Kwanza1.00",
4103 "Angolan New Kwanza (1990\\u20132000)1.00",
4104 "Angolan kwanza (1977\\u20131991)1.00",
4105 "Angolan readjusted kwanza (1995\\u20131999)1.00",
4106 "Angolan kwanza1.00",
4107 "Angolan kwanzas (1977\\u20131991)1.00",
4108 "Angolan readjusted kwanzas (1995\\u20131999)1.00",
4109 "Angolan kwanzas1.00",
4110 "Angolan new kwanza (1990\\u20132000)1.00",
4111 "Angolan new kwanzas (1990\\u20132000)1.00",
4112 "Argentine Austral1.00",
4113 "Argentine Peso (1983\\u20131985)1.00",
4114 "Argentine Peso1.00",
4115 "Argentine austral1.00",
4116 "Argentine australs1.00",
4117 "Argentine peso (1983\\u20131985)1.00",
4118 "Argentine peso1.00",
4119 "Argentine pesos (1983\\u20131985)1.00",
4120 "Argentine pesos1.00",
4121 "Armenian Dram1.00",
4122 "Armenian dram1.00",
4123 "Armenian drams1.00",
4124 "Aruban Florin1.00",
4125 "Aruban florin1.00",
4126 "Australian Dollar1.00",
4127 "Australian dollar1.00",
4128 "Australian dollars1.00",
4129 "Austrian Schilling1.00",
4130 "Austrian schilling1.00",
4131 "Austrian schillings1.00",
4132 "Azerbaijani Manat (1993\\u20132006)1.00",
4133 "Azerbaijani Manat1.00",
4134 "Azerbaijani manat (1993\\u20132006)1.00",
4135 "Azerbaijani manat1.00",
4136 "Azerbaijani manats (1993\\u20132006)1.00",
4137 "Azerbaijani manats1.00",
4138 "BAD1.00",
4139 "BAD1.00",
4140 "BAM1.00",
4141 "BBD1.00",
4142 "BDT1.00",
4143 "BEC1.00",
4144 "BEC1.00",
4145 "BEF1.00",
4146 "BEL1.00",
4147 "BEL1.00",
4148 "BGL1.00",
4149 "BGN1.00",
4150 "BGN1.00",
4151 "BHD1.00",
4152 "BIF1.00",
4153 "BMD1.00",
4154 "BND1.00",
4155 "BOB1.00",
4156 "BOP1.00",
4157 "BOP1.00",
4158 "BOV1.00",
4159 "BOV1.00",
4160 "BRB1.00",
4161 "BRB1.00",
4162 "BRC1.00",
4163 "BRC1.00",
4164 "BRE1.00",
4165 "BRE1.00",
4166 "BRL1.00",
4167 "BRN1.00",
4168 "BRN1.00",
4169 "BRR1.00",
4170 "BRR1.00",
4171 "BSD1.00",
4172 "BSD1.00",
4173 "BTN1.00",
4174 "BUK1.00",
4175 "BUK1.00",
4176 "BWP1.00",
4177 "BYB1.00",
4178 "BYB1.00",
4179 "BYR1.00",
4180 "BZD1.00",
4181 "Bahamian Dollar1.00",
4182 "Bahamian dollar1.00",
4183 "Bahamian dollars1.00",
4184 "Bahraini Dinar1.00",
4185 "Bahraini dinar1.00",
4186 "Bahraini dinars1.00",
4187 "Bangladeshi Taka1.00",
4188 "Bangladeshi taka1.00",
4189 "Bangladeshi takas1.00",
4190 "Barbadian Dollar1.00",
4191 "Barbadian dollar1.00",
4192 "Barbadian dollars1.00",
4193 "Belarusian Ruble (1994\\u20131999)1.00",
4194 "Belarusian Ruble1.00",
4195 "Belarusian ruble (1994\\u20131999)1.00",
4196 "Belarusian rubles (1994\\u20131999)1.00",
4197 "Belarusian ruble1.00",
4198 "Belarusian rubles1.00",
4199 "Belgian Franc (convertible)1.00",
4200 "Belgian Franc (financial)1.00",
4201 "Belgian Franc1.00",
4202 "Belgian franc (convertible)1.00",
4203 "Belgian franc (financial)1.00",
4204 "Belgian franc1.00",
4205 "Belgian francs (convertible)1.00",
4206 "Belgian francs (financial)1.00",
4207 "Belgian francs1.00",
4208 "Belize Dollar1.00",
4209 "Belize dollar1.00",
4210 "Belize dollars1.00",
4211 "Bermudan Dollar1.00",
4212 "Bermudan dollar1.00",
4213 "Bermudan dollars1.00",
4214 "Bhutanese Ngultrum1.00",
4215 "Bhutanese ngultrum1.00",
4216 "Bhutanese ngultrums1.00",
4217 "Bolivian Mvdol1.00",
4218 "Bolivian Peso1.00",
4219 "Bolivian mvdol1.00",
4220 "Bolivian mvdols1.00",
4221 "Bolivian peso1.00",
4222 "Bolivian pesos1.00",
4223 "Bolivian Boliviano1.00",
4224 "Bolivian Boliviano1.00",
4225 "Bolivian Bolivianos1.00",
4226 "Bosnia-Herzegovina Convertible Mark1.00",
4227 "Bosnia-Herzegovina Dinar (1992\\u20131994)1.00",
4228 "Bosnia-Herzegovina convertible mark1.00",
4229 "Bosnia-Herzegovina convertible marks1.00",
4230 "Bosnia-Herzegovina dinar (1992\\u20131994)1.00",
4231 "Bosnia-Herzegovina dinars (1992\\u20131994)1.00",
4232 "Botswanan Pula1.00",
4233 "Botswanan pula1.00",
4234 "Botswanan pulas1.00",
4235 "Brazilian New Cruzado (1989\\u20131990)1.00",
4236 "Brazilian Cruzado (1986\\u20131989)1.00",
4237 "Brazilian Cruzeiro (1990\\u20131993)1.00",
4238 "Brazilian New Cruzeiro (1967\\u20131986)1.00",
4239 "Brazilian Cruzeiro (1993\\u20131994)1.00",
4240 "Brazilian Real1.00",
4241 "Brazilian new cruzado (1989\\u20131990)1.00",
4242 "Brazilian new cruzados (1989\\u20131990)1.00",
4243 "Brazilian cruzado (1986\\u20131989)1.00",
4244 "Brazilian cruzados (1986\\u20131989)1.00",
4245 "Brazilian cruzeiro (1990\\u20131993)1.00",
4246 "Brazilian new cruzeiro (1967\\u20131986)1.00",
4247 "Brazilian cruzeiro (1993\\u20131994)1.00",
4248 "Brazilian cruzeiros (1990\\u20131993)1.00",
4249 "Brazilian new cruzeiros (1967\\u20131986)1.00",
4250 "Brazilian cruzeiros (1993\\u20131994)1.00",
4251 "Brazilian real1.00",
4252 "Brazilian reals1.00",
4253 "British Pound1.00",
4254 "British pound1.00",
4255 "British pounds1.00",
4256 "Brunei Dollar1.00",
4257 "Brunei dollar1.00",
4258 "Brunei dollars1.00",
4259 "Bulgarian Hard Lev1.00",
4260 "Bulgarian Lev1.00",
4261 "Bulgarian Leva1.00",
4262 "Bulgarian hard lev1.00",
4263 "Bulgarian hard leva1.00",
4264 "Bulgarian lev1.00",
4265 "Burmese Kyat1.00",
4266 "Burmese kyat1.00",
4267 "Burmese kyats1.00",
4268 "Burundian Franc1.00",
4269 "Burundian franc1.00",
4270 "Burundian francs1.00",
4271 "CA$1.00",
4272 "CAD1.00",
4273 "CDF1.00",
4274 "CDF1.00",
4275 "West African CFA Franc1.00",
4276 "Central African CFA Franc1.00",
4277 "West African CFA franc1.00",
4278 "Central African CFA franc1.00",
4279 "West African CFA francs1.00",
4280 "Central African CFA francs1.00",
4281 "CFP Franc1.00",
4282 "CFP franc1.00",
4283 "CFP francs1.00",
4284 "CFPF1.00",
4285 "CHE1.00",
4286 "CHE1.00",
4287 "CHF1.00",
4288 "CHW1.00",
4289 "CHW1.00",
4290 "CLF1.00",
4291 "CLF1.00",
4292 "CLP1.00",
4293 "CNY1.00",
4294 "COP1.00",
4295 "COU1.00",
4296 "COU1.00",
4297 "CRC1.00",
4298 "CSD1.00",
4299 "CSD1.00",
4300 "CSK1.00",
4301 "CSK1.00",
4302 "CUP1.00",
4303 "CUP1.00",
4304 "CVE1.00",
4305 "CYP1.00",
4306 "CZK1.00",
4307 "Cambodian Riel1.00",
4308 "Cambodian riel1.00",
4309 "Cambodian riels1.00",
4310 "Canadian Dollar1.00",
4311 "Canadian dollar1.00",
4312 "Canadian dollars1.00",
4313 "Cape Verdean Escudo1.00",
4314 "Cape Verdean escudo1.00",
4315 "Cape Verdean escudos1.00",
4316 "Cayman Islands Dollar1.00",
4317 "Cayman Islands dollar1.00",
4318 "Cayman Islands dollars1.00",
4319 "Chilean Peso1.00",
4320 "Chilean Unit of Account (UF)1.00",
4321 "Chilean peso1.00",
4322 "Chilean pesos1.00",
4323 "Chilean unit of account (UF)1.00",
4324 "Chilean units of account (UF)1.00",
4325 "Chinese Yuan1.00",
4326 "Chinese yuan1.00",
4327 "Colombian Peso1.00",
4328 "Colombian peso1.00",
4329 "Colombian pesos1.00",
4330 "Comorian Franc1.00",
4331 "Comorian franc1.00",
4332 "Comorian francs1.00",
4333 "Congolese Franc1.00",
4334 "Congolese franc1.00",
4335 "Congolese francs1.00",
4336 "Costa Rican Col\\u00f3n1.00",
4337 "Costa Rican col\\u00f3n1.00",
4338 "Costa Rican col\\u00f3ns1.00",
4339 "Croatian Dinar1.00",
4340 "Croatian Kuna1.00",
4341 "Croatian dinar1.00",
4342 "Croatian dinars1.00",
4343 "Croatian kuna1.00",
4344 "Croatian kunas1.00",
4345 "Cuban Peso1.00",
4346 "Cuban peso1.00",
4347 "Cuban pesos1.00",
4348 "Cypriot Pound1.00",
4349 "Cypriot pound1.00",
4350 "Cypriot pounds1.00",
4351 "Czech Koruna1.00",
4352 "Czech koruna1.00",
4353 "Czech korunas1.00",
4354 "Czechoslovak Hard Koruna1.00",
4355 "Czechoslovak hard koruna1.00",
4356 "Czechoslovak hard korunas1.00",
4357 "DDM1.00",
4358 "DDM1.00",
4359 "DEM1.00",
4360 "DEM1.00",
4361 "DJF1.00",
4362 "DKK1.00",
4363 "DOP1.00",
4364 "DZD1.00",
4365 "Danish Krone1.00",
4366 "Danish krone1.00",
4367 "Danish kroner1.00",
4368 "German Mark1.00",
4369 "German mark1.00",
4370 "German marks1.00",
4371 "Djiboutian Franc1.00",
4372 "Djiboutian franc1.00",
4373 "Djiboutian francs1.00",
4374 "Dominican Peso1.00",
4375 "Dominican peso1.00",
4376 "Dominican pesos1.00",
4377 "EC$1.00",
4378 "ECS1.00",
4379 "ECS1.00",
4380 "ECV1.00",
4381 "ECV1.00",
4382 "EEK1.00",
4383 "EEK1.00",
4384 "EGP1.00",
4385 "EGP1.00",
4386 "ERN1.00",
4387 "ERN1.00",
4388 "ESA1.00",
4389 "ESA1.00",
4390 "ESB1.00",
4391 "ESB1.00",
4392 "ESP1.00",
4393 "ETB1.00",
4394 "EUR1.00",
4395 "East Caribbean Dollar1.00",
4396 "East Caribbean dollar1.00",
4397 "East Caribbean dollars1.00",
4398 "East German Mark1.00",
4399 "East German mark1.00",
4400 "East German marks1.00",
4401 "Ecuadorian Sucre1.00",
4402 "Ecuadorian Unit of Constant Value1.00",
4403 "Ecuadorian sucre1.00",
4404 "Ecuadorian sucres1.00",
4405 "Ecuadorian unit of constant value1.00",
4406 "Ecuadorian units of constant value1.00",
4407 "Egyptian Pound1.00",
4408 "Egyptian pound1.00",
4409 "Egyptian pounds1.00",
4410 "Salvadoran Col\\u00f3n1.00",
4411 "Salvadoran col\\u00f3n1.00",
4412 "Salvadoran colones1.00",
4413 "Equatorial Guinean Ekwele1.00",
4414 "Equatorial Guinean ekwele1.00",
4415 "Eritrean Nakfa1.00",
4416 "Eritrean nakfa1.00",
4417 "Eritrean nakfas1.00",
4418 "Estonian Kroon1.00",
4419 "Estonian kroon1.00",
4420 "Estonian kroons1.00",
4421 "Ethiopian Birr1.00",
4422 "Ethiopian birr1.00",
4423 "Ethiopian birrs1.00",
4424 "Euro1.00",
4425 "European Composite Unit1.00",
4426 "European Currency Unit1.00",
4427 "European Monetary Unit1.00",
4428 "European Unit of Account (XBC)1.00",
4429 "European Unit of Account (XBD)1.00",
4430 "European composite unit1.00",
4431 "European composite units1.00",
4432 "European currency unit1.00",
4433 "European currency units1.00",
4434 "European monetary unit1.00",
4435 "European monetary units1.00",
4436 "European unit of account (XBC)1.00",
4437 "European unit of account (XBD)1.00",
4438 "European units of account (XBC)1.00",
4439 "European units of account (XBD)1.00",
4440 "FIM1.00",
4441 "FIM1.00",
4442 "FJD1.00",
4443 "FKP1.00",
4444 "FKP1.00",
4445 "FRF1.00",
4446 "FRF1.00",
4447 "Falkland Islands Pound1.00",
4448 "Falkland Islands pound1.00",
4449 "Falkland Islands pounds1.00",
4450 "Fijian Dollar1.00",
4451 "Fijian dollar1.00",
4452 "Fijian dollars1.00",
4453 "Finnish Markka1.00",
4454 "Finnish markka1.00",
4455 "Finnish markkas1.00",
4456 "CHF1.00",
4457 "French Franc1.00",
4458 "French Gold Franc1.00",
4459 "French UIC-Franc1.00",
4460 "French UIC-franc1.00",
4461 "French UIC-francs1.00",
4462 "French franc1.00",
4463 "French francs1.00",
4464 "French gold franc1.00",
4465 "French gold francs1.00",
4466 "GBP1.00",
4467 "GEK1.00",
4468 "GEK1.00",
4469 "GEL1.00",
4470 "GHC1.00",
4471 "GHC1.00",
4472 "GHS1.00",
4473 "GIP1.00",
4474 "GIP1.00",
4475 "GMD1.00",
4476 "GMD1.00",
4477 "GNF1.00",
4478 "GNS1.00",
4479 "GNS1.00",
4480 "GQE1.00",
4481 "GQE1.00",
4482 "GRD1.00",
4483 "GRD1.00",
4484 "GTQ1.00",
4485 "GWE1.00",
4486 "GWE1.00",
4487 "GWP1.00",
4488 "GWP1.00",
4489 "GYD1.00",
4490 "Gambian Dalasi1.00",
4491 "Gambian dalasi1.00",
4492 "Gambian dalasis1.00",
4493 "Georgian Kupon Larit1.00",
4494 "Georgian Lari1.00",
4495 "Georgian kupon larit1.00",
4496 "Georgian kupon larits1.00",
4497 "Georgian lari1.00",
4498 "Georgian laris1.00",
4499 "Ghanaian Cedi (1979\\u20132007)1.00",
4500 "Ghanaian Cedi1.00",
4501 "Ghanaian cedi (1979\\u20132007)1.00",
4502 "Ghanaian cedi1.00",
4503 "Ghanaian cedis (1979\\u20132007)1.00",
4504 "Ghanaian cedis1.00",
4505 "Gibraltar Pound1.00",
4506 "Gibraltar pound1.00",
4507 "Gibraltar pounds1.00",
4508 "Gold1.00",
4509 "Gold1.00",
4510 "Greek Drachma1.00",
4511 "Greek drachma1.00",
4512 "Greek drachmas1.00",
4513 "Guatemalan Quetzal1.00",
4514 "Guatemalan quetzal1.00",
4515 "Guatemalan quetzals1.00",
4516 "Guinean Franc1.00",
4517 "Guinean Syli1.00",
4518 "Guinean franc1.00",
4519 "Guinean francs1.00",
4520 "Guinean syli1.00",
4521 "Guinean sylis1.00",
4522 "Guinea-Bissau Peso1.00",
4523 "Guinea-Bissau peso1.00",
4524 "Guinea-Bissau pesos1.00",
4525 "Guyanaese Dollar1.00",
4526 "Guyanaese dollar1.00",
4527 "Guyanaese dollars1.00",
4528 "HK$1.00",
4529 "HKD1.00",
4530 "HNL1.00",
4531 "HRD1.00",
4532 "HRD1.00",
4533 "HRK1.00",
4534 "HRK1.00",
4535 "HTG1.00",
4536 "HTG1.00",
4537 "HUF1.00",
4538 "Haitian Gourde1.00",
4539 "Haitian gourde1.00",
4540 "Haitian gourdes1.00",
4541 "Honduran Lempira1.00",
4542 "Honduran lempira1.00",
4543 "Honduran lempiras1.00",
4544 "Hong Kong Dollar1.00",
4545 "Hong Kong dollar1.00",
4546 "Hong Kong dollars1.00",
4547 "Hungarian Forint1.00",
4548 "Hungarian forint1.00",
4549 "Hungarian forints1.00",
4550 "IDR1.00",
4551 "IEP1.00",
4552 "ILP1.00",
4553 "ILP1.00",
4554 "ILS1.00",
4555 "INR1.00",
4556 "IQD1.00",
4557 "IRR1.00",
4558 "ISK1.00",
4559 "ISK1.00",
4560 "ITL1.00",
4561 "Icelandic Kr\\u00f3na1.00",
4562 "Icelandic kr\\u00f3na1.00",
4563 "Icelandic kr\\u00f3nur1.00",
4564 "Indian Rupee1.00",
4565 "Indian rupee1.00",
4566 "Indian rupees1.00",
4567 "Indonesian Rupiah1.00",
4568 "Indonesian rupiah1.00",
4569 "Indonesian rupiahs1.00",
4570 "Iranian Rial1.00",
4571 "Iranian rial1.00",
4572 "Iranian rials1.00",
4573 "Iraqi Dinar1.00",
4574 "Iraqi dinar1.00",
4575 "Iraqi dinars1.00",
4576 "Irish Pound1.00",
4577 "Irish pound1.00",
4578 "Irish pounds1.00",
4579 "Israeli Pound1.00",
4580 "Israeli new shekel1.00",
4581 "Israeli pound1.00",
4582 "Israeli pounds1.00",
4583 "Italian Lira1.00",
4584 "Italian lira1.00",
4585 "Italian liras1.00",
4586 "JMD1.00",
4587 "JOD1.00",
4588 "JPY1.00",
4589 "Jamaican Dollar1.00",
4590 "Jamaican dollar1.00",
4591 "Jamaican dollars1.00",
4592 "Japanese Yen1.00",
4593 "Japanese yen1.00",
4594 "Jordanian Dinar1.00",
4595 "Jordanian dinar1.00",
4596 "Jordanian dinars1.00",
4597 "KES1.00",
4598 "KGS1.00",
4599 "KHR1.00",
4600 "KMF1.00",
4601 "KPW1.00",
4602 "KPW1.00",
4603 "KRW1.00",
4604 "KWD1.00",
4605 "KYD1.00",
4606 "KYD1.00",
4607 "KZT1.00",
4608 "Kazakhstani Tenge1.00",
4609 "Kazakhstani tenge1.00",
4610 "Kazakhstani tenges1.00",
4611 "Kenyan Shilling1.00",
4612 "Kenyan shilling1.00",
4613 "Kenyan shillings1.00",
4614 "Kuwaiti Dinar1.00",
4615 "Kuwaiti dinar1.00",
4616 "Kuwaiti dinars1.00",
4617 "Kyrgystani Som1.00",
4618 "Kyrgystani som1.00",
4619 "Kyrgystani soms1.00",
4620 "HNL1.00",
4621 "LAK1.00",
4622 "LAK1.00",
4623 "LBP1.00",
4624 "LKR1.00",
4625 "LRD1.00",
4626 "LRD1.00",
4627 "LSL1.00",
4628 "LTL1.00",
4629 "LTL1.00",
4630 "LTT1.00",
4631 "LTT1.00",
4632 "LUC1.00",
4633 "LUC1.00",
4634 "LUF1.00",
4635 "LUF1.00",
4636 "LUL1.00",
4637 "LUL1.00",
4638 "LVL1.00",
4639 "LVL1.00",
4640 "LVR1.00",
4641 "LVR1.00",
4642 "LYD1.00",
4643 "Laotian Kip1.00",
4644 "Laotian kip1.00",
4645 "Laotian kips1.00",
4646 "Latvian Lats1.00",
4647 "Latvian Ruble1.00",
4648 "Latvian lats1.00",
4649 "Latvian lati1.00",
4650 "Latvian ruble1.00",
4651 "Latvian rubles1.00",
4652 "Lebanese Pound1.00",
4653 "Lebanese pound1.00",
4654 "Lebanese pounds1.00",
4655 "Lesotho Loti1.00",
4656 "Lesotho loti1.00",
4657 "Lesotho lotis1.00",
4658 "Liberian Dollar1.00",
4659 "Liberian dollar1.00",
4660 "Liberian dollars1.00",
4661 "Libyan Dinar1.00",
4662 "Libyan dinar1.00",
4663 "Libyan dinars1.00",
4664 "Lithuanian Litas1.00",
4665 "Lithuanian Talonas1.00",
4666 "Lithuanian litas1.00",
4667 "Lithuanian litai1.00",
4668 "Lithuanian talonas1.00",
4669 "Lithuanian talonases1.00",
4670 "Luxembourgian Convertible Franc1.00",
4671 "Luxembourg Financial Franc1.00",
4672 "Luxembourgian Franc1.00",
4673 "Luxembourgian convertible franc1.00",
4674 "Luxembourgian convertible francs1.00",
4675 "Luxembourg financial franc1.00",
4676 "Luxembourg financial francs1.00",
4677 "Luxembourgian franc1.00",
4678 "Luxembourgian francs1.00",
4679 "MAD1.00",
4680 "MAD1.00",
4681 "MAF1.00",
4682 "MAF1.00",
4683 "MDL1.00",
4684 "MDL1.00",
4685 "MX$1.00",
4686 "MGA1.00",
4687 "MGA1.00",
4688 "MGF1.00",
4689 "MGF1.00",
4690 "MKD1.00",
4691 "MLF1.00",
4692 "MLF1.00",
4693 "MMK1.00",
4694 "MMK1.00",
4695 "MNT1.00",
4696 "MOP1.00",
4697 "MOP1.00",
4698 "MRO1.00",
4699 "MTL1.00",
4700 "MTP1.00",
4701 "MTP1.00",
4702 "MUR1.00",
4703 "MUR1.00",
4704 "MVR1.00",
4705 "MVR1.00",
4706 "MWK1.00",
4707 "MXN1.00",
4708 "MXP1.00",
4709 "MXP1.00",
4710 "MXV1.00",
4711 "MXV1.00",
4712 "MYR1.00",
4713 "MZE1.00",
4714 "MZE1.00",
4715 "MZM1.00",
4716 "MZN1.00",
4717 "Macanese Pataca1.00",
4718 "Macanese pataca1.00",
4719 "Macanese patacas1.00",
4720 "Macedonian Denar1.00",
4721 "Macedonian denar1.00",
4722 "Macedonian denari1.00",
4723 "Malagasy Ariaries1.00",
4724 "Malagasy Ariary1.00",
4725 "Malagasy Ariary1.00",
4726 "Malagasy Franc1.00",
4727 "Malagasy franc1.00",
4728 "Malagasy francs1.00",
4729 "Malawian Kwacha1.00",
4730 "Malawian Kwacha1.00",
4731 "Malawian Kwachas1.00",
4732 "Malaysian Ringgit1.00",
4733 "Malaysian ringgit1.00",
4734 "Malaysian ringgits1.00",
4735 "Maldivian Rufiyaa1.00",
4736 "Maldivian rufiyaa1.00",
4737 "Maldivian rufiyaas1.00",
4738 "Malian Franc1.00",
4739 "Malian franc1.00",
4740 "Malian francs1.00",
4741 "Maltese Lira1.00",
4742 "Maltese Pound1.00",
4743 "Maltese lira1.00",
4744 "Maltese lira1.00",
4745 "Maltese pound1.00",
4746 "Maltese pounds1.00",
4747 "Mauritanian Ouguiya1.00",
4748 "Mauritanian ouguiya1.00",
4749 "Mauritanian ouguiyas1.00",
4750 "Mauritian Rupee1.00",
4751 "Mauritian rupee1.00",
4752 "Mauritian rupees1.00",
4753 "Mexican Peso1.00",
4754 "Mexican Silver Peso (1861\\u20131992)1.00",
4755 "Mexican Investment Unit1.00",
4756 "Mexican peso1.00",
4757 "Mexican pesos1.00",
4758 "Mexican silver peso (1861\\u20131992)1.00",
4759 "Mexican silver pesos (1861\\u20131992)1.00",
4760 "Mexican investment unit1.00",
4761 "Mexican investment units1.00",
4762 "Moldovan Leu1.00",
4763 "Moldovan leu1.00",
4764 "Moldovan lei1.00",
4765 "Mongolian Tugrik1.00",
4766 "Mongolian tugrik1.00",
4767 "Mongolian tugriks1.00",
4768 "Moroccan Dirham1.00",
4769 "Moroccan Franc1.00",
4770 "Moroccan dirham1.00",
4771 "Moroccan dirhams1.00",
4772 "Moroccan franc1.00",
4773 "Moroccan francs1.00",
4774 "Mozambican Escudo1.00",
4775 "Mozambican Metical1.00",
4776 "Mozambican escudo1.00",
4777 "Mozambican escudos1.00",
4778 "Mozambican metical1.00",
4779 "Mozambican meticals1.00",
4780 "Myanmar Kyat1.00",
4781 "Myanmar kyat1.00",
4782 "Myanmar kyats1.00",
4783 "NAD1.00",
4784 "NGN1.00",
4785 "NIC1.00",
4786 "NIO1.00",
4787 "NIO1.00",
4788 "NLG1.00",
4789 "NLG1.00",
4790 "NOK1.00",
4791 "NPR1.00",
4792 "NT$1.00",
4793 "NZ$1.00",
4794 "NZD1.00",
4795 "Namibian Dollar1.00",
4796 "Namibian dollar1.00",
4797 "Namibian dollars1.00",
4798 "Nepalese Rupee1.00",
4799 "Nepalese rupee1.00",
4800 "Nepalese rupees1.00",
4801 "Netherlands Antillean Guilder1.00",
4802 "Netherlands Antillean guilder1.00",
4803 "Netherlands Antillean guilders1.00",
4804 "Dutch Guilder1.00",
4805 "Dutch guilder1.00",
4806 "Dutch guilders1.00",
4807 "Israeli New Shekel1.00",
4808 "Israeli New Shekels1.00",
4809 "New Zealand Dollar1.00",
4810 "New Zealand dollar1.00",
4811 "New Zealand dollars1.00",
4812 "Nicaraguan C\\u00f3rdoba1.00",
4813 "Nicaraguan C\\u00f3rdoba (1988\\u20131991)1.00",
4814 "Nicaraguan c\\u00f3rdoba1.00",
4815 "Nicaraguan c\\u00f3rdobas1.00",
4816 "Nicaraguan c\\u00f3rdoba (1988\\u20131991)1.00",
4817 "Nicaraguan c\\u00f3rdobas (1988\\u20131991)1.00",
4818 "Nigerian Naira1.00",
4819 "Nigerian naira1.00",
4820 "Nigerian nairas1.00",
4821 "North Korean Won1.00",
4822 "North Korean won1.00",
4823 "North Korean won1.00",
4824 "Norwegian Krone1.00",
4825 "Norwegian krone1.00",
4826 "Norwegian kroner1.00",
4827 "OMR1.00",
4828 "Mozambican Metical (1980\\u20132006)1.00",
4829 "Mozambican metical (1980\\u20132006)1.00",
4830 "Mozambican meticals (1980\\u20132006)1.00",
4831 "Romanian Lei (1952\\u20132006)1.00",
4832 "Romanian Leu (1952\\u20132006)1.00",
4833 "Romanian leu (1952\\u20132006)1.00",
4834 "Serbian Dinar (2002\\u20132006)1.00",
4835 "Serbian dinar (2002\\u20132006)1.00",
4836 "Serbian dinars (2002\\u20132006)1.00",
4837 "Sudanese Dinar (1992\\u20132007)1.00",
4838 "Sudanese Pound (1957\\u20131998)1.00",
4839 "Sudanese dinar (1992\\u20132007)1.00",
4840 "Sudanese dinars (1992\\u20132007)1.00",
4841 "Sudanese pound (1957\\u20131998)1.00",
4842 "Sudanese pounds (1957\\u20131998)1.00",
4843 "Turkish Lira (1922\\u20132005)1.00",
4844 "Turkish Lira (1922\\u20132005)1.00",
4845 "Omani Rial1.00",
4846 "Omani rial1.00",
4847 "Omani rials1.00",
4848 "PAB1.00",
4849 "PAB1.00",
4850 "PEI1.00",
4851 "PEI1.00",
4852 "PEN1.00",
4853 "PEN1.00",
4854 "PES1.00",
4855 "PES1.00",
4856 "PGK1.00",
4857 "PGK1.00",
4858 "PHP1.00",
4859 "PKR1.00",
4860 "PLN1.00",
4861 "PLZ1.00",
4862 "PLZ1.00",
4863 "PTE1.00",
4864 "PTE1.00",
4865 "PYG1.00",
4866 "Pakistani Rupee1.00",
4867 "Pakistani rupee1.00",
4868 "Pakistani rupees1.00",
4869 "Palladium1.00",
4870 "Palladium1.00",
4871 "Panamanian Balboa1.00",
4872 "Panamanian balboa1.00",
4873 "Panamanian balboas1.00",
4874 "Papua New Guinean Kina1.00",
4875 "Papua New Guinean kina1.00",
4876 "Papua New Guinean kina1.00",
4877 "Paraguayan Guarani1.00",
4878 "Paraguayan guarani1.00",
4879 "Paraguayan guaranis1.00",
4880 "Peruvian Inti1.00",
4881 "Peruvian Sol1.00",
4882 "Peruvian Sol (1863\\u20131965)1.00",
4883 "Peruvian inti1.00",
4884 "Peruvian intis1.00",
4885 "Peruvian sol1.00",
4886 "Peruvian soles1.00",
4887 "Peruvian sol (1863\\u20131965)1.00",
4888 "Peruvian soles (1863\\u20131965)1.00",
4889 "Philippine Piso1.00",
4890 "Philippine piso1.00",
4891 "Philippine pisos1.00",
4892 "Platinum1.00",
4893 "Platinum1.00",
4894 "Polish Zloty (1950\\u20131995)1.00",
4895 "Polish Zloty1.00",
4896 "Polish zlotys1.00",
4897 "Polish zloty (PLZ)1.00",
4898 "Polish zloty1.00",
4899 "Polish zlotys (PLZ)1.00",
4900 "Portuguese Escudo1.00",
4901 "Portuguese Guinea Escudo1.00",
4902 "Portuguese Guinea escudo1.00",
4903 "Portuguese Guinea escudos1.00",
4904 "Portuguese escudo1.00",
4905 "Portuguese escudos1.00",
4906 "GTQ1.00",
4907 "QAR1.00",
4908 "Qatari Rial1.00",
4909 "Qatari rial1.00",
4910 "Qatari rials1.00",
4911 "RHD1.00",
4912 "RHD1.00",
4913 "RINET Funds1.00",
4914 "RINET Funds1.00",
4915 "CN\\u00a51.00",
4916 "ROL1.00",
4917 "ROL1.00",
4918 "RON1.00",
4919 "RON1.00",
4920 "RSD1.00",
4921 "RSD1.00",
4922 "RUB1.00",
4923 "RUR1.00",
4924 "RUR1.00",
4925 "RWF1.00",
4926 "RWF1.00",
4927 "Rhodesian Dollar1.00",
4928 "Rhodesian dollar1.00",
4929 "Rhodesian dollars1.00",
4930 "Romanian Leu1.00",
4931 "Romanian lei1.00",
4932 "Romanian leu1.00",
4933 "Russian Ruble (1991\\u20131998)1.00",
4934 "Russian Ruble1.00",
4935 "Russian ruble (1991\\u20131998)1.00",
4936 "Russian ruble1.00",
4937 "Russian rubles (1991\\u20131998)1.00",
4938 "Russian rubles1.00",
4939 "Rwandan Franc1.00",
4940 "Rwandan franc1.00",
4941 "Rwandan francs1.00",
4942 "SAR1.00",
4943 "SBD1.00",
4944 "SCR1.00",
4945 "SDD1.00",
4946 "SDD1.00",
4947 "SDG1.00",
4948 "SDG1.00",
4949 "SDP1.00",
4950 "SDP1.00",
4951 "SEK1.00",
4952 "SGD1.00",
4953 "SHP1.00",
4954 "SHP1.00",
4955 "SIT1.00",
4956 "SIT1.00",
4957 "SKK1.00",
4958 "SLL1.00",
4959 "SLL1.00",
4960 "SOS1.00",
4961 "SRD1.00",
4962 "SRD1.00",
4963 "SRG1.00",
4964 "STD1.00",
4965 "SUR1.00",
4966 "SUR1.00",
4967 "SVC1.00",
4968 "SVC1.00",
4969 "SYP1.00",
4970 "SZL1.00",
4971 "St. Helena Pound1.00",
4972 "St. Helena pound1.00",
4973 "St. Helena pounds1.00",
4974 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra1.00",
4975 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra1.00",
4976 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras1.00",
4977 "Saudi Riyal1.00",
4978 "Saudi riyal1.00",
4979 "Saudi riyals1.00",
4980 "Serbian Dinar1.00",
4981 "Serbian dinar1.00",
4982 "Serbian dinars1.00",
4983 "Seychellois Rupee1.00",
4984 "Seychellois rupee1.00",
4985 "Seychellois rupees1.00",
4986 "Sierra Leonean Leone1.00",
4987 "Sierra Leonean leone1.00",
4988 "Sierra Leonean leones1.00",
4989 "Silver1.00",
4990 "Silver1.00",
4991 "Singapore Dollar1.00",
4992 "Singapore dollar1.00",
4993 "Singapore dollars1.00",
4994 "Slovak Koruna1.00",
4995 "Slovak koruna1.00",
4996 "Slovak korunas1.00",
4997 "Slovenian Tolar1.00",
4998 "Slovenian tolar1.00",
4999 "Slovenian tolars1.00",
5000 "Solomon Islands Dollar1.00",
5001 "Solomon Islands dollar1.00",
5002 "Solomon Islands dollars1.00",
5003 "Somali Shilling1.00",
5004 "Somali shilling1.00",
5005 "Somali shillings1.00",
5006 "South African Rand (financial)1.00",
5007 "South African Rand1.00",
5008 "South African rand (financial)1.00",
5009 "South African rand1.00",
5010 "South African rands (financial)1.00",
5011 "South African rand1.00",
5012 "South Korean Won1.00",
5013 "South Korean won1.00",
5014 "South Korean won1.00",
5015 "Soviet Rouble1.00",
5016 "Soviet rouble1.00",
5017 "Soviet roubles1.00",
5018 "Spanish Peseta (A account)1.00",
5019 "Spanish Peseta (convertible account)1.00",
5020 "Spanish Peseta1.00",
5021 "Spanish peseta (A account)1.00",
5022 "Spanish peseta (convertible account)1.00",
5023 "Spanish peseta1.00",
5024 "Spanish pesetas (A account)1.00",
5025 "Spanish pesetas (convertible account)1.00",
5026 "Spanish pesetas1.00",
5027 "Special Drawing Rights1.00",
5028 "Sri Lankan Rupee1.00",
5029 "Sri Lankan rupee1.00",
5030 "Sri Lankan rupees1.00",
5031 "Sudanese Pound1.00",
5032 "Sudanese pound1.00",
5033 "Sudanese pounds1.00",
5034 "Surinamese Dollar1.00",
5035 "Surinamese dollar1.00",
5036 "Surinamese dollars1.00",
5037 "Surinamese Guilder1.00",
5038 "Surinamese guilder1.00",
5039 "Surinamese guilders1.00",
5040 "Swazi Lilangeni1.00",
5041 "Swazi lilangeni1.00",
5042 "Swazi emalangeni1.00",
5043 "Swedish Krona1.00",
5044 "Swedish krona1.00",
5045 "Swedish kronor1.00",
5046 "Swiss Franc1.00",
5047 "Swiss franc1.00",
5048 "Swiss francs1.00",
5049 "Syrian Pound1.00",
5050 "Syrian pound1.00",
5051 "Syrian pounds1.00",
5052 "THB1.00",
5053 "TJR1.00",
5054 "TJR1.00",
5055 "TJS1.00",
5056 "TJS1.00",
5057 "TMM1.00",
5058 "TMM1.00",
5059 "TND1.00",
5060 "TND1.00",
5061 "TOP1.00",
5062 "TPE1.00",
5063 "TPE1.00",
5064 "TRL1.00",
5065 "TRY1.00",
5066 "TRY1.00",
5067 "TTD1.00",
5068 "TWD1.00",
5069 "TZS1.00",
5070 "New Taiwan Dollar1.00",
5071 "New Taiwan dollar1.00",
5072 "New Taiwan dollars1.00",
5073 "Tajikistani Ruble1.00",
5074 "Tajikistani Somoni1.00",
5075 "Tajikistani ruble1.00",
5076 "Tajikistani rubles1.00",
5077 "Tajikistani somoni1.00",
5078 "Tajikistani somonis1.00",
5079 "Tanzanian Shilling1.00",
5080 "Tanzanian shilling1.00",
5081 "Tanzanian shillings1.00",
5082 "Testing Currency Code1.00",
5083 "Testing Currency Code1.00",
5084 "Thai Baht1.00",
5085 "Thai baht1.00",
5086 "Thai baht1.00",
5087 "Timorese Escudo1.00",
5088 "Timorese escudo1.00",
5089 "Timorese escudos1.00",
5090 "Tongan Pa\\u02bbanga1.00",
5091 "Tongan pa\\u02bbanga1.00",
5092 "Tongan pa\\u02bbanga1.00",
5093 "Trinidad & Tobago Dollar1.00",
5094 "Trinidad & Tobago dollar1.00",
5095 "Trinidad & Tobago dollars1.00",
5096 "Tunisian Dinar1.00",
5097 "Tunisian dinar1.00",
5098 "Tunisian dinars1.00",
5099 "Turkish Lira1.00",
5100 "Turkish Lira1.00",
5101 "Turkish lira1.00",
5102 "Turkmenistani Manat1.00",
5103 "Turkmenistani manat1.00",
5104 "Turkmenistani manat1.00",
5105 "UAE dirham1.00",
5106 "UAE dirhams1.00",
5107 "UAH1.00",
5108 "UAK1.00",
5109 "UAK1.00",
5110 "UGS1.00",
5111 "UGS1.00",
5112 "UGX1.00",
5113 "US Dollar (Next day)1.00",
5114 "US Dollar (Same day)1.00",
5115 "US Dollar1.00",
5116 "US dollar (next day)1.00",
5117 "US dollar (same day)1.00",
5118 "US dollar1.00",
5119 "US dollars (next day)1.00",
5120 "US dollars (same day)1.00",
5121 "US dollars1.00",
5122 "USD1.00",
5123 "USN1.00",
5124 "USN1.00",
5125 "USS1.00",
5126 "USS1.00",
5127 "UYI1.00",
5128 "UYI1.00",
5129 "UYP1.00",
5130 "UYP1.00",
5131 "UYU1.00",
5132 "UZS1.00",
5133 "UZS1.00",
5134 "Ugandan Shilling (1966\\u20131987)1.00",
5135 "Ugandan Shilling1.00",
5136 "Ugandan shilling (1966\\u20131987)1.00",
5137 "Ugandan shilling1.00",
5138 "Ugandan shillings (1966\\u20131987)1.00",
5139 "Ugandan shillings1.00",
5140 "Ukrainian Hryvnia1.00",
5141 "Ukrainian Karbovanets1.00",
5142 "Ukrainian hryvnia1.00",
5143 "Ukrainian hryvnias1.00",
5144 "Ukrainian karbovanets1.00",
5145 "Ukrainian karbovantsiv1.00",
5146 "Colombian Real Value Unit1.00",
5147 "United Arab Emirates Dirham1.00",
5148 "Unknown Currency1.00",
5149 "Uruguayan Peso (1975\\u20131993)1.00",
5150 "Uruguayan Peso1.00",
5151 "Uruguayan Peso (Indexed Units)1.00",
5152 "Uruguayan peso (1975\\u20131993)1.00",
5153 "Uruguayan peso (indexed units)1.00",
5154 "Uruguayan peso1.00",
5155 "Uruguayan pesos (1975\\u20131993)1.00",
5156 "Uruguayan pesos (indexed units)1.00",
5157 "Uruguayan pesos1.00",
5158 "Uzbekistani Som1.00",
5159 "Uzbekistani som1.00",
5160 "Uzbekistani som1.00",
5161 "VEB1.00",
5162 "VEF1.00",
5163 "VND1.00",
5164 "VUV1.00",
5165 "Vanuatu Vatu1.00",
5166 "Vanuatu vatu1.00",
5167 "Vanuatu vatus1.00",
5168 "Venezuelan Bol\\u00edvar1.00",
5169 "Venezuelan Bol\\u00edvar (1871\\u20132008)1.00",
5170 "Venezuelan bol\\u00edvar1.00",
5171 "Venezuelan bol\\u00edvars1.00",
5172 "Venezuelan bol\\u00edvar (1871\\u20132008)1.00",
5173 "Venezuelan bol\\u00edvars (1871\\u20132008)1.00",
5174 "Vietnamese Dong1.00",
5175 "Vietnamese dong1.00",
5176 "Vietnamese dong1.00",
5177 "WIR Euro1.00",
5178 "WIR Franc1.00",
5179 "WIR euro1.00",
5180 "WIR euros1.00",
5181 "WIR franc1.00",
5182 "WIR francs1.00",
5183 "WST1.00",
5184 "WST1.00",
5185 "Samoan Tala1.00",
5186 "Samoan tala1.00",
5187 "Samoan tala1.00",
5188 "XAF1.00",
5189 "XAF1.00",
5190 "XAG1.00",
5191 "XAG1.00",
5192 "XAU1.00",
5193 "XAU1.00",
5194 "XBA1.00",
5195 "XBA1.00",
5196 "XBB1.00",
5197 "XBB1.00",
5198 "XBC1.00",
5199 "XBC1.00",
5200 "XBD1.00",
5201 "XBD1.00",
5202 "XCD1.00",
5203 "XDR1.00",
5204 "XDR1.00",
5205 "XEU1.00",
5206 "XEU1.00",
5207 "XFO1.00",
5208 "XFO1.00",
5209 "XFU1.00",
5210 "XFU1.00",
5211 "XOF1.00",
5212 "XOF1.00",
5213 "XPD1.00",
5214 "XPD1.00",
5215 "XPF1.00",
5216 "XPT1.00",
5217 "XPT1.00",
5218 "XRE1.00",
5219 "XRE1.00",
5220 "XTS1.00",
5221 "XTS1.00",
5222 "XXX1.00",
5223 "XXX1.00",
5224 "YDD1.00",
5225 "YDD1.00",
5226 "YER1.00",
5227 "YUD1.00",
5228 "YUD1.00",
5229 "YUM1.00",
5230 "YUM1.00",
5231 "YUN1.00",
5232 "YUN1.00",
5233 "Yemeni Dinar1.00",
5234 "Yemeni Rial1.00",
5235 "Yemeni dinar1.00",
5236 "Yemeni dinars1.00",
5237 "Yemeni rial1.00",
5238 "Yemeni rials1.00",
5239 "Yugoslavian Convertible Dinar (1990\\u20131992)1.00",
5240 "Yugoslavian Hard Dinar (1966\\u20131990)1.00",
5241 "Yugoslavian New Dinar (1994\\u20132002)1.00",
5242 "Yugoslavian convertible dinar (1990\\u20131992)1.00",
5243 "Yugoslavian convertible dinars (1990\\u20131992)1.00",
5244 "Yugoslavian hard dinar (1966\\u20131990)1.00",
5245 "Yugoslavian hard dinars (1966\\u20131990)1.00",
5246 "Yugoslavian new dinar (1994\\u20132002)1.00",
5247 "Yugoslavian new dinars (1994\\u20132002)1.00",
5248 "ZAL1.00",
5249 "ZAL1.00",
5250 "ZAR1.00",
5251 "ZMK1.00",
5252 "ZMK1.00",
5253 "ZRN1.00",
5254 "ZRN1.00",
5255 "ZRZ1.00",
5256 "ZRZ1.00",
5257 "ZWD1.00",
5258 "Zairean New Zaire (1993\\u20131998)1.00",
5259 "Zairean Zaire (1971\\u20131993)1.00",
5260 "Zairean new zaire (1993\\u20131998)1.00",
5261 "Zairean new zaires (1993\\u20131998)1.00",
5262 "Zairean zaire (1971\\u20131993)1.00",
5263 "Zairean zaires (1971\\u20131993)1.00",
5264 "Zambian Kwacha1.00",
5265 "Zambian kwacha1.00",
5266 "Zambian kwachas1.00",
5267 "Zimbabwean Dollar (1980\\u20132008)1.00",
5268 "Zimbabwean dollar (1980\\u20132008)1.00",
5269 "Zimbabwean dollars (1980\\u20132008)1.00",
5270 "euro1.00",
5271 "euros1.00",
5272 "Turkish lira (1922\\u20132005)1.00",
5273 "special drawing rights1.00",
5274 "Colombian real value unit1.00",
5275 "Colombian real value units1.00",
5276 "unknown currency1.00",
5277 "\\u00a31.00",
5278 "\\u00a51.00",
5279 "\\u20ab1.00",
5280 "\\u20aa1.00",
5281 "\\u20ac1.00",
5282 "\\u20b91.00",
5283 //
5284 // Following has extra text, should be parsed correctly too
5285 "$1.00 random",
5286 "USD1.00 random",
5287 "1.00 US dollar random",
5288 "1.00 US dollars random",
5289 "1.00 Afghan Afghani random",
5290 "1.00 Afghan Afghani random",
5291 "1.00 Afghan Afghanis (1927\\u20131992) random",
5292 "1.00 Afghan Afghanis random",
5293 "1.00 Albanian Lek random",
5294 "1.00 Albanian lek random",
5295 "1.00 Albanian lek\\u00eb random",
5296 "1.00 Algerian Dinar random",
5297 "1.00 Algerian dinar random",
5298 "1.00 Algerian dinars random",
5299 "1.00 Andorran Peseta random",
5300 "1.00 Andorran peseta random",
5301 "1.00 Andorran pesetas random",
5302 "1.00 Angolan Kwanza (1977\\u20131990) random",
5303 "1.00 Angolan Readjusted Kwanza (1995\\u20131999) random",
5304 "1.00 Angolan Kwanza random",
5305 "1.00 Angolan New Kwanza (1990\\u20132000) random",
5306 "1.00 Angolan kwanza (1977\\u20131991) random",
5307 "1.00 Angolan readjusted kwanza (1995\\u20131999) random",
5308 "1.00 Angolan kwanza random",
5309 "1.00 Angolan kwanzas (1977\\u20131991) random",
5310 "1.00 Angolan readjusted kwanzas (1995\\u20131999) random",
5311 "1.00 Angolan kwanzas random",
5312 "1.00 Angolan new kwanza (1990\\u20132000) random",
5313 "1.00 Angolan new kwanzas (1990\\u20132000) random",
5314 "1.00 Argentine Austral random",
5315 "1.00 Argentine Peso (1983\\u20131985) random",
5316 "1.00 Argentine Peso random",
5317 "1.00 Argentine austral random",
5318 "1.00 Argentine australs random",
5319 "1.00 Argentine peso (1983\\u20131985) random",
5320 "1.00 Argentine peso random",
5321 "1.00 Argentine pesos (1983\\u20131985) random",
5322 "1.00 Argentine pesos random",
5323 "1.00 Armenian Dram random",
5324 "1.00 Armenian dram random",
5325 "1.00 Armenian drams random",
5326 "1.00 Aruban Florin random",
5327 "1.00 Aruban florin random",
5328 "1.00 Australian Dollar random",
5329 "1.00 Australian dollar random",
5330 "1.00 Australian dollars random",
5331 "1.00 Austrian Schilling random",
5332 "1.00 Austrian schilling random",
5333 "1.00 Austrian schillings random",
5334 "1.00 Azerbaijani Manat (1993\\u20132006) random",
5335 "1.00 Azerbaijani Manat random",
5336 "1.00 Azerbaijani manat (1993\\u20132006) random",
5337 "1.00 Azerbaijani manat random",
5338 "1.00 Azerbaijani manats (1993\\u20132006) random",
5339 "1.00 Azerbaijani manats random",
5340 "1.00 Bahamian Dollar random",
5341 "1.00 Bahamian dollar random",
5342 "1.00 Bahamian dollars random",
5343 "1.00 Bahraini Dinar random",
5344 "1.00 Bahraini dinar random",
5345 "1.00 Bahraini dinars random",
5346 "1.00 Bangladeshi Taka random",
5347 "1.00 Bangladeshi taka random",
5348 "1.00 Bangladeshi takas random",
5349 "1.00 Barbadian Dollar random",
5350 "1.00 Barbadian dollar random",
5351 "1.00 Barbadian dollars random",
5352 "1.00 Belarusian Ruble (1994\\u20131999) random",
5353 "1.00 Belarusian Ruble random",
5354 "1.00 Belarusian ruble (1994\\u20131999) random",
5355 "1.00 Belarusian rubles (1994\\u20131999) random",
5356 "1.00 Belarusian ruble random",
5357 "1.00 Belarusian rubles random",
5358 "1.00 Belgian Franc (convertible) random",
5359 "1.00 Belgian Franc (financial) random",
5360 "1.00 Belgian Franc random",
5361 "1.00 Belgian franc (convertible) random",
5362 "1.00 Belgian franc (financial) random",
5363 "1.00 Belgian franc random",
5364 "1.00 Belgian francs (convertible) random",
5365 "1.00 Belgian francs (financial) random",
5366 "1.00 Belgian francs random",
5367 "1.00 Belize Dollar random",
5368 "1.00 Belize dollar random",
5369 "1.00 Belize dollars random",
5370 "1.00 Bermudan Dollar random",
5371 "1.00 Bermudan dollar random",
5372 "1.00 Bermudan dollars random",
5373 "1.00 Bhutanese Ngultrum random",
5374 "1.00 Bhutanese ngultrum random",
5375 "1.00 Bhutanese ngultrums random",
5376 "1.00 Bolivian Mvdol random",
5377 "1.00 Bolivian Peso random",
5378 "1.00 Bolivian mvdol random",
5379 "1.00 Bolivian mvdols random",
5380 "1.00 Bolivian peso random",
5381 "1.00 Bolivian pesos random",
5382 "1.00 Bolivian Boliviano random",
5383 "1.00 Bolivian Boliviano random",
5384 "1.00 Bolivian Bolivianos random",
5385 "1.00 Bosnia-Herzegovina Convertible Mark random",
5386 "1.00 Bosnia-Herzegovina Dinar (1992\\u20131994) random",
5387 "1.00 Bosnia-Herzegovina convertible mark random",
5388 "1.00 Bosnia-Herzegovina convertible marks random",
5389 "1.00 Bosnia-Herzegovina dinar (1992\\u20131994) random",
5390 "1.00 Bosnia-Herzegovina dinars (1992\\u20131994) random",
5391 "1.00 Botswanan Pula random",
5392 "1.00 Botswanan pula random",
5393 "1.00 Botswanan pulas random",
5394 "1.00 Brazilian New Cruzado (1989\\u20131990) random",
5395 "1.00 Brazilian Cruzado (1986\\u20131989) random",
5396 "1.00 Brazilian Cruzeiro (1990\\u20131993) random",
5397 "1.00 Brazilian New Cruzeiro (1967\\u20131986) random",
5398 "1.00 Brazilian Cruzeiro (1993\\u20131994) random",
5399 "1.00 Brazilian Real random",
5400 "1.00 Brazilian new cruzado (1989\\u20131990) random",
5401 "1.00 Brazilian new cruzados (1989\\u20131990) random",
5402 "1.00 Brazilian cruzado (1986\\u20131989) random",
5403 "1.00 Brazilian cruzados (1986\\u20131989) random",
5404 "1.00 Brazilian cruzeiro (1990\\u20131993) random",
5405 "1.00 Brazilian new cruzeiro (1967\\u20131986) random",
5406 "1.00 Brazilian cruzeiro (1993\\u20131994) random",
5407 "1.00 Brazilian cruzeiros (1990\\u20131993) random",
5408 "1.00 Brazilian new cruzeiros (1967\\u20131986) random",
5409 "1.00 Brazilian cruzeiros (1993\\u20131994) random",
5410 "1.00 Brazilian real random",
5411 "1.00 Brazilian reals random",
5412 "1.00 British Pound random",
5413 "1.00 British pound random",
5414 "1.00 British pounds random",
5415 "1.00 Brunei Dollar random",
5416 "1.00 Brunei dollar random",
5417 "1.00 Brunei dollars random",
5418 "1.00 Bulgarian Hard Lev random",
5419 "1.00 Bulgarian Lev random",
5420 "1.00 Bulgarian Leva random",
5421 "1.00 Bulgarian hard lev random",
5422 "1.00 Bulgarian hard leva random",
5423 "1.00 Bulgarian lev random",
5424 "1.00 Burmese Kyat random",
5425 "1.00 Burmese kyat random",
5426 "1.00 Burmese kyats random",
5427 "1.00 Burundian Franc random",
5428 "1.00 Burundian franc random",
5429 "1.00 Burundian francs random",
5430 "1.00 Cambodian Riel random",
5431 "1.00 Cambodian riel random",
5432 "1.00 Cambodian riels random",
5433 "1.00 Canadian Dollar random",
5434 "1.00 Canadian dollar random",
5435 "1.00 Canadian dollars random",
5436 "1.00 Cape Verdean Escudo random",
5437 "1.00 Cape Verdean escudo random",
5438 "1.00 Cape Verdean escudos random",
5439 "1.00 Cayman Islands Dollar random",
5440 "1.00 Cayman Islands dollar random",
5441 "1.00 Cayman Islands dollars random",
5442 "1.00 Chilean Peso random",
5443 "1.00 Chilean Unit of Account (UF) random",
5444 "1.00 Chilean peso random",
5445 "1.00 Chilean pesos random",
5446 "1.00 Chilean unit of account (UF) random",
5447 "1.00 Chilean units of account (UF) random",
5448 "1.00 Chinese Yuan random",
5449 "1.00 Chinese yuan random",
5450 "1.00 Colombian Peso random",
5451 "1.00 Colombian peso random",
5452 "1.00 Colombian pesos random",
5453 "1.00 Comorian Franc random",
5454 "1.00 Comorian franc random",
5455 "1.00 Comorian francs random",
5456 "1.00 Congolese Franc Congolais random",
5457 "1.00 Congolese franc Congolais random",
5458 "1.00 Congolese francs Congolais random",
5459 "1.00 Costa Rican Col\\u00f3n random",
5460 "1.00 Costa Rican col\\u00f3n random",
5461 "1.00 Costa Rican col\\u00f3ns random",
5462 "1.00 Croatian Dinar random",
5463 "1.00 Croatian Kuna random",
5464 "1.00 Croatian dinar random",
5465 "1.00 Croatian dinars random",
5466 "1.00 Croatian kuna random",
5467 "1.00 Croatian kunas random",
5468 "1.00 Cuban Peso random",
5469 "1.00 Cuban peso random",
5470 "1.00 Cuban pesos random",
5471 "1.00 Cypriot Pound random",
5472 "1.00 Cypriot pound random",
5473 "1.00 Cypriot pounds random",
5474 "1.00 Czech Koruna random",
5475 "1.00 Czech koruna random",
5476 "1.00 Czech korunas random",
5477 "1.00 Czechoslovak Hard Koruna random",
5478 "1.00 Czechoslovak hard koruna random",
5479 "1.00 Czechoslovak hard korunas random",
5480 "1.00 Danish Krone random",
5481 "1.00 Danish krone random",
5482 "1.00 Danish kroner random",
5483 "1.00 German Mark random",
5484 "1.00 German mark random",
5485 "1.00 German marks random",
5486 "1.00 Djiboutian Franc random",
5487 "1.00 Djiboutian franc random",
5488 "1.00 Djiboutian francs random",
5489 "1.00 Dominican Peso random",
5490 "1.00 Dominican peso random",
5491 "1.00 Dominican pesos random",
5492 "1.00 East Caribbean Dollar random",
5493 "1.00 East Caribbean dollar random",
5494 "1.00 East Caribbean dollars random",
5495 "1.00 East German Mark random",
5496 "1.00 East German mark random",
5497 "1.00 East German marks random",
5498 "1.00 Ecuadorian Sucre random",
5499 "1.00 Ecuadorian Unit of Constant Value random",
5500 "1.00 Ecuadorian sucre random",
5501 "1.00 Ecuadorian sucres random",
5502 "1.00 Ecuadorian unit of constant value random",
5503 "1.00 Ecuadorian units of constant value random",
5504 "1.00 Egyptian Pound random",
5505 "1.00 Egyptian pound random",
5506 "1.00 Egyptian pounds random",
5507 "1.00 Salvadoran Col\\u00f3n random",
5508 "1.00 Salvadoran col\\u00f3n random",
5509 "1.00 Salvadoran colones random",
5510 "1.00 Equatorial Guinean Ekwele random",
5511 "1.00 Equatorial Guinean ekwele random",
5512 "1.00 Eritrean Nakfa random",
5513 "1.00 Eritrean nakfa random",
5514 "1.00 Eritrean nakfas random",
5515 "1.00 Estonian Kroon random",
5516 "1.00 Estonian kroon random",
5517 "1.00 Estonian kroons random",
5518 "1.00 Ethiopian Birr random",
5519 "1.00 Ethiopian birr random",
5520 "1.00 Ethiopian birrs random",
5521 "1.00 European Composite Unit random",
5522 "1.00 European Currency Unit random",
5523 "1.00 European Monetary Unit random",
5524 "1.00 European Unit of Account (XBC) random",
5525 "1.00 European Unit of Account (XBD) random",
5526 "1.00 European composite unit random",
5527 "1.00 European composite units random",
5528 "1.00 European currency unit random",
5529 "1.00 European currency units random",
5530 "1.00 European monetary unit random",
5531 "1.00 European monetary units random",
5532 "1.00 European unit of account (XBC) random",
5533 "1.00 European unit of account (XBD) random",
5534 "1.00 European units of account (XBC) random",
5535 "1.00 European units of account (XBD) random",
5536 "1.00 Falkland Islands Pound random",
5537 "1.00 Falkland Islands pound random",
5538 "1.00 Falkland Islands pounds random",
5539 "1.00 Fijian Dollar random",
5540 "1.00 Fijian dollar random",
5541 "1.00 Fijian dollars random",
5542 "1.00 Finnish Markka random",
5543 "1.00 Finnish markka random",
5544 "1.00 Finnish markkas random",
5545 "1.00 French Franc random",
5546 "1.00 French Gold Franc random",
5547 "1.00 French UIC-Franc random",
5548 "1.00 French UIC-franc random",
5549 "1.00 French UIC-francs random",
5550 "1.00 French franc random",
5551 "1.00 French francs random",
5552 "1.00 French gold franc random",
5553 "1.00 French gold francs random",
5554 "1.00 Gambian Dalasi random",
5555 "1.00 Gambian dalasi random",
5556 "1.00 Gambian dalasis random",
5557 "1.00 Georgian Kupon Larit random",
5558 "1.00 Georgian Lari random",
5559 "1.00 Georgian kupon larit random",
5560 "1.00 Georgian kupon larits random",
5561 "1.00 Georgian lari random",
5562 "1.00 Georgian laris random",
5563 "1.00 Ghanaian Cedi (1979\\u20132007) random",
5564 "1.00 Ghanaian Cedi random",
5565 "1.00 Ghanaian cedi (1979\\u20132007) random",
5566 "1.00 Ghanaian cedi random",
5567 "1.00 Ghanaian cedis (1979\\u20132007) random",
5568 "1.00 Ghanaian cedis random",
5569 "1.00 Gibraltar Pound random",
5570 "1.00 Gibraltar pound random",
5571 "1.00 Gibraltar pounds random",
5572 "1.00 Gold random",
5573 "1.00 Gold random",
5574 "1.00 Greek Drachma random",
5575 "1.00 Greek drachma random",
5576 "1.00 Greek drachmas random",
5577 "1.00 Guatemalan Quetzal random",
5578 "1.00 Guatemalan quetzal random",
5579 "1.00 Guatemalan quetzals random",
5580 "1.00 Guinean Franc random",
5581 "1.00 Guinean Syli random",
5582 "1.00 Guinean franc random",
5583 "1.00 Guinean francs random",
5584 "1.00 Guinean syli random",
5585 "1.00 Guinean sylis random",
5586 "1.00 Guinea-Bissau Peso random",
5587 "1.00 Guinea-Bissau peso random",
5588 "1.00 Guinea-Bissau pesos random",
5589 "1.00 Guyanaese Dollar random",
5590 "1.00 Guyanaese dollar random",
5591 "1.00 Guyanaese dollars random",
5592 "1.00 Haitian Gourde random",
5593 "1.00 Haitian gourde random",
5594 "1.00 Haitian gourdes random",
5595 "1.00 Honduran Lempira random",
5596 "1.00 Honduran lempira random",
5597 "1.00 Honduran lempiras random",
5598 "1.00 Hong Kong Dollar random",
5599 "1.00 Hong Kong dollar random",
5600 "1.00 Hong Kong dollars random",
5601 "1.00 Hungarian Forint random",
5602 "1.00 Hungarian forint random",
5603 "1.00 Hungarian forints random",
5604 "1.00 Icelandic Kr\\u00f3na random",
5605 "1.00 Icelandic kr\\u00f3na random",
5606 "1.00 Icelandic kr\\u00f3nur random",
5607 "1.00 Indian Rupee random",
5608 "1.00 Indian rupee random",
5609 "1.00 Indian rupees random",
5610 "1.00 Indonesian Rupiah random",
5611 "1.00 Indonesian rupiah random",
5612 "1.00 Indonesian rupiahs random",
5613 "1.00 Iranian Rial random",
5614 "1.00 Iranian rial random",
5615 "1.00 Iranian rials random",
5616 "1.00 Iraqi Dinar random",
5617 "1.00 Iraqi dinar random",
5618 "1.00 Iraqi dinars random",
5619 "1.00 Irish Pound random",
5620 "1.00 Irish pound random",
5621 "1.00 Irish pounds random",
5622 "1.00 Israeli Pound random",
5623 "1.00 Israeli new shekel random",
5624 "1.00 Israeli pound random",
5625 "1.00 Israeli pounds random",
5626 "1.00 Italian Lira random",
5627 "1.00 Italian lira random",
5628 "1.00 Italian liras random",
5629 "1.00 Jamaican Dollar random",
5630 "1.00 Jamaican dollar random",
5631 "1.00 Jamaican dollars random",
5632 "1.00 Japanese Yen random",
5633 "1.00 Japanese yen random",
5634 "1.00 Jordanian Dinar random",
5635 "1.00 Jordanian dinar random",
5636 "1.00 Jordanian dinars random",
5637 "1.00 Kazakhstani Tenge random",
5638 "1.00 Kazakhstani tenge random",
5639 "1.00 Kazakhstani tenges random",
5640 "1.00 Kenyan Shilling random",
5641 "1.00 Kenyan shilling random",
5642 "1.00 Kenyan shillings random",
5643 "1.00 Kuwaiti Dinar random",
5644 "1.00 Kuwaiti dinar random",
5645 "1.00 Kuwaiti dinars random",
5646 "1.00 Kyrgystani Som random",
5647 "1.00 Kyrgystani som random",
5648 "1.00 Kyrgystani soms random",
5649 "1.00 Laotian Kip random",
5650 "1.00 Laotian kip random",
5651 "1.00 Laotian kips random",
5652 "1.00 Latvian Lats random",
5653 "1.00 Latvian Ruble random",
5654 "1.00 Latvian lats random",
5655 "1.00 Latvian lati random",
5656 "1.00 Latvian ruble random",
5657 "1.00 Latvian rubles random",
5658 "1.00 Lebanese Pound random",
5659 "1.00 Lebanese pound random",
5660 "1.00 Lebanese pounds random",
5661 "1.00 Lesotho Loti random",
5662 "1.00 Lesotho loti random",
5663 "1.00 Lesotho lotis random",
5664 "1.00 Liberian Dollar random",
5665 "1.00 Liberian dollar random",
5666 "1.00 Liberian dollars random",
5667 "1.00 Libyan Dinar random",
5668 "1.00 Libyan dinar random",
5669 "1.00 Libyan dinars random",
5670 "1.00 Lithuanian Litas random",
5671 "1.00 Lithuanian Talonas random",
5672 "1.00 Lithuanian litas random",
5673 "1.00 Lithuanian litai random",
5674 "1.00 Lithuanian talonas random",
5675 "1.00 Lithuanian talonases random",
5676 "1.00 Luxembourgian Convertible Franc random",
5677 "1.00 Luxembourg Financial Franc random",
5678 "1.00 Luxembourgian Franc random",
5679 "1.00 Luxembourgian convertible franc random",
5680 "1.00 Luxembourgian convertible francs random",
5681 "1.00 Luxembourg financial franc random",
5682 "1.00 Luxembourg financial francs random",
5683 "1.00 Luxembourgian franc random",
5684 "1.00 Luxembourgian francs random",
5685 "1.00 Macanese Pataca random",
5686 "1.00 Macanese pataca random",
5687 "1.00 Macanese patacas random",
5688 "1.00 Macedonian Denar random",
5689 "1.00 Macedonian denar random",
5690 "1.00 Macedonian denari random",
5691 "1.00 Malagasy Ariaries random",
5692 "1.00 Malagasy Ariary random",
5693 "1.00 Malagasy Ariary random",
5694 "1.00 Malagasy Franc random",
5695 "1.00 Malagasy franc random",
5696 "1.00 Malagasy francs random",
5697 "1.00 Malawian Kwacha random",
5698 "1.00 Malawian Kwacha random",
5699 "1.00 Malawian Kwachas random",
5700 "1.00 Malaysian Ringgit random",
5701 "1.00 Malaysian ringgit random",
5702 "1.00 Malaysian ringgits random",
5703 "1.00 Maldivian Rufiyaa random",
5704 "1.00 Maldivian rufiyaa random",
5705 "1.00 Maldivian rufiyaas random",
5706 "1.00 Malian Franc random",
5707 "1.00 Malian franc random",
5708 "1.00 Malian francs random",
5709 "1.00 Maltese Lira random",
5710 "1.00 Maltese Pound random",
5711 "1.00 Maltese lira random",
5712 "1.00 Maltese liras random",
5713 "1.00 Maltese pound random",
5714 "1.00 Maltese pounds random",
5715 "1.00 Mauritanian Ouguiya random",
5716 "1.00 Mauritanian ouguiya random",
5717 "1.00 Mauritanian ouguiyas random",
5718 "1.00 Mauritian Rupee random",
5719 "1.00 Mauritian rupee random",
5720 "1.00 Mauritian rupees random",
5721 "1.00 Mexican Peso random",
5722 "1.00 Mexican Silver Peso (1861\\u20131992) random",
5723 "1.00 Mexican Investment Unit random",
5724 "1.00 Mexican peso random",
5725 "1.00 Mexican pesos random",
5726 "1.00 Mexican silver peso (1861\\u20131992) random",
5727 "1.00 Mexican silver pesos (1861\\u20131992) random",
5728 "1.00 Mexican investment unit random",
5729 "1.00 Mexican investment units random",
5730 "1.00 Moldovan Leu random",
5731 "1.00 Moldovan leu random",
5732 "1.00 Moldovan lei random",
5733 "1.00 Mongolian Tugrik random",
5734 "1.00 Mongolian tugrik random",
5735 "1.00 Mongolian tugriks random",
5736 "1.00 Moroccan Dirham random",
5737 "1.00 Moroccan Franc random",
5738 "1.00 Moroccan dirham random",
5739 "1.00 Moroccan dirhams random",
5740 "1.00 Moroccan franc random",
5741 "1.00 Moroccan francs random",
5742 "1.00 Mozambican Escudo random",
5743 "1.00 Mozambican Metical random",
5744 "1.00 Mozambican escudo random",
5745 "1.00 Mozambican escudos random",
5746 "1.00 Mozambican metical random",
5747 "1.00 Mozambican meticals random",
5748 "1.00 Myanmar Kyat random",
5749 "1.00 Myanmar kyat random",
5750 "1.00 Myanmar kyats random",
5751 "1.00 Namibian Dollar random",
5752 "1.00 Namibian dollar random",
5753 "1.00 Namibian dollars random",
5754 "1.00 Nepalese Rupee random",
5755 "1.00 Nepalese rupee random",
5756 "1.00 Nepalese rupees random",
5757 "1.00 Netherlands Antillean Guilder random",
5758 "1.00 Netherlands Antillean guilder random",
5759 "1.00 Netherlands Antillean guilders random",
5760 "1.00 Dutch Guilder random",
5761 "1.00 Dutch guilder random",
5762 "1.00 Dutch guilders random",
5763 "1.00 Israeli New Shekel random",
5764 "1.00 Israeli new shekels random",
5765 "1.00 New Zealand Dollar random",
5766 "1.00 New Zealand dollar random",
5767 "1.00 New Zealand dollars random",
5768 "1.00 Nicaraguan C\\u00f3rdoba random",
5769 "1.00 Nicaraguan C\\u00f3rdoba (1988\\u20131991) random",
5770 "1.00 Nicaraguan c\\u00f3rdoba random",
5771 "1.00 Nicaraguan c\\u00f3rdoba random",
5772 "1.00 Nicaraguan c\\u00f3rdoba (1988\\u20131991) random",
5773 "1.00 Nicaraguan c\\u00f3rdobas (1988\\u20131991) random",
5774 "1.00 Nigerian Naira random",
5775 "1.00 Nigerian naira random",
5776 "1.00 Nigerian nairas random",
5777 "1.00 North Korean Won random",
5778 "1.00 North Korean won random",
5779 "1.00 North Korean won random",
5780 "1.00 Norwegian Krone random",
5781 "1.00 Norwegian krone random",
5782 "1.00 Norwegian kroner random",
5783 "1.00 Mozambican Metical (1980\\u20132006) random",
5784 "1.00 Mozambican metical (1980\\u20132006) random",
5785 "1.00 Mozambican meticals (1980\\u20132006) random",
5786 "1.00 Romanian Lei (1952\\u20132006) random",
5787 "1.00 Romanian Leu (1952\\u20132006) random",
5788 "1.00 Romanian leu (1952\\u20132006) random",
5789 "1.00 Serbian Dinar (2002\\u20132006) random",
5790 "1.00 Serbian dinar (2002\\u20132006) random",
5791 "1.00 Serbian dinars (2002\\u20132006) random",
5792 "1.00 Sudanese Dinar (1992\\u20132007) random",
5793 "1.00 Sudanese Pound (1957\\u20131998) random",
5794 "1.00 Sudanese dinar (1992\\u20132007) random",
5795 "1.00 Sudanese dinars (1992\\u20132007) random",
5796 "1.00 Sudanese pound (1957\\u20131998) random",
5797 "1.00 Sudanese pounds (1957\\u20131998) random",
5798 "1.00 Turkish Lira (1922\\u20132005) random",
5799 "1.00 Turkish Lira (1922\\u20132005) random",
5800 "1.00 Omani Rial random",
5801 "1.00 Omani rial random",
5802 "1.00 Omani rials random",
5803 "1.00 Pakistani Rupee random",
5804 "1.00 Pakistani rupee random",
5805 "1.00 Pakistani rupees random",
5806 "1.00 Palladium random",
5807 "1.00 Palladium random",
5808 "1.00 Panamanian Balboa random",
5809 "1.00 Panamanian balboa random",
5810 "1.00 Panamanian balboas random",
5811 "1.00 Papua New Guinean Kina random",
5812 "1.00 Papua New Guinean kina random",
5813 "1.00 Papua New Guinean kina random",
5814 "1.00 Paraguayan Guarani random",
5815 "1.00 Paraguayan guarani random",
5816 "1.00 Paraguayan guaranis random",
5817 "1.00 Peruvian Inti random",
5818 "1.00 Peruvian Sol random",
5819 "1.00 Peruvian Sol (1863\\u20131965) random",
5820 "1.00 Peruvian inti random",
5821 "1.00 Peruvian intis random",
5822 "1.00 Peruvian sol random",
5823 "1.00 Peruvian soles random",
5824 "1.00 Peruvian sol (1863\\u20131965) random",
5825 "1.00 Peruvian soles (1863\\u20131965) random",
5826 "1.00 Philippine Piso random",
5827 "1.00 Philippine piso random",
5828 "1.00 Philippine pisos random",
5829 "1.00 Platinum random",
5830 "1.00 Platinum random",
5831 "1.00 Polish Zloty (1950\\u20131995) random",
5832 "1.00 Polish Zloty random",
5833 "1.00 Polish zlotys random",
5834 "1.00 Polish zloty (PLZ) random",
5835 "1.00 Polish zloty random",
5836 "1.00 Polish zlotys (PLZ) random",
5837 "1.00 Portuguese Escudo random",
5838 "1.00 Portuguese Guinea Escudo random",
5839 "1.00 Portuguese Guinea escudo random",
5840 "1.00 Portuguese Guinea escudos random",
5841 "1.00 Portuguese escudo random",
5842 "1.00 Portuguese escudos random",
5843 "1.00 Qatari Rial random",
5844 "1.00 Qatari rial random",
5845 "1.00 Qatari rials random",
5846 "1.00 RINET Funds random",
5847 "1.00 RINET Funds random",
5848 "1.00 Rhodesian Dollar random",
5849 "1.00 Rhodesian dollar random",
5850 "1.00 Rhodesian dollars random",
5851 "1.00 Romanian Leu random",
5852 "1.00 Romanian lei random",
5853 "1.00 Romanian leu random",
5854 "1.00 Russian Ruble (1991\\u20131998) random",
5855 "1.00 Russian Ruble random",
5856 "1.00 Russian ruble (1991\\u20131998) random",
5857 "1.00 Russian ruble random",
5858 "1.00 Russian rubles (1991\\u20131998) random",
5859 "1.00 Russian rubles random",
5860 "1.00 Rwandan Franc random",
5861 "1.00 Rwandan franc random",
5862 "1.00 Rwandan francs random",
5863 "1.00 St. Helena Pound random",
5864 "1.00 St. Helena pound random",
5865 "1.00 St. Helena pounds random",
5866 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra random",
5867 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra random",
5868 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras random",
5869 "1.00 Saudi Riyal random",
5870 "1.00 Saudi riyal random",
5871 "1.00 Saudi riyals random",
5872 "1.00 Serbian Dinar random",
5873 "1.00 Serbian dinar random",
5874 "1.00 Serbian dinars random",
5875 "1.00 Seychellois Rupee random",
5876 "1.00 Seychellois rupee random",
5877 "1.00 Seychellois rupees random",
5878 "1.00 Sierra Leonean Leone random",
5879 "1.00 Sierra Leonean leone random",
5880 "1.00 Sierra Leonean leones random",
5881 "1.00 Singapore Dollar random",
5882 "1.00 Singapore dollar random",
5883 "1.00 Singapore dollars random",
5884 "1.00 Slovak Koruna random",
5885 "1.00 Slovak koruna random",
5886 "1.00 Slovak korunas random",
5887 "1.00 Slovenian Tolar random",
5888 "1.00 Slovenian tolar random",
5889 "1.00 Slovenian tolars random",
5890 "1.00 Solomon Islands Dollar random",
5891 "1.00 Solomon Islands dollar random",
5892 "1.00 Solomon Islands dollars random",
5893 "1.00 Somali Shilling random",
5894 "1.00 Somali shilling random",
5895 "1.00 Somali shillings random",
5896 "1.00 South African Rand (financial) random",
5897 "1.00 South African Rand random",
5898 "1.00 South African rand (financial) random",
5899 "1.00 South African rand random",
5900 "1.00 South African rands (financial) random",
5901 "1.00 South African rand random",
5902 "1.00 South Korean Won random",
5903 "1.00 South Korean won random",
5904 "1.00 South Korean won random",
5905 "1.00 Soviet Rouble random",
5906 "1.00 Soviet rouble random",
5907 "1.00 Soviet roubles random",
5908 "1.00 Spanish Peseta (A account) random",
5909 "1.00 Spanish Peseta (convertible account) random",
5910 "1.00 Spanish Peseta random",
5911 "1.00 Spanish peseta (A account) random",
5912 "1.00 Spanish peseta (convertible account) random",
5913 "1.00 Spanish peseta random",
5914 "1.00 Spanish pesetas (A account) random",
5915 "1.00 Spanish pesetas (convertible account) random",
5916 "1.00 Spanish pesetas random",
5917 "1.00 Special Drawing Rights random",
5918 "1.00 Sri Lankan Rupee random",
5919 "1.00 Sri Lankan rupee random",
5920 "1.00 Sri Lankan rupees random",
5921 "1.00 Sudanese Pound random",
5922 "1.00 Sudanese pound random",
5923 "1.00 Sudanese pounds random",
5924 "1.00 Surinamese Dollar random",
5925 "1.00 Surinamese dollar random",
5926 "1.00 Surinamese dollars random",
5927 "1.00 Surinamese Guilder random",
5928 "1.00 Surinamese guilder random",
5929 "1.00 Surinamese guilders random",
5930 "1.00 Swazi Lilangeni random",
5931 "1.00 Swazi lilangeni random",
5932 "1.00 Swazi emalangeni random",
5933 "1.00 Swedish Krona random",
5934 "1.00 Swedish krona random",
5935 "1.00 Swedish kronor random",
5936 "1.00 Swiss Franc random",
5937 "1.00 Swiss franc random",
5938 "1.00 Swiss francs random",
5939 "1.00 Syrian Pound random",
5940 "1.00 Syrian pound random",
5941 "1.00 Syrian pounds random",
5942 "1.00 New Taiwan Dollar random",
5943 "1.00 New Taiwan dollar random",
5944 "1.00 New Taiwan dollars random",
5945 "1.00 Tajikistani Ruble random",
5946 "1.00 Tajikistani Somoni random",
5947 "1.00 Tajikistani ruble random",
5948 "1.00 Tajikistani rubles random",
5949 "1.00 Tajikistani somoni random",
5950 "1.00 Tajikistani somonis random",
5951 "1.00 Tanzanian Shilling random",
5952 "1.00 Tanzanian shilling random",
5953 "1.00 Tanzanian shillings random",
5954 "1.00 Testing Currency Code random",
5955 "1.00 Testing Currency Code random",
5956 "1.00 Thai Baht random",
5957 "1.00 Thai baht random",
5958 "1.00 Thai baht random",
5959 "1.00 Timorese Escudo random",
5960 "1.00 Timorese escudo random",
5961 "1.00 Timorese escudos random",
5962 "1.00 Trinidad & Tobago Dollar random",
5963 "1.00 Trinidad & Tobago dollar random",
5964 "1.00 Trinidad & Tobago dollars random",
5965 "1.00 Tunisian Dinar random",
5966 "1.00 Tunisian dinar random",
5967 "1.00 Tunisian dinars random",
5968 "1.00 Turkish Lira random",
5969 "1.00 Turkish Lira random",
5970 "1.00 Turkish lira random",
5971 "1.00 Turkmenistani Manat random",
5972 "1.00 Turkmenistani manat random",
5973 "1.00 Turkmenistani manat random",
5974 "1.00 US Dollar (Next day) random",
5975 "1.00 US Dollar (Same day) random",
5976 "1.00 US Dollar random",
5977 "1.00 US dollar (next day) random",
5978 "1.00 US dollar (same day) random",
5979 "1.00 US dollar random",
5980 "1.00 US dollars (next day) random",
5981 "1.00 US dollars (same day) random",
5982 "1.00 US dollars random",
5983 "1.00 Ugandan Shilling (1966\\u20131987) random",
5984 "1.00 Ugandan Shilling random",
5985 "1.00 Ugandan shilling (1966\\u20131987) random",
5986 "1.00 Ugandan shilling random",
5987 "1.00 Ugandan shillings (1966\\u20131987) random",
5988 "1.00 Ugandan shillings random",
5989 "1.00 Ukrainian Hryvnia random",
5990 "1.00 Ukrainian Karbovanets random",
5991 "1.00 Ukrainian hryvnia random",
5992 "1.00 Ukrainian hryvnias random",
5993 "1.00 Ukrainian karbovanets random",
5994 "1.00 Ukrainian karbovantsiv random",
5995 "1.00 Colombian Real Value Unit random",
5996 "1.00 United Arab Emirates Dirham random",
5997 "1.00 Unknown Currency random",
5998 "1.00 Uruguayan Peso (1975\\u20131993) random",
5999 "1.00 Uruguayan Peso random",
6000 "1.00 Uruguayan Peso (Indexed Units) random",
6001 "1.00 Uruguayan peso (1975\\u20131993) random",
6002 "1.00 Uruguayan peso (indexed units) random",
6003 "1.00 Uruguayan peso random",
6004 "1.00 Uruguayan pesos (1975\\u20131993) random",
6005 "1.00 Uruguayan pesos (indexed units) random",
6006 "1.00 Uzbekistani Som random",
6007 "1.00 Uzbekistani som random",
6008 "1.00 Uzbekistani som random",
6009 "1.00 Vanuatu Vatu random",
6010 "1.00 Vanuatu vatu random",
6011 "1.00 Vanuatu vatus random",
6012 "1.00 Venezuelan Bol\\u00edvar random",
6013 "1.00 Venezuelan Bol\\u00edvar (1871\\u20132008) random",
6014 "1.00 Venezuelan bol\\u00edvar random",
6015 "1.00 Venezuelan bol\\u00edvars random",
6016 "1.00 Venezuelan bol\\u00edvar (1871\\u20132008) random",
6017 "1.00 Venezuelan bol\\u00edvars (1871\\u20132008) random",
6018 "1.00 Vietnamese Dong random",
6019 "1.00 Vietnamese dong random",
6020 "1.00 Vietnamese dong random",
6021 "1.00 WIR Euro random",
6022 "1.00 WIR Franc random",
6023 "1.00 WIR euro random",
6024 "1.00 WIR euros random",
6025 "1.00 WIR franc random",
6026 "1.00 WIR francs random",
6027 "1.00 Samoan Tala random",
6028 "1.00 Samoan tala random",
6029 "1.00 Samoan tala random",
6030 "1.00 Yemeni Dinar random",
6031 "1.00 Yemeni Rial random",
6032 "1.00 Yemeni dinar random",
6033 "1.00 Yemeni dinars random",
6034 "1.00 Yemeni rial random",
6035 "1.00 Yemeni rials random",
6036 "1.00 Yugoslavian Convertible Dinar (1990\\u20131992) random",
6037 "1.00 Yugoslavian Hard Dinar (1966\\u20131990) random",
6038 "1.00 Yugoslavian New Dinar (1994\\u20132002) random",
6039 "1.00 Yugoslavian convertible dinar (1990\\u20131992) random",
6040 "1.00 Yugoslavian convertible dinars (1990\\u20131992) random",
6041 "1.00 Yugoslavian hard dinar (1966\\u20131990) random",
6042 "1.00 Yugoslavian hard dinars (1966\\u20131990) random",
6043 "1.00 Yugoslavian new dinar (1994\\u20132002) random",
6044 "1.00 Yugoslavian new dinars (1994\\u20132002) random",
6045 "1.00 Zairean New Zaire (1993\\u20131998) random",
6046 "1.00 Zairean Zaire (1971\\u20131993) random",
6047 "1.00 Zairean new zaire (1993\\u20131998) random",
6048 "1.00 Zairean new zaires (1993\\u20131998) random",
6049 "1.00 Zairean zaire (1971\\u20131993) random",
6050 "1.00 Zairean zaires (1971\\u20131993) random",
6051 "1.00 Zambian Kwacha random",
6052 "1.00 Zambian kwacha random",
6053 "1.00 Zambian kwachas random",
6054 "1.00 Zimbabwean Dollar (1980\\u20132008) random",
6055 "1.00 Zimbabwean dollar (1980\\u20132008) random",
6056 "1.00 Zimbabwean dollars (1980\\u20132008) random",
6057 "1.00 euro random",
6058 "1.00 euros random",
6059 "1.00 Turkish lira (1922\\u20132005) random",
6060 "1.00 special drawing rights random",
6061 "1.00 Colombian real value unit random",
6062 "1.00 Colombian real value units random",
6063 "1.00 unknown currency random",
6064 };
6065
6066 const char* WRONG_DATA[] = {
6067 // Following are missing one last char in the currency name
6068 "1.00 Nicaraguan Cordob",
6069 "1.00 Namibian Dolla",
6070 "1.00 Namibian dolla",
6071 "1.00 Nepalese Rupe",
6072 "1.00 Nepalese rupe",
6073 "1.00 Netherlands Antillean Guilde",
6074 "1.00 Netherlands Antillean guilde",
6075 "1.00 Dutch Guilde",
6076 "1.00 Dutch guilde",
6077 "1.00 Israeli New Sheqe",
6078 "1.00 New Zealand Dolla",
6079 "1.00 New Zealand dolla",
6080 "1.00 Nicaraguan cordob",
6081 "1.00 Nigerian Nair",
6082 "1.00 Nigerian nair",
6083 "1.00 North Korean Wo",
6084 "1.00 North Korean wo",
6085 "1.00 Norwegian Kron",
6086 "1.00 Norwegian kron",
6087 "1.00 US dolla",
6088 "1.00",
6089 "A1.00",
6090 "AD1.00",
6091 "AE1.00",
6092 "AF1.00",
6093 "AL1.00",
6094 "AM1.00",
6095 "AN1.00",
6096 "AO1.00",
6097 "AR1.00",
6098 "AT1.00",
6099 "AU1.00",
6100 "AW1.00",
6101 "AZ1.00",
6102 "Afghan Afghan1.00",
6103 "Afghan Afghani (1927\\u201320021.00",
6104 "Afl1.00",
6105 "Albanian Le1.00",
6106 "Algerian Dina1.00",
6107 "Andorran Peset1.00",
6108 "Angolan Kwanz1.00",
6109 "Angolan Kwanza (1977\\u201319901.00",
6110 "Angolan Readjusted Kwanza (1995\\u201319991.00",
6111 "Angolan New Kwanza (1990\\u201320001.00",
6112 "Argentine Austra1.00",
6113 "Argentine Pes1.00",
6114 "Argentine Peso (1983\\u201319851.00",
6115 "Armenian Dra1.00",
6116 "Aruban Flori1.00",
6117 "Australian Dolla1.00",
6118 "Austrian Schillin1.00",
6119 "Azerbaijani Mana1.00",
6120 "Azerbaijani Manat (1993\\u201320061.00",
6121 "B1.00",
6122 "BA1.00",
6123 "BB1.00",
6124 "BE1.00",
6125 "BG1.00",
6126 "BH1.00",
6127 "BI1.00",
6128 "BM1.00",
6129 "BN1.00",
6130 "BO1.00",
6131 "BR1.00",
6132 "BS1.00",
6133 "BT1.00",
6134 "BU1.00",
6135 "BW1.00",
6136 "BY1.00",
6137 "BZ1.00",
6138 "Bahamian Dolla1.00",
6139 "Bahraini Dina1.00",
6140 "Bangladeshi Tak1.00",
6141 "Barbadian Dolla1.00",
6142 "Bds1.00",
6143 "Belarusian Ruble (1994\\u201319991.00",
6144 "Belarusian Rubl1.00",
6145 "Belgian Fran1.00",
6146 "Belgian Franc (convertible1.00",
6147 "Belgian Franc (financial1.00",
6148 "Belize Dolla1.00",
6149 "Bermudan Dolla1.00",
6150 "Bhutanese Ngultru1.00",
6151 "Bolivian Mvdo1.00",
6152 "Bolivian Pes1.00",
6153 "Bolivian Bolivian1.00",
6154 "Bosnia-Herzegovina Convertible Mar1.00",
6155 "Bosnia-Herzegovina Dina1.00",
6156 "Botswanan Pul1.00",
6157 "Brazilian Cruzad1.00",
6158 "Brazilian Cruzado Nov1.00",
6159 "Brazilian Cruzeir1.00",
6160 "Brazilian Cruzeiro (1990\\u201319931.00",
6161 "Brazilian New Cruzeiro (1967\\u201319861.00",
6162 "Brazilian Rea1.00",
6163 "British Pound Sterlin1.00",
6164 "Brunei Dolla1.00",
6165 "Bulgarian Hard Le1.00",
6166 "Bulgarian Le1.00",
6167 "Burmese Kya1.00",
6168 "Burundian Fran1.00",
6169 "C1.00",
6170 "CA1.00",
6171 "CD1.00",
6172 "CFP Fran1.00",
6173 "CFP1.00",
6174 "CH1.00",
6175 "CL1.00",
6176 "CN1.00",
6177 "CO1.00",
6178 "CS1.00",
6179 "CU1.00",
6180 "CV1.00",
6181 "CY1.00",
6182 "CZ1.00",
6183 "Cambodian Rie1.00",
6184 "Canadian Dolla1.00",
6185 "Cape Verdean Escud1.00",
6186 "Cayman Islands Dolla1.00",
6187 "Chilean Pes1.00",
6188 "Chilean Unit of Accoun1.00",
6189 "Chinese Yua1.00",
6190 "Colombian Pes1.00",
6191 "Comoro Fran1.00",
6192 "Congolese Fran1.00",
6193 "Costa Rican Col\\u00f31.00",
6194 "Croatian Dina1.00",
6195 "Croatian Kun1.00",
6196 "Cuban Pes1.00",
6197 "Cypriot Poun1.00",
6198 "Czech Republic Korun1.00",
6199 "Czechoslovak Hard Korun1.00",
6200 "D1.00",
6201 "DD1.00",
6202 "DE1.00",
6203 "DJ1.00",
6204 "DK1.00",
6205 "DO1.00",
6206 "DZ1.00",
6207 "Danish Kron1.00",
6208 "German Mar1.00",
6209 "Djiboutian Fran1.00",
6210 "Dk1.00",
6211 "Dominican Pes1.00",
6212 "EC1.00",
6213 "EE1.00",
6214 "EG1.00",
6215 "EQ1.00",
6216 "ER1.00",
6217 "ES1.00",
6218 "ET1.00",
6219 "EU1.00",
6220 "East Caribbean Dolla1.00",
6221 "East German Ostmar1.00",
6222 "Ecuadorian Sucr1.00",
6223 "Ecuadorian Unit of Constant Valu1.00",
6224 "Egyptian Poun1.00",
6225 "Ekwel1.00",
6226 "Salvadoran Col\\u00f31.00",
6227 "Equatorial Guinean Ekwel1.00",
6228 "Eritrean Nakf1.00",
6229 "Es1.00",
6230 "Estonian Kroo1.00",
6231 "Ethiopian Bir1.00",
6232 "Eur1.00",
6233 "European Composite Uni1.00",
6234 "European Currency Uni1.00",
6235 "European Monetary Uni1.00",
6236 "European Unit of Account (XBC1.00",
6237 "European Unit of Account (XBD1.00",
6238 "F1.00",
6239 "FB1.00",
6240 "FI1.00",
6241 "FJ1.00",
6242 "FK1.00",
6243 "FR1.00",
6244 "Falkland Islands Poun1.00",
6245 "Fd1.00",
6246 "Fijian Dolla1.00",
6247 "Finnish Markk1.00",
6248 "Fr1.00",
6249 "French Fran1.00",
6250 "French Gold Fran1.00",
6251 "French UIC-Fran1.00",
6252 "G1.00",
6253 "GB1.00",
6254 "GE1.00",
6255 "GH1.00",
6256 "GI1.00",
6257 "GM1.00",
6258 "GN1.00",
6259 "GQ1.00",
6260 "GR1.00",
6261 "GT1.00",
6262 "GW1.00",
6263 "GY1.00",
6264 "Gambian Dalas1.00",
6265 "Georgian Kupon Lari1.00",
6266 "Georgian Lar1.00",
6267 "Ghanaian Ced1.00",
6268 "Ghanaian Cedi (1979\\u201320071.00",
6269 "Gibraltar Poun1.00",
6270 "Gol1.00",
6271 "Greek Drachm1.00",
6272 "Guatemalan Quetza1.00",
6273 "Guinean Fran1.00",
6274 "Guinean Syl1.00",
6275 "Guinea-Bissau Pes1.00",
6276 "Guyanaese Dolla1.00",
6277 "HK1.00",
6278 "HN1.00",
6279 "HR1.00",
6280 "HT1.00",
6281 "HU1.00",
6282 "Haitian Gourd1.00",
6283 "Honduran Lempir1.00",
6284 "Hong Kong Dolla1.00",
6285 "Hungarian Forin1.00",
6286 "I1.00",
6287 "IE1.00",
6288 "IL1.00",
6289 "IN1.00",
6290 "IQ1.00",
6291 "IR1.00",
6292 "IS1.00",
6293 "IT1.00",
6294 "Icelandic Kron1.00",
6295 "Indian Rupe1.00",
6296 "Indonesian Rupia1.00",
6297 "Iranian Ria1.00",
6298 "Iraqi Dina1.00",
6299 "Irish Poun1.00",
6300 "Israeli Poun1.00",
6301 "Italian Lir1.00",
6302 "J1.00",
6303 "JM1.00",
6304 "JO1.00",
6305 "JP1.00",
6306 "Jamaican Dolla1.00",
6307 "Japanese Ye1.00",
6308 "Jordanian Dina1.00",
6309 "K S1.00",
6310 "K1.00",
6311 "KE1.00",
6312 "KG1.00",
6313 "KH1.00",
6314 "KP1.00",
6315 "KR1.00",
6316 "KW1.00",
6317 "KY1.00",
6318 "KZ1.00",
6319 "Kazakhstani Teng1.00",
6320 "Kenyan Shillin1.00",
6321 "Kuwaiti Dina1.00",
6322 "Kyrgystani So1.00",
6323 "LA1.00",
6324 "LB1.00",
6325 "LK1.00",
6326 "LR1.00",
6327 "LT1.00",
6328 "LU1.00",
6329 "LV1.00",
6330 "LY1.00",
6331 "Laotian Ki1.00",
6332 "Latvian Lat1.00",
6333 "Latvian Rubl1.00",
6334 "Lebanese Poun1.00",
6335 "Lesotho Lot1.00",
6336 "Liberian Dolla1.00",
6337 "Libyan Dina1.00",
6338 "Lithuanian Lit1.00",
6339 "Lithuanian Talona1.00",
6340 "Luxembourgian Convertible Fran1.00",
6341 "Luxembourg Financial Fran1.00",
6342 "Luxembourgian Fran1.00",
6343 "MA1.00",
6344 "MD1.00",
6345 "MDe1.00",
6346 "MEX1.00",
6347 "MG1.00",
6348 "ML1.00",
6349 "MM1.00",
6350 "MN1.00",
6351 "MO1.00",
6352 "MR1.00",
6353 "MT1.00",
6354 "MU1.00",
6355 "MV1.00",
6356 "MW1.00",
6357 "MX1.00",
6358 "MY1.00",
6359 "MZ1.00",
6360 "Macanese Patac1.00",
6361 "Macedonian Dena1.00",
6362 "Malagasy Ariar1.00",
6363 "Malagasy Fran1.00",
6364 "Malawian Kwach1.00",
6365 "Malaysian Ringgi1.00",
6366 "Maldivian Rufiya1.00",
6367 "Malian Fran1.00",
6368 "Malot1.00",
6369 "Maltese Lir1.00",
6370 "Maltese Poun1.00",
6371 "Mauritanian Ouguiy1.00",
6372 "Mauritian Rupe1.00",
6373 "Mexican Pes1.00",
6374 "Mexican Silver Peso (1861\\u201319921.00",
6375 "Mexican Investment Uni1.00",
6376 "Moldovan Le1.00",
6377 "Mongolian Tugri1.00",
6378 "Moroccan Dirha1.00",
6379 "Moroccan Fran1.00",
6380 "Mozambican Escud1.00",
6381 "Mozambican Metica1.00",
6382 "Myanmar Kya1.00",
6383 "N1.00",
6384 "NA1.00",
6385 "NAf1.00",
6386 "NG1.00",
6387 "NI1.00",
6388 "NK1.00",
6389 "NL1.00",
6390 "NO1.00",
6391 "NP1.00",
6392 "NT1.00",
6393 "Namibian Dolla1.00",
6394 "Nepalese Rupe1.00",
6395 "Netherlands Antillean Guilde1.00",
6396 "Dutch Guilde1.00",
6397 "Israeli New Sheqe1.00",
6398 "New Zealand Dolla1.00",
6399 "Nicaraguan C\\u00f3rdoba (1988\\u201319911.00",
6400 "Nicaraguan C\\u00f3rdob1.00",
6401 "Nigerian Nair1.00",
6402 "North Korean Wo1.00",
6403 "Norwegian Kron1.00",
6404 "Nr1.00",
6405 "OM1.00",
6406 "Old Mozambican Metica1.00",
6407 "Romanian Leu (1952\\u201320061.00",
6408 "Serbian Dinar (2002\\u201320061.00",
6409 "Sudanese Dinar (1992\\u201320071.00",
6410 "Sudanese Pound (1957\\u201319981.00",
6411 "Turkish Lira (1922\\u201320051.00",
6412 "Omani Ria1.00",
6413 "PA1.00",
6414 "PE1.00",
6415 "PG1.00",
6416 "PH1.00",
6417 "PK1.00",
6418 "PL1.00",
6419 "PT1.00",
6420 "PY1.00",
6421 "Pakistani Rupe1.00",
6422 "Palladiu1.00",
6423 "Panamanian Balbo1.00",
6424 "Papua New Guinean Kin1.00",
6425 "Paraguayan Guaran1.00",
6426 "Peruvian Int1.00",
6427 "Peruvian Sol (1863\\u201319651.00",
6428 "Peruvian Sol Nuev1.00",
6429 "Philippine Pes1.00",
6430 "Platinu1.00",
6431 "Polish Zlot1.00",
6432 "Polish Zloty (1950\\u201319951.00",
6433 "Portuguese Escud1.00",
6434 "Portuguese Guinea Escud1.00",
6435 "Pr1.00",
6436 "QA1.00",
6437 "Qatari Ria1.00",
6438 "RD1.00",
6439 "RH1.00",
6440 "RINET Fund1.00",
6441 "RS1.00",
6442 "RU1.00",
6443 "RW1.00",
6444 "Rb1.00",
6445 "Rhodesian Dolla1.00",
6446 "Romanian Le1.00",
6447 "Russian Rubl1.00",
6448 "Russian Ruble (1991\\u201319981.00",
6449 "Rwandan Fran1.00",
6450 "S1.00",
6451 "SA1.00",
6452 "SB1.00",
6453 "SC1.00",
6454 "SD1.00",
6455 "SE1.00",
6456 "SG1.00",
6457 "SH1.00",
6458 "SI1.00",
6459 "SK1.00",
6460 "SL R1.00",
6461 "SL1.00",
6462 "SO1.00",
6463 "ST1.00",
6464 "SU1.00",
6465 "SV1.00",
6466 "SY1.00",
6467 "SZ1.00",
6468 "St. Helena Poun1.00",
6469 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobr1.00",
6470 "Saudi Riya1.00",
6471 "Serbian Dina1.00",
6472 "Seychellois Rupe1.00",
6473 "Sh1.00",
6474 "Sierra Leonean Leon1.00",
6475 "Silve1.00",
6476 "Singapore Dolla1.00",
6477 "Slovak Korun1.00",
6478 "Slovenian Tola1.00",
6479 "Solomon Islands Dolla1.00",
6480 "Somali Shillin1.00",
6481 "South African Ran1.00",
6482 "South African Rand (financial1.00",
6483 "South Korean Wo1.00",
6484 "Soviet Roubl1.00",
6485 "Spanish Peset1.00",
6486 "Spanish Peseta (A account1.00",
6487 "Spanish Peseta (convertible account1.00",
6488 "Special Drawing Right1.00",
6489 "Sri Lankan Rupe1.00",
6490 "Sudanese Poun1.00",
6491 "Surinamese Dolla1.00",
6492 "Surinamese Guilde1.00",
6493 "Swazi Lilangen1.00",
6494 "Swedish Kron1.00",
6495 "Swiss Fran1.00",
6496 "Syrian Poun1.00",
6497 "T S1.00",
6498 "TH1.00",
6499 "TJ1.00",
6500 "TM1.00",
6501 "TN1.00",
6502 "TO1.00",
6503 "TP1.00",
6504 "TR1.00",
6505 "TT1.00",
6506 "TW1.00",
6507 "TZ1.00",
6508 "New Taiwan Dolla1.00",
6509 "Tajikistani Rubl1.00",
6510 "Tajikistani Somon1.00",
6511 "Tanzanian Shillin1.00",
6512 "Testing Currency Cod1.00",
6513 "Thai Bah1.00",
6514 "Timorese Escud1.00",
6515 "Tongan Pa\\u20bbang1.00",
6516 "Trinidad & Tobago Dolla1.00",
6517 "Tunisian Dina1.00",
6518 "Turkish Lir1.00",
6519 "Turkmenistani Mana1.00",
6520 "U S1.00",
6521 "U1.00",
6522 "UA1.00",
6523 "UG1.00",
6524 "US Dolla1.00",
6525 "US Dollar (Next day1.00",
6526 "US Dollar (Same day1.00",
6527 "US1.00",
6528 "UY1.00",
6529 "UZ1.00",
6530 "Ugandan Shillin1.00",
6531 "Ugandan Shilling (1966\\u201319871.00",
6532 "Ukrainian Hryvni1.00",
6533 "Ukrainian Karbovanet1.00",
6534 "Colombian Real Value Uni1.00",
6535 "United Arab Emirates Dirha1.00",
6536 "Unknown Currenc1.00",
6537 "Ur1.00",
6538 "Uruguay Peso (1975\\u201319931.00",
6539 "Uruguay Peso Uruguay1.00",
6540 "Uruguay Peso (Indexed Units1.00",
6541 "Uzbekistani So1.00",
6542 "V1.00",
6543 "VE1.00",
6544 "VN1.00",
6545 "VU1.00",
6546 "Vanuatu Vat1.00",
6547 "Venezuelan Bol\\u00edva1.00",
6548 "Venezuelan Bol\\u00edvar Fuert1.00",
6549 "Vietnamese Don1.00",
6550 "West African CFA Fran1.00",
6551 "Central African CFA Fran1.00",
6552 "WIR Eur1.00",
6553 "WIR Fran1.00",
6554 "WS1.00",
6555 "Samoa Tal1.00",
6556 "XA1.00",
6557 "XB1.00",
6558 "XC1.00",
6559 "XD1.00",
6560 "XE1.00",
6561 "XF1.00",
6562 "XO1.00",
6563 "XP1.00",
6564 "XR1.00",
6565 "XT1.00",
6566 "XX1.00",
6567 "YD1.00",
6568 "YE1.00",
6569 "YU1.00",
6570 "Yemeni Dina1.00",
6571 "Yemeni Ria1.00",
6572 "Yugoslavian Convertible Dina1.00",
6573 "Yugoslavian Hard Dinar (1966\\u201319901.00",
6574 "Yugoslavian New Dina1.00",
6575 "Z1.00",
6576 "ZA1.00",
6577 "ZM1.00",
6578 "ZR1.00",
6579 "ZW1.00",
6580 "Zairean New Zaire (1993\\u201319981.00",
6581 "Zairean Zair1.00",
6582 "Zambian Kwach1.00",
6583 "Zimbabwean Dollar (1980\\u201320081.00",
6584 "dra1.00",
6585 "lar1.00",
6586 "le1.00",
6587 "man1.00",
6588 "so1.00",
6589 };
6590
6591 Locale locale("en_US");
6592 for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
6593 UnicodeString formatted = ctou(DATA[i]);
6594 UErrorCode status = U_ZERO_ERROR;
6595 LocalPointer<NumberFormat> numFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status), status);
6596 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {
6597 return;
6598 }
6599 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
6600 numFmt->setLenient(TRUE);
6601 ParsePosition parsePos;
6602 LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6603 if (parsePos.getIndex() > 0) {
6604 double doubleVal = currAmt->getNumber().getDouble(status);
6605 if ( doubleVal != 1.0 ) {
6606 errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
6607 }
6608 } else {
6609 errln("Failed to parse as currency: " + formatted);
6610 }
6611 }
6612
6613 for (uint32_t i=0; i<UPRV_LENGTHOF(WRONG_DATA); ++i) {
6614 UnicodeString formatted = ctou(WRONG_DATA[i]);
6615 UErrorCode status = U_ZERO_ERROR;
6616 NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6617 if (numFmt != NULL && U_SUCCESS(status)) {
6618 ParsePosition parsePos;
6619 LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6620 if (parsePos.getIndex() > 0) {
6621 double doubleVal = currAmt->getNumber().getDouble(status);
6622 errln("Parsed as currency, should not have: " + formatted + " -> " + doubleVal);
6623 }
6624 } else {
6625 dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));
6626 delete numFmt;
6627 break;
6628 }
6629 delete numFmt;
6630 }
6631 }
6632
6633 const char* attrString(int32_t);
6634
6635 // UnicodeString s;
6636 // std::string ss;
6637 // std::cout << s.toUTF8String(ss)
expectPositions(FieldPositionIterator & iter,int32_t * values,int32_t tupleCount,const UnicodeString & str)6638 void NumberFormatTest::expectPositions(FieldPositionIterator& iter, int32_t *values, int32_t tupleCount,
6639 const UnicodeString& str) {
6640 UBool found[10];
6641 FieldPosition fp;
6642
6643 if (tupleCount > 10) {
6644 assertTrue("internal error, tupleCount too large", FALSE);
6645 } else {
6646 for (int i = 0; i < tupleCount; ++i) {
6647 found[i] = FALSE;
6648 }
6649 }
6650
6651 logln(str);
6652 while (iter.next(fp)) {
6653 UBool ok = FALSE;
6654 int32_t id = fp.getField();
6655 int32_t start = fp.getBeginIndex();
6656 int32_t limit = fp.getEndIndex();
6657
6658 // is there a logln using printf?
6659 char buf[128];
6660 sprintf(buf, "%24s %3d %3d %3d", attrString(id), id, start, limit);
6661 logln(buf);
6662
6663 for (int i = 0; i < tupleCount; ++i) {
6664 if (found[i]) {
6665 continue;
6666 }
6667 if (values[i*3] == id &&
6668 values[i*3+1] == start &&
6669 values[i*3+2] == limit) {
6670 found[i] = ok = TRUE;
6671 break;
6672 }
6673 }
6674
6675 assertTrue((UnicodeString)"found [" + id + "," + start + "," + limit + "]", ok);
6676 }
6677
6678 // check that all were found
6679 UBool ok = TRUE;
6680 for (int i = 0; i < tupleCount; ++i) {
6681 if (!found[i]) {
6682 ok = FALSE;
6683 assertTrue((UnicodeString) "missing [" + values[i*3] + "," + values[i*3+1] + "," + values[i*3+2] + "]", found[i]);
6684 }
6685 }
6686 assertTrue("no expected values were missing", ok);
6687 }
6688
expectPosition(FieldPosition & pos,int32_t id,int32_t start,int32_t limit,const UnicodeString & str)6689 void NumberFormatTest::expectPosition(FieldPosition& pos, int32_t id, int32_t start, int32_t limit,
6690 const UnicodeString& str) {
6691 logln(str);
6692 assertTrue((UnicodeString)"id " + id + " == " + pos.getField(), id == pos.getField());
6693 assertTrue((UnicodeString)"begin " + start + " == " + pos.getBeginIndex(), start == pos.getBeginIndex());
6694 assertTrue((UnicodeString)"end " + limit + " == " + pos.getEndIndex(), limit == pos.getEndIndex());
6695 }
6696
TestFieldPositionIterator()6697 void NumberFormatTest::TestFieldPositionIterator() {
6698 // bug 7372
6699 UErrorCode status = U_ZERO_ERROR;
6700 FieldPositionIterator iter1;
6701 FieldPositionIterator iter2;
6702 FieldPosition pos;
6703
6704 DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(status);
6705 if (failure(status, "NumberFormat::createInstance", TRUE)) return;
6706
6707 double num = 1234.56;
6708 UnicodeString str1;
6709 UnicodeString str2;
6710
6711 assertTrue((UnicodeString)"self==", iter1 == iter1);
6712 assertTrue((UnicodeString)"iter1==iter2", iter1 == iter2);
6713
6714 decFmt->format(num, str1, &iter1, status);
6715 assertTrue((UnicodeString)"iter1 != iter2", iter1 != iter2);
6716 decFmt->format(num, str2, &iter2, status);
6717 assertTrue((UnicodeString)"iter1 == iter2 (2)", iter1 == iter2);
6718 iter1.next(pos);
6719 assertTrue((UnicodeString)"iter1 != iter2 (2)", iter1 != iter2);
6720 iter2.next(pos);
6721 assertTrue((UnicodeString)"iter1 == iter2 (3)", iter1 == iter2);
6722
6723 // should format ok with no iterator
6724 str2.remove();
6725 decFmt->format(num, str2, NULL, status);
6726 assertEquals("null fpiter", str1, str2);
6727
6728 delete decFmt;
6729 }
6730
TestFormatAttributes()6731 void NumberFormatTest::TestFormatAttributes() {
6732 Locale locale("en_US");
6733 UErrorCode status = U_ZERO_ERROR;
6734 DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6735 if (failure(status, "NumberFormat::createInstance", TRUE)) return;
6736 double val = 12345.67;
6737
6738 {
6739 int32_t expected[] = {
6740 UNUM_CURRENCY_FIELD, 0, 1,
6741 UNUM_GROUPING_SEPARATOR_FIELD, 3, 4,
6742 UNUM_INTEGER_FIELD, 1, 7,
6743 UNUM_DECIMAL_SEPARATOR_FIELD, 7, 8,
6744 UNUM_FRACTION_FIELD, 8, 10,
6745 };
6746 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6747
6748 FieldPositionIterator posIter;
6749 UnicodeString result;
6750 decFmt->format(val, result, &posIter, status);
6751 expectPositions(posIter, expected, tupleCount, result);
6752 }
6753 {
6754 FieldPosition fp(UNUM_INTEGER_FIELD);
6755 UnicodeString result;
6756 decFmt->format(val, result, fp);
6757 expectPosition(fp, UNUM_INTEGER_FIELD, 1, 7, result);
6758 }
6759 {
6760 FieldPosition fp(UNUM_FRACTION_FIELD);
6761 UnicodeString result;
6762 decFmt->format(val, result, fp);
6763 expectPosition(fp, UNUM_FRACTION_FIELD, 8, 10, result);
6764 }
6765 delete decFmt;
6766
6767 decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_SCIENTIFIC, status);
6768 val = -0.0000123;
6769 {
6770 int32_t expected[] = {
6771 UNUM_SIGN_FIELD, 0, 1,
6772 UNUM_INTEGER_FIELD, 1, 2,
6773 UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3,
6774 UNUM_FRACTION_FIELD, 3, 5,
6775 UNUM_EXPONENT_SYMBOL_FIELD, 5, 6,
6776 UNUM_EXPONENT_SIGN_FIELD, 6, 7,
6777 UNUM_EXPONENT_FIELD, 7, 8
6778 };
6779 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6780
6781 FieldPositionIterator posIter;
6782 UnicodeString result;
6783 decFmt->format(val, result, &posIter, status);
6784 expectPositions(posIter, expected, tupleCount, result);
6785 }
6786 {
6787 FieldPosition fp(UNUM_INTEGER_FIELD);
6788 UnicodeString result;
6789 decFmt->format(val, result, fp);
6790 expectPosition(fp, UNUM_INTEGER_FIELD, 1, 2, result);
6791 }
6792 {
6793 FieldPosition fp(UNUM_FRACTION_FIELD);
6794 UnicodeString result;
6795 decFmt->format(val, result, fp);
6796 expectPosition(fp, UNUM_FRACTION_FIELD, 3, 5, result);
6797 }
6798 delete decFmt;
6799
6800 fflush(stderr);
6801 }
6802
attrString(int32_t attrId)6803 const char* attrString(int32_t attrId) {
6804 switch (attrId) {
6805 case UNUM_INTEGER_FIELD: return "integer";
6806 case UNUM_FRACTION_FIELD: return "fraction";
6807 case UNUM_DECIMAL_SEPARATOR_FIELD: return "decimal separator";
6808 case UNUM_EXPONENT_SYMBOL_FIELD: return "exponent symbol";
6809 case UNUM_EXPONENT_SIGN_FIELD: return "exponent sign";
6810 case UNUM_EXPONENT_FIELD: return "exponent";
6811 case UNUM_GROUPING_SEPARATOR_FIELD: return "grouping separator";
6812 case UNUM_CURRENCY_FIELD: return "currency";
6813 case UNUM_PERCENT_FIELD: return "percent";
6814 case UNUM_PERMILL_FIELD: return "permille";
6815 case UNUM_SIGN_FIELD: return "sign";
6816 default: return "";
6817 }
6818 }
6819
6820 //
6821 // Test formatting & parsing of big decimals.
6822 // API test, not a comprehensive test.
6823 // See DecimalFormatTest/DataDrivenTests
6824 //
6825 #define ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \
6826 assertSuccess(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (status)); \
6827 } UPRV_BLOCK_MACRO_END
6828 #define ASSERT_EQUALS(expected, actual) UPRV_BLOCK_MACRO_BEGIN { \
6829 assertEquals(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (expected), (actual)); \
6830 } UPRV_BLOCK_MACRO_END
6831
TestDecimal()6832 void NumberFormatTest::TestDecimal() {
6833 {
6834 UErrorCode status = U_ZERO_ERROR;
6835 Formattable f("12.345678999987654321E666", status);
6836 ASSERT_SUCCESS(status);
6837 StringPiece s = f.getDecimalNumber(status);
6838 ASSERT_SUCCESS(status);
6839 ASSERT_EQUALS("1.2345678999987654321E+667", s.data());
6840 //printf("%s\n", s.data());
6841 }
6842
6843 {
6844 UErrorCode status = U_ZERO_ERROR;
6845 Formattable f1("this is not a number", status);
6846 ASSERT_EQUALS(U_DECIMAL_NUMBER_SYNTAX_ERROR, status);
6847 }
6848
6849 {
6850 UErrorCode status = U_ZERO_ERROR;
6851 Formattable f;
6852 f.setDecimalNumber("123.45", status);
6853 ASSERT_SUCCESS(status);
6854 ASSERT_EQUALS( Formattable::kDouble, f.getType());
6855 ASSERT_EQUALS(123.45, f.getDouble());
6856 ASSERT_EQUALS(123.45, f.getDouble(status));
6857 ASSERT_SUCCESS(status);
6858 ASSERT_EQUALS("123.45", f.getDecimalNumber(status).data());
6859 ASSERT_SUCCESS(status);
6860
6861 f.setDecimalNumber("4.5678E7", status);
6862 int32_t n;
6863 n = f.getLong();
6864 ASSERT_EQUALS(45678000, n);
6865
6866 status = U_ZERO_ERROR;
6867 f.setDecimalNumber("-123", status);
6868 ASSERT_SUCCESS(status);
6869 ASSERT_EQUALS( Formattable::kLong, f.getType());
6870 ASSERT_EQUALS(-123, f.getLong());
6871 ASSERT_EQUALS(-123, f.getLong(status));
6872 ASSERT_SUCCESS(status);
6873 ASSERT_EQUALS("-123", f.getDecimalNumber(status).data());
6874 ASSERT_SUCCESS(status);
6875
6876 status = U_ZERO_ERROR;
6877 f.setDecimalNumber("1234567890123", status); // Number too big for 32 bits
6878 ASSERT_SUCCESS(status);
6879 ASSERT_EQUALS( Formattable::kInt64, f.getType());
6880 ASSERT_EQUALS(1234567890123LL, f.getInt64());
6881 ASSERT_EQUALS(1234567890123LL, f.getInt64(status));
6882 ASSERT_SUCCESS(status);
6883 ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status).data());
6884 ASSERT_SUCCESS(status);
6885 }
6886
6887 {
6888 UErrorCode status = U_ZERO_ERROR;
6889 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6890 if (U_FAILURE(status) || fmtr == NULL) {
6891 dataerrln("Unable to create NumberFormat");
6892 } else {
6893 UnicodeString formattedResult;
6894 StringPiece num("244444444444444444444444444444444444446.4");
6895 fmtr->format(num, formattedResult, NULL, status);
6896 ASSERT_SUCCESS(status);
6897 ASSERT_EQUALS("244,444,444,444,444,444,444,444,444,444,444,444,446.4", formattedResult);
6898 //std::string ss; std::cout << formattedResult.toUTF8String(ss);
6899 delete fmtr;
6900 }
6901 }
6902
6903 {
6904 // Check formatting a DigitList. DigitList is internal, but this is
6905 // a critical interface that must work.
6906 UErrorCode status = U_ZERO_ERROR;
6907 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6908 if (U_FAILURE(status) || fmtr == NULL) {
6909 dataerrln("Unable to create NumberFormat");
6910 } else {
6911 UnicodeString formattedResult;
6912 DecimalQuantity dl;
6913 StringPiece num("123.4566666666666666666666666666666666621E+40");
6914 dl.setToDecNumber(num, status);
6915 ASSERT_SUCCESS(status);
6916 fmtr->format(dl, formattedResult, NULL, status);
6917 ASSERT_SUCCESS(status);
6918 ASSERT_EQUALS("1,234,566,666,666,666,666,666,666,666,666,666,666,621,000", formattedResult);
6919
6920 status = U_ZERO_ERROR;
6921 num.set("666.666");
6922 dl.setToDecNumber(num, status);
6923 FieldPosition pos(NumberFormat::FRACTION_FIELD);
6924 ASSERT_SUCCESS(status);
6925 formattedResult.remove();
6926 fmtr->format(dl, formattedResult, pos, status);
6927 ASSERT_SUCCESS(status);
6928 ASSERT_EQUALS("666.666", formattedResult);
6929 ASSERT_EQUALS(4, pos.getBeginIndex());
6930 ASSERT_EQUALS(7, pos.getEndIndex());
6931 delete fmtr;
6932 }
6933 }
6934
6935 {
6936 // Check a parse with a formatter with a multiplier.
6937 UErrorCode status = U_ZERO_ERROR;
6938 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_PERCENT, status);
6939 if (U_FAILURE(status) || fmtr == NULL) {
6940 dataerrln("Unable to create NumberFormat");
6941 } else {
6942 UnicodeString input = "1.84%";
6943 Formattable result;
6944 fmtr->parse(input, result, status);
6945 ASSERT_SUCCESS(status);
6946 ASSERT_EQUALS("0.0184", result.getDecimalNumber(status).data());
6947 //std::cout << result.getDecimalNumber(status).data();
6948 delete fmtr;
6949 }
6950 }
6951
6952 #if U_PLATFORM != U_PF_CYGWIN || defined(CYGWINMSVC)
6953 /*
6954 * This test fails on Cygwin (1.7.16) using GCC because of a rounding issue with strtod().
6955 * See #9463
6956 */
6957 {
6958 // Check that a parse returns a decimal number with full accuracy
6959 UErrorCode status = U_ZERO_ERROR;
6960 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6961 if (U_FAILURE(status) || fmtr == NULL) {
6962 dataerrln("Unable to create NumberFormat");
6963 } else {
6964 UnicodeString input = "1.002200044400088880000070000";
6965 Formattable result;
6966 fmtr->parse(input, result, status);
6967 ASSERT_SUCCESS(status);
6968 ASSERT_EQUALS(0, strcmp("1.00220004440008888000007", result.getDecimalNumber(status).data()));
6969 ASSERT_EQUALS(1.00220004440008888, result.getDouble());
6970 //std::cout << result.getDecimalNumber(status).data();
6971 delete fmtr;
6972 }
6973 }
6974 #endif
6975
6976 }
6977
TestCurrencyFractionDigits()6978 void NumberFormatTest::TestCurrencyFractionDigits() {
6979 UErrorCode status = U_ZERO_ERROR;
6980 UnicodeString text1, text2;
6981 double value = 99.12345;
6982
6983 // Create currenct instance
6984 NumberFormat* fmt = NumberFormat::createCurrencyInstance("ja_JP", status);
6985 if (U_FAILURE(status) || fmt == NULL) {
6986 dataerrln("Unable to create NumberFormat");
6987 } else {
6988 fmt->format(value, text1);
6989
6990 // Reset the same currency and format the test value again
6991 fmt->setCurrency(fmt->getCurrency(), status);
6992 ASSERT_SUCCESS(status);
6993 fmt->format(value, text2);
6994
6995 if (text1 != text2) {
6996 errln((UnicodeString)"NumberFormat::format() should return the same result - text1="
6997 + text1 + " text2=" + text2);
6998 }
6999 }
7000 delete fmt;
7001 }
7002
TestExponentParse()7003 void NumberFormatTest::TestExponentParse() {
7004
7005 UErrorCode status = U_ZERO_ERROR;
7006 Formattable result;
7007 ParsePosition parsePos(0);
7008
7009 // set the exponent symbol
7010 status = U_ZERO_ERROR;
7011 DecimalFormatSymbols symbols(Locale::getDefault(), status);
7012 if(U_FAILURE(status)) {
7013 dataerrln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (Default)");
7014 return;
7015 }
7016
7017 // create format instance
7018 status = U_ZERO_ERROR;
7019 DecimalFormat fmt(u"#####", symbols, status);
7020 if(U_FAILURE(status)) {
7021 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
7022 }
7023
7024 // parse the text
7025 fmt.parse("5.06e-27", result, parsePos);
7026 if(result.getType() != Formattable::kDouble &&
7027 result.getDouble() != 5.06E-27 &&
7028 parsePos.getIndex() != 8
7029 )
7030 {
7031 errln("ERROR: parse failed - expected 5.06E-27, 8 - returned %d, %i",
7032 result.getDouble(), parsePos.getIndex());
7033 }
7034 }
7035
TestExplicitParents()7036 void NumberFormatTest::TestExplicitParents() {
7037
7038 /* Test that number formats are properly inherited from es_419 */
7039 /* These could be subject to change if the CLDR data changes */
7040 static const char* parentLocaleTests[][2]= {
7041 /* locale ID */ /* expected */
7042 {"es_CO", "1.250,75" },
7043 {"es_ES", "1.250,75" },
7044 {"es_GQ", "1.250,75" },
7045 {"es_MX", "1,250.75" },
7046 {"es_US", "1,250.75" },
7047 {"es_VE", "1.250,75" },
7048 };
7049
7050 UnicodeString s;
7051
7052 for(int i=0; i < UPRV_LENGTHOF(parentLocaleTests); i++){
7053 UErrorCode status = U_ZERO_ERROR;
7054 const char *localeID = parentLocaleTests[i][0];
7055 UnicodeString expected(parentLocaleTests[i][1], -1, US_INV);
7056 expected = expected.unescape();
7057 char loc[256]={0};
7058 uloc_canonicalize(localeID, loc, 256, &status);
7059 NumberFormat *fmt= NumberFormat::createInstance(Locale(loc), status);
7060 if(U_FAILURE(status)){
7061 dataerrln("Could not create number formatter for locale %s - %s",localeID, u_errorName(status));
7062 continue;
7063 }
7064 s.remove();
7065 fmt->format(1250.75, s);
7066 if(s!=expected){
7067 errln(UnicodeString("FAIL: Expected: ")+expected
7068 + UnicodeString(" Got: ") + s
7069 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
7070 }
7071 if (U_FAILURE(status)){
7072 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
7073 }
7074 delete fmt;
7075 }
7076
7077 }
7078
7079 /**
7080 * Test available numbering systems API.
7081 */
TestAvailableNumberingSystems()7082 void NumberFormatTest::TestAvailableNumberingSystems() {
7083 IcuTestErrorCode status(*this, "TestAvailableNumberingSystems");
7084 StringEnumeration *availableNumberingSystems = NumberingSystem::getAvailableNames(status);
7085 CHECK_DATA(status, "NumberingSystem::getAvailableNames()");
7086
7087 int32_t nsCount = availableNumberingSystems->count(status);
7088 if ( nsCount < 74 ) {
7089 errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 74, got %d",nsCount);
7090 }
7091
7092 /* A relatively simple test of the API. We call getAvailableNames() and cycle through */
7093 /* each name returned, attempting to create a numbering system based on that name and */
7094 /* verifying that the name returned from the resulting numbering system is the same */
7095 /* one that we initially thought. */
7096
7097 int32_t len;
7098 const char* prevName = nullptr;
7099 for ( int32_t i = 0 ; i < nsCount ; i++ ) {
7100 const char *nsname = availableNumberingSystems->next(&len,status);
7101 NumberingSystem* ns = NumberingSystem::createInstanceByName(nsname,status);
7102 logln("OK for ns = %s",nsname);
7103 if ( uprv_strcmp(nsname,ns->getName()) ) {
7104 errln("FAIL: Numbering system name didn't match for name = %s\n",nsname);
7105 }
7106 if (prevName != nullptr) {
7107 int comp = uprv_strcmp(prevName, nsname);
7108 assertTrue(
7109 UnicodeString(u"NS names should be in alphabetical order: ")
7110 + prevName + u" vs " + nsname,
7111 // TODO: Why are there duplicates? This doesn't work if comp < 0
7112 comp <= 0);
7113 }
7114 prevName = nsname;
7115
7116 delete ns;
7117 }
7118
7119 LocalPointer<NumberingSystem> dummy(NumberingSystem::createInstanceByName("dummy", status), status);
7120 status.expectErrorAndReset(U_UNSUPPORTED_ERROR);
7121 assertTrue("Non-existent numbering system should return null", dummy.isNull());
7122
7123 delete availableNumberingSystems;
7124 }
7125
7126 void
Test9087(void)7127 NumberFormatTest::Test9087(void)
7128 {
7129 U_STRING_DECL(pattern,"#",1);
7130 U_STRING_INIT(pattern,"#",1);
7131
7132 U_STRING_DECL(infstr,"INF",3);
7133 U_STRING_INIT(infstr,"INF",3);
7134
7135 U_STRING_DECL(nanstr,"NAN",3);
7136 U_STRING_INIT(nanstr,"NAN",3);
7137
7138 UChar outputbuf[50] = {0};
7139 UErrorCode status = U_ZERO_ERROR;
7140 UNumberFormat* fmt = unum_open(UNUM_PATTERN_DECIMAL,pattern,1,NULL,NULL,&status);
7141 if ( U_FAILURE(status) ) {
7142 dataerrln("FAIL: error in unum_open() - %s", u_errorName(status));
7143 return;
7144 }
7145
7146 unum_setSymbol(fmt,UNUM_INFINITY_SYMBOL,infstr,3,&status);
7147 unum_setSymbol(fmt,UNUM_NAN_SYMBOL,nanstr,3,&status);
7148 if ( U_FAILURE(status) ) {
7149 errln("FAIL: error setting symbols");
7150 }
7151
7152 double inf = uprv_getInfinity();
7153
7154 unum_setAttribute(fmt,UNUM_ROUNDING_MODE,UNUM_ROUND_HALFEVEN);
7155 unum_setDoubleAttribute(fmt,UNUM_ROUNDING_INCREMENT,0);
7156
7157 UFieldPosition position = { 0, 0, 0};
7158 unum_formatDouble(fmt,inf,outputbuf,50,&position,&status);
7159
7160 if ( u_strcmp(infstr, outputbuf)) {
7161 errln((UnicodeString)"FAIL: unexpected result for infinity - expected " + infstr + " got " + outputbuf);
7162 }
7163
7164 unum_close(fmt);
7165 }
7166
TestFormatFastpaths()7167 void NumberFormatTest::TestFormatFastpaths() {
7168 // get some additional case
7169 {
7170 UErrorCode status=U_ZERO_ERROR;
7171 DecimalFormat df(UnicodeString(u"0000"),status);
7172 if (U_FAILURE(status)) {
7173 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7174 } else {
7175 int64_t long_number = 1;
7176 UnicodeString expect = "0001";
7177 UnicodeString result;
7178 FieldPosition pos;
7179 df.format(long_number, result, pos);
7180 if(U_FAILURE(status)||expect!=result) {
7181 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s",
7182 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7183 } else {
7184 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
7185 }
7186 }
7187 }
7188 {
7189 UErrorCode status=U_ZERO_ERROR;
7190 DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7191 if (U_FAILURE(status)) {
7192 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7193 } else {
7194 int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
7195 // uint8_t bits[8];
7196 // memcpy(bits,&long_number,8);
7197 // for(int i=0;i<8;i++) {
7198 // logln("bits: %02X", (unsigned int)bits[i]);
7199 // }
7200 UnicodeString expect = "-9223372036854775808";
7201 UnicodeString result;
7202 FieldPosition pos;
7203 df.format(long_number, result, pos);
7204 if(U_FAILURE(status)||expect!=result) {
7205 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775808",
7206 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7207 } else {
7208 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
7209 }
7210 }
7211 }
7212 {
7213 UErrorCode status=U_ZERO_ERROR;
7214 DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7215 if (U_FAILURE(status)) {
7216 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7217 } else {
7218 int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
7219 // uint8_t bits[8];
7220 // memcpy(bits,&long_number,8);
7221 // for(int i=0;i<8;i++) {
7222 // logln("bits: %02X", (unsigned int)bits[i]);
7223 // }
7224 UnicodeString expect = "9223372036854775807";
7225 UnicodeString result;
7226 FieldPosition pos;
7227 df.format(long_number, result, pos);
7228 if(U_FAILURE(status)||expect!=result) {
7229 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on U_INT64_MAX",
7230 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7231 } else {
7232 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
7233 }
7234 }
7235 }
7236 {
7237 UErrorCode status=U_ZERO_ERROR;
7238 DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7239 if (U_FAILURE(status)) {
7240 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7241 } else {
7242 int64_t long_number = 0;
7243 // uint8_t bits[8];
7244 // memcpy(bits,&long_number,8);
7245 // for(int i=0;i<8;i++) {
7246 // logln("bits: %02X", (unsigned int)bits[i]);
7247 // }
7248 UnicodeString expect = "0000000000000000000";
7249 UnicodeString result;
7250 FieldPosition pos;
7251 df.format(long_number, result, pos);
7252 if(U_FAILURE(status)||expect!=result) {
7253 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on 0",
7254 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7255 } else {
7256 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
7257 }
7258 }
7259 }
7260 {
7261 UErrorCode status=U_ZERO_ERROR;
7262 DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7263 if (U_FAILURE(status)) {
7264 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7265 } else {
7266 int64_t long_number = U_INT64_MIN + 1;
7267 UnicodeString expect = "-9223372036854775807";
7268 UnicodeString result;
7269 FieldPosition pos;
7270 df.format(long_number, result, pos);
7271 if(U_FAILURE(status)||expect!=result) {
7272 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775807",
7273 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7274 } else {
7275 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
7276 }
7277 }
7278 }
7279 }
7280
7281
TestFormattableSize(void)7282 void NumberFormatTest::TestFormattableSize(void) {
7283 if(sizeof(Formattable) > 112) {
7284 errln("Error: sizeof(Formattable)=%d, 112=%d\n",
7285 sizeof(Formattable), 112);
7286 } else if(sizeof(Formattable) < 112) {
7287 logln("Warning: sizeof(Formattable)=%d, 112=%d\n",
7288 sizeof(Formattable), 112);
7289 } else {
7290 logln("sizeof(Formattable)=%d, 112=%d\n",
7291 sizeof(Formattable), 112);
7292 }
7293 }
7294
testFormattableAsUFormattable(const char * file,int line,Formattable & f)7295 UBool NumberFormatTest::testFormattableAsUFormattable(const char *file, int line, Formattable &f) {
7296 UnicodeString fileLine = UnicodeString(file)+UnicodeString(":")+line+UnicodeString(": ");
7297
7298 UFormattable *u = f.toUFormattable();
7299 logln();
7300 if (u == NULL) {
7301 errln("%s:%d: Error: f.toUFormattable() retuned NULL.");
7302 return FALSE;
7303 }
7304 logln("%s:%d: comparing Formattable with UFormattable", file, line);
7305 logln(fileLine + toString(f));
7306
7307 UErrorCode status = U_ZERO_ERROR;
7308 UErrorCode valueStatus = U_ZERO_ERROR;
7309 UFormattableType expectUType = UFMT_COUNT; // invalid
7310
7311 UBool triedExact = FALSE; // did we attempt an exact comparison?
7312 UBool exactMatch = FALSE; // was the exact comparison true?
7313
7314 switch( f.getType() ) {
7315 case Formattable::kDate:
7316 expectUType = UFMT_DATE;
7317 exactMatch = (f.getDate()==ufmt_getDate(u, &valueStatus));
7318 triedExact = TRUE;
7319 break;
7320 case Formattable::kDouble:
7321 expectUType = UFMT_DOUBLE;
7322 exactMatch = (f.getDouble()==ufmt_getDouble(u, &valueStatus));
7323 triedExact = TRUE;
7324 break;
7325 case Formattable::kLong:
7326 expectUType = UFMT_LONG;
7327 exactMatch = (f.getLong()==ufmt_getLong(u, &valueStatus));
7328 triedExact = TRUE;
7329 break;
7330 case Formattable::kString:
7331 expectUType = UFMT_STRING;
7332 {
7333 UnicodeString str;
7334 f.getString(str);
7335 int32_t len;
7336 const UChar* uch = ufmt_getUChars(u, &len, &valueStatus);
7337 if(U_SUCCESS(valueStatus)) {
7338 UnicodeString str2(uch, len);
7339 assertTrue("UChar* NULL-terminated", uch[len]==0);
7340 exactMatch = (str == str2);
7341 }
7342 triedExact = TRUE;
7343 }
7344 break;
7345 case Formattable::kArray:
7346 expectUType = UFMT_ARRAY;
7347 triedExact = TRUE;
7348 {
7349 int32_t count = ufmt_getArrayLength(u, &valueStatus);
7350 int32_t count2;
7351 const Formattable *array2 = f.getArray(count2);
7352 exactMatch = assertEquals(fileLine + " array count", count, count2);
7353
7354 if(exactMatch) {
7355 for(int i=0;U_SUCCESS(valueStatus) && i<count;i++) {
7356 UFormattable *uu = ufmt_getArrayItemByIndex(u, i, &valueStatus);
7357 if(*Formattable::fromUFormattable(uu) != (array2[i])) {
7358 errln("%s:%d: operator== did not match at index[%d] - %p vs %p", file, line, i,
7359 (const void*)Formattable::fromUFormattable(uu), (const void*)&(array2[i]));
7360 exactMatch = FALSE;
7361 } else {
7362 if(!testFormattableAsUFormattable("(sub item)",i,*Formattable::fromUFormattable(uu))) {
7363 exactMatch = FALSE;
7364 }
7365 }
7366 }
7367 }
7368 }
7369 break;
7370 case Formattable::kInt64:
7371 expectUType = UFMT_INT64;
7372 exactMatch = (f.getInt64()==ufmt_getInt64(u, &valueStatus));
7373 triedExact = TRUE;
7374 break;
7375 case Formattable::kObject:
7376 expectUType = UFMT_OBJECT;
7377 exactMatch = (f.getObject()==ufmt_getObject(u, &valueStatus));
7378 triedExact = TRUE;
7379 break;
7380 }
7381 UFormattableType uType = ufmt_getType(u, &status);
7382
7383 if(U_FAILURE(status)) {
7384 errln("%s:%d: Error calling ufmt_getType - %s", file, line, u_errorName(status));
7385 return FALSE;
7386 }
7387
7388 if(uType != expectUType) {
7389 errln("%s:%d: got type (%d) expected (%d) from ufmt_getType", file, line, (int) uType, (int) expectUType);
7390 }
7391
7392 if(triedExact) {
7393 if(U_FAILURE(valueStatus)) {
7394 errln("%s:%d: got err %s trying to ufmt_get...() for exact match check", file, line, u_errorName(valueStatus));
7395 } else if(!exactMatch) {
7396 errln("%s:%d: failed exact match for the Formattable type", file, line);
7397 } else {
7398 logln("%s:%d: exact match OK", file, line);
7399 }
7400 } else {
7401 logln("%s:%d: note, did not attempt exact match for this formattable type", file, line);
7402 }
7403
7404 if( assertEquals(fileLine + " isNumeric()", f.isNumeric(), ufmt_isNumeric(u))
7405 && f.isNumeric()) {
7406 UErrorCode convStatus = U_ZERO_ERROR;
7407
7408 if(uType != UFMT_INT64) { // may fail to compare
7409 assertTrue(fileLine + " as doubles ==", f.getDouble(convStatus)==ufmt_getDouble(u, &convStatus));
7410 }
7411
7412 if( assertSuccess(fileLine + " (numeric conversion status)", convStatus) ) {
7413 StringPiece fDecNum = f.getDecimalNumber(convStatus);
7414 #if 1
7415 int32_t len;
7416 const char *decNumChars = ufmt_getDecNumChars(u, &len, &convStatus);
7417 #else
7418 // copy version
7419 char decNumChars[200];
7420 int32_t len = ufmt_getDecNumChars(u, decNumChars, 200, &convStatus);
7421 #endif
7422
7423 if( assertSuccess(fileLine + " (decNumbers conversion)", convStatus) ) {
7424 logln(fileLine + decNumChars);
7425 assertEquals(fileLine + " decNumChars length==", len, fDecNum.length());
7426 assertEquals(fileLine + " decNumChars digits", decNumChars, fDecNum.data());
7427 }
7428
7429 UErrorCode int64ConversionF = U_ZERO_ERROR;
7430 int64_t l = f.getInt64(int64ConversionF);
7431 UErrorCode int64ConversionU = U_ZERO_ERROR;
7432 int64_t r = ufmt_getInt64(u, &int64ConversionU);
7433
7434 if( (l==r)
7435 && ( uType != UFMT_INT64 ) // int64 better not overflow
7436 && (U_INVALID_FORMAT_ERROR==int64ConversionU)
7437 && (U_INVALID_FORMAT_ERROR==int64ConversionF) ) {
7438 logln("%s:%d: OK: 64 bit overflow", file, line);
7439 } else {
7440 assertEquals(fileLine + " as int64 ==", l, r);
7441 assertSuccess(fileLine + " Formattable.getnt64()", int64ConversionF);
7442 assertSuccess(fileLine + " ufmt_getInt64()", int64ConversionU);
7443 }
7444 }
7445 }
7446 return exactMatch || !triedExact;
7447 }
7448
TestUFormattable(void)7449 void NumberFormatTest::TestUFormattable(void) {
7450 {
7451 // test that a default formattable is equal to Formattable()
7452 UErrorCode status = U_ZERO_ERROR;
7453 LocalUFormattablePointer defaultUFormattable(ufmt_open(&status));
7454 assertSuccess("calling umt_open", status);
7455 Formattable defaultFormattable;
7456 assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7457 (defaultFormattable
7458 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7459 assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7460 (defaultFormattable
7461 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7462 assertTrue((UnicodeString)"comparing Formattable() round tripped through UFormattable",
7463 (defaultFormattable
7464 == *(Formattable::fromUFormattable(defaultFormattable.toUFormattable()))));
7465 assertTrue((UnicodeString)"comparing &Formattable() round tripped through UFormattable",
7466 ((&defaultFormattable)
7467 == Formattable::fromUFormattable(defaultFormattable.toUFormattable())));
7468 assertFalse((UnicodeString)"comparing &Formattable() with ufmt_open()",
7469 ((&defaultFormattable)
7470 == Formattable::fromUFormattable(defaultUFormattable.getAlias())));
7471 testFormattableAsUFormattable(__FILE__, __LINE__, defaultFormattable);
7472 }
7473 // test some random Formattables
7474 {
7475 Formattable f(ucal_getNow(), Formattable::kIsDate);
7476 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7477 }
7478 {
7479 Formattable f((double)1.61803398874989484820); // golden ratio
7480 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7481 }
7482 {
7483 Formattable f((int64_t)80994231587905127LL); // weight of the moon, in kilotons http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
7484 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7485 }
7486 {
7487 Formattable f((int32_t)4); // random number, source: http://www.xkcd.com/221/
7488 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7489 }
7490 {
7491 Formattable f("Hello world."); // should be invariant?
7492 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7493 }
7494 {
7495 UErrorCode status2 = U_ZERO_ERROR;
7496 Formattable f(StringPiece("73476730924573500000000.0"), status2); // weight of the moon, kg
7497 assertSuccess("Constructing a StringPiece", status2);
7498 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7499 }
7500 {
7501 UErrorCode status2 = U_ZERO_ERROR;
7502 UObject *obj = new Locale();
7503 Formattable f(obj);
7504 assertSuccess("Constructing a Formattable from a default constructed Locale()", status2);
7505 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7506 }
7507 {
7508 const Formattable array[] = {
7509 Formattable(ucal_getNow(), Formattable::kIsDate),
7510 Formattable((int32_t)4),
7511 Formattable((double)1.234),
7512 };
7513
7514 Formattable fa(array, 3);
7515 testFormattableAsUFormattable(__FILE__, __LINE__, fa);
7516 }
7517 }
7518
TestSignificantDigits(void)7519 void NumberFormatTest::TestSignificantDigits(void) {
7520 double input[] = {
7521 0, 0,
7522 0.1, -0.1,
7523 123, -123,
7524 12345, -12345,
7525 123.45, -123.45,
7526 123.44501, -123.44501,
7527 0.001234, -0.001234,
7528 0.00000000123, -0.00000000123,
7529 0.0000000000000000000123, -0.0000000000000000000123,
7530 1.2, -1.2,
7531 0.0000000012344501, -0.0000000012344501,
7532 123445.01, -123445.01,
7533 12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0,
7534 };
7535 const char* expected[] = {
7536 "0.00", "0.00",
7537 "0.100", "-0.100",
7538 "123", "-123",
7539 "12345", "-12345",
7540 "123.45", "-123.45",
7541 "123.45", "-123.45",
7542 "0.001234", "-0.001234",
7543 "0.00000000123", "-0.00000000123",
7544 "0.0000000000000000000123", "-0.0000000000000000000123",
7545 "1.20", "-1.20",
7546 "0.0000000012345", "-0.0000000012345",
7547 "123450", "-123450",
7548 "12345000000000000000000000000000000", "-12345000000000000000000000000000000",
7549 };
7550
7551 UErrorCode status = U_ZERO_ERROR;
7552 Locale locale("en_US");
7553 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7554 NumberFormat::createInstance(locale, status)));
7555 CHECK_DATA(status,"NumberFormat::createInstance");
7556
7557 numberFormat->setSignificantDigitsUsed(TRUE);
7558 numberFormat->setMinimumSignificantDigits(3);
7559 numberFormat->setMaximumSignificantDigits(5);
7560 numberFormat->setGroupingUsed(false);
7561
7562 UnicodeString result;
7563 UnicodeString expectedResult;
7564 for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
7565 numberFormat->format(input[i], result);
7566 UnicodeString expectedResult(expected[i]);
7567 if (result != expectedResult) {
7568 errln((UnicodeString)"Expected: '" + expectedResult + "' got '" + result);
7569 }
7570 result.remove();
7571 }
7572
7573 // Test for ICU-20063
7574 {
7575 DecimalFormat df({"en-us", status}, status);
7576 df.setSignificantDigitsUsed(TRUE);
7577 expect(df, 9.87654321, u"9.87654");
7578 df.setMaximumSignificantDigits(3);
7579 expect(df, 9.87654321, u"9.88");
7580 // setSignificantDigitsUsed with maxSig only
7581 df.setSignificantDigitsUsed(TRUE);
7582 expect(df, 9.87654321, u"9.88");
7583 df.setMinimumSignificantDigits(2);
7584 expect(df, 9, u"9.0");
7585 // setSignificantDigitsUsed with both minSig and maxSig
7586 df.setSignificantDigitsUsed(TRUE);
7587 expect(df, 9, u"9.0");
7588 // setSignificantDigitsUsed to false: should revert to fraction rounding
7589 df.setSignificantDigitsUsed(FALSE);
7590 expect(df, 9.87654321, u"9.876543");
7591 expect(df, 9, u"9");
7592 df.setSignificantDigitsUsed(TRUE);
7593 df.setMinimumSignificantDigits(2);
7594 expect(df, 9.87654321, u"9.87654");
7595 expect(df, 9, u"9.0");
7596 // setSignificantDigitsUsed with minSig only
7597 df.setSignificantDigitsUsed(TRUE);
7598 expect(df, 9.87654321, u"9.87654");
7599 expect(df, 9, u"9.0");
7600 }
7601 }
7602
TestShowZero()7603 void NumberFormatTest::TestShowZero() {
7604 UErrorCode status = U_ZERO_ERROR;
7605 Locale locale("en_US");
7606 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7607 NumberFormat::createInstance(locale, status)));
7608 CHECK_DATA(status, "NumberFormat::createInstance");
7609
7610 numberFormat->setSignificantDigitsUsed(TRUE);
7611 numberFormat->setMaximumSignificantDigits(3);
7612
7613 UnicodeString result;
7614 numberFormat->format(0.0, result);
7615 if (result != "0") {
7616 errln((UnicodeString)"Expected: 0, got " + result);
7617 }
7618 }
7619
TestBug9936()7620 void NumberFormatTest::TestBug9936() {
7621 UErrorCode status = U_ZERO_ERROR;
7622 Locale locale("en_US");
7623 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7624 NumberFormat::createInstance(locale, status)));
7625 if (U_FAILURE(status)) {
7626 dataerrln("File %s, Line %d: status = %s.\n", __FILE__, __LINE__, u_errorName(status));
7627 return;
7628 }
7629
7630 if (numberFormat->areSignificantDigitsUsed() == TRUE) {
7631 errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
7632 }
7633 numberFormat->setSignificantDigitsUsed(TRUE);
7634 if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7635 errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7636 }
7637
7638 numberFormat->setSignificantDigitsUsed(FALSE);
7639 if (numberFormat->areSignificantDigitsUsed() == TRUE) {
7640 errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
7641 }
7642
7643 numberFormat->setMinimumSignificantDigits(3);
7644 if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7645 errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7646 }
7647
7648 numberFormat->setSignificantDigitsUsed(FALSE);
7649 numberFormat->setMaximumSignificantDigits(6);
7650 if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7651 errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7652 }
7653
7654 }
7655
TestParseNegativeWithFaLocale()7656 void NumberFormatTest::TestParseNegativeWithFaLocale() {
7657 UErrorCode status = U_ZERO_ERROR;
7658 DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status);
7659 CHECK_DATA(status, "NumberFormat::createInstance");
7660 test->setLenient(TRUE);
7661 Formattable af;
7662 ParsePosition ppos;
7663 UnicodeString value("\\u200e-0,5");
7664 value = value.unescape();
7665 test->parse(value, af, ppos);
7666 if (ppos.getIndex() == 0) {
7667 errln("Expected -0,5 to parse for Farsi.");
7668 }
7669 delete test;
7670 }
7671
TestParseNegativeWithAlternateMinusSign()7672 void NumberFormatTest::TestParseNegativeWithAlternateMinusSign() {
7673 UErrorCode status = U_ZERO_ERROR;
7674 DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("en", status);
7675 CHECK_DATA(status, "NumberFormat::createInstance");
7676 test->setLenient(TRUE);
7677 Formattable af;
7678 ParsePosition ppos;
7679 UnicodeString value("\\u208B0.5");
7680 value = value.unescape();
7681 test->parse(value, af, ppos);
7682 if (ppos.getIndex() == 0) {
7683 errln(UnicodeString("Expected ") + value + UnicodeString(" to parse."));
7684 }
7685 delete test;
7686 }
7687
TestCustomCurrencySignAndSeparator()7688 void NumberFormatTest::TestCustomCurrencySignAndSeparator() {
7689 UErrorCode status = U_ZERO_ERROR;
7690 DecimalFormatSymbols custom(Locale::getUS(), status);
7691 CHECK(status, "DecimalFormatSymbols constructor");
7692
7693 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "*");
7694 custom.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, "^");
7695 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, ":");
7696
7697 UnicodeString pat(" #,##0.00");
7698 pat.insert(0, (UChar)0x00A4);
7699
7700 DecimalFormat fmt(pat, custom, status);
7701 CHECK(status, "DecimalFormat constructor");
7702
7703 UnicodeString numstr("* 1^234:56");
7704 expect2(fmt, (Formattable)((double)1234.56), numstr);
7705 }
7706
7707 typedef struct {
7708 const char * locale;
7709 UBool lenient;
7710 UnicodeString numString;
7711 double value;
7712 } SignsAndMarksItem;
7713
7714
TestParseSignsAndMarks()7715 void NumberFormatTest::TestParseSignsAndMarks() {
7716 const SignsAndMarksItem items[] = {
7717 // locale lenient numString value
7718 { "en", FALSE, CharsToUnicodeString("12"), 12 },
7719 { "en", TRUE, CharsToUnicodeString("12"), 12 },
7720 { "en", FALSE, CharsToUnicodeString("-23"), -23 },
7721 { "en", TRUE, CharsToUnicodeString("-23"), -23 },
7722 { "en", TRUE, CharsToUnicodeString("- 23"), -23 },
7723 { "en", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
7724 { "en", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
7725 { "en", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
7726
7727 { "en@numbers=arab", FALSE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7728 { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7729 { "en@numbers=arab", FALSE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7730 { "en@numbers=arab", TRUE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7731 { "en@numbers=arab", TRUE, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
7732 { "en@numbers=arab", FALSE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7733 { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7734 { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
7735
7736 { "en@numbers=arabext", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7737 { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7738 { "en@numbers=arabext", FALSE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7739 { "en@numbers=arabext", TRUE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7740 { "en@numbers=arabext", TRUE, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
7741 { "en@numbers=arabext", FALSE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7742 { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7743 { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
7744
7745 { "he", FALSE, CharsToUnicodeString("12"), 12 },
7746 { "he", TRUE, CharsToUnicodeString("12"), 12 },
7747 { "he", FALSE, CharsToUnicodeString("-23"), -23 },
7748 { "he", TRUE, CharsToUnicodeString("-23"), -23 },
7749 { "he", TRUE, CharsToUnicodeString("- 23"), -23 },
7750 { "he", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
7751 { "he", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
7752 { "he", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
7753
7754 { "ar", FALSE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7755 { "ar", TRUE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7756 { "ar", FALSE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7757 { "ar", TRUE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7758 { "ar", TRUE, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
7759 { "ar", FALSE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7760 { "ar", TRUE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7761 { "ar", TRUE, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
7762
7763 { "ar_MA", FALSE, CharsToUnicodeString("12"), 12 },
7764 { "ar_MA", TRUE, CharsToUnicodeString("12"), 12 },
7765 { "ar_MA", FALSE, CharsToUnicodeString("-23"), -23 },
7766 { "ar_MA", TRUE, CharsToUnicodeString("-23"), -23 },
7767 { "ar_MA", TRUE, CharsToUnicodeString("- 23"), -23 },
7768 { "ar_MA", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
7769 { "ar_MA", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
7770 { "ar_MA", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
7771
7772 { "fa", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7773 { "fa", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7774 { "fa", FALSE, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
7775 { "fa", TRUE, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
7776 { "fa", TRUE, CharsToUnicodeString("\\u2212 \\u06F6\\u06F7"), -67 },
7777 { "fa", FALSE, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
7778 { "fa", TRUE, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
7779 { "fa", TRUE, CharsToUnicodeString("\\u200E\\u2212\\u200E \\u06F6\\u06F7"), -67 },
7780
7781 { "ps", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7782 { "ps", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7783 { "ps", FALSE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7784 { "ps", TRUE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7785 { "ps", TRUE, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
7786 { "ps", FALSE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7787 { "ps", TRUE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7788 { "ps", TRUE, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
7789 { "ps", FALSE, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
7790 { "ps", TRUE, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
7791 { "ps", TRUE, CharsToUnicodeString("-\\u200E \\u06F6\\u06F7"), -67 },
7792 // terminator
7793 { NULL, 0, UnicodeString(""), 0 },
7794 };
7795
7796 const SignsAndMarksItem * itemPtr;
7797 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
7798 UErrorCode status = U_ZERO_ERROR;
7799 NumberFormat *numfmt = NumberFormat::createInstance(Locale(itemPtr->locale), status);
7800 if (U_SUCCESS(status)) {
7801 numfmt->setLenient(itemPtr->lenient);
7802 Formattable fmtobj;
7803 ParsePosition ppos;
7804 numfmt->parse(itemPtr->numString, fmtobj, ppos);
7805 if (ppos.getIndex() == itemPtr->numString.length()) {
7806 double parsedValue = fmtobj.getDouble(status);
7807 if (U_FAILURE(status) || parsedValue != itemPtr->value) {
7808 errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives value " + parsedValue);
7809 }
7810 } else {
7811 errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives position " + ppos.getIndex());
7812 }
7813 } else {
7814 dataerrln("FAIL: NumberFormat::createInstance for locale % gives error %s", itemPtr->locale, u_errorName(status));
7815 }
7816 delete numfmt;
7817 }
7818 }
7819
7820 typedef struct {
7821 DecimalFormat::ERoundingMode mode;
7822 double value;
7823 UnicodeString expected;
7824 } Test10419Data;
7825
7826
7827 // Tests that rounding works right when fractional digits is set to 0.
Test10419RoundingWith0FractionDigits()7828 void NumberFormatTest::Test10419RoundingWith0FractionDigits() {
7829 const Test10419Data items[] = {
7830 { DecimalFormat::kRoundCeiling, 1.488, "2"},
7831 { DecimalFormat::kRoundDown, 1.588, "1"},
7832 { DecimalFormat::kRoundFloor, 1.888, "1"},
7833 { DecimalFormat::kRoundHalfDown, 1.5, "1"},
7834 { DecimalFormat::kRoundHalfEven, 2.5, "2"},
7835 { DecimalFormat::kRoundHalfUp, 2.5, "3"},
7836 { DecimalFormat::kRoundUp, 1.5, "2"},
7837 };
7838 UErrorCode status = U_ZERO_ERROR;
7839 LocalPointer<DecimalFormat> decfmt((DecimalFormat *) NumberFormat::createInstance(Locale("en_US"), status));
7840 if (U_FAILURE(status)) {
7841 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
7842 return;
7843 }
7844 for (int32_t i = 0; i < UPRV_LENGTHOF(items); ++i) {
7845 decfmt->setRoundingMode(items[i].mode);
7846 decfmt->setMaximumFractionDigits(0);
7847 UnicodeString actual;
7848 if (items[i].expected != decfmt->format(items[i].value, actual)) {
7849 errln("Expected " + items[i].expected + ", got " + actual);
7850 }
7851 }
7852 }
7853
Test10468ApplyPattern()7854 void NumberFormatTest::Test10468ApplyPattern() {
7855 // Padding char of fmt is now 'a'
7856 UErrorCode status = U_ZERO_ERROR;
7857 DecimalFormat fmt("'I''ll'*a###.##", status);
7858
7859 if (U_FAILURE(status)) {
7860 errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7861 return;
7862 }
7863
7864 assertEquals("Padding character should be 'a'.", u"a", fmt.getPadCharacterString());
7865
7866 // Padding char of fmt ought to be '*' since that is the default and no
7867 // explicit padding char is specified in the new pattern.
7868 fmt.applyPattern("AA#,##0.00ZZ", status);
7869
7870 // Oops this still prints 'a' even though we changed the pattern.
7871 assertEquals("applyPattern did not clear padding character.", u" ", fmt.getPadCharacterString());
7872 }
7873
TestRoundingScientific10542()7874 void NumberFormatTest::TestRoundingScientific10542() {
7875 UErrorCode status = U_ZERO_ERROR;
7876 DecimalFormat format("0.00E0", status);
7877 if (U_FAILURE(status)) {
7878 errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7879 return;
7880 }
7881
7882 DecimalFormat::ERoundingMode roundingModes[] = {
7883 DecimalFormat::kRoundCeiling,
7884 DecimalFormat::kRoundDown,
7885 DecimalFormat::kRoundFloor,
7886 DecimalFormat::kRoundHalfDown,
7887 DecimalFormat::kRoundHalfEven,
7888 DecimalFormat::kRoundHalfUp,
7889 DecimalFormat::kRoundUp};
7890 const char *descriptions[] = {
7891 "Round Ceiling",
7892 "Round Down",
7893 "Round Floor",
7894 "Round half down",
7895 "Round half even",
7896 "Round half up",
7897 "Round up"};
7898
7899 {
7900 double values[] = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016};
7901 // The order of these expected values correspond to the order of roundingModes and the order of values.
7902 const char *expected[] = {
7903 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.02E-3", "3.02E-3", "3.02E-3",
7904 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7905 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7906 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.02E-3",
7907 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7908 "-3.01E-3", "-3.01E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7909 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.02E-3", "3.02E-3", "3.02E-3"};
7910 verifyRounding(
7911 format,
7912 values,
7913 expected,
7914 roundingModes,
7915 descriptions,
7916 UPRV_LENGTHOF(values),
7917 UPRV_LENGTHOF(roundingModes));
7918 }
7919 {
7920 double values[] = {-3006.0, -3005, -3004, 3014, 3015, 3016};
7921 // The order of these expected values correspond to the order of roundingModes and the order of values.
7922 const char *expected[] = {
7923 "-3.00E3", "-3.00E3", "-3.00E3", "3.02E3", "3.02E3", "3.02E3",
7924 "-3.00E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.01E3",
7925 "-3.01E3", "-3.01E3", "-3.01E3", "3.01E3", "3.01E3", "3.01E3",
7926 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.02E3",
7927 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7928 "-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7929 "-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"};
7930 verifyRounding(
7931 format,
7932 values,
7933 expected,
7934 roundingModes,
7935 descriptions,
7936 UPRV_LENGTHOF(values),
7937 UPRV_LENGTHOF(roundingModes));
7938 }
7939 /* Commented out for now until we decide how rounding to zero should work, +0 vs. -0
7940 {
7941 double values[] = {0.0, -0.0};
7942 // The order of these expected values correspond to the order of roundingModes and the order of values.
7943 const char *expected[] = {
7944 "0.00E0", "-0.00E0",
7945 "0.00E0", "-0.00E0",
7946 "0.00E0", "-0.00E0",
7947 "0.00E0", "-0.00E0",
7948 "0.00E0", "-0.00E0",
7949 "0.00E0", "-0.00E0",
7950 "0.00E0", "-0.00E0"};
7951 verifyRounding(
7952 format,
7953 values,
7954 expected,
7955 roundingModes,
7956 descriptions,
7957 UPRV_LENGTHOF(values),
7958 UPRV_LENGTHOF(roundingModes));
7959 }
7960 */
7961 {
7962
7963 double values[] = {1e25, 1e25 + 1e15, 1e25 - 1e15};
7964 // The order of these expected values correspond to the order of roundingModes and the order of values.
7965 const char *expected[] = {
7966 "1.00E25", "1.01E25", "1.00E25",
7967 "1.00E25", "1.00E25", "9.99E24",
7968 "1.00E25", "1.00E25", "9.99E24",
7969 "1.00E25", "1.00E25", "1.00E25",
7970 "1.00E25", "1.00E25", "1.00E25",
7971 "1.00E25", "1.00E25", "1.00E25",
7972 "1.00E25", "1.01E25", "1.00E25"};
7973 verifyRounding(
7974 format,
7975 values,
7976 expected,
7977 roundingModes,
7978 descriptions,
7979 UPRV_LENGTHOF(values),
7980 UPRV_LENGTHOF(roundingModes));
7981 }
7982 {
7983 double values[] = {-1e25, -1e25 + 1e15, -1e25 - 1e15};
7984 // The order of these expected values correspond to the order of roundingModes and the order of values.
7985 const char *expected[] = {
7986 "-1.00E25", "-9.99E24", "-1.00E25",
7987 "-1.00E25", "-9.99E24", "-1.00E25",
7988 "-1.00E25", "-1.00E25", "-1.01E25",
7989 "-1.00E25", "-1.00E25", "-1.00E25",
7990 "-1.00E25", "-1.00E25", "-1.00E25",
7991 "-1.00E25", "-1.00E25", "-1.00E25",
7992 "-1.00E25", "-1.00E25", "-1.01E25"};
7993 verifyRounding(
7994 format,
7995 values,
7996 expected,
7997 roundingModes,
7998 descriptions,
7999 UPRV_LENGTHOF(values),
8000 UPRV_LENGTHOF(roundingModes));
8001 }
8002 {
8003 double values[] = {1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
8004 // The order of these expected values correspond to the order of roundingModes and the order of values.
8005 const char *expected[] = {
8006 "1.00E-25", "1.01E-25", "1.00E-25",
8007 "1.00E-25", "1.00E-25", "9.99E-26",
8008 "1.00E-25", "1.00E-25", "9.99E-26",
8009 "1.00E-25", "1.00E-25", "1.00E-25",
8010 "1.00E-25", "1.00E-25", "1.00E-25",
8011 "1.00E-25", "1.00E-25", "1.00E-25",
8012 "1.00E-25", "1.01E-25", "1.00E-25"};
8013 verifyRounding(
8014 format,
8015 values,
8016 expected,
8017 roundingModes,
8018 descriptions,
8019 UPRV_LENGTHOF(values),
8020 UPRV_LENGTHOF(roundingModes));
8021 }
8022 {
8023 double values[] = {-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
8024 // The order of these expected values correspond to the order of roundingModes and the order of values.
8025 const char *expected[] = {
8026 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8027 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8028 "-1.00E-25", "-1.00E-25", "-1.01E-25",
8029 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8030 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8031 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8032 "-1.00E-25", "-1.00E-25", "-1.01E-25"};
8033 verifyRounding(
8034 format,
8035 values,
8036 expected,
8037 roundingModes,
8038 descriptions,
8039 UPRV_LENGTHOF(values),
8040 UPRV_LENGTHOF(roundingModes));
8041 }
8042 }
8043
TestZeroScientific10547()8044 void NumberFormatTest::TestZeroScientific10547() {
8045 UErrorCode status = U_ZERO_ERROR;
8046 DecimalFormat fmt("0.00E0", status);
8047 if (!assertSuccess("Format creation", status)) {
8048 return;
8049 }
8050 UnicodeString out;
8051 fmt.format(-0.0, out);
8052 assertEquals("format", "-0.00E0", out, true);
8053 }
8054
verifyRounding(DecimalFormat & format,const double * values,const char * const * expected,const DecimalFormat::ERoundingMode * roundingModes,const char * const * descriptions,int32_t valueSize,int32_t roundingModeSize)8055 void NumberFormatTest::verifyRounding(
8056 DecimalFormat& format,
8057 const double *values,
8058 const char * const *expected,
8059 const DecimalFormat::ERoundingMode *roundingModes,
8060 const char * const *descriptions,
8061 int32_t valueSize,
8062 int32_t roundingModeSize) {
8063 for (int32_t i = 0; i < roundingModeSize; ++i) {
8064 format.setRoundingMode(roundingModes[i]);
8065 for (int32_t j = 0; j < valueSize; j++) {
8066 UnicodeString currentExpected(expected[i * valueSize + j]);
8067 currentExpected = currentExpected.unescape();
8068 UnicodeString actual;
8069 format.format(values[j], actual);
8070 if (currentExpected != actual) {
8071 dataerrln("For %s value %f, expected '%s', got '%s'",
8072 descriptions[i], values[j], CStr(currentExpected)(), CStr(actual)());
8073 }
8074 }
8075 }
8076 }
8077
TestAccountingCurrency()8078 void NumberFormatTest::TestAccountingCurrency() {
8079 UErrorCode status = U_ZERO_ERROR;
8080 UNumberFormatStyle style = UNUM_CURRENCY_ACCOUNTING;
8081
8082 expect(NumberFormat::createInstance("en_US", style, status),
8083 (Formattable)(double)1234.5, "$1,234.50", TRUE, status);
8084 expect(NumberFormat::createInstance("en_US", style, status),
8085 (Formattable)(double)-1234.5, "($1,234.50)", TRUE, status);
8086 expect(NumberFormat::createInstance("en_US", style, status),
8087 (Formattable)(double)0, "$0.00", TRUE, status);
8088 expect(NumberFormat::createInstance("en_US", style, status),
8089 (Formattable)(double)-0.2, "($0.20)", TRUE, status);
8090 expect(NumberFormat::createInstance("ja_JP", style, status),
8091 (Formattable)(double)10000, UnicodeString("\\uFFE510,000").unescape(), TRUE, status);
8092 expect(NumberFormat::createInstance("ja_JP", style, status),
8093 (Formattable)(double)-1000.5, UnicodeString("(\\uFFE51,000)").unescape(), FALSE, status);
8094 expect(NumberFormat::createInstance("de_DE", style, status),
8095 (Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status);
8096 expect(NumberFormat::createInstance("en_ID", style, status),
8097 (Formattable)(double)0, UnicodeString("IDR\\u00A00.00").unescape(), TRUE, status);
8098 expect(NumberFormat::createInstance("en_ID", style, status),
8099 (Formattable)(double)-0.2, UnicodeString("(IDR\\u00A00.20)").unescape(), TRUE, status);
8100 expect(NumberFormat::createInstance("sh_ME", style, status),
8101 (Formattable)(double)0, UnicodeString("0,00\\u00A0\\u20AC").unescape(), TRUE, status);
8102 expect(NumberFormat::createInstance("sh_ME", style, status),
8103 (Formattable)(double)-0.2, UnicodeString("(0,20\\u00A0\\u20AC)").unescape(), TRUE, status);
8104 }
8105
8106 /**
8107 * ICU4J has the behavior explained below, but ICU4C is not affected. Test is added to prevent regression.
8108 *
8109 * en_ID/sh_ME uses language only locales en/sh which requires NumberFormatServiceShim to fill in the currency, but
8110 * prior to ICU-20631, currency was not filled in for accounting, cash and standard, so currency placeholder was
8111 * used instead of the desired locale's currency.
8112 */
TestCurrencyFormatForMissingLocale()8113 void NumberFormatTest::TestCurrencyFormatForMissingLocale() {
8114 IcuTestErrorCode status(*this, "TestCurrencyFormatForMissingLocale");
8115 Locale locale = Locale::createCanonical("sh_ME");
8116
8117 LocalPointer<NumberFormat> curFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status));
8118 // Fail here with missing data.
8119 if (!assertTrue(WHERE, curFmt.isValid(), false, true)) {return;};
8120 assertEquals("Currency instance is not for the desired locale for CURRENCYSTYLE", curFmt->getCurrency(), "EUR");
8121 UnicodeString currBuf;
8122 curFmt->format(-1234.5, currBuf);
8123 assertEquals("NumberFormat format outputs wrong value for CURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", currBuf);
8124
8125 LocalPointer<NumberFormat> accFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_ACCOUNTING, status));
8126 assertEquals("Currency instance is not for the desired locale for ACCOUNTINGCURRENCYSTYLE", accFmt->getCurrency(), "EUR");
8127 UnicodeString accBuf;
8128 accFmt->format(-1234.5, accBuf);
8129 assertEquals("NumberFormat format outputs wrong value for ACCOUNTINGCURRENCYSTYLE", u"(1.234,50\u00A0\u20AC)", accBuf);
8130
8131 LocalPointer<NumberFormat> cashFmt(NumberFormat::createInstance(locale, UNUM_CASH_CURRENCY, status));
8132 assertEquals("Currency instance is not for the desired locale for CASHCURRENCYSTYLE", cashFmt->getCurrency(), "EUR");
8133 UnicodeString cashBuf;
8134 cashFmt->format(-1234.5, cashBuf);
8135 assertEquals("NumberFormat format outputs wrong value for CASHCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", cashBuf);
8136
8137 LocalPointer<NumberFormat> stdFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_STANDARD, status));
8138 assertEquals("Currency instance is not for the desired locale for STANDARDCURRENCYSTYLE", stdFmt->getCurrency(), "EUR");
8139 UnicodeString stdBuf;
8140 stdFmt->format(-1234.5, stdBuf);
8141 assertEquals("NumberFormat format outputs wrong value for STANDARDCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", stdBuf);
8142 }
8143
8144 // for #5186
TestEquality()8145 void NumberFormatTest::TestEquality() {
8146 UErrorCode status = U_ZERO_ERROR;
8147 DecimalFormatSymbols symbols(Locale("root"), status);
8148 if (U_FAILURE(status)) {
8149 dataerrln("Fail: can't create DecimalFormatSymbols for root");
8150 return;
8151 }
8152 UnicodeString pattern("#,##0.###");
8153 DecimalFormat fmtBase(pattern, symbols, status);
8154 if (U_FAILURE(status)) {
8155 dataerrln("Fail: can't create DecimalFormat using root symbols");
8156 return;
8157 }
8158
8159 DecimalFormat* fmtClone = fmtBase.clone();
8160 fmtClone->setFormatWidth(fmtBase.getFormatWidth() + 32);
8161 if (*fmtClone == fmtBase) {
8162 errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth");
8163 }
8164 delete fmtClone;
8165 }
8166
TestCurrencyUsage()8167 void NumberFormatTest::TestCurrencyUsage() {
8168 double agent = 123.567;
8169
8170 UErrorCode status;
8171 DecimalFormat *fmt;
8172
8173 // compare the Currency and Currency Cash Digits
8174 // Note that as of CLDR 26:
8175 // * TWD and PKR switched from 0 decimals to 2; ISK still has 0, so change test to that
8176 // * CAD rounds to .05 in cash mode only
8177 // 1st time for getter/setter, 2nd time for factory method
8178 Locale enUS_ISK("en_US@currency=ISK");
8179
8180 for(int i=0; i<2; i++){
8181 status = U_ZERO_ERROR;
8182 if(i == 0){
8183 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CURRENCY, status);
8184 if (assertSuccess("en_US@currency=ISK/CURRENCY", status, TRUE) == FALSE) {
8185 continue;
8186 }
8187
8188 UnicodeString original;
8189 fmt->format(agent,original);
8190 assertEquals("Test Currency Usage 1", u"ISK\u00A0124", original);
8191
8192 // test the getter here
8193 UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8194 assertEquals("Test usage getter - standard", (int32_t)curUsage, (int32_t)UCURR_USAGE_STANDARD);
8195
8196 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8197 }else{
8198 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CASH_CURRENCY, status);
8199 if (assertSuccess("en_US@currency=ISK/CASH", status, TRUE) == FALSE) {
8200 continue;
8201 }
8202 }
8203
8204 // must be usage = cash
8205 UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8206 assertEquals("Test usage getter - cash", (int32_t)curUsage, (int32_t)UCURR_USAGE_CASH);
8207
8208 UnicodeString cash_currency;
8209 fmt->format(agent,cash_currency);
8210 assertEquals("Test Currency Usage 2", u"ISK\u00A0124", cash_currency);
8211 delete fmt;
8212 }
8213
8214 // compare the Currency and Currency Cash Rounding
8215 // 1st time for getter/setter, 2nd time for factory method
8216 Locale enUS_CAD("en_US@currency=CAD");
8217 for(int i=0; i<2; i++){
8218 status = U_ZERO_ERROR;
8219 if(i == 0){
8220 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8221 if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
8222 continue;
8223 }
8224
8225 UnicodeString original_rounding;
8226 fmt->format(agent, original_rounding);
8227 assertEquals("Test Currency Usage 3", u"CA$123.57", original_rounding);
8228 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8229 }else{
8230 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8231 if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
8232 continue;
8233 }
8234 }
8235
8236 UnicodeString cash_rounding_currency;
8237 fmt->format(agent, cash_rounding_currency);
8238 assertEquals("Test Currency Usage 4", u"CA$123.55", cash_rounding_currency);
8239 delete fmt;
8240 }
8241
8242 // Test the currency change
8243 // 1st time for getter/setter, 2nd time for factory method
8244 const UChar CUR_PKR[] = {0x50, 0x4B, 0x52, 0};
8245 for(int i=0; i<2; i++){
8246 status = U_ZERO_ERROR;
8247 if(i == 0){
8248 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8249 if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
8250 continue;
8251 }
8252 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8253 }else{
8254 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8255 if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
8256 continue;
8257 }
8258 }
8259
8260 UnicodeString cur_original;
8261 fmt->setCurrencyUsage(UCURR_USAGE_STANDARD, &status);
8262 fmt->format(agent, cur_original);
8263 assertEquals("Test Currency Usage 5", u"CA$123.57", cur_original);
8264
8265 fmt->setCurrency(CUR_PKR, status);
8266 assertSuccess("Set currency to PKR", status);
8267
8268 UnicodeString PKR_changed;
8269 fmt->format(agent, PKR_changed);
8270 assertEquals("Test Currency Usage 6", u"PKR\u00A0123.57", PKR_changed);
8271 delete fmt;
8272 }
8273 }
8274
8275
8276 // Check the constant MAX_INT64_IN_DOUBLE.
8277 // The value should convert to a double with no loss of precision.
8278 // A failure may indicate a platform with a different double format, requiring
8279 // a revision to the constant.
8280 //
8281 // Note that this is actually hard to test, because the language standard gives
8282 // compilers considerable flexibility to do unexpected things with rounding and
8283 // with overflow in simple int to/from float conversions. Some compilers will completely optimize
8284 // away a simple round-trip conversion from int64_t -> double -> int64_t.
8285
TestDoubleLimit11439()8286 void NumberFormatTest::TestDoubleLimit11439() {
8287 char buf[50];
8288 for (int64_t num = MAX_INT64_IN_DOUBLE-10; num<=MAX_INT64_IN_DOUBLE; num++) {
8289 sprintf(buf, "%lld", (long long)num);
8290 double fNum = 0.0;
8291 sscanf(buf, "%lf", &fNum);
8292 int64_t rtNum = static_cast<int64_t>(fNum);
8293 if (num != rtNum) {
8294 errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8295 return;
8296 }
8297 }
8298 for (int64_t num = -MAX_INT64_IN_DOUBLE+10; num>=-MAX_INT64_IN_DOUBLE; num--) {
8299 sprintf(buf, "%lld", (long long)num);
8300 double fNum = 0.0;
8301 sscanf(buf, "%lf", &fNum);
8302 int64_t rtNum = static_cast<int64_t>(fNum);
8303 if (num != rtNum) {
8304 errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8305 return;
8306 }
8307 }
8308 }
8309
TestGetAffixes()8310 void NumberFormatTest::TestGetAffixes() {
8311 UErrorCode status = U_ZERO_ERROR;
8312 DecimalFormatSymbols sym("en_US", status);
8313 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8314 pattern = pattern.unescape();
8315 DecimalFormat fmt(pattern, sym, status);
8316 if (U_FAILURE(status)) {
8317 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8318 return;
8319 }
8320 UnicodeString affixStr;
8321 assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8322 assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8323 assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8324 assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8325
8326 // Test equality with affixes. set affix methods can't capture special
8327 // characters which is why equality should fail.
8328 {
8329 DecimalFormat fmtCopy(fmt);
8330 assertTrue("", fmt == fmtCopy);
8331 UnicodeString someAffix;
8332 fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(someAffix));
8333 assertTrue("", fmt != fmtCopy);
8334 }
8335 {
8336 DecimalFormat fmtCopy(fmt);
8337 assertTrue("", fmt == fmtCopy);
8338 UnicodeString someAffix;
8339 fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(someAffix));
8340 assertTrue("", fmt != fmtCopy);
8341 }
8342 {
8343 DecimalFormat fmtCopy(fmt);
8344 assertTrue("", fmt == fmtCopy);
8345 UnicodeString someAffix;
8346 fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(someAffix));
8347 assertTrue("", fmt != fmtCopy);
8348 }
8349 {
8350 DecimalFormat fmtCopy(fmt);
8351 assertTrue("", fmt == fmtCopy);
8352 UnicodeString someAffix;
8353 fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(someAffix));
8354 assertTrue("", fmt != fmtCopy);
8355 }
8356 fmt.setPositivePrefix("Don't");
8357 fmt.setPositiveSuffix("do");
8358 UnicodeString someAffix("be''eet\\u00a4\\u00a4\\u00a4 it.");
8359 someAffix = someAffix.unescape();
8360 fmt.setNegativePrefix(someAffix);
8361 fmt.setNegativeSuffix("%");
8362 assertEquals("", "Don't", fmt.getPositivePrefix(affixStr));
8363 assertEquals("", "do", fmt.getPositiveSuffix(affixStr));
8364 assertEquals("", someAffix, fmt.getNegativePrefix(affixStr));
8365 assertEquals("", "%", fmt.getNegativeSuffix(affixStr));
8366 }
8367
TestToPatternScientific11648()8368 void NumberFormatTest::TestToPatternScientific11648() {
8369 UErrorCode status = U_ZERO_ERROR;
8370 Locale en("en");
8371 DecimalFormatSymbols sym(en, status);
8372 DecimalFormat fmt("0.00", sym, status);
8373 if (U_FAILURE(status)) {
8374 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8375 return;
8376 }
8377 fmt.setScientificNotation(TRUE);
8378 UnicodeString pattern;
8379 assertEquals("", "0.00E0", fmt.toPattern(pattern));
8380 DecimalFormat fmt2(pattern, sym, status);
8381 assertSuccess("", status);
8382 }
8383
TestBenchmark()8384 void NumberFormatTest::TestBenchmark() {
8385 /*
8386 UErrorCode status = U_ZERO_ERROR;
8387 Locale en("en");
8388 DecimalFormatSymbols sym(en, status);
8389 DecimalFormat fmt("0.0000000", new DecimalFormatSymbols(sym), status);
8390 // DecimalFormat fmt("0.00000E0", new DecimalFormatSymbols(sym), status);
8391 // DecimalFormat fmt("0", new DecimalFormatSymbols(sym), status);
8392 FieldPosition fpos(FieldPosition::DONT_CARE);
8393 clock_t start = clock();
8394 for (int32_t i = 0; i < 1000000; ++i) {
8395 UnicodeString append;
8396 fmt.format(3.0, append, fpos, status);
8397 // fmt.format(4.6692016, append, fpos, status);
8398 // fmt.format(1234567.8901, append, fpos, status);
8399 // fmt.format(2.99792458E8, append, fpos, status);
8400 // fmt.format(31, append);
8401 }
8402 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8403 assertSuccess("", status);
8404
8405 UErrorCode status = U_ZERO_ERROR;
8406 MessageFormat fmt("{0, plural, one {I have # friend.} other {I have # friends.}}", status);
8407 FieldPosition fpos(FieldPosition::DONT_CARE);
8408 Formattable one(1.0);
8409 Formattable three(3.0);
8410 clock_t start = clock();
8411 for (int32_t i = 0; i < 500000; ++i) {
8412 UnicodeString append;
8413 fmt.format(&one, 1, append, fpos, status);
8414 UnicodeString append2;
8415 fmt.format(&three, 1, append2, fpos, status);
8416 }
8417 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8418 assertSuccess("", status);
8419
8420 UErrorCode status = U_ZERO_ERROR;
8421 Locale en("en");
8422 Measure measureC(23, MeasureUnit::createCelsius(status), status);
8423 MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
8424 FieldPosition fpos(FieldPosition::DONT_CARE);
8425 clock_t start = clock();
8426 for (int32_t i = 0; i < 1000000; ++i) {
8427 UnicodeString appendTo;
8428 fmt.formatMeasures(
8429 &measureC, 1, appendTo, fpos, status);
8430 }
8431 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8432 assertSuccess("", status);
8433 */
8434 }
8435
TestFractionalDigitsForCurrency()8436 void NumberFormatTest::TestFractionalDigitsForCurrency() {
8437 UErrorCode status = U_ZERO_ERROR;
8438 LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance("en", status));
8439 if (U_FAILURE(status)) {
8440 dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8441 return;
8442 }
8443 UChar JPY[] = {0x4A, 0x50, 0x59, 0x0};
8444 fmt->setCurrency(JPY, status);
8445 if (!assertSuccess("", status)) {
8446 return;
8447 }
8448 assertEquals("", 0, fmt->getMaximumFractionDigits());
8449 }
8450
8451
TestFormatCurrencyPlural()8452 void NumberFormatTest::TestFormatCurrencyPlural() {
8453 UErrorCode status = U_ZERO_ERROR;
8454 Locale locale = Locale::createCanonical("en_US");
8455 NumberFormat *fmt = NumberFormat::createInstance(locale, UNUM_CURRENCY_PLURAL, status);
8456 if (U_FAILURE(status)) {
8457 dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8458 return;
8459 }
8460 UnicodeString formattedNum;
8461 fmt->format(11234.567, formattedNum, NULL, status);
8462 assertEquals("", "11,234.57 US dollars", formattedNum);
8463 delete fmt;
8464 }
8465
TestCtorApplyPatternDifference()8466 void NumberFormatTest::TestCtorApplyPatternDifference() {
8467 UErrorCode status = U_ZERO_ERROR;
8468 DecimalFormatSymbols sym("en_US", status);
8469 UnicodeString pattern("\\u00a40");
8470 DecimalFormat fmt(pattern.unescape(), sym, status);
8471 if (U_FAILURE(status)) {
8472 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8473 return;
8474 }
8475 UnicodeString result;
8476 assertEquals(
8477 "ctor favors precision of currency",
8478 "$5.00",
8479 fmt.format((double)5, result));
8480 result.remove();
8481 fmt.applyPattern(pattern.unescape(), status);
8482 assertEquals(
8483 "applyPattern favors precision of pattern",
8484 "$5",
8485 fmt.format((double)5, result));
8486 }
8487
Test11868()8488 void NumberFormatTest::Test11868() {
8489 double posAmt = 34.567;
8490 double negAmt = -9876.543;
8491
8492 Locale selectedLocale("en_US");
8493 UErrorCode status = U_ZERO_ERROR;
8494
8495 UnicodeString result;
8496 FieldPosition fpCurr(UNUM_CURRENCY_FIELD);
8497 LocalPointer<NumberFormat> fmt(
8498 NumberFormat::createInstance(
8499 selectedLocale, UNUM_CURRENCY_PLURAL, status));
8500 if (!assertSuccess("Format creation", status)) {
8501 return;
8502 }
8503 fmt->format(posAmt, result, fpCurr, status);
8504 assertEquals("", "34.57 US dollars", result);
8505 assertEquals("begin index", 6, fpCurr.getBeginIndex());
8506 assertEquals("end index", 16, fpCurr.getEndIndex());
8507
8508 // Test field position iterator
8509 {
8510 NumberFormatTest_Attributes attributes[] = {
8511 {UNUM_INTEGER_FIELD, 0, 2},
8512 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8513 {UNUM_FRACTION_FIELD, 3, 5},
8514 {UNUM_CURRENCY_FIELD, 6, 16},
8515 {0, -1, 0}};
8516 UnicodeString result;
8517 FieldPositionIterator iter;
8518 fmt->format(posAmt, result, &iter, status);
8519 assertEquals("", "34.57 US dollars", result);
8520 verifyFieldPositionIterator(attributes, iter);
8521 }
8522
8523 result.remove();
8524 fmt->format(negAmt, result, fpCurr, status);
8525 assertEquals("", "-9,876.54 US dollars", result);
8526 assertEquals("begin index", 10, fpCurr.getBeginIndex());
8527 assertEquals("end index", 20, fpCurr.getEndIndex());
8528
8529 // Test field position iterator
8530 {
8531 NumberFormatTest_Attributes attributes[] = {
8532 {UNUM_SIGN_FIELD, 0, 1},
8533 {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
8534 {UNUM_INTEGER_FIELD, 1, 6},
8535 {UNUM_DECIMAL_SEPARATOR_FIELD, 6, 7},
8536 {UNUM_FRACTION_FIELD, 7, 9},
8537 {UNUM_CURRENCY_FIELD, 10, 20},
8538 {0, -1, 0}};
8539 UnicodeString result;
8540 FieldPositionIterator iter;
8541 fmt->format(negAmt, result, &iter, status);
8542 assertEquals("", "-9,876.54 US dollars", result);
8543 verifyFieldPositionIterator(attributes, iter);
8544 }
8545 }
8546
Test10727_RoundingZero()8547 void NumberFormatTest::Test10727_RoundingZero() {
8548 IcuTestErrorCode status(*this, "Test10727_RoundingZero");
8549 DecimalQuantity dq;
8550 dq.setToDouble(-0.0);
8551 assertTrue("", dq.isNegative());
8552 dq.roundToMagnitude(0, UNUM_ROUND_HALFEVEN, status);
8553 assertTrue("", dq.isNegative());
8554 }
8555
Test11739_ParseLongCurrency()8556 void NumberFormatTest::Test11739_ParseLongCurrency() {
8557 IcuTestErrorCode status(*this, "Test11739_ParseLongCurrency");
8558 LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("sr_BA", status));
8559 if (status.errDataIfFailureAndReset()) { return; }
8560 ((DecimalFormat*) nf.getAlias())->applyPattern(u"#,##0.0 ¤¤¤", status);
8561 ParsePosition ppos(0);
8562 LocalPointer<CurrencyAmount> result(nf->parseCurrency(u"1.500 амерички долар", ppos));
8563 assertEquals("Should parse to 1500 USD", -1, ppos.getErrorIndex());
8564 if (ppos.getErrorIndex() != -1) {
8565 return;
8566 }
8567 assertEquals("Should parse to 1500 USD", 1500LL, result->getNumber().getInt64(status));
8568 assertEquals("Should parse to 1500 USD", u"USD", result->getISOCurrency());
8569 }
8570
Test13035_MultiCodePointPaddingInPattern()8571 void NumberFormatTest::Test13035_MultiCodePointPaddingInPattern() {
8572 IcuTestErrorCode status(*this, "Test13035_MultiCodePointPaddingInPattern");
8573 DecimalFormat df(u"a*'நி'###0b", status);
8574 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8575 UnicodeString result;
8576 df.format(12, result.remove());
8577 // TODO(13034): Re-enable this test when support is added in ICU4C.
8578 //assertEquals("Multi-codepoint padding should not be split", u"aநிநி12b", result);
8579 df = DecimalFormat(u"a*\U0001F601###0b", status);
8580 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8581 result = df.format(12, result.remove());
8582 assertEquals("Single-codepoint padding should not be split", u"a\U0001F601\U0001F60112b", result, true);
8583 df = DecimalFormat(u"a*''###0b", status);
8584 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8585 result = df.format(12, result.remove());
8586 assertEquals("Quote should be escapable in padding syntax", "a''12b", result, true);
8587 }
8588
Test13737_ParseScientificStrict()8589 void NumberFormatTest::Test13737_ParseScientificStrict() {
8590 IcuTestErrorCode status(*this, "Test13737_ParseScientificStrict");
8591 LocalPointer<NumberFormat> df(NumberFormat::createScientificInstance("en", status), status);
8592 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8593 df->setLenient(FALSE);
8594 // Parse Test
8595 expect(*df, u"1.2", 1.2);
8596 }
8597
Test11376_getAndSetPositivePrefix()8598 void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
8599 {
8600 const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8601 UErrorCode status = U_ZERO_ERROR;
8602 LocalPointer<NumberFormat> fmt(
8603 NumberFormat::createCurrencyInstance("en", status));
8604 if (!assertSuccess("", status)) {
8605 return;
8606 }
8607 DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8608 dfmt->setCurrency(USD);
8609 UnicodeString result;
8610
8611 // This line should be a no-op. I am setting the positive prefix
8612 // to be the same thing it was before.
8613 dfmt->setPositivePrefix(dfmt->getPositivePrefix(result));
8614
8615 UnicodeString appendTo;
8616 assertEquals("", "$3.78", dfmt->format(3.78, appendTo, status));
8617 assertSuccess("", status);
8618 }
8619 {
8620 const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8621 UErrorCode status = U_ZERO_ERROR;
8622 LocalPointer<NumberFormat> fmt(
8623 NumberFormat::createInstance("en", UNUM_CURRENCY_PLURAL, status));
8624 if (!assertSuccess("", status)) {
8625 return;
8626 }
8627 DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8628 UnicodeString result;
8629 assertEquals("", u" (unknown currency)", dfmt->getPositiveSuffix(result));
8630 dfmt->setCurrency(USD);
8631
8632 // getPositiveSuffix() always returns the suffix for the
8633 // "other" plural category
8634 assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8635 UnicodeString appendTo;
8636 assertEquals("", "3.78 US dollars", dfmt->format(3.78, appendTo, status));
8637 assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8638 dfmt->setPositiveSuffix("booya");
8639 appendTo.remove();
8640 assertEquals("", "3.78booya", dfmt->format(3.78, appendTo, status));
8641 assertEquals("", "booya", dfmt->getPositiveSuffix(result));
8642 }
8643 }
8644
Test11475_signRecognition()8645 void NumberFormatTest::Test11475_signRecognition() {
8646 UErrorCode status = U_ZERO_ERROR;
8647 DecimalFormatSymbols sym("en", status);
8648 UnicodeString result;
8649 {
8650 DecimalFormat fmt("+0.00", sym, status);
8651 if (!assertSuccess("", status)) {
8652 return;
8653 }
8654 NumberFormatTest_Attributes attributes[] = {
8655 {UNUM_SIGN_FIELD, 0, 1},
8656 {UNUM_INTEGER_FIELD, 1, 2},
8657 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8658 {UNUM_FRACTION_FIELD, 3, 5},
8659 {0, -1, 0}};
8660 UnicodeString result;
8661 FieldPositionIterator iter;
8662 fmt.format(2.3, result, &iter, status);
8663 assertEquals("", "+2.30", result);
8664 verifyFieldPositionIterator(attributes, iter);
8665 }
8666 {
8667 DecimalFormat fmt("++0.00+;-(#)--", sym, status);
8668 if (!assertSuccess("", status)) {
8669 return;
8670 }
8671 {
8672 NumberFormatTest_Attributes attributes[] = {
8673 {UNUM_SIGN_FIELD, 0, 2},
8674 {UNUM_INTEGER_FIELD, 2, 3},
8675 {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8676 {UNUM_FRACTION_FIELD, 4, 6},
8677 {UNUM_SIGN_FIELD, 6, 7},
8678 {0, -1, 0}};
8679 UnicodeString result;
8680 FieldPositionIterator iter;
8681 fmt.format(2.3, result, &iter, status);
8682 assertEquals("", "++2.30+", result);
8683 verifyFieldPositionIterator(attributes, iter);
8684 }
8685 {
8686 NumberFormatTest_Attributes attributes[] = {
8687 {UNUM_SIGN_FIELD, 0, 1},
8688 {UNUM_INTEGER_FIELD, 2, 3},
8689 {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8690 {UNUM_FRACTION_FIELD, 4, 6},
8691 {UNUM_SIGN_FIELD, 7, 9},
8692 {0, -1, 0}};
8693 UnicodeString result;
8694 FieldPositionIterator iter;
8695 fmt.format(-2.3, result, &iter, status);
8696 assertEquals("", "-(2.30)--", result);
8697 verifyFieldPositionIterator(attributes, iter);
8698 }
8699 }
8700 }
8701
Test11640_getAffixes()8702 void NumberFormatTest::Test11640_getAffixes() {
8703 UErrorCode status = U_ZERO_ERROR;
8704 DecimalFormatSymbols symbols("en_US", status);
8705 if (!assertSuccess("", status)) {
8706 return;
8707 }
8708 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8709 pattern = pattern.unescape();
8710 DecimalFormat fmt(pattern, symbols, status);
8711 if (!assertSuccess("", status)) {
8712 return;
8713 }
8714 UnicodeString affixStr;
8715 assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8716 assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8717 assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8718 assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8719 }
8720
Test11649_toPatternWithMultiCurrency()8721 void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
8722 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
8723 pattern = pattern.unescape();
8724 UErrorCode status = U_ZERO_ERROR;
8725 DecimalFormat fmt(pattern, status);
8726 if (!assertSuccess("", status)) {
8727 return;
8728 }
8729 static UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8730 fmt.setCurrency(USD);
8731 UnicodeString appendTo;
8732
8733 assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
8734
8735 UnicodeString topattern;
8736 fmt.toPattern(topattern);
8737 DecimalFormat fmt2(topattern, status);
8738 if (!assertSuccess("", status)) {
8739 return;
8740 }
8741 fmt2.setCurrency(USD);
8742
8743 appendTo.remove();
8744 assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
8745 }
8746
Test13327_numberingSystemBufferOverflow()8747 void NumberFormatTest::Test13327_numberingSystemBufferOverflow() {
8748 UErrorCode status = U_ZERO_ERROR;
8749 for (int runId = 0; runId < 2; runId++) {
8750 // Construct a locale string with a very long "numbers" value.
8751 // The first time, make the value length exactly equal to ULOC_KEYWORDS_CAPACITY.
8752 // The second time, make it exceed ULOC_KEYWORDS_CAPACITY.
8753 int extraLength = (runId == 0) ? 0 : 5;
8754
8755 CharString localeId("en@numbers=", status);
8756 for (int i = 0; i < ULOC_KEYWORDS_CAPACITY + extraLength; i++) {
8757 localeId.append('x', status);
8758 }
8759 assertSuccess("Constructing locale string", status);
8760 Locale locale(localeId.data());
8761
8762 LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(locale, status));
8763 assertFalse("Should not be null", ns.getAlias() == nullptr);
8764 assertSuccess("Should create with no error", status);
8765 }
8766 }
8767
Test13391_chakmaParsing()8768 void NumberFormatTest::Test13391_chakmaParsing() {
8769 UErrorCode status = U_ZERO_ERROR;
8770 LocalPointer<DecimalFormat> df(dynamic_cast<DecimalFormat*>(
8771 NumberFormat::createInstance(Locale("ccp"), status)));
8772 if (df == nullptr) {
8773 dataerrln("%s %d Chakma df is null", __FILE__, __LINE__);
8774 return;
8775 }
8776 const UChar* expected = u"\U00011137\U00011138,\U00011139\U0001113A\U0001113B";
8777 UnicodeString actual;
8778 df->format(12345, actual, status);
8779 assertSuccess("Should not fail when formatting in ccp", status);
8780 assertEquals("Should produce expected output in ccp", expected, actual);
8781
8782 Formattable result;
8783 df->parse(expected, result, status);
8784 assertSuccess("Should not fail when parsing in ccp", status);
8785 assertEquals("Should parse to 12345 in ccp", 12345, result);
8786
8787 const UChar* expectedScientific = u"\U00011137.\U00011139E\U00011138";
8788 UnicodeString actualScientific;
8789 df.adoptInstead(static_cast<DecimalFormat*>(
8790 NumberFormat::createScientificInstance(Locale("ccp"), status)));
8791 df->format(130, actualScientific, status);
8792 assertSuccess("Should not fail when formatting scientific in ccp", status);
8793 assertEquals("Should produce expected scientific output in ccp",
8794 expectedScientific, actualScientific);
8795
8796 Formattable resultScientific;
8797 df->parse(expectedScientific, resultScientific, status);
8798 assertSuccess("Should not fail when parsing scientific in ccp", status);
8799 assertEquals("Should parse scientific to 130 in ccp", 130, resultScientific);
8800 }
8801
8802
verifyFieldPositionIterator(NumberFormatTest_Attributes * expected,FieldPositionIterator & iter)8803 void NumberFormatTest::verifyFieldPositionIterator(
8804 NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
8805 int32_t idx = 0;
8806 FieldPosition fp;
8807 while (iter.next(fp)) {
8808 if (expected[idx].spos == -1) {
8809 errln("Iterator should have ended. got %d", fp.getField());
8810 return;
8811 }
8812 assertEquals("id", expected[idx].id, fp.getField());
8813 assertEquals("start", expected[idx].spos, fp.getBeginIndex());
8814 assertEquals("end", expected[idx].epos, fp.getEndIndex());
8815 ++idx;
8816 }
8817 if (expected[idx].spos != -1) {
8818 errln("Premature end of iterator. expected %d", expected[idx].id);
8819 }
8820 }
8821
Test11735_ExceptionIssue()8822 void NumberFormatTest::Test11735_ExceptionIssue() {
8823 IcuTestErrorCode status(*this, "Test11735_ExceptionIssue");
8824 Locale enLocale("en");
8825 DecimalFormatSymbols symbols(enLocale, status);
8826 if (status.isSuccess()) {
8827 DecimalFormat fmt("0", symbols, status);
8828 assertSuccess("Fail: Construct DecimalFormat formatter", status, true, __FILE__, __LINE__);
8829 ParsePosition ppos(0);
8830 fmt.parseCurrency("53.45", ppos); // NPE thrown here in ICU4J.
8831 assertEquals("Issue11735 ppos", 0, ppos.getIndex());
8832 }
8833 }
8834
Test11035_FormatCurrencyAmount()8835 void NumberFormatTest::Test11035_FormatCurrencyAmount() {
8836 UErrorCode status = U_ZERO_ERROR;
8837 double amount = 12345.67;
8838 const char16_t* expected = u"12,345$67 ";
8839
8840 // Test two ways to set a currency via API
8841
8842 Locale loc1 = Locale("pt_PT");
8843 LocalPointer<NumberFormat> fmt1(NumberFormat::createCurrencyInstance(loc1, status),
8844 status);
8845 if (U_FAILURE(status)) {
8846 dataerrln("%s %d NumberFormat instance fmt1 is null", __FILE__, __LINE__);
8847 return;
8848 }
8849 fmt1->setCurrency(u"PTE", status);
8850 assertSuccess("Setting currency on fmt1", status);
8851 UnicodeString actualSetCurrency;
8852 fmt1->format(amount, actualSetCurrency);
8853
8854 Locale loc2 = Locale("pt_PT@currency=PTE");
8855 LocalPointer<NumberFormat> fmt2(NumberFormat::createCurrencyInstance(loc2, status));
8856 assertSuccess("Creating fmt2", status);
8857 UnicodeString actualLocaleString;
8858 fmt2->format(amount, actualLocaleString);
8859
8860 assertEquals("Custom Currency Pattern, Set Currency", expected, actualSetCurrency);
8861 assertEquals("Custom Currency Pattern, Locale String", expected, actualLocaleString);
8862 }
8863
Test11318_DoubleConversion()8864 void NumberFormatTest::Test11318_DoubleConversion() {
8865 IcuTestErrorCode status(*this, "Test11318_DoubleConversion");
8866 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
8867 if (U_FAILURE(status)) {
8868 dataerrln("%s %d Error in NumberFormat instance creation", __FILE__, __LINE__);
8869 return;
8870 }
8871 nf->setMaximumFractionDigits(40);
8872 nf->setMaximumIntegerDigits(40);
8873 UnicodeString appendTo;
8874 nf->format(999999999999999.9, appendTo);
8875 assertEquals("Should render all digits", u"999,999,999,999,999.9", appendTo);
8876 }
8877
TestParsePercentRegression()8878 void NumberFormatTest::TestParsePercentRegression() {
8879 IcuTestErrorCode status(*this, "TestParsePercentRegression");
8880 LocalPointer<DecimalFormat> df1((DecimalFormat*) NumberFormat::createInstance("en", status), status);
8881 LocalPointer<DecimalFormat> df2((DecimalFormat*) NumberFormat::createPercentInstance("en", status), status);
8882 if (status.isFailure()) {return; }
8883 df1->setLenient(TRUE);
8884 df2->setLenient(TRUE);
8885
8886 {
8887 ParsePosition ppos;
8888 Formattable result;
8889 df1->parse("50%", result, ppos);
8890 assertEquals("df1 should accept a number but not the percent sign", 2, ppos.getIndex());
8891 assertEquals("df1 should return the number as 50", 50.0, result.getDouble(status));
8892 }
8893 {
8894 ParsePosition ppos;
8895 Formattable result;
8896 df2->parse("50%", result, ppos);
8897 assertEquals("df2 should accept the percent sign", 3, ppos.getIndex());
8898 assertEquals("df2 should return the number as 0.5", 0.5, result.getDouble(status));
8899 }
8900 {
8901 ParsePosition ppos;
8902 Formattable result;
8903 df2->parse("50", result, ppos);
8904 assertEquals("df2 should return the number as 0.5 even though the percent sign is missing",
8905 0.5,
8906 result.getDouble(status));
8907 }
8908 }
8909
TestMultiplierWithScale()8910 void NumberFormatTest::TestMultiplierWithScale() {
8911 IcuTestErrorCode status(*this, "TestMultiplierWithScale");
8912
8913 // Test magnitude combined with multiplier, as shown in API docs
8914 DecimalFormat df("0", {"en", status}, status);
8915 if (status.isSuccess()) {
8916 df.setMultiplier(5);
8917 df.setMultiplierScale(-1);
8918 expect2(df, 100, u"50"); // round-trip test
8919 }
8920 }
8921
TestFastFormatInt32()8922 void NumberFormatTest::TestFastFormatInt32() {
8923 IcuTestErrorCode status(*this, "TestFastFormatInt32");
8924
8925 // The two simplest formatters, old API and new API.
8926 // Old API should use the fastpath for ints.
8927 LocalizedNumberFormatter lnf = NumberFormatter::withLocale("en");
8928 LocalPointer<NumberFormat> df(NumberFormat::createInstance("en", status), status);
8929 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8930
8931 double nums[] = {
8932 0.0,
8933 -0.0,
8934 NAN,
8935 INFINITY,
8936 0.1,
8937 1.0,
8938 1.1,
8939 2.0,
8940 3.0,
8941 9.0,
8942 10.0,
8943 99.0,
8944 100.0,
8945 999.0,
8946 1000.0,
8947 9999.0,
8948 10000.0,
8949 99999.0,
8950 100000.0,
8951 999999.0,
8952 1000000.0,
8953 static_cast<double>(INT32_MAX) - 1,
8954 static_cast<double>(INT32_MAX),
8955 static_cast<double>(INT32_MAX) + 1,
8956 static_cast<double>(INT32_MIN) - 1,
8957 static_cast<double>(INT32_MIN),
8958 static_cast<double>(INT32_MIN) + 1};
8959
8960 for (auto num : nums) {
8961 UnicodeString expected = lnf.formatDouble(num, status).toString(status);
8962 UnicodeString actual;
8963 df->format(num, actual);
8964 assertEquals(UnicodeString("d = ") + num, expected, actual);
8965 }
8966 }
8967
Test11646_Equality()8968 void NumberFormatTest::Test11646_Equality() {
8969 UErrorCode status = U_ZERO_ERROR;
8970 DecimalFormatSymbols symbols(Locale::getEnglish(), status);
8971 UnicodeString pattern(u"\u00a4\u00a4\u00a4 0.00 %\u00a4\u00a4");
8972 DecimalFormat fmt(pattern, symbols, status);
8973 if (!assertSuccess("", status)) return;
8974
8975 // Test equality with affixes. set affix methods can't capture special
8976 // characters which is why equality should fail.
8977 {
8978 DecimalFormat fmtCopy(fmt);
8979 assertTrue("", fmt == fmtCopy);
8980 UnicodeString positivePrefix;
8981 fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(positivePrefix));
8982 assertFalse("", fmt == fmtCopy);
8983 }
8984 {
8985 DecimalFormat fmtCopy = DecimalFormat(fmt);
8986 assertTrue("", fmt == fmtCopy);
8987 UnicodeString positivePrefix;
8988 fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(positivePrefix));
8989 assertFalse("", fmt == fmtCopy);
8990 }
8991 {
8992 DecimalFormat fmtCopy(fmt);
8993 assertTrue("", fmt == fmtCopy);
8994 UnicodeString negativePrefix;
8995 fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(negativePrefix));
8996 assertFalse("", fmt == fmtCopy);
8997 }
8998 {
8999 DecimalFormat fmtCopy(fmt);
9000 assertTrue("", fmt == fmtCopy);
9001 UnicodeString negativePrefix;
9002 fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(negativePrefix));
9003 assertFalse("", fmt == fmtCopy);
9004 }
9005 }
9006
TestParseNaN()9007 void NumberFormatTest::TestParseNaN() {
9008 IcuTestErrorCode status(*this, "TestParseNaN");
9009
9010 DecimalFormat df("0", { "en", status }, status);
9011 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9012 Formattable parseResult;
9013 df.parse(u"NaN", parseResult, status);
9014 assertEquals("NaN should parse successfully", NAN, parseResult.getDouble());
9015 assertFalse("Result NaN should be positive", std::signbit(parseResult.getDouble()));
9016 UnicodeString formatResult;
9017 df.format(parseResult.getDouble(), formatResult);
9018 assertEquals("NaN should round-trip", u"NaN", formatResult);
9019 }
9020
TestFormatFailIfMoreThanMaxDigits()9021 void NumberFormatTest::TestFormatFailIfMoreThanMaxDigits() {
9022 IcuTestErrorCode status(*this, "TestFormatFailIfMoreThanMaxDigits");
9023
9024 DecimalFormat df("0", {"en-US", status}, status);
9025 if (status.errDataIfFailureAndReset()) {
9026 return;
9027 }
9028 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isFormatFailIfMoreThanMaxDigits());
9029 df.setFormatFailIfMoreThanMaxDigits(TRUE);
9030 assertEquals("Coverage for getter 2", (UBool) TRUE, df.isFormatFailIfMoreThanMaxDigits());
9031 df.setMaximumIntegerDigits(2);
9032 UnicodeString result;
9033 df.format(1234, result, status);
9034 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
9035 }
9036
TestParseCaseSensitive()9037 void NumberFormatTest::TestParseCaseSensitive() {
9038 IcuTestErrorCode status(*this, "TestParseCaseSensitive");
9039
9040 DecimalFormat df(u"0", {"en-US", status}, status);
9041 if (status.errDataIfFailureAndReset()) {
9042 return;
9043 }
9044 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isParseCaseSensitive());
9045 df.setParseCaseSensitive(TRUE);
9046 assertEquals("Coverage for getter 1", (UBool) TRUE, df.isParseCaseSensitive());
9047 Formattable result;
9048 ParsePosition ppos;
9049 df.parse(u"1e2", result, ppos);
9050 assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9051 assertEquals("Result should be 1", 1.0, result.getDouble(status));
9052 }
9053
TestParseNoExponent()9054 void NumberFormatTest::TestParseNoExponent() {
9055 IcuTestErrorCode status(*this, "TestParseNoExponent");
9056
9057 DecimalFormat df(u"0", {"en-US", status}, status);
9058 if (status.errDataIfFailureAndReset()) {
9059 return;
9060 }
9061 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isParseNoExponent());
9062 df.setParseNoExponent(TRUE);
9063 assertEquals("Coverage for getter 1", (UBool) TRUE, df.isParseNoExponent());
9064 Formattable result;
9065 ParsePosition ppos;
9066 df.parse(u"1E2", result, ppos);
9067 assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9068 assertEquals("Result should be 1", 1.0, result.getDouble(status));
9069 }
9070
TestSignAlwaysShown()9071 void NumberFormatTest::TestSignAlwaysShown() {
9072 IcuTestErrorCode status(*this, "TestSignAlwaysShown");
9073
9074 DecimalFormat df(u"0", {"en-US", status}, status);
9075 if (status.errDataIfFailureAndReset()) {
9076 return;
9077 }
9078 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isSignAlwaysShown());
9079 df.setSignAlwaysShown(TRUE);
9080 assertEquals("Coverage for getter 1", (UBool) TRUE, df.isSignAlwaysShown());
9081 UnicodeString result;
9082 df.format(1234, result, status);
9083 status.errIfFailureAndReset();
9084 assertEquals("Should show sign on positive number", u"+1234", result);
9085 }
9086
TestMinimumGroupingDigits()9087 void NumberFormatTest::TestMinimumGroupingDigits() {
9088 IcuTestErrorCode status(*this, "TestMinimumGroupingDigits");
9089
9090 DecimalFormat df(u"#,##0", {"en-US", status}, status);
9091 if (status.errDataIfFailureAndReset()) {
9092 return;
9093 }
9094 assertEquals("Coverage for getter 1", -1, df.getMinimumGroupingDigits());
9095 df.setMinimumGroupingDigits(2);
9096 assertEquals("Coverage for getter 1", 2, df.getMinimumGroupingDigits());
9097 UnicodeString result;
9098 df.format(1234, result, status);
9099 status.errIfFailureAndReset();
9100 assertEquals("Should not have grouping", u"1234", result);
9101 df.format(12345, result.remove(), status);
9102 status.errIfFailureAndReset();
9103 assertEquals("Should have grouping", u"12,345", result);
9104
9105
9106 // Test special values -1, UNUM_MINIMUM_GROUPING_DIGITS_AUTO and
9107 // UNUM_MINIMUM_GROUPING_DIGITS_MIN2
9108 struct TestCase {
9109 const char* locale;
9110 int32_t minGroup;
9111 double input;
9112 const char16_t* expected;
9113 } cases[] = {
9114 { "en-US", 1, 1000, u"1,000" },
9115 { "en-US", 1, 10000, u"10,000" },
9116 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1,000" },
9117 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10,000" },
9118 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9119 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10,000" },
9120
9121 { "es", 1, 1000, u"1.000" },
9122 { "es", 1, 10000, u"10.000" },
9123 { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1000" },
9124 { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10.000" },
9125 { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9126 { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10.000" },
9127 };
9128 for (const auto& cas : cases) {
9129 UnicodeString message = UnicodeString(cas.locale)
9130 + u" " + Int64ToUnicodeString(cas.minGroup)
9131 + u" " + DoubleToUnicodeString(cas.input);
9132 status.setScope(message);
9133 DecimalFormat df(u"#,##0", {cas.locale, status}, status);
9134 if (status.errIfFailureAndReset()) { continue; }
9135 df.setMinimumGroupingDigits(cas.minGroup);
9136 UnicodeString actual;
9137 df.format(cas.input, actual, status);
9138 if (status.errIfFailureAndReset()) { continue; }
9139 assertEquals(message, cas.expected, actual);
9140 }
9141 }
9142
Test11897_LocalizedPatternSeparator()9143 void NumberFormatTest::Test11897_LocalizedPatternSeparator() {
9144 IcuTestErrorCode status(*this, "Test11897_LocalizedPatternSeparator");
9145
9146 // In a locale with a different <list> symbol, like arabic,
9147 // kPatternSeparatorSymbol should still be ';'
9148 {
9149 DecimalFormatSymbols dfs("ar", status);
9150 assertEquals("pattern separator symbol should be ;",
9151 u";",
9152 dfs.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
9153 }
9154
9155 // However, the custom symbol should be used in localized notation
9156 // when set manually via API
9157 {
9158 DecimalFormatSymbols dfs("en", status);
9159 dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u"!", FALSE);
9160 DecimalFormat df(u"0", dfs, status);
9161 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9162 df.applyPattern("a0;b0", status); // should not throw
9163 UnicodeString result;
9164 assertEquals("should apply the normal pattern",
9165 df.getNegativePrefix(result.remove()),
9166 "b");
9167 df.applyLocalizedPattern(u"c0!d0", status); // should not throw
9168 assertEquals("should apply the localized pattern",
9169 df.getNegativePrefix(result.remove()),
9170 "d");
9171 }
9172 }
9173
Test13055_PercentageRounding()9174 void NumberFormatTest::Test13055_PercentageRounding() {
9175 IcuTestErrorCode status(*this, "PercentageRounding");
9176 UnicodeString actual;
9177 LocalPointer<NumberFormat>pFormat(NumberFormat::createPercentInstance("en_US", status));
9178 if (U_FAILURE(status)) {
9179 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9180 return;
9181 }
9182 pFormat->setMaximumFractionDigits(0);
9183 pFormat->setRoundingMode(DecimalFormat::kRoundHalfEven);
9184 pFormat->format(2.155, actual);
9185 assertEquals("Should round percent toward even number", "216%", actual);
9186 }
9187
Test11839()9188 void NumberFormatTest::Test11839() {
9189 IcuTestErrorCode errorCode(*this, "Test11839");
9190 // Ticket #11839: DecimalFormat does not respect custom plus sign
9191 LocalPointer<DecimalFormatSymbols> dfs(new DecimalFormatSymbols(Locale::getEnglish(), errorCode), errorCode);
9192 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9193 dfs->setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"a∸");
9194 dfs->setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"b∔"); // ∔ U+2214 DOT PLUS
9195 DecimalFormat df(u"0.00+;0.00-", dfs.orphan(), errorCode);
9196 UnicodeString result;
9197 df.format(-1.234, result, errorCode);
9198 assertEquals("Locale-specific minus sign should be used", u"1.23a∸", result);
9199 df.format(1.234, result.remove(), errorCode);
9200 assertEquals("Locale-specific plus sign should be used", u"1.23b∔", result);
9201 // Test round-trip with parse
9202 expect2(df, -456, u"456.00a∸");
9203 expect2(df, 456, u"456.00b∔");
9204 }
9205
Test10354()9206 void NumberFormatTest::Test10354() {
9207 IcuTestErrorCode errorCode(*this, "Test10354");
9208 // Ticket #10354: invalid FieldPositionIterator when formatting with empty NaN
9209 DecimalFormatSymbols dfs(errorCode);
9210 UnicodeString empty;
9211 dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, empty);
9212 DecimalFormat df(errorCode);
9213 df.setDecimalFormatSymbols(dfs);
9214 UnicodeString result;
9215 FieldPositionIterator positions;
9216 df.format(NAN, result, &positions, errorCode);
9217 errorCode.errIfFailureAndReset("DecimalFormat.format(NAN, FieldPositionIterator) failed");
9218 FieldPosition fp;
9219 while (positions.next(fp)) {
9220 // Should not loop forever
9221 }
9222 }
9223
Test11645_ApplyPatternEquality()9224 void NumberFormatTest::Test11645_ApplyPatternEquality() {
9225 IcuTestErrorCode status(*this, "Test11645_ApplyPatternEquality");
9226 const char16_t* pattern = u"#,##0.0#";
9227 LocalPointer<DecimalFormat> fmt((DecimalFormat*) NumberFormat::createInstance(status), status);
9228 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9229 fmt->applyPattern(pattern, status);
9230 LocalPointer<DecimalFormat> fmtCopy;
9231
9232 static const int32_t newMultiplier = 37;
9233 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9234 assertFalse("Value before setter", fmtCopy->getMultiplier() == newMultiplier);
9235 fmtCopy->setMultiplier(newMultiplier);
9236 assertEquals("Value after setter", fmtCopy->getMultiplier(), newMultiplier);
9237 fmtCopy->applyPattern(pattern, status);
9238 assertEquals("Value after applyPattern", fmtCopy->getMultiplier(), newMultiplier);
9239 assertFalse("multiplier", *fmt == *fmtCopy);
9240
9241 static const NumberFormat::ERoundingMode newRoundingMode = NumberFormat::ERoundingMode::kRoundCeiling;
9242 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9243 assertFalse("Value before setter", fmtCopy->getRoundingMode() == newRoundingMode);
9244 fmtCopy->setRoundingMode(newRoundingMode);
9245 assertEquals("Value after setter", fmtCopy->getRoundingMode(), newRoundingMode);
9246 fmtCopy->applyPattern(pattern, status);
9247 assertEquals("Value after applyPattern", fmtCopy->getRoundingMode(), newRoundingMode);
9248 assertFalse("roundingMode", *fmt == *fmtCopy);
9249
9250 static const char16_t *const newCurrency = u"EAT";
9251 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9252 assertFalse("Value before setter", fmtCopy->getCurrency() == newCurrency);
9253 fmtCopy->setCurrency(newCurrency);
9254 assertEquals("Value after setter", fmtCopy->getCurrency(), newCurrency);
9255 fmtCopy->applyPattern(pattern, status);
9256 assertEquals("Value after applyPattern", fmtCopy->getCurrency(), newCurrency);
9257 assertFalse("currency", *fmt == *fmtCopy);
9258
9259 static const UCurrencyUsage newCurrencyUsage = UCurrencyUsage::UCURR_USAGE_CASH;
9260 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9261 assertFalse("Value before setter", fmtCopy->getCurrencyUsage() == newCurrencyUsage);
9262 fmtCopy->setCurrencyUsage(newCurrencyUsage, status);
9263 assertEquals("Value after setter", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9264 fmtCopy->applyPattern(pattern, status);
9265 assertEquals("Value after applyPattern", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9266 assertFalse("currencyUsage", *fmt == *fmtCopy);
9267 }
9268
Test12567()9269 void NumberFormatTest::Test12567() {
9270 IcuTestErrorCode errorCode(*this, "Test12567");
9271 // Ticket #12567: DecimalFormat.equals() may not be symmetric
9272 LocalPointer<DecimalFormat> df1((DecimalFormat *)
9273 NumberFormat::createInstance(Locale::getUS(), UNUM_CURRENCY, errorCode));
9274 LocalPointer<DecimalFormat> df2((DecimalFormat *)
9275 NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, errorCode));
9276 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9277 // NOTE: CurrencyPluralInfo equality not tested in C++ because its operator== is not defined.
9278 df1->applyPattern(u"0.00", errorCode);
9279 df2->applyPattern(u"0.00", errorCode);
9280 assertTrue("df1 == df2", *df1 == *df2);
9281 assertTrue("df2 == df1", *df2 == *df1);
9282 df2->setPositivePrefix(u"abc");
9283 assertTrue("df1 != df2", *df1 != *df2);
9284 assertTrue("df2 != df1", *df2 != *df1);
9285 }
9286
Test11626_CustomizeCurrencyPluralInfo()9287 void NumberFormatTest::Test11626_CustomizeCurrencyPluralInfo() {
9288 IcuTestErrorCode errorCode(*this, "Test11626_CustomizeCurrencyPluralInfo");
9289 // Ticket #11626: No unit test demonstrating how to use CurrencyPluralInfo to
9290 // change formatting spelled out currencies
9291 // Use locale sr because it has interesting plural rules.
9292 Locale locale("sr");
9293 LocalPointer<DecimalFormatSymbols> symbols(new DecimalFormatSymbols(locale, errorCode), errorCode);
9294 CurrencyPluralInfo info(locale, errorCode);
9295 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9296 info.setCurrencyPluralPattern(u"one", u"0 qwerty", errorCode);
9297 info.setCurrencyPluralPattern(u"few", u"0 dvorak", errorCode);
9298 DecimalFormat df(u"#", symbols.orphan(), UNUM_CURRENCY_PLURAL, errorCode);
9299 df.setCurrencyPluralInfo(info);
9300 df.setCurrency(u"USD");
9301 df.setMaximumFractionDigits(0);
9302
9303 UnicodeString result;
9304 assertEquals("Plural one", u"1 qwerty", df.format(1, result, errorCode));
9305 assertEquals("Plural few", u"3 dvorak", df.format(3, result.remove(), errorCode));
9306 assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9307
9308 info.setPluralRules(u"few: n is 1; one: n in 2..4", errorCode);
9309 df.setCurrencyPluralInfo(info);
9310 assertEquals("Plural one", u"1 dvorak", df.format(1, result.remove(), errorCode));
9311 assertEquals("Plural few", u"3 qwerty", df.format(3, result.remove(), errorCode));
9312 assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9313 }
9314
Test20073_StrictPercentParseErrorIndex()9315 void NumberFormatTest::Test20073_StrictPercentParseErrorIndex() {
9316 IcuTestErrorCode status(*this, "Test20073_StrictPercentParseErrorIndex");
9317 ParsePosition parsePosition(0);
9318 DecimalFormat df(u"0%", {"en-us", status}, status);
9319 if (U_FAILURE(status)) {
9320 dataerrln("Unable to create DecimalFormat instance.");
9321 return;
9322 }
9323 df.setLenient(FALSE);
9324 Formattable result;
9325 df.parse(u"%2%", result, parsePosition);
9326 assertEquals("", 0, parsePosition.getIndex());
9327 assertEquals("", 0, parsePosition.getErrorIndex());
9328 }
9329
Test13056_GroupingSize()9330 void NumberFormatTest::Test13056_GroupingSize() {
9331 UErrorCode status = U_ZERO_ERROR;
9332 DecimalFormat df(u"#,##0", status);
9333 if (!assertSuccess("", status)) return;
9334 assertEquals("Primary grouping should return 3", 3, df.getGroupingSize());
9335 assertEquals("Secondary grouping should return 0", 0, df.getSecondaryGroupingSize());
9336 df.setSecondaryGroupingSize(3);
9337 assertEquals("Primary grouping should still return 3", 3, df.getGroupingSize());
9338 assertEquals("Secondary grouping should round-trip", 3, df.getSecondaryGroupingSize());
9339 df.setGroupingSize(4);
9340 assertEquals("Primary grouping should return 4", 4, df.getGroupingSize());
9341 assertEquals("Secondary should remember explicit setting and return 3", 3, df.getSecondaryGroupingSize());
9342 }
9343
9344
Test11025_CurrencyPadding()9345 void NumberFormatTest::Test11025_CurrencyPadding() {
9346 UErrorCode status = U_ZERO_ERROR;
9347 UnicodeString pattern(u"¤¤ **####0.00");
9348 DecimalFormatSymbols sym(Locale::getFrance(), status);
9349 if (!assertSuccess("", status)) return;
9350 DecimalFormat fmt(pattern, sym, status);
9351 if (!assertSuccess("", status)) return;
9352 UnicodeString result;
9353 fmt.format(433.0, result);
9354 assertEquals("Number should be padded to 11 characters", "EUR *433,00", result);
9355 }
9356
Test11648_ExpDecFormatMalPattern()9357 void NumberFormatTest::Test11648_ExpDecFormatMalPattern() {
9358 UErrorCode status = U_ZERO_ERROR;
9359
9360 DecimalFormat fmt("0.00", {"en", status}, status);
9361 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9362 fmt.setScientificNotation(TRUE);
9363 UnicodeString pattern;
9364
9365 assertEquals("A valid scientific notation pattern should be produced",
9366 "0.00E0",
9367 fmt.toPattern(pattern));
9368
9369 DecimalFormat fmt2(pattern, status);
9370 assertSuccess("", status);
9371 }
9372
Test11649_DecFmtCurrencies()9373 void NumberFormatTest::Test11649_DecFmtCurrencies() {
9374 IcuTestErrorCode status(*this, "Test11649_DecFmtCurrencies");
9375 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
9376 pattern = pattern.unescape();
9377 DecimalFormat fmt(pattern, status);
9378 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9379 static const UChar USD[] = u"USD";
9380 fmt.setCurrency(USD);
9381 UnicodeString appendTo;
9382
9383 assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
9384 UnicodeString topattern;
9385
9386 assertEquals("", pattern, fmt.toPattern(topattern));
9387 DecimalFormat fmt2(topattern, status);
9388 fmt2.setCurrency(USD);
9389
9390 appendTo.remove();
9391 assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
9392 }
9393
Test13148_ParseGroupingSeparators()9394 void NumberFormatTest::Test13148_ParseGroupingSeparators() {
9395 IcuTestErrorCode status(*this, "Test13148");
9396 LocalPointer<DecimalFormat> fmt(
9397 (DecimalFormat*)NumberFormat::createInstance("en-ZA", status), status);
9398 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9399
9400 DecimalFormatSymbols symbols = *fmt->getDecimalFormatSymbols();
9401
9402 symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'.');
9403 symbols.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u',');
9404 fmt->setDecimalFormatSymbols(symbols);
9405 Formattable number;
9406 fmt->parse(u"300,000", number, status);
9407 assertEquals("Should parse as 300000", 300000LL, number.getInt64(status));
9408 }
9409
Test12753_PatternDecimalPoint()9410 void NumberFormatTest::Test12753_PatternDecimalPoint() {
9411 UErrorCode status = U_ZERO_ERROR;
9412 DecimalFormatSymbols symbols(Locale::getUS(), status);
9413 symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"*", false);
9414 DecimalFormat df(u"0.00", symbols, status);
9415 if (!assertSuccess("", status)) return;
9416 df.setDecimalPatternMatchRequired(true);
9417 Formattable result;
9418 df.parse(u"123",result, status);
9419 assertEquals("Parsing integer succeeded even though setDecimalPatternMatchRequired was set",
9420 U_INVALID_FORMAT_ERROR, status);
9421 }
9422
Test11647_PatternCurrencySymbols()9423 void NumberFormatTest::Test11647_PatternCurrencySymbols() {
9424 UErrorCode status = U_ZERO_ERROR;
9425 DecimalFormat df(status);
9426 df.applyPattern(u"¤¤¤¤#", status);
9427 if (!assertSuccess("", status)) return;
9428 UnicodeString actual;
9429 df.format(123, actual);
9430 assertEquals("Should replace 4 currency signs with U+FFFD", u"\uFFFD123", actual);
9431 }
9432
Test11913_BigDecimal()9433 void NumberFormatTest::Test11913_BigDecimal() {
9434 UErrorCode status = U_ZERO_ERROR;
9435 LocalPointer<NumberFormat> df(NumberFormat::createInstance(Locale::getEnglish(), status), status);
9436 if (!assertSuccess("", status)) return;
9437 UnicodeString result;
9438 df->format(StringPiece("1.23456789E400"), result, nullptr, status);
9439 assertSuccess("", status);
9440 assertEquals("Should format more than 309 digits", u"12,345,678", UnicodeString(result, 0, 10));
9441 assertEquals("Should format more than 309 digits", 534, result.length());
9442 }
9443
Test11020_RoundingInScientificNotation()9444 void NumberFormatTest::Test11020_RoundingInScientificNotation() {
9445 UErrorCode status = U_ZERO_ERROR;
9446 DecimalFormatSymbols sym(Locale::getFrance(), status);
9447 DecimalFormat fmt(u"0.05E0", sym, status);
9448 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9449 assertSuccess("", status);
9450 UnicodeString result;
9451 fmt.format(12301.2, result);
9452 assertEquals("Rounding increment should be applied after magnitude scaling", u"1,25E4", result);
9453 }
9454
Test11640_TripleCurrencySymbol()9455 void NumberFormatTest::Test11640_TripleCurrencySymbol() {
9456 IcuTestErrorCode status(*this, "Test11640_TripleCurrencySymbol");
9457 UnicodeString actual;
9458 DecimalFormat dFormat(u"¤¤¤ 0", status);
9459 if (U_FAILURE(status)) {
9460 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9461 return;
9462 }
9463 dFormat.setCurrency(u"USD");
9464 UnicodeString result;
9465 dFormat.getPositivePrefix(result);
9466 assertEquals("Triple-currency should give long name on getPositivePrefix",
9467 "US dollars ", result);
9468 }
9469
9470
Test13763_FieldPositionIteratorOffset()9471 void NumberFormatTest::Test13763_FieldPositionIteratorOffset() {
9472 IcuTestErrorCode status(*this, "Test13763_FieldPositionIteratorOffset");
9473 FieldPositionIterator fpi;
9474 UnicodeString result(u"foo\U0001F4FBbar"); // 8 code units
9475 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9476 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9477 nf->format(5142.3, result, &fpi, status);
9478
9479 int32_t expected[] = {
9480 UNUM_GROUPING_SEPARATOR_FIELD, 9, 10,
9481 UNUM_INTEGER_FIELD, 8, 13,
9482 UNUM_DECIMAL_SEPARATOR_FIELD, 13, 14,
9483 UNUM_FRACTION_FIELD, 14, 15,
9484 };
9485 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
9486 expectPositions(fpi, expected, tupleCount, result);
9487 }
9488
Test13777_ParseLongNameNonCurrencyMode()9489 void NumberFormatTest::Test13777_ParseLongNameNonCurrencyMode() {
9490 IcuTestErrorCode status(*this, "Test13777_ParseLongNameNonCurrencyMode");
9491
9492 LocalPointer<NumberFormat> df(
9493 NumberFormat::createInstance("en-us", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9494 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9495 expect2(*df, 1.5, u"1.50 US dollars");
9496 }
9497
Test13804_EmptyStringsWhenParsing()9498 void NumberFormatTest::Test13804_EmptyStringsWhenParsing() {
9499 IcuTestErrorCode status(*this, "Test13804_EmptyStringsWhenParsing");
9500
9501 DecimalFormatSymbols dfs("en", status);
9502 if (status.errIfFailureAndReset()) {
9503 return;
9504 }
9505 dfs.setSymbol(DecimalFormatSymbols::kCurrencySymbol, u"", FALSE);
9506 dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"", FALSE);
9507 dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u"", FALSE);
9508 dfs.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, u"", FALSE);
9509 dfs.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, u"", FALSE);
9510 dfs.setSymbol(DecimalFormatSymbols::kThreeDigitSymbol, u"", FALSE);
9511 dfs.setSymbol(DecimalFormatSymbols::kFourDigitSymbol, u"", FALSE);
9512 dfs.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, u"", FALSE);
9513 dfs.setSymbol(DecimalFormatSymbols::kSixDigitSymbol, u"", FALSE);
9514 dfs.setSymbol(DecimalFormatSymbols::kSevenDigitSymbol, u"", FALSE);
9515 dfs.setSymbol(DecimalFormatSymbols::kEightDigitSymbol, u"", FALSE);
9516 dfs.setSymbol(DecimalFormatSymbols::kNineDigitSymbol, u"", FALSE);
9517 dfs.setSymbol(DecimalFormatSymbols::kExponentMultiplicationSymbol, u"", FALSE);
9518 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"", FALSE);
9519 dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u"", FALSE);
9520 dfs.setSymbol(DecimalFormatSymbols::kInfinitySymbol, u"", FALSE);
9521 dfs.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, u"", FALSE);
9522 dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"", FALSE);
9523 dfs.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, u"", FALSE);
9524 dfs.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, u"", FALSE);
9525 dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, u"", FALSE);
9526 dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, FALSE, u"");
9527 dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, TRUE, u"");
9528 dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u"", FALSE);
9529 dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u"", FALSE);
9530 dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"", FALSE);
9531
9532 DecimalFormat df("0", dfs, status);
9533 if (status.errIfFailureAndReset()) {
9534 return;
9535 }
9536 df.setGroupingUsed(TRUE);
9537 df.setScientificNotation(TRUE);
9538 df.setLenient(TRUE); // enable all matchers
9539 {
9540 UnicodeString result;
9541 df.format(0, result); // should not crash or hit infinite loop
9542 }
9543 const char16_t* samples[] = {
9544 u"",
9545 u"123",
9546 u"$123",
9547 u"-",
9548 u"+",
9549 u"44%",
9550 u"1E+2.3"
9551 };
9552 for (auto& sample : samples) {
9553 logln(UnicodeString(u"Attempting parse on: ") + sample);
9554 status.setScope(sample);
9555 // We don't care about the results, only that we don't crash and don't loop.
9556 Formattable result;
9557 ParsePosition ppos(0);
9558 df.parse(sample, result, ppos);
9559 ppos = ParsePosition(0);
9560 LocalPointer<CurrencyAmount> curramt(df.parseCurrency(sample, ppos));
9561 status.errIfFailureAndReset();
9562 }
9563
9564 // Test with a nonempty exponent separator symbol to cover more code
9565 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"E", FALSE);
9566 df.setDecimalFormatSymbols(dfs);
9567 {
9568 Formattable result;
9569 ParsePosition ppos(0);
9570 df.parse(u"1E+2.3", result, ppos);
9571 }
9572 }
9573
Test20037_ScientificIntegerOverflow()9574 void NumberFormatTest::Test20037_ScientificIntegerOverflow() {
9575 IcuTestErrorCode status(*this, "Test20037_ScientificIntegerOverflow");
9576
9577 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(status));
9578 if (U_FAILURE(status)) {
9579 dataerrln("Unable to create NumberFormat instance.");
9580 return;
9581 }
9582 Formattable result;
9583
9584 // Test overflow of exponent
9585 nf->parse(u"1E-2147483648", result, status);
9586 StringPiece sp = result.getDecimalNumber(status);
9587 assertEquals(u"Should snap to zero",
9588 u"0",
9589 {sp.data(), sp.length(), US_INV});
9590
9591 // Test edge case overflow of exponent
9592 result = Formattable();
9593 nf->parse(u"1E-2147483647E-1", result, status);
9594 sp = result.getDecimalNumber(status);
9595 assertEquals(u"Should not overflow and should parse only the first exponent",
9596 u"1E-2147483647",
9597 {sp.data(), sp.length(), US_INV});
9598
9599 // Test edge case overflow of exponent
9600 result = Formattable();
9601 nf->parse(u".0003e-2147483644", result, status);
9602 sp = result.getDecimalNumber(status);
9603 assertEquals(u"Should not overflow",
9604 u"3E-2147483648",
9605 {sp.data(), sp.length(), US_INV});
9606
9607 // Test largest parseable exponent
9608 result = Formattable();
9609 nf->parse(u"9876e2147483643", result, status);
9610 sp = result.getDecimalNumber(status);
9611 assertEquals(u"Should not overflow",
9612 u"9.876E+2147483646",
9613 {sp.data(), sp.length(), US_INV});
9614
9615 // Test max value as well
9616 const char16_t* infinityInputs[] = {
9617 u"9876e2147483644",
9618 u"9876e2147483645",
9619 u"9876e2147483646",
9620 u"9876e2147483647",
9621 u"9876e2147483648",
9622 u"9876e2147483649",
9623 };
9624 for (const auto& input : infinityInputs) {
9625 result = Formattable();
9626 nf->parse(input, result, status);
9627 sp = result.getDecimalNumber(status);
9628 assertEquals(UnicodeString("Should become Infinity: ") + input,
9629 u"Infinity",
9630 {sp.data(), sp.length(), US_INV});
9631 }
9632 }
9633
Test13840_ParseLongStringCrash()9634 void NumberFormatTest::Test13840_ParseLongStringCrash() {
9635 IcuTestErrorCode status(*this, "Test13840_ParseLongStringCrash");
9636
9637 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9638 if (status.errIfFailureAndReset()) { return; }
9639
9640 Formattable result;
9641 static const char16_t* bigString =
9642 u"111111111111111111111111111111111111111111111111111111111111111111111"
9643 u"111111111111111111111111111111111111111111111111111111111111111111111"
9644 u"111111111111111111111111111111111111111111111111111111111111111111111"
9645 u"111111111111111111111111111111111111111111111111111111111111111111111"
9646 u"111111111111111111111111111111111111111111111111111111111111111111111"
9647 u"111111111111111111111111111111111111111111111111111111111111111111111";
9648 nf->parse(bigString, result, status);
9649
9650 // Normalize the input string:
9651 CharString expectedChars;
9652 expectedChars.appendInvariantChars(bigString, status);
9653 DecimalQuantity expectedDQ;
9654 expectedDQ.setToDecNumber(expectedChars.toStringPiece(), status);
9655 UnicodeString expectedUString = expectedDQ.toScientificString();
9656
9657 // Get the output string:
9658 StringPiece actualChars = result.getDecimalNumber(status);
9659 UnicodeString actualUString = UnicodeString(actualChars.data(), actualChars.length(), US_INV);
9660
9661 assertEquals("Should round-trip without crashing", expectedUString, actualUString);
9662 }
9663
Test13850_EmptyStringCurrency()9664 void NumberFormatTest::Test13850_EmptyStringCurrency() {
9665 IcuTestErrorCode status(*this, "Test13840_EmptyStringCurrency");
9666
9667 struct TestCase {
9668 const char16_t* currencyArg;
9669 UErrorCode expectedError;
9670 } cases[] = {
9671 {u"", U_USING_FALLBACK_WARNING},
9672 {u"U", U_ILLEGAL_ARGUMENT_ERROR},
9673 {u"Us", U_ILLEGAL_ARGUMENT_ERROR},
9674 {nullptr, U_USING_FALLBACK_WARNING},
9675 {u"U$D", U_INVARIANT_CONVERSION_ERROR},
9676 {u"Xxx", U_USING_FALLBACK_WARNING}
9677 };
9678 for (const auto& cas : cases) {
9679 UnicodeString message(u"with currency arg: ");
9680 if (cas.currencyArg == nullptr) {
9681 message += u"nullptr";
9682 } else {
9683 message += UnicodeString(cas.currencyArg);
9684 }
9685 status.setScope(message);
9686 LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-US", status), status);
9687 if (status.errIfFailureAndReset()) { return; }
9688 UnicodeString actual;
9689 nf->format(1, actual, status);
9690 status.errIfFailureAndReset();
9691 assertEquals(u"Should format with US currency " + message, u"$1.00", actual);
9692 nf->setCurrency(cas.currencyArg, status);
9693 if (status.expectErrorAndReset(cas.expectedError)) {
9694 // If an error occurred, do not check formatting.
9695 continue;
9696 }
9697 nf->format(1, actual.remove(), status);
9698 assertEquals(u"Should unset the currency " + message, u"\u00A41.00", actual);
9699 status.errIfFailureAndReset();
9700 }
9701 }
9702
Test20348_CurrencyPrefixOverride()9703 void NumberFormatTest::Test20348_CurrencyPrefixOverride() {
9704 IcuTestErrorCode status(*this, "Test20348_CurrencyPrefixOverride");
9705 LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9706 NumberFormat::createCurrencyInstance("en", status)));
9707 if (status.errIfFailureAndReset()) { return; }
9708 UnicodeString result;
9709 assertEquals("Initial pattern",
9710 u"¤#,##0.00", fmt->toPattern(result.remove()));
9711 assertEquals("Initial prefix",
9712 u"¤", fmt->getPositivePrefix(result.remove()));
9713 assertEquals("Initial suffix",
9714 u"-¤", fmt->getNegativePrefix(result.remove()));
9715 assertEquals("Initial format",
9716 u"\u00A4100.00", fmt->format(100, result.remove(), NULL, status));
9717
9718 fmt->setPositivePrefix(u"$");
9719 assertEquals("Set positive prefix pattern",
9720 u"$#,##0.00;-\u00A4#,##0.00", fmt->toPattern(result.remove()));
9721 assertEquals("Set positive prefix prefix",
9722 u"$", fmt->getPositivePrefix(result.remove()));
9723 assertEquals("Set positive prefix suffix",
9724 u"-¤", fmt->getNegativePrefix(result.remove()));
9725 assertEquals("Set positive prefix format",
9726 u"$100.00", fmt->format(100, result.remove(), NULL, status));
9727
9728 fmt->setNegativePrefix(u"-$");
9729 assertEquals("Set negative prefix pattern",
9730 u"$#,##0.00;'-'$#,##0.00", fmt->toPattern(result.remove()));
9731 assertEquals("Set negative prefix prefix",
9732 u"$", fmt->getPositivePrefix(result.remove()));
9733 assertEquals("Set negative prefix suffix",
9734 u"-$", fmt->getNegativePrefix(result.remove()));
9735 assertEquals("Set negative prefix format",
9736 u"$100.00", fmt->format(100, result.remove(), NULL, status));
9737 }
9738
Test20956_MonetarySymbolGetters()9739 void NumberFormatTest::Test20956_MonetarySymbolGetters() {
9740 IcuTestErrorCode status(*this, "Test20956_MonetarySymbolGetters");
9741 LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9742 NumberFormat::createCurrencyInstance("et", status)));
9743 if (status.errDataIfFailureAndReset()) {
9744 return;
9745 }
9746
9747 decimalFormat->setCurrency(u"EEK");
9748
9749 const DecimalFormatSymbols* decimalFormatSymbols = decimalFormat->getDecimalFormatSymbols();
9750 assertEquals("MONETARY DECIMAL SEPARATOR",
9751 u".",
9752 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
9753 assertEquals("DECIMAL SEPARATOR",
9754 u",",
9755 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol));
9756 assertEquals("MONETARY GROUPING SEPARATOR",
9757 u" ",
9758 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol));
9759 assertEquals("GROUPING SEPARATOR",
9760 u" ",
9761 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
9762 assertEquals("CURRENCY SYMBOL",
9763 u"kr",
9764 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
9765
9766 UnicodeString sb;
9767 decimalFormat->format(12345.12, sb, status);
9768 assertEquals("OUTPUT", u"12 345.12 kr", sb);
9769 }
9770
Test20358_GroupingInPattern()9771 void NumberFormatTest::Test20358_GroupingInPattern() {
9772 IcuTestErrorCode status(*this, "Test20358_GroupingInPattern");
9773 LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9774 NumberFormat::createInstance("en", status)));
9775 if (status.errIfFailureAndReset()) { return; }
9776 UnicodeString result;
9777 assertEquals("Initial pattern",
9778 u"#,##0.###", fmt->toPattern(result.remove()));
9779 assertTrue("Initial grouping",
9780 fmt->isGroupingUsed());
9781 assertEquals("Initial format",
9782 u"54,321", fmt->format(54321, result.remove(), NULL, status));
9783
9784 fmt->setGroupingUsed(false);
9785 assertEquals("Set grouping false",
9786 u"0.###", fmt->toPattern(result.remove()));
9787 assertFalse("Set grouping false grouping",
9788 fmt->isGroupingUsed());
9789 assertEquals("Set grouping false format",
9790 u"54321", fmt->format(54321, result.remove(), NULL, status));
9791
9792 fmt->setGroupingUsed(true);
9793 assertEquals("Set grouping true",
9794 u"#,##0.###", fmt->toPattern(result.remove()));
9795 assertTrue("Set grouping true grouping",
9796 fmt->isGroupingUsed());
9797 assertEquals("Set grouping true format",
9798 u"54,321", fmt->format(54321, result.remove(), NULL, status));
9799 }
9800
Test13731_DefaultCurrency()9801 void NumberFormatTest::Test13731_DefaultCurrency() {
9802 IcuTestErrorCode status(*this, "Test13731_DefaultCurrency");
9803 UnicodeString result;
9804 {
9805 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9806 "en", UNumberFormatStyle::UNUM_CURRENCY, status), status);
9807 if (status.errIfFailureAndReset()) { return; }
9808 assertEquals("symbol", u"¤1.10",
9809 nf->format(1.1, result.remove(), status));
9810 assertEquals("currency", u"XXX", nf->getCurrency());
9811 }
9812 {
9813 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9814 "en", UNumberFormatStyle::UNUM_CURRENCY_ISO, status), status);
9815 if (status.errIfFailureAndReset()) { return; }
9816 assertEquals("iso_code", u"XXX 1.10",
9817 nf->format(1.1, result.remove(), status));
9818 assertEquals("currency", u"XXX", nf->getCurrency());
9819 }
9820 {
9821 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9822 "en", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9823 if (status.errIfFailureAndReset()) { return; }
9824 assertEquals("plural", u"1.10 (unknown currency)",
9825 nf->format(1.1, result.remove(), status));
9826 assertEquals("currency", u"XXX", nf->getCurrency());
9827 }
9828 }
9829
Test20499_CurrencyVisibleDigitsPlural()9830 void NumberFormatTest::Test20499_CurrencyVisibleDigitsPlural() {
9831 IcuTestErrorCode status(*this, "Test20499_CurrencyVisibleDigitsPlural");
9832 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9833 "ro-RO", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9834 const char16_t* expected = u"24,00 lei românești";
9835 for (int32_t i=0; i<5; i++) {
9836 UnicodeString actual;
9837 nf->format(24, actual, status);
9838 assertEquals(UnicodeString(u"iteration ") + Int64ToUnicodeString(i),
9839 expected, actual);
9840 }
9841 }
9842
Test13735_GroupingSizeGetter()9843 void NumberFormatTest::Test13735_GroupingSizeGetter() {
9844 IcuTestErrorCode status(*this, "Test13735_GroupingSizeGetter");
9845 {
9846 DecimalFormat df("0", {"en", status}, status);
9847 assertEquals("pat 0: ", 0, df.getGroupingSize());
9848 df.setGroupingUsed(false);
9849 assertEquals("pat 0 then disabled: ", 0, df.getGroupingSize());
9850 df.setGroupingUsed(true);
9851 assertEquals("pat 0 then enabled: ", 0, df.getGroupingSize());
9852 }
9853 {
9854 DecimalFormat df("#,##0", {"en", status}, status);
9855 assertEquals("pat #,##0: ", 3, df.getGroupingSize());
9856 df.setGroupingUsed(false);
9857 assertEquals("pat #,##0 then disabled: ", 3, df.getGroupingSize());
9858 df.setGroupingUsed(true);
9859 assertEquals("pat #,##0 then enabled: ", 3, df.getGroupingSize());
9860 }
9861 }
9862
Test13734_StrictFlexibleWhitespace()9863 void NumberFormatTest::Test13734_StrictFlexibleWhitespace() {
9864 IcuTestErrorCode status(*this, "Test13734_StrictFlexibleWhitespace");
9865 {
9866 DecimalFormat df("+0", {"en", status}, status);
9867 df.setLenient(FALSE);
9868 Formattable result;
9869 ParsePosition ppos;
9870 df.parse("+ 33", result, ppos);
9871 assertEquals("ppos : ", 0, ppos.getIndex());
9872 assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9873 }
9874 {
9875 DecimalFormat df("+ 0", {"en", status}, status);
9876 df.setLenient(FALSE);
9877 Formattable result;
9878 ParsePosition ppos;
9879 df.parse("+ 33", result, ppos);
9880 assertEquals("ppos : ", 0, ppos.getIndex());
9881 assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9882 }
9883 }
9884
Test20961_CurrencyPluralPattern()9885 void NumberFormatTest::Test20961_CurrencyPluralPattern() {
9886 IcuTestErrorCode status(*this, "Test20961_CurrencyPluralPattern");
9887 {
9888 LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9889 NumberFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9890 if (status.errDataIfFailureAndReset()) {
9891 return;
9892 }
9893 UnicodeString result;
9894 decimalFormat->toPattern(result);
9895 assertEquals("Currency pattern", u"#,##0.00 ¤¤¤", result);
9896 }
9897 }
9898
Test21134_ToNumberFormatter()9899 void NumberFormatTest::Test21134_ToNumberFormatter() {
9900 IcuTestErrorCode status(*this, "Test21134_ToNumberFormatter");
9901 LocalizedNumberFormatter outer1;
9902 LocalizedNumberFormatter outer2;
9903 LocalPointer<LocalizedNumberFormatter> outer3;
9904 {
9905 // Case 1: new formatter object
9906 DecimalFormat inner(u"a0b", {"en", status}, status);
9907 if (auto ptr = inner.toNumberFormatter(status)) {
9908 // Copy assignment
9909 outer1 = *ptr;
9910 } else {
9911 status.errIfFailureAndReset();
9912 return;
9913 }
9914 }
9915 {
9916 // Case 2: compiled formatter object (used at least 3 times)
9917 DecimalFormat inner(u"c0d", {"en", status}, status);
9918 UnicodeString dummy;
9919 inner.format(100, dummy);
9920 inner.format(100, dummy);
9921 inner.format(100, dummy);
9922 if (auto ptr = inner.toNumberFormatter(status)) {
9923 // Copy assignment
9924 outer2 = *ptr;
9925 } else {
9926 status.errIfFailureAndReset();
9927 return;
9928 }
9929 }
9930 {
9931 // Case 3: currency plural info (different code path)
9932 LocalPointer<DecimalFormat> inner(static_cast<DecimalFormat*>(
9933 DecimalFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9934 if (auto ptr = inner->toNumberFormatter(status)) {
9935 // Copy constructor
9936 outer3.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(*ptr), status);
9937 } else {
9938 status.errIfFailureAndReset();
9939 return;
9940 }
9941 }
9942 auto result1 = outer1.formatDouble(99, status);
9943 assertEquals("Using NumberFormatter from DecimalFormat, new version",
9944 u"a99b",
9945 result1.toTempString(status));
9946 auto result2 = outer2.formatDouble(99, status);
9947 assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9948 u"c99d",
9949 result2.toTempString(status));
9950 auto result3 = outer3->formatDouble(99, status);
9951 assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9952 u"99.00 US dollars",
9953 result3.toTempString(status));
9954 }
9955
Test13733_StrictAndLenient()9956 void NumberFormatTest::Test13733_StrictAndLenient() {
9957 IcuTestErrorCode status(*this, "Test13733_StrictAndLenient");
9958
9959 static const struct TestCase {
9960 const char16_t* inputString;
9961 const char16_t* patternString;
9962 int64_t expectedStrictParse;
9963 int64_t expectedLenientParse;
9964 } cases[] = { {u"CA$ 12", u"¤ 0", 12, 12},
9965 {u"CA$12", u"¤0", 12, 12},
9966 {u"CAD 12", u"¤¤ 0", 12, 12},
9967 {u"12 CAD", u"0 ¤¤", 12, 12},
9968 {u"12 Canadian dollars", u"0 ¤¤¤", 12, 12},
9969 {u"$12 ", u"¤¤¤¤0", 12, 12},
9970 {u"12$", u"0¤¤¤¤", 12, 12},
9971 {u"CA$ 12", u"¤0", 0, 12},
9972 {u"CA$ 12", u"0 ¤¤", 0, 12},
9973 {u"CA$ 12", u"0 ¤¤¤", 0, 12},
9974 {u"CA$ 12", u"¤¤¤¤0", 0, 12},
9975 {u"CA$ 12", u"0¤¤¤¤", 0, 12},
9976 {u"CA$12", u"¤ 0", 0, 12},
9977 {u"CA$12", u"¤¤ 0", 0, 12},
9978 {u"CA$12", u"0 ¤¤", 0, 12},
9979 {u"CA$12", u"0 ¤¤¤", 0, 12},
9980 {u"CA$12", u"0¤¤¤¤", 0, 12},
9981 {u"CAD 12", u"¤0", 0, 12},
9982 {u"CAD 12", u"0 ¤¤", 0, 12},
9983 {u"CAD 12", u"0 ¤¤¤", 0, 12},
9984 {u"CAD 12", u"¤¤¤¤0", 0, 12},
9985 {u"CAD 12", u"0¤¤¤¤", 0, 12},
9986 {u"12 CAD", u"¤ 0", 0, 12},
9987 {u"12 CAD", u"¤0", 0, 12},
9988 {u"12 CAD", u"¤¤ 0", 0, 12},
9989 {u"12 CAD", u"¤¤¤¤0", 0, 12},
9990 {u"12 CAD", u"0¤¤¤¤", 0, 12},
9991 {u"12 Canadian dollars", u"¤ 0", 0, 12},
9992 {u"12 Canadian dollars", u"¤0", 0, 12},
9993 {u"12 Canadian dollars", u"¤¤ 0", 0, 12},
9994 {u"12 Canadian dollars", u"¤¤¤¤0", 0, 12},
9995 {u"12 Canadian dollars", u"0¤¤¤¤", 0, 12},
9996 {u"$12 ", u"¤ 0", 0, 12},
9997 {u"$12 ", u"¤¤ 0", 0, 12},
9998 {u"$12 ", u"0 ¤¤", 0, 12},
9999 {u"$12 ", u"0 ¤¤¤", 0, 12},
10000 {u"$12 ", u"0¤¤¤¤", 0, 12},
10001 {u"12$", u"¤ 0", 0, 12},
10002 {u"12$", u"¤0", 0, 12},
10003 {u"12$", u"¤¤ 0", 0, 12},
10004 {u"12$", u"0 ¤¤", 0, 12},
10005 {u"12$", u"0 ¤¤¤", 0, 12},
10006 {u"12$", u"¤¤¤¤0", 0, 12} };
10007 for (auto& cas : cases) {
10008 UnicodeString inputString(cas.inputString);
10009 UnicodeString patternString(cas.patternString);
10010 int64_t parsedStrictValue = 0;
10011 int64_t parsedLenientValue = 0;
10012 ParsePosition ppos;
10013
10014 DecimalFormatSymbols dfs(Locale::getEnglish(), status);
10015 if (status.errDataIfFailureAndReset()) {
10016 return;
10017 }
10018 DecimalFormat df(patternString, dfs, status);
10019 if (status.errDataIfFailureAndReset()) {
10020 return;
10021 }
10022 df.setLenient(FALSE);
10023 LocalPointer<CurrencyAmount> ca_strict(df.parseCurrency(inputString, ppos));
10024 if (ca_strict != nullptr) {
10025 parsedStrictValue = ca_strict->getNumber().getInt64();
10026 }
10027 assertEquals("Strict parse of " + inputString + " using " + patternString,
10028 parsedStrictValue, cas.expectedStrictParse);
10029
10030 ppos.setIndex(0);
10031 df.setLenient(TRUE);
10032 LocalPointer<CurrencyAmount> ca_lenient(df.parseCurrency(inputString, ppos));
10033 Formattable parsedNumber_lenient = ca_lenient->getNumber();
10034 if (ca_lenient != nullptr) {
10035 parsedLenientValue = ca_lenient->getNumber().getInt64();
10036 }
10037 assertEquals("Lenient parse of " + inputString + " using " + patternString,
10038 parsedLenientValue, cas.expectedLenientParse);
10039 }
10040 }
10041
Test21232_ParseTimeout()10042 void NumberFormatTest::Test21232_ParseTimeout() {
10043 IcuTestErrorCode status(*this, "Test21232_ParseTimeout");
10044
10045 DecimalFormat df(status);
10046 if (status.errDataIfFailureAndReset()) {
10047 return;
10048 }
10049
10050 UnicodeString input = u"4444444444444444444444444444444444444444";
10051 if (quick) {
10052 for (int32_t i = 0; i < 5; i++) {
10053 input.append(input);
10054 }
10055 assertEquals("Somewhat long input of digits", 1280, input.length());
10056 } else {
10057 for (int32_t i = 0; i < 12; i++) {
10058 input.append(input);
10059 }
10060 assertEquals("Very long input of digits", 163840, input.length());
10061 }
10062 Formattable result;
10063 df.parse(input, result, status);
10064 // Should not hang
10065 }
10066
Test10997_FormatCurrency()10067 void NumberFormatTest::Test10997_FormatCurrency() {
10068 IcuTestErrorCode status(*this, "Test10997_FormatCurrency");
10069
10070 UErrorCode error = U_ZERO_ERROR;
10071 NumberFormat* fmt = NumberFormat::createCurrencyInstance(Locale::getUS(), error);
10072 if (U_FAILURE(error)) {
10073 return;
10074 }
10075 fmt->setMinimumFractionDigits(4);
10076 fmt->setMaximumFractionDigits(4);
10077
10078 FieldPosition fp;
10079
10080 UnicodeString str;
10081 Formattable usdAmnt(new CurrencyAmount(123.45, u"USD", status));
10082 fmt->format(usdAmnt, str, fp, status);
10083 assertEquals("minFrac 4 should be respected in default currency", u"$123.4500", str);
10084
10085 UnicodeString str2;
10086 Formattable eurAmnt(new CurrencyAmount(123.45, u"EUR", status));
10087 fmt->format(eurAmnt, str2, fp, status);
10088 assertEquals("minFrac 4 should be respected in different currency", u"€123.4500", str2);
10089
10090 delete fmt;
10091 }
10092
10093 #endif /* #if !UCONFIG_NO_FORMATTING */
10094