1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8 /* Modification History:
9 * Date Name Description
10 * 07/15/99 helena Ported to HPUX 10/11 CC.
11 */
12
13 #include "unicode/utypes.h"
14
15 #if !UCONFIG_NO_FORMATTING
16
17 #include "numfmtst.h"
18 #include "unicode/currpinf.h"
19 #include "unicode/dcfmtsym.h"
20 #include "unicode/decimfmt.h"
21 #include "unicode/localpointer.h"
22 #include "unicode/ucurr.h"
23 #include "unicode/ustring.h"
24 #include "unicode/measfmt.h"
25 #include "unicode/curramt.h"
26 #include "unicode/strenum.h"
27 #include "textfile.h"
28 #include "tokiter.h"
29 #include "charstr.h"
30 #include "cstr.h"
31 #include "putilimp.h"
32 #include "winnmtst.h"
33 #include <cmath>
34 #include <float.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include "cmemory.h"
38 #include "cstring.h"
39 #include "unicode/numsys.h"
40 #include "fmtableimp.h"
41 #include "numberformattesttuple.h"
42 #include "unicode/msgfmt.h"
43 #include "number_decimalquantity.h"
44 #include "unicode/numberformatter.h"
45
46 #if (U_PLATFORM == U_PF_AIX) || (U_PLATFORM == U_PF_OS390)
47 // These should not be macros. If they are,
48 // replace them with std::isnan and std::isinf
49 #if defined(isnan)
50 #undef isnan
51 namespace std {
isnan(double x)52 bool isnan(double x) {
53 return _isnan(x);
54 }
55 }
56 #endif
57 #if defined(isinf)
58 #undef isinf
59 namespace std {
isinf(double x)60 bool isinf(double x) {
61 return _isinf(x);
62 }
63 }
64 #endif
65 #endif
66
67 using icu::number::impl::DecimalQuantity;
68 using namespace icu::number;
69
70 //#define NUMFMTST_CACHE_DEBUG 1
71 #include "stdio.h" /* for sprintf */
72 // #include "iostream" // for cout
73
74 //#define NUMFMTST_DEBUG 1
75
76 static const UChar EUR[] = {69,85,82,0}; // "EUR"
77 static const UChar ISO_CURRENCY_USD[] = {0x55, 0x53, 0x44, 0}; // "USD"
78
79
80 // *****************************************************************************
81 // class NumberFormatTest
82 // *****************************************************************************
83
84 #define CHECK(status,str) UPRV_BLOCK_MACRO_BEGIN { \
85 if (U_FAILURE(status)) { \
86 errcheckln(status, UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \
87 return; \
88 } \
89 } UPRV_BLOCK_MACRO_END
90 #define CHECK_DATA(status,str) UPRV_BLOCK_MACRO_BEGIN { \
91 if (U_FAILURE(status)) { \
92 dataerrln(UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \
93 return; \
94 } \
95 } UPRV_BLOCK_MACRO_END
96
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)97 void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
98 {
99 TESTCASE_AUTO_BEGIN;
100 TESTCASE_AUTO(TestCurrencySign);
101 TESTCASE_AUTO(TestCurrency);
102 TESTCASE_AUTO(TestParse);
103 TESTCASE_AUTO(TestRounding487);
104 TESTCASE_AUTO(TestQuotes);
105 TESTCASE_AUTO(TestExponential);
106 TESTCASE_AUTO(TestPatterns);
107 TESTCASE_AUTO(Test20186_SpacesAroundSemicolon);
108
109 // Upgrade to alphaWorks - liu 5/99
110 TESTCASE_AUTO(TestExponent);
111 TESTCASE_AUTO(TestScientific);
112 TESTCASE_AUTO(TestPad);
113 TESTCASE_AUTO(TestPatterns2);
114 TESTCASE_AUTO(TestSecondaryGrouping);
115 TESTCASE_AUTO(TestSurrogateSupport);
116 TESTCASE_AUTO(TestAPI);
117
118 TESTCASE_AUTO(TestCurrencyObject);
119 TESTCASE_AUTO(TestCurrencyPatterns);
120 //TESTCASE_AUTO(TestDigitList);
121 TESTCASE_AUTO(TestWhiteSpaceParsing);
122 TESTCASE_AUTO(TestComplexCurrency); // This test removed because CLDR no longer uses choice formats in currency symbols.
123 TESTCASE_AUTO(TestRegCurrency);
124 TESTCASE_AUTO(TestSymbolsWithBadLocale);
125 TESTCASE_AUTO(TestAdoptDecimalFormatSymbols);
126
127 TESTCASE_AUTO(TestScientific2);
128 TESTCASE_AUTO(TestScientificGrouping);
129 TESTCASE_AUTO(TestInt64);
130
131 TESTCASE_AUTO(TestPerMill);
132 TESTCASE_AUTO(TestIllegalPatterns);
133 TESTCASE_AUTO(TestCases);
134
135 TESTCASE_AUTO(TestCurrencyNames);
136 TESTCASE_AUTO(TestCurrencyVariants);
137 TESTCASE_AUTO(TestCurrencyAmount);
138 TESTCASE_AUTO(TestCurrencyUnit);
139 TESTCASE_AUTO(TestCoverage);
140 TESTCASE_AUTO(TestLocalizedPatternSymbolCoverage);
141 TESTCASE_AUTO(TestJB3832);
142 TESTCASE_AUTO(TestHost);
143 TESTCASE_AUTO(TestHostClone);
144 TESTCASE_AUTO(TestCurrencyFormat);
145 TESTCASE_AUTO(TestRounding);
146 TESTCASE_AUTO(TestNonpositiveMultiplier);
147 TESTCASE_AUTO(TestNumberingSystems);
148 TESTCASE_AUTO(TestSpaceParsing);
149 TESTCASE_AUTO(TestMultiCurrencySign);
150 TESTCASE_AUTO(TestCurrencyFormatForMixParsing);
151 TESTCASE_AUTO(TestMismatchedCurrencyFormatFail);
152 TESTCASE_AUTO(TestDecimalFormatCurrencyParse);
153 TESTCASE_AUTO(TestCurrencyIsoPluralFormat);
154 TESTCASE_AUTO(TestCurrencyParsing);
155 TESTCASE_AUTO(TestParseCurrencyInUCurr);
156 TESTCASE_AUTO(TestFormatAttributes);
157 TESTCASE_AUTO(TestFieldPositionIterator);
158 TESTCASE_AUTO(TestDecimal);
159 TESTCASE_AUTO(TestCurrencyFractionDigits);
160 TESTCASE_AUTO(TestExponentParse);
161 TESTCASE_AUTO(TestExplicitParents);
162 TESTCASE_AUTO(TestLenientParse);
163 TESTCASE_AUTO(TestAvailableNumberingSystems);
164 TESTCASE_AUTO(TestRoundingPattern);
165 TESTCASE_AUTO(Test9087);
166 TESTCASE_AUTO(TestFormatFastpaths);
167 TESTCASE_AUTO(TestFormattableSize);
168 TESTCASE_AUTO(TestUFormattable);
169 TESTCASE_AUTO(TestSignificantDigits);
170 TESTCASE_AUTO(TestShowZero);
171 TESTCASE_AUTO(TestCompatibleCurrencies);
172 TESTCASE_AUTO(TestBug9936);
173 TESTCASE_AUTO(TestParseNegativeWithFaLocale);
174 TESTCASE_AUTO(TestParseNegativeWithAlternateMinusSign);
175 TESTCASE_AUTO(TestCustomCurrencySignAndSeparator);
176 TESTCASE_AUTO(TestParseSignsAndMarks);
177 TESTCASE_AUTO(Test10419RoundingWith0FractionDigits);
178 TESTCASE_AUTO(Test10468ApplyPattern);
179 TESTCASE_AUTO(TestRoundingScientific10542);
180 TESTCASE_AUTO(TestZeroScientific10547);
181 TESTCASE_AUTO(TestAccountingCurrency);
182 TESTCASE_AUTO(TestCurrencyFormatForMissingLocale);
183 TESTCASE_AUTO(TestEquality);
184 TESTCASE_AUTO(TestCurrencyUsage);
185 TESTCASE_AUTO(TestDoubleLimit11439);
186 TESTCASE_AUTO(TestGetAffixes);
187 TESTCASE_AUTO(TestToPatternScientific11648);
188 TESTCASE_AUTO(TestBenchmark);
189 TESTCASE_AUTO(TestCtorApplyPatternDifference);
190 TESTCASE_AUTO(TestFractionalDigitsForCurrency);
191 TESTCASE_AUTO(TestFormatCurrencyPlural);
192 TESTCASE_AUTO(Test11868);
193 TESTCASE_AUTO(Test11739_ParseLongCurrency);
194 TESTCASE_AUTO(Test13035_MultiCodePointPaddingInPattern);
195 TESTCASE_AUTO(Test13737_ParseScientificStrict);
196 TESTCASE_AUTO(Test10727_RoundingZero);
197 TESTCASE_AUTO(Test11376_getAndSetPositivePrefix);
198 TESTCASE_AUTO(Test11475_signRecognition);
199 TESTCASE_AUTO(Test11640_getAffixes);
200 TESTCASE_AUTO(Test11649_toPatternWithMultiCurrency);
201 TESTCASE_AUTO(Test13327_numberingSystemBufferOverflow);
202 TESTCASE_AUTO(Test13391_chakmaParsing);
203 TESTCASE_AUTO(Test11735_ExceptionIssue);
204 TESTCASE_AUTO(Test11035_FormatCurrencyAmount);
205 TESTCASE_AUTO(Test11318_DoubleConversion);
206 TESTCASE_AUTO(TestParsePercentRegression);
207 TESTCASE_AUTO(TestMultiplierWithScale);
208 TESTCASE_AUTO(TestFastFormatInt32);
209 TESTCASE_AUTO(Test11646_Equality);
210 TESTCASE_AUTO(TestParseNaN);
211 TESTCASE_AUTO(TestFormatFailIfMoreThanMaxDigits);
212 TESTCASE_AUTO(TestParseCaseSensitive);
213 TESTCASE_AUTO(TestParseNoExponent);
214 TESTCASE_AUTO(TestSignAlwaysShown);
215 TESTCASE_AUTO(TestMinimumGroupingDigits);
216 TESTCASE_AUTO(Test11897_LocalizedPatternSeparator);
217 TESTCASE_AUTO(Test13055_PercentageRounding);
218 TESTCASE_AUTO(Test11839);
219 TESTCASE_AUTO(Test10354);
220 TESTCASE_AUTO(Test11645_ApplyPatternEquality);
221 TESTCASE_AUTO(Test12567);
222 TESTCASE_AUTO(Test11626_CustomizeCurrencyPluralInfo);
223 TESTCASE_AUTO(Test20073_StrictPercentParseErrorIndex);
224 TESTCASE_AUTO(Test13056_GroupingSize);
225 TESTCASE_AUTO(Test11025_CurrencyPadding);
226 TESTCASE_AUTO(Test11648_ExpDecFormatMalPattern);
227 TESTCASE_AUTO(Test11649_DecFmtCurrencies);
228 TESTCASE_AUTO(Test13148_ParseGroupingSeparators);
229 TESTCASE_AUTO(Test12753_PatternDecimalPoint);
230 TESTCASE_AUTO(Test11647_PatternCurrencySymbols);
231 TESTCASE_AUTO(Test11913_BigDecimal);
232 TESTCASE_AUTO(Test11020_RoundingInScientificNotation);
233 TESTCASE_AUTO(Test11640_TripleCurrencySymbol);
234 TESTCASE_AUTO(Test13763_FieldPositionIteratorOffset);
235 TESTCASE_AUTO(Test13777_ParseLongNameNonCurrencyMode);
236 TESTCASE_AUTO(Test13804_EmptyStringsWhenParsing);
237 TESTCASE_AUTO(Test20037_ScientificIntegerOverflow);
238 TESTCASE_AUTO(Test13840_ParseLongStringCrash);
239 TESTCASE_AUTO(Test13850_EmptyStringCurrency);
240 TESTCASE_AUTO(Test20348_CurrencyPrefixOverride);
241 TESTCASE_AUTO(Test20956_MonetarySymbolGetters);
242 TESTCASE_AUTO(Test20358_GroupingInPattern);
243 TESTCASE_AUTO(Test13731_DefaultCurrency);
244 TESTCASE_AUTO(Test20499_CurrencyVisibleDigitsPlural);
245 TESTCASE_AUTO(Test13735_GroupingSizeGetter);
246 TESTCASE_AUTO(Test13734_StrictFlexibleWhitespace);
247 TESTCASE_AUTO(Test20961_CurrencyPluralPattern);
248 TESTCASE_AUTO(Test21134_ToNumberFormatter);
249 TESTCASE_AUTO(Test13733_StrictAndLenient);
250 TESTCASE_AUTO(Test20425_IntegerIncrement);
251 TESTCASE_AUTO(Test20425_FractionWithIntegerIncrement);
252 TESTCASE_AUTO(Test21232_ParseTimeout);
253 TESTCASE_AUTO(Test10997_FormatCurrency);
254 TESTCASE_AUTO(Test21556_CurrencyAsDecimal);
255 TESTCASE_AUTO_END;
256 }
257
258 // -------------------------------------
259
260 // Test API (increase code coverage)
261 void
TestAPI(void)262 NumberFormatTest::TestAPI(void)
263 {
264 logln("Test API");
265 UErrorCode status = U_ZERO_ERROR;
266 NumberFormat *test = NumberFormat::createInstance("root", status);
267 if(U_FAILURE(status)) {
268 dataerrln("unable to create format object - %s", u_errorName(status));
269 }
270 if(test != NULL) {
271 test->setMinimumIntegerDigits(10);
272 test->setMaximumIntegerDigits(1);
273
274 test->setMinimumFractionDigits(10);
275 test->setMaximumFractionDigits(1);
276
277 UnicodeString result;
278 FieldPosition pos;
279 Formattable bla("Paja Patak"); // Donald Duck for non Serbian speakers
280 test->format(bla, result, pos, status);
281 if(U_SUCCESS(status)) {
282 errln("Yuck... Formatted a duck... As a number!");
283 } else {
284 status = U_ZERO_ERROR;
285 }
286
287 result.remove();
288 int64_t ll = 12;
289 test->format(ll, result);
290 assertEquals("format int64_t error", u"2.0", result);
291
292 test->setMinimumIntegerDigits(4);
293 test->setMinimumFractionDigits(4);
294
295 result.remove();
296 test->format(ll, result);
297 assertEquals("format int64_t error", u"0,012.0000", result);
298
299 ParsePosition ppos;
300 LocalPointer<CurrencyAmount> currAmt(test->parseCurrency("",ppos));
301 // old test for (U_FAILURE(status)) was bogus here, method does not set status!
302 if (ppos.getIndex()) {
303 errln("Parsed empty string as currency");
304 }
305
306 delete test;
307 }
308 }
309
310 class StubNumberFormat :public NumberFormat{
311 public:
StubNumberFormat()312 StubNumberFormat(){}
format(double,UnicodeString & appendTo,FieldPosition &) const313 virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const override {
314 return appendTo;
315 }
format(int32_t,UnicodeString & appendTo,FieldPosition &) const316 virtual UnicodeString& format(int32_t ,UnicodeString& appendTo,FieldPosition& ) const override {
317 return appendTo.append((UChar)0x0033);
318 }
format(int64_t number,UnicodeString & appendTo,FieldPosition & pos) const319 virtual UnicodeString& format(int64_t number,UnicodeString& appendTo,FieldPosition& pos) const override {
320 return NumberFormat::format(number, appendTo, pos);
321 }
format(const Formattable &,UnicodeString & appendTo,FieldPosition &,UErrorCode &) const322 virtual UnicodeString& format(const Formattable& , UnicodeString& appendTo, FieldPosition& , UErrorCode& ) const override {
323 return appendTo;
324 }
parse(const UnicodeString &,Formattable &,ParsePosition &) const325 virtual void parse(const UnicodeString& ,
326 Formattable& ,
327 ParsePosition& ) const override {}
parse(const UnicodeString &,Formattable &,UErrorCode &) const328 virtual void parse( const UnicodeString& ,
329 Formattable& ,
330 UErrorCode& ) const override {}
getDynamicClassID(void) const331 virtual UClassID getDynamicClassID(void) const override {
332 static char classID = 0;
333 return (UClassID)&classID;
334 }
clone() const335 virtual StubNumberFormat* clone() const override {return NULL;}
336 };
337
338 void
TestCoverage(void)339 NumberFormatTest::TestCoverage(void){
340 StubNumberFormat stub;
341 UnicodeString agent("agent");
342 FieldPosition pos;
343 int64_t num = 4;
344 if (stub.format(num, agent, pos) != UnicodeString("agent3")){
345 errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)");
346 }
347 }
348
TestLocalizedPatternSymbolCoverage()349 void NumberFormatTest::TestLocalizedPatternSymbolCoverage() {
350 IcuTestErrorCode errorCode(*this, "TestLocalizedPatternSymbolCoverage");
351 // Ticket #12961: DecimalFormat::toLocalizedPattern() is not working as designed.
352 DecimalFormatSymbols dfs(errorCode);
353 dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u'⁖');
354 dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'⁘');
355 dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u'⁙');
356 dfs.setSymbol(DecimalFormatSymbols::kDigitSymbol, u'▰');
357 dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u'໐');
358 dfs.setSymbol(DecimalFormatSymbols::kSignificantDigitSymbol, u'⁕');
359 dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u'†');
360 dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u'‡');
361 dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u'⁜');
362 dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u'‱');
363 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"⁑⁑"); // tests multi-char sequence
364 dfs.setSymbol(DecimalFormatSymbols::kPadEscapeSymbol, u'⁂');
365
366 {
367 UnicodeString standardPattern(u"#,##0.05+%;#,##0.05-%");
368 UnicodeString localizedPattern(u"▰⁖▰▰໐⁘໐໕†⁜⁙▰⁖▰▰໐⁘໐໕‡⁜");
369
370 DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
371 df1.applyPattern(standardPattern, errorCode);
372 DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
373 df2.applyLocalizedPattern(localizedPattern, errorCode);
374 assertTrue("DecimalFormat instances should be equal", df1 == df2);
375 UnicodeString p2;
376 assertEquals("toPattern should match on localizedPattern instance",
377 standardPattern, df2.toPattern(p2));
378 UnicodeString lp1;
379 assertEquals("toLocalizedPattern should match on standardPattern instance",
380 localizedPattern, df1.toLocalizedPattern(lp1));
381 }
382
383 {
384 UnicodeString standardPattern(u"* @@@E0‰");
385 UnicodeString localizedPattern(u"⁂ ⁕⁕⁕⁑⁑໐‱");
386
387 DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
388 df1.applyPattern(standardPattern, errorCode);
389 DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
390 df2.applyLocalizedPattern(localizedPattern, errorCode);
391 assertTrue("DecimalFormat instances should be equal", df1 == df2);
392 UnicodeString p2;
393 assertEquals("toPattern should match on localizedPattern instance",
394 standardPattern, df2.toPattern(p2));
395 UnicodeString lp1;
396 assertEquals("toLocalizedPattern should match on standardPattern instance",
397 localizedPattern, df1.toLocalizedPattern(lp1));
398 }
399 }
400
401 // Test various patterns
402 void
TestPatterns(void)403 NumberFormatTest::TestPatterns(void)
404 {
405 UErrorCode status = U_ZERO_ERROR;
406 DecimalFormatSymbols sym(Locale::getUS(), status);
407 if (U_FAILURE(status)) { errcheckln(status, "FAIL: Could not construct DecimalFormatSymbols - %s", u_errorName(status)); return; }
408
409 const char* pat[] = { "#.#", "#.", ".#", "#" };
410 int32_t pat_length = UPRV_LENGTHOF(pat);
411 const char* newpat[] = { "0.#", "0.", "#.0", "0" };
412 const char* num[] = { "0", "0.", ".0", "0" };
413 for (int32_t i=0; i<pat_length; ++i)
414 {
415 status = U_ZERO_ERROR;
416 DecimalFormat fmt(pat[i], sym, status);
417 if (U_FAILURE(status)) { errln((UnicodeString)"FAIL: DecimalFormat constructor failed for " + pat[i]); continue; }
418 UnicodeString newp; fmt.toPattern(newp);
419 if (!(newp == newpat[i]))
420 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
421 "; " + newp + " seen instead");
422
423 UnicodeString s; (*(NumberFormat*)&fmt).format((int32_t)0, s);
424 if (!(s == num[i]))
425 {
426 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
427 "; " + s + " seen instead");
428 logln((UnicodeString)"Min integer digits = " + fmt.getMinimumIntegerDigits());
429 }
430 }
431 }
432
Test20186_SpacesAroundSemicolon()433 void NumberFormatTest::Test20186_SpacesAroundSemicolon() {
434 IcuTestErrorCode status(*this, "Test20186_SpacesAroundSemicolon");
435 DecimalFormat df(u"0.00 ; -0.00", {"en-us", status}, status);
436 expect2(df, 1, u"1.00 ");
437 expect2(df, -1, u" -1.00");
438
439 df = DecimalFormat(u"0.00;", {"en-us", status}, status);
440 expect2(df, 1, u"1.00");
441 expect2(df, -1, u"-1.00");
442
443 df = DecimalFormat(u"0.00;0.00", {"en-us", status}, status);
444 expect2(df, 1, u"1.00");
445 expect(df, -1, u"1.00"); // parses as 1, not -1
446
447 df = DecimalFormat(u" 0.00 ; -0.00 ", {"en-us", status}, status);
448 expect2(df, 1, u" 1.00 ");
449 expect2(df, -1, u" -1.00 ");
450 }
451
452 /*
453 icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
454 icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
455 icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
456 */
457 /*
458 void
459 NumberFormatTest::TestDigitList(void)
460 {
461 // API coverage for DigitList
462 DigitList list1;
463 list1.append('1');
464 list1.fDecimalAt = 1;
465 DigitList list2;
466 list2.set((int32_t)1);
467 if (list1 != list2) {
468 errln("digitlist append, operator!= or set failed ");
469 }
470 if (!(list1 == list2)) {
471 errln("digitlist append, operator== or set failed ");
472 }
473 }
474 */
475
476 // -------------------------------------
477
478 // Test exponential pattern
479 void
TestExponential(void)480 NumberFormatTest::TestExponential(void)
481 {
482 UErrorCode status = U_ZERO_ERROR;
483 DecimalFormatSymbols sym(Locale::getUS(), status);
484 if (U_FAILURE(status)) { errcheckln(status, "FAIL: Bad status returned by DecimalFormatSymbols ct - %s", u_errorName(status)); return; }
485 const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
486 int32_t pat_length = UPRV_LENGTHOF(pat);
487
488 // The following #if statements allow this test to be built and run on
489 // platforms that do not have standard IEEE numerics. For example,
490 // S/390 doubles have an exponent range of -78 to +75. For the
491 // following #if statements to work, float.h must define
492 // DBL_MAX_10_EXP to be a compile-time constant.
493
494 // This section may be expanded as needed.
495
496 #if DBL_MAX_10_EXP > 300
497 double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
498 int32_t val_length = UPRV_LENGTHOF(val);
499 const char* valFormat[] =
500 {
501 // 0.####E0
502 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
503 // 00.000E00
504 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
505 // ##0.######E000
506 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
507 // 0.###E0;[0.###E0]
508 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
509 };
510 double valParse[] =
511 {
512 0.01234, 123460000, 1.23E300, -3.1416E-271,
513 0.01234, 123460000, 1.23E300, -3.1416E-271,
514 0.01234, 123456800, 1.23E300, -3.141593E-271,
515 0.01234, 123500000, 1.23E300, -3.142E-271,
516 };
517 #elif DBL_MAX_10_EXP > 70
518 double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
519 int32_t val_length = UPRV_LENGTHOF(val);
520 char* valFormat[] =
521 {
522 // 0.####E0
523 "1.234E-2", "1.2346E8", "1.23E70", "-3.1416E-71",
524 // 00.000E00
525 "12.340E-03", "12.346E07", "12.300E69", "-31.416E-72",
526 // ##0.######E000
527 "12.34E-003", "123.4568E006", "12.3E069", "-31.41593E-072",
528 // 0.###E0;[0.###E0]
529 "1.234E-2", "1.235E8", "1.23E70", "[3.142E-71]"
530 };
531 double valParse[] =
532 {
533 0.01234, 123460000, 1.23E70, -3.1416E-71,
534 0.01234, 123460000, 1.23E70, -3.1416E-71,
535 0.01234, 123456800, 1.23E70, -3.141593E-71,
536 0.01234, 123500000, 1.23E70, -3.142E-71,
537 };
538 #else
539 // Don't test double conversion
540 double* val = 0;
541 int32_t val_length = 0;
542 char** valFormat = 0;
543 double* valParse = 0;
544 logln("Warning: Skipping double conversion tests");
545 #endif
546
547 int32_t lval[] = { 0, -1, 1, 123456789 };
548 int32_t lval_length = UPRV_LENGTHOF(lval);
549 const char* lvalFormat[] =
550 {
551 // 0.####E0
552 "0E0", "-1E0", "1E0", "1.2346E8",
553 // 00.000E00
554 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
555 // ##0.######E000
556 "0E000", "-1E000", "1E000", "123.4568E006",
557 // 0.###E0;[0.###E0]
558 "0E0", "[1E0]", "1E0", "1.235E8"
559 };
560 int32_t lvalParse[] =
561 {
562 0, -1, 1, 123460000,
563 0, -1, 1, 123460000,
564 0, -1, 1, 123456800,
565 0, -1, 1, 123500000,
566 };
567 int32_t ival = 0, ilval = 0;
568 for (int32_t p=0; p<pat_length; ++p)
569 {
570 DecimalFormat fmt(pat[p], sym, status);
571 if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormat ct"); continue; }
572 UnicodeString pattern;
573 logln((UnicodeString)"Pattern \"" + pat[p] + "\" -toPattern-> \"" +
574 fmt.toPattern(pattern) + "\"");
575 int32_t v;
576 for (v=0; v<val_length; ++v)
577 {
578 UnicodeString s; (*(NumberFormat*)&fmt).format(val[v], s);
579 logln((UnicodeString)" " + val[v] + " -format-> " + s);
580 if (s != valFormat[v+ival])
581 errln((UnicodeString)"FAIL: Expected " + valFormat[v+ival]);
582
583 ParsePosition pos(0);
584 Formattable af;
585 fmt.parse(s, af, pos);
586 double a;
587 UBool useEpsilon = FALSE;
588 if (af.getType() == Formattable::kLong)
589 a = af.getLong();
590 else if (af.getType() == Formattable::kDouble) {
591 a = af.getDouble();
592 #if U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400
593 // S/390 will show a failure like this:
594 //| -3.141592652999999e-271 -format-> -3.1416E-271
595 //| -parse-> -3.1416e-271
596 //| FAIL: Expected -3.141599999999999e-271
597 // To compensate, we use an epsilon-based equality
598 // test on S/390 only. We don't want to do this in
599 // general because it's less exacting.
600 useEpsilon = TRUE;
601 #endif
602 }
603 else {
604 errln(UnicodeString("FAIL: Non-numeric Formattable returned: ") + pattern + " " + s);
605 continue;
606 }
607 if (pos.getIndex() == s.length())
608 {
609 logln((UnicodeString)" -parse-> " + a);
610 // Use epsilon comparison as necessary
611 if ((useEpsilon &&
612 (uprv_fabs(a - valParse[v+ival]) / a > (2*DBL_EPSILON))) ||
613 (!useEpsilon && a != valParse[v+ival]))
614 {
615 errln((UnicodeString)"FAIL: Expected " + valParse[v+ival] + " but got " + a
616 + " on input " + s);
617 }
618 }
619 else {
620 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
621 errln((UnicodeString)" should be (" + s.length() + " chars) -> " + valParse[v+ival]);
622 }
623 }
624 for (v=0; v<lval_length; ++v)
625 {
626 UnicodeString s;
627 (*(NumberFormat*)&fmt).format(lval[v], s);
628 logln((UnicodeString)" " + lval[v] + "L -format-> " + s);
629 if (s != lvalFormat[v+ilval])
630 errln((UnicodeString)"ERROR: Expected " + lvalFormat[v+ilval] + " Got: " + s);
631
632 ParsePosition pos(0);
633 Formattable af;
634 fmt.parse(s, af, pos);
635 if (af.getType() == Formattable::kLong ||
636 af.getType() == Formattable::kInt64) {
637 UErrorCode status = U_ZERO_ERROR;
638 int32_t a = af.getLong(status);
639 if (pos.getIndex() == s.length())
640 {
641 logln((UnicodeString)" -parse-> " + a);
642 if (a != lvalParse[v+ilval])
643 errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval] + " but got " + a);
644 }
645 else
646 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
647 }
648 else
649 errln((UnicodeString)"FAIL: Non-long Formattable returned for " + s
650 + " Double: " + af.getDouble()
651 + ", Long: " + af.getLong());
652 }
653 ival += val_length;
654 ilval += lval_length;
655 }
656 }
657
658 void
TestScientific2()659 NumberFormatTest::TestScientific2() {
660 // jb 2552
661 UErrorCode status = U_ZERO_ERROR;
662 DecimalFormat* fmt = (DecimalFormat*)NumberFormat::createCurrencyInstance("en_US", status);
663 if (U_SUCCESS(status)) {
664 double num = 12.34;
665 expect(*fmt, num, "$12.34");
666 fmt->setScientificNotation(TRUE);
667 expect(*fmt, num, "$1.23E1");
668 fmt->setScientificNotation(FALSE);
669 expect(*fmt, num, "$12.34");
670 }
671 delete fmt;
672 }
673
674 void
TestScientificGrouping()675 NumberFormatTest::TestScientificGrouping() {
676 // jb 2552
677 UErrorCode status = U_ZERO_ERROR;
678 DecimalFormat fmt("##0.00E0",status);
679 if (assertSuccess("", status, true, __FILE__, __LINE__)) {
680 expect(fmt, .01234, "12.3E-3");
681 expect(fmt, .1234, "123E-3");
682 expect(fmt, 1.234, "1.23E0");
683 expect(fmt, 12.34, "12.3E0");
684 expect(fmt, 123.4, "123E0");
685 expect(fmt, 1234., "1.23E3");
686 }
687 }
688
689 /*static void setFromString(DigitList& dl, const char* str) {
690 char c;
691 UBool decimalSet = FALSE;
692 dl.clear();
693 while ((c = *str++)) {
694 if (c == '-') {
695 dl.fIsPositive = FALSE;
696 } else if (c == '+') {
697 dl.fIsPositive = TRUE;
698 } else if (c == '.') {
699 dl.fDecimalAt = dl.fCount;
700 decimalSet = TRUE;
701 } else {
702 dl.append(c);
703 }
704 }
705 if (!decimalSet) {
706 dl.fDecimalAt = dl.fCount;
707 }
708 }*/
709
710 void
TestInt64()711 NumberFormatTest::TestInt64() {
712 UErrorCode status = U_ZERO_ERROR;
713 DecimalFormat fmt("#.#E0",status);
714 if (U_FAILURE(status)) {
715 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
716 return;
717 }
718 fmt.setMaximumFractionDigits(20);
719 if (U_SUCCESS(status)) {
720 expect(fmt, (Formattable)(int64_t)0, "0E0");
721 expect(fmt, (Formattable)(int64_t)-1, "-1E0");
722 expect(fmt, (Formattable)(int64_t)1, "1E0");
723 expect(fmt, (Formattable)(int64_t)2147483647, "2.147483647E9");
724 expect(fmt, (Formattable)((int64_t)-2147483647-1), "-2.147483648E9");
725 expect(fmt, (Formattable)(int64_t)U_INT64_MAX, "9.223372036854775807E18");
726 expect(fmt, (Formattable)(int64_t)U_INT64_MIN, "-9.223372036854775808E18");
727 }
728
729 // also test digitlist
730 /* int64_t int64max = U_INT64_MAX;
731 int64_t int64min = U_INT64_MIN;
732 const char* int64maxstr = "9223372036854775807";
733 const char* int64minstr = "-9223372036854775808";
734 UnicodeString fail("fail: ");
735
736 // test max int64 value
737 DigitList dl;
738 setFromString(dl, int64maxstr);
739 {
740 if (!dl.fitsIntoInt64(FALSE)) {
741 errln(fail + int64maxstr + " didn't fit");
742 }
743 int64_t int64Value = dl.getInt64();
744 if (int64Value != int64max) {
745 errln(fail + int64maxstr);
746 }
747 dl.set(int64Value);
748 int64Value = dl.getInt64();
749 if (int64Value != int64max) {
750 errln(fail + int64maxstr);
751 }
752 }
753 // test negative of max int64 value (1 shy of min int64 value)
754 dl.fIsPositive = FALSE;
755 {
756 if (!dl.fitsIntoInt64(FALSE)) {
757 errln(fail + "-" + int64maxstr + " didn't fit");
758 }
759 int64_t int64Value = dl.getInt64();
760 if (int64Value != -int64max) {
761 errln(fail + "-" + int64maxstr);
762 }
763 dl.set(int64Value);
764 int64Value = dl.getInt64();
765 if (int64Value != -int64max) {
766 errln(fail + "-" + int64maxstr);
767 }
768 }
769 // test min int64 value
770 setFromString(dl, int64minstr);
771 {
772 if (!dl.fitsIntoInt64(FALSE)) {
773 errln(fail + "-" + int64minstr + " didn't fit");
774 }
775 int64_t int64Value = dl.getInt64();
776 if (int64Value != int64min) {
777 errln(fail + int64minstr);
778 }
779 dl.set(int64Value);
780 int64Value = dl.getInt64();
781 if (int64Value != int64min) {
782 errln(fail + int64minstr);
783 }
784 }
785 // test negative of min int 64 value (1 more than max int64 value)
786 dl.fIsPositive = TRUE; // won't fit
787 {
788 if (dl.fitsIntoInt64(FALSE)) {
789 errln(fail + "-(" + int64minstr + ") didn't fit");
790 }
791 }*/
792 }
793
794 // -------------------------------------
795
796 // Test the handling of quotes
797 void
TestQuotes(void)798 NumberFormatTest::TestQuotes(void)
799 {
800 UErrorCode status = U_ZERO_ERROR;
801 UnicodeString *pat;
802 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), status);
803 if (U_FAILURE(status)) {
804 errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
805 delete sym;
806 return;
807 }
808 pat = new UnicodeString("a'fo''o'b#");
809 DecimalFormat *fmt = new DecimalFormat(*pat, *sym, status);
810 UnicodeString s;
811 ((NumberFormat*)fmt)->format((int32_t)123, s);
812 logln((UnicodeString)"Pattern \"" + *pat + "\"");
813 logln((UnicodeString)" Format 123 -> " + escape(s));
814 if (!(s=="afo'ob123"))
815 errln((UnicodeString)"FAIL: Expected afo'ob123");
816
817 s.truncate(0);
818 delete fmt;
819 delete pat;
820
821 pat = new UnicodeString("a''b#");
822 fmt = new DecimalFormat(*pat, *sym, status);
823 ((NumberFormat*)fmt)->format((int32_t)123, s);
824 logln((UnicodeString)"Pattern \"" + *pat + "\"");
825 logln((UnicodeString)" Format 123 -> " + escape(s));
826 if (!(s=="a'b123"))
827 errln((UnicodeString)"FAIL: Expected a'b123");
828 delete fmt;
829 delete pat;
830 delete sym;
831 }
832
833 /**
834 * Test the handling of the currency symbol in patterns.
835 */
836 void
TestCurrencySign(void)837 NumberFormatTest::TestCurrencySign(void)
838 {
839 UErrorCode status = U_ZERO_ERROR;
840 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale::getUS(), status);
841 UnicodeString pat;
842 UChar currency = 0x00A4;
843 if (U_FAILURE(status)) {
844 errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
845 delete sym;
846 return;
847 }
848 // "\xA4#,##0.00;-\xA4#,##0.00"
849 pat.append(currency).append("#,##0.00;-").
850 append(currency).append("#,##0.00");
851 DecimalFormat *fmt = new DecimalFormat(pat, *sym, status);
852 UnicodeString s; ((NumberFormat*)fmt)->format(1234.56, s);
853 pat.truncate(0);
854 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
855 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
856 if (s != "$1,234.56") dataerrln((UnicodeString)"FAIL: Expected $1,234.56");
857 s.truncate(0);
858 ((NumberFormat*)fmt)->format(- 1234.56, s);
859 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
860 if (s != "-$1,234.56") dataerrln((UnicodeString)"FAIL: Expected -$1,234.56");
861 delete fmt;
862 pat.truncate(0);
863 // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
864 pat.append(currency).append(currency).
865 append(" #,##0.00;").
866 append(currency).append(currency).
867 append(" -#,##0.00");
868 fmt = new DecimalFormat(pat, *sym, status);
869 s.truncate(0);
870 ((NumberFormat*)fmt)->format(1234.56, s);
871 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
872 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
873 if (s != "USD 1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD 1,234.56");
874 s.truncate(0);
875 ((NumberFormat*)fmt)->format(-1234.56, s);
876 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
877 if (s != "USD -1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD -1,234.56");
878 delete fmt;
879 delete sym;
880 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + u_errorName(status));
881 }
882
883 // -------------------------------------
884
toHexString(int32_t i)885 static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
886
887 UnicodeString&
escape(UnicodeString & s)888 NumberFormatTest::escape(UnicodeString& s)
889 {
890 UnicodeString buf;
891 for (int32_t i=0; i<s.length(); ++i)
892 {
893 UChar c = s[(int32_t)i];
894 if (c <= (UChar)0x7F) buf += c;
895 else {
896 buf += (UChar)0x5c; buf += (UChar)0x55;
897 buf += toHexString((c & 0xF000) >> 12);
898 buf += toHexString((c & 0x0F00) >> 8);
899 buf += toHexString((c & 0x00F0) >> 4);
900 buf += toHexString(c & 0x000F);
901 }
902 }
903 return (s = buf);
904 }
905
906
907 // -------------------------------------
908 static const char* testCases[][2]= {
909 /* locale ID */ /* expected */
910 {"ca_ES@currency=ESP", "\\u20A7\\u00A01.150" },
911 {"de_LU@currency=LUF", "1,150\\u00A0F" },
912 {"el_GR@currency=GRD", "1.150,50\\u00A0\\u0394\\u03C1\\u03C7" },
913 {"en_BE@currency=BEF", "1.150,50\\u00A0BEF" },
914 {"es_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
915 {"eu_ES@currency=ESP", "\\u20A7\\u00A01.150" },
916 {"gl_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
917 {"it_IT@currency=ITL", "ITL\\u00A01.150" },
918 {"pt_PT@currency=PTE", "1,150$50\\u00A0\\u200B"}, // per cldrbug 7670
919 {"en_US@currency=JPY", "\\u00A51,150"},
920 {"en_US@currency=jpy", "\\u00A51,150"},
921 {"en-US-u-cu-jpy", "\\u00A51,150"}
922 };
923 /**
924 * Test localized currency patterns.
925 */
926 void
TestCurrency(void)927 NumberFormatTest::TestCurrency(void)
928 {
929 UErrorCode status = U_ZERO_ERROR;
930 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
931 if (U_FAILURE(status)) {
932 dataerrln("Error calling NumberFormat::createCurrencyInstance()");
933 return;
934 }
935
936 UnicodeString s; currencyFmt->format(1.50, s);
937 logln((UnicodeString)"Un pauvre ici a..........." + s);
938 if (!(s==CharsToUnicodeString("1,50\\u00A0$")))
939 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$ but got " + s);
940 delete currencyFmt;
941 s.truncate(0);
942 char loc[256]={0};
943 int len = uloc_canonicalize("de_DE@currency=DEM", loc, 256, &status);
944 (void)len; // Suppress unused variable warning.
945 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
946 currencyFmt->format(1.50, s);
947 logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
948 if (!(s==CharsToUnicodeString("1,50\\u00A0DM")))
949 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM but got " + s);
950 delete currencyFmt;
951 s.truncate(0);
952 len = uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status);
953 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
954 currencyFmt->format(1.50, s);
955 logln((UnicodeString)"Un pauvre en France a....." + s);
956 if (!(s==CharsToUnicodeString("1,50\\u00A0F")))
957 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>F");
958 delete currencyFmt;
959 if (U_FAILURE(status))
960 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
961
962 for(int i=0; i < UPRV_LENGTHOF(testCases); i++){
963 status = U_ZERO_ERROR;
964 const char *localeID = testCases[i][0];
965 UnicodeString expected(testCases[i][1], -1, US_INV);
966 expected = expected.unescape();
967 s.truncate(0);
968 char loc[256]={0};
969 uloc_canonicalize(localeID, loc, 256, &status);
970 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
971 if(U_FAILURE(status)){
972 errln("Could not create currency formatter for locale %s",localeID);
973 continue;
974 }
975 currencyFmt->format(1150.50, s);
976 if(s!=expected){
977 errln(UnicodeString("FAIL: Expected: ")+expected
978 + UnicodeString(" Got: ") + s
979 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
980 }
981 if (U_FAILURE(status)){
982 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
983 }
984 delete currencyFmt;
985 }
986 }
987
988 // -------------------------------------
989
990 /**
991 * Test the Currency object handling, new as of ICU 2.2.
992 */
TestCurrencyObject()993 void NumberFormatTest::TestCurrencyObject() {
994 UErrorCode ec = U_ZERO_ERROR;
995 NumberFormat* fmt =
996 NumberFormat::createCurrencyInstance(Locale::getUS(), ec);
997
998 if (U_FAILURE(ec)) {
999 dataerrln("FAIL: getCurrencyInstance(US) - %s", u_errorName(ec));
1000 delete fmt;
1001 return;
1002 }
1003
1004 Locale null("", "", "");
1005
1006 expectCurrency(*fmt, null, 1234.56, "$1,234.56");
1007
1008 expectCurrency(*fmt, Locale::getFrance(),
1009 1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro
1010
1011 expectCurrency(*fmt, Locale::getJapan(),
1012 1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
1013
1014 expectCurrency(*fmt, Locale("fr", "CH", ""),
1015 1234.56, "CHF 1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
1016
1017 expectCurrency(*fmt, Locale::getUS(),
1018 1234.56, "$1,234.56");
1019
1020 delete fmt;
1021 fmt = NumberFormat::createCurrencyInstance(Locale::getFrance(), ec);
1022
1023 if (U_FAILURE(ec)) {
1024 errln("FAIL: getCurrencyInstance(FRANCE)");
1025 delete fmt;
1026 return;
1027 }
1028
1029 expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC"));
1030
1031 expectCurrency(*fmt, Locale::getJapan(),
1032 1234.56, CharsToUnicodeString("1\\u202F235 JPY")); // Yen
1033
1034 expectCurrency(*fmt, Locale("fr", "CH", ""),
1035 1234.56, CharsToUnicodeString("1\\u202F234,56 CHF")); // no more 0.05 rounding here, see cldrbug 5548
1036
1037 expectCurrency(*fmt, Locale::getUS(),
1038 1234.56, CharsToUnicodeString("1\\u202F234,56 $US"));
1039
1040 expectCurrency(*fmt, Locale::getFrance(),
1041 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC")); // Euro
1042
1043 delete fmt;
1044 }
1045
1046 // -------------------------------------
1047
1048 /**
1049 * Do rudimentary testing of parsing.
1050 */
1051 void
TestParse(void)1052 NumberFormatTest::TestParse(void)
1053 {
1054 UErrorCode status = U_ZERO_ERROR;
1055 UnicodeString arg("0");
1056 DecimalFormat* format = new DecimalFormat("00", status);
1057 //try {
1058 Formattable n; format->parse(arg, n, status);
1059 logln((UnicodeString)"parse(" + arg + ") = " + n.getLong());
1060 if (n.getType() != Formattable::kLong ||
1061 n.getLong() != 0) errln((UnicodeString)"FAIL: Expected 0");
1062 delete format;
1063 if (U_FAILURE(status)) errcheckln(status, (UnicodeString)"FAIL: Status " + u_errorName(status));
1064 //}
1065 //catch(Exception e) {
1066 // errln((UnicodeString)"Exception caught: " + e);
1067 //}
1068 }
1069
1070 // -------------------------------------
1071
1072 static const char *lenientAffixTestCases[] = {
1073 "(1)",
1074 "( 1)",
1075 "(1 )",
1076 "( 1 )"
1077 };
1078
1079 static const char *lenientMinusTestCases[] = {
1080 "-5",
1081 "\\u22125",
1082 "\\u27965"
1083 };
1084
1085 static const char *lenientCurrencyTestCases[] = {
1086 "$1,000",
1087 "$ 1,000",
1088 "$1000",
1089 "$ 1000",
1090 "$1 000.00",
1091 "$ 1 000.00",
1092 "$ 1\\u00A0000.00",
1093 "1000.00"
1094 };
1095
1096 // changed from () to - per cldrbug 5674
1097 static const char *lenientNegativeCurrencyTestCases[] = {
1098 "-$1,000",
1099 "-$ 1,000",
1100 "-$1000",
1101 "-$ 1000",
1102 "-$1 000.00",
1103 "-$ 1 000.00",
1104 "- $ 1,000.00 ",
1105 "-$ 1\\u00A0000.00",
1106 "-1000.00"
1107 };
1108
1109 static const char *lenientPercentTestCases[] = {
1110 "25%",
1111 " 25%",
1112 " 25 %",
1113 "25 %",
1114 "25\\u00A0%",
1115 "25"
1116 };
1117
1118 static const char *lenientNegativePercentTestCases[] = {
1119 "-25%",
1120 " -25%",
1121 " - 25%",
1122 "- 25 %",
1123 " - 25 %",
1124 "-25 %",
1125 "-25\\u00A0%",
1126 "-25",
1127 "- 25"
1128 };
1129
1130 static const char *strictFailureTestCases[] = {
1131 " 1000",
1132 "10,00",
1133 "1,000,.0"
1134 };
1135
1136 /**
1137 * Test lenient parsing.
1138 */
1139 void
TestLenientParse(void)1140 NumberFormatTest::TestLenientParse(void)
1141 {
1142 UErrorCode status = U_ZERO_ERROR;
1143 DecimalFormat *format = new DecimalFormat("(#,##0)", status);
1144 Formattable n;
1145
1146 if (format == NULL || U_FAILURE(status)) {
1147 dataerrln("Unable to create DecimalFormat (#,##0) - %s", u_errorName(status));
1148 } else {
1149 format->setLenient(TRUE);
1150 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientAffixTestCases); t += 1) {
1151 UnicodeString testCase = ctou(lenientAffixTestCases[t]);
1152
1153 format->parse(testCase, n, status);
1154 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1155
1156 if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
1157 n.getLong() != 1) {
1158 dataerrln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t]
1159 + (UnicodeString) "\"; error code = " + u_errorName(status));
1160 status = U_ZERO_ERROR;
1161 }
1162 }
1163 delete format;
1164 }
1165
1166 Locale en_US("en_US");
1167 Locale sv_SE("sv_SE");
1168
1169 NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, UNUM_DECIMAL, status);
1170
1171 if (mFormat == NULL || U_FAILURE(status)) {
1172 dataerrln("Unable to create NumberFormat (sv_SE, UNUM_DECIMAL) - %s", u_errorName(status));
1173 } else {
1174 mFormat->setLenient(TRUE);
1175 for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1176 UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1177
1178 mFormat->parse(testCase, n, status);
1179 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1180
1181 if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1182 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1183 + (UnicodeString) "\"; error code = " + u_errorName(status));
1184 status = U_ZERO_ERROR;
1185 }
1186 }
1187 delete mFormat;
1188 }
1189
1190 mFormat = NumberFormat::createInstance(en_US, UNUM_DECIMAL, status);
1191
1192 if (mFormat == NULL || U_FAILURE(status)) {
1193 dataerrln("Unable to create NumberFormat (en_US, UNUM_DECIMAL) - %s", u_errorName(status));
1194 } else {
1195 mFormat->setLenient(TRUE);
1196 for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1197 UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1198
1199 mFormat->parse(testCase, n, status);
1200 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1201
1202 if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1203 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1204 + (UnicodeString) "\"; error code = " + u_errorName(status));
1205 status = U_ZERO_ERROR;
1206 }
1207 }
1208 delete mFormat;
1209 }
1210
1211 NumberFormat *cFormat = NumberFormat::createInstance(en_US, UNUM_CURRENCY, status);
1212
1213 if (cFormat == NULL || U_FAILURE(status)) {
1214 dataerrln("Unable to create NumberFormat (en_US, UNUM_CURRENCY) - %s", u_errorName(status));
1215 } else {
1216 cFormat->setLenient(TRUE);
1217 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientCurrencyTestCases); t += 1) {
1218 UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
1219
1220 cFormat->parse(testCase, n, status);
1221 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1222
1223 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1224 n.getLong() != 1000) {
1225 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t]
1226 + (UnicodeString) "\"; error code = " + u_errorName(status));
1227 status = U_ZERO_ERROR;
1228 }
1229 }
1230
1231 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativeCurrencyTestCases); t += 1) {
1232 UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
1233
1234 cFormat->parse(testCase, n, status);
1235 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1236
1237 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1238 n.getLong() != -1000) {
1239 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t]
1240 + (UnicodeString) "\"; error code = " + u_errorName(status));
1241 status = U_ZERO_ERROR;
1242 }
1243 }
1244
1245 delete cFormat;
1246 }
1247
1248 NumberFormat *pFormat = NumberFormat::createPercentInstance(en_US, status);
1249
1250 if (pFormat == NULL || U_FAILURE(status)) {
1251 dataerrln("Unable to create NumberFormat::createPercentInstance (en_US) - %s", u_errorName(status));
1252 } else {
1253 pFormat->setLenient(TRUE);
1254 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientPercentTestCases); t += 1) {
1255 UnicodeString testCase = ctou(lenientPercentTestCases[t]);
1256
1257 pFormat->parse(testCase, n, status);
1258 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1259
1260 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1261 n.getDouble() != 0.25) {
1262 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t]
1263 + (UnicodeString) "\"; error code = " + u_errorName(status)
1264 + "; got: " + n.getDouble(status));
1265 status = U_ZERO_ERROR;
1266 }
1267 }
1268
1269 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativePercentTestCases); t += 1) {
1270 UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
1271
1272 pFormat->parse(testCase, n, status);
1273 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1274
1275 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1276 n.getDouble() != -0.25) {
1277 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t]
1278 + (UnicodeString) "\"; error code = " + u_errorName(status)
1279 + "; got: " + n.getDouble(status));
1280 status = U_ZERO_ERROR;
1281 }
1282 }
1283
1284 delete pFormat;
1285 }
1286
1287 // Test cases that should fail with a strict parse and pass with a
1288 // lenient parse.
1289 NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);
1290
1291 if (nFormat == NULL || U_FAILURE(status)) {
1292 dataerrln("Unable to create NumberFormat (en_US) - %s", u_errorName(status));
1293 } else {
1294 // first, make sure that they fail with a strict parse
1295 for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1296 UnicodeString testCase = ctou(strictFailureTestCases[t]);
1297
1298 nFormat->parse(testCase, n, status);
1299 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1300
1301 if (! U_FAILURE(status)) {
1302 errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t]
1303 + (UnicodeString) "\"; error code = " + u_errorName(status));
1304 }
1305
1306 status = U_ZERO_ERROR;
1307 }
1308
1309 // then, make sure that they pass with a lenient parse
1310 nFormat->setLenient(TRUE);
1311 for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1312 UnicodeString testCase = ctou(strictFailureTestCases[t]);
1313
1314 nFormat->parse(testCase, n, status);
1315 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1316
1317 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1318 n.getLong() != 1000) {
1319 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t]
1320 + (UnicodeString) "\"; error code = " + u_errorName(status));
1321 status = U_ZERO_ERROR;
1322 }
1323 }
1324
1325 delete nFormat;
1326 }
1327 }
1328
1329 // -------------------------------------
1330
1331 /**
1332 * Test proper rounding by the format method.
1333 */
1334 void
TestRounding487(void)1335 NumberFormatTest::TestRounding487(void)
1336 {
1337 UErrorCode status = U_ZERO_ERROR;
1338 NumberFormat *nf = NumberFormat::createInstance(status);
1339 if (U_FAILURE(status)) {
1340 dataerrln("Error calling NumberFormat::createInstance()");
1341 return;
1342 }
1343
1344 roundingTest(*nf, 0.00159999, 4, "0.0016");
1345 roundingTest(*nf, 0.00995, 4, "0.01");
1346
1347 roundingTest(*nf, 12.3995, 3, "12.4");
1348
1349 roundingTest(*nf, 12.4999, 0, "12");
1350 roundingTest(*nf, - 19.5, 0, "-20");
1351 delete nf;
1352 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
1353 }
1354
1355 /**
1356 * Test the functioning of the secondary grouping value.
1357 */
TestSecondaryGrouping(void)1358 void NumberFormatTest::TestSecondaryGrouping(void) {
1359 UErrorCode status = U_ZERO_ERROR;
1360 DecimalFormatSymbols US(Locale::getUS(), status);
1361 CHECK(status, "DecimalFormatSymbols ct");
1362
1363 DecimalFormat f("#,##,###", US, status);
1364 CHECK(status, "DecimalFormat ct");
1365
1366 expect2(f, (int32_t)123456789L, "12,34,56,789");
1367 expectPat(f, "#,##,##0");
1368 f.applyPattern("#,###", status);
1369 CHECK(status, "applyPattern");
1370
1371 f.setSecondaryGroupingSize(4);
1372 expect2(f, (int32_t)123456789L, "12,3456,789");
1373 expectPat(f, "#,####,##0");
1374 NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
1375 CHECK_DATA(status, "createInstance(hi_IN)");
1376
1377 UnicodeString out;
1378 int32_t l = (int32_t)1876543210L;
1379 g->format(l, out);
1380 delete g;
1381 // expect "1,87,65,43,210", but with Hindi digits
1382 // 01234567890123
1383 UBool ok = TRUE;
1384 if (out.length() != 14) {
1385 ok = FALSE;
1386 } else {
1387 for (int32_t i=0; i<out.length(); ++i) {
1388 UBool expectGroup = FALSE;
1389 switch (i) {
1390 case 1:
1391 case 4:
1392 case 7:
1393 case 10:
1394 expectGroup = TRUE;
1395 break;
1396 }
1397 // Later -- fix this to get the actual grouping
1398 // character from the resource bundle.
1399 UBool isGroup = (out.charAt(i) == 0x002C);
1400 if (isGroup != expectGroup) {
1401 ok = FALSE;
1402 break;
1403 }
1404 }
1405 }
1406 if (!ok) {
1407 errln((UnicodeString)"FAIL Expected " + l +
1408 " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
1409 escape(out) + "\"");
1410 } else {
1411 logln((UnicodeString)"Ok " + l +
1412 " x hi_IN -> \"" +
1413 escape(out) + "\"");
1414 }
1415 }
1416
TestWhiteSpaceParsing(void)1417 void NumberFormatTest::TestWhiteSpaceParsing(void) {
1418 UErrorCode ec = U_ZERO_ERROR;
1419 DecimalFormatSymbols US(Locale::getUS(), ec);
1420 DecimalFormat fmt("a b#0c ", US, ec);
1421 if (U_FAILURE(ec)) {
1422 errcheckln(ec, "FAIL: Constructor - %s", u_errorName(ec));
1423 return;
1424 }
1425 // From ICU 62, flexible whitespace needs lenient mode
1426 fmt.setLenient(TRUE);
1427 int32_t n = 1234;
1428 expect(fmt, "a b1234c ", n);
1429 expect(fmt, "a b1234c ", n);
1430 }
1431
1432 /**
1433 * Test currencies whose display name is a ChoiceFormat.
1434 */
TestComplexCurrency()1435 void NumberFormatTest::TestComplexCurrency() {
1436
1437 // UErrorCode ec = U_ZERO_ERROR;
1438 // Locale loc("kn", "IN", "");
1439 // NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
1440 // if (U_SUCCESS(ec)) {
1441 // expect2(*fmt, 1.0, CharsToUnicodeString("Re.\\u00A01.00"));
1442 // Use .00392625 because that's 2^-8. Any value less than 0.005 is fine.
1443 // expect(*fmt, 1.00390625, CharsToUnicodeString("Re.\\u00A01.00")); // tricky
1444 // expect2(*fmt, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
1445 // expect2(*fmt, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
1446 // expect2(*fmt, -1.0, CharsToUnicodeString("-Re.\\u00A01.00"));
1447 // expect2(*fmt, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
1448 // } else {
1449 // errln("FAIL: getCurrencyInstance(kn_IN)");
1450 // }
1451 // delete fmt;
1452
1453 }
1454
1455 // -------------------------------------
1456
1457 void
roundingTest(NumberFormat & nf,double x,int32_t maxFractionDigits,const char * expected)1458 NumberFormatTest::roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)
1459 {
1460 nf.setMaximumFractionDigits(maxFractionDigits);
1461 UnicodeString out; nf.format(x, out);
1462 logln((UnicodeString)"" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
1463 if (!(out==expected)) errln((UnicodeString)"FAIL: Expected " + expected);
1464 }
1465
1466 /**
1467 * Upgrade to alphaWorks
1468 */
TestExponent(void)1469 void NumberFormatTest::TestExponent(void) {
1470 UErrorCode status = U_ZERO_ERROR;
1471 DecimalFormatSymbols US(Locale::getUS(), status);
1472 CHECK(status, "DecimalFormatSymbols constructor");
1473 DecimalFormat fmt1(UnicodeString("0.###E0"), US, status);
1474 CHECK(status, "DecimalFormat(0.###E0)");
1475 DecimalFormat fmt2(UnicodeString("0.###E+0"), US, status);
1476 CHECK(status, "DecimalFormat(0.###E+0)");
1477 int32_t n = 1234;
1478 expect2(fmt1, n, "1.234E3");
1479 expect2(fmt2, n, "1.234E+3");
1480 expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
1481 }
1482
1483 /**
1484 * Upgrade to alphaWorks
1485 */
TestScientific(void)1486 void NumberFormatTest::TestScientific(void) {
1487 UErrorCode status = U_ZERO_ERROR;
1488 DecimalFormatSymbols US(Locale::getUS(), status);
1489 CHECK(status, "DecimalFormatSymbols constructor");
1490
1491 // Test pattern round-trip
1492 const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
1493 "0.###E0;[0.###E0]" };
1494 int32_t PAT_length = UPRV_LENGTHOF(PAT);
1495 int32_t DIGITS[] = {
1496 // min int, max int, min frac, max frac
1497 1, 1, 0, 0, // "#E0"
1498 1, 1, 0, 4, // "0.####E0"
1499 2, 2, 3, 3, // "00.000E00"
1500 1, 3, 0, 4, // "##0.####E000"
1501 1, 1, 0, 3, // "0.###E0;[0.###E0]"
1502 };
1503 for (int32_t i=0; i<PAT_length; ++i) {
1504 UnicodeString pat(PAT[i]);
1505 DecimalFormat df(pat, US, status);
1506 CHECK(status, "DecimalFormat constructor");
1507 UnicodeString pat2;
1508 df.toPattern(pat2);
1509 if (pat == pat2) {
1510 logln(UnicodeString("Ok Pattern rt \"") +
1511 pat + "\" -> \"" +
1512 pat2 + "\"");
1513 } else {
1514 errln(UnicodeString("FAIL Pattern rt \"") +
1515 pat + "\" -> \"" +
1516 pat2 + "\"");
1517 }
1518 // Make sure digit counts match what we expect
1519 if (df.getMinimumIntegerDigits() != DIGITS[4*i] ||
1520 df.getMaximumIntegerDigits() != DIGITS[4*i+1] ||
1521 df.getMinimumFractionDigits() != DIGITS[4*i+2] ||
1522 df.getMaximumFractionDigits() != DIGITS[4*i+3]) {
1523 errln(UnicodeString("FAIL \"" + pat +
1524 "\" min/max int; min/max frac = ") +
1525 df.getMinimumIntegerDigits() + "/" +
1526 df.getMaximumIntegerDigits() + ";" +
1527 df.getMinimumFractionDigits() + "/" +
1528 df.getMaximumFractionDigits() + ", expect " +
1529 DIGITS[4*i] + "/" +
1530 DIGITS[4*i+1] + ";" +
1531 DIGITS[4*i+2] + "/" +
1532 DIGITS[4*i+3]);
1533 }
1534 }
1535
1536
1537 // Test the constructor for default locale. We have to
1538 // manually set the default locale, as there is no
1539 // guarantee that the default locale has the same
1540 // scientific format.
1541 Locale def = Locale::getDefault();
1542 Locale::setDefault(Locale::getUS(), status);
1543 expect2(NumberFormat::createScientificInstance(status),
1544 12345.678901,
1545 "1.2345678901E4", status);
1546 Locale::setDefault(def, status);
1547
1548 expect2(new DecimalFormat("#E0", US, status),
1549 12345.0,
1550 "1.2345E4", status);
1551 expect(new DecimalFormat("0E0", US, status),
1552 12345.0,
1553 "1E4", status);
1554 expect2(NumberFormat::createScientificInstance(Locale::getUS(), status),
1555 12345.678901,
1556 "1.2345678901E4", status);
1557 expect(new DecimalFormat("##0.###E0", US, status),
1558 12345.0,
1559 "12.34E3", status);
1560 expect(new DecimalFormat("##0.###E0", US, status),
1561 12345.00001,
1562 "12.35E3", status);
1563 expect2(new DecimalFormat("##0.####E0", US, status),
1564 (int32_t) 12345,
1565 "12.345E3", status);
1566 expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status),
1567 12345.678901,
1568 "1,2345678901E4", status);
1569 expect(new DecimalFormat("##0.####E0", US, status),
1570 789.12345e-9,
1571 "789.12E-9", status);
1572 expect2(new DecimalFormat("##0.####E0", US, status),
1573 780.e-9,
1574 "780E-9", status);
1575 expect(new DecimalFormat(".###E0", US, status),
1576 45678.0,
1577 ".457E5", status);
1578 expect2(new DecimalFormat(".###E0", US, status),
1579 (int32_t) 0,
1580 ".0E0", status);
1581 /*
1582 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
1583 new DecimalFormat("##E0", US),
1584 new DecimalFormat("####E0", US),
1585 new DecimalFormat("0E0", US),
1586 new DecimalFormat("00E0", US),
1587 new DecimalFormat("000E0", US),
1588 },
1589 new Long(45678000),
1590 new String[] { "4.5678E7",
1591 "45.678E6",
1592 "4567.8E4",
1593 "5E7",
1594 "46E6",
1595 "457E5",
1596 }
1597 );
1598 !
1599 ! Unroll this test into individual tests below...
1600 !
1601 */
1602 expect2(new DecimalFormat("#E0", US, status),
1603 (int32_t) 45678000, "4.5678E7", status);
1604 expect2(new DecimalFormat("##E0", US, status),
1605 (int32_t) 45678000, "45.678E6", status);
1606 expect2(new DecimalFormat("####E0", US, status),
1607 (int32_t) 45678000, "4567.8E4", status);
1608 expect(new DecimalFormat("0E0", US, status),
1609 (int32_t) 45678000, "5E7", status);
1610 expect(new DecimalFormat("00E0", US, status),
1611 (int32_t) 45678000, "46E6", status);
1612 expect(new DecimalFormat("000E0", US, status),
1613 (int32_t) 45678000, "457E5", status);
1614 /*
1615 expect(new DecimalFormat("###E0", US, status),
1616 new Object[] { new Double(0.0000123), "12.3E-6",
1617 new Double(0.000123), "123E-6",
1618 new Double(0.00123), "1.23E-3",
1619 new Double(0.0123), "12.3E-3",
1620 new Double(0.123), "123E-3",
1621 new Double(1.23), "1.23E0",
1622 new Double(12.3), "12.3E0",
1623 new Double(123), "123E0",
1624 new Double(1230), "1.23E3",
1625 });
1626 !
1627 ! Unroll this test into individual tests below...
1628 !
1629 */
1630 expect2(new DecimalFormat("###E0", US, status),
1631 0.0000123, "12.3E-6", status);
1632 expect2(new DecimalFormat("###E0", US, status),
1633 0.000123, "123E-6", status);
1634 expect2(new DecimalFormat("###E0", US, status),
1635 0.00123, "1.23E-3", status);
1636 expect2(new DecimalFormat("###E0", US, status),
1637 0.0123, "12.3E-3", status);
1638 expect2(new DecimalFormat("###E0", US, status),
1639 0.123, "123E-3", status);
1640 expect2(new DecimalFormat("###E0", US, status),
1641 1.23, "1.23E0", status);
1642 expect2(new DecimalFormat("###E0", US, status),
1643 12.3, "12.3E0", status);
1644 expect2(new DecimalFormat("###E0", US, status),
1645 123.0, "123E0", status);
1646 expect2(new DecimalFormat("###E0", US, status),
1647 1230.0, "1.23E3", status);
1648 /*
1649 expect(new DecimalFormat("0.#E+00", US, status),
1650 new Object[] { new Double(0.00012), "1.2E-04",
1651 new Long(12000), "1.2E+04",
1652 });
1653 !
1654 ! Unroll this test into individual tests below...
1655 !
1656 */
1657 expect2(new DecimalFormat("0.#E+00", US, status),
1658 0.00012, "1.2E-04", status);
1659 expect2(new DecimalFormat("0.#E+00", US, status),
1660 (int32_t) 12000, "1.2E+04", status);
1661 }
1662
1663 /**
1664 * Upgrade to alphaWorks
1665 */
TestPad(void)1666 void NumberFormatTest::TestPad(void) {
1667 UErrorCode status = U_ZERO_ERROR;
1668 DecimalFormatSymbols US(Locale::getUS(), status);
1669 CHECK(status, "DecimalFormatSymbols constructor");
1670
1671 expect2(new DecimalFormat("*^##.##", US, status),
1672 int32_t(0), "^^^^0", status);
1673 expect2(new DecimalFormat("*^##.##", US, status),
1674 -1.3, "^-1.3", status);
1675 expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1676 int32_t(0), "0.0E0______ g-m/s^2", status);
1677 expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1678 1.0/3, "333.333E-3_ g-m/s^2", status);
1679 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1680 int32_t(0), "0.0______ g-m/s^2", status);
1681 expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1682 1.0/3, "0.33333__ g-m/s^2", status);
1683
1684 // Test padding before a sign
1685 const char *formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1686 expect2(new DecimalFormat(formatStr, US, status),
1687 int32_t(-10), "xxxxxxxxxx(10.0)", status);
1688 expect2(new DecimalFormat(formatStr, US, status),
1689 int32_t(-1000),"xxxxxxx(1,000.0)", status);
1690 expect2(new DecimalFormat(formatStr, US, status),
1691 int32_t(-1000000),"xxx(1,000,000.0)", status);
1692 expect2(new DecimalFormat(formatStr, US, status),
1693 -100.37, "xxxxxxxx(100.37)", status);
1694 expect2(new DecimalFormat(formatStr, US, status),
1695 -10456.37, "xxxxx(10,456.37)", status);
1696 expect2(new DecimalFormat(formatStr, US, status),
1697 -1120456.37, "xx(1,120,456.37)", status);
1698 expect2(new DecimalFormat(formatStr, US, status),
1699 -112045600.37, "(112,045,600.37)", status);
1700 expect2(new DecimalFormat(formatStr, US, status),
1701 -1252045600.37,"(1,252,045,600.37)", status);
1702
1703 expect2(new DecimalFormat(formatStr, US, status),
1704 int32_t(10), "xxxxxxxxxxxx10.0", status);
1705 expect2(new DecimalFormat(formatStr, US, status),
1706 int32_t(1000),"xxxxxxxxx1,000.0", status);
1707 expect2(new DecimalFormat(formatStr, US, status),
1708 int32_t(1000000),"xxxxx1,000,000.0", status);
1709 expect2(new DecimalFormat(formatStr, US, status),
1710 100.37, "xxxxxxxxxx100.37", status);
1711 expect2(new DecimalFormat(formatStr, US, status),
1712 10456.37, "xxxxxxx10,456.37", status);
1713 expect2(new DecimalFormat(formatStr, US, status),
1714 1120456.37, "xxxx1,120,456.37", status);
1715 expect2(new DecimalFormat(formatStr, US, status),
1716 112045600.37, "xx112,045,600.37", status);
1717 expect2(new DecimalFormat(formatStr, US, status),
1718 10252045600.37,"10,252,045,600.37", status);
1719
1720
1721 // Test padding between a sign and a number
1722 const char *formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1723 expect2(new DecimalFormat(formatStr2, US, status),
1724 int32_t(-10), "(10.0xxxxxxxxxx)", status);
1725 expect2(new DecimalFormat(formatStr2, US, status),
1726 int32_t(-1000),"(1,000.0xxxxxxx)", status);
1727 expect2(new DecimalFormat(formatStr2, US, status),
1728 int32_t(-1000000),"(1,000,000.0xxx)", status);
1729 expect2(new DecimalFormat(formatStr2, US, status),
1730 -100.37, "(100.37xxxxxxxx)", status);
1731 expect2(new DecimalFormat(formatStr2, US, status),
1732 -10456.37, "(10,456.37xxxxx)", status);
1733 expect2(new DecimalFormat(formatStr2, US, status),
1734 -1120456.37, "(1,120,456.37xx)", status);
1735 expect2(new DecimalFormat(formatStr2, US, status),
1736 -112045600.37, "(112,045,600.37)", status);
1737 expect2(new DecimalFormat(formatStr2, US, status),
1738 -1252045600.37,"(1,252,045,600.37)", status);
1739
1740 expect2(new DecimalFormat(formatStr2, US, status),
1741 int32_t(10), "10.0xxxxxxxxxxxx", status);
1742 expect2(new DecimalFormat(formatStr2, US, status),
1743 int32_t(1000),"1,000.0xxxxxxxxx", status);
1744 expect2(new DecimalFormat(formatStr2, US, status),
1745 int32_t(1000000),"1,000,000.0xxxxx", status);
1746 expect2(new DecimalFormat(formatStr2, US, status),
1747 100.37, "100.37xxxxxxxxxx", status);
1748 expect2(new DecimalFormat(formatStr2, US, status),
1749 10456.37, "10,456.37xxxxxxx", status);
1750 expect2(new DecimalFormat(formatStr2, US, status),
1751 1120456.37, "1,120,456.37xxxx", status);
1752 expect2(new DecimalFormat(formatStr2, US, status),
1753 112045600.37, "112,045,600.37xx", status);
1754 expect2(new DecimalFormat(formatStr2, US, status),
1755 10252045600.37,"10,252,045,600.37", status);
1756
1757 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1758 DecimalFormat fmt("#", US, status);
1759 CHECK(status, "DecimalFormat constructor");
1760 UnicodeString padString("P");
1761 fmt.setPadCharacter(padString);
1762 expectPad(fmt, "*P##.##", DecimalFormat::kPadBeforePrefix, 5, padString);
1763 fmt.setPadCharacter((UnicodeString)"^");
1764 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, (UnicodeString)"^");
1765 //commented until implementation is complete
1766 /* fmt.setPadCharacter((UnicodeString)"^^^");
1767 expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1768 padString.remove();
1769 padString.append((UChar)0x0061);
1770 padString.append((UChar)0x0302);
1771 fmt.setPadCharacter(padString);
1772 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1773 UnicodeString pattern(patternChars);
1774 expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1775 */
1776
1777 }
1778
1779 /**
1780 * Upgrade to alphaWorks
1781 */
TestPatterns2(void)1782 void NumberFormatTest::TestPatterns2(void) {
1783 UErrorCode status = U_ZERO_ERROR;
1784 DecimalFormatSymbols US(Locale::getUS(), status);
1785 CHECK(status, "DecimalFormatSymbols constructor");
1786
1787 DecimalFormat fmt("#", US, status);
1788 CHECK(status, "DecimalFormat constructor");
1789
1790 UChar hat = 0x005E; /*^*/
1791
1792 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, hat);
1793 expectPad(fmt, "$*^#", DecimalFormat::kPadAfterPrefix, 2, hat);
1794 expectPad(fmt, "#*^", DecimalFormat::kPadBeforeSuffix, 1, hat);
1795 expectPad(fmt, "#$*^", DecimalFormat::kPadAfterSuffix, 2, hat);
1796 expectPad(fmt, "$*^$#", ILLEGAL);
1797 expectPad(fmt, "#$*^$", ILLEGAL);
1798 expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix,
1799 12, (UChar)0x0078 /*x*/);
1800 expectPad(fmt, "''#0*x", DecimalFormat::kPadBeforeSuffix,
1801 3, (UChar)0x0078 /*x*/);
1802 expectPad(fmt, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix,
1803 10, (UChar)0x0061 /*a*/);
1804
1805 fmt.applyPattern("AA#,##0.00ZZ", status);
1806 CHECK(status, "applyPattern");
1807 fmt.setPadCharacter(hat);
1808
1809 fmt.setFormatWidth(10);
1810
1811 fmt.setPadPosition(DecimalFormat::kPadBeforePrefix);
1812 expectPat(fmt, "*^AA#,##0.00ZZ");
1813
1814 fmt.setPadPosition(DecimalFormat::kPadBeforeSuffix);
1815 expectPat(fmt, "AA#,##0.00*^ZZ");
1816
1817 fmt.setPadPosition(DecimalFormat::kPadAfterSuffix);
1818 expectPat(fmt, "AA#,##0.00ZZ*^");
1819
1820 // 12 3456789012
1821 UnicodeString exp("AA*^#,##0.00ZZ", "");
1822 fmt.setFormatWidth(12);
1823 fmt.setPadPosition(DecimalFormat::kPadAfterPrefix);
1824 expectPat(fmt, exp);
1825
1826 fmt.setFormatWidth(13);
1827 // 12 34567890123
1828 expectPat(fmt, "AA*^##,##0.00ZZ");
1829
1830 fmt.setFormatWidth(14);
1831 // 12 345678901234
1832 expectPat(fmt, "AA*^###,##0.00ZZ");
1833
1834 fmt.setFormatWidth(15);
1835 // 12 3456789012345
1836 expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1837
1838 fmt.setFormatWidth(16);
1839 // 12 34567890123456
1840 expectPat(fmt, "AA*^#####,##0.00ZZ");
1841 }
1842
TestSurrogateSupport(void)1843 void NumberFormatTest::TestSurrogateSupport(void) {
1844 UErrorCode status = U_ZERO_ERROR;
1845 DecimalFormatSymbols custom(Locale::getUS(), status);
1846 CHECK(status, "DecimalFormatSymbols constructor");
1847
1848 custom.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, "decimal");
1849 custom.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, "plus");
1850 custom.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, " minus ");
1851 custom.setSymbol(DecimalFormatSymbols::kExponentialSymbol, "exponent");
1852
1853 UnicodeString patternStr("*\\U00010000##.##", "");
1854 patternStr = patternStr.unescape();
1855 UnicodeString expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1856 expStr = expStr.unescape();
1857 expect2(new DecimalFormat(patternStr, custom, status),
1858 int32_t(0), expStr, status);
1859
1860 status = U_ZERO_ERROR;
1861 expect2(new DecimalFormat("*^##.##", custom, status),
1862 int32_t(0), "^^^^0", status);
1863 status = U_ZERO_ERROR;
1864 expect2(new DecimalFormat("##.##", custom, status),
1865 -1.3, " minus 1decimal3", status);
1866 status = U_ZERO_ERROR;
1867 expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1868 int32_t(0), "0decimal0exponent0 g-m/s^2", status);
1869 status = U_ZERO_ERROR;
1870 expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1871 1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
1872 status = U_ZERO_ERROR;
1873 expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1874 int32_t(0), "0decimal0 g-m/s^2", status);
1875 status = U_ZERO_ERROR;
1876 expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1877 1.0/3, "0decimal33333 g-m/s^2", status);
1878
1879 UnicodeString zero((UChar32)0x10000);
1880 UnicodeString one((UChar32)0x10001);
1881 UnicodeString two((UChar32)0x10002);
1882 UnicodeString five((UChar32)0x10005);
1883 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
1884 custom.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, one);
1885 custom.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, two);
1886 custom.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, five);
1887 expStr = UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1888 expStr = expStr.unescape();
1889 status = U_ZERO_ERROR;
1890 expect2(new DecimalFormat("##0.000", custom, status),
1891 1.25, expStr, status);
1892
1893 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
1894 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
1895 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
1896 patternStr = UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
1897 patternStr = patternStr.unescape();
1898 expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1899 status = U_ZERO_ERROR;
1900 expect2(new DecimalFormat(patternStr, custom, status),
1901 int32_t(-20), expStr, status);
1902
1903 custom.setSymbol(DecimalFormatSymbols::kPercentSymbol, "percent");
1904 patternStr = "'You''ve lost ' -0.00 %' of your money today'";
1905 patternStr = patternStr.unescape();
1906 expStr = UnicodeString(" minus You've lost minus 2000decimal00 percent of your money today", "");
1907 status = U_ZERO_ERROR;
1908 expect2(new DecimalFormat(patternStr, custom, status),
1909 int32_t(-20), expStr, status);
1910 }
1911
TestCurrencyPatterns(void)1912 void NumberFormatTest::TestCurrencyPatterns(void) {
1913 int32_t i, locCount;
1914 const Locale* locs = NumberFormat::getAvailableLocales(locCount);
1915 for (i=0; i<locCount; ++i) {
1916 UErrorCode ec = U_ZERO_ERROR;
1917 NumberFormat* nf = NumberFormat::createCurrencyInstance(locs[i], ec);
1918 if (U_FAILURE(ec)) {
1919 errln("FAIL: Can't create NumberFormat(%s) - %s", locs[i].getName(), u_errorName(ec));
1920 } else {
1921 // Make sure currency formats do not have a variable number
1922 // of fraction digits
1923 int32_t min = nf->getMinimumFractionDigits();
1924 int32_t max = nf->getMaximumFractionDigits();
1925 if (min != max) {
1926 UnicodeString a, b;
1927 nf->format(1.0, a);
1928 nf->format(1.125, b);
1929 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1930 " min fraction digits != max fraction digits; "
1931 "x 1.0 => " + escape(a) +
1932 "; x 1.125 => " + escape(b));
1933 }
1934
1935 // Make sure EURO currency formats have exactly 2 fraction digits
1936 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
1937 if (df != NULL) {
1938 if (u_strcmp(EUR, df->getCurrency()) == 0) {
1939 if (min != 2 || max != 2) {
1940 UnicodeString a;
1941 nf->format(1.0, a);
1942 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1943 " is a EURO format but it does not have 2 fraction digits; "
1944 "x 1.0 => " +
1945 escape(a));
1946 }
1947 }
1948 }
1949 }
1950 delete nf;
1951 }
1952 }
1953
TestRegCurrency(void)1954 void NumberFormatTest::TestRegCurrency(void) {
1955 #if !UCONFIG_NO_SERVICE
1956 UErrorCode status = U_ZERO_ERROR;
1957 UChar USD[4];
1958 ucurr_forLocale("en_US", USD, 4, &status);
1959 UChar YEN[4];
1960 ucurr_forLocale("ja_JP", YEN, 4, &status);
1961 UChar TMP[4];
1962
1963 if(U_FAILURE(status)) {
1964 errcheckln(status, "Unable to get currency for locale, error %s", u_errorName(status));
1965 return;
1966 }
1967
1968 UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
1969
1970 ucurr_forLocale("en_US", TMP, 4, &status);
1971 if (u_strcmp(YEN, TMP) != 0) {
1972 errln("FAIL: didn't return YEN registered for en_US");
1973 }
1974
1975 int32_t fallbackLen = ucurr_forLocale("en_XX_BAR", TMP, 4, &status);
1976 if (fallbackLen) {
1977 errln("FAIL: tried to fallback en_XX_BAR");
1978 }
1979 status = U_ZERO_ERROR; // reset
1980
1981 if (!ucurr_unregister(enkey, &status)) {
1982 errln("FAIL: couldn't unregister enkey");
1983 }
1984
1985 ucurr_forLocale("en_US", TMP, 4, &status);
1986 if (u_strcmp(USD, TMP) != 0) {
1987 errln("FAIL: didn't return USD for en_US after unregister of en_US");
1988 }
1989 status = U_ZERO_ERROR; // reset
1990
1991 ucurr_forLocale("en_US_BLAH", TMP, 4, &status);
1992 if (u_strcmp(USD, TMP) != 0) {
1993 errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1994 }
1995 status = U_ZERO_ERROR; // reset
1996 #endif
1997 }
1998
TestCurrencyNames(void)1999 void NumberFormatTest::TestCurrencyNames(void) {
2000 // Do a basic check of getName()
2001 // USD { "US$", "US Dollar" } // 04/04/1792-
2002 UErrorCode ec = U_ZERO_ERROR;
2003 static const UChar USD[] = {0x55, 0x53, 0x44, 0}; /*USD*/
2004 static const UChar USX[] = {0x55, 0x53, 0x58, 0}; /*USX*/
2005 static const UChar CAD[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
2006 static const UChar ITL[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
2007 UBool isChoiceFormat;
2008 int32_t len;
2009 const UBool possibleDataError = TRUE;
2010 // Warning: HARD-CODED LOCALE DATA in this test. If it fails, CHECK
2011 // THE LOCALE DATA before diving into the code.
2012 assertEquals("USD.getName(SYMBOL_NAME, en)",
2013 UnicodeString("$"),
2014 UnicodeString(ucurr_getName(USD, "en",
2015 UCURR_SYMBOL_NAME,
2016 &isChoiceFormat, &len, &ec)),
2017 possibleDataError);
2018 assertEquals("USD.getName(NARROW_SYMBOL_NAME, en)",
2019 UnicodeString("$"),
2020 UnicodeString(ucurr_getName(USD, "en",
2021 UCURR_NARROW_SYMBOL_NAME,
2022 &isChoiceFormat, &len, &ec)),
2023 possibleDataError);
2024 assertEquals("USD.getName(LONG_NAME, en)",
2025 UnicodeString("US Dollar"),
2026 UnicodeString(ucurr_getName(USD, "en",
2027 UCURR_LONG_NAME,
2028 &isChoiceFormat, &len, &ec)),
2029 possibleDataError);
2030 assertEquals("CAD.getName(SYMBOL_NAME, en)",
2031 UnicodeString("CA$"),
2032 UnicodeString(ucurr_getName(CAD, "en",
2033 UCURR_SYMBOL_NAME,
2034 &isChoiceFormat, &len, &ec)),
2035 possibleDataError);
2036 assertEquals("CAD.getName(NARROW_SYMBOL_NAME, en)",
2037 UnicodeString("$"),
2038 UnicodeString(ucurr_getName(CAD, "en",
2039 UCURR_NARROW_SYMBOL_NAME,
2040 &isChoiceFormat, &len, &ec)),
2041 possibleDataError);
2042 assertEquals("CAD.getName(SYMBOL_NAME, en_CA)",
2043 UnicodeString("$"),
2044 UnicodeString(ucurr_getName(CAD, "en_CA",
2045 UCURR_SYMBOL_NAME,
2046 &isChoiceFormat, &len, &ec)),
2047 possibleDataError);
2048 assertEquals("USD.getName(SYMBOL_NAME, en_CA)",
2049 UnicodeString("US$"),
2050 UnicodeString(ucurr_getName(USD, "en_CA",
2051 UCURR_SYMBOL_NAME,
2052 &isChoiceFormat, &len, &ec)),
2053 possibleDataError);
2054 assertEquals("USD.getName(NARROW_SYMBOL_NAME, en_CA)",
2055 UnicodeString("$"),
2056 UnicodeString(ucurr_getName(USD, "en_CA",
2057 UCURR_NARROW_SYMBOL_NAME,
2058 &isChoiceFormat, &len, &ec)),
2059 possibleDataError);
2060 assertEquals("USD.getName(SYMBOL_NAME) in en_NZ",
2061 UnicodeString("US$"),
2062 UnicodeString(ucurr_getName(USD, "en_NZ",
2063 UCURR_SYMBOL_NAME,
2064 &isChoiceFormat, &len, &ec)),
2065 possibleDataError);
2066 assertEquals("CAD.getName(SYMBOL_NAME)",
2067 UnicodeString("CA$"),
2068 UnicodeString(ucurr_getName(CAD, "en_NZ",
2069 UCURR_SYMBOL_NAME,
2070 &isChoiceFormat, &len, &ec)),
2071 possibleDataError);
2072 assertEquals("USX.getName(SYMBOL_NAME)",
2073 UnicodeString("USX"),
2074 UnicodeString(ucurr_getName(USX, "en_US",
2075 UCURR_SYMBOL_NAME,
2076 &isChoiceFormat, &len, &ec)),
2077 possibleDataError);
2078 assertEquals("USX.getName(NARROW_SYMBOL_NAME)",
2079 UnicodeString("USX"),
2080 UnicodeString(ucurr_getName(USX, "en_US",
2081 UCURR_NARROW_SYMBOL_NAME,
2082 &isChoiceFormat, &len, &ec)),
2083 possibleDataError);
2084 assertEquals("USX.getName(LONG_NAME)",
2085 UnicodeString("USX"),
2086 UnicodeString(ucurr_getName(USX, "en_US",
2087 UCURR_LONG_NAME,
2088 &isChoiceFormat, &len, &ec)),
2089 possibleDataError);
2090 assertSuccess("ucurr_getName", ec);
2091
2092 ec = U_ZERO_ERROR;
2093
2094 // Test that a default or fallback warning is being returned. JB 4239.
2095 ucurr_getName(CAD, "es_ES", UCURR_LONG_NAME, &isChoiceFormat,
2096 &len, &ec);
2097 assertTrue("ucurr_getName (es_ES fallback)",
2098 U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);
2099
2100 ucurr_getName(CAD, "zh_TW", UCURR_LONG_NAME, &isChoiceFormat,
2101 &len, &ec);
2102 assertTrue("ucurr_getName (zh_TW fallback)",
2103 U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);
2104
2105 ucurr_getName(CAD, "en_US", UCURR_LONG_NAME, &isChoiceFormat,
2106 &len, &ec);
2107 assertTrue("ucurr_getName (en_US default)",
2108 U_USING_DEFAULT_WARNING == ec || U_USING_FALLBACK_WARNING == ec, TRUE);
2109
2110 ucurr_getName(CAD, "ti", UCURR_LONG_NAME, &isChoiceFormat,
2111 &len, &ec);
2112 assertTrue("ucurr_getName (ti default)",
2113 U_USING_DEFAULT_WARNING == ec, TRUE);
2114
2115 // Test that a default warning is being returned when falling back to root. JB 4536.
2116 ucurr_getName(ITL, "cy", UCURR_LONG_NAME, &isChoiceFormat,
2117 &len, &ec);
2118 assertTrue("ucurr_getName (cy default to root)",
2119 U_USING_DEFAULT_WARNING == ec, TRUE);
2120
2121 // TODO add more tests later
2122 }
2123
TestCurrencyVariants()2124 void NumberFormatTest::TestCurrencyVariants(){
2125 IcuTestErrorCode status(*this, "TestCurrencyVariants");
2126
2127 struct TestCase {
2128 const char* locale;
2129 const char16_t* isoCode;
2130 const char16_t* expectedShort;
2131 const char16_t* expectedNarrow;
2132 const char16_t* expectedFormal;
2133 const char16_t* expectedVariant;
2134 UErrorCode expectedNarrowError;
2135 } cases[] = {
2136 {"en-US", u"CAD", u"CA$", u"$", u"CA$", u"CA$", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2137 {"en-US", u"CDF", u"CDF", u"CDF", u"CDF", u"CDF", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2138 {"sw-CD", u"CDF", u"FC", u"FC", u"FC", u"FC", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2139 {"en-US", u"GEL", u"GEL", u"₾", u"GEL", u"GEL", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2140 {"ka-GE", u"GEL", u"₾", u"₾", u"₾", u"₾", U_USING_FALLBACK_WARNING}, // narrow: fallback to ka
2141 {"ka", u"GEL", u"₾", u"₾", u"₾", u"₾", U_ZERO_ERROR}, // no fallback on narrow
2142 {"zh-TW", u"TWD", u"$", u"$", u"NT$", u"$", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2143 {"ccp", u"TRY", u"TRY", u"₺", u"TRY", u"TL", U_ZERO_ERROR}, // no fallback on variant
2144 };
2145 for (const auto& cas : cases) {
2146 status.setScope(cas.isoCode);
2147 UBool choiceFormatIgnored;
2148 int32_t lengthIgnored;
2149 const UChar* actualShort = ucurr_getName(
2150 cas.isoCode,
2151 cas.locale,
2152 UCURR_SYMBOL_NAME,
2153 &choiceFormatIgnored,
2154 &lengthIgnored,
2155 status);
2156 const UChar* actualFormal = ucurr_getName(
2157 cas.isoCode,
2158 cas.locale,
2159 UCURR_FORMAL_SYMBOL_NAME,
2160 &choiceFormatIgnored,
2161 &lengthIgnored,
2162 status);
2163 const UChar* actualVarant = ucurr_getName(
2164 cas.isoCode,
2165 cas.locale,
2166 UCURR_VARIANT_SYMBOL_NAME,
2167 &choiceFormatIgnored,
2168 &lengthIgnored,
2169 status);
2170 status.errIfFailureAndReset();
2171 const UChar* actualNarrow = ucurr_getName(
2172 cas.isoCode,
2173 cas.locale,
2174 UCURR_NARROW_SYMBOL_NAME,
2175 &choiceFormatIgnored,
2176 &lengthIgnored,
2177 status);
2178 status.expectErrorAndReset(cas.expectedNarrowError);
2179 assertEquals(UnicodeString("Short symbol: ") + cas.locale + u": " + cas.isoCode,
2180 cas.expectedShort, actualShort);
2181 assertEquals(UnicodeString("Narrow symbol: ") + cas.locale + u": " + cas.isoCode,
2182 cas.expectedNarrow, actualNarrow);
2183 assertEquals(UnicodeString("Formal symbol: ") + cas.locale + u": " + cas.isoCode,
2184 cas.expectedFormal, actualFormal);
2185 assertEquals(UnicodeString("Variant symbol: ") + cas.locale + u": " + cas.isoCode,
2186 cas.expectedVariant, actualVarant);
2187 }
2188 }
2189
TestCurrencyUnit(void)2190 void NumberFormatTest::TestCurrencyUnit(void){
2191 UErrorCode ec = U_ZERO_ERROR;
2192 static const UChar USD[] = u"USD";
2193 static const char USD8[] = "USD";
2194 static const UChar BAD[] = u"???";
2195 static const UChar BAD2[] = u"??A";
2196 static const UChar XXX[] = u"XXX";
2197 static const char XXX8[] = "XXX";
2198 static const UChar XYZ[] = u"XYZ";
2199 static const char XYZ8[] = "XYZ";
2200 static const UChar INV[] = u"{$%";
2201 static const char INV8[] = "{$%";
2202 static const UChar ZZZ[] = u"zz";
2203 static const char ZZZ8[] = "zz";
2204 static const UChar JPY[] = u"JPY";
2205 static const char JPY8[] = "JPY";
2206 static const UChar jpy[] = u"jpy";
2207 static const char jpy8[] = "jpy";
2208
2209 UChar* EUR = (UChar*) malloc(6);
2210 EUR[0] = u'E';
2211 EUR[1] = u'U';
2212 EUR[2] = u'R';
2213 char* EUR8 = (char*) malloc(3);
2214 EUR8[0] = 'E';
2215 EUR8[1] = 'U';
2216 EUR8[2] = 'R';
2217
2218 CurrencyUnit cu(USD, ec);
2219 assertSuccess("CurrencyUnit", ec);
2220 assertEquals("getISOCurrency()", USD, cu.getISOCurrency());
2221 assertEquals("getSubtype()", USD8, cu.getSubtype());
2222
2223 // Test XYZ, a valid but non-standard currency.
2224 // Note: Country code XY is private-use, so XYZ should remain unallocated.
2225 CurrencyUnit extended(XYZ, ec);
2226 assertSuccess("non-standard", ec);
2227 assertEquals("non-standard", XYZ, extended.getISOCurrency());
2228 assertEquals("non-standard", XYZ8, extended.getSubtype());
2229
2230 CurrencyUnit inv(INV, ec);
2231 assertEquals("non-invariant", U_INVARIANT_CONVERSION_ERROR, ec);
2232 assertEquals("non-invariant", XXX, inv.getISOCurrency());
2233 ec = U_ZERO_ERROR;
2234
2235 CurrencyUnit zzz(ZZZ, ec);
2236 assertEquals("too short", U_ILLEGAL_ARGUMENT_ERROR, ec);
2237 assertEquals("too short", XXX, zzz.getISOCurrency());
2238 ec = U_ZERO_ERROR;
2239
2240 CurrencyUnit eur(EUR, ec);
2241 assertEquals("non-nul-terminated", u"EUR", eur.getISOCurrency());
2242 assertEquals("non-nul-terminated", "EUR", eur.getSubtype());
2243
2244 // Test StringPiece constructor
2245 CurrencyUnit cu8(USD8, ec);
2246 assertEquals("StringPiece constructor", USD, cu8.getISOCurrency());
2247
2248 CurrencyUnit inv8(INV8, ec);
2249 assertEquals("non-invariant 8", U_INVARIANT_CONVERSION_ERROR, ec);
2250 assertEquals("non-invariant 8", XXX, inv8.getISOCurrency());
2251 ec = U_ZERO_ERROR;
2252
2253 CurrencyUnit zzz8(ZZZ8, ec);
2254 assertEquals("too short 8", U_ILLEGAL_ARGUMENT_ERROR, ec);
2255 assertEquals("too short 8", XXX, zzz8.getISOCurrency());
2256 ec = U_ZERO_ERROR;
2257
2258 CurrencyUnit zzz8b({ZZZ8, 3}, ec);
2259 assertEquals("too short 8b", U_ILLEGAL_ARGUMENT_ERROR, ec);
2260 assertEquals("too short 8b", XXX, zzz8b.getISOCurrency());
2261 ec = U_ZERO_ERROR;
2262
2263 CurrencyUnit eur8({EUR8, 3}, ec);
2264 assertEquals("non-nul-terminated 8", u"EUR", eur8.getISOCurrency());
2265 assertEquals("non-nul-terminated 8", "EUR", eur8.getSubtype());
2266
2267 CurrencyUnit cu2(cu);
2268 if (!(cu2 == cu)){
2269 errln("CurrencyUnit copy constructed object should be same");
2270 }
2271
2272 CurrencyUnit * cu3 = cu.clone();
2273 if (!(*cu3 == cu)){
2274 errln("CurrencyUnit cloned object should be same");
2275 }
2276 CurrencyUnit bad(BAD, ec);
2277 assertSuccess("CurrencyUnit", ec);
2278 if (cu.getOffset() == bad.getOffset()) {
2279 errln("Indexes of different currencies should differ.");
2280 }
2281 CurrencyUnit bad2(BAD2, ec);
2282 assertSuccess("CurrencyUnit", ec);
2283 if (bad2.getOffset() != bad.getOffset()) {
2284 errln("Indexes of unrecognized currencies should be the same.");
2285 }
2286 if (bad == bad2) {
2287 errln("Different unrecognized currencies should not be equal.");
2288 }
2289 bad = bad2;
2290 if (bad != bad2) {
2291 errln("Currency unit assignment should be the same.");
2292 }
2293 delete cu3;
2294
2295 // Test default constructor
2296 CurrencyUnit def;
2297 assertEquals("Default currency", XXX, def.getISOCurrency());
2298 assertEquals("Default currency as subtype", XXX8, def.getSubtype());
2299
2300 // Test slicing
2301 MeasureUnit sliced1 = cu;
2302 MeasureUnit sliced2 = cu;
2303 MeasureUnit sliced3 = extended;
2304 assertEquals("Subtype after slicing 1", USD8, sliced1.getSubtype());
2305 assertEquals("Subtype after slicing 2", USD8, sliced2.getSubtype());
2306 assertEquals("Subtype after slicing 3", XYZ8, sliced3.getSubtype());
2307 CurrencyUnit restored1(sliced1, ec);
2308 CurrencyUnit restored2(sliced2, ec);
2309 CurrencyUnit restored3(sliced3, ec);
2310 assertSuccess("Restoring from MeasureUnit", ec);
2311 assertEquals("Subtype after restoring 1", USD8, restored1.getSubtype());
2312 assertEquals("Subtype after restoring 2", USD8, restored2.getSubtype());
2313 assertEquals("Subtype after restoring 3", XYZ8, restored3.getSubtype());
2314 assertEquals("ISO Code after restoring 1", USD, restored1.getISOCurrency());
2315 assertEquals("ISO Code after restoring 2", USD, restored2.getISOCurrency());
2316 assertEquals("ISO Code after restoring 3", XYZ, restored3.getISOCurrency());
2317
2318 // Test copy constructor failure
2319 LocalPointer<MeasureUnit> meter(MeasureUnit::createMeter(ec));
2320 assertSuccess("Creating meter", ec);
2321 CurrencyUnit failure(*meter, ec);
2322 assertEquals("Copying from meter should fail", ec, U_ILLEGAL_ARGUMENT_ERROR);
2323 assertEquals("Copying should not give uninitialized ISO code", u"", failure.getISOCurrency());
2324
2325 // Test equality
2326 ec = U_ZERO_ERROR;
2327 assertFalse("FAIL: USD == JPY", CurrencyUnit(USD, ec) == CurrencyUnit(JPY, ec));
2328 assertTrue("FAIL: USD != USD", CurrencyUnit(USD, ec) == CurrencyUnit(USD, ec));
2329 assertTrue("FAIL: JPY != jpy", CurrencyUnit(JPY, ec) == CurrencyUnit(jpy, ec));
2330 assertTrue("FAIL: jpy != JPY", CurrencyUnit(jpy, ec) == CurrencyUnit(JPY, ec));
2331
2332 // Test equality with system charset instances
2333 assertFalse("FAIL: USD8 == JPY8", CurrencyUnit(USD8, ec) == CurrencyUnit(JPY8, ec));
2334 assertTrue("FAIL: USD8 != USD8", CurrencyUnit(USD8, ec) == CurrencyUnit(USD8, ec));
2335 assertTrue("FAIL: JPY8 != jpy8", CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy8, ec));
2336 assertTrue("FAIL: jpy8 != JPY8", CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY8, ec));
2337
2338 // Test equality between UTF-16 and system charset instances
2339 assertTrue("FAIL: USD != USD8", CurrencyUnit(USD, ec) == CurrencyUnit(USD8, ec));
2340 assertTrue("FAIL: USD8 != USD", CurrencyUnit(USD8, ec) == CurrencyUnit(USD, ec));
2341 assertTrue("FAIL: JPY != jpy8", CurrencyUnit(JPY, ec) == CurrencyUnit(jpy8, ec));
2342 assertTrue("FAIL: JPY8 != jpy", CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy, ec));
2343 assertTrue("FAIL: jpy != JPY8", CurrencyUnit(jpy, ec) == CurrencyUnit(JPY8, ec));
2344 assertTrue("FAIL: jpy8 != JPY", CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY, ec));
2345
2346 free(EUR);
2347 free(EUR8);
2348 }
2349
TestCurrencyAmount(void)2350 void NumberFormatTest::TestCurrencyAmount(void){
2351 UErrorCode ec = U_ZERO_ERROR;
2352 static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
2353 CurrencyAmount ca(9, USD, ec);
2354 assertSuccess("CurrencyAmount", ec);
2355
2356 CurrencyAmount ca2(ca);
2357 if (!(ca2 == ca)){
2358 errln("CurrencyAmount copy constructed object should be same");
2359 }
2360
2361 ca2=ca;
2362 if (!(ca2 == ca)){
2363 errln("CurrencyAmount assigned object should be same");
2364 }
2365
2366 CurrencyAmount *ca3 = ca.clone();
2367 if (!(*ca3 == ca)){
2368 errln("CurrencyAmount cloned object should be same");
2369 }
2370 delete ca3;
2371 }
2372
TestSymbolsWithBadLocale(void)2373 void NumberFormatTest::TestSymbolsWithBadLocale(void) {
2374 Locale locDefault;
2375 static const char *badLocales[] = {
2376 // length < ULOC_FULLNAME_CAPACITY
2377 "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME",
2378
2379 // length > ULOC_FULLNAME_CAPACITY
2380 "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME"
2381 }; // expect U_USING_DEFAULT_WARNING for both
2382
2383 unsigned int i;
2384 for (i = 0; i < UPRV_LENGTHOF(badLocales); i++) {
2385 const char *localeName = badLocales[i];
2386 Locale locBad(localeName);
2387 assertTrue(WHERE, !locBad.isBogus());
2388 UErrorCode status = U_ZERO_ERROR;
2389 UnicodeString intlCurrencySymbol((UChar)0xa4);
2390
2391 intlCurrencySymbol.append((UChar)0xa4);
2392
2393 logln("Current locale is %s", Locale::getDefault().getName());
2394 Locale::setDefault(locBad, status);
2395 logln("Current locale is %s", Locale::getDefault().getName());
2396 DecimalFormatSymbols mySymbols(status);
2397 if (status != U_USING_DEFAULT_WARNING) {
2398 errln("DecimalFormatSymbols should return U_USING_DEFAULT_WARNING.");
2399 }
2400 if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
2401 errln("DecimalFormatSymbols does not have the right locale.", locBad.getName());
2402 }
2403 int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
2404 for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
2405 UnicodeString symbolString = mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum);
2406 logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ") + prettify(symbolString));
2407 if (symbolString.length() == 0
2408 && symbolEnum != (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
2409 && symbolEnum != (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol)
2410 {
2411 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
2412 }
2413 }
2414
2415 status = U_ZERO_ERROR;
2416 Locale::setDefault(locDefault, status);
2417 logln("Current locale is %s", Locale::getDefault().getName());
2418 }
2419 }
2420
2421 /**
2422 * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
2423 * behave the same, except for memory ownership semantics. (No
2424 * version of this test on Java, since Java has only one method.)
2425 */
TestAdoptDecimalFormatSymbols(void)2426 void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
2427 UErrorCode ec = U_ZERO_ERROR;
2428 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2429 if (U_FAILURE(ec)) {
2430 errcheckln(ec, "Fail: DecimalFormatSymbols constructor - %s", u_errorName(ec));
2431 delete sym;
2432 return;
2433 }
2434 UnicodeString pat(" #,##0.00");
2435 pat.insert(0, (UChar)0x00A4);
2436 DecimalFormat fmt(pat, sym, ec);
2437 if (U_FAILURE(ec)) {
2438 errln("Fail: DecimalFormat constructor");
2439 return;
2440 }
2441
2442 UnicodeString str;
2443 fmt.format(2350.75, str);
2444 if (str == "$ 2,350.75") {
2445 logln(str);
2446 } else {
2447 dataerrln("Fail: " + str + ", expected $ 2,350.75");
2448 }
2449
2450 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2451 if (U_FAILURE(ec)) {
2452 errln("Fail: DecimalFormatSymbols constructor");
2453 delete sym;
2454 return;
2455 }
2456 sym->setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2457 fmt.adoptDecimalFormatSymbols(sym);
2458
2459 str.truncate(0);
2460 fmt.format(2350.75, str);
2461 if (str == "Q 2,350.75") {
2462 logln(str);
2463 } else {
2464 dataerrln("Fail: adoptDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2465 }
2466
2467 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2468 if (U_FAILURE(ec)) {
2469 errln("Fail: DecimalFormatSymbols constructor");
2470 delete sym;
2471 return;
2472 }
2473 DecimalFormat fmt2(pat, sym, ec);
2474 if (U_FAILURE(ec)) {
2475 errln("Fail: DecimalFormat constructor");
2476 return;
2477 }
2478
2479 DecimalFormatSymbols sym2(Locale::getUS(), ec);
2480 if (U_FAILURE(ec)) {
2481 errln("Fail: DecimalFormatSymbols constructor");
2482 return;
2483 }
2484 sym2.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2485 fmt2.setDecimalFormatSymbols(sym2);
2486
2487 str.truncate(0);
2488 fmt2.format(2350.75, str);
2489 if (str == "Q 2,350.75") {
2490 logln(str);
2491 } else {
2492 dataerrln("Fail: setDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2493 }
2494 }
2495
TestPerMill()2496 void NumberFormatTest::TestPerMill() {
2497 UErrorCode ec = U_ZERO_ERROR;
2498 UnicodeString str;
2499 DecimalFormat fmt(ctou("###.###\\u2030"), ec);
2500 if (!assertSuccess("DecimalFormat ct", ec)) return;
2501 assertEquals("0.4857 x ###.###\\u2030",
2502 ctou("485.7\\u2030"), fmt.format(0.4857, str), true);
2503
2504 DecimalFormatSymbols sym(Locale::getUS(), ec);
2505 if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2506 return;
2507 }
2508 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
2509 DecimalFormat fmt2("", sym, ec);
2510 if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2511 return;
2512 }
2513 fmt2.applyLocalizedPattern("###.###m", ec);
2514 if (!assertSuccess("setup", ec)) return;
2515 str.truncate(0);
2516 assertEquals("0.4857 x ###.###m",
2517 "485.7m", fmt2.format(0.4857, str));
2518 }
2519
2520 /**
2521 * Generic test for patterns that should be legal/illegal.
2522 */
TestIllegalPatterns()2523 void NumberFormatTest::TestIllegalPatterns() {
2524 // Test cases:
2525 // Prefix with "-:" for illegal patterns
2526 // Prefix with "+:" for legal patterns
2527 const char* DATA[] = {
2528 // Unquoted special characters in the suffix are illegal
2529 "-:000.000|###",
2530 "+:000.000'|###'",
2531 0
2532 };
2533 for (int32_t i=0; DATA[i]; ++i) {
2534 const char* pat=DATA[i];
2535 UBool valid = (*pat) == '+';
2536 pat += 2;
2537 UErrorCode ec = U_ZERO_ERROR;
2538 DecimalFormat fmt(pat, ec); // locale doesn't matter here
2539 if (U_SUCCESS(ec) == valid) {
2540 logln("Ok: pattern \"%s\": %s",
2541 pat, u_errorName(ec));
2542 } else {
2543 errcheckln(ec, "FAIL: pattern \"%s\" should have %s; got %s",
2544 pat, (valid?"succeeded":"failed"),
2545 u_errorName(ec));
2546 }
2547 }
2548 }
2549
2550 //----------------------------------------------------------------------
2551
2552 static const char* KEYWORDS[] = {
2553 /*0*/ "ref=", // <reference pattern to parse numbers>
2554 /*1*/ "loc=", // <locale for formats>
2555 /*2*/ "f:", // <pattern or '-'> <number> <exp. string>
2556 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number>
2557 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string>
2558 /*5*/ "p:", // <pattern or '-'> <string> <exp. number>
2559 /*6*/ "perr:", // <pattern or '-'> <invalid string>
2560 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
2561 /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2562 0
2563 };
2564
2565 /**
2566 * Return an integer representing the next token from this
2567 * iterator. The integer will be an index into the given list, or
2568 * -1 if there are no more tokens, or -2 if the token is not on
2569 * the list.
2570 */
keywordIndex(const UnicodeString & tok)2571 static int32_t keywordIndex(const UnicodeString& tok) {
2572 for (int32_t i=0; KEYWORDS[i]!=0; ++i) {
2573 if (tok==KEYWORDS[i]) {
2574 return i;
2575 }
2576 }
2577 return -1;
2578 }
2579
2580 /**
2581 * Parse a CurrencyAmount using the given NumberFormat, with
2582 * the 'delim' character separating the number and the currency.
2583 */
parseCurrencyAmount(const UnicodeString & str,const NumberFormat & fmt,UChar delim,Formattable & result,UErrorCode & ec)2584 static void parseCurrencyAmount(const UnicodeString& str,
2585 const NumberFormat& fmt,
2586 UChar delim,
2587 Formattable& result,
2588 UErrorCode& ec) {
2589 UnicodeString num, cur;
2590 int32_t i = str.indexOf(delim);
2591 str.extractBetween(0, i, num);
2592 str.extractBetween(i+1, INT32_MAX, cur);
2593 Formattable n;
2594 fmt.parse(num, n, ec);
2595 result.adoptObject(new CurrencyAmount(n, cur.getTerminatedBuffer(), ec));
2596 }
2597
TestCases()2598 void NumberFormatTest::TestCases() {
2599 UErrorCode ec = U_ZERO_ERROR;
2600 TextFile reader("NumberFormatTestCases.txt", "UTF8", ec);
2601 if (U_FAILURE(ec)) {
2602 dataerrln("Couldn't open NumberFormatTestCases.txt");
2603 return;
2604 }
2605 TokenIterator tokens(&reader);
2606
2607 Locale loc("en", "US", "");
2608 DecimalFormat *ref = 0, *fmt = 0;
2609 MeasureFormat *mfmt = 0;
2610 UnicodeString pat, tok, mloc, str, out, where, currAmt;
2611 Formattable n;
2612
2613 for (;;) {
2614 ec = U_ZERO_ERROR;
2615 if (!tokens.next(tok, ec)) {
2616 break;
2617 }
2618 where = UnicodeString("(") + tokens.getLineNumber() + ") ";
2619 int32_t cmd = keywordIndex(tok);
2620 switch (cmd) {
2621 case 0:
2622 // ref= <reference pattern>
2623 if (!tokens.next(tok, ec)) goto error;
2624 delete ref;
2625 ref = new DecimalFormat(tok,
2626 new DecimalFormatSymbols(Locale::getUS(), ec), ec);
2627 if (U_FAILURE(ec)) {
2628 dataerrln("Error constructing DecimalFormat");
2629 goto error;
2630 }
2631 break;
2632 case 1:
2633 // loc= <locale>
2634 if (!tokens.next(tok, ec)) goto error;
2635 loc = Locale::createFromName(CharString().appendInvariantChars(tok, ec).data());
2636 break;
2637 case 2: // f:
2638 case 3: // fp:
2639 case 4: // rt:
2640 case 5: // p:
2641 if (!tokens.next(tok, ec)) goto error;
2642 if (tok != "-") {
2643 pat = tok;
2644 delete fmt;
2645 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc, ec), ec);
2646 if (U_FAILURE(ec)) {
2647 errln("FAIL: " + where + "Pattern \"" + pat + "\": " + u_errorName(ec));
2648 ec = U_ZERO_ERROR;
2649 if (!tokens.next(tok, ec)) goto error;
2650 if (!tokens.next(tok, ec)) goto error;
2651 if (cmd == 3) {
2652 if (!tokens.next(tok, ec)) goto error;
2653 }
2654 continue;
2655 }
2656 }
2657 if (cmd == 2 || cmd == 3 || cmd == 4) {
2658 // f: <pattern or '-'> <number> <exp. string>
2659 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
2660 // rt: <pattern or '-'> <number> <string>
2661 UnicodeString num;
2662 if (!tokens.next(num, ec)) goto error;
2663 if (!tokens.next(str, ec)) goto error;
2664 ref->parse(num, n, ec);
2665 assertSuccess("parse", ec);
2666 assertEquals(where + "\"" + pat + "\".format(" + num + ")",
2667 str, fmt->format(n, out.remove(), ec));
2668 assertSuccess("format", ec);
2669 if (cmd == 3) { // fp:
2670 if (!tokens.next(num, ec)) goto error;
2671 ref->parse(num, n, ec);
2672 assertSuccess("parse", ec);
2673 }
2674 if (cmd != 2) { // != f:
2675 Formattable m;
2676 fmt->parse(str, m, ec);
2677 assertSuccess("parse", ec);
2678 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2679 n, m);
2680 }
2681 }
2682 // p: <pattern or '-'> <string to parse> <exp. number>
2683 else {
2684 UnicodeString expstr;
2685 if (!tokens.next(str, ec)) goto error;
2686 if (!tokens.next(expstr, ec)) goto error;
2687 Formattable exp, n;
2688 ref->parse(expstr, exp, ec);
2689 assertSuccess("parse", ec);
2690 fmt->parse(str, n, ec);
2691 assertSuccess("parse", ec);
2692 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2693 exp, n);
2694 }
2695 break;
2696 case 8: // fpc:
2697 if (!tokens.next(tok, ec)) goto error;
2698 if (tok != "-") {
2699 mloc = tok;
2700 delete mfmt;
2701 mfmt = MeasureFormat::createCurrencyFormat(
2702 Locale::createFromName(
2703 CharString().appendInvariantChars(mloc, ec).data()), ec);
2704 if (U_FAILURE(ec)) {
2705 errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
2706 ec = U_ZERO_ERROR;
2707 if (!tokens.next(tok, ec)) goto error;
2708 if (!tokens.next(tok, ec)) goto error;
2709 if (!tokens.next(tok, ec)) goto error;
2710 continue;
2711 }
2712 } else if (mfmt == NULL) {
2713 errln("FAIL: " + where + "Loc \"" + mloc + "\": skip case using previous locale, no valid MeasureFormat");
2714 if (!tokens.next(tok, ec)) goto error;
2715 if (!tokens.next(tok, ec)) goto error;
2716 if (!tokens.next(tok, ec)) goto error;
2717 continue;
2718 }
2719 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2720 if (!tokens.next(currAmt, ec)) goto error;
2721 if (!tokens.next(str, ec)) goto error;
2722 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2723 if (assertSuccess("parseCurrencyAmount", ec)) {
2724 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
2725 str, mfmt->format(n, out.remove(), ec));
2726 assertSuccess("format", ec);
2727 }
2728 if (!tokens.next(currAmt, ec)) goto error;
2729 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2730 if (assertSuccess("parseCurrencyAmount", ec)) {
2731 Formattable m;
2732
2733 mfmt->parseObject(str, m, ec);
2734 if (assertSuccess("parseCurrency", ec)) {
2735 assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
2736 n, m);
2737 } else {
2738 errln("FAIL: source " + str);
2739 }
2740 }
2741 break;
2742 case 6:
2743 // perr: <pattern or '-'> <invalid string>
2744 errln("FAIL: Under construction");
2745 goto done;
2746 case 7: {
2747 // pat: <pattern> <exp. toPattern, or '-' or 'err'>
2748 UnicodeString testpat;
2749 UnicodeString exppat;
2750 if (!tokens.next(testpat, ec)) goto error;
2751 if (!tokens.next(exppat, ec)) goto error;
2752 UBool err = exppat == "err";
2753 UBool existingPat = FALSE;
2754 if (testpat == "-") {
2755 if (err) {
2756 errln("FAIL: " + where + "Invalid command \"pat: - err\"");
2757 continue;
2758 }
2759 existingPat = TRUE;
2760 testpat = pat;
2761 }
2762 if (exppat == "-") exppat = testpat;
2763 DecimalFormat* f = 0;
2764 UErrorCode ec2 = U_ZERO_ERROR;
2765 if (existingPat) {
2766 f = fmt;
2767 } else {
2768 f = new DecimalFormat(testpat, ec2);
2769 }
2770 if (U_SUCCESS(ec2)) {
2771 if (err) {
2772 errln("FAIL: " + where + "Invalid pattern \"" + testpat +
2773 "\" was accepted");
2774 } else {
2775 UnicodeString pat2;
2776 assertEquals(where + "\"" + testpat + "\".toPattern()",
2777 exppat, f->toPattern(pat2));
2778 }
2779 } else {
2780 if (err) {
2781 logln("Ok: " + where + "Invalid pattern \"" + testpat +
2782 "\" failed: " + u_errorName(ec2));
2783 } else {
2784 errln("FAIL: " + where + "Valid pattern \"" + testpat +
2785 "\" failed: " + u_errorName(ec2));
2786 }
2787 }
2788 if (!existingPat) delete f;
2789 } break;
2790 case -1:
2791 errln("FAIL: " + where + "Unknown command \"" + tok + "\"");
2792 goto done;
2793 }
2794 }
2795 goto done;
2796
2797 error:
2798 if (U_SUCCESS(ec)) {
2799 errln("FAIL: Unexpected EOF");
2800 } else {
2801 errcheckln(ec, "FAIL: " + where + "Unexpected " + u_errorName(ec));
2802 }
2803
2804 done:
2805 delete mfmt;
2806 delete fmt;
2807 delete ref;
2808 }
2809
2810
2811 //----------------------------------------------------------------------
2812 // Support methods
2813 //----------------------------------------------------------------------
2814
equalValue(const Formattable & a,const Formattable & b)2815 UBool NumberFormatTest::equalValue(const Formattable& a, const Formattable& b) {
2816 if (a.getType() == b.getType()) {
2817 return a == b;
2818 }
2819
2820 if (a.getType() == Formattable::kLong) {
2821 if (b.getType() == Formattable::kInt64) {
2822 return a.getLong() == b.getLong();
2823 } else if (b.getType() == Formattable::kDouble) {
2824 return (double) a.getLong() == b.getDouble(); // TODO check use of double instead of long
2825 }
2826 } else if (a.getType() == Formattable::kDouble) {
2827 if (b.getType() == Formattable::kLong) {
2828 return a.getDouble() == (double) b.getLong();
2829 } else if (b.getType() == Formattable::kInt64) {
2830 return a.getDouble() == (double)b.getInt64();
2831 }
2832 } else if (a.getType() == Formattable::kInt64) {
2833 if (b.getType() == Formattable::kLong) {
2834 return a.getInt64() == (int64_t)b.getLong();
2835 } else if (b.getType() == Formattable::kDouble) {
2836 return a.getInt64() == (int64_t)b.getDouble();
2837 }
2838 }
2839 return FALSE;
2840 }
2841
expect3(NumberFormat & fmt,const Formattable & n,const UnicodeString & str)2842 void NumberFormatTest::expect3(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2843 // Don't round-trip format test, since we explicitly do it
2844 expect_rbnf(fmt, n, str, FALSE);
2845 expect_rbnf(fmt, str, n);
2846 }
2847
expect2(NumberFormat & fmt,const Formattable & n,const UnicodeString & str)2848 void NumberFormatTest::expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2849 // Don't round-trip format test, since we explicitly do it
2850 expect(fmt, n, str, FALSE);
2851 expect(fmt, str, n);
2852 }
2853
expect2(NumberFormat * fmt,const Formattable & n,const UnicodeString & exp,UErrorCode status)2854 void NumberFormatTest::expect2(NumberFormat* fmt, const Formattable& n,
2855 const UnicodeString& exp,
2856 UErrorCode status) {
2857 if (fmt == NULL || U_FAILURE(status)) {
2858 dataerrln("FAIL: NumberFormat constructor");
2859 } else {
2860 expect2(*fmt, n, exp);
2861 }
2862 delete fmt;
2863 }
2864
expect(NumberFormat & fmt,const UnicodeString & str,const Formattable & n)2865 void NumberFormatTest::expect(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2866 UErrorCode status = U_ZERO_ERROR;
2867 Formattable num;
2868 fmt.parse(str, num, status);
2869 if (U_FAILURE(status)) {
2870 dataerrln(UnicodeString("FAIL: Parse failed for \"") + str + "\" - " + u_errorName(status));
2871 return;
2872 }
2873 UnicodeString pat;
2874 ((DecimalFormat*) &fmt)->toPattern(pat);
2875 if (equalValue(num, n)) {
2876 logln(UnicodeString("Ok \"") + str + "\" x " +
2877 pat + " = " +
2878 toString(num));
2879 } else {
2880 dataerrln(UnicodeString("FAIL \"") + str + "\" x " +
2881 pat + " = " +
2882 toString(num) + ", expected " + toString(n));
2883 }
2884 }
2885
expect_rbnf(NumberFormat & fmt,const UnicodeString & str,const Formattable & n)2886 void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2887 UErrorCode status = U_ZERO_ERROR;
2888 Formattable num;
2889 fmt.parse(str, num, status);
2890 if (U_FAILURE(status)) {
2891 errln(UnicodeString("FAIL: Parse failed for \"") + str + "\"");
2892 return;
2893 }
2894 if (equalValue(num, n)) {
2895 logln(UnicodeString("Ok \"") + str + " = " +
2896 toString(num));
2897 } else {
2898 errln(UnicodeString("FAIL \"") + str + " = " +
2899 toString(num) + ", expected " + toString(n));
2900 }
2901 }
2902
expect_rbnf(NumberFormat & fmt,const Formattable & n,const UnicodeString & exp,UBool rt)2903 void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const Formattable& n,
2904 const UnicodeString& exp, UBool rt) {
2905 UnicodeString saw;
2906 FieldPosition pos;
2907 UErrorCode status = U_ZERO_ERROR;
2908 fmt.format(n, saw, pos, status);
2909 CHECK(status, "NumberFormat::format");
2910 if (saw == exp) {
2911 logln(UnicodeString("Ok ") + toString(n) +
2912 " = \"" +
2913 escape(saw) + "\"");
2914 // We should be able to round-trip the formatted string =>
2915 // number => string (but not the other way around: number
2916 // => string => number2, might have number2 != number):
2917 if (rt) {
2918 Formattable n2;
2919 fmt.parse(exp, n2, status);
2920 if (U_FAILURE(status)) {
2921 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\"");
2922 return;
2923 }
2924 UnicodeString saw2;
2925 fmt.format(n2, saw2, pos, status);
2926 CHECK(status, "NumberFormat::format");
2927 if (saw2 != exp) {
2928 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2929 " => \"" + saw2 + "\"");
2930 }
2931 }
2932 } else {
2933 errln(UnicodeString("FAIL ") + toString(n) +
2934 " = \"" +
2935 escape(saw) + "\", expected \"" + exp + "\"");
2936 }
2937 }
2938
expect(NumberFormat & fmt,const Formattable & n,const UnicodeString & exp,UBool rt)2939 void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
2940 const UnicodeString& exp, UBool rt) {
2941 UnicodeString saw;
2942 FieldPosition pos;
2943 UErrorCode status = U_ZERO_ERROR;
2944 fmt.format(n, saw, pos, status);
2945 CHECK(status, "NumberFormat::format");
2946 UnicodeString pat;
2947 ((DecimalFormat*) &fmt)->toPattern(pat);
2948 if (saw == exp) {
2949 logln(UnicodeString("Ok ") + toString(n) + " x " +
2950 escape(pat) + " = \"" +
2951 escape(saw) + "\"");
2952 // We should be able to round-trip the formatted string =>
2953 // number => string (but not the other way around: number
2954 // => string => number2, might have number2 != number):
2955 if (rt) {
2956 Formattable n2;
2957 fmt.parse(exp, n2, status);
2958 if (U_FAILURE(status)) {
2959 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\" - " + u_errorName(status));
2960 return;
2961 }
2962 UnicodeString saw2;
2963 fmt.format(n2, saw2, pos, status);
2964 CHECK(status, "NumberFormat::format");
2965 if (saw2 != exp) {
2966 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2967 " => \"" + saw2 + "\"");
2968 }
2969 }
2970 } else {
2971 dataerrln(UnicodeString("FAIL ") + toString(n) + " x " +
2972 escape(pat) + " = \"" +
2973 escape(saw) + "\", expected \"" + exp + "\"");
2974 }
2975 }
2976
expect(NumberFormat * fmt,const Formattable & n,const UnicodeString & exp,UBool rt,UErrorCode status)2977 void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
2978 const UnicodeString& exp, UBool rt,
2979 UErrorCode status) {
2980 if (fmt == NULL || U_FAILURE(status)) {
2981 dataerrln("FAIL: NumberFormat constructor");
2982 } else {
2983 expect(*fmt, n, exp, rt);
2984 }
2985 delete fmt;
2986 }
2987
expectCurrency(NumberFormat & nf,const Locale & locale,double value,const UnicodeString & string)2988 void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
2989 double value, const UnicodeString& string) {
2990 UErrorCode ec = U_ZERO_ERROR;
2991 DecimalFormat& fmt = * (DecimalFormat*) &nf;
2992 const UChar DEFAULT_CURR[] = {45/*-*/,0};
2993 UChar curr[4];
2994 u_strcpy(curr, DEFAULT_CURR);
2995 if (*locale.getLanguage() != 0) {
2996 ucurr_forLocale(locale.getName(), curr, 4, &ec);
2997 assertSuccess("ucurr_forLocale", ec);
2998 fmt.setCurrency(curr, ec);
2999 assertSuccess("DecimalFormat::setCurrency", ec);
3000 fmt.setCurrency(curr); //Deprecated variant, for coverage only
3001 }
3002 UnicodeString s;
3003 fmt.format(value, s);
3004 s.findAndReplace((UChar32)0x00A0, (UChar32)0x0020);
3005
3006 // Default display of the number yields "1234.5599999999999"
3007 // instead of "1234.56". Use a formatter to fix this.
3008 NumberFormat* f =
3009 NumberFormat::createInstance(Locale::getUS(), ec);
3010 UnicodeString v;
3011 if (U_FAILURE(ec)) {
3012 // Oops; bad formatter. Use default op+= display.
3013 v = (UnicodeString)"" + value;
3014 } else {
3015 f->setMaximumFractionDigits(4);
3016 f->setGroupingUsed(FALSE);
3017 f->format(value, v);
3018 }
3019 delete f;
3020
3021 if (s == string) {
3022 logln((UnicodeString)"Ok: " + v + " x " + curr + " => " + prettify(s));
3023 } else {
3024 errln((UnicodeString)"FAIL: " + v + " x " + curr + " => " + prettify(s) +
3025 ", expected " + prettify(string));
3026 }
3027 }
3028
expectPat(DecimalFormat & fmt,const UnicodeString & exp)3029 void NumberFormatTest::expectPat(DecimalFormat& fmt, const UnicodeString& exp) {
3030 UnicodeString pat;
3031 fmt.toPattern(pat);
3032 if (pat == exp) {
3033 logln(UnicodeString("Ok \"") + pat + "\"");
3034 } else {
3035 errln(UnicodeString("FAIL \"") + pat + "\", expected \"" + exp + "\"");
3036 }
3037 }
3038
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos)3039 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3040 int32_t pos) {
3041 expectPad(fmt, pat, pos, 0, (UnicodeString)"");
3042 }
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos,int32_t width,UChar pad)3043 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3044 int32_t pos, int32_t width, UChar pad) {
3045 expectPad(fmt, pat, pos, width, UnicodeString(pad));
3046 }
expectPad(DecimalFormat & fmt,const UnicodeString & pat,int32_t pos,int32_t width,const UnicodeString & pad)3047 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3048 int32_t pos, int32_t width, const UnicodeString& pad) {
3049 int32_t apos = 0, awidth = 0;
3050 UnicodeString apadStr;
3051 UErrorCode status = U_ZERO_ERROR;
3052 fmt.applyPattern(pat, status);
3053 if (U_SUCCESS(status)) {
3054 apos = fmt.getPadPosition();
3055 awidth = fmt.getFormatWidth();
3056 apadStr=fmt.getPadCharacterString();
3057 } else {
3058 apos = -1;
3059 awidth = width;
3060 apadStr = pad;
3061 }
3062 if (apos == pos && awidth == width && apadStr == pad) {
3063 UnicodeString infoStr;
3064 if (pos == ILLEGAL) {
3065 infoStr = UnicodeString(" width=", "") + awidth + UnicodeString(" pad=", "") + apadStr;
3066 }
3067 logln(UnicodeString("Ok \"") + pat + "\" pos=" + apos + infoStr);
3068 } else {
3069 errln(UnicodeString("FAIL \"") + pat + "\" pos=" + apos +
3070 " width=" + awidth + " pad=" + apadStr +
3071 ", expected " + pos + " " + width + " " + pad);
3072 }
3073 }
3074
3075 // This test is flaky b/c the symbols for CNY and JPY are equivalent in this locale - FIXME
TestCompatibleCurrencies()3076 void NumberFormatTest::TestCompatibleCurrencies() {
3077 /*
3078 static const UChar JPY[] = {0x4A, 0x50, 0x59, 0};
3079 static const UChar CNY[] = {0x43, 0x4E, 0x59, 0};
3080 UErrorCode status = U_ZERO_ERROR;
3081 LocalPointer<NumberFormat> fmt(
3082 NumberFormat::createCurrencyInstance(Locale::getUS(), status));
3083 if (U_FAILURE(status)) {
3084 errln("Could not create number format instance.");
3085 return;
3086 }
3087 logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3088 expectParseCurrency(*fmt, JPY, 1235, "\\u00A51,235");
3089 logln("%s:%d - testing parse of fullwidth yen sign\n", __FILE__, __LINE__);
3090 expectParseCurrency(*fmt, JPY, 1235, "\\uFFE51,235");
3091 logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3092 expectParseCurrency(*fmt, CNY, 1235, "CN\\u00A51,235");
3093
3094 LocalPointer<NumberFormat> fmtTW(
3095 NumberFormat::createCurrencyInstance(Locale::getTaiwan(), status));
3096
3097 logln("%s:%d - testing parse of halfwidth yen sign in TW\n", __FILE__, __LINE__);
3098 expectParseCurrency(*fmtTW, CNY, 1235, "\\u00A51,235");
3099 logln("%s:%d - testing parse of fullwidth yen sign in TW\n", __FILE__, __LINE__);
3100 expectParseCurrency(*fmtTW, CNY, 1235, "\\uFFE51,235");
3101
3102 LocalPointer<NumberFormat> fmtJP(
3103 NumberFormat::createCurrencyInstance(Locale::getJapan(), status));
3104
3105 logln("%s:%d - testing parse of halfwidth yen sign in JP\n", __FILE__, __LINE__);
3106 expectParseCurrency(*fmtJP, JPY, 1235, "\\u00A51,235");
3107 logln("%s:%d - testing parse of fullwidth yen sign in JP\n", __FILE__, __LINE__);
3108 expectParseCurrency(*fmtJP, JPY, 1235, "\\uFFE51,235");
3109
3110 // more..
3111 */
3112 }
3113
expectParseCurrency(const NumberFormat & fmt,const UChar * currency,double amount,const char * text)3114 void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text) {
3115 ParsePosition ppos;
3116 UnicodeString utext = ctou(text);
3117 LocalPointer<CurrencyAmount> currencyAmount(fmt.parseCurrency(utext, ppos));
3118 if (!ppos.getIndex()) {
3119 errln(UnicodeString("Parse of ") + utext + " should have succeeded.");
3120 return;
3121 }
3122 UErrorCode status = U_ZERO_ERROR;
3123
3124 char theInfo[100];
3125 sprintf(theInfo, "For locale %s, string \"%s\", currency ",
3126 fmt.getLocale(ULOC_ACTUAL_LOCALE, status).getBaseName(),
3127 text);
3128 u_austrcpy(theInfo+uprv_strlen(theInfo), currency);
3129
3130 char theOperation[100];
3131
3132 uprv_strcpy(theOperation, theInfo);
3133 uprv_strcat(theOperation, ", check amount:");
3134 assertTrue(theOperation, amount == currencyAmount->getNumber().getDouble(status));
3135
3136 uprv_strcpy(theOperation, theInfo);
3137 uprv_strcat(theOperation, ", check currency:");
3138 assertEquals(theOperation, currency, currencyAmount->getISOCurrency());
3139 }
3140
3141
TestJB3832()3142 void NumberFormatTest::TestJB3832(){
3143 const char* localeID = "pt_PT@currency=PTE";
3144 Locale loc(localeID);
3145 UErrorCode status = U_ZERO_ERROR;
3146 UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0\\u200B")); // per cldrbug 7670
3147 UnicodeString s;
3148 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
3149 if(U_FAILURE(status)){
3150 dataerrln("Could not create currency formatter for locale %s - %s", localeID, u_errorName(status));
3151 return;
3152 }
3153 currencyFmt->format(1150.50, s);
3154 if(s!=expected){
3155 errln(UnicodeString("FAIL: Expected: ")+expected
3156 + UnicodeString(" Got: ") + s
3157 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
3158 }
3159 if (U_FAILURE(status)){
3160 errln("FAIL: Status %s", u_errorName(status));
3161 }
3162 delete currencyFmt;
3163 }
3164
TestHost()3165 void NumberFormatTest::TestHost()
3166 {
3167 #if U_PLATFORM_USES_ONLY_WIN32_API
3168 Win32NumberTest::testLocales(this);
3169 #endif
3170 Locale loc("en_US@compat=host");
3171 for (UNumberFormatStyle k = UNUM_DECIMAL;
3172 k < UNUM_FORMAT_STYLE_COUNT; k = (UNumberFormatStyle)(k+1)) {
3173 UErrorCode status = U_ZERO_ERROR;
3174 LocalPointer<NumberFormat> full(NumberFormat::createInstance(loc, k, status));
3175 if (!NumberFormat::isStyleSupported(k)) {
3176 if (status != U_UNSUPPORTED_ERROR) {
3177 errln("FAIL: expected style %d to be unsupported - %s",
3178 k, u_errorName(status));
3179 }
3180 continue;
3181 }
3182 if (full.isNull() || U_FAILURE(status)) {
3183 dataerrln("FAIL: Can't create number instance of style %d for host - %s",
3184 k, u_errorName(status));
3185 return;
3186 }
3187 UnicodeString result1;
3188 Formattable number(10.00);
3189 full->format(number, result1, status);
3190 if (U_FAILURE(status)) {
3191 errln("FAIL: Can't format for host");
3192 return;
3193 }
3194 Formattable formattable;
3195 full->parse(result1, formattable, status);
3196 if (U_FAILURE(status)) {
3197 errln("FAIL: Can't parse for host");
3198 return;
3199 }
3200 }
3201 }
3202
TestHostClone()3203 void NumberFormatTest::TestHostClone()
3204 {
3205 /*
3206 Verify that a cloned formatter gives the same results
3207 and is useable after the original has been deleted.
3208 */
3209 // This is mainly important on Windows.
3210 UErrorCode status = U_ZERO_ERROR;
3211 Locale loc("en_US@compat=host");
3212 UDate now = Calendar::getNow();
3213 NumberFormat *full = NumberFormat::createInstance(loc, status);
3214 if (full == NULL || U_FAILURE(status)) {
3215 dataerrln("FAIL: Can't create NumberFormat date instance - %s", u_errorName(status));
3216 return;
3217 }
3218 UnicodeString result1;
3219 full->format(now, result1, status);
3220 Format *fullClone = full->clone();
3221 delete full;
3222 full = NULL;
3223
3224 UnicodeString result2;
3225 fullClone->format(now, result2, status);
3226 if (U_FAILURE(status)) {
3227 errln("FAIL: format failure.");
3228 }
3229 if (result1 != result2) {
3230 errln("FAIL: Clone returned different result from non-clone.");
3231 }
3232 delete fullClone;
3233 }
3234
TestCurrencyFormat()3235 void NumberFormatTest::TestCurrencyFormat()
3236 {
3237 // This test is here to increase code coverage.
3238 UErrorCode status = U_ZERO_ERROR;
3239 MeasureFormat *cloneObj;
3240 UnicodeString str;
3241 Formattable toFormat, result;
3242 static const UChar ISO_CODE[4] = {0x0047, 0x0042, 0x0050, 0};
3243
3244 Locale saveDefaultLocale = Locale::getDefault();
3245 Locale::setDefault( Locale::getUK(), status );
3246 if (U_FAILURE(status)) {
3247 errln("couldn't set default Locale!");
3248 return;
3249 }
3250
3251 MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
3252 Locale::setDefault( saveDefaultLocale, status );
3253 if (U_FAILURE(status)){
3254 dataerrln("FAIL: Status %s", u_errorName(status));
3255 return;
3256 }
3257 cloneObj = measureObj->clone();
3258 if (cloneObj == NULL) {
3259 errln("Clone doesn't work");
3260 return;
3261 }
3262 toFormat.adoptObject(new CurrencyAmount(1234.56, ISO_CODE, status));
3263 measureObj->format(toFormat, str, status);
3264 measureObj->parseObject(str, result, status);
3265 if (U_FAILURE(status)){
3266 errln("FAIL: Status %s", u_errorName(status));
3267 }
3268 if (result != toFormat) {
3269 errln("measureObj does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3270 }
3271 status = U_ZERO_ERROR;
3272 str.truncate(0);
3273 cloneObj->format(toFormat, str, status);
3274 cloneObj->parseObject(str, result, status);
3275 if (U_FAILURE(status)){
3276 errln("FAIL: Status %s", u_errorName(status));
3277 }
3278 if (result != toFormat) {
3279 errln("Clone does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3280 }
3281 if (*measureObj != *cloneObj) {
3282 errln("Cloned object is not equal to the original object");
3283 }
3284 delete measureObj;
3285 delete cloneObj;
3286
3287 status = U_USELESS_COLLATOR_ERROR;
3288 if (MeasureFormat::createCurrencyFormat(status) != NULL) {
3289 errln("createCurrencyFormat should have returned NULL.");
3290 }
3291 }
3292
3293 /* Port of ICU4J rounding test. */
TestRounding()3294 void NumberFormatTest::TestRounding() {
3295 UErrorCode status = U_ZERO_ERROR;
3296 DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3297
3298 if (U_FAILURE(status)) {
3299 dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3300 return;
3301 }
3302
3303 int roundingIncrements[]={1, 2, 5, 20, 50, 100};
3304 int testValues[]={0, 300};
3305
3306 for (int j=0; j<2; j++) {
3307 for (int mode=DecimalFormat::kRoundUp;mode<DecimalFormat::kRoundHalfEven;mode++) {
3308 df->setRoundingMode((DecimalFormat::ERoundingMode)mode);
3309 for (int increment=0; increment<6; increment++) {
3310 double base=testValues[j];
3311 double rInc=roundingIncrements[increment];
3312 checkRounding(df, base, 20, rInc);
3313 rInc=1.000000000/rInc;
3314 checkRounding(df, base, 20, rInc);
3315 }
3316 }
3317 }
3318 delete df;
3319 }
3320
TestRoundingPattern()3321 void NumberFormatTest::TestRoundingPattern() {
3322 UErrorCode status = U_ZERO_ERROR;
3323 struct {
3324 UnicodeString pattern;
3325 double testCase;
3326 UnicodeString expected;
3327 } tests[] = {
3328 { (UnicodeString)"##0.65", 1.234, (UnicodeString)"1.30" },
3329 { (UnicodeString)"#50", 1230, (UnicodeString)"1250" }
3330 };
3331 int32_t numOfTests = UPRV_LENGTHOF(tests);
3332 UnicodeString result;
3333
3334 DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3335 if (U_FAILURE(status)) {
3336 dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3337 return;
3338 }
3339
3340 for (int32_t i = 0; i < numOfTests; i++) {
3341 result.remove();
3342
3343 df->applyPattern(tests[i].pattern, status);
3344 if (U_FAILURE(status)) {
3345 errln("Unable to apply pattern to decimal formatter. - %s", u_errorName(status));
3346 }
3347
3348 df->format(tests[i].testCase, result);
3349
3350 if (result != tests[i].expected) {
3351 errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
3352 }
3353 }
3354
3355 delete df;
3356 }
3357
checkRounding(DecimalFormat * df,double base,int iterations,double increment)3358 void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
3359 df->setRoundingIncrement(increment);
3360 double lastParsed=INT32_MIN; //Intger.MIN_VALUE
3361 for (int i=-iterations; i<=iterations;i++) {
3362 double iValue=base+(increment*(i*0.1));
3363 double smallIncrement=0.00000001;
3364 if (iValue!=0) {
3365 smallIncrement*=iValue;
3366 }
3367 //we not only test the value, but some values in a small range around it
3368 lastParsed=checkRound(df, iValue-smallIncrement, lastParsed);
3369 lastParsed=checkRound(df, iValue, lastParsed);
3370 lastParsed=checkRound(df, iValue+smallIncrement, lastParsed);
3371 }
3372 }
3373
checkRound(DecimalFormat * df,double iValue,double lastParsed)3374 double NumberFormatTest::checkRound(DecimalFormat* df, double iValue, double lastParsed) {
3375 UErrorCode status=U_ZERO_ERROR;
3376 UnicodeString formattedDecimal;
3377 double parsed;
3378 Formattable result;
3379 df->format(iValue, formattedDecimal, status);
3380
3381 if (U_FAILURE(status)) {
3382 errln("Error formatting number.");
3383 }
3384
3385 df->parse(formattedDecimal, result, status);
3386
3387 if (U_FAILURE(status)) {
3388 errln("Error parsing number.");
3389 }
3390
3391 parsed=result.getDouble();
3392
3393 if (lastParsed>parsed) {
3394 errln("Rounding wrong direction! %d > %d", lastParsed, parsed);
3395 }
3396
3397 return lastParsed;
3398 }
3399
TestNonpositiveMultiplier()3400 void NumberFormatTest::TestNonpositiveMultiplier() {
3401 UErrorCode status = U_ZERO_ERROR;
3402 DecimalFormatSymbols US(Locale::getUS(), status);
3403 CHECK(status, "DecimalFormatSymbols constructor");
3404 DecimalFormat df(UnicodeString("0"), US, status);
3405 CHECK(status, "DecimalFormat(0)");
3406
3407 // test zero multiplier
3408
3409 int32_t mult = df.getMultiplier();
3410 df.setMultiplier(0);
3411 if (df.getMultiplier() != mult) {
3412 errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
3413 }
3414
3415 // test negative multiplier
3416
3417 df.setMultiplier(-1);
3418 if (df.getMultiplier() != -1) {
3419 errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
3420 return;
3421 }
3422
3423 expect(df, "1122.123", -1122.123);
3424 expect(df, "-1122.123", 1122.123);
3425 expect(df, "1.2", -1.2);
3426 expect(df, "-1.2", 1.2);
3427
3428 // Note: the tests with the final parameter of FALSE will not round trip.
3429 // The initial numeric value will format correctly, after the multiplier.
3430 // Parsing the formatted text will be out-of-range for an int64, however.
3431 // The expect() function could be modified to detect this and fall back
3432 // to looking at the decimal parsed value, but it doesn't.
3433 expect(df, U_INT64_MIN, "9223372036854775808", FALSE);
3434 expect(df, U_INT64_MIN+1, "9223372036854775807");
3435 expect(df, (int64_t)-123, "123");
3436 expect(df, (int64_t)123, "-123");
3437 expect(df, U_INT64_MAX-1, "-9223372036854775806");
3438 expect(df, U_INT64_MAX, "-9223372036854775807");
3439
3440 df.setMultiplier(-2);
3441 expect(df, -(U_INT64_MIN/2)-1, "-9223372036854775806");
3442 expect(df, -(U_INT64_MIN/2), "-9223372036854775808");
3443 expect(df, -(U_INT64_MIN/2)+1, "-9223372036854775810", FALSE);
3444
3445 df.setMultiplier(-7);
3446 expect(df, -(U_INT64_MAX/7)-1, "9223372036854775814", FALSE);
3447 expect(df, -(U_INT64_MAX/7), "9223372036854775807");
3448 expect(df, -(U_INT64_MAX/7)+1, "9223372036854775800");
3449
3450 // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
3451 // (right now the big numbers get turned into doubles and lose tons of accuracy)
3452 //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
3453 //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
3454 //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
3455 //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
3456
3457 // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
3458 //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3459 //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3460 //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3461 //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3462 }
3463
3464 typedef struct {
3465 const char * stringToParse;
3466 int parsedPos;
3467 int errorIndex;
3468 UBool lenient;
3469 } TestSpaceParsingItem;
3470
3471 void
TestSpaceParsing()3472 NumberFormatTest::TestSpaceParsing() {
3473 // the data are:
3474 // the string to be parsed, parsed position, parsed error index
3475 const TestSpaceParsingItem DATA[] = {
3476 {"$124", 4, -1, FALSE},
3477 {"$124 $124", 4, -1, FALSE},
3478 {"$124 ", 4, -1, FALSE},
3479 {"$ 124 ", 0, 1, FALSE},
3480 {"$\\u00A0124 ", 5, -1, FALSE},
3481 {" $ 124 ", 0, 0, FALSE},
3482 {"124$", 0, 4, FALSE},
3483 {"124 $", 0, 3, FALSE},
3484 {"$124", 4, -1, TRUE},
3485 {"$124 $124", 4, -1, TRUE},
3486 {"$124 ", 4, -1, TRUE},
3487 {"$ 124 ", 5, -1, TRUE},
3488 {"$\\u00A0124 ", 5, -1, TRUE},
3489 {" $ 124 ", 6, -1, TRUE},
3490 {"124$", 4, -1, TRUE},
3491 {"124$", 4, -1, TRUE},
3492 {"124 $", 5, -1, TRUE},
3493 {"124 $", 5, -1, TRUE},
3494 };
3495 UErrorCode status = U_ZERO_ERROR;
3496 Locale locale("en_US");
3497 NumberFormat* foo = NumberFormat::createCurrencyInstance(locale, status);
3498
3499 if (U_FAILURE(status)) {
3500 delete foo;
3501 return;
3502 }
3503 for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3504 ParsePosition parsePosition(0);
3505 UnicodeString stringToBeParsed = ctou(DATA[i].stringToParse);
3506 int parsedPosition = DATA[i].parsedPos;
3507 int errorIndex = DATA[i].errorIndex;
3508 foo->setLenient(DATA[i].lenient);
3509 Formattable result;
3510 foo->parse(stringToBeParsed, result, parsePosition);
3511 logln("Parsing: " + stringToBeParsed);
3512 if (parsePosition.getIndex() != parsedPosition ||
3513 parsePosition.getErrorIndex() != errorIndex) {
3514 errln("FAILED parse " + stringToBeParsed + "; lenient: " + DATA[i].lenient + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
3515 }
3516 if (parsePosition.getErrorIndex() == -1 &&
3517 result.getType() == Formattable::kLong &&
3518 result.getLong() != 124) {
3519 errln("FAILED parse " + stringToBeParsed + "; wrong number, expect: 124, got " + result.getLong());
3520 }
3521 }
3522 delete foo;
3523 }
3524
3525 /**
3526 * Test using various numbering systems and numbering system keyword.
3527 */
3528 typedef struct {
3529 const char *localeName;
3530 double value;
3531 UBool isRBNF;
3532 const char *expectedResult;
3533 } TestNumberingSystemItem;
3534
TestNumberingSystems()3535 void NumberFormatTest::TestNumberingSystems() {
3536
3537 const TestNumberingSystemItem DATA[] = {
3538 { "en_US@numbers=thai", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" },
3539 { "en_US@numbers=hebr", 5678.0, TRUE, "\\u05D4\\u05F3\\u05EA\\u05E8\\u05E2\\u05F4\\u05D7" },
3540 { "en_US@numbers=arabext", 1234.567, FALSE, "\\u06F1\\u066c\\u06F2\\u06F3\\u06F4\\u066b\\u06F5\\u06F6\\u06F7" },
3541 { "ar_EG", 1234.567, FALSE, "\\u0661\\u066C\\u0662\\u0663\\u0664\\u066b\\u0665\\u0666\\u0667" },
3542 { "th_TH@numbers=traditional", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" }, // fall back to native per TR35
3543 { "ar_MA", 1234.567, FALSE, "1.234,567" },
3544 { "en_US@numbers=hanidec", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3545 { "ta_IN@numbers=native", 1234.567, FALSE, "\\u0BE7,\\u0BE8\\u0BE9\\u0BEA.\\u0BEB\\u0BEC\\u0BED" },
3546 { "ta_IN@numbers=traditional", 1235.0, TRUE, "\\u0BF2\\u0BE8\\u0BF1\\u0BE9\\u0BF0\\u0BEB" },
3547 { "ta_IN@numbers=finance", 1234.567, FALSE, "1,234.567" }, // fall back to default per TR35
3548 { "zh_TW@numbers=native", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3549 { "zh_TW@numbers=traditional", 1234.567, TRUE, "\\u4E00\\u5343\\u4E8C\\u767E\\u4E09\\u5341\\u56DB\\u9EDE\\u4E94\\u516D\\u4E03" },
3550 { "zh_TW@numbers=finance", 1234.567, TRUE, "\\u58F9\\u4EDF\\u8CB3\\u4F70\\u53C3\\u62FE\\u8086\\u9EDE\\u4F0D\\u9678\\u67D2" },
3551 { NULL, 0, FALSE, NULL }
3552 };
3553
3554 UErrorCode ec;
3555
3556 const TestNumberingSystemItem *item;
3557 for (item = DATA; item->localeName != NULL; item++) {
3558 ec = U_ZERO_ERROR;
3559 Locale loc = Locale::createFromName(item->localeName);
3560
3561 NumberFormat *origFmt = NumberFormat::createInstance(loc,ec);
3562 if (U_FAILURE(ec)) {
3563 dataerrln("FAIL: getInstance(%s) - %s", item->localeName, u_errorName(ec));
3564 continue;
3565 }
3566 // Clone to test ticket #10682
3567 NumberFormat *fmt = origFmt->clone();
3568 delete origFmt;
3569
3570
3571 if (item->isRBNF) {
3572 expect3(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3573 } else {
3574 expect2(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3575 }
3576 delete fmt;
3577 }
3578
3579
3580 // Test bogus keyword value
3581 ec = U_ZERO_ERROR;
3582 Locale loc4 = Locale::createFromName("en_US@numbers=foobar");
3583 NumberFormat* fmt4= NumberFormat::createInstance(loc4, ec);
3584 if ( ec != U_UNSUPPORTED_ERROR ) {
3585 errln("FAIL: getInstance(en_US@numbers=foobar) should have returned U_UNSUPPORTED_ERROR");
3586 delete fmt4;
3587 }
3588
3589 ec = U_ZERO_ERROR;
3590 NumberingSystem *ns = NumberingSystem::createInstance(ec);
3591 if (U_FAILURE(ec)) {
3592 dataerrln("FAIL: NumberingSystem::createInstance(ec); - %s", u_errorName(ec));
3593 }
3594
3595 if ( ns != NULL ) {
3596 ns->getDynamicClassID();
3597 ns->getStaticClassID();
3598 } else {
3599 errln("FAIL: getInstance() returned NULL.");
3600 }
3601
3602 NumberingSystem *ns1 = new NumberingSystem(*ns);
3603 if (ns1 == NULL) {
3604 errln("FAIL: NumberSystem copy constructor returned NULL.");
3605 }
3606
3607 delete ns1;
3608 delete ns;
3609
3610 }
3611
3612
3613 void
TestMultiCurrencySign()3614 NumberFormatTest::TestMultiCurrencySign() {
3615 const char* DATA[][6] = {
3616 // the fields in the following test are:
3617 // locale,
3618 // currency pattern (with negative pattern),
3619 // currency number to be formatted,
3620 // currency format using currency symbol name, such as "$" for USD,
3621 // currency format using currency ISO name, such as "USD",
3622 // currency format using plural name, such as "US dollars".
3623 // for US locale
3624 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1234.56", "$1,234.56", "USD\\u00A01,234.56", "US dollars\\u00A01,234.56"},
3625 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD\\u00A01,234.56", "-US dollars\\u00A01,234.56"},
3626 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD\\u00A01.00", "US dollars\\u00A01.00"},
3627 // for CHINA locale
3628 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\u00A51,234.56", "CNY\\u00A01,234.56", "\\u4EBA\\u6C11\\u5E01\\u00A01,234.56"},
3629 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\u00A51,234.56)", "(CNY\\u00A01,234.56)", "(\\u4EBA\\u6C11\\u5E01\\u00A01,234.56)"},
3630 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\u00A51.00", "CNY\\u00A01.00", "\\u4EBA\\u6C11\\u5E01\\u00A01.00"}
3631 };
3632
3633 const UChar doubleCurrencySign[] = {0xA4, 0xA4, 0};
3634 UnicodeString doubleCurrencyStr(doubleCurrencySign);
3635 const UChar tripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
3636 UnicodeString tripleCurrencyStr(tripleCurrencySign);
3637
3638 for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3639 const char* locale = DATA[i][0];
3640 UnicodeString pat = ctou(DATA[i][1]);
3641 double numberToBeFormat = atof(DATA[i][2]);
3642 UErrorCode status = U_ZERO_ERROR;
3643 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale(locale), status);
3644 if (U_FAILURE(status)) {
3645 delete sym;
3646 continue;
3647 }
3648 for (int j=1; j<=3; ++j) {
3649 // j represents the number of currency sign in the pattern.
3650 if (j == 2) {
3651 pat = pat.findAndReplace(ctou("\\u00A4"), doubleCurrencyStr);
3652 } else if (j == 3) {
3653 pat = pat.findAndReplace(ctou("\\u00A4\\u00A4"), tripleCurrencyStr);
3654 }
3655
3656 DecimalFormat* fmt = new DecimalFormat(pat, new DecimalFormatSymbols(*sym), status);
3657 if (U_FAILURE(status)) {
3658 errln("FAILED init DecimalFormat ");
3659 delete fmt;
3660 continue;
3661 }
3662 UnicodeString s;
3663 ((NumberFormat*) fmt)->format(numberToBeFormat, s);
3664 // DATA[i][3] is the currency format result using a
3665 // single currency sign.
3666 // DATA[i][4] is the currency format result using
3667 // double currency sign.
3668 // DATA[i][5] is the currency format result using
3669 // triple currency sign.
3670 // DATA[i][j+2] is the currency format result using
3671 // 'j' number of currency sign.
3672 UnicodeString currencyFormatResult = ctou(DATA[i][2+j]);
3673 if (s.compare(currencyFormatResult)) {
3674 errln("FAIL format: Expected " + currencyFormatResult + "; Got " + s);
3675 }
3676 // mix style parsing
3677 for (int k=3; k<=5; ++k) {
3678 // DATA[i][3] is the currency format result using a
3679 // single currency sign.
3680 // DATA[i][4] is the currency format result using
3681 // double currency sign.
3682 // DATA[i][5] is the currency format result using
3683 // triple currency sign.
3684 UnicodeString oneCurrencyFormat = ctou(DATA[i][k]);
3685 UErrorCode status = U_ZERO_ERROR;
3686 Formattable parseRes;
3687 fmt->parse(oneCurrencyFormat, parseRes, status);
3688 if (U_FAILURE(status) ||
3689 (parseRes.getType() == Formattable::kDouble &&
3690 parseRes.getDouble() != numberToBeFormat) ||
3691 (parseRes.getType() == Formattable::kLong &&
3692 parseRes.getLong() != numberToBeFormat)) {
3693 errln("FAILED parse " + oneCurrencyFormat + "; (i, j, k): " +
3694 i + ", " + j + ", " + k);
3695 }
3696 }
3697 delete fmt;
3698 }
3699 delete sym;
3700 }
3701 }
3702
3703
3704 void
TestCurrencyFormatForMixParsing()3705 NumberFormatTest::TestCurrencyFormatForMixParsing() {
3706 UErrorCode status = U_ZERO_ERROR;
3707 MeasureFormat* curFmt = MeasureFormat::createCurrencyFormat(Locale("en_US"), status);
3708 if (U_FAILURE(status)) {
3709 delete curFmt;
3710 return;
3711 }
3712 const char* formats[] = {
3713 "$1,234.56", // string to be parsed
3714 "USD1,234.56",
3715 "US dollars1,234.56",
3716 // "1,234.56 US dollars" // Fails in 62 because currency format is not compatible with pattern.
3717 };
3718 const CurrencyAmount* curramt = NULL;
3719 for (uint32_t i = 0; i < UPRV_LENGTHOF(formats); ++i) {
3720 UnicodeString stringToBeParsed = ctou(formats[i]);
3721 logln(UnicodeString("stringToBeParsed: ") + stringToBeParsed);
3722 Formattable result;
3723 UErrorCode status = U_ZERO_ERROR;
3724 curFmt->parseObject(stringToBeParsed, result, status);
3725 if (U_FAILURE(status)) {
3726 errln("FAIL: measure format parsing: '%s' ec: %s", formats[i], u_errorName(status));
3727 } else if (result.getType() != Formattable::kObject ||
3728 (curramt = dynamic_cast<const CurrencyAmount*>(result.getObject())) == NULL ||
3729 curramt->getNumber().getDouble() != 1234.56 ||
3730 UnicodeString(curramt->getISOCurrency()).compare(ISO_CURRENCY_USD)
3731 ) {
3732 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number ");
3733 if (curramt->getNumber().getDouble() != 1234.56) {
3734 errln((UnicodeString)"wong number, expect: 1234.56" + ", got: " + curramt->getNumber().getDouble());
3735 }
3736 if (curramt->getISOCurrency() != ISO_CURRENCY_USD) {
3737 errln((UnicodeString)"wong currency, expect: USD" + ", got: " + curramt->getISOCurrency());
3738 }
3739 }
3740 }
3741 delete curFmt;
3742 }
3743
3744
3745 /** Starting in ICU 62, strict mode is actually strict with currency formats. */
TestMismatchedCurrencyFormatFail()3746 void NumberFormatTest::TestMismatchedCurrencyFormatFail() {
3747 IcuTestErrorCode status(*this, "TestMismatchedCurrencyFormatFail");
3748 LocalPointer<DecimalFormat> df(
3749 dynamic_cast<DecimalFormat*>(DecimalFormat::createCurrencyInstance("en", status)), status);
3750 if (!assertSuccess("createCurrencyInstance() failed.", status, true, __FILE__, __LINE__)) {return;}
3751 UnicodeString pattern;
3752 assertEquals("Test assumes that currency sign is at the beginning",
3753 u"\u00A4#,##0.00",
3754 df->toPattern(pattern));
3755 // Should round-trip on the correct currency format:
3756 expect2(*df, 1.23, u"\u00A41.23");
3757 df->setCurrency(u"EUR", status);
3758 expect2(*df, 1.23, u"\u20AC1.23");
3759 // Should parse with currency in the wrong place in lenient mode
3760 df->setLenient(TRUE);
3761 expect(*df, u"1.23\u20AC", 1.23);
3762 expectParseCurrency(*df, u"EUR", 1.23, "1.23\\u20AC");
3763 // Should NOT parse with currency in the wrong place in STRICT mode
3764 df->setLenient(FALSE);
3765 {
3766 Formattable result;
3767 ErrorCode failStatus;
3768 df->parse(u"1.23\u20AC", result, failStatus);
3769 assertEquals("Should fail to parse", U_INVALID_FORMAT_ERROR, failStatus);
3770 }
3771 {
3772 ParsePosition ppos;
3773 df->parseCurrency(u"1.23\u20AC", ppos);
3774 assertEquals("Should fail to parse currency", 0, ppos.getIndex());
3775 }
3776 }
3777
3778
3779 void
TestDecimalFormatCurrencyParse()3780 NumberFormatTest::TestDecimalFormatCurrencyParse() {
3781 // Locale.US
3782 UErrorCode status = U_ZERO_ERROR;
3783 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale("en_US"), status);
3784 if (U_FAILURE(status)) {
3785 delete sym;
3786 return;
3787 }
3788 UnicodeString pat;
3789 UChar currency = 0x00A4;
3790 // "\xA4#,##0.00;-\xA4#,##0.00"
3791 pat.append(currency).append(currency).append(currency).append("#,##0.00;-").append(currency).append(currency).append(currency).append("#,##0.00");
3792 DecimalFormat* fmt = new DecimalFormat(pat, sym, status);
3793 if (U_FAILURE(status)) {
3794 delete fmt;
3795 errln("failed to new DecimalFormat in TestDecimalFormatCurrencyParse");
3796 return;
3797 }
3798 const char* DATA[][2] = {
3799 // the data are:
3800 // string to be parsed, the parsed result (number)
3801 {"$1.00", "1"},
3802 {"USD1.00", "1"},
3803 {"1.00 US dollar", "1"},
3804 {"$1,234.56", "1234.56"},
3805 {"USD1,234.56", "1234.56"},
3806 {"1,234.56 US dollar", "1234.56"},
3807 };
3808 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3809 fmt->setLenient(TRUE);
3810 for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3811 UnicodeString stringToBeParsed = ctou(DATA[i][0]);
3812 double parsedResult = atof(DATA[i][1]);
3813 UErrorCode status = U_ZERO_ERROR;
3814 Formattable result;
3815 fmt->parse(stringToBeParsed, result, status);
3816 logln((UnicodeString)"Input: " + stringToBeParsed + "; output: " + result.getDouble(status));
3817 if (U_FAILURE(status) ||
3818 (result.getType() == Formattable::kDouble &&
3819 result.getDouble() != parsedResult) ||
3820 (result.getType() == Formattable::kLong &&
3821 result.getLong() != parsedResult)) {
3822 errln((UnicodeString)"FAIL parse: Expected " + parsedResult);
3823 }
3824 }
3825 delete fmt;
3826 }
3827
3828
3829 void
TestCurrencyIsoPluralFormat()3830 NumberFormatTest::TestCurrencyIsoPluralFormat() {
3831 static const char* DATA[][6] = {
3832 // the data are:
3833 // locale,
3834 // currency amount to be formatted,
3835 // currency ISO code to be formatted,
3836 // format result using CURRENCYSTYLE,
3837 // format result using ISOCURRENCYSTYLE,
3838 // format result using PLURALCURRENCYSTYLE,
3839
3840 {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3841 {"en_US", "1234.56", "USD", "$1,234.56", "USD\\u00A01,234.56", "1,234.56 US dollars"},
3842 {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD\\u00A01,234.56", "-1,234.56 US dollars"},
3843 {"zh_CN", "1", "USD", "US$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7F8E\\u5143"},
3844 {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD\\u00A01,234.56", "1,234.56\\u00A0\\u7F8E\\u5143"},
3845 {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A01.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3846 {"zh_CN", "1234.56", "CNY", "\\u00A51,234.56", "CNY\\u00A01,234.56", "1,234.56\\u00A0\\u4EBA\\u6C11\\u5E01"},
3847 {"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3848 {"ru_RU", "2", "RUB", "2,00\\u00A0\\u20BD", "2,00\\u00A0RUB", "2,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3849 {"ru_RU", "5", "RUB", "5,00\\u00A0\\u20BD", "5,00\\u00A0RUB", "5,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3850 // test locale without currency information
3851 {"root", "-1.23", "USD", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"},
3852 // test choice format
3853 {"es_AR", "1", "INR", "INR\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"},
3854 };
3855 static const UNumberFormatStyle currencyStyles[] = {
3856 UNUM_CURRENCY,
3857 UNUM_CURRENCY_ISO,
3858 UNUM_CURRENCY_PLURAL
3859 };
3860
3861 for (int32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3862 const char* localeString = DATA[i][0];
3863 double numberToBeFormat = atof(DATA[i][1]);
3864 const char* currencyISOCode = DATA[i][2];
3865 logln(UnicodeString(u"Locale: ") + localeString + "; amount: " + numberToBeFormat);
3866 Locale locale(localeString);
3867 for (int32_t kIndex = 0; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3868 UNumberFormatStyle k = currencyStyles[kIndex];
3869 logln(UnicodeString(u"UNumberFormatStyle: ") + k);
3870 UErrorCode status = U_ZERO_ERROR;
3871 NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3872 if (U_FAILURE(status)) {
3873 delete numFmt;
3874 dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3875 continue;
3876 }
3877 UChar currencyCode[4];
3878 u_charsToUChars(currencyISOCode, currencyCode, 4);
3879 numFmt->setCurrency(currencyCode, status);
3880 if (U_FAILURE(status)) {
3881 delete numFmt;
3882 errln((UnicodeString)"can not set currency:" + currencyISOCode);
3883 continue;
3884 }
3885
3886 UnicodeString strBuf;
3887 numFmt->format(numberToBeFormat, strBuf);
3888 int resultDataIndex = 3 + kIndex;
3889 // DATA[i][resultDataIndex] is the currency format result
3890 // using 'k' currency style.
3891 UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
3892 if (strBuf.compare(formatResult)) {
3893 errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
3894 }
3895 // test parsing, and test parsing for all currency formats.
3896 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3897 numFmt->setLenient(TRUE);
3898 for (int j = 3; j < 6; ++j) {
3899 // DATA[i][3] is the currency format result using
3900 // CURRENCYSTYLE formatter.
3901 // DATA[i][4] is the currency format result using
3902 // ISOCURRENCYSTYLE formatter.
3903 // DATA[i][5] is the currency format result using
3904 // PLURALCURRENCYSTYLE formatter.
3905 UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
3906 UErrorCode status = U_ZERO_ERROR;
3907 Formattable parseResult;
3908 numFmt->parse(oneCurrencyFormatResult, parseResult, status);
3909 if (U_FAILURE(status) ||
3910 (parseResult.getType() == Formattable::kDouble &&
3911 parseResult.getDouble() != numberToBeFormat) ||
3912 (parseResult.getType() == Formattable::kLong &&
3913 parseResult.getLong() != numberToBeFormat)) {
3914 errln((UnicodeString)"FAIL: getCurrencyFormat of locale " +
3915 localeString + " failed roundtripping the number");
3916 if (parseResult.getType() == Formattable::kDouble) {
3917 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getDouble());
3918 } else {
3919 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getLong());
3920 }
3921 }
3922 }
3923 delete numFmt;
3924 }
3925 }
3926 }
3927
3928 void
TestCurrencyParsing()3929 NumberFormatTest::TestCurrencyParsing() {
3930 static const char* DATA[][6] = {
3931 // the data are:
3932 // locale,
3933 // currency amount to be formatted,
3934 // currency ISO code to be formatted,
3935 // format result using CURRENCYSTYLE,
3936 // format result using ISOCURRENCYSTYLE,
3937 // format result using PLURALCURRENCYSTYLE,
3938 {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3939 {"pa_IN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\u0a2f\\u0a42.\\u0a10\\u0a38. \\u0a21\\u0a3e\\u0a32\\u0a30"},
3940 {"es_AR", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 d\\u00f3lar estadounidense"},
3941 {"ar_EG", "1", "USD", "\\u0661\\u066b\\u0660\\u0660\\u00a0US$", "\\u0661\\u066b\\u0660\\u0660\\u00a0USD", "\\u0661\\u066b\\u0660\\u0660 \\u062f\\u0648\\u0644\\u0627\\u0631 \\u0623\\u0645\\u0631\\u064a\\u0643\\u064a"},
3942 {"fa_CA", "1", "USD", "\\u200e$\\u06f1\\u066b\\u06f0\\u06f0", "\\u200eUSD\\u06f1\\u066b\\u06f0\\u06f0", "\\u06f1\\u066b\\u06f0\\u06f0 \\u062f\\u0644\\u0627\\u0631 \\u0622\\u0645\\u0631\\u06cc\\u06a9\\u0627"},
3943 {"he_IL", "1", "USD", "\\u200f1.00\\u00a0$", "\\u200f1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
3944 {"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 ameri\\u010Dkih dolara"},
3945 {"id_ID", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 Dolar Amerika Serikat"},
3946 {"it_IT", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 dollari statunitensi"},
3947 {"ko_KR", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
3948 {"ja_JP", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7c73\\u30c9\\u30eb"},
3949 {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A001.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3950 {"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3951 {"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3952 {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1 \\u65E5\\u5713"},
3953 {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3954 // ICU 62 requires #parseCurrency() to recognize variants when parsing
3955 // {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3956 {"ru_RU", "1", "RUB", "1,00\\u00A0\\u00A0\\u20BD", "1,00\\u00A0\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"}
3957 };
3958 static const UNumberFormatStyle currencyStyles[] = {
3959 UNUM_CURRENCY,
3960 UNUM_CURRENCY_ISO,
3961 UNUM_CURRENCY_PLURAL
3962 };
3963 static const char* currencyStyleNames[] = {
3964 "UNUM_CURRENCY",
3965 "UNUM_CURRENCY_ISO",
3966 "UNUM_CURRENCY_PLURAL"
3967 };
3968
3969 #ifdef NUMFMTST_CACHE_DEBUG
3970 int deadloop = 0;
3971 for (;;) {
3972 printf("loop: %d\n", deadloop++);
3973 #endif
3974 for (uint32_t i=0; i< UPRV_LENGTHOF(DATA); ++i) { /* i = test case # - should be i=0*/
3975 for (int32_t kIndex = 2; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3976 UNumberFormatStyle k = currencyStyles[kIndex]; /* k = style */
3977 const char* localeString = DATA[i][0];
3978 double numberToBeFormat = atof(DATA[i][1]);
3979 const char* currencyISOCode = DATA[i][2];
3980 Locale locale(localeString);
3981 UErrorCode status = U_ZERO_ERROR;
3982 NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3983 logln("#%d NumberFormat(%s, %s) Currency=%s\n",
3984 i, localeString, currencyStyleNames[kIndex],
3985 currencyISOCode);
3986
3987 if (U_FAILURE(status)) {
3988 delete numFmt;
3989 dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3990 continue;
3991 }
3992 UChar currencyCode[4];
3993 u_charsToUChars(currencyISOCode, currencyCode, 4);
3994 numFmt->setCurrency(currencyCode, status);
3995 if (U_FAILURE(status)) {
3996 delete numFmt;
3997 errln((UnicodeString)"can not set currency:" + currencyISOCode);
3998 continue;
3999 }
4000
4001 UnicodeString strBuf;
4002 numFmt->format(numberToBeFormat, strBuf);
4003 int resultDataIndex = 3 + kIndex;
4004 // DATA[i][resultDataIndex] is the currency format result
4005 // using 'k' currency style.
4006 UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
4007 if (strBuf.compare(formatResult)) {
4008 errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
4009 }
4010 // test parsing, and test parsing for all currency formats.
4011 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
4012 numFmt->setLenient(TRUE);
4013 for (int j = 3; j < 6; ++j) {
4014 // DATA[i][3] is the currency format result using
4015 // CURRENCYSTYLE formatter.
4016 // DATA[i][4] is the currency format result using
4017 // ISOCURRENCYSTYLE formatter.
4018 // DATA[i][5] is the currency format result using
4019 // PLURALCURRENCYSTYLE formatter.
4020 UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
4021 UErrorCode status = U_ZERO_ERROR;
4022 Formattable parseResult;
4023 logln("parse(%s)", DATA[i][j]);
4024 numFmt->parse(oneCurrencyFormatResult, parseResult, status);
4025 if (U_FAILURE(status) ||
4026 (parseResult.getType() == Formattable::kDouble &&
4027 parseResult.getDouble() != numberToBeFormat) ||
4028 (parseResult.getType() == Formattable::kLong &&
4029 parseResult.getLong() != numberToBeFormat)) {
4030 errln((UnicodeString)"FAIL: NumberFormat(" + localeString +", " + currencyStyleNames[kIndex] +
4031 "), Currency="+currencyISOCode+", parse("+DATA[i][j]+") returned error " + (UnicodeString)u_errorName(status)+". Testcase: data[" + i + "][" + currencyStyleNames[j-3] +"="+j+"]");
4032 if (parseResult.getType() == Formattable::kDouble) {
4033 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (double): " +parseResult.getDouble());
4034 } else {
4035 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (long): " +parseResult.getLong());
4036 }
4037 errln((UnicodeString)" round-trip would be: " + strBuf);
4038 }
4039 }
4040 delete numFmt;
4041 }
4042 }
4043 #ifdef NUMFMTST_CACHE_DEBUG
4044 }
4045 #endif
4046 }
4047
4048
4049 void
TestParseCurrencyInUCurr()4050 NumberFormatTest::TestParseCurrencyInUCurr() {
4051 const char* DATA[] = {
4052 "1.00 US DOLLAR", // case in-sensitive
4053 "$1.00",
4054 "USD1.00",
4055 "usd1.00", // case in-sensitive: #13696
4056 "US dollar1.00",
4057 "US dollars1.00",
4058 "$1.00",
4059 "A$1.00",
4060 "ADP1.00",
4061 "ADP1.00",
4062 "AED1.00",
4063 "AED1.00",
4064 "AFA1.00",
4065 "AFA1.00",
4066 "AFN1.00",
4067 "ALL1.00",
4068 "AMD1.00",
4069 "ANG1.00",
4070 "AOA1.00",
4071 "AOK1.00",
4072 "AOK1.00",
4073 "AON1.00",
4074 "AON1.00",
4075 "AOR1.00",
4076 "AOR1.00",
4077 "ARS1.00",
4078 "ARA1.00",
4079 "ARA1.00",
4080 "ARP1.00",
4081 "ARP1.00",
4082 "ARS1.00",
4083 "ATS1.00",
4084 "ATS1.00",
4085 "AUD1.00",
4086 "AWG1.00",
4087 "AZM1.00",
4088 "AZM1.00",
4089 "AZN1.00",
4090 "Afghan Afghani (1927\\u20132002)1.00",
4091 "Afghan afghani (1927\\u20132002)1.00",
4092 "Afghan Afghani1.00",
4093 "Afghan Afghanis1.00",
4094 "Albanian Lek1.00",
4095 "Albanian lek1.00",
4096 "Albanian lek\\u00eb1.00",
4097 "Algerian Dinar1.00",
4098 "Algerian dinar1.00",
4099 "Algerian dinars1.00",
4100 "Andorran Peseta1.00",
4101 "Andorran peseta1.00",
4102 "Andorran pesetas1.00",
4103 "Angolan Kwanza (1977\\u20131991)1.00",
4104 "Angolan Readjusted Kwanza (1995\\u20131999)1.00",
4105 "Angolan Kwanza1.00",
4106 "Angolan New Kwanza (1990\\u20132000)1.00",
4107 "Angolan kwanza (1977\\u20131991)1.00",
4108 "Angolan readjusted kwanza (1995\\u20131999)1.00",
4109 "Angolan kwanza1.00",
4110 "Angolan kwanzas (1977\\u20131991)1.00",
4111 "Angolan readjusted kwanzas (1995\\u20131999)1.00",
4112 "Angolan kwanzas1.00",
4113 "Angolan new kwanza (1990\\u20132000)1.00",
4114 "Angolan new kwanzas (1990\\u20132000)1.00",
4115 "Argentine Austral1.00",
4116 "Argentine Peso (1983\\u20131985)1.00",
4117 "Argentine Peso1.00",
4118 "Argentine austral1.00",
4119 "Argentine australs1.00",
4120 "Argentine peso (1983\\u20131985)1.00",
4121 "Argentine peso1.00",
4122 "Argentine pesos (1983\\u20131985)1.00",
4123 "Argentine pesos1.00",
4124 "Armenian Dram1.00",
4125 "Armenian dram1.00",
4126 "Armenian drams1.00",
4127 "Aruban Florin1.00",
4128 "Aruban florin1.00",
4129 "Australian Dollar1.00",
4130 "Australian dollar1.00",
4131 "Australian dollars1.00",
4132 "Austrian Schilling1.00",
4133 "Austrian schilling1.00",
4134 "Austrian schillings1.00",
4135 "Azerbaijani Manat (1993\\u20132006)1.00",
4136 "Azerbaijani Manat1.00",
4137 "Azerbaijani manat (1993\\u20132006)1.00",
4138 "Azerbaijani manat1.00",
4139 "Azerbaijani manats (1993\\u20132006)1.00",
4140 "Azerbaijani manats1.00",
4141 "BAD1.00",
4142 "BAD1.00",
4143 "BAM1.00",
4144 "BBD1.00",
4145 "BDT1.00",
4146 "BEC1.00",
4147 "BEC1.00",
4148 "BEF1.00",
4149 "BEL1.00",
4150 "BEL1.00",
4151 "BGL1.00",
4152 "BGN1.00",
4153 "BGN1.00",
4154 "BHD1.00",
4155 "BIF1.00",
4156 "BMD1.00",
4157 "BND1.00",
4158 "BOB1.00",
4159 "BOP1.00",
4160 "BOP1.00",
4161 "BOV1.00",
4162 "BOV1.00",
4163 "BRB1.00",
4164 "BRB1.00",
4165 "BRC1.00",
4166 "BRC1.00",
4167 "BRE1.00",
4168 "BRE1.00",
4169 "BRL1.00",
4170 "BRN1.00",
4171 "BRN1.00",
4172 "BRR1.00",
4173 "BRR1.00",
4174 "BSD1.00",
4175 "BSD1.00",
4176 "BTN1.00",
4177 "BUK1.00",
4178 "BUK1.00",
4179 "BWP1.00",
4180 "BYB1.00",
4181 "BYB1.00",
4182 "BYR1.00",
4183 "BZD1.00",
4184 "Bahamian Dollar1.00",
4185 "Bahamian dollar1.00",
4186 "Bahamian dollars1.00",
4187 "Bahraini Dinar1.00",
4188 "Bahraini dinar1.00",
4189 "Bahraini dinars1.00",
4190 "Bangladeshi Taka1.00",
4191 "Bangladeshi taka1.00",
4192 "Bangladeshi takas1.00",
4193 "Barbadian Dollar1.00",
4194 "Barbadian dollar1.00",
4195 "Barbadian dollars1.00",
4196 "Belarusian Ruble (1994\\u20131999)1.00",
4197 "Belarusian Ruble1.00",
4198 "Belarusian ruble (1994\\u20131999)1.00",
4199 "Belarusian rubles (1994\\u20131999)1.00",
4200 "Belarusian ruble1.00",
4201 "Belarusian rubles1.00",
4202 "Belgian Franc (convertible)1.00",
4203 "Belgian Franc (financial)1.00",
4204 "Belgian Franc1.00",
4205 "Belgian franc (convertible)1.00",
4206 "Belgian franc (financial)1.00",
4207 "Belgian franc1.00",
4208 "Belgian francs (convertible)1.00",
4209 "Belgian francs (financial)1.00",
4210 "Belgian francs1.00",
4211 "Belize Dollar1.00",
4212 "Belize dollar1.00",
4213 "Belize dollars1.00",
4214 "Bermudan Dollar1.00",
4215 "Bermudan dollar1.00",
4216 "Bermudan dollars1.00",
4217 "Bhutanese Ngultrum1.00",
4218 "Bhutanese ngultrum1.00",
4219 "Bhutanese ngultrums1.00",
4220 "Bolivian Mvdol1.00",
4221 "Bolivian Peso1.00",
4222 "Bolivian mvdol1.00",
4223 "Bolivian mvdols1.00",
4224 "Bolivian peso1.00",
4225 "Bolivian pesos1.00",
4226 "Bolivian Boliviano1.00",
4227 "Bolivian Boliviano1.00",
4228 "Bolivian Bolivianos1.00",
4229 "Bosnia-Herzegovina Convertible Mark1.00",
4230 "Bosnia-Herzegovina Dinar (1992\\u20131994)1.00",
4231 "Bosnia-Herzegovina convertible mark1.00",
4232 "Bosnia-Herzegovina convertible marks1.00",
4233 "Bosnia-Herzegovina dinar (1992\\u20131994)1.00",
4234 "Bosnia-Herzegovina dinars (1992\\u20131994)1.00",
4235 "Botswanan Pula1.00",
4236 "Botswanan pula1.00",
4237 "Botswanan pulas1.00",
4238 "Brazilian New Cruzado (1989\\u20131990)1.00",
4239 "Brazilian Cruzado (1986\\u20131989)1.00",
4240 "Brazilian Cruzeiro (1990\\u20131993)1.00",
4241 "Brazilian New Cruzeiro (1967\\u20131986)1.00",
4242 "Brazilian Cruzeiro (1993\\u20131994)1.00",
4243 "Brazilian Real1.00",
4244 "Brazilian new cruzado (1989\\u20131990)1.00",
4245 "Brazilian new cruzados (1989\\u20131990)1.00",
4246 "Brazilian cruzado (1986\\u20131989)1.00",
4247 "Brazilian cruzados (1986\\u20131989)1.00",
4248 "Brazilian cruzeiro (1990\\u20131993)1.00",
4249 "Brazilian new cruzeiro (1967\\u20131986)1.00",
4250 "Brazilian cruzeiro (1993\\u20131994)1.00",
4251 "Brazilian cruzeiros (1990\\u20131993)1.00",
4252 "Brazilian new cruzeiros (1967\\u20131986)1.00",
4253 "Brazilian cruzeiros (1993\\u20131994)1.00",
4254 "Brazilian real1.00",
4255 "Brazilian reals1.00",
4256 "British Pound1.00",
4257 "British pound1.00",
4258 "British pounds1.00",
4259 "Brunei Dollar1.00",
4260 "Brunei dollar1.00",
4261 "Brunei dollars1.00",
4262 "Bulgarian Hard Lev1.00",
4263 "Bulgarian Lev1.00",
4264 "Bulgarian Leva1.00",
4265 "Bulgarian hard lev1.00",
4266 "Bulgarian hard leva1.00",
4267 "Bulgarian lev1.00",
4268 "Burmese Kyat1.00",
4269 "Burmese kyat1.00",
4270 "Burmese kyats1.00",
4271 "Burundian Franc1.00",
4272 "Burundian franc1.00",
4273 "Burundian francs1.00",
4274 "CA$1.00",
4275 "CAD1.00",
4276 "CDF1.00",
4277 "CDF1.00",
4278 "West African CFA Franc1.00",
4279 "Central African CFA Franc1.00",
4280 "West African CFA franc1.00",
4281 "Central African CFA franc1.00",
4282 "West African CFA francs1.00",
4283 "Central African CFA francs1.00",
4284 "CFP Franc1.00",
4285 "CFP franc1.00",
4286 "CFP francs1.00",
4287 "CFPF1.00",
4288 "CHE1.00",
4289 "CHE1.00",
4290 "CHF1.00",
4291 "CHW1.00",
4292 "CHW1.00",
4293 "CLF1.00",
4294 "CLF1.00",
4295 "CLP1.00",
4296 "CNY1.00",
4297 "COP1.00",
4298 "COU1.00",
4299 "COU1.00",
4300 "CRC1.00",
4301 "CSD1.00",
4302 "CSD1.00",
4303 "CSK1.00",
4304 "CSK1.00",
4305 "CUP1.00",
4306 "CUP1.00",
4307 "CVE1.00",
4308 "CYP1.00",
4309 "CZK1.00",
4310 "Cambodian Riel1.00",
4311 "Cambodian riel1.00",
4312 "Cambodian riels1.00",
4313 "Canadian Dollar1.00",
4314 "Canadian dollar1.00",
4315 "Canadian dollars1.00",
4316 "Cape Verdean Escudo1.00",
4317 "Cape Verdean escudo1.00",
4318 "Cape Verdean escudos1.00",
4319 "Cayman Islands Dollar1.00",
4320 "Cayman Islands dollar1.00",
4321 "Cayman Islands dollars1.00",
4322 "Chilean Peso1.00",
4323 "Chilean Unit of Account (UF)1.00",
4324 "Chilean peso1.00",
4325 "Chilean pesos1.00",
4326 "Chilean unit of account (UF)1.00",
4327 "Chilean units of account (UF)1.00",
4328 "Chinese Yuan1.00",
4329 "Chinese yuan1.00",
4330 "Colombian Peso1.00",
4331 "Colombian peso1.00",
4332 "Colombian pesos1.00",
4333 "Comorian Franc1.00",
4334 "Comorian franc1.00",
4335 "Comorian francs1.00",
4336 "Congolese Franc1.00",
4337 "Congolese franc1.00",
4338 "Congolese francs1.00",
4339 "Costa Rican Col\\u00f3n1.00",
4340 "Costa Rican col\\u00f3n1.00",
4341 "Costa Rican col\\u00f3ns1.00",
4342 "Croatian Dinar1.00",
4343 "Croatian Kuna1.00",
4344 "Croatian dinar1.00",
4345 "Croatian dinars1.00",
4346 "Croatian kuna1.00",
4347 "Croatian kunas1.00",
4348 "Cuban Peso1.00",
4349 "Cuban peso1.00",
4350 "Cuban pesos1.00",
4351 "Cypriot Pound1.00",
4352 "Cypriot pound1.00",
4353 "Cypriot pounds1.00",
4354 "Czech Koruna1.00",
4355 "Czech koruna1.00",
4356 "Czech korunas1.00",
4357 "Czechoslovak Hard Koruna1.00",
4358 "Czechoslovak hard koruna1.00",
4359 "Czechoslovak hard korunas1.00",
4360 "DDM1.00",
4361 "DDM1.00",
4362 "DEM1.00",
4363 "DEM1.00",
4364 "DJF1.00",
4365 "DKK1.00",
4366 "DOP1.00",
4367 "DZD1.00",
4368 "Danish Krone1.00",
4369 "Danish krone1.00",
4370 "Danish kroner1.00",
4371 "German Mark1.00",
4372 "German mark1.00",
4373 "German marks1.00",
4374 "Djiboutian Franc1.00",
4375 "Djiboutian franc1.00",
4376 "Djiboutian francs1.00",
4377 "Dominican Peso1.00",
4378 "Dominican peso1.00",
4379 "Dominican pesos1.00",
4380 "EC$1.00",
4381 "ECS1.00",
4382 "ECS1.00",
4383 "ECV1.00",
4384 "ECV1.00",
4385 "EEK1.00",
4386 "EEK1.00",
4387 "EGP1.00",
4388 "EGP1.00",
4389 "ERN1.00",
4390 "ERN1.00",
4391 "ESA1.00",
4392 "ESA1.00",
4393 "ESB1.00",
4394 "ESB1.00",
4395 "ESP1.00",
4396 "ETB1.00",
4397 "EUR1.00",
4398 "East Caribbean Dollar1.00",
4399 "East Caribbean dollar1.00",
4400 "East Caribbean dollars1.00",
4401 "East German Mark1.00",
4402 "East German mark1.00",
4403 "East German marks1.00",
4404 "Ecuadorian Sucre1.00",
4405 "Ecuadorian Unit of Constant Value1.00",
4406 "Ecuadorian sucre1.00",
4407 "Ecuadorian sucres1.00",
4408 "Ecuadorian unit of constant value1.00",
4409 "Ecuadorian units of constant value1.00",
4410 "Egyptian Pound1.00",
4411 "Egyptian pound1.00",
4412 "Egyptian pounds1.00",
4413 "Salvadoran Col\\u00f3n1.00",
4414 "Salvadoran col\\u00f3n1.00",
4415 "Salvadoran colones1.00",
4416 "Equatorial Guinean Ekwele1.00",
4417 "Equatorial Guinean ekwele1.00",
4418 "Eritrean Nakfa1.00",
4419 "Eritrean nakfa1.00",
4420 "Eritrean nakfas1.00",
4421 "Estonian Kroon1.00",
4422 "Estonian kroon1.00",
4423 "Estonian kroons1.00",
4424 "Ethiopian Birr1.00",
4425 "Ethiopian birr1.00",
4426 "Ethiopian birrs1.00",
4427 "Euro1.00",
4428 "European Composite Unit1.00",
4429 "European Currency Unit1.00",
4430 "European Monetary Unit1.00",
4431 "European Unit of Account (XBC)1.00",
4432 "European Unit of Account (XBD)1.00",
4433 "European composite unit1.00",
4434 "European composite units1.00",
4435 "European currency unit1.00",
4436 "European currency units1.00",
4437 "European monetary unit1.00",
4438 "European monetary units1.00",
4439 "European unit of account (XBC)1.00",
4440 "European unit of account (XBD)1.00",
4441 "European units of account (XBC)1.00",
4442 "European units of account (XBD)1.00",
4443 "FIM1.00",
4444 "FIM1.00",
4445 "FJD1.00",
4446 "FKP1.00",
4447 "FKP1.00",
4448 "FRF1.00",
4449 "FRF1.00",
4450 "Falkland Islands Pound1.00",
4451 "Falkland Islands pound1.00",
4452 "Falkland Islands pounds1.00",
4453 "Fijian Dollar1.00",
4454 "Fijian dollar1.00",
4455 "Fijian dollars1.00",
4456 "Finnish Markka1.00",
4457 "Finnish markka1.00",
4458 "Finnish markkas1.00",
4459 "CHF1.00",
4460 "French Franc1.00",
4461 "French Gold Franc1.00",
4462 "French UIC-Franc1.00",
4463 "French UIC-franc1.00",
4464 "French UIC-francs1.00",
4465 "French franc1.00",
4466 "French francs1.00",
4467 "French gold franc1.00",
4468 "French gold francs1.00",
4469 "GBP1.00",
4470 "GEK1.00",
4471 "GEK1.00",
4472 "GEL1.00",
4473 "GHC1.00",
4474 "GHC1.00",
4475 "GHS1.00",
4476 "GIP1.00",
4477 "GIP1.00",
4478 "GMD1.00",
4479 "GMD1.00",
4480 "GNF1.00",
4481 "GNS1.00",
4482 "GNS1.00",
4483 "GQE1.00",
4484 "GQE1.00",
4485 "GRD1.00",
4486 "GRD1.00",
4487 "GTQ1.00",
4488 "GWE1.00",
4489 "GWE1.00",
4490 "GWP1.00",
4491 "GWP1.00",
4492 "GYD1.00",
4493 "Gambian Dalasi1.00",
4494 "Gambian dalasi1.00",
4495 "Gambian dalasis1.00",
4496 "Georgian Kupon Larit1.00",
4497 "Georgian Lari1.00",
4498 "Georgian kupon larit1.00",
4499 "Georgian kupon larits1.00",
4500 "Georgian lari1.00",
4501 "Georgian laris1.00",
4502 "Ghanaian Cedi (1979\\u20132007)1.00",
4503 "Ghanaian Cedi1.00",
4504 "Ghanaian cedi (1979\\u20132007)1.00",
4505 "Ghanaian cedi1.00",
4506 "Ghanaian cedis (1979\\u20132007)1.00",
4507 "Ghanaian cedis1.00",
4508 "Gibraltar Pound1.00",
4509 "Gibraltar pound1.00",
4510 "Gibraltar pounds1.00",
4511 "Gold1.00",
4512 "Gold1.00",
4513 "Greek Drachma1.00",
4514 "Greek drachma1.00",
4515 "Greek drachmas1.00",
4516 "Guatemalan Quetzal1.00",
4517 "Guatemalan quetzal1.00",
4518 "Guatemalan quetzals1.00",
4519 "Guinean Franc1.00",
4520 "Guinean Syli1.00",
4521 "Guinean franc1.00",
4522 "Guinean francs1.00",
4523 "Guinean syli1.00",
4524 "Guinean sylis1.00",
4525 "Guinea-Bissau Peso1.00",
4526 "Guinea-Bissau peso1.00",
4527 "Guinea-Bissau pesos1.00",
4528 "Guyanaese Dollar1.00",
4529 "Guyanaese dollar1.00",
4530 "Guyanaese dollars1.00",
4531 "HK$1.00",
4532 "HKD1.00",
4533 "HNL1.00",
4534 "HRD1.00",
4535 "HRD1.00",
4536 "HRK1.00",
4537 "HRK1.00",
4538 "HTG1.00",
4539 "HTG1.00",
4540 "HUF1.00",
4541 "Haitian Gourde1.00",
4542 "Haitian gourde1.00",
4543 "Haitian gourdes1.00",
4544 "Honduran Lempira1.00",
4545 "Honduran lempira1.00",
4546 "Honduran lempiras1.00",
4547 "Hong Kong Dollar1.00",
4548 "Hong Kong dollar1.00",
4549 "Hong Kong dollars1.00",
4550 "Hungarian Forint1.00",
4551 "Hungarian forint1.00",
4552 "Hungarian forints1.00",
4553 "IDR1.00",
4554 "IEP1.00",
4555 "ILP1.00",
4556 "ILP1.00",
4557 "ILS1.00",
4558 "INR1.00",
4559 "IQD1.00",
4560 "IRR1.00",
4561 "ISK1.00",
4562 "ISK1.00",
4563 "ITL1.00",
4564 "Icelandic Kr\\u00f3na1.00",
4565 "Icelandic kr\\u00f3na1.00",
4566 "Icelandic kr\\u00f3nur1.00",
4567 "Indian Rupee1.00",
4568 "Indian rupee1.00",
4569 "Indian rupees1.00",
4570 "Indonesian Rupiah1.00",
4571 "Indonesian rupiah1.00",
4572 "Indonesian rupiahs1.00",
4573 "Iranian Rial1.00",
4574 "Iranian rial1.00",
4575 "Iranian rials1.00",
4576 "Iraqi Dinar1.00",
4577 "Iraqi dinar1.00",
4578 "Iraqi dinars1.00",
4579 "Irish Pound1.00",
4580 "Irish pound1.00",
4581 "Irish pounds1.00",
4582 "Israeli Pound1.00",
4583 "Israeli new shekel1.00",
4584 "Israeli pound1.00",
4585 "Israeli pounds1.00",
4586 "Italian Lira1.00",
4587 "Italian lira1.00",
4588 "Italian liras1.00",
4589 "JMD1.00",
4590 "JOD1.00",
4591 "JPY1.00",
4592 "Jamaican Dollar1.00",
4593 "Jamaican dollar1.00",
4594 "Jamaican dollars1.00",
4595 "Japanese Yen1.00",
4596 "Japanese yen1.00",
4597 "Jordanian Dinar1.00",
4598 "Jordanian dinar1.00",
4599 "Jordanian dinars1.00",
4600 "KES1.00",
4601 "KGS1.00",
4602 "KHR1.00",
4603 "KMF1.00",
4604 "KPW1.00",
4605 "KPW1.00",
4606 "KRW1.00",
4607 "KWD1.00",
4608 "KYD1.00",
4609 "KYD1.00",
4610 "KZT1.00",
4611 "Kazakhstani Tenge1.00",
4612 "Kazakhstani tenge1.00",
4613 "Kazakhstani tenges1.00",
4614 "Kenyan Shilling1.00",
4615 "Kenyan shilling1.00",
4616 "Kenyan shillings1.00",
4617 "Kuwaiti Dinar1.00",
4618 "Kuwaiti dinar1.00",
4619 "Kuwaiti dinars1.00",
4620 "Kyrgystani Som1.00",
4621 "Kyrgystani som1.00",
4622 "Kyrgystani soms1.00",
4623 "HNL1.00",
4624 "LAK1.00",
4625 "LAK1.00",
4626 "LBP1.00",
4627 "LKR1.00",
4628 "LRD1.00",
4629 "LRD1.00",
4630 "LSL1.00",
4631 "LTL1.00",
4632 "LTL1.00",
4633 "LTT1.00",
4634 "LTT1.00",
4635 "LUC1.00",
4636 "LUC1.00",
4637 "LUF1.00",
4638 "LUF1.00",
4639 "LUL1.00",
4640 "LUL1.00",
4641 "LVL1.00",
4642 "LVL1.00",
4643 "LVR1.00",
4644 "LVR1.00",
4645 "LYD1.00",
4646 "Laotian Kip1.00",
4647 "Laotian kip1.00",
4648 "Laotian kips1.00",
4649 "Latvian Lats1.00",
4650 "Latvian Ruble1.00",
4651 "Latvian lats1.00",
4652 "Latvian lati1.00",
4653 "Latvian ruble1.00",
4654 "Latvian rubles1.00",
4655 "Lebanese Pound1.00",
4656 "Lebanese pound1.00",
4657 "Lebanese pounds1.00",
4658 "Lesotho Loti1.00",
4659 "Lesotho loti1.00",
4660 "Lesotho lotis1.00",
4661 "Liberian Dollar1.00",
4662 "Liberian dollar1.00",
4663 "Liberian dollars1.00",
4664 "Libyan Dinar1.00",
4665 "Libyan dinar1.00",
4666 "Libyan dinars1.00",
4667 "Lithuanian Litas1.00",
4668 "Lithuanian Talonas1.00",
4669 "Lithuanian litas1.00",
4670 "Lithuanian litai1.00",
4671 "Lithuanian talonas1.00",
4672 "Lithuanian talonases1.00",
4673 "Luxembourgian Convertible Franc1.00",
4674 "Luxembourg Financial Franc1.00",
4675 "Luxembourgian Franc1.00",
4676 "Luxembourgian convertible franc1.00",
4677 "Luxembourgian convertible francs1.00",
4678 "Luxembourg financial franc1.00",
4679 "Luxembourg financial francs1.00",
4680 "Luxembourgian franc1.00",
4681 "Luxembourgian francs1.00",
4682 "MAD1.00",
4683 "MAD1.00",
4684 "MAF1.00",
4685 "MAF1.00",
4686 "MDL1.00",
4687 "MDL1.00",
4688 "MX$1.00",
4689 "MGA1.00",
4690 "MGA1.00",
4691 "MGF1.00",
4692 "MGF1.00",
4693 "MKD1.00",
4694 "MLF1.00",
4695 "MLF1.00",
4696 "MMK1.00",
4697 "MMK1.00",
4698 "MNT1.00",
4699 "MOP1.00",
4700 "MOP1.00",
4701 "MRO1.00",
4702 "MTL1.00",
4703 "MTP1.00",
4704 "MTP1.00",
4705 "MUR1.00",
4706 "MUR1.00",
4707 "MVR1.00",
4708 "MVR1.00",
4709 "MWK1.00",
4710 "MXN1.00",
4711 "MXP1.00",
4712 "MXP1.00",
4713 "MXV1.00",
4714 "MXV1.00",
4715 "MYR1.00",
4716 "MZE1.00",
4717 "MZE1.00",
4718 "MZM1.00",
4719 "MZN1.00",
4720 "Macanese Pataca1.00",
4721 "Macanese pataca1.00",
4722 "Macanese patacas1.00",
4723 "Macedonian Denar1.00",
4724 "Macedonian denar1.00",
4725 "Macedonian denari1.00",
4726 "Malagasy Ariaries1.00",
4727 "Malagasy Ariary1.00",
4728 "Malagasy Ariary1.00",
4729 "Malagasy Franc1.00",
4730 "Malagasy franc1.00",
4731 "Malagasy francs1.00",
4732 "Malawian Kwacha1.00",
4733 "Malawian Kwacha1.00",
4734 "Malawian Kwachas1.00",
4735 "Malaysian Ringgit1.00",
4736 "Malaysian ringgit1.00",
4737 "Malaysian ringgits1.00",
4738 "Maldivian Rufiyaa1.00",
4739 "Maldivian rufiyaa1.00",
4740 "Maldivian rufiyaas1.00",
4741 "Malian Franc1.00",
4742 "Malian franc1.00",
4743 "Malian francs1.00",
4744 "Maltese Lira1.00",
4745 "Maltese Pound1.00",
4746 "Maltese lira1.00",
4747 "Maltese lira1.00",
4748 "Maltese pound1.00",
4749 "Maltese pounds1.00",
4750 "Mauritanian Ouguiya1.00",
4751 "Mauritanian ouguiya1.00",
4752 "Mauritanian ouguiyas1.00",
4753 "Mauritian Rupee1.00",
4754 "Mauritian rupee1.00",
4755 "Mauritian rupees1.00",
4756 "Mexican Peso1.00",
4757 "Mexican Silver Peso (1861\\u20131992)1.00",
4758 "Mexican Investment Unit1.00",
4759 "Mexican peso1.00",
4760 "Mexican pesos1.00",
4761 "Mexican silver peso (1861\\u20131992)1.00",
4762 "Mexican silver pesos (1861\\u20131992)1.00",
4763 "Mexican investment unit1.00",
4764 "Mexican investment units1.00",
4765 "Moldovan Leu1.00",
4766 "Moldovan leu1.00",
4767 "Moldovan lei1.00",
4768 "Mongolian Tugrik1.00",
4769 "Mongolian tugrik1.00",
4770 "Mongolian tugriks1.00",
4771 "Moroccan Dirham1.00",
4772 "Moroccan Franc1.00",
4773 "Moroccan dirham1.00",
4774 "Moroccan dirhams1.00",
4775 "Moroccan franc1.00",
4776 "Moroccan francs1.00",
4777 "Mozambican Escudo1.00",
4778 "Mozambican Metical1.00",
4779 "Mozambican escudo1.00",
4780 "Mozambican escudos1.00",
4781 "Mozambican metical1.00",
4782 "Mozambican meticals1.00",
4783 "Myanmar Kyat1.00",
4784 "Myanmar kyat1.00",
4785 "Myanmar kyats1.00",
4786 "NAD1.00",
4787 "NGN1.00",
4788 "NIC1.00",
4789 "NIO1.00",
4790 "NIO1.00",
4791 "NLG1.00",
4792 "NLG1.00",
4793 "NOK1.00",
4794 "NPR1.00",
4795 "NT$1.00",
4796 "NZ$1.00",
4797 "NZD1.00",
4798 "Namibian Dollar1.00",
4799 "Namibian dollar1.00",
4800 "Namibian dollars1.00",
4801 "Nepalese Rupee1.00",
4802 "Nepalese rupee1.00",
4803 "Nepalese rupees1.00",
4804 "Netherlands Antillean Guilder1.00",
4805 "Netherlands Antillean guilder1.00",
4806 "Netherlands Antillean guilders1.00",
4807 "Dutch Guilder1.00",
4808 "Dutch guilder1.00",
4809 "Dutch guilders1.00",
4810 "Israeli New Shekel1.00",
4811 "Israeli New Shekels1.00",
4812 "New Zealand Dollar1.00",
4813 "New Zealand dollar1.00",
4814 "New Zealand dollars1.00",
4815 "Nicaraguan C\\u00f3rdoba1.00",
4816 "Nicaraguan C\\u00f3rdoba (1988\\u20131991)1.00",
4817 "Nicaraguan c\\u00f3rdoba1.00",
4818 "Nicaraguan c\\u00f3rdobas1.00",
4819 "Nicaraguan c\\u00f3rdoba (1988\\u20131991)1.00",
4820 "Nicaraguan c\\u00f3rdobas (1988\\u20131991)1.00",
4821 "Nigerian Naira1.00",
4822 "Nigerian naira1.00",
4823 "Nigerian nairas1.00",
4824 "North Korean Won1.00",
4825 "North Korean won1.00",
4826 "North Korean won1.00",
4827 "Norwegian Krone1.00",
4828 "Norwegian krone1.00",
4829 "Norwegian kroner1.00",
4830 "OMR1.00",
4831 "Mozambican Metical (1980\\u20132006)1.00",
4832 "Mozambican metical (1980\\u20132006)1.00",
4833 "Mozambican meticals (1980\\u20132006)1.00",
4834 "Romanian Lei (1952\\u20132006)1.00",
4835 "Romanian Leu (1952\\u20132006)1.00",
4836 "Romanian leu (1952\\u20132006)1.00",
4837 "Serbian Dinar (2002\\u20132006)1.00",
4838 "Serbian dinar (2002\\u20132006)1.00",
4839 "Serbian dinars (2002\\u20132006)1.00",
4840 "Sudanese Dinar (1992\\u20132007)1.00",
4841 "Sudanese Pound (1957\\u20131998)1.00",
4842 "Sudanese dinar (1992\\u20132007)1.00",
4843 "Sudanese dinars (1992\\u20132007)1.00",
4844 "Sudanese pound (1957\\u20131998)1.00",
4845 "Sudanese pounds (1957\\u20131998)1.00",
4846 "Turkish Lira (1922\\u20132005)1.00",
4847 "Turkish Lira (1922\\u20132005)1.00",
4848 "Omani Rial1.00",
4849 "Omani rial1.00",
4850 "Omani rials1.00",
4851 "PAB1.00",
4852 "PAB1.00",
4853 "PEI1.00",
4854 "PEI1.00",
4855 "PEN1.00",
4856 "PEN1.00",
4857 "PES1.00",
4858 "PES1.00",
4859 "PGK1.00",
4860 "PGK1.00",
4861 "PHP1.00",
4862 "PKR1.00",
4863 "PLN1.00",
4864 "PLZ1.00",
4865 "PLZ1.00",
4866 "PTE1.00",
4867 "PTE1.00",
4868 "PYG1.00",
4869 "Pakistani Rupee1.00",
4870 "Pakistani rupee1.00",
4871 "Pakistani rupees1.00",
4872 "Palladium1.00",
4873 "Palladium1.00",
4874 "Panamanian Balboa1.00",
4875 "Panamanian balboa1.00",
4876 "Panamanian balboas1.00",
4877 "Papua New Guinean Kina1.00",
4878 "Papua New Guinean kina1.00",
4879 "Papua New Guinean kina1.00",
4880 "Paraguayan Guarani1.00",
4881 "Paraguayan guarani1.00",
4882 "Paraguayan guaranis1.00",
4883 "Peruvian Inti1.00",
4884 "Peruvian Sol1.00",
4885 "Peruvian Sol (1863\\u20131965)1.00",
4886 "Peruvian inti1.00",
4887 "Peruvian intis1.00",
4888 "Peruvian sol1.00",
4889 "Peruvian soles1.00",
4890 "Peruvian sol (1863\\u20131965)1.00",
4891 "Peruvian soles (1863\\u20131965)1.00",
4892 "Philippine Piso1.00",
4893 "Philippine piso1.00",
4894 "Philippine pisos1.00",
4895 "Platinum1.00",
4896 "Platinum1.00",
4897 "Polish Zloty (1950\\u20131995)1.00",
4898 "Polish Zloty1.00",
4899 "Polish zlotys1.00",
4900 "Polish zloty (PLZ)1.00",
4901 "Polish zloty1.00",
4902 "Polish zlotys (PLZ)1.00",
4903 "Portuguese Escudo1.00",
4904 "Portuguese Guinea Escudo1.00",
4905 "Portuguese Guinea escudo1.00",
4906 "Portuguese Guinea escudos1.00",
4907 "Portuguese escudo1.00",
4908 "Portuguese escudos1.00",
4909 "GTQ1.00",
4910 "QAR1.00",
4911 "Qatari Rial1.00",
4912 "Qatari rial1.00",
4913 "Qatari rials1.00",
4914 "RHD1.00",
4915 "RHD1.00",
4916 "RINET Funds1.00",
4917 "RINET Funds1.00",
4918 "CN\\u00a51.00",
4919 "ROL1.00",
4920 "ROL1.00",
4921 "RON1.00",
4922 "RON1.00",
4923 "RSD1.00",
4924 "RSD1.00",
4925 "RUB1.00",
4926 "RUR1.00",
4927 "RUR1.00",
4928 "RWF1.00",
4929 "RWF1.00",
4930 "Rhodesian Dollar1.00",
4931 "Rhodesian dollar1.00",
4932 "Rhodesian dollars1.00",
4933 "Romanian Leu1.00",
4934 "Romanian lei1.00",
4935 "Romanian leu1.00",
4936 "Russian Ruble (1991\\u20131998)1.00",
4937 "Russian Ruble1.00",
4938 "Russian ruble (1991\\u20131998)1.00",
4939 "Russian ruble1.00",
4940 "Russian rubles (1991\\u20131998)1.00",
4941 "Russian rubles1.00",
4942 "Rwandan Franc1.00",
4943 "Rwandan franc1.00",
4944 "Rwandan francs1.00",
4945 "SAR1.00",
4946 "SBD1.00",
4947 "SCR1.00",
4948 "SDD1.00",
4949 "SDD1.00",
4950 "SDG1.00",
4951 "SDG1.00",
4952 "SDP1.00",
4953 "SDP1.00",
4954 "SEK1.00",
4955 "SGD1.00",
4956 "SHP1.00",
4957 "SHP1.00",
4958 "SIT1.00",
4959 "SIT1.00",
4960 "SKK1.00",
4961 "SLL1.00",
4962 "SLL1.00",
4963 "SOS1.00",
4964 "SRD1.00",
4965 "SRD1.00",
4966 "SRG1.00",
4967 "STD1.00",
4968 "SUR1.00",
4969 "SUR1.00",
4970 "SVC1.00",
4971 "SVC1.00",
4972 "SYP1.00",
4973 "SZL1.00",
4974 "St. Helena Pound1.00",
4975 "St. Helena pound1.00",
4976 "St. Helena pounds1.00",
4977 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra1.00",
4978 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra1.00",
4979 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras1.00",
4980 "Saudi Riyal1.00",
4981 "Saudi riyal1.00",
4982 "Saudi riyals1.00",
4983 "Serbian Dinar1.00",
4984 "Serbian dinar1.00",
4985 "Serbian dinars1.00",
4986 "Seychellois Rupee1.00",
4987 "Seychellois rupee1.00",
4988 "Seychellois rupees1.00",
4989 "Sierra Leonean Leone1.00",
4990 "Sierra Leonean leone1.00",
4991 "Sierra Leonean leones1.00",
4992 "Silver1.00",
4993 "Silver1.00",
4994 "Singapore Dollar1.00",
4995 "Singapore dollar1.00",
4996 "Singapore dollars1.00",
4997 "Slovak Koruna1.00",
4998 "Slovak koruna1.00",
4999 "Slovak korunas1.00",
5000 "Slovenian Tolar1.00",
5001 "Slovenian tolar1.00",
5002 "Slovenian tolars1.00",
5003 "Solomon Islands Dollar1.00",
5004 "Solomon Islands dollar1.00",
5005 "Solomon Islands dollars1.00",
5006 "Somali Shilling1.00",
5007 "Somali shilling1.00",
5008 "Somali shillings1.00",
5009 "South African Rand (financial)1.00",
5010 "South African Rand1.00",
5011 "South African rand (financial)1.00",
5012 "South African rand1.00",
5013 "South African rands (financial)1.00",
5014 "South African rand1.00",
5015 "South Korean Won1.00",
5016 "South Korean won1.00",
5017 "South Korean won1.00",
5018 "Soviet Rouble1.00",
5019 "Soviet rouble1.00",
5020 "Soviet roubles1.00",
5021 "Spanish Peseta (A account)1.00",
5022 "Spanish Peseta (convertible account)1.00",
5023 "Spanish Peseta1.00",
5024 "Spanish peseta (A account)1.00",
5025 "Spanish peseta (convertible account)1.00",
5026 "Spanish peseta1.00",
5027 "Spanish pesetas (A account)1.00",
5028 "Spanish pesetas (convertible account)1.00",
5029 "Spanish pesetas1.00",
5030 "Special Drawing Rights1.00",
5031 "Sri Lankan Rupee1.00",
5032 "Sri Lankan rupee1.00",
5033 "Sri Lankan rupees1.00",
5034 "Sudanese Pound1.00",
5035 "Sudanese pound1.00",
5036 "Sudanese pounds1.00",
5037 "Surinamese Dollar1.00",
5038 "Surinamese dollar1.00",
5039 "Surinamese dollars1.00",
5040 "Surinamese Guilder1.00",
5041 "Surinamese guilder1.00",
5042 "Surinamese guilders1.00",
5043 "Swazi Lilangeni1.00",
5044 "Swazi lilangeni1.00",
5045 "Swazi emalangeni1.00",
5046 "Swedish Krona1.00",
5047 "Swedish krona1.00",
5048 "Swedish kronor1.00",
5049 "Swiss Franc1.00",
5050 "Swiss franc1.00",
5051 "Swiss francs1.00",
5052 "Syrian Pound1.00",
5053 "Syrian pound1.00",
5054 "Syrian pounds1.00",
5055 "THB1.00",
5056 "TJR1.00",
5057 "TJR1.00",
5058 "TJS1.00",
5059 "TJS1.00",
5060 "TMM1.00",
5061 "TMM1.00",
5062 "TND1.00",
5063 "TND1.00",
5064 "TOP1.00",
5065 "TPE1.00",
5066 "TPE1.00",
5067 "TRL1.00",
5068 "TRY1.00",
5069 "TRY1.00",
5070 "TTD1.00",
5071 "TWD1.00",
5072 "TZS1.00",
5073 "New Taiwan Dollar1.00",
5074 "New Taiwan dollar1.00",
5075 "New Taiwan dollars1.00",
5076 "Tajikistani Ruble1.00",
5077 "Tajikistani Somoni1.00",
5078 "Tajikistani ruble1.00",
5079 "Tajikistani rubles1.00",
5080 "Tajikistani somoni1.00",
5081 "Tajikistani somonis1.00",
5082 "Tanzanian Shilling1.00",
5083 "Tanzanian shilling1.00",
5084 "Tanzanian shillings1.00",
5085 "Testing Currency Code1.00",
5086 "Testing Currency Code1.00",
5087 "Thai Baht1.00",
5088 "Thai baht1.00",
5089 "Thai baht1.00",
5090 "Timorese Escudo1.00",
5091 "Timorese escudo1.00",
5092 "Timorese escudos1.00",
5093 "Tongan Pa\\u02bbanga1.00",
5094 "Tongan pa\\u02bbanga1.00",
5095 "Tongan pa\\u02bbanga1.00",
5096 "Trinidad & Tobago Dollar1.00",
5097 "Trinidad & Tobago dollar1.00",
5098 "Trinidad & Tobago dollars1.00",
5099 "Tunisian Dinar1.00",
5100 "Tunisian dinar1.00",
5101 "Tunisian dinars1.00",
5102 "Turkish Lira1.00",
5103 "Turkish Lira1.00",
5104 "Turkish lira1.00",
5105 "Turkmenistani Manat1.00",
5106 "Turkmenistani manat1.00",
5107 "Turkmenistani manat1.00",
5108 "UAE dirham1.00",
5109 "UAE dirhams1.00",
5110 "UAH1.00",
5111 "UAK1.00",
5112 "UAK1.00",
5113 "UGS1.00",
5114 "UGS1.00",
5115 "UGX1.00",
5116 "US Dollar (Next day)1.00",
5117 "US Dollar (Same day)1.00",
5118 "US Dollar1.00",
5119 "US dollar (next day)1.00",
5120 "US dollar (same day)1.00",
5121 "US dollar1.00",
5122 "US dollars (next day)1.00",
5123 "US dollars (same day)1.00",
5124 "US dollars1.00",
5125 "USD1.00",
5126 "USN1.00",
5127 "USN1.00",
5128 "USS1.00",
5129 "USS1.00",
5130 "UYI1.00",
5131 "UYI1.00",
5132 "UYP1.00",
5133 "UYP1.00",
5134 "UYU1.00",
5135 "UZS1.00",
5136 "UZS1.00",
5137 "Ugandan Shilling (1966\\u20131987)1.00",
5138 "Ugandan Shilling1.00",
5139 "Ugandan shilling (1966\\u20131987)1.00",
5140 "Ugandan shilling1.00",
5141 "Ugandan shillings (1966\\u20131987)1.00",
5142 "Ugandan shillings1.00",
5143 "Ukrainian Hryvnia1.00",
5144 "Ukrainian Karbovanets1.00",
5145 "Ukrainian hryvnia1.00",
5146 "Ukrainian hryvnias1.00",
5147 "Ukrainian karbovanets1.00",
5148 "Ukrainian karbovantsiv1.00",
5149 "Colombian Real Value Unit1.00",
5150 "United Arab Emirates Dirham1.00",
5151 "Unknown Currency1.00",
5152 "Uruguayan Peso (1975\\u20131993)1.00",
5153 "Uruguayan Peso1.00",
5154 "Uruguayan Peso (Indexed Units)1.00",
5155 "Uruguayan peso (1975\\u20131993)1.00",
5156 "Uruguayan peso (indexed units)1.00",
5157 "Uruguayan peso1.00",
5158 "Uruguayan pesos (1975\\u20131993)1.00",
5159 "Uruguayan pesos (indexed units)1.00",
5160 "Uruguayan pesos1.00",
5161 "Uzbekistani Som1.00",
5162 "Uzbekistani som1.00",
5163 "Uzbekistani som1.00",
5164 "VEB1.00",
5165 "VEF1.00",
5166 "VND1.00",
5167 "VUV1.00",
5168 "Vanuatu Vatu1.00",
5169 "Vanuatu vatu1.00",
5170 "Vanuatu vatus1.00",
5171 "Venezuelan Bol\\u00edvar1.00",
5172 "Venezuelan Bol\\u00edvar (1871\\u20132008)1.00",
5173 "Venezuelan bol\\u00edvar1.00",
5174 "Venezuelan bol\\u00edvars1.00",
5175 "Venezuelan bol\\u00edvar (1871\\u20132008)1.00",
5176 "Venezuelan bol\\u00edvars (1871\\u20132008)1.00",
5177 "Vietnamese Dong1.00",
5178 "Vietnamese dong1.00",
5179 "Vietnamese dong1.00",
5180 "WIR Euro1.00",
5181 "WIR Franc1.00",
5182 "WIR euro1.00",
5183 "WIR euros1.00",
5184 "WIR franc1.00",
5185 "WIR francs1.00",
5186 "WST1.00",
5187 "WST1.00",
5188 "Samoan Tala1.00",
5189 "Samoan tala1.00",
5190 "Samoan tala1.00",
5191 "XAF1.00",
5192 "XAF1.00",
5193 "XAG1.00",
5194 "XAG1.00",
5195 "XAU1.00",
5196 "XAU1.00",
5197 "XBA1.00",
5198 "XBA1.00",
5199 "XBB1.00",
5200 "XBB1.00",
5201 "XBC1.00",
5202 "XBC1.00",
5203 "XBD1.00",
5204 "XBD1.00",
5205 "XCD1.00",
5206 "XDR1.00",
5207 "XDR1.00",
5208 "XEU1.00",
5209 "XEU1.00",
5210 "XFO1.00",
5211 "XFO1.00",
5212 "XFU1.00",
5213 "XFU1.00",
5214 "XOF1.00",
5215 "XOF1.00",
5216 "XPD1.00",
5217 "XPD1.00",
5218 "XPF1.00",
5219 "XPT1.00",
5220 "XPT1.00",
5221 "XRE1.00",
5222 "XRE1.00",
5223 "XTS1.00",
5224 "XTS1.00",
5225 "XXX1.00",
5226 "XXX1.00",
5227 "YDD1.00",
5228 "YDD1.00",
5229 "YER1.00",
5230 "YUD1.00",
5231 "YUD1.00",
5232 "YUM1.00",
5233 "YUM1.00",
5234 "YUN1.00",
5235 "YUN1.00",
5236 "Yemeni Dinar1.00",
5237 "Yemeni Rial1.00",
5238 "Yemeni dinar1.00",
5239 "Yemeni dinars1.00",
5240 "Yemeni rial1.00",
5241 "Yemeni rials1.00",
5242 "Yugoslavian Convertible Dinar (1990\\u20131992)1.00",
5243 "Yugoslavian Hard Dinar (1966\\u20131990)1.00",
5244 "Yugoslavian New Dinar (1994\\u20132002)1.00",
5245 "Yugoslavian convertible dinar (1990\\u20131992)1.00",
5246 "Yugoslavian convertible dinars (1990\\u20131992)1.00",
5247 "Yugoslavian hard dinar (1966\\u20131990)1.00",
5248 "Yugoslavian hard dinars (1966\\u20131990)1.00",
5249 "Yugoslavian new dinar (1994\\u20132002)1.00",
5250 "Yugoslavian new dinars (1994\\u20132002)1.00",
5251 "ZAL1.00",
5252 "ZAL1.00",
5253 "ZAR1.00",
5254 "ZMK1.00",
5255 "ZMK1.00",
5256 "ZRN1.00",
5257 "ZRN1.00",
5258 "ZRZ1.00",
5259 "ZRZ1.00",
5260 "ZWD1.00",
5261 "Zairean New Zaire (1993\\u20131998)1.00",
5262 "Zairean Zaire (1971\\u20131993)1.00",
5263 "Zairean new zaire (1993\\u20131998)1.00",
5264 "Zairean new zaires (1993\\u20131998)1.00",
5265 "Zairean zaire (1971\\u20131993)1.00",
5266 "Zairean zaires (1971\\u20131993)1.00",
5267 "Zambian Kwacha1.00",
5268 "Zambian kwacha1.00",
5269 "Zambian kwachas1.00",
5270 "Zimbabwean Dollar (1980\\u20132008)1.00",
5271 "Zimbabwean dollar (1980\\u20132008)1.00",
5272 "Zimbabwean dollars (1980\\u20132008)1.00",
5273 "euro1.00",
5274 "euros1.00",
5275 "Turkish lira (1922\\u20132005)1.00",
5276 "special drawing rights1.00",
5277 "Colombian real value unit1.00",
5278 "Colombian real value units1.00",
5279 "unknown currency1.00",
5280 "\\u00a31.00",
5281 "\\u00a51.00",
5282 "\\u20ab1.00",
5283 "\\u20aa1.00",
5284 "\\u20ac1.00",
5285 "\\u20b91.00",
5286 //
5287 // Following has extra text, should be parsed correctly too
5288 "$1.00 random",
5289 "USD1.00 random",
5290 "1.00 US dollar random",
5291 "1.00 US dollars random",
5292 "1.00 Afghan Afghani random",
5293 "1.00 Afghan Afghani random",
5294 "1.00 Afghan Afghanis (1927\\u20131992) random",
5295 "1.00 Afghan Afghanis random",
5296 "1.00 Albanian Lek random",
5297 "1.00 Albanian lek random",
5298 "1.00 Albanian lek\\u00eb random",
5299 "1.00 Algerian Dinar random",
5300 "1.00 Algerian dinar random",
5301 "1.00 Algerian dinars random",
5302 "1.00 Andorran Peseta random",
5303 "1.00 Andorran peseta random",
5304 "1.00 Andorran pesetas random",
5305 "1.00 Angolan Kwanza (1977\\u20131990) random",
5306 "1.00 Angolan Readjusted Kwanza (1995\\u20131999) random",
5307 "1.00 Angolan Kwanza random",
5308 "1.00 Angolan New Kwanza (1990\\u20132000) random",
5309 "1.00 Angolan kwanza (1977\\u20131991) random",
5310 "1.00 Angolan readjusted kwanza (1995\\u20131999) random",
5311 "1.00 Angolan kwanza random",
5312 "1.00 Angolan kwanzas (1977\\u20131991) random",
5313 "1.00 Angolan readjusted kwanzas (1995\\u20131999) random",
5314 "1.00 Angolan kwanzas random",
5315 "1.00 Angolan new kwanza (1990\\u20132000) random",
5316 "1.00 Angolan new kwanzas (1990\\u20132000) random",
5317 "1.00 Argentine Austral random",
5318 "1.00 Argentine Peso (1983\\u20131985) random",
5319 "1.00 Argentine Peso random",
5320 "1.00 Argentine austral random",
5321 "1.00 Argentine australs random",
5322 "1.00 Argentine peso (1983\\u20131985) random",
5323 "1.00 Argentine peso random",
5324 "1.00 Argentine pesos (1983\\u20131985) random",
5325 "1.00 Argentine pesos random",
5326 "1.00 Armenian Dram random",
5327 "1.00 Armenian dram random",
5328 "1.00 Armenian drams random",
5329 "1.00 Aruban Florin random",
5330 "1.00 Aruban florin random",
5331 "1.00 Australian Dollar random",
5332 "1.00 Australian dollar random",
5333 "1.00 Australian dollars random",
5334 "1.00 Austrian Schilling random",
5335 "1.00 Austrian schilling random",
5336 "1.00 Austrian schillings random",
5337 "1.00 Azerbaijani Manat (1993\\u20132006) random",
5338 "1.00 Azerbaijani Manat random",
5339 "1.00 Azerbaijani manat (1993\\u20132006) random",
5340 "1.00 Azerbaijani manat random",
5341 "1.00 Azerbaijani manats (1993\\u20132006) random",
5342 "1.00 Azerbaijani manats random",
5343 "1.00 Bahamian Dollar random",
5344 "1.00 Bahamian dollar random",
5345 "1.00 Bahamian dollars random",
5346 "1.00 Bahraini Dinar random",
5347 "1.00 Bahraini dinar random",
5348 "1.00 Bahraini dinars random",
5349 "1.00 Bangladeshi Taka random",
5350 "1.00 Bangladeshi taka random",
5351 "1.00 Bangladeshi takas random",
5352 "1.00 Barbadian Dollar random",
5353 "1.00 Barbadian dollar random",
5354 "1.00 Barbadian dollars random",
5355 "1.00 Belarusian Ruble (1994\\u20131999) random",
5356 "1.00 Belarusian Ruble random",
5357 "1.00 Belarusian ruble (1994\\u20131999) random",
5358 "1.00 Belarusian rubles (1994\\u20131999) random",
5359 "1.00 Belarusian ruble random",
5360 "1.00 Belarusian rubles random",
5361 "1.00 Belgian Franc (convertible) random",
5362 "1.00 Belgian Franc (financial) random",
5363 "1.00 Belgian Franc random",
5364 "1.00 Belgian franc (convertible) random",
5365 "1.00 Belgian franc (financial) random",
5366 "1.00 Belgian franc random",
5367 "1.00 Belgian francs (convertible) random",
5368 "1.00 Belgian francs (financial) random",
5369 "1.00 Belgian francs random",
5370 "1.00 Belize Dollar random",
5371 "1.00 Belize dollar random",
5372 "1.00 Belize dollars random",
5373 "1.00 Bermudan Dollar random",
5374 "1.00 Bermudan dollar random",
5375 "1.00 Bermudan dollars random",
5376 "1.00 Bhutanese Ngultrum random",
5377 "1.00 Bhutanese ngultrum random",
5378 "1.00 Bhutanese ngultrums random",
5379 "1.00 Bolivian Mvdol random",
5380 "1.00 Bolivian Peso random",
5381 "1.00 Bolivian mvdol random",
5382 "1.00 Bolivian mvdols random",
5383 "1.00 Bolivian peso random",
5384 "1.00 Bolivian pesos random",
5385 "1.00 Bolivian Boliviano random",
5386 "1.00 Bolivian Boliviano random",
5387 "1.00 Bolivian Bolivianos random",
5388 "1.00 Bosnia-Herzegovina Convertible Mark random",
5389 "1.00 Bosnia-Herzegovina Dinar (1992\\u20131994) random",
5390 "1.00 Bosnia-Herzegovina convertible mark random",
5391 "1.00 Bosnia-Herzegovina convertible marks random",
5392 "1.00 Bosnia-Herzegovina dinar (1992\\u20131994) random",
5393 "1.00 Bosnia-Herzegovina dinars (1992\\u20131994) random",
5394 "1.00 Botswanan Pula random",
5395 "1.00 Botswanan pula random",
5396 "1.00 Botswanan pulas random",
5397 "1.00 Brazilian New Cruzado (1989\\u20131990) random",
5398 "1.00 Brazilian Cruzado (1986\\u20131989) random",
5399 "1.00 Brazilian Cruzeiro (1990\\u20131993) random",
5400 "1.00 Brazilian New Cruzeiro (1967\\u20131986) random",
5401 "1.00 Brazilian Cruzeiro (1993\\u20131994) random",
5402 "1.00 Brazilian Real random",
5403 "1.00 Brazilian new cruzado (1989\\u20131990) random",
5404 "1.00 Brazilian new cruzados (1989\\u20131990) random",
5405 "1.00 Brazilian cruzado (1986\\u20131989) random",
5406 "1.00 Brazilian cruzados (1986\\u20131989) random",
5407 "1.00 Brazilian cruzeiro (1990\\u20131993) random",
5408 "1.00 Brazilian new cruzeiro (1967\\u20131986) random",
5409 "1.00 Brazilian cruzeiro (1993\\u20131994) random",
5410 "1.00 Brazilian cruzeiros (1990\\u20131993) random",
5411 "1.00 Brazilian new cruzeiros (1967\\u20131986) random",
5412 "1.00 Brazilian cruzeiros (1993\\u20131994) random",
5413 "1.00 Brazilian real random",
5414 "1.00 Brazilian reals random",
5415 "1.00 British Pound random",
5416 "1.00 British pound random",
5417 "1.00 British pounds random",
5418 "1.00 Brunei Dollar random",
5419 "1.00 Brunei dollar random",
5420 "1.00 Brunei dollars random",
5421 "1.00 Bulgarian Hard Lev random",
5422 "1.00 Bulgarian Lev random",
5423 "1.00 Bulgarian Leva random",
5424 "1.00 Bulgarian hard lev random",
5425 "1.00 Bulgarian hard leva random",
5426 "1.00 Bulgarian lev random",
5427 "1.00 Burmese Kyat random",
5428 "1.00 Burmese kyat random",
5429 "1.00 Burmese kyats random",
5430 "1.00 Burundian Franc random",
5431 "1.00 Burundian franc random",
5432 "1.00 Burundian francs random",
5433 "1.00 Cambodian Riel random",
5434 "1.00 Cambodian riel random",
5435 "1.00 Cambodian riels random",
5436 "1.00 Canadian Dollar random",
5437 "1.00 Canadian dollar random",
5438 "1.00 Canadian dollars random",
5439 "1.00 Cape Verdean Escudo random",
5440 "1.00 Cape Verdean escudo random",
5441 "1.00 Cape Verdean escudos random",
5442 "1.00 Cayman Islands Dollar random",
5443 "1.00 Cayman Islands dollar random",
5444 "1.00 Cayman Islands dollars random",
5445 "1.00 Chilean Peso random",
5446 "1.00 Chilean Unit of Account (UF) random",
5447 "1.00 Chilean peso random",
5448 "1.00 Chilean pesos random",
5449 "1.00 Chilean unit of account (UF) random",
5450 "1.00 Chilean units of account (UF) random",
5451 "1.00 Chinese Yuan random",
5452 "1.00 Chinese yuan random",
5453 "1.00 Colombian Peso random",
5454 "1.00 Colombian peso random",
5455 "1.00 Colombian pesos random",
5456 "1.00 Comorian Franc random",
5457 "1.00 Comorian franc random",
5458 "1.00 Comorian francs random",
5459 "1.00 Congolese Franc Congolais random",
5460 "1.00 Congolese franc Congolais random",
5461 "1.00 Congolese francs Congolais random",
5462 "1.00 Costa Rican Col\\u00f3n random",
5463 "1.00 Costa Rican col\\u00f3n random",
5464 "1.00 Costa Rican col\\u00f3ns random",
5465 "1.00 Croatian Dinar random",
5466 "1.00 Croatian Kuna random",
5467 "1.00 Croatian dinar random",
5468 "1.00 Croatian dinars random",
5469 "1.00 Croatian kuna random",
5470 "1.00 Croatian kunas random",
5471 "1.00 Cuban Peso random",
5472 "1.00 Cuban peso random",
5473 "1.00 Cuban pesos random",
5474 "1.00 Cypriot Pound random",
5475 "1.00 Cypriot pound random",
5476 "1.00 Cypriot pounds random",
5477 "1.00 Czech Koruna random",
5478 "1.00 Czech koruna random",
5479 "1.00 Czech korunas random",
5480 "1.00 Czechoslovak Hard Koruna random",
5481 "1.00 Czechoslovak hard koruna random",
5482 "1.00 Czechoslovak hard korunas random",
5483 "1.00 Danish Krone random",
5484 "1.00 Danish krone random",
5485 "1.00 Danish kroner random",
5486 "1.00 German Mark random",
5487 "1.00 German mark random",
5488 "1.00 German marks random",
5489 "1.00 Djiboutian Franc random",
5490 "1.00 Djiboutian franc random",
5491 "1.00 Djiboutian francs random",
5492 "1.00 Dominican Peso random",
5493 "1.00 Dominican peso random",
5494 "1.00 Dominican pesos random",
5495 "1.00 East Caribbean Dollar random",
5496 "1.00 East Caribbean dollar random",
5497 "1.00 East Caribbean dollars random",
5498 "1.00 East German Mark random",
5499 "1.00 East German mark random",
5500 "1.00 East German marks random",
5501 "1.00 Ecuadorian Sucre random",
5502 "1.00 Ecuadorian Unit of Constant Value random",
5503 "1.00 Ecuadorian sucre random",
5504 "1.00 Ecuadorian sucres random",
5505 "1.00 Ecuadorian unit of constant value random",
5506 "1.00 Ecuadorian units of constant value random",
5507 "1.00 Egyptian Pound random",
5508 "1.00 Egyptian pound random",
5509 "1.00 Egyptian pounds random",
5510 "1.00 Salvadoran Col\\u00f3n random",
5511 "1.00 Salvadoran col\\u00f3n random",
5512 "1.00 Salvadoran colones random",
5513 "1.00 Equatorial Guinean Ekwele random",
5514 "1.00 Equatorial Guinean ekwele random",
5515 "1.00 Eritrean Nakfa random",
5516 "1.00 Eritrean nakfa random",
5517 "1.00 Eritrean nakfas random",
5518 "1.00 Estonian Kroon random",
5519 "1.00 Estonian kroon random",
5520 "1.00 Estonian kroons random",
5521 "1.00 Ethiopian Birr random",
5522 "1.00 Ethiopian birr random",
5523 "1.00 Ethiopian birrs random",
5524 "1.00 European Composite Unit random",
5525 "1.00 European Currency Unit random",
5526 "1.00 European Monetary Unit random",
5527 "1.00 European Unit of Account (XBC) random",
5528 "1.00 European Unit of Account (XBD) random",
5529 "1.00 European composite unit random",
5530 "1.00 European composite units random",
5531 "1.00 European currency unit random",
5532 "1.00 European currency units random",
5533 "1.00 European monetary unit random",
5534 "1.00 European monetary units random",
5535 "1.00 European unit of account (XBC) random",
5536 "1.00 European unit of account (XBD) random",
5537 "1.00 European units of account (XBC) random",
5538 "1.00 European units of account (XBD) random",
5539 "1.00 Falkland Islands Pound random",
5540 "1.00 Falkland Islands pound random",
5541 "1.00 Falkland Islands pounds random",
5542 "1.00 Fijian Dollar random",
5543 "1.00 Fijian dollar random",
5544 "1.00 Fijian dollars random",
5545 "1.00 Finnish Markka random",
5546 "1.00 Finnish markka random",
5547 "1.00 Finnish markkas random",
5548 "1.00 French Franc random",
5549 "1.00 French Gold Franc random",
5550 "1.00 French UIC-Franc random",
5551 "1.00 French UIC-franc random",
5552 "1.00 French UIC-francs random",
5553 "1.00 French franc random",
5554 "1.00 French francs random",
5555 "1.00 French gold franc random",
5556 "1.00 French gold francs random",
5557 "1.00 Gambian Dalasi random",
5558 "1.00 Gambian dalasi random",
5559 "1.00 Gambian dalasis random",
5560 "1.00 Georgian Kupon Larit random",
5561 "1.00 Georgian Lari random",
5562 "1.00 Georgian kupon larit random",
5563 "1.00 Georgian kupon larits random",
5564 "1.00 Georgian lari random",
5565 "1.00 Georgian laris random",
5566 "1.00 Ghanaian Cedi (1979\\u20132007) random",
5567 "1.00 Ghanaian Cedi random",
5568 "1.00 Ghanaian cedi (1979\\u20132007) random",
5569 "1.00 Ghanaian cedi random",
5570 "1.00 Ghanaian cedis (1979\\u20132007) random",
5571 "1.00 Ghanaian cedis random",
5572 "1.00 Gibraltar Pound random",
5573 "1.00 Gibraltar pound random",
5574 "1.00 Gibraltar pounds random",
5575 "1.00 Gold random",
5576 "1.00 Gold random",
5577 "1.00 Greek Drachma random",
5578 "1.00 Greek drachma random",
5579 "1.00 Greek drachmas random",
5580 "1.00 Guatemalan Quetzal random",
5581 "1.00 Guatemalan quetzal random",
5582 "1.00 Guatemalan quetzals random",
5583 "1.00 Guinean Franc random",
5584 "1.00 Guinean Syli random",
5585 "1.00 Guinean franc random",
5586 "1.00 Guinean francs random",
5587 "1.00 Guinean syli random",
5588 "1.00 Guinean sylis random",
5589 "1.00 Guinea-Bissau Peso random",
5590 "1.00 Guinea-Bissau peso random",
5591 "1.00 Guinea-Bissau pesos random",
5592 "1.00 Guyanaese Dollar random",
5593 "1.00 Guyanaese dollar random",
5594 "1.00 Guyanaese dollars random",
5595 "1.00 Haitian Gourde random",
5596 "1.00 Haitian gourde random",
5597 "1.00 Haitian gourdes random",
5598 "1.00 Honduran Lempira random",
5599 "1.00 Honduran lempira random",
5600 "1.00 Honduran lempiras random",
5601 "1.00 Hong Kong Dollar random",
5602 "1.00 Hong Kong dollar random",
5603 "1.00 Hong Kong dollars random",
5604 "1.00 Hungarian Forint random",
5605 "1.00 Hungarian forint random",
5606 "1.00 Hungarian forints random",
5607 "1.00 Icelandic Kr\\u00f3na random",
5608 "1.00 Icelandic kr\\u00f3na random",
5609 "1.00 Icelandic kr\\u00f3nur random",
5610 "1.00 Indian Rupee random",
5611 "1.00 Indian rupee random",
5612 "1.00 Indian rupees random",
5613 "1.00 Indonesian Rupiah random",
5614 "1.00 Indonesian rupiah random",
5615 "1.00 Indonesian rupiahs random",
5616 "1.00 Iranian Rial random",
5617 "1.00 Iranian rial random",
5618 "1.00 Iranian rials random",
5619 "1.00 Iraqi Dinar random",
5620 "1.00 Iraqi dinar random",
5621 "1.00 Iraqi dinars random",
5622 "1.00 Irish Pound random",
5623 "1.00 Irish pound random",
5624 "1.00 Irish pounds random",
5625 "1.00 Israeli Pound random",
5626 "1.00 Israeli new shekel random",
5627 "1.00 Israeli pound random",
5628 "1.00 Israeli pounds random",
5629 "1.00 Italian Lira random",
5630 "1.00 Italian lira random",
5631 "1.00 Italian liras random",
5632 "1.00 Jamaican Dollar random",
5633 "1.00 Jamaican dollar random",
5634 "1.00 Jamaican dollars random",
5635 "1.00 Japanese Yen random",
5636 "1.00 Japanese yen random",
5637 "1.00 Jordanian Dinar random",
5638 "1.00 Jordanian dinar random",
5639 "1.00 Jordanian dinars random",
5640 "1.00 Kazakhstani Tenge random",
5641 "1.00 Kazakhstani tenge random",
5642 "1.00 Kazakhstani tenges random",
5643 "1.00 Kenyan Shilling random",
5644 "1.00 Kenyan shilling random",
5645 "1.00 Kenyan shillings random",
5646 "1.00 Kuwaiti Dinar random",
5647 "1.00 Kuwaiti dinar random",
5648 "1.00 Kuwaiti dinars random",
5649 "1.00 Kyrgystani Som random",
5650 "1.00 Kyrgystani som random",
5651 "1.00 Kyrgystani soms random",
5652 "1.00 Laotian Kip random",
5653 "1.00 Laotian kip random",
5654 "1.00 Laotian kips random",
5655 "1.00 Latvian Lats random",
5656 "1.00 Latvian Ruble random",
5657 "1.00 Latvian lats random",
5658 "1.00 Latvian lati random",
5659 "1.00 Latvian ruble random",
5660 "1.00 Latvian rubles random",
5661 "1.00 Lebanese Pound random",
5662 "1.00 Lebanese pound random",
5663 "1.00 Lebanese pounds random",
5664 "1.00 Lesotho Loti random",
5665 "1.00 Lesotho loti random",
5666 "1.00 Lesotho lotis random",
5667 "1.00 Liberian Dollar random",
5668 "1.00 Liberian dollar random",
5669 "1.00 Liberian dollars random",
5670 "1.00 Libyan Dinar random",
5671 "1.00 Libyan dinar random",
5672 "1.00 Libyan dinars random",
5673 "1.00 Lithuanian Litas random",
5674 "1.00 Lithuanian Talonas random",
5675 "1.00 Lithuanian litas random",
5676 "1.00 Lithuanian litai random",
5677 "1.00 Lithuanian talonas random",
5678 "1.00 Lithuanian talonases random",
5679 "1.00 Luxembourgian Convertible Franc random",
5680 "1.00 Luxembourg Financial Franc random",
5681 "1.00 Luxembourgian Franc random",
5682 "1.00 Luxembourgian convertible franc random",
5683 "1.00 Luxembourgian convertible francs random",
5684 "1.00 Luxembourg financial franc random",
5685 "1.00 Luxembourg financial francs random",
5686 "1.00 Luxembourgian franc random",
5687 "1.00 Luxembourgian francs random",
5688 "1.00 Macanese Pataca random",
5689 "1.00 Macanese pataca random",
5690 "1.00 Macanese patacas random",
5691 "1.00 Macedonian Denar random",
5692 "1.00 Macedonian denar random",
5693 "1.00 Macedonian denari random",
5694 "1.00 Malagasy Ariaries random",
5695 "1.00 Malagasy Ariary random",
5696 "1.00 Malagasy Ariary random",
5697 "1.00 Malagasy Franc random",
5698 "1.00 Malagasy franc random",
5699 "1.00 Malagasy francs random",
5700 "1.00 Malawian Kwacha random",
5701 "1.00 Malawian Kwacha random",
5702 "1.00 Malawian Kwachas random",
5703 "1.00 Malaysian Ringgit random",
5704 "1.00 Malaysian ringgit random",
5705 "1.00 Malaysian ringgits random",
5706 "1.00 Maldivian Rufiyaa random",
5707 "1.00 Maldivian rufiyaa random",
5708 "1.00 Maldivian rufiyaas random",
5709 "1.00 Malian Franc random",
5710 "1.00 Malian franc random",
5711 "1.00 Malian francs random",
5712 "1.00 Maltese Lira random",
5713 "1.00 Maltese Pound random",
5714 "1.00 Maltese lira random",
5715 "1.00 Maltese liras random",
5716 "1.00 Maltese pound random",
5717 "1.00 Maltese pounds random",
5718 "1.00 Mauritanian Ouguiya random",
5719 "1.00 Mauritanian ouguiya random",
5720 "1.00 Mauritanian ouguiyas random",
5721 "1.00 Mauritian Rupee random",
5722 "1.00 Mauritian rupee random",
5723 "1.00 Mauritian rupees random",
5724 "1.00 Mexican Peso random",
5725 "1.00 Mexican Silver Peso (1861\\u20131992) random",
5726 "1.00 Mexican Investment Unit random",
5727 "1.00 Mexican peso random",
5728 "1.00 Mexican pesos random",
5729 "1.00 Mexican silver peso (1861\\u20131992) random",
5730 "1.00 Mexican silver pesos (1861\\u20131992) random",
5731 "1.00 Mexican investment unit random",
5732 "1.00 Mexican investment units random",
5733 "1.00 Moldovan Leu random",
5734 "1.00 Moldovan leu random",
5735 "1.00 Moldovan lei random",
5736 "1.00 Mongolian Tugrik random",
5737 "1.00 Mongolian tugrik random",
5738 "1.00 Mongolian tugriks random",
5739 "1.00 Moroccan Dirham random",
5740 "1.00 Moroccan Franc random",
5741 "1.00 Moroccan dirham random",
5742 "1.00 Moroccan dirhams random",
5743 "1.00 Moroccan franc random",
5744 "1.00 Moroccan francs random",
5745 "1.00 Mozambican Escudo random",
5746 "1.00 Mozambican Metical random",
5747 "1.00 Mozambican escudo random",
5748 "1.00 Mozambican escudos random",
5749 "1.00 Mozambican metical random",
5750 "1.00 Mozambican meticals random",
5751 "1.00 Myanmar Kyat random",
5752 "1.00 Myanmar kyat random",
5753 "1.00 Myanmar kyats random",
5754 "1.00 Namibian Dollar random",
5755 "1.00 Namibian dollar random",
5756 "1.00 Namibian dollars random",
5757 "1.00 Nepalese Rupee random",
5758 "1.00 Nepalese rupee random",
5759 "1.00 Nepalese rupees random",
5760 "1.00 Netherlands Antillean Guilder random",
5761 "1.00 Netherlands Antillean guilder random",
5762 "1.00 Netherlands Antillean guilders random",
5763 "1.00 Dutch Guilder random",
5764 "1.00 Dutch guilder random",
5765 "1.00 Dutch guilders random",
5766 "1.00 Israeli New Shekel random",
5767 "1.00 Israeli new shekels random",
5768 "1.00 New Zealand Dollar random",
5769 "1.00 New Zealand dollar random",
5770 "1.00 New Zealand dollars random",
5771 "1.00 Nicaraguan C\\u00f3rdoba random",
5772 "1.00 Nicaraguan C\\u00f3rdoba (1988\\u20131991) random",
5773 "1.00 Nicaraguan c\\u00f3rdoba random",
5774 "1.00 Nicaraguan c\\u00f3rdoba random",
5775 "1.00 Nicaraguan c\\u00f3rdoba (1988\\u20131991) random",
5776 "1.00 Nicaraguan c\\u00f3rdobas (1988\\u20131991) random",
5777 "1.00 Nigerian Naira random",
5778 "1.00 Nigerian naira random",
5779 "1.00 Nigerian nairas random",
5780 "1.00 North Korean Won random",
5781 "1.00 North Korean won random",
5782 "1.00 North Korean won random",
5783 "1.00 Norwegian Krone random",
5784 "1.00 Norwegian krone random",
5785 "1.00 Norwegian kroner random",
5786 "1.00 Mozambican Metical (1980\\u20132006) random",
5787 "1.00 Mozambican metical (1980\\u20132006) random",
5788 "1.00 Mozambican meticals (1980\\u20132006) random",
5789 "1.00 Romanian Lei (1952\\u20132006) random",
5790 "1.00 Romanian Leu (1952\\u20132006) random",
5791 "1.00 Romanian leu (1952\\u20132006) random",
5792 "1.00 Serbian Dinar (2002\\u20132006) random",
5793 "1.00 Serbian dinar (2002\\u20132006) random",
5794 "1.00 Serbian dinars (2002\\u20132006) random",
5795 "1.00 Sudanese Dinar (1992\\u20132007) random",
5796 "1.00 Sudanese Pound (1957\\u20131998) random",
5797 "1.00 Sudanese dinar (1992\\u20132007) random",
5798 "1.00 Sudanese dinars (1992\\u20132007) random",
5799 "1.00 Sudanese pound (1957\\u20131998) random",
5800 "1.00 Sudanese pounds (1957\\u20131998) random",
5801 "1.00 Turkish Lira (1922\\u20132005) random",
5802 "1.00 Turkish Lira (1922\\u20132005) random",
5803 "1.00 Omani Rial random",
5804 "1.00 Omani rial random",
5805 "1.00 Omani rials random",
5806 "1.00 Pakistani Rupee random",
5807 "1.00 Pakistani rupee random",
5808 "1.00 Pakistani rupees random",
5809 "1.00 Palladium random",
5810 "1.00 Palladium random",
5811 "1.00 Panamanian Balboa random",
5812 "1.00 Panamanian balboa random",
5813 "1.00 Panamanian balboas random",
5814 "1.00 Papua New Guinean Kina random",
5815 "1.00 Papua New Guinean kina random",
5816 "1.00 Papua New Guinean kina random",
5817 "1.00 Paraguayan Guarani random",
5818 "1.00 Paraguayan guarani random",
5819 "1.00 Paraguayan guaranis random",
5820 "1.00 Peruvian Inti random",
5821 "1.00 Peruvian Sol random",
5822 "1.00 Peruvian Sol (1863\\u20131965) random",
5823 "1.00 Peruvian inti random",
5824 "1.00 Peruvian intis random",
5825 "1.00 Peruvian sol random",
5826 "1.00 Peruvian soles random",
5827 "1.00 Peruvian sol (1863\\u20131965) random",
5828 "1.00 Peruvian soles (1863\\u20131965) random",
5829 "1.00 Philippine Piso random",
5830 "1.00 Philippine piso random",
5831 "1.00 Philippine pisos random",
5832 "1.00 Platinum random",
5833 "1.00 Platinum random",
5834 "1.00 Polish Zloty (1950\\u20131995) random",
5835 "1.00 Polish Zloty random",
5836 "1.00 Polish zlotys random",
5837 "1.00 Polish zloty (PLZ) random",
5838 "1.00 Polish zloty random",
5839 "1.00 Polish zlotys (PLZ) random",
5840 "1.00 Portuguese Escudo random",
5841 "1.00 Portuguese Guinea Escudo random",
5842 "1.00 Portuguese Guinea escudo random",
5843 "1.00 Portuguese Guinea escudos random",
5844 "1.00 Portuguese escudo random",
5845 "1.00 Portuguese escudos random",
5846 "1.00 Qatari Rial random",
5847 "1.00 Qatari rial random",
5848 "1.00 Qatari rials random",
5849 "1.00 RINET Funds random",
5850 "1.00 RINET Funds random",
5851 "1.00 Rhodesian Dollar random",
5852 "1.00 Rhodesian dollar random",
5853 "1.00 Rhodesian dollars random",
5854 "1.00 Romanian Leu random",
5855 "1.00 Romanian lei random",
5856 "1.00 Romanian leu random",
5857 "1.00 Russian Ruble (1991\\u20131998) random",
5858 "1.00 Russian Ruble random",
5859 "1.00 Russian ruble (1991\\u20131998) random",
5860 "1.00 Russian ruble random",
5861 "1.00 Russian rubles (1991\\u20131998) random",
5862 "1.00 Russian rubles random",
5863 "1.00 Rwandan Franc random",
5864 "1.00 Rwandan franc random",
5865 "1.00 Rwandan francs random",
5866 "1.00 St. Helena Pound random",
5867 "1.00 St. Helena pound random",
5868 "1.00 St. Helena pounds random",
5869 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra random",
5870 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra random",
5871 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras random",
5872 "1.00 Saudi Riyal random",
5873 "1.00 Saudi riyal random",
5874 "1.00 Saudi riyals random",
5875 "1.00 Serbian Dinar random",
5876 "1.00 Serbian dinar random",
5877 "1.00 Serbian dinars random",
5878 "1.00 Seychellois Rupee random",
5879 "1.00 Seychellois rupee random",
5880 "1.00 Seychellois rupees random",
5881 "1.00 Sierra Leonean Leone random",
5882 "1.00 Sierra Leonean leone random",
5883 "1.00 Sierra Leonean leones random",
5884 "1.00 Singapore Dollar random",
5885 "1.00 Singapore dollar random",
5886 "1.00 Singapore dollars random",
5887 "1.00 Slovak Koruna random",
5888 "1.00 Slovak koruna random",
5889 "1.00 Slovak korunas random",
5890 "1.00 Slovenian Tolar random",
5891 "1.00 Slovenian tolar random",
5892 "1.00 Slovenian tolars random",
5893 "1.00 Solomon Islands Dollar random",
5894 "1.00 Solomon Islands dollar random",
5895 "1.00 Solomon Islands dollars random",
5896 "1.00 Somali Shilling random",
5897 "1.00 Somali shilling random",
5898 "1.00 Somali shillings random",
5899 "1.00 South African Rand (financial) random",
5900 "1.00 South African Rand random",
5901 "1.00 South African rand (financial) random",
5902 "1.00 South African rand random",
5903 "1.00 South African rands (financial) random",
5904 "1.00 South African rand random",
5905 "1.00 South Korean Won random",
5906 "1.00 South Korean won random",
5907 "1.00 South Korean won random",
5908 "1.00 Soviet Rouble random",
5909 "1.00 Soviet rouble random",
5910 "1.00 Soviet roubles random",
5911 "1.00 Spanish Peseta (A account) random",
5912 "1.00 Spanish Peseta (convertible account) random",
5913 "1.00 Spanish Peseta random",
5914 "1.00 Spanish peseta (A account) random",
5915 "1.00 Spanish peseta (convertible account) random",
5916 "1.00 Spanish peseta random",
5917 "1.00 Spanish pesetas (A account) random",
5918 "1.00 Spanish pesetas (convertible account) random",
5919 "1.00 Spanish pesetas random",
5920 "1.00 Special Drawing Rights random",
5921 "1.00 Sri Lankan Rupee random",
5922 "1.00 Sri Lankan rupee random",
5923 "1.00 Sri Lankan rupees random",
5924 "1.00 Sudanese Pound random",
5925 "1.00 Sudanese pound random",
5926 "1.00 Sudanese pounds random",
5927 "1.00 Surinamese Dollar random",
5928 "1.00 Surinamese dollar random",
5929 "1.00 Surinamese dollars random",
5930 "1.00 Surinamese Guilder random",
5931 "1.00 Surinamese guilder random",
5932 "1.00 Surinamese guilders random",
5933 "1.00 Swazi Lilangeni random",
5934 "1.00 Swazi lilangeni random",
5935 "1.00 Swazi emalangeni random",
5936 "1.00 Swedish Krona random",
5937 "1.00 Swedish krona random",
5938 "1.00 Swedish kronor random",
5939 "1.00 Swiss Franc random",
5940 "1.00 Swiss franc random",
5941 "1.00 Swiss francs random",
5942 "1.00 Syrian Pound random",
5943 "1.00 Syrian pound random",
5944 "1.00 Syrian pounds random",
5945 "1.00 New Taiwan Dollar random",
5946 "1.00 New Taiwan dollar random",
5947 "1.00 New Taiwan dollars random",
5948 "1.00 Tajikistani Ruble random",
5949 "1.00 Tajikistani Somoni random",
5950 "1.00 Tajikistani ruble random",
5951 "1.00 Tajikistani rubles random",
5952 "1.00 Tajikistani somoni random",
5953 "1.00 Tajikistani somonis random",
5954 "1.00 Tanzanian Shilling random",
5955 "1.00 Tanzanian shilling random",
5956 "1.00 Tanzanian shillings random",
5957 "1.00 Testing Currency Code random",
5958 "1.00 Testing Currency Code random",
5959 "1.00 Thai Baht random",
5960 "1.00 Thai baht random",
5961 "1.00 Thai baht random",
5962 "1.00 Timorese Escudo random",
5963 "1.00 Timorese escudo random",
5964 "1.00 Timorese escudos random",
5965 "1.00 Trinidad & Tobago Dollar random",
5966 "1.00 Trinidad & Tobago dollar random",
5967 "1.00 Trinidad & Tobago dollars random",
5968 "1.00 Tunisian Dinar random",
5969 "1.00 Tunisian dinar random",
5970 "1.00 Tunisian dinars random",
5971 "1.00 Turkish Lira random",
5972 "1.00 Turkish Lira random",
5973 "1.00 Turkish lira random",
5974 "1.00 Turkmenistani Manat random",
5975 "1.00 Turkmenistani manat random",
5976 "1.00 Turkmenistani manat random",
5977 "1.00 US Dollar (Next day) random",
5978 "1.00 US Dollar (Same day) random",
5979 "1.00 US Dollar random",
5980 "1.00 US dollar (next day) random",
5981 "1.00 US dollar (same day) random",
5982 "1.00 US dollar random",
5983 "1.00 US dollars (next day) random",
5984 "1.00 US dollars (same day) random",
5985 "1.00 US dollars random",
5986 "1.00 Ugandan Shilling (1966\\u20131987) random",
5987 "1.00 Ugandan Shilling random",
5988 "1.00 Ugandan shilling (1966\\u20131987) random",
5989 "1.00 Ugandan shilling random",
5990 "1.00 Ugandan shillings (1966\\u20131987) random",
5991 "1.00 Ugandan shillings random",
5992 "1.00 Ukrainian Hryvnia random",
5993 "1.00 Ukrainian Karbovanets random",
5994 "1.00 Ukrainian hryvnia random",
5995 "1.00 Ukrainian hryvnias random",
5996 "1.00 Ukrainian karbovanets random",
5997 "1.00 Ukrainian karbovantsiv random",
5998 "1.00 Colombian Real Value Unit random",
5999 "1.00 United Arab Emirates Dirham random",
6000 "1.00 Unknown Currency random",
6001 "1.00 Uruguayan Peso (1975\\u20131993) random",
6002 "1.00 Uruguayan Peso random",
6003 "1.00 Uruguayan Peso (Indexed Units) random",
6004 "1.00 Uruguayan peso (1975\\u20131993) random",
6005 "1.00 Uruguayan peso (indexed units) random",
6006 "1.00 Uruguayan peso random",
6007 "1.00 Uruguayan pesos (1975\\u20131993) random",
6008 "1.00 Uruguayan pesos (indexed units) random",
6009 "1.00 Uzbekistani Som random",
6010 "1.00 Uzbekistani som random",
6011 "1.00 Uzbekistani som random",
6012 "1.00 Vanuatu Vatu random",
6013 "1.00 Vanuatu vatu random",
6014 "1.00 Vanuatu vatus random",
6015 "1.00 Venezuelan Bol\\u00edvar random",
6016 "1.00 Venezuelan Bol\\u00edvar (1871\\u20132008) random",
6017 "1.00 Venezuelan bol\\u00edvar random",
6018 "1.00 Venezuelan bol\\u00edvars random",
6019 "1.00 Venezuelan bol\\u00edvar (1871\\u20132008) random",
6020 "1.00 Venezuelan bol\\u00edvars (1871\\u20132008) random",
6021 "1.00 Vietnamese Dong random",
6022 "1.00 Vietnamese dong random",
6023 "1.00 Vietnamese dong random",
6024 "1.00 WIR Euro random",
6025 "1.00 WIR Franc random",
6026 "1.00 WIR euro random",
6027 "1.00 WIR euros random",
6028 "1.00 WIR franc random",
6029 "1.00 WIR francs random",
6030 "1.00 Samoan Tala random",
6031 "1.00 Samoan tala random",
6032 "1.00 Samoan tala random",
6033 "1.00 Yemeni Dinar random",
6034 "1.00 Yemeni Rial random",
6035 "1.00 Yemeni dinar random",
6036 "1.00 Yemeni dinars random",
6037 "1.00 Yemeni rial random",
6038 "1.00 Yemeni rials random",
6039 "1.00 Yugoslavian Convertible Dinar (1990\\u20131992) random",
6040 "1.00 Yugoslavian Hard Dinar (1966\\u20131990) random",
6041 "1.00 Yugoslavian New Dinar (1994\\u20132002) random",
6042 "1.00 Yugoslavian convertible dinar (1990\\u20131992) random",
6043 "1.00 Yugoslavian convertible dinars (1990\\u20131992) random",
6044 "1.00 Yugoslavian hard dinar (1966\\u20131990) random",
6045 "1.00 Yugoslavian hard dinars (1966\\u20131990) random",
6046 "1.00 Yugoslavian new dinar (1994\\u20132002) random",
6047 "1.00 Yugoslavian new dinars (1994\\u20132002) random",
6048 "1.00 Zairean New Zaire (1993\\u20131998) random",
6049 "1.00 Zairean Zaire (1971\\u20131993) random",
6050 "1.00 Zairean new zaire (1993\\u20131998) random",
6051 "1.00 Zairean new zaires (1993\\u20131998) random",
6052 "1.00 Zairean zaire (1971\\u20131993) random",
6053 "1.00 Zairean zaires (1971\\u20131993) random",
6054 "1.00 Zambian Kwacha random",
6055 "1.00 Zambian kwacha random",
6056 "1.00 Zambian kwachas random",
6057 "1.00 Zimbabwean Dollar (1980\\u20132008) random",
6058 "1.00 Zimbabwean dollar (1980\\u20132008) random",
6059 "1.00 Zimbabwean dollars (1980\\u20132008) random",
6060 "1.00 euro random",
6061 "1.00 euros random",
6062 "1.00 Turkish lira (1922\\u20132005) random",
6063 "1.00 special drawing rights random",
6064 "1.00 Colombian real value unit random",
6065 "1.00 Colombian real value units random",
6066 "1.00 unknown currency random",
6067 };
6068
6069 const char* WRONG_DATA[] = {
6070 // Following are missing one last char in the currency name
6071 "1.00 Nicaraguan Cordob",
6072 "1.00 Namibian Dolla",
6073 "1.00 Namibian dolla",
6074 "1.00 Nepalese Rupe",
6075 "1.00 Nepalese rupe",
6076 "1.00 Netherlands Antillean Guilde",
6077 "1.00 Netherlands Antillean guilde",
6078 "1.00 Dutch Guilde",
6079 "1.00 Dutch guilde",
6080 "1.00 Israeli New Sheqe",
6081 "1.00 New Zealand Dolla",
6082 "1.00 New Zealand dolla",
6083 "1.00 Nicaraguan cordob",
6084 "1.00 Nigerian Nair",
6085 "1.00 Nigerian nair",
6086 "1.00 North Korean Wo",
6087 "1.00 North Korean wo",
6088 "1.00 Norwegian Kron",
6089 "1.00 Norwegian kron",
6090 "1.00 US dolla",
6091 "1.00",
6092 "A1.00",
6093 "AD1.00",
6094 "AE1.00",
6095 "AF1.00",
6096 "AL1.00",
6097 "AM1.00",
6098 "AN1.00",
6099 "AO1.00",
6100 "AR1.00",
6101 "AT1.00",
6102 "AU1.00",
6103 "AW1.00",
6104 "AZ1.00",
6105 "Afghan Afghan1.00",
6106 "Afghan Afghani (1927\\u201320021.00",
6107 "Afl1.00",
6108 "Albanian Le1.00",
6109 "Algerian Dina1.00",
6110 "Andorran Peset1.00",
6111 "Angolan Kwanz1.00",
6112 "Angolan Kwanza (1977\\u201319901.00",
6113 "Angolan Readjusted Kwanza (1995\\u201319991.00",
6114 "Angolan New Kwanza (1990\\u201320001.00",
6115 "Argentine Austra1.00",
6116 "Argentine Pes1.00",
6117 "Argentine Peso (1983\\u201319851.00",
6118 "Armenian Dra1.00",
6119 "Aruban Flori1.00",
6120 "Australian Dolla1.00",
6121 "Austrian Schillin1.00",
6122 "Azerbaijani Mana1.00",
6123 "Azerbaijani Manat (1993\\u201320061.00",
6124 "B1.00",
6125 "BA1.00",
6126 "BB1.00",
6127 "BE1.00",
6128 "BG1.00",
6129 "BH1.00",
6130 "BI1.00",
6131 "BM1.00",
6132 "BN1.00",
6133 "BO1.00",
6134 "BR1.00",
6135 "BS1.00",
6136 "BT1.00",
6137 "BU1.00",
6138 "BW1.00",
6139 "BY1.00",
6140 "BZ1.00",
6141 "Bahamian Dolla1.00",
6142 "Bahraini Dina1.00",
6143 "Bangladeshi Tak1.00",
6144 "Barbadian Dolla1.00",
6145 "Bds1.00",
6146 "Belarusian Ruble (1994\\u201319991.00",
6147 "Belarusian Rubl1.00",
6148 "Belgian Fran1.00",
6149 "Belgian Franc (convertible1.00",
6150 "Belgian Franc (financial1.00",
6151 "Belize Dolla1.00",
6152 "Bermudan Dolla1.00",
6153 "Bhutanese Ngultru1.00",
6154 "Bolivian Mvdo1.00",
6155 "Bolivian Pes1.00",
6156 "Bolivian Bolivian1.00",
6157 "Bosnia-Herzegovina Convertible Mar1.00",
6158 "Bosnia-Herzegovina Dina1.00",
6159 "Botswanan Pul1.00",
6160 "Brazilian Cruzad1.00",
6161 "Brazilian Cruzado Nov1.00",
6162 "Brazilian Cruzeir1.00",
6163 "Brazilian Cruzeiro (1990\\u201319931.00",
6164 "Brazilian New Cruzeiro (1967\\u201319861.00",
6165 "Brazilian Rea1.00",
6166 "British Pound Sterlin1.00",
6167 "Brunei Dolla1.00",
6168 "Bulgarian Hard Le1.00",
6169 "Bulgarian Le1.00",
6170 "Burmese Kya1.00",
6171 "Burundian Fran1.00",
6172 "C1.00",
6173 "CA1.00",
6174 "CD1.00",
6175 "CFP Fran1.00",
6176 "CFP1.00",
6177 "CH1.00",
6178 "CL1.00",
6179 "CN1.00",
6180 "CO1.00",
6181 "CS1.00",
6182 "CU1.00",
6183 "CV1.00",
6184 "CY1.00",
6185 "CZ1.00",
6186 "Cambodian Rie1.00",
6187 "Canadian Dolla1.00",
6188 "Cape Verdean Escud1.00",
6189 "Cayman Islands Dolla1.00",
6190 "Chilean Pes1.00",
6191 "Chilean Unit of Accoun1.00",
6192 "Chinese Yua1.00",
6193 "Colombian Pes1.00",
6194 "Comoro Fran1.00",
6195 "Congolese Fran1.00",
6196 "Costa Rican Col\\u00f31.00",
6197 "Croatian Dina1.00",
6198 "Croatian Kun1.00",
6199 "Cuban Pes1.00",
6200 "Cypriot Poun1.00",
6201 "Czech Republic Korun1.00",
6202 "Czechoslovak Hard Korun1.00",
6203 "D1.00",
6204 "DD1.00",
6205 "DE1.00",
6206 "DJ1.00",
6207 "DK1.00",
6208 "DO1.00",
6209 "DZ1.00",
6210 "Danish Kron1.00",
6211 "German Mar1.00",
6212 "Djiboutian Fran1.00",
6213 "Dk1.00",
6214 "Dominican Pes1.00",
6215 "EC1.00",
6216 "EE1.00",
6217 "EG1.00",
6218 "EQ1.00",
6219 "ER1.00",
6220 "ES1.00",
6221 "ET1.00",
6222 "EU1.00",
6223 "East Caribbean Dolla1.00",
6224 "East German Ostmar1.00",
6225 "Ecuadorian Sucr1.00",
6226 "Ecuadorian Unit of Constant Valu1.00",
6227 "Egyptian Poun1.00",
6228 "Ekwel1.00",
6229 "Salvadoran Col\\u00f31.00",
6230 "Equatorial Guinean Ekwel1.00",
6231 "Eritrean Nakf1.00",
6232 "Es1.00",
6233 "Estonian Kroo1.00",
6234 "Ethiopian Bir1.00",
6235 "Eur1.00",
6236 "European Composite Uni1.00",
6237 "European Currency Uni1.00",
6238 "European Monetary Uni1.00",
6239 "European Unit of Account (XBC1.00",
6240 "European Unit of Account (XBD1.00",
6241 "F1.00",
6242 "FB1.00",
6243 "FI1.00",
6244 "FJ1.00",
6245 "FK1.00",
6246 "FR1.00",
6247 "Falkland Islands Poun1.00",
6248 "Fd1.00",
6249 "Fijian Dolla1.00",
6250 "Finnish Markk1.00",
6251 "Fr1.00",
6252 "French Fran1.00",
6253 "French Gold Fran1.00",
6254 "French UIC-Fran1.00",
6255 "G1.00",
6256 "GB1.00",
6257 "GE1.00",
6258 "GH1.00",
6259 "GI1.00",
6260 "GM1.00",
6261 "GN1.00",
6262 "GQ1.00",
6263 "GR1.00",
6264 "GT1.00",
6265 "GW1.00",
6266 "GY1.00",
6267 "Gambian Dalas1.00",
6268 "Georgian Kupon Lari1.00",
6269 "Georgian Lar1.00",
6270 "Ghanaian Ced1.00",
6271 "Ghanaian Cedi (1979\\u201320071.00",
6272 "Gibraltar Poun1.00",
6273 "Gol1.00",
6274 "Greek Drachm1.00",
6275 "Guatemalan Quetza1.00",
6276 "Guinean Fran1.00",
6277 "Guinean Syl1.00",
6278 "Guinea-Bissau Pes1.00",
6279 "Guyanaese Dolla1.00",
6280 "HK1.00",
6281 "HN1.00",
6282 "HR1.00",
6283 "HT1.00",
6284 "HU1.00",
6285 "Haitian Gourd1.00",
6286 "Honduran Lempir1.00",
6287 "Hong Kong Dolla1.00",
6288 "Hungarian Forin1.00",
6289 "I1.00",
6290 "IE1.00",
6291 "IL1.00",
6292 "IN1.00",
6293 "IQ1.00",
6294 "IR1.00",
6295 "IS1.00",
6296 "IT1.00",
6297 "Icelandic Kron1.00",
6298 "Indian Rupe1.00",
6299 "Indonesian Rupia1.00",
6300 "Iranian Ria1.00",
6301 "Iraqi Dina1.00",
6302 "Irish Poun1.00",
6303 "Israeli Poun1.00",
6304 "Italian Lir1.00",
6305 "J1.00",
6306 "JM1.00",
6307 "JO1.00",
6308 "JP1.00",
6309 "Jamaican Dolla1.00",
6310 "Japanese Ye1.00",
6311 "Jordanian Dina1.00",
6312 "K S1.00",
6313 "K1.00",
6314 "KE1.00",
6315 "KG1.00",
6316 "KH1.00",
6317 "KP1.00",
6318 "KR1.00",
6319 "KW1.00",
6320 "KY1.00",
6321 "KZ1.00",
6322 "Kazakhstani Teng1.00",
6323 "Kenyan Shillin1.00",
6324 "Kuwaiti Dina1.00",
6325 "Kyrgystani So1.00",
6326 "LA1.00",
6327 "LB1.00",
6328 "LK1.00",
6329 "LR1.00",
6330 "LT1.00",
6331 "LU1.00",
6332 "LV1.00",
6333 "LY1.00",
6334 "Laotian Ki1.00",
6335 "Latvian Lat1.00",
6336 "Latvian Rubl1.00",
6337 "Lebanese Poun1.00",
6338 "Lesotho Lot1.00",
6339 "Liberian Dolla1.00",
6340 "Libyan Dina1.00",
6341 "Lithuanian Lit1.00",
6342 "Lithuanian Talona1.00",
6343 "Luxembourgian Convertible Fran1.00",
6344 "Luxembourg Financial Fran1.00",
6345 "Luxembourgian Fran1.00",
6346 "MA1.00",
6347 "MD1.00",
6348 "MDe1.00",
6349 "MEX1.00",
6350 "MG1.00",
6351 "ML1.00",
6352 "MM1.00",
6353 "MN1.00",
6354 "MO1.00",
6355 "MR1.00",
6356 "MT1.00",
6357 "MU1.00",
6358 "MV1.00",
6359 "MW1.00",
6360 "MX1.00",
6361 "MY1.00",
6362 "MZ1.00",
6363 "Macanese Patac1.00",
6364 "Macedonian Dena1.00",
6365 "Malagasy Ariar1.00",
6366 "Malagasy Fran1.00",
6367 "Malawian Kwach1.00",
6368 "Malaysian Ringgi1.00",
6369 "Maldivian Rufiya1.00",
6370 "Malian Fran1.00",
6371 "Malot1.00",
6372 "Maltese Lir1.00",
6373 "Maltese Poun1.00",
6374 "Mauritanian Ouguiy1.00",
6375 "Mauritian Rupe1.00",
6376 "Mexican Pes1.00",
6377 "Mexican Silver Peso (1861\\u201319921.00",
6378 "Mexican Investment Uni1.00",
6379 "Moldovan Le1.00",
6380 "Mongolian Tugri1.00",
6381 "Moroccan Dirha1.00",
6382 "Moroccan Fran1.00",
6383 "Mozambican Escud1.00",
6384 "Mozambican Metica1.00",
6385 "Myanmar Kya1.00",
6386 "N1.00",
6387 "NA1.00",
6388 "NAf1.00",
6389 "NG1.00",
6390 "NI1.00",
6391 "NK1.00",
6392 "NL1.00",
6393 "NO1.00",
6394 "NP1.00",
6395 "NT1.00",
6396 "Namibian Dolla1.00",
6397 "Nepalese Rupe1.00",
6398 "Netherlands Antillean Guilde1.00",
6399 "Dutch Guilde1.00",
6400 "Israeli New Sheqe1.00",
6401 "New Zealand Dolla1.00",
6402 "Nicaraguan C\\u00f3rdoba (1988\\u201319911.00",
6403 "Nicaraguan C\\u00f3rdob1.00",
6404 "Nigerian Nair1.00",
6405 "North Korean Wo1.00",
6406 "Norwegian Kron1.00",
6407 "Nr1.00",
6408 "OM1.00",
6409 "Old Mozambican Metica1.00",
6410 "Romanian Leu (1952\\u201320061.00",
6411 "Serbian Dinar (2002\\u201320061.00",
6412 "Sudanese Dinar (1992\\u201320071.00",
6413 "Sudanese Pound (1957\\u201319981.00",
6414 "Turkish Lira (1922\\u201320051.00",
6415 "Omani Ria1.00",
6416 "PA1.00",
6417 "PE1.00",
6418 "PG1.00",
6419 "PH1.00",
6420 "PK1.00",
6421 "PL1.00",
6422 "PT1.00",
6423 "PY1.00",
6424 "Pakistani Rupe1.00",
6425 "Palladiu1.00",
6426 "Panamanian Balbo1.00",
6427 "Papua New Guinean Kin1.00",
6428 "Paraguayan Guaran1.00",
6429 "Peruvian Int1.00",
6430 "Peruvian Sol (1863\\u201319651.00",
6431 "Peruvian Sol Nuev1.00",
6432 "Philippine Pes1.00",
6433 "Platinu1.00",
6434 "Polish Zlot1.00",
6435 "Polish Zloty (1950\\u201319951.00",
6436 "Portuguese Escud1.00",
6437 "Portuguese Guinea Escud1.00",
6438 "Pr1.00",
6439 "QA1.00",
6440 "Qatari Ria1.00",
6441 "RD1.00",
6442 "RH1.00",
6443 "RINET Fund1.00",
6444 "RS1.00",
6445 "RU1.00",
6446 "RW1.00",
6447 "Rb1.00",
6448 "Rhodesian Dolla1.00",
6449 "Romanian Le1.00",
6450 "Russian Rubl1.00",
6451 "Russian Ruble (1991\\u201319981.00",
6452 "Rwandan Fran1.00",
6453 "S1.00",
6454 "SA1.00",
6455 "SB1.00",
6456 "SC1.00",
6457 "SD1.00",
6458 "SE1.00",
6459 "SG1.00",
6460 "SH1.00",
6461 "SI1.00",
6462 "SK1.00",
6463 "SL R1.00",
6464 "SL1.00",
6465 "SO1.00",
6466 "ST1.00",
6467 "SU1.00",
6468 "SV1.00",
6469 "SY1.00",
6470 "SZ1.00",
6471 "St. Helena Poun1.00",
6472 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobr1.00",
6473 "Saudi Riya1.00",
6474 "Serbian Dina1.00",
6475 "Seychellois Rupe1.00",
6476 "Sh1.00",
6477 "Sierra Leonean Leon1.00",
6478 "Silve1.00",
6479 "Singapore Dolla1.00",
6480 "Slovak Korun1.00",
6481 "Slovenian Tola1.00",
6482 "Solomon Islands Dolla1.00",
6483 "Somali Shillin1.00",
6484 "South African Ran1.00",
6485 "South African Rand (financial1.00",
6486 "South Korean Wo1.00",
6487 "Soviet Roubl1.00",
6488 "Spanish Peset1.00",
6489 "Spanish Peseta (A account1.00",
6490 "Spanish Peseta (convertible account1.00",
6491 "Special Drawing Right1.00",
6492 "Sri Lankan Rupe1.00",
6493 "Sudanese Poun1.00",
6494 "Surinamese Dolla1.00",
6495 "Surinamese Guilde1.00",
6496 "Swazi Lilangen1.00",
6497 "Swedish Kron1.00",
6498 "Swiss Fran1.00",
6499 "Syrian Poun1.00",
6500 "T S1.00",
6501 "TH1.00",
6502 "TJ1.00",
6503 "TM1.00",
6504 "TN1.00",
6505 "TO1.00",
6506 "TP1.00",
6507 "TR1.00",
6508 "TT1.00",
6509 "TW1.00",
6510 "TZ1.00",
6511 "New Taiwan Dolla1.00",
6512 "Tajikistani Rubl1.00",
6513 "Tajikistani Somon1.00",
6514 "Tanzanian Shillin1.00",
6515 "Testing Currency Cod1.00",
6516 "Thai Bah1.00",
6517 "Timorese Escud1.00",
6518 "Tongan Pa\\u20bbang1.00",
6519 "Trinidad & Tobago Dolla1.00",
6520 "Tunisian Dina1.00",
6521 "Turkish Lir1.00",
6522 "Turkmenistani Mana1.00",
6523 "U S1.00",
6524 "U1.00",
6525 "UA1.00",
6526 "UG1.00",
6527 "US Dolla1.00",
6528 "US Dollar (Next day1.00",
6529 "US Dollar (Same day1.00",
6530 "US1.00",
6531 "UY1.00",
6532 "UZ1.00",
6533 "Ugandan Shillin1.00",
6534 "Ugandan Shilling (1966\\u201319871.00",
6535 "Ukrainian Hryvni1.00",
6536 "Ukrainian Karbovanet1.00",
6537 "Colombian Real Value Uni1.00",
6538 "United Arab Emirates Dirha1.00",
6539 "Unknown Currenc1.00",
6540 "Ur1.00",
6541 "Uruguay Peso (1975\\u201319931.00",
6542 "Uruguay Peso Uruguay1.00",
6543 "Uruguay Peso (Indexed Units1.00",
6544 "Uzbekistani So1.00",
6545 "V1.00",
6546 "VE1.00",
6547 "VN1.00",
6548 "VU1.00",
6549 "Vanuatu Vat1.00",
6550 "Venezuelan Bol\\u00edva1.00",
6551 "Venezuelan Bol\\u00edvar Fuert1.00",
6552 "Vietnamese Don1.00",
6553 "West African CFA Fran1.00",
6554 "Central African CFA Fran1.00",
6555 "WIR Eur1.00",
6556 "WIR Fran1.00",
6557 "WS1.00",
6558 "Samoa Tal1.00",
6559 "XA1.00",
6560 "XB1.00",
6561 "XC1.00",
6562 "XD1.00",
6563 "XE1.00",
6564 "XF1.00",
6565 "XO1.00",
6566 "XP1.00",
6567 "XR1.00",
6568 "XT1.00",
6569 "XX1.00",
6570 "YD1.00",
6571 "YE1.00",
6572 "YU1.00",
6573 "Yemeni Dina1.00",
6574 "Yemeni Ria1.00",
6575 "Yugoslavian Convertible Dina1.00",
6576 "Yugoslavian Hard Dinar (1966\\u201319901.00",
6577 "Yugoslavian New Dina1.00",
6578 "Z1.00",
6579 "ZA1.00",
6580 "ZM1.00",
6581 "ZR1.00",
6582 "ZW1.00",
6583 "Zairean New Zaire (1993\\u201319981.00",
6584 "Zairean Zair1.00",
6585 "Zambian Kwach1.00",
6586 "Zimbabwean Dollar (1980\\u201320081.00",
6587 "dra1.00",
6588 "lar1.00",
6589 "le1.00",
6590 "man1.00",
6591 "so1.00",
6592 };
6593
6594 Locale locale("en_US");
6595 for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
6596 UnicodeString formatted = ctou(DATA[i]);
6597 UErrorCode status = U_ZERO_ERROR;
6598 LocalPointer<NumberFormat> numFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status), status);
6599 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {
6600 return;
6601 }
6602 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
6603 numFmt->setLenient(TRUE);
6604 ParsePosition parsePos;
6605 LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6606 if (parsePos.getIndex() > 0) {
6607 double doubleVal = currAmt->getNumber().getDouble(status);
6608 if ( doubleVal != 1.0 ) {
6609 errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
6610 }
6611 } else {
6612 errln("Failed to parse as currency: " + formatted);
6613 }
6614 }
6615
6616 for (uint32_t i=0; i<UPRV_LENGTHOF(WRONG_DATA); ++i) {
6617 UnicodeString formatted = ctou(WRONG_DATA[i]);
6618 UErrorCode status = U_ZERO_ERROR;
6619 NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6620 if (numFmt != NULL && U_SUCCESS(status)) {
6621 ParsePosition parsePos;
6622 LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6623 if (parsePos.getIndex() > 0) {
6624 double doubleVal = currAmt->getNumber().getDouble(status);
6625 errln("Parsed as currency, should not have: " + formatted + " -> " + doubleVal);
6626 }
6627 } else {
6628 dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));
6629 delete numFmt;
6630 break;
6631 }
6632 delete numFmt;
6633 }
6634 }
6635
6636 const char* attrString(int32_t);
6637
6638 // UnicodeString s;
6639 // std::string ss;
6640 // std::cout << s.toUTF8String(ss)
expectPositions(FieldPositionIterator & iter,int32_t * values,int32_t tupleCount,const UnicodeString & str)6641 void NumberFormatTest::expectPositions(FieldPositionIterator& iter, int32_t *values, int32_t tupleCount,
6642 const UnicodeString& str) {
6643 UBool found[10];
6644 FieldPosition fp;
6645
6646 if (tupleCount > 10) {
6647 assertTrue("internal error, tupleCount too large", FALSE);
6648 } else {
6649 for (int i = 0; i < tupleCount; ++i) {
6650 found[i] = FALSE;
6651 }
6652 }
6653
6654 logln(str);
6655 while (iter.next(fp)) {
6656 UBool ok = FALSE;
6657 int32_t id = fp.getField();
6658 int32_t start = fp.getBeginIndex();
6659 int32_t limit = fp.getEndIndex();
6660
6661 // is there a logln using printf?
6662 char buf[128];
6663 sprintf(buf, "%24s %3d %3d %3d", attrString(id), id, start, limit);
6664 logln(buf);
6665
6666 for (int i = 0; i < tupleCount; ++i) {
6667 if (found[i]) {
6668 continue;
6669 }
6670 if (values[i*3] == id &&
6671 values[i*3+1] == start &&
6672 values[i*3+2] == limit) {
6673 found[i] = ok = TRUE;
6674 break;
6675 }
6676 }
6677
6678 assertTrue((UnicodeString)"found [" + id + "," + start + "," + limit + "]", ok);
6679 }
6680
6681 // check that all were found
6682 UBool ok = TRUE;
6683 for (int i = 0; i < tupleCount; ++i) {
6684 if (!found[i]) {
6685 ok = FALSE;
6686 assertTrue((UnicodeString) "missing [" + values[i*3] + "," + values[i*3+1] + "," + values[i*3+2] + "]", found[i]);
6687 }
6688 }
6689 assertTrue("no expected values were missing", ok);
6690 }
6691
expectPosition(FieldPosition & pos,int32_t id,int32_t start,int32_t limit,const UnicodeString & str)6692 void NumberFormatTest::expectPosition(FieldPosition& pos, int32_t id, int32_t start, int32_t limit,
6693 const UnicodeString& str) {
6694 logln(str);
6695 assertTrue((UnicodeString)"id " + id + " == " + pos.getField(), id == pos.getField());
6696 assertTrue((UnicodeString)"begin " + start + " == " + pos.getBeginIndex(), start == pos.getBeginIndex());
6697 assertTrue((UnicodeString)"end " + limit + " == " + pos.getEndIndex(), limit == pos.getEndIndex());
6698 }
6699
TestFieldPositionIterator()6700 void NumberFormatTest::TestFieldPositionIterator() {
6701 // bug 7372
6702 UErrorCode status = U_ZERO_ERROR;
6703 FieldPositionIterator iter1;
6704 FieldPositionIterator iter2;
6705 FieldPosition pos;
6706
6707 DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(status);
6708 if (failure(status, "NumberFormat::createInstance", TRUE)) return;
6709
6710 double num = 1234.56;
6711 UnicodeString str1;
6712 UnicodeString str2;
6713
6714 assertTrue((UnicodeString)"self==", iter1 == iter1);
6715 assertTrue((UnicodeString)"iter1==iter2", iter1 == iter2);
6716
6717 decFmt->format(num, str1, &iter1, status);
6718 assertTrue((UnicodeString)"iter1 != iter2", iter1 != iter2);
6719 decFmt->format(num, str2, &iter2, status);
6720 assertTrue((UnicodeString)"iter1 == iter2 (2)", iter1 == iter2);
6721 iter1.next(pos);
6722 assertTrue((UnicodeString)"iter1 != iter2 (2)", iter1 != iter2);
6723 iter2.next(pos);
6724 assertTrue((UnicodeString)"iter1 == iter2 (3)", iter1 == iter2);
6725
6726 // should format ok with no iterator
6727 str2.remove();
6728 decFmt->format(num, str2, NULL, status);
6729 assertEquals("null fpiter", str1, str2);
6730
6731 delete decFmt;
6732 }
6733
TestFormatAttributes()6734 void NumberFormatTest::TestFormatAttributes() {
6735 Locale locale("en_US");
6736 UErrorCode status = U_ZERO_ERROR;
6737 DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6738 if (failure(status, "NumberFormat::createInstance", TRUE)) return;
6739 double val = 12345.67;
6740
6741 {
6742 int32_t expected[] = {
6743 UNUM_CURRENCY_FIELD, 0, 1,
6744 UNUM_GROUPING_SEPARATOR_FIELD, 3, 4,
6745 UNUM_INTEGER_FIELD, 1, 7,
6746 UNUM_DECIMAL_SEPARATOR_FIELD, 7, 8,
6747 UNUM_FRACTION_FIELD, 8, 10,
6748 };
6749 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6750
6751 FieldPositionIterator posIter;
6752 UnicodeString result;
6753 decFmt->format(val, result, &posIter, status);
6754 expectPositions(posIter, expected, tupleCount, result);
6755 }
6756 {
6757 FieldPosition fp(UNUM_INTEGER_FIELD);
6758 UnicodeString result;
6759 decFmt->format(val, result, fp);
6760 expectPosition(fp, UNUM_INTEGER_FIELD, 1, 7, result);
6761 }
6762 {
6763 FieldPosition fp(UNUM_FRACTION_FIELD);
6764 UnicodeString result;
6765 decFmt->format(val, result, fp);
6766 expectPosition(fp, UNUM_FRACTION_FIELD, 8, 10, result);
6767 }
6768 delete decFmt;
6769
6770 decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_SCIENTIFIC, status);
6771 val = -0.0000123;
6772 {
6773 int32_t expected[] = {
6774 UNUM_SIGN_FIELD, 0, 1,
6775 UNUM_INTEGER_FIELD, 1, 2,
6776 UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3,
6777 UNUM_FRACTION_FIELD, 3, 5,
6778 UNUM_EXPONENT_SYMBOL_FIELD, 5, 6,
6779 UNUM_EXPONENT_SIGN_FIELD, 6, 7,
6780 UNUM_EXPONENT_FIELD, 7, 8
6781 };
6782 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6783
6784 FieldPositionIterator posIter;
6785 UnicodeString result;
6786 decFmt->format(val, result, &posIter, status);
6787 expectPositions(posIter, expected, tupleCount, result);
6788 }
6789 {
6790 FieldPosition fp(UNUM_INTEGER_FIELD);
6791 UnicodeString result;
6792 decFmt->format(val, result, fp);
6793 expectPosition(fp, UNUM_INTEGER_FIELD, 1, 2, result);
6794 }
6795 {
6796 FieldPosition fp(UNUM_FRACTION_FIELD);
6797 UnicodeString result;
6798 decFmt->format(val, result, fp);
6799 expectPosition(fp, UNUM_FRACTION_FIELD, 3, 5, result);
6800 }
6801 delete decFmt;
6802
6803 fflush(stderr);
6804 }
6805
attrString(int32_t attrId)6806 const char* attrString(int32_t attrId) {
6807 switch (attrId) {
6808 case UNUM_INTEGER_FIELD: return "integer";
6809 case UNUM_FRACTION_FIELD: return "fraction";
6810 case UNUM_DECIMAL_SEPARATOR_FIELD: return "decimal separator";
6811 case UNUM_EXPONENT_SYMBOL_FIELD: return "exponent symbol";
6812 case UNUM_EXPONENT_SIGN_FIELD: return "exponent sign";
6813 case UNUM_EXPONENT_FIELD: return "exponent";
6814 case UNUM_GROUPING_SEPARATOR_FIELD: return "grouping separator";
6815 case UNUM_CURRENCY_FIELD: return "currency";
6816 case UNUM_PERCENT_FIELD: return "percent";
6817 case UNUM_PERMILL_FIELD: return "permille";
6818 case UNUM_SIGN_FIELD: return "sign";
6819 default: return "";
6820 }
6821 }
6822
6823 //
6824 // Test formatting & parsing of big decimals.
6825 // API test, not a comprehensive test.
6826 // See DecimalFormatTest/DataDrivenTests
6827 //
6828 #define ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \
6829 assertSuccess(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (status)); \
6830 } UPRV_BLOCK_MACRO_END
6831 #define ASSERT_EQUALS(expected, actual) UPRV_BLOCK_MACRO_BEGIN { \
6832 assertEquals(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (expected), (actual)); \
6833 } UPRV_BLOCK_MACRO_END
6834
TestDecimal()6835 void NumberFormatTest::TestDecimal() {
6836 {
6837 UErrorCode status = U_ZERO_ERROR;
6838 Formattable f("12.345678999987654321E666", status);
6839 ASSERT_SUCCESS(status);
6840 StringPiece s = f.getDecimalNumber(status);
6841 ASSERT_SUCCESS(status);
6842 ASSERT_EQUALS("1.2345678999987654321E+667", s.data());
6843 //printf("%s\n", s.data());
6844 }
6845
6846 {
6847 UErrorCode status = U_ZERO_ERROR;
6848 Formattable f1("this is not a number", status);
6849 ASSERT_EQUALS(U_DECIMAL_NUMBER_SYNTAX_ERROR, status);
6850 }
6851
6852 {
6853 UErrorCode status = U_ZERO_ERROR;
6854 Formattable f;
6855 f.setDecimalNumber("123.45", status);
6856 ASSERT_SUCCESS(status);
6857 ASSERT_EQUALS( Formattable::kDouble, f.getType());
6858 ASSERT_EQUALS(123.45, f.getDouble());
6859 ASSERT_EQUALS(123.45, f.getDouble(status));
6860 ASSERT_SUCCESS(status);
6861 ASSERT_EQUALS("123.45", f.getDecimalNumber(status).data());
6862 ASSERT_SUCCESS(status);
6863
6864 f.setDecimalNumber("4.5678E7", status);
6865 int32_t n;
6866 n = f.getLong();
6867 ASSERT_EQUALS(45678000, n);
6868
6869 status = U_ZERO_ERROR;
6870 f.setDecimalNumber("-123", status);
6871 ASSERT_SUCCESS(status);
6872 ASSERT_EQUALS( Formattable::kLong, f.getType());
6873 ASSERT_EQUALS(-123, f.getLong());
6874 ASSERT_EQUALS(-123, f.getLong(status));
6875 ASSERT_SUCCESS(status);
6876 ASSERT_EQUALS("-123", f.getDecimalNumber(status).data());
6877 ASSERT_SUCCESS(status);
6878
6879 status = U_ZERO_ERROR;
6880 f.setDecimalNumber("1234567890123", status); // Number too big for 32 bits
6881 ASSERT_SUCCESS(status);
6882 ASSERT_EQUALS( Formattable::kInt64, f.getType());
6883 ASSERT_EQUALS(1234567890123LL, f.getInt64());
6884 ASSERT_EQUALS(1234567890123LL, f.getInt64(status));
6885 ASSERT_SUCCESS(status);
6886 ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status).data());
6887 ASSERT_SUCCESS(status);
6888 }
6889
6890 {
6891 UErrorCode status = U_ZERO_ERROR;
6892 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6893 if (U_FAILURE(status) || fmtr == NULL) {
6894 dataerrln("Unable to create NumberFormat");
6895 } else {
6896 UnicodeString formattedResult;
6897 StringPiece num("244444444444444444444444444444444444446.4");
6898 fmtr->format(num, formattedResult, NULL, status);
6899 ASSERT_SUCCESS(status);
6900 ASSERT_EQUALS("244,444,444,444,444,444,444,444,444,444,444,444,446.4", formattedResult);
6901 //std::string ss; std::cout << formattedResult.toUTF8String(ss);
6902 delete fmtr;
6903 }
6904 }
6905
6906 {
6907 // Check formatting a DigitList. DigitList is internal, but this is
6908 // a critical interface that must work.
6909 UErrorCode status = U_ZERO_ERROR;
6910 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6911 if (U_FAILURE(status) || fmtr == NULL) {
6912 dataerrln("Unable to create NumberFormat");
6913 } else {
6914 UnicodeString formattedResult;
6915 DecimalQuantity dl;
6916 StringPiece num("123.4566666666666666666666666666666666621E+40");
6917 dl.setToDecNumber(num, status);
6918 ASSERT_SUCCESS(status);
6919 fmtr->format(dl, formattedResult, NULL, status);
6920 ASSERT_SUCCESS(status);
6921 ASSERT_EQUALS("1,234,566,666,666,666,666,666,666,666,666,666,666,621,000", formattedResult);
6922
6923 status = U_ZERO_ERROR;
6924 num.set("666.666");
6925 dl.setToDecNumber(num, status);
6926 FieldPosition pos(NumberFormat::FRACTION_FIELD);
6927 ASSERT_SUCCESS(status);
6928 formattedResult.remove();
6929 fmtr->format(dl, formattedResult, pos, status);
6930 ASSERT_SUCCESS(status);
6931 ASSERT_EQUALS("666.666", formattedResult);
6932 ASSERT_EQUALS(4, pos.getBeginIndex());
6933 ASSERT_EQUALS(7, pos.getEndIndex());
6934 delete fmtr;
6935 }
6936 }
6937
6938 {
6939 // Check a parse with a formatter with a multiplier.
6940 UErrorCode status = U_ZERO_ERROR;
6941 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_PERCENT, status);
6942 if (U_FAILURE(status) || fmtr == NULL) {
6943 dataerrln("Unable to create NumberFormat");
6944 } else {
6945 UnicodeString input = "1.84%";
6946 Formattable result;
6947 fmtr->parse(input, result, status);
6948 ASSERT_SUCCESS(status);
6949 ASSERT_EQUALS("0.0184", result.getDecimalNumber(status).data());
6950 //std::cout << result.getDecimalNumber(status).data();
6951 delete fmtr;
6952 }
6953 }
6954
6955 #if U_PLATFORM != U_PF_CYGWIN || defined(CYGWINMSVC)
6956 /*
6957 * This test fails on Cygwin (1.7.16) using GCC because of a rounding issue with strtod().
6958 * See #9463
6959 */
6960 {
6961 // Check that a parse returns a decimal number with full accuracy
6962 UErrorCode status = U_ZERO_ERROR;
6963 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6964 if (U_FAILURE(status) || fmtr == NULL) {
6965 dataerrln("Unable to create NumberFormat");
6966 } else {
6967 UnicodeString input = "1.002200044400088880000070000";
6968 Formattable result;
6969 fmtr->parse(input, result, status);
6970 ASSERT_SUCCESS(status);
6971 ASSERT_EQUALS(0, strcmp("1.00220004440008888000007", result.getDecimalNumber(status).data()));
6972 ASSERT_EQUALS(1.00220004440008888, result.getDouble());
6973 //std::cout << result.getDecimalNumber(status).data();
6974 delete fmtr;
6975 }
6976 }
6977 #endif
6978
6979 }
6980
TestCurrencyFractionDigits()6981 void NumberFormatTest::TestCurrencyFractionDigits() {
6982 UErrorCode status = U_ZERO_ERROR;
6983 UnicodeString text1, text2;
6984 double value = 99.12345;
6985
6986 // Create currenct instance
6987 NumberFormat* fmt = NumberFormat::createCurrencyInstance("ja_JP", status);
6988 if (U_FAILURE(status) || fmt == NULL) {
6989 dataerrln("Unable to create NumberFormat");
6990 } else {
6991 fmt->format(value, text1);
6992
6993 // Reset the same currency and format the test value again
6994 fmt->setCurrency(fmt->getCurrency(), status);
6995 ASSERT_SUCCESS(status);
6996 fmt->format(value, text2);
6997
6998 if (text1 != text2) {
6999 errln((UnicodeString)"NumberFormat::format() should return the same result - text1="
7000 + text1 + " text2=" + text2);
7001 }
7002 }
7003 delete fmt;
7004 }
7005
TestExponentParse()7006 void NumberFormatTest::TestExponentParse() {
7007
7008 UErrorCode status = U_ZERO_ERROR;
7009 Formattable result;
7010 ParsePosition parsePos(0);
7011
7012 // set the exponent symbol
7013 status = U_ZERO_ERROR;
7014 DecimalFormatSymbols symbols(Locale::getDefault(), status);
7015 if(U_FAILURE(status)) {
7016 dataerrln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (Default)");
7017 return;
7018 }
7019
7020 // create format instance
7021 status = U_ZERO_ERROR;
7022 DecimalFormat fmt(u"#####", symbols, status);
7023 if(U_FAILURE(status)) {
7024 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
7025 }
7026
7027 // parse the text
7028 fmt.parse("5.06e-27", result, parsePos);
7029 if(result.getType() != Formattable::kDouble &&
7030 result.getDouble() != 5.06E-27 &&
7031 parsePos.getIndex() != 8
7032 )
7033 {
7034 errln("ERROR: parse failed - expected 5.06E-27, 8 - returned %d, %i",
7035 result.getDouble(), parsePos.getIndex());
7036 }
7037 }
7038
TestExplicitParents()7039 void NumberFormatTest::TestExplicitParents() {
7040
7041 /* Test that number formats are properly inherited from es_419 */
7042 /* These could be subject to change if the CLDR data changes */
7043 static const char* parentLocaleTests[][2]= {
7044 /* locale ID */ /* expected */
7045 {"es_CO", "1.250,75" },
7046 {"es_ES", "1.250,75" },
7047 {"es_GQ", "1.250,75" },
7048 {"es_MX", "1,250.75" },
7049 {"es_US", "1,250.75" },
7050 {"es_VE", "1.250,75" },
7051 };
7052
7053 UnicodeString s;
7054
7055 for(int i=0; i < UPRV_LENGTHOF(parentLocaleTests); i++){
7056 UErrorCode status = U_ZERO_ERROR;
7057 const char *localeID = parentLocaleTests[i][0];
7058 UnicodeString expected(parentLocaleTests[i][1], -1, US_INV);
7059 expected = expected.unescape();
7060 char loc[256]={0};
7061 uloc_canonicalize(localeID, loc, 256, &status);
7062 NumberFormat *fmt= NumberFormat::createInstance(Locale(loc), status);
7063 if(U_FAILURE(status)){
7064 dataerrln("Could not create number formatter for locale %s - %s",localeID, u_errorName(status));
7065 continue;
7066 }
7067 s.remove();
7068 fmt->format(1250.75, s);
7069 if(s!=expected){
7070 errln(UnicodeString("FAIL: Expected: ")+expected
7071 + UnicodeString(" Got: ") + s
7072 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
7073 }
7074 if (U_FAILURE(status)){
7075 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
7076 }
7077 delete fmt;
7078 }
7079
7080 }
7081
7082 /**
7083 * Test available numbering systems API.
7084 */
TestAvailableNumberingSystems()7085 void NumberFormatTest::TestAvailableNumberingSystems() {
7086 IcuTestErrorCode status(*this, "TestAvailableNumberingSystems");
7087 StringEnumeration *availableNumberingSystems = NumberingSystem::getAvailableNames(status);
7088 CHECK_DATA(status, "NumberingSystem::getAvailableNames()");
7089
7090 int32_t nsCount = availableNumberingSystems->count(status);
7091 if ( nsCount < 74 ) {
7092 errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 74, got %d",nsCount);
7093 }
7094
7095 /* A relatively simple test of the API. We call getAvailableNames() and cycle through */
7096 /* each name returned, attempting to create a numbering system based on that name and */
7097 /* verifying that the name returned from the resulting numbering system is the same */
7098 /* one that we initially thought. */
7099
7100 int32_t len;
7101 const char* prevName = nullptr;
7102 for ( int32_t i = 0 ; i < nsCount ; i++ ) {
7103 const char *nsname = availableNumberingSystems->next(&len,status);
7104 NumberingSystem* ns = NumberingSystem::createInstanceByName(nsname,status);
7105 logln("OK for ns = %s",nsname);
7106 if ( uprv_strcmp(nsname,ns->getName()) ) {
7107 errln("FAIL: Numbering system name didn't match for name = %s\n",nsname);
7108 }
7109 if (prevName != nullptr) {
7110 int comp = uprv_strcmp(prevName, nsname);
7111 assertTrue(
7112 UnicodeString(u"NS names should be in alphabetical order: ")
7113 + prevName + u" vs " + nsname,
7114 // TODO: Why are there duplicates? This doesn't work if comp < 0
7115 comp <= 0);
7116 }
7117 prevName = nsname;
7118
7119 delete ns;
7120 }
7121
7122 LocalPointer<NumberingSystem> dummy(NumberingSystem::createInstanceByName("dummy", status), status);
7123 status.expectErrorAndReset(U_UNSUPPORTED_ERROR);
7124 assertTrue("Non-existent numbering system should return null", dummy.isNull());
7125
7126 delete availableNumberingSystems;
7127 }
7128
7129 void
Test9087(void)7130 NumberFormatTest::Test9087(void)
7131 {
7132 U_STRING_DECL(pattern,"#",1);
7133 U_STRING_INIT(pattern,"#",1);
7134
7135 U_STRING_DECL(infstr,"INF",3);
7136 U_STRING_INIT(infstr,"INF",3);
7137
7138 U_STRING_DECL(nanstr,"NAN",3);
7139 U_STRING_INIT(nanstr,"NAN",3);
7140
7141 UChar outputbuf[50] = {0};
7142 UErrorCode status = U_ZERO_ERROR;
7143 UNumberFormat* fmt = unum_open(UNUM_PATTERN_DECIMAL,pattern,1,NULL,NULL,&status);
7144 if ( U_FAILURE(status) ) {
7145 dataerrln("FAIL: error in unum_open() - %s", u_errorName(status));
7146 return;
7147 }
7148
7149 unum_setSymbol(fmt,UNUM_INFINITY_SYMBOL,infstr,3,&status);
7150 unum_setSymbol(fmt,UNUM_NAN_SYMBOL,nanstr,3,&status);
7151 if ( U_FAILURE(status) ) {
7152 errln("FAIL: error setting symbols");
7153 }
7154
7155 double inf = uprv_getInfinity();
7156
7157 unum_setAttribute(fmt,UNUM_ROUNDING_MODE,UNUM_ROUND_HALFEVEN);
7158 unum_setDoubleAttribute(fmt,UNUM_ROUNDING_INCREMENT,0);
7159
7160 UFieldPosition position = { 0, 0, 0};
7161 unum_formatDouble(fmt,inf,outputbuf,50,&position,&status);
7162
7163 if ( u_strcmp(infstr, outputbuf)) {
7164 errln((UnicodeString)"FAIL: unexpected result for infinity - expected " + infstr + " got " + outputbuf);
7165 }
7166
7167 unum_close(fmt);
7168 }
7169
TestFormatFastpaths()7170 void NumberFormatTest::TestFormatFastpaths() {
7171 // get some additional case
7172 {
7173 UErrorCode status=U_ZERO_ERROR;
7174 DecimalFormat df(UnicodeString(u"0000"),status);
7175 if (U_FAILURE(status)) {
7176 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7177 } else {
7178 int64_t long_number = 1;
7179 UnicodeString expect = "0001";
7180 UnicodeString result;
7181 FieldPosition pos;
7182 df.format(long_number, result, pos);
7183 if(U_FAILURE(status)||expect!=result) {
7184 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s",
7185 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7186 } else {
7187 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
7188 }
7189 }
7190 }
7191 {
7192 UErrorCode status=U_ZERO_ERROR;
7193 DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7194 if (U_FAILURE(status)) {
7195 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7196 } else {
7197 int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
7198 // uint8_t bits[8];
7199 // memcpy(bits,&long_number,8);
7200 // for(int i=0;i<8;i++) {
7201 // logln("bits: %02X", (unsigned int)bits[i]);
7202 // }
7203 UnicodeString expect = "-9223372036854775808";
7204 UnicodeString result;
7205 FieldPosition pos;
7206 df.format(long_number, result, pos);
7207 if(U_FAILURE(status)||expect!=result) {
7208 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775808",
7209 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7210 } else {
7211 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
7212 }
7213 }
7214 }
7215 {
7216 UErrorCode status=U_ZERO_ERROR;
7217 DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7218 if (U_FAILURE(status)) {
7219 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7220 } else {
7221 int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
7222 // uint8_t bits[8];
7223 // memcpy(bits,&long_number,8);
7224 // for(int i=0;i<8;i++) {
7225 // logln("bits: %02X", (unsigned int)bits[i]);
7226 // }
7227 UnicodeString expect = "9223372036854775807";
7228 UnicodeString result;
7229 FieldPosition pos;
7230 df.format(long_number, result, pos);
7231 if(U_FAILURE(status)||expect!=result) {
7232 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on U_INT64_MAX",
7233 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7234 } else {
7235 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
7236 }
7237 }
7238 }
7239 {
7240 UErrorCode status=U_ZERO_ERROR;
7241 DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7242 if (U_FAILURE(status)) {
7243 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7244 } else {
7245 int64_t long_number = 0;
7246 // uint8_t bits[8];
7247 // memcpy(bits,&long_number,8);
7248 // for(int i=0;i<8;i++) {
7249 // logln("bits: %02X", (unsigned int)bits[i]);
7250 // }
7251 UnicodeString expect = "0000000000000000000";
7252 UnicodeString result;
7253 FieldPosition pos;
7254 df.format(long_number, result, pos);
7255 if(U_FAILURE(status)||expect!=result) {
7256 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on 0",
7257 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7258 } else {
7259 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
7260 }
7261 }
7262 }
7263 {
7264 UErrorCode status=U_ZERO_ERROR;
7265 DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7266 if (U_FAILURE(status)) {
7267 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7268 } else {
7269 int64_t long_number = U_INT64_MIN + 1;
7270 UnicodeString expect = "-9223372036854775807";
7271 UnicodeString result;
7272 FieldPosition pos;
7273 df.format(long_number, result, pos);
7274 if(U_FAILURE(status)||expect!=result) {
7275 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775807",
7276 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7277 } else {
7278 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
7279 }
7280 }
7281 }
7282 }
7283
7284
TestFormattableSize(void)7285 void NumberFormatTest::TestFormattableSize(void) {
7286 if(sizeof(Formattable) > 112) {
7287 errln("Error: sizeof(Formattable)=%d, 112=%d\n",
7288 sizeof(Formattable), 112);
7289 } else if(sizeof(Formattable) < 112) {
7290 logln("Warning: sizeof(Formattable)=%d, 112=%d\n",
7291 sizeof(Formattable), 112);
7292 } else {
7293 logln("sizeof(Formattable)=%d, 112=%d\n",
7294 sizeof(Formattable), 112);
7295 }
7296 }
7297
testFormattableAsUFormattable(const char * file,int line,Formattable & f)7298 UBool NumberFormatTest::testFormattableAsUFormattable(const char *file, int line, Formattable &f) {
7299 UnicodeString fileLine = UnicodeString(file)+UnicodeString(":")+line+UnicodeString(": ");
7300
7301 UFormattable *u = f.toUFormattable();
7302 logln();
7303 if (u == NULL) {
7304 errln("%s:%d: Error: f.toUFormattable() retuned NULL.");
7305 return FALSE;
7306 }
7307 logln("%s:%d: comparing Formattable with UFormattable", file, line);
7308 logln(fileLine + toString(f));
7309
7310 UErrorCode status = U_ZERO_ERROR;
7311 UErrorCode valueStatus = U_ZERO_ERROR;
7312 UFormattableType expectUType = UFMT_COUNT; // invalid
7313
7314 UBool triedExact = FALSE; // did we attempt an exact comparison?
7315 UBool exactMatch = FALSE; // was the exact comparison true?
7316
7317 switch( f.getType() ) {
7318 case Formattable::kDate:
7319 expectUType = UFMT_DATE;
7320 exactMatch = (f.getDate()==ufmt_getDate(u, &valueStatus));
7321 triedExact = TRUE;
7322 break;
7323 case Formattable::kDouble:
7324 expectUType = UFMT_DOUBLE;
7325 exactMatch = (f.getDouble()==ufmt_getDouble(u, &valueStatus));
7326 triedExact = TRUE;
7327 break;
7328 case Formattable::kLong:
7329 expectUType = UFMT_LONG;
7330 exactMatch = (f.getLong()==ufmt_getLong(u, &valueStatus));
7331 triedExact = TRUE;
7332 break;
7333 case Formattable::kString:
7334 expectUType = UFMT_STRING;
7335 {
7336 UnicodeString str;
7337 f.getString(str);
7338 int32_t len;
7339 const UChar* uch = ufmt_getUChars(u, &len, &valueStatus);
7340 if(U_SUCCESS(valueStatus)) {
7341 UnicodeString str2(uch, len);
7342 assertTrue("UChar* NULL-terminated", uch[len]==0);
7343 exactMatch = (str == str2);
7344 }
7345 triedExact = TRUE;
7346 }
7347 break;
7348 case Formattable::kArray:
7349 expectUType = UFMT_ARRAY;
7350 triedExact = TRUE;
7351 {
7352 int32_t count = ufmt_getArrayLength(u, &valueStatus);
7353 int32_t count2;
7354 const Formattable *array2 = f.getArray(count2);
7355 exactMatch = assertEquals(fileLine + " array count", count, count2);
7356
7357 if(exactMatch) {
7358 for(int i=0;U_SUCCESS(valueStatus) && i<count;i++) {
7359 UFormattable *uu = ufmt_getArrayItemByIndex(u, i, &valueStatus);
7360 if(*Formattable::fromUFormattable(uu) != (array2[i])) {
7361 errln("%s:%d: operator== did not match at index[%d] - %p vs %p", file, line, i,
7362 (const void*)Formattable::fromUFormattable(uu), (const void*)&(array2[i]));
7363 exactMatch = FALSE;
7364 } else {
7365 if(!testFormattableAsUFormattable("(sub item)",i,*Formattable::fromUFormattable(uu))) {
7366 exactMatch = FALSE;
7367 }
7368 }
7369 }
7370 }
7371 }
7372 break;
7373 case Formattable::kInt64:
7374 expectUType = UFMT_INT64;
7375 exactMatch = (f.getInt64()==ufmt_getInt64(u, &valueStatus));
7376 triedExact = TRUE;
7377 break;
7378 case Formattable::kObject:
7379 expectUType = UFMT_OBJECT;
7380 exactMatch = (f.getObject()==ufmt_getObject(u, &valueStatus));
7381 triedExact = TRUE;
7382 break;
7383 }
7384 UFormattableType uType = ufmt_getType(u, &status);
7385
7386 if(U_FAILURE(status)) {
7387 errln("%s:%d: Error calling ufmt_getType - %s", file, line, u_errorName(status));
7388 return FALSE;
7389 }
7390
7391 if(uType != expectUType) {
7392 errln("%s:%d: got type (%d) expected (%d) from ufmt_getType", file, line, (int) uType, (int) expectUType);
7393 }
7394
7395 if(triedExact) {
7396 if(U_FAILURE(valueStatus)) {
7397 errln("%s:%d: got err %s trying to ufmt_get...() for exact match check", file, line, u_errorName(valueStatus));
7398 } else if(!exactMatch) {
7399 errln("%s:%d: failed exact match for the Formattable type", file, line);
7400 } else {
7401 logln("%s:%d: exact match OK", file, line);
7402 }
7403 } else {
7404 logln("%s:%d: note, did not attempt exact match for this formattable type", file, line);
7405 }
7406
7407 if( assertEquals(fileLine + " isNumeric()", f.isNumeric(), ufmt_isNumeric(u))
7408 && f.isNumeric()) {
7409 UErrorCode convStatus = U_ZERO_ERROR;
7410
7411 if(uType != UFMT_INT64) { // may fail to compare
7412 assertTrue(fileLine + " as doubles ==", f.getDouble(convStatus)==ufmt_getDouble(u, &convStatus));
7413 }
7414
7415 if( assertSuccess(fileLine + " (numeric conversion status)", convStatus) ) {
7416 StringPiece fDecNum = f.getDecimalNumber(convStatus);
7417 #if 1
7418 int32_t len;
7419 const char *decNumChars = ufmt_getDecNumChars(u, &len, &convStatus);
7420 #else
7421 // copy version
7422 char decNumChars[200];
7423 int32_t len = ufmt_getDecNumChars(u, decNumChars, 200, &convStatus);
7424 #endif
7425
7426 if( assertSuccess(fileLine + " (decNumbers conversion)", convStatus) ) {
7427 logln(fileLine + decNumChars);
7428 assertEquals(fileLine + " decNumChars length==", len, fDecNum.length());
7429 assertEquals(fileLine + " decNumChars digits", decNumChars, fDecNum.data());
7430 }
7431
7432 UErrorCode int64ConversionF = U_ZERO_ERROR;
7433 int64_t l = f.getInt64(int64ConversionF);
7434 UErrorCode int64ConversionU = U_ZERO_ERROR;
7435 int64_t r = ufmt_getInt64(u, &int64ConversionU);
7436
7437 if( (l==r)
7438 && ( uType != UFMT_INT64 ) // int64 better not overflow
7439 && (U_INVALID_FORMAT_ERROR==int64ConversionU)
7440 && (U_INVALID_FORMAT_ERROR==int64ConversionF) ) {
7441 logln("%s:%d: OK: 64 bit overflow", file, line);
7442 } else {
7443 assertEquals(fileLine + " as int64 ==", l, r);
7444 assertSuccess(fileLine + " Formattable.getnt64()", int64ConversionF);
7445 assertSuccess(fileLine + " ufmt_getInt64()", int64ConversionU);
7446 }
7447 }
7448 }
7449 return exactMatch || !triedExact;
7450 }
7451
TestUFormattable(void)7452 void NumberFormatTest::TestUFormattable(void) {
7453 {
7454 // test that a default formattable is equal to Formattable()
7455 UErrorCode status = U_ZERO_ERROR;
7456 LocalUFormattablePointer defaultUFormattable(ufmt_open(&status));
7457 assertSuccess("calling umt_open", status);
7458 Formattable defaultFormattable;
7459 assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7460 (defaultFormattable
7461 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7462 assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7463 (defaultFormattable
7464 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7465 assertTrue((UnicodeString)"comparing Formattable() round tripped through UFormattable",
7466 (defaultFormattable
7467 == *(Formattable::fromUFormattable(defaultFormattable.toUFormattable()))));
7468 assertTrue((UnicodeString)"comparing &Formattable() round tripped through UFormattable",
7469 ((&defaultFormattable)
7470 == Formattable::fromUFormattable(defaultFormattable.toUFormattable())));
7471 assertFalse((UnicodeString)"comparing &Formattable() with ufmt_open()",
7472 ((&defaultFormattable)
7473 == Formattable::fromUFormattable(defaultUFormattable.getAlias())));
7474 testFormattableAsUFormattable(__FILE__, __LINE__, defaultFormattable);
7475 }
7476 // test some random Formattables
7477 {
7478 Formattable f(ucal_getNow(), Formattable::kIsDate);
7479 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7480 }
7481 {
7482 Formattable f((double)1.61803398874989484820); // golden ratio
7483 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7484 }
7485 {
7486 Formattable f((int64_t)80994231587905127LL); // weight of the moon, in kilotons http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
7487 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7488 }
7489 {
7490 Formattable f((int32_t)4); // random number, source: http://www.xkcd.com/221/
7491 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7492 }
7493 {
7494 Formattable f("Hello world."); // should be invariant?
7495 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7496 }
7497 {
7498 UErrorCode status2 = U_ZERO_ERROR;
7499 Formattable f(StringPiece("73476730924573500000000.0"), status2); // weight of the moon, kg
7500 assertSuccess("Constructing a StringPiece", status2);
7501 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7502 }
7503 {
7504 UErrorCode status2 = U_ZERO_ERROR;
7505 UObject *obj = new Locale();
7506 Formattable f(obj);
7507 assertSuccess("Constructing a Formattable from a default constructed Locale()", status2);
7508 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7509 }
7510 {
7511 const Formattable array[] = {
7512 Formattable(ucal_getNow(), Formattable::kIsDate),
7513 Formattable((int32_t)4),
7514 Formattable((double)1.234),
7515 };
7516
7517 Formattable fa(array, 3);
7518 testFormattableAsUFormattable(__FILE__, __LINE__, fa);
7519 }
7520 }
7521
TestSignificantDigits(void)7522 void NumberFormatTest::TestSignificantDigits(void) {
7523 double input[] = {
7524 0, 0,
7525 0.1, -0.1,
7526 123, -123,
7527 12345, -12345,
7528 123.45, -123.45,
7529 123.44501, -123.44501,
7530 0.001234, -0.001234,
7531 0.00000000123, -0.00000000123,
7532 0.0000000000000000000123, -0.0000000000000000000123,
7533 1.2, -1.2,
7534 0.0000000012344501, -0.0000000012344501,
7535 123445.01, -123445.01,
7536 12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0,
7537 };
7538 const char* expected[] = {
7539 "0.00", "0.00",
7540 "0.100", "-0.100",
7541 "123", "-123",
7542 "12345", "-12345",
7543 "123.45", "-123.45",
7544 "123.45", "-123.45",
7545 "0.001234", "-0.001234",
7546 "0.00000000123", "-0.00000000123",
7547 "0.0000000000000000000123", "-0.0000000000000000000123",
7548 "1.20", "-1.20",
7549 "0.0000000012345", "-0.0000000012345",
7550 "123450", "-123450",
7551 "12345000000000000000000000000000000", "-12345000000000000000000000000000000",
7552 };
7553
7554 UErrorCode status = U_ZERO_ERROR;
7555 Locale locale("en_US");
7556 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7557 NumberFormat::createInstance(locale, status)));
7558 CHECK_DATA(status,"NumberFormat::createInstance");
7559
7560 numberFormat->setSignificantDigitsUsed(TRUE);
7561 numberFormat->setMinimumSignificantDigits(3);
7562 numberFormat->setMaximumSignificantDigits(5);
7563 numberFormat->setGroupingUsed(false);
7564
7565 UnicodeString result;
7566 UnicodeString expectedResult;
7567 for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
7568 numberFormat->format(input[i], result);
7569 UnicodeString expectedResult(expected[i]);
7570 if (result != expectedResult) {
7571 errln((UnicodeString)"Expected: '" + expectedResult + "' got '" + result);
7572 }
7573 result.remove();
7574 }
7575
7576 // Test for ICU-20063
7577 {
7578 DecimalFormat df({"en-us", status}, status);
7579 df.setSignificantDigitsUsed(TRUE);
7580 expect(df, 9.87654321, u"9.87654");
7581 df.setMaximumSignificantDigits(3);
7582 expect(df, 9.87654321, u"9.88");
7583 // setSignificantDigitsUsed with maxSig only
7584 df.setSignificantDigitsUsed(TRUE);
7585 expect(df, 9.87654321, u"9.88");
7586 df.setMinimumSignificantDigits(2);
7587 expect(df, 9, u"9.0");
7588 // setSignificantDigitsUsed with both minSig and maxSig
7589 df.setSignificantDigitsUsed(TRUE);
7590 expect(df, 9, u"9.0");
7591 // setSignificantDigitsUsed to false: should revert to fraction rounding
7592 df.setSignificantDigitsUsed(FALSE);
7593 expect(df, 9.87654321, u"9.876543");
7594 expect(df, 9, u"9");
7595 df.setSignificantDigitsUsed(TRUE);
7596 df.setMinimumSignificantDigits(2);
7597 expect(df, 9.87654321, u"9.87654");
7598 expect(df, 9, u"9.0");
7599 // setSignificantDigitsUsed with minSig only
7600 df.setSignificantDigitsUsed(TRUE);
7601 expect(df, 9.87654321, u"9.87654");
7602 expect(df, 9, u"9.0");
7603 }
7604 }
7605
TestShowZero()7606 void NumberFormatTest::TestShowZero() {
7607 UErrorCode status = U_ZERO_ERROR;
7608 Locale locale("en_US");
7609 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7610 NumberFormat::createInstance(locale, status)));
7611 CHECK_DATA(status, "NumberFormat::createInstance");
7612
7613 numberFormat->setSignificantDigitsUsed(TRUE);
7614 numberFormat->setMaximumSignificantDigits(3);
7615
7616 UnicodeString result;
7617 numberFormat->format(0.0, result);
7618 if (result != "0") {
7619 errln((UnicodeString)"Expected: 0, got " + result);
7620 }
7621 }
7622
TestBug9936()7623 void NumberFormatTest::TestBug9936() {
7624 UErrorCode status = U_ZERO_ERROR;
7625 Locale locale("en_US");
7626 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7627 NumberFormat::createInstance(locale, status)));
7628 if (U_FAILURE(status)) {
7629 dataerrln("File %s, Line %d: status = %s.\n", __FILE__, __LINE__, u_errorName(status));
7630 return;
7631 }
7632
7633 if (numberFormat->areSignificantDigitsUsed() == TRUE) {
7634 errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
7635 }
7636 numberFormat->setSignificantDigitsUsed(TRUE);
7637 if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7638 errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7639 }
7640
7641 numberFormat->setSignificantDigitsUsed(FALSE);
7642 if (numberFormat->areSignificantDigitsUsed() == TRUE) {
7643 errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
7644 }
7645
7646 numberFormat->setMinimumSignificantDigits(3);
7647 if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7648 errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7649 }
7650
7651 numberFormat->setSignificantDigitsUsed(FALSE);
7652 numberFormat->setMaximumSignificantDigits(6);
7653 if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7654 errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7655 }
7656
7657 }
7658
TestParseNegativeWithFaLocale()7659 void NumberFormatTest::TestParseNegativeWithFaLocale() {
7660 UErrorCode status = U_ZERO_ERROR;
7661 DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status);
7662 CHECK_DATA(status, "NumberFormat::createInstance");
7663 test->setLenient(TRUE);
7664 Formattable af;
7665 ParsePosition ppos;
7666 UnicodeString value("\\u200e-0,5");
7667 value = value.unescape();
7668 test->parse(value, af, ppos);
7669 if (ppos.getIndex() == 0) {
7670 errln("Expected -0,5 to parse for Farsi.");
7671 }
7672 delete test;
7673 }
7674
TestParseNegativeWithAlternateMinusSign()7675 void NumberFormatTest::TestParseNegativeWithAlternateMinusSign() {
7676 UErrorCode status = U_ZERO_ERROR;
7677 DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("en", status);
7678 CHECK_DATA(status, "NumberFormat::createInstance");
7679 test->setLenient(TRUE);
7680 Formattable af;
7681 ParsePosition ppos;
7682 UnicodeString value("\\u208B0.5");
7683 value = value.unescape();
7684 test->parse(value, af, ppos);
7685 if (ppos.getIndex() == 0) {
7686 errln(UnicodeString("Expected ") + value + UnicodeString(" to parse."));
7687 }
7688 delete test;
7689 }
7690
TestCustomCurrencySignAndSeparator()7691 void NumberFormatTest::TestCustomCurrencySignAndSeparator() {
7692 UErrorCode status = U_ZERO_ERROR;
7693 DecimalFormatSymbols custom(Locale::getUS(), status);
7694 CHECK(status, "DecimalFormatSymbols constructor");
7695
7696 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "*");
7697 custom.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, "^");
7698 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, ":");
7699
7700 UnicodeString pat(" #,##0.00");
7701 pat.insert(0, (UChar)0x00A4);
7702
7703 DecimalFormat fmt(pat, custom, status);
7704 CHECK(status, "DecimalFormat constructor");
7705
7706 UnicodeString numstr("* 1^234:56");
7707 expect2(fmt, (Formattable)((double)1234.56), numstr);
7708 }
7709
7710 typedef struct {
7711 const char * locale;
7712 UBool lenient;
7713 UnicodeString numString;
7714 double value;
7715 } SignsAndMarksItem;
7716
7717
TestParseSignsAndMarks()7718 void NumberFormatTest::TestParseSignsAndMarks() {
7719 const SignsAndMarksItem items[] = {
7720 // locale lenient numString value
7721 { "en", FALSE, CharsToUnicodeString("12"), 12 },
7722 { "en", TRUE, CharsToUnicodeString("12"), 12 },
7723 { "en", FALSE, CharsToUnicodeString("-23"), -23 },
7724 { "en", TRUE, CharsToUnicodeString("-23"), -23 },
7725 { "en", TRUE, CharsToUnicodeString("- 23"), -23 },
7726 { "en", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
7727 { "en", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
7728 { "en", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
7729
7730 { "en@numbers=arab", FALSE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7731 { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7732 { "en@numbers=arab", FALSE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7733 { "en@numbers=arab", TRUE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7734 { "en@numbers=arab", TRUE, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
7735 { "en@numbers=arab", FALSE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7736 { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7737 { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
7738
7739 { "en@numbers=arabext", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7740 { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7741 { "en@numbers=arabext", FALSE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7742 { "en@numbers=arabext", TRUE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7743 { "en@numbers=arabext", TRUE, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
7744 { "en@numbers=arabext", FALSE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7745 { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7746 { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
7747
7748 { "he", FALSE, CharsToUnicodeString("12"), 12 },
7749 { "he", TRUE, CharsToUnicodeString("12"), 12 },
7750 { "he", FALSE, CharsToUnicodeString("-23"), -23 },
7751 { "he", TRUE, CharsToUnicodeString("-23"), -23 },
7752 { "he", TRUE, CharsToUnicodeString("- 23"), -23 },
7753 { "he", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
7754 { "he", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
7755 { "he", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
7756
7757 { "ar", FALSE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7758 { "ar", TRUE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7759 { "ar", FALSE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7760 { "ar", TRUE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7761 { "ar", TRUE, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
7762 { "ar", FALSE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7763 { "ar", TRUE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7764 { "ar", TRUE, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
7765
7766 { "ar_MA", FALSE, CharsToUnicodeString("12"), 12 },
7767 { "ar_MA", TRUE, CharsToUnicodeString("12"), 12 },
7768 { "ar_MA", FALSE, CharsToUnicodeString("-23"), -23 },
7769 { "ar_MA", TRUE, CharsToUnicodeString("-23"), -23 },
7770 { "ar_MA", TRUE, CharsToUnicodeString("- 23"), -23 },
7771 { "ar_MA", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
7772 { "ar_MA", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
7773 { "ar_MA", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
7774
7775 { "fa", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7776 { "fa", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7777 { "fa", FALSE, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
7778 { "fa", TRUE, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
7779 { "fa", TRUE, CharsToUnicodeString("\\u2212 \\u06F6\\u06F7"), -67 },
7780 { "fa", FALSE, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
7781 { "fa", TRUE, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
7782 { "fa", TRUE, CharsToUnicodeString("\\u200E\\u2212\\u200E \\u06F6\\u06F7"), -67 },
7783
7784 { "ps", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7785 { "ps", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7786 { "ps", FALSE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7787 { "ps", TRUE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7788 { "ps", TRUE, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
7789 { "ps", FALSE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7790 { "ps", TRUE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7791 { "ps", TRUE, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
7792 { "ps", FALSE, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
7793 { "ps", TRUE, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
7794 { "ps", TRUE, CharsToUnicodeString("-\\u200E \\u06F6\\u06F7"), -67 },
7795 // terminator
7796 { NULL, 0, UnicodeString(""), 0 },
7797 };
7798
7799 const SignsAndMarksItem * itemPtr;
7800 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
7801 UErrorCode status = U_ZERO_ERROR;
7802 NumberFormat *numfmt = NumberFormat::createInstance(Locale(itemPtr->locale), status);
7803 if (U_SUCCESS(status)) {
7804 numfmt->setLenient(itemPtr->lenient);
7805 Formattable fmtobj;
7806 ParsePosition ppos;
7807 numfmt->parse(itemPtr->numString, fmtobj, ppos);
7808 if (ppos.getIndex() == itemPtr->numString.length()) {
7809 double parsedValue = fmtobj.getDouble(status);
7810 if (U_FAILURE(status) || parsedValue != itemPtr->value) {
7811 errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives value " + parsedValue);
7812 }
7813 } else {
7814 errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives position " + ppos.getIndex());
7815 }
7816 } else {
7817 dataerrln("FAIL: NumberFormat::createInstance for locale % gives error %s", itemPtr->locale, u_errorName(status));
7818 }
7819 delete numfmt;
7820 }
7821 }
7822
7823 typedef struct {
7824 DecimalFormat::ERoundingMode mode;
7825 double value;
7826 UnicodeString expected;
7827 } Test10419Data;
7828
7829
7830 // Tests that rounding works right when fractional digits is set to 0.
Test10419RoundingWith0FractionDigits()7831 void NumberFormatTest::Test10419RoundingWith0FractionDigits() {
7832 const Test10419Data items[] = {
7833 { DecimalFormat::kRoundCeiling, 1.488, "2"},
7834 { DecimalFormat::kRoundDown, 1.588, "1"},
7835 { DecimalFormat::kRoundFloor, 1.888, "1"},
7836 { DecimalFormat::kRoundHalfDown, 1.5, "1"},
7837 { DecimalFormat::kRoundHalfEven, 2.5, "2"},
7838 { DecimalFormat::kRoundHalfUp, 2.5, "3"},
7839 { DecimalFormat::kRoundUp, 1.5, "2"},
7840 };
7841 UErrorCode status = U_ZERO_ERROR;
7842 LocalPointer<DecimalFormat> decfmt((DecimalFormat *) NumberFormat::createInstance(Locale("en_US"), status));
7843 if (U_FAILURE(status)) {
7844 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
7845 return;
7846 }
7847 for (int32_t i = 0; i < UPRV_LENGTHOF(items); ++i) {
7848 decfmt->setRoundingMode(items[i].mode);
7849 decfmt->setMaximumFractionDigits(0);
7850 UnicodeString actual;
7851 if (items[i].expected != decfmt->format(items[i].value, actual)) {
7852 errln("Expected " + items[i].expected + ", got " + actual);
7853 }
7854 }
7855 }
7856
Test10468ApplyPattern()7857 void NumberFormatTest::Test10468ApplyPattern() {
7858 // Padding char of fmt is now 'a'
7859 UErrorCode status = U_ZERO_ERROR;
7860 DecimalFormat fmt("'I''ll'*a###.##", status);
7861
7862 if (U_FAILURE(status)) {
7863 errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7864 return;
7865 }
7866
7867 assertEquals("Padding character should be 'a'.", u"a", fmt.getPadCharacterString());
7868
7869 // Padding char of fmt ought to be '*' since that is the default and no
7870 // explicit padding char is specified in the new pattern.
7871 fmt.applyPattern("AA#,##0.00ZZ", status);
7872
7873 // Oops this still prints 'a' even though we changed the pattern.
7874 assertEquals("applyPattern did not clear padding character.", u" ", fmt.getPadCharacterString());
7875 }
7876
TestRoundingScientific10542()7877 void NumberFormatTest::TestRoundingScientific10542() {
7878 UErrorCode status = U_ZERO_ERROR;
7879 DecimalFormat format("0.00E0", status);
7880 if (U_FAILURE(status)) {
7881 errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7882 return;
7883 }
7884
7885 DecimalFormat::ERoundingMode roundingModes[] = {
7886 DecimalFormat::kRoundCeiling,
7887 DecimalFormat::kRoundDown,
7888 DecimalFormat::kRoundFloor,
7889 DecimalFormat::kRoundHalfDown,
7890 DecimalFormat::kRoundHalfEven,
7891 DecimalFormat::kRoundHalfUp,
7892 DecimalFormat::kRoundUp};
7893 const char *descriptions[] = {
7894 "Round Ceiling",
7895 "Round Down",
7896 "Round Floor",
7897 "Round half down",
7898 "Round half even",
7899 "Round half up",
7900 "Round up"};
7901
7902 {
7903 double values[] = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016};
7904 // The order of these expected values correspond to the order of roundingModes and the order of values.
7905 const char *expected[] = {
7906 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.02E-3", "3.02E-3", "3.02E-3",
7907 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7908 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7909 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.02E-3",
7910 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7911 "-3.01E-3", "-3.01E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7912 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.02E-3", "3.02E-3", "3.02E-3"};
7913 verifyRounding(
7914 format,
7915 values,
7916 expected,
7917 roundingModes,
7918 descriptions,
7919 UPRV_LENGTHOF(values),
7920 UPRV_LENGTHOF(roundingModes));
7921 }
7922 {
7923 double values[] = {-3006.0, -3005, -3004, 3014, 3015, 3016};
7924 // The order of these expected values correspond to the order of roundingModes and the order of values.
7925 const char *expected[] = {
7926 "-3.00E3", "-3.00E3", "-3.00E3", "3.02E3", "3.02E3", "3.02E3",
7927 "-3.00E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.01E3",
7928 "-3.01E3", "-3.01E3", "-3.01E3", "3.01E3", "3.01E3", "3.01E3",
7929 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.02E3",
7930 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7931 "-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7932 "-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"};
7933 verifyRounding(
7934 format,
7935 values,
7936 expected,
7937 roundingModes,
7938 descriptions,
7939 UPRV_LENGTHOF(values),
7940 UPRV_LENGTHOF(roundingModes));
7941 }
7942 /* Commented out for now until we decide how rounding to zero should work, +0 vs. -0
7943 {
7944 double values[] = {0.0, -0.0};
7945 // The order of these expected values correspond to the order of roundingModes and the order of values.
7946 const char *expected[] = {
7947 "0.00E0", "-0.00E0",
7948 "0.00E0", "-0.00E0",
7949 "0.00E0", "-0.00E0",
7950 "0.00E0", "-0.00E0",
7951 "0.00E0", "-0.00E0",
7952 "0.00E0", "-0.00E0",
7953 "0.00E0", "-0.00E0"};
7954 verifyRounding(
7955 format,
7956 values,
7957 expected,
7958 roundingModes,
7959 descriptions,
7960 UPRV_LENGTHOF(values),
7961 UPRV_LENGTHOF(roundingModes));
7962 }
7963 */
7964 {
7965
7966 double values[] = {1e25, 1e25 + 1e15, 1e25 - 1e15};
7967 // The order of these expected values correspond to the order of roundingModes and the order of values.
7968 const char *expected[] = {
7969 "1.00E25", "1.01E25", "1.00E25",
7970 "1.00E25", "1.00E25", "9.99E24",
7971 "1.00E25", "1.00E25", "9.99E24",
7972 "1.00E25", "1.00E25", "1.00E25",
7973 "1.00E25", "1.00E25", "1.00E25",
7974 "1.00E25", "1.00E25", "1.00E25",
7975 "1.00E25", "1.01E25", "1.00E25"};
7976 verifyRounding(
7977 format,
7978 values,
7979 expected,
7980 roundingModes,
7981 descriptions,
7982 UPRV_LENGTHOF(values),
7983 UPRV_LENGTHOF(roundingModes));
7984 }
7985 {
7986 double values[] = {-1e25, -1e25 + 1e15, -1e25 - 1e15};
7987 // The order of these expected values correspond to the order of roundingModes and the order of values.
7988 const char *expected[] = {
7989 "-1.00E25", "-9.99E24", "-1.00E25",
7990 "-1.00E25", "-9.99E24", "-1.00E25",
7991 "-1.00E25", "-1.00E25", "-1.01E25",
7992 "-1.00E25", "-1.00E25", "-1.00E25",
7993 "-1.00E25", "-1.00E25", "-1.00E25",
7994 "-1.00E25", "-1.00E25", "-1.00E25",
7995 "-1.00E25", "-1.00E25", "-1.01E25"};
7996 verifyRounding(
7997 format,
7998 values,
7999 expected,
8000 roundingModes,
8001 descriptions,
8002 UPRV_LENGTHOF(values),
8003 UPRV_LENGTHOF(roundingModes));
8004 }
8005 {
8006 double values[] = {1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
8007 // The order of these expected values correspond to the order of roundingModes and the order of values.
8008 const char *expected[] = {
8009 "1.00E-25", "1.01E-25", "1.00E-25",
8010 "1.00E-25", "1.00E-25", "9.99E-26",
8011 "1.00E-25", "1.00E-25", "9.99E-26",
8012 "1.00E-25", "1.00E-25", "1.00E-25",
8013 "1.00E-25", "1.00E-25", "1.00E-25",
8014 "1.00E-25", "1.00E-25", "1.00E-25",
8015 "1.00E-25", "1.01E-25", "1.00E-25"};
8016 verifyRounding(
8017 format,
8018 values,
8019 expected,
8020 roundingModes,
8021 descriptions,
8022 UPRV_LENGTHOF(values),
8023 UPRV_LENGTHOF(roundingModes));
8024 }
8025 {
8026 double values[] = {-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
8027 // The order of these expected values correspond to the order of roundingModes and the order of values.
8028 const char *expected[] = {
8029 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8030 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8031 "-1.00E-25", "-1.00E-25", "-1.01E-25",
8032 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8033 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8034 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8035 "-1.00E-25", "-1.00E-25", "-1.01E-25"};
8036 verifyRounding(
8037 format,
8038 values,
8039 expected,
8040 roundingModes,
8041 descriptions,
8042 UPRV_LENGTHOF(values),
8043 UPRV_LENGTHOF(roundingModes));
8044 }
8045 }
8046
TestZeroScientific10547()8047 void NumberFormatTest::TestZeroScientific10547() {
8048 UErrorCode status = U_ZERO_ERROR;
8049 DecimalFormat fmt("0.00E0", status);
8050 if (!assertSuccess("Format creation", status)) {
8051 return;
8052 }
8053 UnicodeString out;
8054 fmt.format(-0.0, out);
8055 assertEquals("format", "-0.00E0", out, true);
8056 }
8057
verifyRounding(DecimalFormat & format,const double * values,const char * const * expected,const DecimalFormat::ERoundingMode * roundingModes,const char * const * descriptions,int32_t valueSize,int32_t roundingModeSize)8058 void NumberFormatTest::verifyRounding(
8059 DecimalFormat& format,
8060 const double *values,
8061 const char * const *expected,
8062 const DecimalFormat::ERoundingMode *roundingModes,
8063 const char * const *descriptions,
8064 int32_t valueSize,
8065 int32_t roundingModeSize) {
8066 for (int32_t i = 0; i < roundingModeSize; ++i) {
8067 format.setRoundingMode(roundingModes[i]);
8068 for (int32_t j = 0; j < valueSize; j++) {
8069 UnicodeString currentExpected(expected[i * valueSize + j]);
8070 currentExpected = currentExpected.unescape();
8071 UnicodeString actual;
8072 format.format(values[j], actual);
8073 if (currentExpected != actual) {
8074 dataerrln("For %s value %f, expected '%s', got '%s'",
8075 descriptions[i], values[j], CStr(currentExpected)(), CStr(actual)());
8076 }
8077 }
8078 }
8079 }
8080
TestAccountingCurrency()8081 void NumberFormatTest::TestAccountingCurrency() {
8082 UErrorCode status = U_ZERO_ERROR;
8083 UNumberFormatStyle style = UNUM_CURRENCY_ACCOUNTING;
8084
8085 expect(NumberFormat::createInstance("en_US", style, status),
8086 (Formattable)(double)1234.5, "$1,234.50", TRUE, status);
8087 expect(NumberFormat::createInstance("en_US", style, status),
8088 (Formattable)(double)-1234.5, "($1,234.50)", TRUE, status);
8089 expect(NumberFormat::createInstance("en_US", style, status),
8090 (Formattable)(double)0, "$0.00", TRUE, status);
8091 expect(NumberFormat::createInstance("en_US", style, status),
8092 (Formattable)(double)-0.2, "($0.20)", TRUE, status);
8093 expect(NumberFormat::createInstance("ja_JP", style, status),
8094 (Formattable)(double)10000, UnicodeString("\\uFFE510,000").unescape(), TRUE, status);
8095 expect(NumberFormat::createInstance("ja_JP", style, status),
8096 (Formattable)(double)-1000.5, UnicodeString("(\\uFFE51,000)").unescape(), FALSE, status);
8097 expect(NumberFormat::createInstance("de_DE", style, status),
8098 (Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status);
8099 expect(NumberFormat::createInstance("en_ID", style, status),
8100 (Formattable)(double)0, UnicodeString("IDR\\u00A00.00").unescape(), TRUE, status);
8101 expect(NumberFormat::createInstance("en_ID", style, status),
8102 (Formattable)(double)-0.2, UnicodeString("(IDR\\u00A00.20)").unescape(), TRUE, status);
8103 expect(NumberFormat::createInstance("sh_ME", style, status),
8104 (Formattable)(double)0, UnicodeString("0,00\\u00A0\\u20AC").unescape(), TRUE, status);
8105 expect(NumberFormat::createInstance("sh_ME", style, status),
8106 (Formattable)(double)-0.2, UnicodeString("(0,20\\u00A0\\u20AC)").unescape(), TRUE, status);
8107 }
8108
8109 /**
8110 * ICU4J has the behavior explained below, but ICU4C is not affected. Test is added to prevent regression.
8111 *
8112 * en_ID/sh_ME uses language only locales en/sh which requires NumberFormatServiceShim to fill in the currency, but
8113 * prior to ICU-20631, currency was not filled in for accounting, cash and standard, so currency placeholder was
8114 * used instead of the desired locale's currency.
8115 */
TestCurrencyFormatForMissingLocale()8116 void NumberFormatTest::TestCurrencyFormatForMissingLocale() {
8117 IcuTestErrorCode status(*this, "TestCurrencyFormatForMissingLocale");
8118 Locale locale = Locale::createCanonical("sh_ME");
8119
8120 LocalPointer<NumberFormat> curFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status));
8121 // Fail here with missing data.
8122 if (!assertTrue(WHERE, curFmt.isValid(), false, true)) {return;};
8123 assertEquals("Currency instance is not for the desired locale for CURRENCYSTYLE", curFmt->getCurrency(), "EUR");
8124 UnicodeString currBuf;
8125 curFmt->format(-1234.5, currBuf);
8126 assertEquals("NumberFormat format outputs wrong value for CURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", currBuf);
8127
8128 LocalPointer<NumberFormat> accFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_ACCOUNTING, status));
8129 assertEquals("Currency instance is not for the desired locale for ACCOUNTINGCURRENCYSTYLE", accFmt->getCurrency(), "EUR");
8130 UnicodeString accBuf;
8131 accFmt->format(-1234.5, accBuf);
8132 assertEquals("NumberFormat format outputs wrong value for ACCOUNTINGCURRENCYSTYLE", u"(1.234,50\u00A0\u20AC)", accBuf);
8133
8134 LocalPointer<NumberFormat> cashFmt(NumberFormat::createInstance(locale, UNUM_CASH_CURRENCY, status));
8135 assertEquals("Currency instance is not for the desired locale for CASHCURRENCYSTYLE", cashFmt->getCurrency(), "EUR");
8136 UnicodeString cashBuf;
8137 cashFmt->format(-1234.5, cashBuf);
8138 assertEquals("NumberFormat format outputs wrong value for CASHCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", cashBuf);
8139
8140 LocalPointer<NumberFormat> stdFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_STANDARD, status));
8141 assertEquals("Currency instance is not for the desired locale for STANDARDCURRENCYSTYLE", stdFmt->getCurrency(), "EUR");
8142 UnicodeString stdBuf;
8143 stdFmt->format(-1234.5, stdBuf);
8144 assertEquals("NumberFormat format outputs wrong value for STANDARDCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", stdBuf);
8145 }
8146
8147 // for #5186
TestEquality()8148 void NumberFormatTest::TestEquality() {
8149 UErrorCode status = U_ZERO_ERROR;
8150 DecimalFormatSymbols symbols(Locale("root"), status);
8151 if (U_FAILURE(status)) {
8152 dataerrln("Fail: can't create DecimalFormatSymbols for root");
8153 return;
8154 }
8155 UnicodeString pattern("#,##0.###");
8156 DecimalFormat fmtBase(pattern, symbols, status);
8157 if (U_FAILURE(status)) {
8158 dataerrln("Fail: can't create DecimalFormat using root symbols");
8159 return;
8160 }
8161
8162 DecimalFormat* fmtClone = fmtBase.clone();
8163 fmtClone->setFormatWidth(fmtBase.getFormatWidth() + 32);
8164 if (*fmtClone == fmtBase) {
8165 errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth");
8166 }
8167 delete fmtClone;
8168 }
8169
TestCurrencyUsage()8170 void NumberFormatTest::TestCurrencyUsage() {
8171 double agent = 123.567;
8172
8173 UErrorCode status;
8174 DecimalFormat *fmt;
8175
8176 // compare the Currency and Currency Cash Digits
8177 // Note that as of CLDR 26:
8178 // * TWD and PKR switched from 0 decimals to 2; ISK still has 0, so change test to that
8179 // * CAD rounds to .05 in cash mode only
8180 // 1st time for getter/setter, 2nd time for factory method
8181 Locale enUS_ISK("en_US@currency=ISK");
8182
8183 for(int i=0; i<2; i++){
8184 status = U_ZERO_ERROR;
8185 if(i == 0){
8186 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CURRENCY, status);
8187 if (assertSuccess("en_US@currency=ISK/CURRENCY", status, TRUE) == FALSE) {
8188 continue;
8189 }
8190
8191 UnicodeString original;
8192 fmt->format(agent,original);
8193 assertEquals("Test Currency Usage 1", u"ISK\u00A0124", original);
8194
8195 // test the getter here
8196 UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8197 assertEquals("Test usage getter - standard", (int32_t)curUsage, (int32_t)UCURR_USAGE_STANDARD);
8198
8199 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8200 }else{
8201 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CASH_CURRENCY, status);
8202 if (assertSuccess("en_US@currency=ISK/CASH", status, TRUE) == FALSE) {
8203 continue;
8204 }
8205 }
8206
8207 // must be usage = cash
8208 UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8209 assertEquals("Test usage getter - cash", (int32_t)curUsage, (int32_t)UCURR_USAGE_CASH);
8210
8211 UnicodeString cash_currency;
8212 fmt->format(agent,cash_currency);
8213 assertEquals("Test Currency Usage 2", u"ISK\u00A0124", cash_currency);
8214 delete fmt;
8215 }
8216
8217 // compare the Currency and Currency Cash Rounding
8218 // 1st time for getter/setter, 2nd time for factory method
8219 Locale enUS_CAD("en_US@currency=CAD");
8220 for(int i=0; i<2; i++){
8221 status = U_ZERO_ERROR;
8222 if(i == 0){
8223 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8224 if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
8225 continue;
8226 }
8227
8228 UnicodeString original_rounding;
8229 fmt->format(agent, original_rounding);
8230 assertEquals("Test Currency Usage 3", u"CA$123.57", original_rounding);
8231 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8232 }else{
8233 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8234 if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
8235 continue;
8236 }
8237 }
8238
8239 UnicodeString cash_rounding_currency;
8240 fmt->format(agent, cash_rounding_currency);
8241 assertEquals("Test Currency Usage 4", u"CA$123.55", cash_rounding_currency);
8242 delete fmt;
8243 }
8244
8245 // Test the currency change
8246 // 1st time for getter/setter, 2nd time for factory method
8247 const UChar CUR_PKR[] = {0x50, 0x4B, 0x52, 0};
8248 for(int i=0; i<2; i++){
8249 status = U_ZERO_ERROR;
8250 if(i == 0){
8251 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8252 if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
8253 continue;
8254 }
8255 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8256 }else{
8257 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8258 if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
8259 continue;
8260 }
8261 }
8262
8263 UnicodeString cur_original;
8264 fmt->setCurrencyUsage(UCURR_USAGE_STANDARD, &status);
8265 fmt->format(agent, cur_original);
8266 assertEquals("Test Currency Usage 5", u"CA$123.57", cur_original);
8267
8268 fmt->setCurrency(CUR_PKR, status);
8269 assertSuccess("Set currency to PKR", status);
8270
8271 UnicodeString PKR_changed;
8272 fmt->format(agent, PKR_changed);
8273 assertEquals("Test Currency Usage 6", u"PKR\u00A0123.57", PKR_changed);
8274 delete fmt;
8275 }
8276 }
8277
8278
8279 // Check the constant MAX_INT64_IN_DOUBLE.
8280 // The value should convert to a double with no loss of precision.
8281 // A failure may indicate a platform with a different double format, requiring
8282 // a revision to the constant.
8283 //
8284 // Note that this is actually hard to test, because the language standard gives
8285 // compilers considerable flexibility to do unexpected things with rounding and
8286 // with overflow in simple int to/from float conversions. Some compilers will completely optimize
8287 // away a simple round-trip conversion from int64_t -> double -> int64_t.
8288
TestDoubleLimit11439()8289 void NumberFormatTest::TestDoubleLimit11439() {
8290 char buf[50];
8291 for (int64_t num = MAX_INT64_IN_DOUBLE-10; num<=MAX_INT64_IN_DOUBLE; num++) {
8292 sprintf(buf, "%lld", (long long)num);
8293 double fNum = 0.0;
8294 sscanf(buf, "%lf", &fNum);
8295 int64_t rtNum = static_cast<int64_t>(fNum);
8296 if (num != rtNum) {
8297 errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8298 return;
8299 }
8300 }
8301 for (int64_t num = -MAX_INT64_IN_DOUBLE+10; num>=-MAX_INT64_IN_DOUBLE; num--) {
8302 sprintf(buf, "%lld", (long long)num);
8303 double fNum = 0.0;
8304 sscanf(buf, "%lf", &fNum);
8305 int64_t rtNum = static_cast<int64_t>(fNum);
8306 if (num != rtNum) {
8307 errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8308 return;
8309 }
8310 }
8311 }
8312
TestGetAffixes()8313 void NumberFormatTest::TestGetAffixes() {
8314 UErrorCode status = U_ZERO_ERROR;
8315 DecimalFormatSymbols sym("en_US", status);
8316 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8317 pattern = pattern.unescape();
8318 DecimalFormat fmt(pattern, sym, status);
8319 if (U_FAILURE(status)) {
8320 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8321 return;
8322 }
8323 UnicodeString affixStr;
8324 assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8325 assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8326 assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8327 assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8328
8329 // Test equality with affixes. set affix methods can't capture special
8330 // characters which is why equality should fail.
8331 {
8332 DecimalFormat fmtCopy(fmt);
8333 assertTrue("", fmt == fmtCopy);
8334 UnicodeString someAffix;
8335 fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(someAffix));
8336 assertTrue("", fmt != fmtCopy);
8337 }
8338 {
8339 DecimalFormat fmtCopy(fmt);
8340 assertTrue("", fmt == fmtCopy);
8341 UnicodeString someAffix;
8342 fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(someAffix));
8343 assertTrue("", fmt != fmtCopy);
8344 }
8345 {
8346 DecimalFormat fmtCopy(fmt);
8347 assertTrue("", fmt == fmtCopy);
8348 UnicodeString someAffix;
8349 fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(someAffix));
8350 assertTrue("", fmt != fmtCopy);
8351 }
8352 {
8353 DecimalFormat fmtCopy(fmt);
8354 assertTrue("", fmt == fmtCopy);
8355 UnicodeString someAffix;
8356 fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(someAffix));
8357 assertTrue("", fmt != fmtCopy);
8358 }
8359 fmt.setPositivePrefix("Don't");
8360 fmt.setPositiveSuffix("do");
8361 UnicodeString someAffix("be''eet\\u00a4\\u00a4\\u00a4 it.");
8362 someAffix = someAffix.unescape();
8363 fmt.setNegativePrefix(someAffix);
8364 fmt.setNegativeSuffix("%");
8365 assertEquals("", "Don't", fmt.getPositivePrefix(affixStr));
8366 assertEquals("", "do", fmt.getPositiveSuffix(affixStr));
8367 assertEquals("", someAffix, fmt.getNegativePrefix(affixStr));
8368 assertEquals("", "%", fmt.getNegativeSuffix(affixStr));
8369 }
8370
TestToPatternScientific11648()8371 void NumberFormatTest::TestToPatternScientific11648() {
8372 UErrorCode status = U_ZERO_ERROR;
8373 Locale en("en");
8374 DecimalFormatSymbols sym(en, status);
8375 DecimalFormat fmt("0.00", sym, status);
8376 if (U_FAILURE(status)) {
8377 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8378 return;
8379 }
8380 fmt.setScientificNotation(TRUE);
8381 UnicodeString pattern;
8382 assertEquals("", "0.00E0", fmt.toPattern(pattern));
8383 DecimalFormat fmt2(pattern, sym, status);
8384 assertSuccess("", status);
8385 }
8386
TestBenchmark()8387 void NumberFormatTest::TestBenchmark() {
8388 /*
8389 UErrorCode status = U_ZERO_ERROR;
8390 Locale en("en");
8391 DecimalFormatSymbols sym(en, status);
8392 DecimalFormat fmt("0.0000000", new DecimalFormatSymbols(sym), status);
8393 // DecimalFormat fmt("0.00000E0", new DecimalFormatSymbols(sym), status);
8394 // DecimalFormat fmt("0", new DecimalFormatSymbols(sym), status);
8395 FieldPosition fpos(FieldPosition::DONT_CARE);
8396 clock_t start = clock();
8397 for (int32_t i = 0; i < 1000000; ++i) {
8398 UnicodeString append;
8399 fmt.format(3.0, append, fpos, status);
8400 // fmt.format(4.6692016, append, fpos, status);
8401 // fmt.format(1234567.8901, append, fpos, status);
8402 // fmt.format(2.99792458E8, append, fpos, status);
8403 // fmt.format(31, append);
8404 }
8405 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8406 assertSuccess("", status);
8407
8408 UErrorCode status = U_ZERO_ERROR;
8409 MessageFormat fmt("{0, plural, one {I have # friend.} other {I have # friends.}}", status);
8410 FieldPosition fpos(FieldPosition::DONT_CARE);
8411 Formattable one(1.0);
8412 Formattable three(3.0);
8413 clock_t start = clock();
8414 for (int32_t i = 0; i < 500000; ++i) {
8415 UnicodeString append;
8416 fmt.format(&one, 1, append, fpos, status);
8417 UnicodeString append2;
8418 fmt.format(&three, 1, append2, fpos, status);
8419 }
8420 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8421 assertSuccess("", status);
8422
8423 UErrorCode status = U_ZERO_ERROR;
8424 Locale en("en");
8425 Measure measureC(23, MeasureUnit::createCelsius(status), status);
8426 MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
8427 FieldPosition fpos(FieldPosition::DONT_CARE);
8428 clock_t start = clock();
8429 for (int32_t i = 0; i < 1000000; ++i) {
8430 UnicodeString appendTo;
8431 fmt.formatMeasures(
8432 &measureC, 1, appendTo, fpos, status);
8433 }
8434 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8435 assertSuccess("", status);
8436 */
8437 }
8438
TestFractionalDigitsForCurrency()8439 void NumberFormatTest::TestFractionalDigitsForCurrency() {
8440 UErrorCode status = U_ZERO_ERROR;
8441 LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance("en", status));
8442 if (U_FAILURE(status)) {
8443 dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8444 return;
8445 }
8446 UChar JPY[] = {0x4A, 0x50, 0x59, 0x0};
8447 fmt->setCurrency(JPY, status);
8448 if (!assertSuccess("", status)) {
8449 return;
8450 }
8451 assertEquals("", 0, fmt->getMaximumFractionDigits());
8452 }
8453
8454
TestFormatCurrencyPlural()8455 void NumberFormatTest::TestFormatCurrencyPlural() {
8456 UErrorCode status = U_ZERO_ERROR;
8457 Locale locale = Locale::createCanonical("en_US");
8458 NumberFormat *fmt = NumberFormat::createInstance(locale, UNUM_CURRENCY_PLURAL, status);
8459 if (U_FAILURE(status)) {
8460 dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8461 return;
8462 }
8463 UnicodeString formattedNum;
8464 fmt->format(11234.567, formattedNum, NULL, status);
8465 assertEquals("", "11,234.57 US dollars", formattedNum);
8466 delete fmt;
8467 }
8468
TestCtorApplyPatternDifference()8469 void NumberFormatTest::TestCtorApplyPatternDifference() {
8470 UErrorCode status = U_ZERO_ERROR;
8471 DecimalFormatSymbols sym("en_US", status);
8472 UnicodeString pattern("\\u00a40");
8473 DecimalFormat fmt(pattern.unescape(), sym, status);
8474 if (U_FAILURE(status)) {
8475 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8476 return;
8477 }
8478 UnicodeString result;
8479 assertEquals(
8480 "ctor favors precision of currency",
8481 "$5.00",
8482 fmt.format((double)5, result));
8483 result.remove();
8484 fmt.applyPattern(pattern.unescape(), status);
8485 assertEquals(
8486 "applyPattern favors precision of pattern",
8487 "$5",
8488 fmt.format((double)5, result));
8489 }
8490
Test11868()8491 void NumberFormatTest::Test11868() {
8492 double posAmt = 34.567;
8493 double negAmt = -9876.543;
8494
8495 Locale selectedLocale("en_US");
8496 UErrorCode status = U_ZERO_ERROR;
8497
8498 UnicodeString result;
8499 FieldPosition fpCurr(UNUM_CURRENCY_FIELD);
8500 LocalPointer<NumberFormat> fmt(
8501 NumberFormat::createInstance(
8502 selectedLocale, UNUM_CURRENCY_PLURAL, status));
8503 if (!assertSuccess("Format creation", status)) {
8504 return;
8505 }
8506 fmt->format(posAmt, result, fpCurr, status);
8507 assertEquals("", "34.57 US dollars", result);
8508 assertEquals("begin index", 6, fpCurr.getBeginIndex());
8509 assertEquals("end index", 16, fpCurr.getEndIndex());
8510
8511 // Test field position iterator
8512 {
8513 NumberFormatTest_Attributes attributes[] = {
8514 {UNUM_INTEGER_FIELD, 0, 2},
8515 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8516 {UNUM_FRACTION_FIELD, 3, 5},
8517 {UNUM_CURRENCY_FIELD, 6, 16},
8518 {0, -1, 0}};
8519 UnicodeString result;
8520 FieldPositionIterator iter;
8521 fmt->format(posAmt, result, &iter, status);
8522 assertEquals("", "34.57 US dollars", result);
8523 verifyFieldPositionIterator(attributes, iter);
8524 }
8525
8526 result.remove();
8527 fmt->format(negAmt, result, fpCurr, status);
8528 assertEquals("", "-9,876.54 US dollars", result);
8529 assertEquals("begin index", 10, fpCurr.getBeginIndex());
8530 assertEquals("end index", 20, fpCurr.getEndIndex());
8531
8532 // Test field position iterator
8533 {
8534 NumberFormatTest_Attributes attributes[] = {
8535 {UNUM_SIGN_FIELD, 0, 1},
8536 {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
8537 {UNUM_INTEGER_FIELD, 1, 6},
8538 {UNUM_DECIMAL_SEPARATOR_FIELD, 6, 7},
8539 {UNUM_FRACTION_FIELD, 7, 9},
8540 {UNUM_CURRENCY_FIELD, 10, 20},
8541 {0, -1, 0}};
8542 UnicodeString result;
8543 FieldPositionIterator iter;
8544 fmt->format(negAmt, result, &iter, status);
8545 assertEquals("", "-9,876.54 US dollars", result);
8546 verifyFieldPositionIterator(attributes, iter);
8547 }
8548 }
8549
Test10727_RoundingZero()8550 void NumberFormatTest::Test10727_RoundingZero() {
8551 IcuTestErrorCode status(*this, "Test10727_RoundingZero");
8552 DecimalQuantity dq;
8553 dq.setToDouble(-0.0);
8554 assertTrue("", dq.isNegative());
8555 dq.roundToMagnitude(0, UNUM_ROUND_HALFEVEN, status);
8556 assertTrue("", dq.isNegative());
8557 }
8558
Test11739_ParseLongCurrency()8559 void NumberFormatTest::Test11739_ParseLongCurrency() {
8560 IcuTestErrorCode status(*this, "Test11739_ParseLongCurrency");
8561 LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("sr_BA", status));
8562 if (status.errDataIfFailureAndReset()) { return; }
8563 ((DecimalFormat*) nf.getAlias())->applyPattern(u"#,##0.0 ¤¤¤", status);
8564 ParsePosition ppos(0);
8565 LocalPointer<CurrencyAmount> result(nf->parseCurrency(u"1.500 амерички долар", ppos));
8566 assertEquals("Should parse to 1500 USD", -1, ppos.getErrorIndex());
8567 if (ppos.getErrorIndex() != -1) {
8568 return;
8569 }
8570 assertEquals("Should parse to 1500 USD", 1500LL, result->getNumber().getInt64(status));
8571 assertEquals("Should parse to 1500 USD", u"USD", result->getISOCurrency());
8572 }
8573
Test13035_MultiCodePointPaddingInPattern()8574 void NumberFormatTest::Test13035_MultiCodePointPaddingInPattern() {
8575 IcuTestErrorCode status(*this, "Test13035_MultiCodePointPaddingInPattern");
8576 DecimalFormat df(u"a*'நி'###0b", status);
8577 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8578 UnicodeString result;
8579 df.format(12, result.remove());
8580 // TODO(13034): Re-enable this test when support is added in ICU4C.
8581 //assertEquals("Multi-codepoint padding should not be split", u"aநிநி12b", result);
8582 df = DecimalFormat(u"a*\U0001F601###0b", status);
8583 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8584 result = df.format(12, result.remove());
8585 assertEquals("Single-codepoint padding should not be split", u"a\U0001F601\U0001F60112b", result, true);
8586 df = DecimalFormat(u"a*''###0b", status);
8587 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8588 result = df.format(12, result.remove());
8589 assertEquals("Quote should be escapable in padding syntax", "a''12b", result, true);
8590 }
8591
Test13737_ParseScientificStrict()8592 void NumberFormatTest::Test13737_ParseScientificStrict() {
8593 IcuTestErrorCode status(*this, "Test13737_ParseScientificStrict");
8594 LocalPointer<NumberFormat> df(NumberFormat::createScientificInstance("en", status), status);
8595 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8596 df->setLenient(FALSE);
8597 // Parse Test
8598 expect(*df, u"1.2", 1.2);
8599 }
8600
Test11376_getAndSetPositivePrefix()8601 void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
8602 {
8603 const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8604 UErrorCode status = U_ZERO_ERROR;
8605 LocalPointer<NumberFormat> fmt(
8606 NumberFormat::createCurrencyInstance("en", status));
8607 if (!assertSuccess("", status)) {
8608 return;
8609 }
8610 DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8611 dfmt->setCurrency(USD);
8612 UnicodeString result;
8613
8614 // This line should be a no-op. I am setting the positive prefix
8615 // to be the same thing it was before.
8616 dfmt->setPositivePrefix(dfmt->getPositivePrefix(result));
8617
8618 UnicodeString appendTo;
8619 assertEquals("", "$3.78", dfmt->format(3.78, appendTo, status));
8620 assertSuccess("", status);
8621 }
8622 {
8623 const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8624 UErrorCode status = U_ZERO_ERROR;
8625 LocalPointer<NumberFormat> fmt(
8626 NumberFormat::createInstance("en", UNUM_CURRENCY_PLURAL, status));
8627 if (!assertSuccess("", status)) {
8628 return;
8629 }
8630 DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8631 UnicodeString result;
8632 assertEquals("", u" (unknown currency)", dfmt->getPositiveSuffix(result));
8633 dfmt->setCurrency(USD);
8634
8635 // getPositiveSuffix() always returns the suffix for the
8636 // "other" plural category
8637 assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8638 UnicodeString appendTo;
8639 assertEquals("", "3.78 US dollars", dfmt->format(3.78, appendTo, status));
8640 assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8641 dfmt->setPositiveSuffix("booya");
8642 appendTo.remove();
8643 assertEquals("", "3.78booya", dfmt->format(3.78, appendTo, status));
8644 assertEquals("", "booya", dfmt->getPositiveSuffix(result));
8645 }
8646 }
8647
Test11475_signRecognition()8648 void NumberFormatTest::Test11475_signRecognition() {
8649 UErrorCode status = U_ZERO_ERROR;
8650 DecimalFormatSymbols sym("en", status);
8651 UnicodeString result;
8652 {
8653 DecimalFormat fmt("+0.00", sym, status);
8654 if (!assertSuccess("", status)) {
8655 return;
8656 }
8657 NumberFormatTest_Attributes attributes[] = {
8658 {UNUM_SIGN_FIELD, 0, 1},
8659 {UNUM_INTEGER_FIELD, 1, 2},
8660 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8661 {UNUM_FRACTION_FIELD, 3, 5},
8662 {0, -1, 0}};
8663 UnicodeString result;
8664 FieldPositionIterator iter;
8665 fmt.format(2.3, result, &iter, status);
8666 assertEquals("", "+2.30", result);
8667 verifyFieldPositionIterator(attributes, iter);
8668 }
8669 {
8670 DecimalFormat fmt("++0.00+;-(#)--", sym, status);
8671 if (!assertSuccess("", status)) {
8672 return;
8673 }
8674 {
8675 NumberFormatTest_Attributes attributes[] = {
8676 {UNUM_SIGN_FIELD, 0, 2},
8677 {UNUM_INTEGER_FIELD, 2, 3},
8678 {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8679 {UNUM_FRACTION_FIELD, 4, 6},
8680 {UNUM_SIGN_FIELD, 6, 7},
8681 {0, -1, 0}};
8682 UnicodeString result;
8683 FieldPositionIterator iter;
8684 fmt.format(2.3, result, &iter, status);
8685 assertEquals("", "++2.30+", result);
8686 verifyFieldPositionIterator(attributes, iter);
8687 }
8688 {
8689 NumberFormatTest_Attributes attributes[] = {
8690 {UNUM_SIGN_FIELD, 0, 1},
8691 {UNUM_INTEGER_FIELD, 2, 3},
8692 {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8693 {UNUM_FRACTION_FIELD, 4, 6},
8694 {UNUM_SIGN_FIELD, 7, 9},
8695 {0, -1, 0}};
8696 UnicodeString result;
8697 FieldPositionIterator iter;
8698 fmt.format(-2.3, result, &iter, status);
8699 assertEquals("", "-(2.30)--", result);
8700 verifyFieldPositionIterator(attributes, iter);
8701 }
8702 }
8703 }
8704
Test11640_getAffixes()8705 void NumberFormatTest::Test11640_getAffixes() {
8706 UErrorCode status = U_ZERO_ERROR;
8707 DecimalFormatSymbols symbols("en_US", status);
8708 if (!assertSuccess("", status)) {
8709 return;
8710 }
8711 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8712 pattern = pattern.unescape();
8713 DecimalFormat fmt(pattern, symbols, status);
8714 if (!assertSuccess("", status)) {
8715 return;
8716 }
8717 UnicodeString affixStr;
8718 assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8719 assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8720 assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8721 assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8722 }
8723
Test11649_toPatternWithMultiCurrency()8724 void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
8725 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
8726 pattern = pattern.unescape();
8727 UErrorCode status = U_ZERO_ERROR;
8728 DecimalFormat fmt(pattern, status);
8729 if (!assertSuccess("", status)) {
8730 return;
8731 }
8732 static UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8733 fmt.setCurrency(USD);
8734 UnicodeString appendTo;
8735
8736 assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
8737
8738 UnicodeString topattern;
8739 fmt.toPattern(topattern);
8740 DecimalFormat fmt2(topattern, status);
8741 if (!assertSuccess("", status)) {
8742 return;
8743 }
8744 fmt2.setCurrency(USD);
8745
8746 appendTo.remove();
8747 assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
8748 }
8749
Test13327_numberingSystemBufferOverflow()8750 void NumberFormatTest::Test13327_numberingSystemBufferOverflow() {
8751 UErrorCode status = U_ZERO_ERROR;
8752 for (int runId = 0; runId < 2; runId++) {
8753 // Construct a locale string with a very long "numbers" value.
8754 // The first time, make the value length exactly equal to ULOC_KEYWORDS_CAPACITY.
8755 // The second time, make it exceed ULOC_KEYWORDS_CAPACITY.
8756 int extraLength = (runId == 0) ? 0 : 5;
8757
8758 CharString localeId("en@numbers=", status);
8759 for (int i = 0; i < ULOC_KEYWORDS_CAPACITY + extraLength; i++) {
8760 localeId.append('x', status);
8761 }
8762 assertSuccess("Constructing locale string", status);
8763 Locale locale(localeId.data());
8764
8765 LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(locale, status));
8766 assertFalse("Should not be null", ns.getAlias() == nullptr);
8767 assertSuccess("Should create with no error", status);
8768 }
8769 }
8770
Test13391_chakmaParsing()8771 void NumberFormatTest::Test13391_chakmaParsing() {
8772 UErrorCode status = U_ZERO_ERROR;
8773 LocalPointer<DecimalFormat> df(dynamic_cast<DecimalFormat*>(
8774 NumberFormat::createInstance(Locale("ccp"), status)));
8775 if (df == nullptr) {
8776 dataerrln("%s %d Chakma df is null", __FILE__, __LINE__);
8777 return;
8778 }
8779 const UChar* expected = u"\U00011137\U00011138,\U00011139\U0001113A\U0001113B";
8780 UnicodeString actual;
8781 df->format(12345, actual, status);
8782 assertSuccess("Should not fail when formatting in ccp", status);
8783 assertEquals("Should produce expected output in ccp", expected, actual);
8784
8785 Formattable result;
8786 df->parse(expected, result, status);
8787 assertSuccess("Should not fail when parsing in ccp", status);
8788 assertEquals("Should parse to 12345 in ccp", 12345, result);
8789
8790 const UChar* expectedScientific = u"\U00011137.\U00011139E\U00011138";
8791 UnicodeString actualScientific;
8792 df.adoptInstead(static_cast<DecimalFormat*>(
8793 NumberFormat::createScientificInstance(Locale("ccp"), status)));
8794 df->format(130, actualScientific, status);
8795 assertSuccess("Should not fail when formatting scientific in ccp", status);
8796 assertEquals("Should produce expected scientific output in ccp",
8797 expectedScientific, actualScientific);
8798
8799 Formattable resultScientific;
8800 df->parse(expectedScientific, resultScientific, status);
8801 assertSuccess("Should not fail when parsing scientific in ccp", status);
8802 assertEquals("Should parse scientific to 130 in ccp", 130, resultScientific);
8803 }
8804
8805
verifyFieldPositionIterator(NumberFormatTest_Attributes * expected,FieldPositionIterator & iter)8806 void NumberFormatTest::verifyFieldPositionIterator(
8807 NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
8808 int32_t idx = 0;
8809 FieldPosition fp;
8810 while (iter.next(fp)) {
8811 if (expected[idx].spos == -1) {
8812 errln("Iterator should have ended. got %d", fp.getField());
8813 return;
8814 }
8815 assertEquals("id", expected[idx].id, fp.getField());
8816 assertEquals("start", expected[idx].spos, fp.getBeginIndex());
8817 assertEquals("end", expected[idx].epos, fp.getEndIndex());
8818 ++idx;
8819 }
8820 if (expected[idx].spos != -1) {
8821 errln("Premature end of iterator. expected %d", expected[idx].id);
8822 }
8823 }
8824
Test11735_ExceptionIssue()8825 void NumberFormatTest::Test11735_ExceptionIssue() {
8826 IcuTestErrorCode status(*this, "Test11735_ExceptionIssue");
8827 Locale enLocale("en");
8828 DecimalFormatSymbols symbols(enLocale, status);
8829 if (status.isSuccess()) {
8830 DecimalFormat fmt("0", symbols, status);
8831 assertSuccess("Fail: Construct DecimalFormat formatter", status, true, __FILE__, __LINE__);
8832 ParsePosition ppos(0);
8833 fmt.parseCurrency("53.45", ppos); // NPE thrown here in ICU4J.
8834 assertEquals("Issue11735 ppos", 0, ppos.getIndex());
8835 }
8836 }
8837
Test11035_FormatCurrencyAmount()8838 void NumberFormatTest::Test11035_FormatCurrencyAmount() {
8839 UErrorCode status = U_ZERO_ERROR;
8840 double amount = 12345.67;
8841 const char16_t* expected = u"12,345$67 ";
8842
8843 // Test two ways to set a currency via API
8844
8845 Locale loc1 = Locale("pt_PT");
8846 LocalPointer<NumberFormat> fmt1(NumberFormat::createCurrencyInstance(loc1, status),
8847 status);
8848 if (U_FAILURE(status)) {
8849 dataerrln("%s %d NumberFormat instance fmt1 is null", __FILE__, __LINE__);
8850 return;
8851 }
8852 fmt1->setCurrency(u"PTE", status);
8853 assertSuccess("Setting currency on fmt1", status);
8854 UnicodeString actualSetCurrency;
8855 fmt1->format(amount, actualSetCurrency);
8856
8857 Locale loc2 = Locale("pt_PT@currency=PTE");
8858 LocalPointer<NumberFormat> fmt2(NumberFormat::createCurrencyInstance(loc2, status));
8859 assertSuccess("Creating fmt2", status);
8860 UnicodeString actualLocaleString;
8861 fmt2->format(amount, actualLocaleString);
8862
8863 assertEquals("Custom Currency Pattern, Set Currency", expected, actualSetCurrency);
8864 assertEquals("Custom Currency Pattern, Locale String", expected, actualLocaleString);
8865 }
8866
Test11318_DoubleConversion()8867 void NumberFormatTest::Test11318_DoubleConversion() {
8868 IcuTestErrorCode status(*this, "Test11318_DoubleConversion");
8869 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
8870 if (U_FAILURE(status)) {
8871 dataerrln("%s %d Error in NumberFormat instance creation", __FILE__, __LINE__);
8872 return;
8873 }
8874 nf->setMaximumFractionDigits(40);
8875 nf->setMaximumIntegerDigits(40);
8876 UnicodeString appendTo;
8877 nf->format(999999999999999.9, appendTo);
8878 assertEquals("Should render all digits", u"999,999,999,999,999.9", appendTo);
8879 }
8880
TestParsePercentRegression()8881 void NumberFormatTest::TestParsePercentRegression() {
8882 IcuTestErrorCode status(*this, "TestParsePercentRegression");
8883 LocalPointer<DecimalFormat> df1((DecimalFormat*) NumberFormat::createInstance("en", status), status);
8884 LocalPointer<DecimalFormat> df2((DecimalFormat*) NumberFormat::createPercentInstance("en", status), status);
8885 if (status.isFailure()) {return; }
8886 df1->setLenient(TRUE);
8887 df2->setLenient(TRUE);
8888
8889 {
8890 ParsePosition ppos;
8891 Formattable result;
8892 df1->parse("50%", result, ppos);
8893 assertEquals("df1 should accept a number but not the percent sign", 2, ppos.getIndex());
8894 assertEquals("df1 should return the number as 50", 50.0, result.getDouble(status));
8895 }
8896 {
8897 ParsePosition ppos;
8898 Formattable result;
8899 df2->parse("50%", result, ppos);
8900 assertEquals("df2 should accept the percent sign", 3, ppos.getIndex());
8901 assertEquals("df2 should return the number as 0.5", 0.5, result.getDouble(status));
8902 }
8903 {
8904 ParsePosition ppos;
8905 Formattable result;
8906 df2->parse("50", result, ppos);
8907 assertEquals("df2 should return the number as 0.5 even though the percent sign is missing",
8908 0.5,
8909 result.getDouble(status));
8910 }
8911 }
8912
TestMultiplierWithScale()8913 void NumberFormatTest::TestMultiplierWithScale() {
8914 IcuTestErrorCode status(*this, "TestMultiplierWithScale");
8915
8916 // Test magnitude combined with multiplier, as shown in API docs
8917 DecimalFormat df("0", {"en", status}, status);
8918 if (status.isSuccess()) {
8919 df.setMultiplier(5);
8920 df.setMultiplierScale(-1);
8921 expect2(df, 100, u"50"); // round-trip test
8922 }
8923 }
8924
TestFastFormatInt32()8925 void NumberFormatTest::TestFastFormatInt32() {
8926 IcuTestErrorCode status(*this, "TestFastFormatInt32");
8927
8928 // The two simplest formatters, old API and new API.
8929 // Old API should use the fastpath for ints.
8930 LocalizedNumberFormatter lnf = NumberFormatter::withLocale("en");
8931 LocalPointer<NumberFormat> df(NumberFormat::createInstance("en", status), status);
8932 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8933
8934 double nums[] = {
8935 0.0,
8936 -0.0,
8937 NAN,
8938 INFINITY,
8939 0.1,
8940 1.0,
8941 1.1,
8942 2.0,
8943 3.0,
8944 9.0,
8945 10.0,
8946 99.0,
8947 100.0,
8948 999.0,
8949 1000.0,
8950 9999.0,
8951 10000.0,
8952 99999.0,
8953 100000.0,
8954 999999.0,
8955 1000000.0,
8956 static_cast<double>(INT32_MAX) - 1,
8957 static_cast<double>(INT32_MAX),
8958 static_cast<double>(INT32_MAX) + 1,
8959 static_cast<double>(INT32_MIN) - 1,
8960 static_cast<double>(INT32_MIN),
8961 static_cast<double>(INT32_MIN) + 1};
8962
8963 for (auto num : nums) {
8964 UnicodeString expected = lnf.formatDouble(num, status).toString(status);
8965 UnicodeString actual;
8966 df->format(num, actual);
8967 assertEquals(UnicodeString("d = ") + num, expected, actual);
8968 }
8969 }
8970
Test11646_Equality()8971 void NumberFormatTest::Test11646_Equality() {
8972 UErrorCode status = U_ZERO_ERROR;
8973 DecimalFormatSymbols symbols(Locale::getEnglish(), status);
8974 UnicodeString pattern(u"\u00a4\u00a4\u00a4 0.00 %\u00a4\u00a4");
8975 DecimalFormat fmt(pattern, symbols, status);
8976 if (!assertSuccess("", status)) return;
8977
8978 // Test equality with affixes. set affix methods can't capture special
8979 // characters which is why equality should fail.
8980 {
8981 DecimalFormat fmtCopy(fmt);
8982 assertTrue("", fmt == fmtCopy);
8983 UnicodeString positivePrefix;
8984 fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(positivePrefix));
8985 assertFalse("", fmt == fmtCopy);
8986 }
8987 {
8988 DecimalFormat fmtCopy = DecimalFormat(fmt);
8989 assertTrue("", fmt == fmtCopy);
8990 UnicodeString positivePrefix;
8991 fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(positivePrefix));
8992 assertFalse("", fmt == fmtCopy);
8993 }
8994 {
8995 DecimalFormat fmtCopy(fmt);
8996 assertTrue("", fmt == fmtCopy);
8997 UnicodeString negativePrefix;
8998 fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(negativePrefix));
8999 assertFalse("", fmt == fmtCopy);
9000 }
9001 {
9002 DecimalFormat fmtCopy(fmt);
9003 assertTrue("", fmt == fmtCopy);
9004 UnicodeString negativePrefix;
9005 fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(negativePrefix));
9006 assertFalse("", fmt == fmtCopy);
9007 }
9008 }
9009
TestParseNaN()9010 void NumberFormatTest::TestParseNaN() {
9011 IcuTestErrorCode status(*this, "TestParseNaN");
9012
9013 DecimalFormat df("0", { "en", status }, status);
9014 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9015 Formattable parseResult;
9016 df.parse(u"NaN", parseResult, status);
9017 assertEquals("NaN should parse successfully", NAN, parseResult.getDouble());
9018 assertFalse("Result NaN should be positive", std::signbit(parseResult.getDouble()));
9019 UnicodeString formatResult;
9020 df.format(parseResult.getDouble(), formatResult);
9021 assertEquals("NaN should round-trip", u"NaN", formatResult);
9022 }
9023
TestFormatFailIfMoreThanMaxDigits()9024 void NumberFormatTest::TestFormatFailIfMoreThanMaxDigits() {
9025 IcuTestErrorCode status(*this, "TestFormatFailIfMoreThanMaxDigits");
9026
9027 DecimalFormat df("0", {"en-US", status}, status);
9028 if (status.errDataIfFailureAndReset()) {
9029 return;
9030 }
9031 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isFormatFailIfMoreThanMaxDigits());
9032 df.setFormatFailIfMoreThanMaxDigits(TRUE);
9033 assertEquals("Coverage for getter 2", (UBool) TRUE, df.isFormatFailIfMoreThanMaxDigits());
9034 df.setMaximumIntegerDigits(2);
9035 UnicodeString result;
9036 df.format(1234, result, status);
9037 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
9038 }
9039
TestParseCaseSensitive()9040 void NumberFormatTest::TestParseCaseSensitive() {
9041 IcuTestErrorCode status(*this, "TestParseCaseSensitive");
9042
9043 DecimalFormat df(u"0", {"en-US", status}, status);
9044 if (status.errDataIfFailureAndReset()) {
9045 return;
9046 }
9047 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isParseCaseSensitive());
9048 df.setParseCaseSensitive(TRUE);
9049 assertEquals("Coverage for getter 1", (UBool) TRUE, df.isParseCaseSensitive());
9050 Formattable result;
9051 ParsePosition ppos;
9052 df.parse(u"1e2", result, ppos);
9053 assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9054 assertEquals("Result should be 1", 1.0, result.getDouble(status));
9055 }
9056
TestParseNoExponent()9057 void NumberFormatTest::TestParseNoExponent() {
9058 IcuTestErrorCode status(*this, "TestParseNoExponent");
9059
9060 DecimalFormat df(u"0", {"en-US", status}, status);
9061 if (status.errDataIfFailureAndReset()) {
9062 return;
9063 }
9064 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isParseNoExponent());
9065 df.setParseNoExponent(TRUE);
9066 assertEquals("Coverage for getter 1", (UBool) TRUE, df.isParseNoExponent());
9067 Formattable result;
9068 ParsePosition ppos;
9069 df.parse(u"1E2", result, ppos);
9070 assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9071 assertEquals("Result should be 1", 1.0, result.getDouble(status));
9072 }
9073
TestSignAlwaysShown()9074 void NumberFormatTest::TestSignAlwaysShown() {
9075 IcuTestErrorCode status(*this, "TestSignAlwaysShown");
9076
9077 DecimalFormat df(u"0", {"en-US", status}, status);
9078 if (status.errDataIfFailureAndReset()) {
9079 return;
9080 }
9081 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isSignAlwaysShown());
9082 df.setSignAlwaysShown(TRUE);
9083 assertEquals("Coverage for getter 1", (UBool) TRUE, df.isSignAlwaysShown());
9084 UnicodeString result;
9085 df.format(1234, result, status);
9086 status.errIfFailureAndReset();
9087 assertEquals("Should show sign on positive number", u"+1234", result);
9088 }
9089
TestMinimumGroupingDigits()9090 void NumberFormatTest::TestMinimumGroupingDigits() {
9091 IcuTestErrorCode status(*this, "TestMinimumGroupingDigits");
9092
9093 DecimalFormat df(u"#,##0", {"en-US", status}, status);
9094 if (status.errDataIfFailureAndReset()) {
9095 return;
9096 }
9097 assertEquals("Coverage for getter 1", -1, df.getMinimumGroupingDigits());
9098 df.setMinimumGroupingDigits(2);
9099 assertEquals("Coverage for getter 1", 2, df.getMinimumGroupingDigits());
9100 UnicodeString result;
9101 df.format(1234, result, status);
9102 status.errIfFailureAndReset();
9103 assertEquals("Should not have grouping", u"1234", result);
9104 df.format(12345, result.remove(), status);
9105 status.errIfFailureAndReset();
9106 assertEquals("Should have grouping", u"12,345", result);
9107
9108
9109 // Test special values -1, UNUM_MINIMUM_GROUPING_DIGITS_AUTO and
9110 // UNUM_MINIMUM_GROUPING_DIGITS_MIN2
9111 struct TestCase {
9112 const char* locale;
9113 int32_t minGroup;
9114 double input;
9115 const char16_t* expected;
9116 } cases[] = {
9117 { "en-US", 1, 1000, u"1,000" },
9118 { "en-US", 1, 10000, u"10,000" },
9119 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1,000" },
9120 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10,000" },
9121 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9122 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10,000" },
9123
9124 { "es", 1, 1000, u"1.000" },
9125 { "es", 1, 10000, u"10.000" },
9126 { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1000" },
9127 { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10.000" },
9128 { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9129 { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10.000" },
9130 };
9131 for (const auto& cas : cases) {
9132 UnicodeString message = UnicodeString(cas.locale)
9133 + u" " + Int64ToUnicodeString(cas.minGroup)
9134 + u" " + DoubleToUnicodeString(cas.input);
9135 status.setScope(message);
9136 DecimalFormat df(u"#,##0", {cas.locale, status}, status);
9137 if (status.errIfFailureAndReset()) { continue; }
9138 df.setMinimumGroupingDigits(cas.minGroup);
9139 UnicodeString actual;
9140 df.format(cas.input, actual, status);
9141 if (status.errIfFailureAndReset()) { continue; }
9142 assertEquals(message, cas.expected, actual);
9143 }
9144 }
9145
Test11897_LocalizedPatternSeparator()9146 void NumberFormatTest::Test11897_LocalizedPatternSeparator() {
9147 IcuTestErrorCode status(*this, "Test11897_LocalizedPatternSeparator");
9148
9149 // In a locale with a different <list> symbol, like arabic,
9150 // kPatternSeparatorSymbol should still be ';'
9151 {
9152 DecimalFormatSymbols dfs("ar", status);
9153 assertEquals("pattern separator symbol should be ;",
9154 u";",
9155 dfs.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
9156 }
9157
9158 // However, the custom symbol should be used in localized notation
9159 // when set manually via API
9160 {
9161 DecimalFormatSymbols dfs("en", status);
9162 dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u"!", FALSE);
9163 DecimalFormat df(u"0", dfs, status);
9164 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9165 df.applyPattern("a0;b0", status); // should not throw
9166 UnicodeString result;
9167 assertEquals("should apply the normal pattern",
9168 df.getNegativePrefix(result.remove()),
9169 "b");
9170 df.applyLocalizedPattern(u"c0!d0", status); // should not throw
9171 assertEquals("should apply the localized pattern",
9172 df.getNegativePrefix(result.remove()),
9173 "d");
9174 }
9175 }
9176
Test13055_PercentageRounding()9177 void NumberFormatTest::Test13055_PercentageRounding() {
9178 IcuTestErrorCode status(*this, "PercentageRounding");
9179 UnicodeString actual;
9180 LocalPointer<NumberFormat>pFormat(NumberFormat::createPercentInstance("en_US", status));
9181 if (U_FAILURE(status)) {
9182 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9183 return;
9184 }
9185 pFormat->setMaximumFractionDigits(0);
9186 pFormat->setRoundingMode(DecimalFormat::kRoundHalfEven);
9187 pFormat->format(2.155, actual);
9188 assertEquals("Should round percent toward even number", "216%", actual);
9189 }
9190
Test11839()9191 void NumberFormatTest::Test11839() {
9192 IcuTestErrorCode errorCode(*this, "Test11839");
9193 // Ticket #11839: DecimalFormat does not respect custom plus sign
9194 LocalPointer<DecimalFormatSymbols> dfs(new DecimalFormatSymbols(Locale::getEnglish(), errorCode), errorCode);
9195 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9196 dfs->setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"a∸");
9197 dfs->setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"b∔"); // ∔ U+2214 DOT PLUS
9198 DecimalFormat df(u"0.00+;0.00-", dfs.orphan(), errorCode);
9199 UnicodeString result;
9200 df.format(-1.234, result, errorCode);
9201 assertEquals("Locale-specific minus sign should be used", u"1.23a∸", result);
9202 df.format(1.234, result.remove(), errorCode);
9203 assertEquals("Locale-specific plus sign should be used", u"1.23b∔", result);
9204 // Test round-trip with parse
9205 expect2(df, -456, u"456.00a∸");
9206 expect2(df, 456, u"456.00b∔");
9207 }
9208
Test10354()9209 void NumberFormatTest::Test10354() {
9210 IcuTestErrorCode errorCode(*this, "Test10354");
9211 // Ticket #10354: invalid FieldPositionIterator when formatting with empty NaN
9212 DecimalFormatSymbols dfs(errorCode);
9213 UnicodeString empty;
9214 dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, empty);
9215 DecimalFormat df(errorCode);
9216 df.setDecimalFormatSymbols(dfs);
9217 UnicodeString result;
9218 FieldPositionIterator positions;
9219 df.format(NAN, result, &positions, errorCode);
9220 errorCode.errIfFailureAndReset("DecimalFormat.format(NAN, FieldPositionIterator) failed");
9221 FieldPosition fp;
9222 while (positions.next(fp)) {
9223 // Should not loop forever
9224 }
9225 }
9226
Test11645_ApplyPatternEquality()9227 void NumberFormatTest::Test11645_ApplyPatternEquality() {
9228 IcuTestErrorCode status(*this, "Test11645_ApplyPatternEquality");
9229 const char16_t* pattern = u"#,##0.0#";
9230 LocalPointer<DecimalFormat> fmt((DecimalFormat*) NumberFormat::createInstance(status), status);
9231 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9232 fmt->applyPattern(pattern, status);
9233 LocalPointer<DecimalFormat> fmtCopy;
9234
9235 static const int32_t newMultiplier = 37;
9236 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9237 assertFalse("Value before setter", fmtCopy->getMultiplier() == newMultiplier);
9238 fmtCopy->setMultiplier(newMultiplier);
9239 assertEquals("Value after setter", fmtCopy->getMultiplier(), newMultiplier);
9240 fmtCopy->applyPattern(pattern, status);
9241 assertEquals("Value after applyPattern", fmtCopy->getMultiplier(), newMultiplier);
9242 assertFalse("multiplier", *fmt == *fmtCopy);
9243
9244 static const NumberFormat::ERoundingMode newRoundingMode = NumberFormat::ERoundingMode::kRoundCeiling;
9245 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9246 assertFalse("Value before setter", fmtCopy->getRoundingMode() == newRoundingMode);
9247 fmtCopy->setRoundingMode(newRoundingMode);
9248 assertEquals("Value after setter", fmtCopy->getRoundingMode(), newRoundingMode);
9249 fmtCopy->applyPattern(pattern, status);
9250 assertEquals("Value after applyPattern", fmtCopy->getRoundingMode(), newRoundingMode);
9251 assertFalse("roundingMode", *fmt == *fmtCopy);
9252
9253 static const char16_t *const newCurrency = u"EAT";
9254 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9255 assertFalse("Value before setter", fmtCopy->getCurrency() == newCurrency);
9256 fmtCopy->setCurrency(newCurrency);
9257 assertEquals("Value after setter", fmtCopy->getCurrency(), newCurrency);
9258 fmtCopy->applyPattern(pattern, status);
9259 assertEquals("Value after applyPattern", fmtCopy->getCurrency(), newCurrency);
9260 assertFalse("currency", *fmt == *fmtCopy);
9261
9262 static const UCurrencyUsage newCurrencyUsage = UCurrencyUsage::UCURR_USAGE_CASH;
9263 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9264 assertFalse("Value before setter", fmtCopy->getCurrencyUsage() == newCurrencyUsage);
9265 fmtCopy->setCurrencyUsage(newCurrencyUsage, status);
9266 assertEquals("Value after setter", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9267 fmtCopy->applyPattern(pattern, status);
9268 assertEquals("Value after applyPattern", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9269 assertFalse("currencyUsage", *fmt == *fmtCopy);
9270 }
9271
Test12567()9272 void NumberFormatTest::Test12567() {
9273 IcuTestErrorCode errorCode(*this, "Test12567");
9274 // Ticket #12567: DecimalFormat.equals() may not be symmetric
9275 LocalPointer<DecimalFormat> df1((DecimalFormat *)
9276 NumberFormat::createInstance(Locale::getUS(), UNUM_CURRENCY, errorCode));
9277 LocalPointer<DecimalFormat> df2((DecimalFormat *)
9278 NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, errorCode));
9279 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9280 // NOTE: CurrencyPluralInfo equality not tested in C++ because its operator== is not defined.
9281 df1->applyPattern(u"0.00", errorCode);
9282 df2->applyPattern(u"0.00", errorCode);
9283 assertTrue("df1 == df2", *df1 == *df2);
9284 assertTrue("df2 == df1", *df2 == *df1);
9285 df2->setPositivePrefix(u"abc");
9286 assertTrue("df1 != df2", *df1 != *df2);
9287 assertTrue("df2 != df1", *df2 != *df1);
9288 }
9289
Test11626_CustomizeCurrencyPluralInfo()9290 void NumberFormatTest::Test11626_CustomizeCurrencyPluralInfo() {
9291 IcuTestErrorCode errorCode(*this, "Test11626_CustomizeCurrencyPluralInfo");
9292 // Ticket #11626: No unit test demonstrating how to use CurrencyPluralInfo to
9293 // change formatting spelled out currencies
9294 // Use locale sr because it has interesting plural rules.
9295 Locale locale("sr");
9296 LocalPointer<DecimalFormatSymbols> symbols(new DecimalFormatSymbols(locale, errorCode), errorCode);
9297 CurrencyPluralInfo info(locale, errorCode);
9298 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9299 info.setCurrencyPluralPattern(u"one", u"0 qwerty", errorCode);
9300 info.setCurrencyPluralPattern(u"few", u"0 dvorak", errorCode);
9301 DecimalFormat df(u"#", symbols.orphan(), UNUM_CURRENCY_PLURAL, errorCode);
9302 df.setCurrencyPluralInfo(info);
9303 df.setCurrency(u"USD");
9304 df.setMaximumFractionDigits(0);
9305
9306 UnicodeString result;
9307 assertEquals("Plural one", u"1 qwerty", df.format(1, result, errorCode));
9308 assertEquals("Plural few", u"3 dvorak", df.format(3, result.remove(), errorCode));
9309 assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9310
9311 info.setPluralRules(u"few: n is 1; one: n in 2..4", errorCode);
9312 df.setCurrencyPluralInfo(info);
9313 assertEquals("Plural one", u"1 dvorak", df.format(1, result.remove(), errorCode));
9314 assertEquals("Plural few", u"3 qwerty", df.format(3, result.remove(), errorCode));
9315 assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9316 }
9317
Test20073_StrictPercentParseErrorIndex()9318 void NumberFormatTest::Test20073_StrictPercentParseErrorIndex() {
9319 IcuTestErrorCode status(*this, "Test20073_StrictPercentParseErrorIndex");
9320 ParsePosition parsePosition(0);
9321 DecimalFormat df(u"0%", {"en-us", status}, status);
9322 if (U_FAILURE(status)) {
9323 dataerrln("Unable to create DecimalFormat instance.");
9324 return;
9325 }
9326 df.setLenient(FALSE);
9327 Formattable result;
9328 df.parse(u"%2%", result, parsePosition);
9329 assertEquals("", 0, parsePosition.getIndex());
9330 assertEquals("", 0, parsePosition.getErrorIndex());
9331 }
9332
Test13056_GroupingSize()9333 void NumberFormatTest::Test13056_GroupingSize() {
9334 UErrorCode status = U_ZERO_ERROR;
9335 DecimalFormat df(u"#,##0", status);
9336 if (!assertSuccess("", status)) return;
9337 assertEquals("Primary grouping should return 3", 3, df.getGroupingSize());
9338 assertEquals("Secondary grouping should return 0", 0, df.getSecondaryGroupingSize());
9339 df.setSecondaryGroupingSize(3);
9340 assertEquals("Primary grouping should still return 3", 3, df.getGroupingSize());
9341 assertEquals("Secondary grouping should round-trip", 3, df.getSecondaryGroupingSize());
9342 df.setGroupingSize(4);
9343 assertEquals("Primary grouping should return 4", 4, df.getGroupingSize());
9344 assertEquals("Secondary should remember explicit setting and return 3", 3, df.getSecondaryGroupingSize());
9345 }
9346
9347
Test11025_CurrencyPadding()9348 void NumberFormatTest::Test11025_CurrencyPadding() {
9349 UErrorCode status = U_ZERO_ERROR;
9350 UnicodeString pattern(u"¤¤ **####0.00");
9351 DecimalFormatSymbols sym(Locale::getFrance(), status);
9352 if (!assertSuccess("", status)) return;
9353 DecimalFormat fmt(pattern, sym, status);
9354 if (!assertSuccess("", status)) return;
9355 UnicodeString result;
9356 fmt.format(433.0, result);
9357 assertEquals("Number should be padded to 11 characters", "EUR *433,00", result);
9358 }
9359
Test11648_ExpDecFormatMalPattern()9360 void NumberFormatTest::Test11648_ExpDecFormatMalPattern() {
9361 UErrorCode status = U_ZERO_ERROR;
9362
9363 DecimalFormat fmt("0.00", {"en", status}, status);
9364 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9365 fmt.setScientificNotation(TRUE);
9366 UnicodeString pattern;
9367
9368 assertEquals("A valid scientific notation pattern should be produced",
9369 "0.00E0",
9370 fmt.toPattern(pattern));
9371
9372 DecimalFormat fmt2(pattern, status);
9373 assertSuccess("", status);
9374 }
9375
Test11649_DecFmtCurrencies()9376 void NumberFormatTest::Test11649_DecFmtCurrencies() {
9377 IcuTestErrorCode status(*this, "Test11649_DecFmtCurrencies");
9378 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
9379 pattern = pattern.unescape();
9380 DecimalFormat fmt(pattern, status);
9381 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9382 static const UChar USD[] = u"USD";
9383 fmt.setCurrency(USD);
9384 UnicodeString appendTo;
9385
9386 assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
9387 UnicodeString topattern;
9388
9389 assertEquals("", pattern, fmt.toPattern(topattern));
9390 DecimalFormat fmt2(topattern, status);
9391 fmt2.setCurrency(USD);
9392
9393 appendTo.remove();
9394 assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
9395 }
9396
Test13148_ParseGroupingSeparators()9397 void NumberFormatTest::Test13148_ParseGroupingSeparators() {
9398 IcuTestErrorCode status(*this, "Test13148");
9399 LocalPointer<DecimalFormat> fmt(
9400 (DecimalFormat*)NumberFormat::createInstance("en-ZA", status), status);
9401 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9402
9403 DecimalFormatSymbols symbols = *fmt->getDecimalFormatSymbols();
9404
9405 symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'.');
9406 symbols.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u',');
9407 fmt->setDecimalFormatSymbols(symbols);
9408 Formattable number;
9409 fmt->parse(u"300,000", number, status);
9410 assertEquals("Should parse as 300000", 300000LL, number.getInt64(status));
9411 }
9412
Test12753_PatternDecimalPoint()9413 void NumberFormatTest::Test12753_PatternDecimalPoint() {
9414 UErrorCode status = U_ZERO_ERROR;
9415 DecimalFormatSymbols symbols(Locale::getUS(), status);
9416 symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"*", false);
9417 DecimalFormat df(u"0.00", symbols, status);
9418 if (!assertSuccess("", status)) return;
9419 df.setDecimalPatternMatchRequired(true);
9420 Formattable result;
9421 df.parse(u"123",result, status);
9422 assertEquals("Parsing integer succeeded even though setDecimalPatternMatchRequired was set",
9423 U_INVALID_FORMAT_ERROR, status);
9424 }
9425
Test11647_PatternCurrencySymbols()9426 void NumberFormatTest::Test11647_PatternCurrencySymbols() {
9427 UErrorCode status = U_ZERO_ERROR;
9428 DecimalFormat df(status);
9429 df.applyPattern(u"¤¤¤¤#", status);
9430 if (!assertSuccess("", status)) return;
9431 UnicodeString actual;
9432 df.format(123, actual);
9433 assertEquals("Should replace 4 currency signs with U+FFFD", u"\uFFFD123", actual);
9434 }
9435
Test11913_BigDecimal()9436 void NumberFormatTest::Test11913_BigDecimal() {
9437 UErrorCode status = U_ZERO_ERROR;
9438 LocalPointer<NumberFormat> df(NumberFormat::createInstance(Locale::getEnglish(), status), status);
9439 if (!assertSuccess("", status)) return;
9440 UnicodeString result;
9441 df->format(StringPiece("1.23456789E400"), result, nullptr, status);
9442 assertSuccess("", status);
9443 assertEquals("Should format more than 309 digits", u"12,345,678", UnicodeString(result, 0, 10));
9444 assertEquals("Should format more than 309 digits", 534, result.length());
9445 }
9446
Test11020_RoundingInScientificNotation()9447 void NumberFormatTest::Test11020_RoundingInScientificNotation() {
9448 UErrorCode status = U_ZERO_ERROR;
9449 DecimalFormatSymbols sym(Locale::getFrance(), status);
9450 DecimalFormat fmt(u"0.05E0", sym, status);
9451 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9452 assertSuccess("", status);
9453 UnicodeString result;
9454 fmt.format(12301.2, result);
9455 assertEquals("Rounding increment should be applied after magnitude scaling", u"1,25E4", result);
9456 }
9457
Test11640_TripleCurrencySymbol()9458 void NumberFormatTest::Test11640_TripleCurrencySymbol() {
9459 IcuTestErrorCode status(*this, "Test11640_TripleCurrencySymbol");
9460 UnicodeString actual;
9461 DecimalFormat dFormat(u"¤¤¤ 0", status);
9462 if (U_FAILURE(status)) {
9463 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9464 return;
9465 }
9466 dFormat.setCurrency(u"USD");
9467 UnicodeString result;
9468 dFormat.getPositivePrefix(result);
9469 assertEquals("Triple-currency should give long name on getPositivePrefix",
9470 "US dollars ", result);
9471 }
9472
9473
Test13763_FieldPositionIteratorOffset()9474 void NumberFormatTest::Test13763_FieldPositionIteratorOffset() {
9475 IcuTestErrorCode status(*this, "Test13763_FieldPositionIteratorOffset");
9476 FieldPositionIterator fpi;
9477 UnicodeString result(u"foo\U0001F4FBbar"); // 8 code units
9478 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9479 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9480 nf->format(5142.3, result, &fpi, status);
9481
9482 int32_t expected[] = {
9483 UNUM_GROUPING_SEPARATOR_FIELD, 9, 10,
9484 UNUM_INTEGER_FIELD, 8, 13,
9485 UNUM_DECIMAL_SEPARATOR_FIELD, 13, 14,
9486 UNUM_FRACTION_FIELD, 14, 15,
9487 };
9488 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
9489 expectPositions(fpi, expected, tupleCount, result);
9490 }
9491
Test13777_ParseLongNameNonCurrencyMode()9492 void NumberFormatTest::Test13777_ParseLongNameNonCurrencyMode() {
9493 IcuTestErrorCode status(*this, "Test13777_ParseLongNameNonCurrencyMode");
9494
9495 LocalPointer<NumberFormat> df(
9496 NumberFormat::createInstance("en-us", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9497 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9498 expect2(*df, 1.5, u"1.50 US dollars");
9499 }
9500
Test13804_EmptyStringsWhenParsing()9501 void NumberFormatTest::Test13804_EmptyStringsWhenParsing() {
9502 IcuTestErrorCode status(*this, "Test13804_EmptyStringsWhenParsing");
9503
9504 DecimalFormatSymbols dfs("en", status);
9505 if (status.errIfFailureAndReset()) {
9506 return;
9507 }
9508 dfs.setSymbol(DecimalFormatSymbols::kCurrencySymbol, u"", FALSE);
9509 dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"", FALSE);
9510 dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u"", FALSE);
9511 dfs.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, u"", FALSE);
9512 dfs.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, u"", FALSE);
9513 dfs.setSymbol(DecimalFormatSymbols::kThreeDigitSymbol, u"", FALSE);
9514 dfs.setSymbol(DecimalFormatSymbols::kFourDigitSymbol, u"", FALSE);
9515 dfs.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, u"", FALSE);
9516 dfs.setSymbol(DecimalFormatSymbols::kSixDigitSymbol, u"", FALSE);
9517 dfs.setSymbol(DecimalFormatSymbols::kSevenDigitSymbol, u"", FALSE);
9518 dfs.setSymbol(DecimalFormatSymbols::kEightDigitSymbol, u"", FALSE);
9519 dfs.setSymbol(DecimalFormatSymbols::kNineDigitSymbol, u"", FALSE);
9520 dfs.setSymbol(DecimalFormatSymbols::kExponentMultiplicationSymbol, u"", FALSE);
9521 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"", FALSE);
9522 dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u"", FALSE);
9523 dfs.setSymbol(DecimalFormatSymbols::kInfinitySymbol, u"", FALSE);
9524 dfs.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, u"", FALSE);
9525 dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"", FALSE);
9526 dfs.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, u"", FALSE);
9527 dfs.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, u"", FALSE);
9528 dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, u"", FALSE);
9529 dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, FALSE, u"");
9530 dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, TRUE, u"");
9531 dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u"", FALSE);
9532 dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u"", FALSE);
9533 dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"", FALSE);
9534
9535 DecimalFormat df("0", dfs, status);
9536 if (status.errIfFailureAndReset()) {
9537 return;
9538 }
9539 df.setGroupingUsed(TRUE);
9540 df.setScientificNotation(TRUE);
9541 df.setLenient(TRUE); // enable all matchers
9542 {
9543 UnicodeString result;
9544 df.format(0, result); // should not crash or hit infinite loop
9545 }
9546 const char16_t* samples[] = {
9547 u"",
9548 u"123",
9549 u"$123",
9550 u"-",
9551 u"+",
9552 u"44%",
9553 u"1E+2.3"
9554 };
9555 for (auto& sample : samples) {
9556 logln(UnicodeString(u"Attempting parse on: ") + sample);
9557 status.setScope(sample);
9558 // We don't care about the results, only that we don't crash and don't loop.
9559 Formattable result;
9560 ParsePosition ppos(0);
9561 df.parse(sample, result, ppos);
9562 ppos = ParsePosition(0);
9563 LocalPointer<CurrencyAmount> curramt(df.parseCurrency(sample, ppos));
9564 status.errIfFailureAndReset();
9565 }
9566
9567 // Test with a nonempty exponent separator symbol to cover more code
9568 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"E", FALSE);
9569 df.setDecimalFormatSymbols(dfs);
9570 {
9571 Formattable result;
9572 ParsePosition ppos(0);
9573 df.parse(u"1E+2.3", result, ppos);
9574 }
9575 }
9576
Test20037_ScientificIntegerOverflow()9577 void NumberFormatTest::Test20037_ScientificIntegerOverflow() {
9578 IcuTestErrorCode status(*this, "Test20037_ScientificIntegerOverflow");
9579
9580 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(status));
9581 if (U_FAILURE(status)) {
9582 dataerrln("Unable to create NumberFormat instance.");
9583 return;
9584 }
9585 Formattable result;
9586
9587 // Test overflow of exponent
9588 nf->parse(u"1E-2147483648", result, status);
9589 StringPiece sp = result.getDecimalNumber(status);
9590 assertEquals(u"Should snap to zero",
9591 u"0",
9592 {sp.data(), sp.length(), US_INV});
9593
9594 // Test edge case overflow of exponent
9595 result = Formattable();
9596 nf->parse(u"1E-2147483647E-1", result, status);
9597 sp = result.getDecimalNumber(status);
9598 assertEquals(u"Should not overflow and should parse only the first exponent",
9599 u"1E-2147483647",
9600 {sp.data(), sp.length(), US_INV});
9601
9602 // Test edge case overflow of exponent
9603 result = Formattable();
9604 nf->parse(u".0003e-2147483644", result, status);
9605 sp = result.getDecimalNumber(status);
9606 assertEquals(u"Should not overflow",
9607 u"3E-2147483648",
9608 {sp.data(), sp.length(), US_INV});
9609
9610 // Test largest parseable exponent
9611 result = Formattable();
9612 nf->parse(u"9876e2147483643", result, status);
9613 sp = result.getDecimalNumber(status);
9614 assertEquals(u"Should not overflow",
9615 u"9.876E+2147483646",
9616 {sp.data(), sp.length(), US_INV});
9617
9618 // Test max value as well
9619 const char16_t* infinityInputs[] = {
9620 u"9876e2147483644",
9621 u"9876e2147483645",
9622 u"9876e2147483646",
9623 u"9876e2147483647",
9624 u"9876e2147483648",
9625 u"9876e2147483649",
9626 };
9627 for (const auto& input : infinityInputs) {
9628 result = Formattable();
9629 nf->parse(input, result, status);
9630 sp = result.getDecimalNumber(status);
9631 assertEquals(UnicodeString("Should become Infinity: ") + input,
9632 u"Infinity",
9633 {sp.data(), sp.length(), US_INV});
9634 }
9635 }
9636
Test13840_ParseLongStringCrash()9637 void NumberFormatTest::Test13840_ParseLongStringCrash() {
9638 IcuTestErrorCode status(*this, "Test13840_ParseLongStringCrash");
9639
9640 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9641 if (status.errIfFailureAndReset()) { return; }
9642
9643 Formattable result;
9644 static const char16_t* bigString =
9645 u"111111111111111111111111111111111111111111111111111111111111111111111"
9646 u"111111111111111111111111111111111111111111111111111111111111111111111"
9647 u"111111111111111111111111111111111111111111111111111111111111111111111"
9648 u"111111111111111111111111111111111111111111111111111111111111111111111"
9649 u"111111111111111111111111111111111111111111111111111111111111111111111"
9650 u"111111111111111111111111111111111111111111111111111111111111111111111";
9651 nf->parse(bigString, result, status);
9652
9653 // Normalize the input string:
9654 CharString expectedChars;
9655 expectedChars.appendInvariantChars(bigString, status);
9656 DecimalQuantity expectedDQ;
9657 expectedDQ.setToDecNumber(expectedChars.toStringPiece(), status);
9658 UnicodeString expectedUString = expectedDQ.toScientificString();
9659
9660 // Get the output string:
9661 StringPiece actualChars = result.getDecimalNumber(status);
9662 UnicodeString actualUString = UnicodeString(actualChars.data(), actualChars.length(), US_INV);
9663
9664 assertEquals("Should round-trip without crashing", expectedUString, actualUString);
9665 }
9666
Test13850_EmptyStringCurrency()9667 void NumberFormatTest::Test13850_EmptyStringCurrency() {
9668 IcuTestErrorCode status(*this, "Test13840_EmptyStringCurrency");
9669
9670 struct TestCase {
9671 const char16_t* currencyArg;
9672 UErrorCode expectedError;
9673 } cases[] = {
9674 {u"", U_USING_FALLBACK_WARNING},
9675 {u"U", U_ILLEGAL_ARGUMENT_ERROR},
9676 {u"Us", U_ILLEGAL_ARGUMENT_ERROR},
9677 {nullptr, U_USING_FALLBACK_WARNING},
9678 {u"U$D", U_INVARIANT_CONVERSION_ERROR},
9679 {u"Xxx", U_USING_FALLBACK_WARNING}
9680 };
9681 for (const auto& cas : cases) {
9682 UnicodeString message(u"with currency arg: ");
9683 if (cas.currencyArg == nullptr) {
9684 message += u"nullptr";
9685 } else {
9686 message += UnicodeString(cas.currencyArg);
9687 }
9688 status.setScope(message);
9689 LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-US", status), status);
9690 if (status.errIfFailureAndReset()) { return; }
9691 UnicodeString actual;
9692 nf->format(1, actual, status);
9693 status.errIfFailureAndReset();
9694 assertEquals(u"Should format with US currency " + message, u"$1.00", actual);
9695 nf->setCurrency(cas.currencyArg, status);
9696 if (status.expectErrorAndReset(cas.expectedError)) {
9697 // If an error occurred, do not check formatting.
9698 continue;
9699 }
9700 nf->format(1, actual.remove(), status);
9701 assertEquals(u"Should unset the currency " + message, u"\u00A41.00", actual);
9702 status.errIfFailureAndReset();
9703 }
9704 }
9705
Test20348_CurrencyPrefixOverride()9706 void NumberFormatTest::Test20348_CurrencyPrefixOverride() {
9707 IcuTestErrorCode status(*this, "Test20348_CurrencyPrefixOverride");
9708 LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9709 NumberFormat::createCurrencyInstance("en", status)));
9710 if (status.errIfFailureAndReset()) { return; }
9711 UnicodeString result;
9712 assertEquals("Initial pattern",
9713 u"¤#,##0.00", fmt->toPattern(result.remove()));
9714 assertEquals("Initial prefix",
9715 u"¤", fmt->getPositivePrefix(result.remove()));
9716 assertEquals("Initial suffix",
9717 u"-¤", fmt->getNegativePrefix(result.remove()));
9718 assertEquals("Initial format",
9719 u"\u00A4100.00", fmt->format(100, result.remove(), NULL, status));
9720
9721 fmt->setPositivePrefix(u"$");
9722 assertEquals("Set positive prefix pattern",
9723 u"$#,##0.00;-\u00A4#,##0.00", fmt->toPattern(result.remove()));
9724 assertEquals("Set positive prefix prefix",
9725 u"$", fmt->getPositivePrefix(result.remove()));
9726 assertEquals("Set positive prefix suffix",
9727 u"-¤", fmt->getNegativePrefix(result.remove()));
9728 assertEquals("Set positive prefix format",
9729 u"$100.00", fmt->format(100, result.remove(), NULL, status));
9730
9731 fmt->setNegativePrefix(u"-$");
9732 assertEquals("Set negative prefix pattern",
9733 u"$#,##0.00;'-'$#,##0.00", fmt->toPattern(result.remove()));
9734 assertEquals("Set negative prefix prefix",
9735 u"$", fmt->getPositivePrefix(result.remove()));
9736 assertEquals("Set negative prefix suffix",
9737 u"-$", fmt->getNegativePrefix(result.remove()));
9738 assertEquals("Set negative prefix format",
9739 u"$100.00", fmt->format(100, result.remove(), NULL, status));
9740 }
9741
Test20956_MonetarySymbolGetters()9742 void NumberFormatTest::Test20956_MonetarySymbolGetters() {
9743 IcuTestErrorCode status(*this, "Test20956_MonetarySymbolGetters");
9744 LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9745 NumberFormat::createCurrencyInstance("et", status)));
9746 if (status.errDataIfFailureAndReset()) {
9747 return;
9748 }
9749
9750 decimalFormat->setCurrency(u"EEK");
9751
9752 const DecimalFormatSymbols* decimalFormatSymbols = decimalFormat->getDecimalFormatSymbols();
9753 assertEquals("MONETARY DECIMAL SEPARATOR",
9754 u".",
9755 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
9756 assertEquals("DECIMAL SEPARATOR",
9757 u",",
9758 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol));
9759 assertEquals("MONETARY GROUPING SEPARATOR",
9760 u" ",
9761 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol));
9762 assertEquals("GROUPING SEPARATOR",
9763 u" ",
9764 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
9765 assertEquals("CURRENCY SYMBOL",
9766 u"kr",
9767 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
9768
9769 UnicodeString sb;
9770 decimalFormat->format(12345.12, sb, status);
9771 assertEquals("OUTPUT", u"12 345.12 kr", sb);
9772 }
9773
Test20358_GroupingInPattern()9774 void NumberFormatTest::Test20358_GroupingInPattern() {
9775 IcuTestErrorCode status(*this, "Test20358_GroupingInPattern");
9776 LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9777 NumberFormat::createInstance("en", status)));
9778 if (status.errIfFailureAndReset()) { return; }
9779 UnicodeString result;
9780 assertEquals("Initial pattern",
9781 u"#,##0.###", fmt->toPattern(result.remove()));
9782 assertTrue("Initial grouping",
9783 fmt->isGroupingUsed());
9784 assertEquals("Initial format",
9785 u"54,321", fmt->format(54321, result.remove(), NULL, status));
9786
9787 fmt->setGroupingUsed(false);
9788 assertEquals("Set grouping false",
9789 u"0.###", fmt->toPattern(result.remove()));
9790 assertFalse("Set grouping false grouping",
9791 fmt->isGroupingUsed());
9792 assertEquals("Set grouping false format",
9793 u"54321", fmt->format(54321, result.remove(), NULL, status));
9794
9795 fmt->setGroupingUsed(true);
9796 assertEquals("Set grouping true",
9797 u"#,##0.###", fmt->toPattern(result.remove()));
9798 assertTrue("Set grouping true grouping",
9799 fmt->isGroupingUsed());
9800 assertEquals("Set grouping true format",
9801 u"54,321", fmt->format(54321, result.remove(), NULL, status));
9802 }
9803
Test13731_DefaultCurrency()9804 void NumberFormatTest::Test13731_DefaultCurrency() {
9805 IcuTestErrorCode status(*this, "Test13731_DefaultCurrency");
9806 UnicodeString result;
9807 {
9808 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9809 "en", UNumberFormatStyle::UNUM_CURRENCY, status), status);
9810 if (status.errIfFailureAndReset()) { return; }
9811 assertEquals("symbol", u"¤1.10",
9812 nf->format(1.1, result.remove(), status));
9813 assertEquals("currency", u"XXX", nf->getCurrency());
9814 }
9815 {
9816 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9817 "en", UNumberFormatStyle::UNUM_CURRENCY_ISO, status), status);
9818 if (status.errIfFailureAndReset()) { return; }
9819 assertEquals("iso_code", u"XXX 1.10",
9820 nf->format(1.1, result.remove(), status));
9821 assertEquals("currency", u"XXX", nf->getCurrency());
9822 }
9823 {
9824 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9825 "en", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9826 if (status.errIfFailureAndReset()) { return; }
9827 assertEquals("plural", u"1.10 (unknown currency)",
9828 nf->format(1.1, result.remove(), status));
9829 assertEquals("currency", u"XXX", nf->getCurrency());
9830 }
9831 }
9832
Test20499_CurrencyVisibleDigitsPlural()9833 void NumberFormatTest::Test20499_CurrencyVisibleDigitsPlural() {
9834 IcuTestErrorCode status(*this, "Test20499_CurrencyVisibleDigitsPlural");
9835 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9836 "ro-RO", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9837 const char16_t* expected = u"24,00 lei românești";
9838 for (int32_t i=0; i<5; i++) {
9839 UnicodeString actual;
9840 nf->format(24, actual, status);
9841 assertEquals(UnicodeString(u"iteration ") + Int64ToUnicodeString(i),
9842 expected, actual);
9843 }
9844 }
9845
Test13735_GroupingSizeGetter()9846 void NumberFormatTest::Test13735_GroupingSizeGetter() {
9847 IcuTestErrorCode status(*this, "Test13735_GroupingSizeGetter");
9848 {
9849 DecimalFormat df("0", {"en", status}, status);
9850 assertEquals("pat 0: ", 0, df.getGroupingSize());
9851 df.setGroupingUsed(false);
9852 assertEquals("pat 0 then disabled: ", 0, df.getGroupingSize());
9853 df.setGroupingUsed(true);
9854 assertEquals("pat 0 then enabled: ", 0, df.getGroupingSize());
9855 }
9856 {
9857 DecimalFormat df("#,##0", {"en", status}, status);
9858 assertEquals("pat #,##0: ", 3, df.getGroupingSize());
9859 df.setGroupingUsed(false);
9860 assertEquals("pat #,##0 then disabled: ", 3, df.getGroupingSize());
9861 df.setGroupingUsed(true);
9862 assertEquals("pat #,##0 then enabled: ", 3, df.getGroupingSize());
9863 }
9864 }
9865
Test13734_StrictFlexibleWhitespace()9866 void NumberFormatTest::Test13734_StrictFlexibleWhitespace() {
9867 IcuTestErrorCode status(*this, "Test13734_StrictFlexibleWhitespace");
9868 {
9869 DecimalFormat df("+0", {"en", status}, status);
9870 df.setLenient(FALSE);
9871 Formattable result;
9872 ParsePosition ppos;
9873 df.parse("+ 33", result, ppos);
9874 assertEquals("ppos : ", 0, ppos.getIndex());
9875 assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9876 }
9877 {
9878 DecimalFormat df("+ 0", {"en", status}, status);
9879 df.setLenient(FALSE);
9880 Formattable result;
9881 ParsePosition ppos;
9882 df.parse("+ 33", result, ppos);
9883 assertEquals("ppos : ", 0, ppos.getIndex());
9884 assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9885 }
9886 }
9887
Test20961_CurrencyPluralPattern()9888 void NumberFormatTest::Test20961_CurrencyPluralPattern() {
9889 IcuTestErrorCode status(*this, "Test20961_CurrencyPluralPattern");
9890 {
9891 LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9892 NumberFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9893 if (status.errDataIfFailureAndReset()) {
9894 return;
9895 }
9896 UnicodeString result;
9897 decimalFormat->toPattern(result);
9898 assertEquals("Currency pattern", u"#,##0.00 ¤¤¤", result);
9899 }
9900 }
9901
Test21134_ToNumberFormatter()9902 void NumberFormatTest::Test21134_ToNumberFormatter() {
9903 IcuTestErrorCode status(*this, "Test21134_ToNumberFormatter");
9904 LocalizedNumberFormatter outer1;
9905 LocalizedNumberFormatter outer2;
9906 LocalPointer<LocalizedNumberFormatter> outer3;
9907 {
9908 // Case 1: new formatter object
9909 DecimalFormat inner(u"a0b", {"en", status}, status);
9910 if (auto ptr = inner.toNumberFormatter(status)) {
9911 // Copy assignment
9912 outer1 = *ptr;
9913 } else {
9914 status.errIfFailureAndReset();
9915 return;
9916 }
9917 }
9918 {
9919 // Case 2: compiled formatter object (used at least 3 times)
9920 DecimalFormat inner(u"c0d", {"en", status}, status);
9921 UnicodeString dummy;
9922 inner.format(100, dummy);
9923 inner.format(100, dummy);
9924 inner.format(100, dummy);
9925 if (auto ptr = inner.toNumberFormatter(status)) {
9926 // Copy assignment
9927 outer2 = *ptr;
9928 } else {
9929 status.errIfFailureAndReset();
9930 return;
9931 }
9932 }
9933 {
9934 // Case 3: currency plural info (different code path)
9935 LocalPointer<DecimalFormat> inner(static_cast<DecimalFormat*>(
9936 DecimalFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9937 if (auto ptr = inner->toNumberFormatter(status)) {
9938 // Copy constructor
9939 outer3.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(*ptr), status);
9940 } else {
9941 status.errIfFailureAndReset();
9942 return;
9943 }
9944 }
9945 auto result1 = outer1.formatDouble(99, status);
9946 assertEquals("Using NumberFormatter from DecimalFormat, new version",
9947 u"a99b",
9948 result1.toTempString(status));
9949 auto result2 = outer2.formatDouble(99, status);
9950 assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9951 u"c99d",
9952 result2.toTempString(status));
9953 auto result3 = outer3->formatDouble(99, status);
9954 assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9955 u"99.00 US dollars",
9956 result3.toTempString(status));
9957 }
9958
Test13733_StrictAndLenient()9959 void NumberFormatTest::Test13733_StrictAndLenient() {
9960 IcuTestErrorCode status(*this, "Test13733_StrictAndLenient");
9961
9962 static const struct TestCase {
9963 const char16_t* inputString;
9964 const char16_t* patternString;
9965 int64_t expectedStrictParse;
9966 int64_t expectedLenientParse;
9967 } cases[] = { {u"CA$ 12", u"¤ 0", 12, 12},
9968 {u"CA$12", u"¤0", 12, 12},
9969 {u"CAD 12", u"¤¤ 0", 12, 12},
9970 {u"12 CAD", u"0 ¤¤", 12, 12},
9971 {u"12 Canadian dollars", u"0 ¤¤¤", 12, 12},
9972 {u"$12 ", u"¤¤¤¤0", 12, 12},
9973 {u"12$", u"0¤¤¤¤", 12, 12},
9974 {u"CA$ 12", u"¤0", 0, 12},
9975 {u"CA$ 12", u"0 ¤¤", 0, 12},
9976 {u"CA$ 12", u"0 ¤¤¤", 0, 12},
9977 {u"CA$ 12", u"¤¤¤¤0", 0, 12},
9978 {u"CA$ 12", u"0¤¤¤¤", 0, 12},
9979 {u"CA$12", u"¤ 0", 0, 12},
9980 {u"CA$12", u"¤¤ 0", 0, 12},
9981 {u"CA$12", u"0 ¤¤", 0, 12},
9982 {u"CA$12", u"0 ¤¤¤", 0, 12},
9983 {u"CA$12", u"0¤¤¤¤", 0, 12},
9984 {u"CAD 12", u"¤0", 0, 12},
9985 {u"CAD 12", u"0 ¤¤", 0, 12},
9986 {u"CAD 12", u"0 ¤¤¤", 0, 12},
9987 {u"CAD 12", u"¤¤¤¤0", 0, 12},
9988 {u"CAD 12", u"0¤¤¤¤", 0, 12},
9989 {u"12 CAD", u"¤ 0", 0, 12},
9990 {u"12 CAD", u"¤0", 0, 12},
9991 {u"12 CAD", u"¤¤ 0", 0, 12},
9992 {u"12 CAD", u"¤¤¤¤0", 0, 12},
9993 {u"12 CAD", u"0¤¤¤¤", 0, 12},
9994 {u"12 Canadian dollars", u"¤ 0", 0, 12},
9995 {u"12 Canadian dollars", u"¤0", 0, 12},
9996 {u"12 Canadian dollars", u"¤¤ 0", 0, 12},
9997 {u"12 Canadian dollars", u"¤¤¤¤0", 0, 12},
9998 {u"12 Canadian dollars", u"0¤¤¤¤", 0, 12},
9999 {u"$12 ", u"¤ 0", 0, 12},
10000 {u"$12 ", u"¤¤ 0", 0, 12},
10001 {u"$12 ", u"0 ¤¤", 0, 12},
10002 {u"$12 ", u"0 ¤¤¤", 0, 12},
10003 {u"$12 ", u"0¤¤¤¤", 0, 12},
10004 {u"12$", u"¤ 0", 0, 12},
10005 {u"12$", u"¤0", 0, 12},
10006 {u"12$", u"¤¤ 0", 0, 12},
10007 {u"12$", u"0 ¤¤", 0, 12},
10008 {u"12$", u"0 ¤¤¤", 0, 12},
10009 {u"12$", u"¤¤¤¤0", 0, 12} };
10010 for (auto& cas : cases) {
10011 UnicodeString inputString(cas.inputString);
10012 UnicodeString patternString(cas.patternString);
10013 int64_t parsedStrictValue = 0;
10014 int64_t parsedLenientValue = 0;
10015 ParsePosition ppos;
10016
10017 DecimalFormatSymbols dfs(Locale::getEnglish(), status);
10018 if (status.errDataIfFailureAndReset()) {
10019 return;
10020 }
10021 DecimalFormat df(patternString, dfs, status);
10022 if (status.errDataIfFailureAndReset()) {
10023 return;
10024 }
10025 df.setLenient(FALSE);
10026 LocalPointer<CurrencyAmount> ca_strict(df.parseCurrency(inputString, ppos));
10027 if (ca_strict != nullptr) {
10028 parsedStrictValue = ca_strict->getNumber().getInt64();
10029 }
10030 assertEquals("Strict parse of " + inputString + " using " + patternString,
10031 parsedStrictValue, cas.expectedStrictParse);
10032
10033 ppos.setIndex(0);
10034 df.setLenient(TRUE);
10035 LocalPointer<CurrencyAmount> ca_lenient(df.parseCurrency(inputString, ppos));
10036 Formattable parsedNumber_lenient = ca_lenient->getNumber();
10037 if (ca_lenient != nullptr) {
10038 parsedLenientValue = ca_lenient->getNumber().getInt64();
10039 }
10040 assertEquals("Lenient parse of " + inputString + " using " + patternString,
10041 parsedLenientValue, cas.expectedLenientParse);
10042 }
10043 }
10044
Test20425_IntegerIncrement()10045 void NumberFormatTest::Test20425_IntegerIncrement() {
10046 IcuTestErrorCode status(*this, "Test20425_IntegerIncrement");
10047
10048 DecimalFormat df("##00", status);
10049 df.setRoundingIncrement(1);
10050 UnicodeString actual;
10051 df.format(1235.5, actual, status);
10052 assertEquals("Should round to integer", u"1236", actual);
10053 }
10054
Test20425_FractionWithIntegerIncrement()10055 void NumberFormatTest::Test20425_FractionWithIntegerIncrement() {
10056 IcuTestErrorCode status(*this, "Test20425_FractionWithIntegerIncrement");
10057
10058 DecimalFormat df("0.0", status);
10059 df.setRoundingIncrement(1);
10060 UnicodeString actual;
10061 df.format(8.6, actual, status);
10062 assertEquals("Should have a fraction digit", u"9.0", actual);
10063 }
10064
Test21232_ParseTimeout()10065 void NumberFormatTest::Test21232_ParseTimeout() {
10066 IcuTestErrorCode status(*this, "Test21232_ParseTimeout");
10067
10068 DecimalFormat df(status);
10069 if (status.errDataIfFailureAndReset()) {
10070 return;
10071 }
10072
10073 UnicodeString input = u"4444444444444444444444444444444444444444";
10074 if (quick) {
10075 for (int32_t i = 0; i < 5; i++) {
10076 input.append(input);
10077 }
10078 assertEquals("Somewhat long input of digits", 1280, input.length());
10079 } else {
10080 for (int32_t i = 0; i < 12; i++) {
10081 input.append(input);
10082 }
10083 assertEquals("Very long input of digits", 163840, input.length());
10084 }
10085 Formattable result;
10086 df.parse(input, result, status);
10087 // Should not hang
10088 }
10089
Test10997_FormatCurrency()10090 void NumberFormatTest::Test10997_FormatCurrency() {
10091 IcuTestErrorCode status(*this, "Test10997_FormatCurrency");
10092
10093 LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance(Locale::getUS(), status));
10094 if (status.errDataIfFailureAndReset()) {
10095 return;
10096 }
10097 fmt->setMinimumFractionDigits(4);
10098 fmt->setMaximumFractionDigits(4);
10099
10100 FieldPosition fp;
10101
10102 UnicodeString str;
10103 Formattable usdAmnt(new CurrencyAmount(123.45, u"USD", status));
10104 fmt->format(usdAmnt, str, fp, status);
10105 assertEquals("minFrac 4 should be respected in default currency", u"$123.4500", str);
10106
10107 UnicodeString str2;
10108 Formattable eurAmnt(new CurrencyAmount(123.45, u"EUR", status));
10109 fmt->format(eurAmnt, str2, fp, status);
10110 assertEquals("minFrac 4 should be respected in different currency", u"€123.4500", str2);
10111 }
10112
Test21556_CurrencyAsDecimal()10113 void NumberFormatTest::Test21556_CurrencyAsDecimal() {
10114 IcuTestErrorCode status(*this, "Test21556_CurrencyAsDecimal");
10115
10116 {
10117 DecimalFormat df(u"a0¤00b", status);
10118 if (status.errDataIfFailureAndReset()) {
10119 return;
10120 }
10121 df.setCurrency(u"EUR", status);
10122 UnicodeString result;
10123 FieldPosition fp(UNUM_CURRENCY_FIELD);
10124 df.format(3.141, result, fp);
10125 assertEquals("Basic test: format", u"a3€14b", result);
10126 UnicodeString pattern;
10127 assertEquals("Basic test: toPattern", u"a0¤00b", df.toPattern(pattern));
10128 assertEquals("Basic test: field position begin", 2, fp.getBeginIndex());
10129 assertEquals("Basic test: field position end", 3, fp.getEndIndex());
10130 }
10131
10132 {
10133 LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-GB", status));
10134 DecimalFormat* df = static_cast<DecimalFormat*>(nf.getAlias());
10135 df->applyPattern(u"a0¤00b", status);
10136 UnicodeString result;
10137 FieldPosition fp(UNUM_CURRENCY_FIELD);
10138 df->format(3.141, result, fp);
10139 assertEquals("Via applyPattern: format", u"a3£14b", result);
10140 UnicodeString pattern;
10141 assertEquals("Via applyPattern: toPattern", u"a0¤00b", df->toPattern(pattern));
10142 assertEquals("Via applyPattern: field position begin", 2, fp.getBeginIndex());
10143 assertEquals("Via applyPattern: field position end", 3, fp.getEndIndex());
10144 }
10145 }
10146
10147 #endif /* #if !UCONFIG_NO_FORMATTING */
10148