blob: bdcce79c50cc40db337f322e5287db61731e9772 [file] [log] [blame]
Frank Tang3e05d9d2021-11-08 14:04:04 -08001// © 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
51namespace std {
52 bool isnan(double x) {
53 return _isnan(x);
54 }
55}
56#endif
57#if defined(isinf)
58#undef isinf
59namespace std {
60 bool isinf(double x) {
61 return _isinf(x);
62 }
63}
64#endif
65#endif
66
67using icu::number::impl::DecimalQuantity;
68using 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
76static const UChar EUR[] = {69,85,82,0}; // "EUR"
77static 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
97void 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);
Frank Tang1f164ee2022-11-08 12:31:27 -0800255 TESTCASE_AUTO(Test22088_Ethiopic);
Frank Tang3e05d9d2021-11-08 14:04:04 -0800256 TESTCASE_AUTO_END;
257}
258
259// -------------------------------------
260
261// Test API (increase code coverage)
262void
263NumberFormatTest::TestAPI(void)
264{
265 logln("Test API");
266 UErrorCode status = U_ZERO_ERROR;
267 NumberFormat *test = NumberFormat::createInstance("root", status);
268 if(U_FAILURE(status)) {
269 dataerrln("unable to create format object - %s", u_errorName(status));
270 }
271 if(test != NULL) {
272 test->setMinimumIntegerDigits(10);
273 test->setMaximumIntegerDigits(1);
274
275 test->setMinimumFractionDigits(10);
276 test->setMaximumFractionDigits(1);
277
278 UnicodeString result;
279 FieldPosition pos;
280 Formattable bla("Paja Patak"); // Donald Duck for non Serbian speakers
281 test->format(bla, result, pos, status);
282 if(U_SUCCESS(status)) {
283 errln("Yuck... Formatted a duck... As a number!");
284 } else {
285 status = U_ZERO_ERROR;
286 }
287
288 result.remove();
289 int64_t ll = 12;
290 test->format(ll, result);
291 assertEquals("format int64_t error", u"2.0", result);
292
293 test->setMinimumIntegerDigits(4);
294 test->setMinimumFractionDigits(4);
295
296 result.remove();
297 test->format(ll, result);
298 assertEquals("format int64_t error", u"0,012.0000", result);
299
300 ParsePosition ppos;
301 LocalPointer<CurrencyAmount> currAmt(test->parseCurrency("",ppos));
302 // old test for (U_FAILURE(status)) was bogus here, method does not set status!
303 if (ppos.getIndex()) {
304 errln("Parsed empty string as currency");
305 }
306
307 delete test;
308 }
309}
310
311class StubNumberFormat :public NumberFormat{
312public:
313 StubNumberFormat(){}
314 virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const override {
315 return appendTo;
316 }
317 virtual UnicodeString& format(int32_t ,UnicodeString& appendTo,FieldPosition& ) const override {
318 return appendTo.append((UChar)0x0033);
319 }
320 virtual UnicodeString& format(int64_t number,UnicodeString& appendTo,FieldPosition& pos) const override {
321 return NumberFormat::format(number, appendTo, pos);
322 }
323 virtual UnicodeString& format(const Formattable& , UnicodeString& appendTo, FieldPosition& , UErrorCode& ) const override {
324 return appendTo;
325 }
326 virtual void parse(const UnicodeString& ,
327 Formattable& ,
328 ParsePosition& ) const override {}
329 virtual void parse( const UnicodeString& ,
330 Formattable& ,
331 UErrorCode& ) const override {}
332 virtual UClassID getDynamicClassID(void) const override {
333 static char classID = 0;
334 return (UClassID)&classID;
335 }
336 virtual StubNumberFormat* clone() const override {return NULL;}
337};
338
339void
340NumberFormatTest::TestCoverage(void){
341 StubNumberFormat stub;
342 UnicodeString agent("agent");
343 FieldPosition pos;
344 int64_t num = 4;
345 if (stub.format(num, agent, pos) != UnicodeString("agent3")){
346 errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)");
347 }
348}
349
350void NumberFormatTest::TestLocalizedPatternSymbolCoverage() {
351 IcuTestErrorCode errorCode(*this, "TestLocalizedPatternSymbolCoverage");
352 // Ticket #12961: DecimalFormat::toLocalizedPattern() is not working as designed.
353 DecimalFormatSymbols dfs(errorCode);
354 dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u'⁖');
355 dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'⁘');
356 dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u'⁙');
357 dfs.setSymbol(DecimalFormatSymbols::kDigitSymbol, u'▰');
358 dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u'໐');
359 dfs.setSymbol(DecimalFormatSymbols::kSignificantDigitSymbol, u'⁕');
360 dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u'†');
361 dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u'‡');
362 dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u'⁜');
363 dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u'‱');
364 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"⁑⁑"); // tests multi-char sequence
365 dfs.setSymbol(DecimalFormatSymbols::kPadEscapeSymbol, u'⁂');
366
367 {
368 UnicodeString standardPattern(u"#,##0.05+%;#,##0.05-%");
369 UnicodeString localizedPattern(u"▰⁖▰▰໐⁘໐໕†⁜⁙▰⁖▰▰໐⁘໐໕‡⁜");
370
371 DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
372 df1.applyPattern(standardPattern, errorCode);
373 DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
374 df2.applyLocalizedPattern(localizedPattern, errorCode);
375 assertTrue("DecimalFormat instances should be equal", df1 == df2);
376 UnicodeString p2;
377 assertEquals("toPattern should match on localizedPattern instance",
378 standardPattern, df2.toPattern(p2));
379 UnicodeString lp1;
380 assertEquals("toLocalizedPattern should match on standardPattern instance",
381 localizedPattern, df1.toLocalizedPattern(lp1));
382 }
383
384 {
385 UnicodeString standardPattern(u"* @@@E0‰");
386 UnicodeString localizedPattern(u"⁂ ⁕⁕⁕⁑⁑໐‱");
387
388 DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
389 df1.applyPattern(standardPattern, errorCode);
390 DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
391 df2.applyLocalizedPattern(localizedPattern, errorCode);
392 assertTrue("DecimalFormat instances should be equal", df1 == df2);
393 UnicodeString p2;
394 assertEquals("toPattern should match on localizedPattern instance",
395 standardPattern, df2.toPattern(p2));
396 UnicodeString lp1;
397 assertEquals("toLocalizedPattern should match on standardPattern instance",
398 localizedPattern, df1.toLocalizedPattern(lp1));
399 }
400}
401
402// Test various patterns
403void
404NumberFormatTest::TestPatterns(void)
405{
406 UErrorCode status = U_ZERO_ERROR;
407 DecimalFormatSymbols sym(Locale::getUS(), status);
408 if (U_FAILURE(status)) { errcheckln(status, "FAIL: Could not construct DecimalFormatSymbols - %s", u_errorName(status)); return; }
409
410 const char* pat[] = { "#.#", "#.", ".#", "#" };
411 int32_t pat_length = UPRV_LENGTHOF(pat);
412 const char* newpat[] = { "0.#", "0.", "#.0", "0" };
413 const char* num[] = { "0", "0.", ".0", "0" };
414 for (int32_t i=0; i<pat_length; ++i)
415 {
416 status = U_ZERO_ERROR;
417 DecimalFormat fmt(pat[i], sym, status);
418 if (U_FAILURE(status)) { errln((UnicodeString)"FAIL: DecimalFormat constructor failed for " + pat[i]); continue; }
419 UnicodeString newp; fmt.toPattern(newp);
420 if (!(newp == newpat[i]))
421 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
422 "; " + newp + " seen instead");
423
424 UnicodeString s; (*(NumberFormat*)&fmt).format((int32_t)0, s);
425 if (!(s == num[i]))
426 {
427 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
428 "; " + s + " seen instead");
429 logln((UnicodeString)"Min integer digits = " + fmt.getMinimumIntegerDigits());
430 }
431 }
432}
433
434void NumberFormatTest::Test20186_SpacesAroundSemicolon() {
435 IcuTestErrorCode status(*this, "Test20186_SpacesAroundSemicolon");
436 DecimalFormat df(u"0.00 ; -0.00", {"en-us", status}, status);
437 expect2(df, 1, u"1.00 ");
438 expect2(df, -1, u" -1.00");
439
440 df = DecimalFormat(u"0.00;", {"en-us", status}, status);
441 expect2(df, 1, u"1.00");
442 expect2(df, -1, u"-1.00");
443
444 df = DecimalFormat(u"0.00;0.00", {"en-us", status}, status);
445 expect2(df, 1, u"1.00");
446 expect(df, -1, u"1.00"); // parses as 1, not -1
447
448 df = DecimalFormat(u" 0.00 ; -0.00 ", {"en-us", status}, status);
449 expect2(df, 1, u" 1.00 ");
450 expect2(df, -1, u" -1.00 ");
451}
452
453/*
454icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
455icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
456icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
457*/
458/*
459void
460NumberFormatTest::TestDigitList(void)
461{
462 // API coverage for DigitList
463 DigitList list1;
464 list1.append('1');
465 list1.fDecimalAt = 1;
466 DigitList list2;
467 list2.set((int32_t)1);
468 if (list1 != list2) {
469 errln("digitlist append, operator!= or set failed ");
470 }
471 if (!(list1 == list2)) {
472 errln("digitlist append, operator== or set failed ");
473 }
474}
475*/
476
477// -------------------------------------
478
479// Test exponential pattern
480void
481NumberFormatTest::TestExponential(void)
482{
483 UErrorCode status = U_ZERO_ERROR;
484 DecimalFormatSymbols sym(Locale::getUS(), status);
485 if (U_FAILURE(status)) { errcheckln(status, "FAIL: Bad status returned by DecimalFormatSymbols ct - %s", u_errorName(status)); return; }
486 const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
487 int32_t pat_length = UPRV_LENGTHOF(pat);
488
489// The following #if statements allow this test to be built and run on
490// platforms that do not have standard IEEE numerics. For example,
491// S/390 doubles have an exponent range of -78 to +75. For the
492// following #if statements to work, float.h must define
493// DBL_MAX_10_EXP to be a compile-time constant.
494
495// This section may be expanded as needed.
496
497#if DBL_MAX_10_EXP > 300
498 double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
499 int32_t val_length = UPRV_LENGTHOF(val);
500 const char* valFormat[] =
501 {
502 // 0.####E0
503 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
504 // 00.000E00
505 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
506 // ##0.######E000
507 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
508 // 0.###E0;[0.###E0]
509 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
510 };
511 double valParse[] =
512 {
513 0.01234, 123460000, 1.23E300, -3.1416E-271,
514 0.01234, 123460000, 1.23E300, -3.1416E-271,
515 0.01234, 123456800, 1.23E300, -3.141593E-271,
516 0.01234, 123500000, 1.23E300, -3.142E-271,
517 };
518#elif DBL_MAX_10_EXP > 70
519 double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
520 int32_t val_length = UPRV_LENGTHOF(val);
521 char* valFormat[] =
522 {
523 // 0.####E0
524 "1.234E-2", "1.2346E8", "1.23E70", "-3.1416E-71",
525 // 00.000E00
526 "12.340E-03", "12.346E07", "12.300E69", "-31.416E-72",
527 // ##0.######E000
528 "12.34E-003", "123.4568E006", "12.3E069", "-31.41593E-072",
529 // 0.###E0;[0.###E0]
530 "1.234E-2", "1.235E8", "1.23E70", "[3.142E-71]"
531 };
532 double valParse[] =
533 {
534 0.01234, 123460000, 1.23E70, -3.1416E-71,
535 0.01234, 123460000, 1.23E70, -3.1416E-71,
536 0.01234, 123456800, 1.23E70, -3.141593E-71,
537 0.01234, 123500000, 1.23E70, -3.142E-71,
538 };
539#else
540 // Don't test double conversion
541 double* val = 0;
542 int32_t val_length = 0;
543 char** valFormat = 0;
544 double* valParse = 0;
545 logln("Warning: Skipping double conversion tests");
546#endif
547
548 int32_t lval[] = { 0, -1, 1, 123456789 };
549 int32_t lval_length = UPRV_LENGTHOF(lval);
550 const char* lvalFormat[] =
551 {
552 // 0.####E0
553 "0E0", "-1E0", "1E0", "1.2346E8",
554 // 00.000E00
555 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
556 // ##0.######E000
557 "0E000", "-1E000", "1E000", "123.4568E006",
558 // 0.###E0;[0.###E0]
559 "0E0", "[1E0]", "1E0", "1.235E8"
560 };
561 int32_t lvalParse[] =
562 {
563 0, -1, 1, 123460000,
564 0, -1, 1, 123460000,
565 0, -1, 1, 123456800,
566 0, -1, 1, 123500000,
567 };
568 int32_t ival = 0, ilval = 0;
569 for (int32_t p=0; p<pat_length; ++p)
570 {
571 DecimalFormat fmt(pat[p], sym, status);
572 if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormat ct"); continue; }
573 UnicodeString pattern;
574 logln((UnicodeString)"Pattern \"" + pat[p] + "\" -toPattern-> \"" +
575 fmt.toPattern(pattern) + "\"");
576 int32_t v;
577 for (v=0; v<val_length; ++v)
578 {
579 UnicodeString s; (*(NumberFormat*)&fmt).format(val[v], s);
580 logln((UnicodeString)" " + val[v] + " -format-> " + s);
581 if (s != valFormat[v+ival])
582 errln((UnicodeString)"FAIL: Expected " + valFormat[v+ival]);
583
584 ParsePosition pos(0);
585 Formattable af;
586 fmt.parse(s, af, pos);
587 double a;
Frank Tang1f164ee2022-11-08 12:31:27 -0800588 UBool useEpsilon = false;
Frank Tang3e05d9d2021-11-08 14:04:04 -0800589 if (af.getType() == Formattable::kLong)
590 a = af.getLong();
591 else if (af.getType() == Formattable::kDouble) {
592 a = af.getDouble();
593#if U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400
594 // S/390 will show a failure like this:
595 //| -3.141592652999999e-271 -format-> -3.1416E-271
596 //| -parse-> -3.1416e-271
597 //| FAIL: Expected -3.141599999999999e-271
598 // To compensate, we use an epsilon-based equality
599 // test on S/390 only. We don't want to do this in
600 // general because it's less exacting.
Frank Tang1f164ee2022-11-08 12:31:27 -0800601 useEpsilon = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -0800602#endif
603 }
604 else {
605 errln(UnicodeString("FAIL: Non-numeric Formattable returned: ") + pattern + " " + s);
606 continue;
607 }
608 if (pos.getIndex() == s.length())
609 {
610 logln((UnicodeString)" -parse-> " + a);
611 // Use epsilon comparison as necessary
612 if ((useEpsilon &&
613 (uprv_fabs(a - valParse[v+ival]) / a > (2*DBL_EPSILON))) ||
614 (!useEpsilon && a != valParse[v+ival]))
615 {
616 errln((UnicodeString)"FAIL: Expected " + valParse[v+ival] + " but got " + a
617 + " on input " + s);
618 }
619 }
620 else {
621 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
622 errln((UnicodeString)" should be (" + s.length() + " chars) -> " + valParse[v+ival]);
623 }
624 }
625 for (v=0; v<lval_length; ++v)
626 {
627 UnicodeString s;
628 (*(NumberFormat*)&fmt).format(lval[v], s);
629 logln((UnicodeString)" " + lval[v] + "L -format-> " + s);
630 if (s != lvalFormat[v+ilval])
631 errln((UnicodeString)"ERROR: Expected " + lvalFormat[v+ilval] + " Got: " + s);
632
633 ParsePosition pos(0);
634 Formattable af;
635 fmt.parse(s, af, pos);
636 if (af.getType() == Formattable::kLong ||
637 af.getType() == Formattable::kInt64) {
638 UErrorCode status = U_ZERO_ERROR;
639 int32_t a = af.getLong(status);
640 if (pos.getIndex() == s.length())
641 {
642 logln((UnicodeString)" -parse-> " + a);
643 if (a != lvalParse[v+ilval])
644 errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval] + " but got " + a);
645 }
646 else
647 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
648 }
649 else
650 errln((UnicodeString)"FAIL: Non-long Formattable returned for " + s
651 + " Double: " + af.getDouble()
652 + ", Long: " + af.getLong());
653 }
654 ival += val_length;
655 ilval += lval_length;
656 }
657}
658
659void
660NumberFormatTest::TestScientific2() {
661 // jb 2552
662 UErrorCode status = U_ZERO_ERROR;
663 DecimalFormat* fmt = (DecimalFormat*)NumberFormat::createCurrencyInstance("en_US", status);
664 if (U_SUCCESS(status)) {
665 double num = 12.34;
666 expect(*fmt, num, "$12.34");
Frank Tang1f164ee2022-11-08 12:31:27 -0800667 fmt->setScientificNotation(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -0800668 expect(*fmt, num, "$1.23E1");
Frank Tang1f164ee2022-11-08 12:31:27 -0800669 fmt->setScientificNotation(false);
Frank Tang3e05d9d2021-11-08 14:04:04 -0800670 expect(*fmt, num, "$12.34");
671 }
672 delete fmt;
673}
674
675void
676NumberFormatTest::TestScientificGrouping() {
677 // jb 2552
678 UErrorCode status = U_ZERO_ERROR;
679 DecimalFormat fmt("##0.00E0",status);
680 if (assertSuccess("", status, true, __FILE__, __LINE__)) {
681 expect(fmt, .01234, "12.3E-3");
682 expect(fmt, .1234, "123E-3");
683 expect(fmt, 1.234, "1.23E0");
684 expect(fmt, 12.34, "12.3E0");
685 expect(fmt, 123.4, "123E0");
686 expect(fmt, 1234., "1.23E3");
687 }
688}
689
690/*static void setFromString(DigitList& dl, const char* str) {
691 char c;
Frank Tang1f164ee2022-11-08 12:31:27 -0800692 UBool decimalSet = false;
Frank Tang3e05d9d2021-11-08 14:04:04 -0800693 dl.clear();
694 while ((c = *str++)) {
695 if (c == '-') {
Frank Tang1f164ee2022-11-08 12:31:27 -0800696 dl.fIsPositive = false;
Frank Tang3e05d9d2021-11-08 14:04:04 -0800697 } else if (c == '+') {
Frank Tang1f164ee2022-11-08 12:31:27 -0800698 dl.fIsPositive = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -0800699 } else if (c == '.') {
700 dl.fDecimalAt = dl.fCount;
Frank Tang1f164ee2022-11-08 12:31:27 -0800701 decimalSet = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -0800702 } else {
703 dl.append(c);
704 }
705 }
706 if (!decimalSet) {
707 dl.fDecimalAt = dl.fCount;
708 }
709}*/
710
711void
712NumberFormatTest::TestInt64() {
713 UErrorCode status = U_ZERO_ERROR;
714 DecimalFormat fmt("#.#E0",status);
715 if (U_FAILURE(status)) {
716 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
717 return;
718 }
719 fmt.setMaximumFractionDigits(20);
720 if (U_SUCCESS(status)) {
721 expect(fmt, (Formattable)(int64_t)0, "0E0");
722 expect(fmt, (Formattable)(int64_t)-1, "-1E0");
723 expect(fmt, (Formattable)(int64_t)1, "1E0");
724 expect(fmt, (Formattable)(int64_t)2147483647, "2.147483647E9");
725 expect(fmt, (Formattable)((int64_t)-2147483647-1), "-2.147483648E9");
726 expect(fmt, (Formattable)(int64_t)U_INT64_MAX, "9.223372036854775807E18");
727 expect(fmt, (Formattable)(int64_t)U_INT64_MIN, "-9.223372036854775808E18");
728 }
729
730 // also test digitlist
731/* int64_t int64max = U_INT64_MAX;
732 int64_t int64min = U_INT64_MIN;
733 const char* int64maxstr = "9223372036854775807";
734 const char* int64minstr = "-9223372036854775808";
735 UnicodeString fail("fail: ");
736
737 // test max int64 value
738 DigitList dl;
739 setFromString(dl, int64maxstr);
740 {
Frank Tang1f164ee2022-11-08 12:31:27 -0800741 if (!dl.fitsIntoInt64(false)) {
Frank Tang3e05d9d2021-11-08 14:04:04 -0800742 errln(fail + int64maxstr + " didn't fit");
743 }
744 int64_t int64Value = dl.getInt64();
745 if (int64Value != int64max) {
746 errln(fail + int64maxstr);
747 }
748 dl.set(int64Value);
749 int64Value = dl.getInt64();
750 if (int64Value != int64max) {
751 errln(fail + int64maxstr);
752 }
753 }
754 // test negative of max int64 value (1 shy of min int64 value)
Frank Tang1f164ee2022-11-08 12:31:27 -0800755 dl.fIsPositive = false;
Frank Tang3e05d9d2021-11-08 14:04:04 -0800756 {
Frank Tang1f164ee2022-11-08 12:31:27 -0800757 if (!dl.fitsIntoInt64(false)) {
Frank Tang3e05d9d2021-11-08 14:04:04 -0800758 errln(fail + "-" + int64maxstr + " didn't fit");
759 }
760 int64_t int64Value = dl.getInt64();
761 if (int64Value != -int64max) {
762 errln(fail + "-" + int64maxstr);
763 }
764 dl.set(int64Value);
765 int64Value = dl.getInt64();
766 if (int64Value != -int64max) {
767 errln(fail + "-" + int64maxstr);
768 }
769 }
770 // test min int64 value
771 setFromString(dl, int64minstr);
772 {
Frank Tang1f164ee2022-11-08 12:31:27 -0800773 if (!dl.fitsIntoInt64(false)) {
Frank Tang3e05d9d2021-11-08 14:04:04 -0800774 errln(fail + "-" + int64minstr + " didn't fit");
775 }
776 int64_t int64Value = dl.getInt64();
777 if (int64Value != int64min) {
778 errln(fail + int64minstr);
779 }
780 dl.set(int64Value);
781 int64Value = dl.getInt64();
782 if (int64Value != int64min) {
783 errln(fail + int64minstr);
784 }
785 }
786 // test negative of min int 64 value (1 more than max int64 value)
Frank Tang1f164ee2022-11-08 12:31:27 -0800787 dl.fIsPositive = true; // won't fit
Frank Tang3e05d9d2021-11-08 14:04:04 -0800788 {
Frank Tang1f164ee2022-11-08 12:31:27 -0800789 if (dl.fitsIntoInt64(false)) {
Frank Tang3e05d9d2021-11-08 14:04:04 -0800790 errln(fail + "-(" + int64minstr + ") didn't fit");
791 }
792 }*/
793}
794
795// -------------------------------------
796
797// Test the handling of quotes
798void
799NumberFormatTest::TestQuotes(void)
800{
801 UErrorCode status = U_ZERO_ERROR;
802 UnicodeString *pat;
803 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), status);
804 if (U_FAILURE(status)) {
805 errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
806 delete sym;
807 return;
808 }
809 pat = new UnicodeString("a'fo''o'b#");
810 DecimalFormat *fmt = new DecimalFormat(*pat, *sym, status);
811 UnicodeString s;
812 ((NumberFormat*)fmt)->format((int32_t)123, s);
813 logln((UnicodeString)"Pattern \"" + *pat + "\"");
814 logln((UnicodeString)" Format 123 -> " + escape(s));
815 if (!(s=="afo'ob123"))
816 errln((UnicodeString)"FAIL: Expected afo'ob123");
817
818 s.truncate(0);
819 delete fmt;
820 delete pat;
821
822 pat = new UnicodeString("a''b#");
823 fmt = new DecimalFormat(*pat, *sym, status);
824 ((NumberFormat*)fmt)->format((int32_t)123, s);
825 logln((UnicodeString)"Pattern \"" + *pat + "\"");
826 logln((UnicodeString)" Format 123 -> " + escape(s));
827 if (!(s=="a'b123"))
828 errln((UnicodeString)"FAIL: Expected a'b123");
829 delete fmt;
830 delete pat;
831 delete sym;
832}
833
834/**
835 * Test the handling of the currency symbol in patterns.
836 */
837void
838NumberFormatTest::TestCurrencySign(void)
839{
840 UErrorCode status = U_ZERO_ERROR;
841 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale::getUS(), status);
842 UnicodeString pat;
843 UChar currency = 0x00A4;
844 if (U_FAILURE(status)) {
845 errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
846 delete sym;
847 return;
848 }
849 // "\xA4#,##0.00;-\xA4#,##0.00"
850 pat.append(currency).append("#,##0.00;-").
851 append(currency).append("#,##0.00");
852 DecimalFormat *fmt = new DecimalFormat(pat, *sym, status);
853 UnicodeString s; ((NumberFormat*)fmt)->format(1234.56, s);
854 pat.truncate(0);
855 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
856 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
857 if (s != "$1,234.56") dataerrln((UnicodeString)"FAIL: Expected $1,234.56");
858 s.truncate(0);
859 ((NumberFormat*)fmt)->format(- 1234.56, s);
860 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
861 if (s != "-$1,234.56") dataerrln((UnicodeString)"FAIL: Expected -$1,234.56");
862 delete fmt;
863 pat.truncate(0);
864 // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
865 pat.append(currency).append(currency).
866 append(" #,##0.00;").
867 append(currency).append(currency).
868 append(" -#,##0.00");
869 fmt = new DecimalFormat(pat, *sym, status);
870 s.truncate(0);
871 ((NumberFormat*)fmt)->format(1234.56, s);
872 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
873 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
874 if (s != "USD 1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD 1,234.56");
875 s.truncate(0);
876 ((NumberFormat*)fmt)->format(-1234.56, s);
877 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
878 if (s != "USD -1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD -1,234.56");
879 delete fmt;
880 delete sym;
881 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + u_errorName(status));
882}
883
884// -------------------------------------
885
886static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
887
888UnicodeString&
889NumberFormatTest::escape(UnicodeString& s)
890{
891 UnicodeString buf;
892 for (int32_t i=0; i<s.length(); ++i)
893 {
894 UChar c = s[(int32_t)i];
895 if (c <= (UChar)0x7F) buf += c;
896 else {
897 buf += (UChar)0x5c; buf += (UChar)0x55;
898 buf += toHexString((c & 0xF000) >> 12);
899 buf += toHexString((c & 0x0F00) >> 8);
900 buf += toHexString((c & 0x00F0) >> 4);
901 buf += toHexString(c & 0x000F);
902 }
903 }
904 return (s = buf);
905}
906
907
908// -------------------------------------
909static const char* testCases[][2]= {
910 /* locale ID */ /* expected */
911 {"ca_ES@currency=ESP", "\\u20A7\\u00A01.150" },
912 {"de_LU@currency=LUF", "1,150\\u00A0F" },
913 {"el_GR@currency=GRD", "1.150,50\\u00A0\\u0394\\u03C1\\u03C7" },
914 {"en_BE@currency=BEF", "1.150,50\\u00A0BEF" },
915 {"es_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
916 {"eu_ES@currency=ESP", "\\u20A7\\u00A01.150" },
917 {"gl_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
918 {"it_IT@currency=ITL", "ITL\\u00A01.150" },
919 {"pt_PT@currency=PTE", "1,150$50\\u00A0\\u200B"}, // per cldrbug 7670
920 {"en_US@currency=JPY", "\\u00A51,150"},
921 {"en_US@currency=jpy", "\\u00A51,150"},
922 {"en-US-u-cu-jpy", "\\u00A51,150"}
923};
924/**
925 * Test localized currency patterns.
926 */
927void
928NumberFormatTest::TestCurrency(void)
929{
930 UErrorCode status = U_ZERO_ERROR;
931 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
932 if (U_FAILURE(status)) {
933 dataerrln("Error calling NumberFormat::createCurrencyInstance()");
934 return;
935 }
936
937 UnicodeString s; currencyFmt->format(1.50, s);
938 logln((UnicodeString)"Un pauvre ici a..........." + s);
939 if (!(s==CharsToUnicodeString("1,50\\u00A0$")))
940 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$ but got " + s);
941 delete currencyFmt;
942 s.truncate(0);
943 char loc[256]={0};
944 int len = uloc_canonicalize("de_DE@currency=DEM", loc, 256, &status);
945 (void)len; // Suppress unused variable warning.
946 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
947 currencyFmt->format(1.50, s);
948 logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
949 if (!(s==CharsToUnicodeString("1,50\\u00A0DM")))
950 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM but got " + s);
951 delete currencyFmt;
952 s.truncate(0);
953 len = uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status);
954 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
955 currencyFmt->format(1.50, s);
956 logln((UnicodeString)"Un pauvre en France a....." + s);
957 if (!(s==CharsToUnicodeString("1,50\\u00A0F")))
958 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>F");
959 delete currencyFmt;
960 if (U_FAILURE(status))
961 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
962
963 for(int i=0; i < UPRV_LENGTHOF(testCases); i++){
964 status = U_ZERO_ERROR;
965 const char *localeID = testCases[i][0];
966 UnicodeString expected(testCases[i][1], -1, US_INV);
967 expected = expected.unescape();
968 s.truncate(0);
969 char loc[256]={0};
970 uloc_canonicalize(localeID, loc, 256, &status);
971 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
972 if(U_FAILURE(status)){
973 errln("Could not create currency formatter for locale %s",localeID);
974 continue;
975 }
976 currencyFmt->format(1150.50, s);
977 if(s!=expected){
978 errln(UnicodeString("FAIL: Expected: ")+expected
979 + UnicodeString(" Got: ") + s
980 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
981 }
982 if (U_FAILURE(status)){
983 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
984 }
985 delete currencyFmt;
986 }
987}
988
989// -------------------------------------
990
991/**
992 * Test the Currency object handling, new as of ICU 2.2.
993 */
994void NumberFormatTest::TestCurrencyObject() {
995 UErrorCode ec = U_ZERO_ERROR;
996 NumberFormat* fmt =
997 NumberFormat::createCurrencyInstance(Locale::getUS(), ec);
998
999 if (U_FAILURE(ec)) {
1000 dataerrln("FAIL: getCurrencyInstance(US) - %s", u_errorName(ec));
1001 delete fmt;
1002 return;
1003 }
1004
1005 Locale null("", "", "");
1006
1007 expectCurrency(*fmt, null, 1234.56, "$1,234.56");
1008
1009 expectCurrency(*fmt, Locale::getFrance(),
1010 1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro
1011
1012 expectCurrency(*fmt, Locale::getJapan(),
1013 1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
1014
1015 expectCurrency(*fmt, Locale("fr", "CH", ""),
1016 1234.56, "CHF 1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
1017
1018 expectCurrency(*fmt, Locale::getUS(),
1019 1234.56, "$1,234.56");
1020
1021 delete fmt;
1022 fmt = NumberFormat::createCurrencyInstance(Locale::getFrance(), ec);
1023
1024 if (U_FAILURE(ec)) {
1025 errln("FAIL: getCurrencyInstance(FRANCE)");
1026 delete fmt;
1027 return;
1028 }
1029
1030 expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC"));
1031
1032 expectCurrency(*fmt, Locale::getJapan(),
1033 1234.56, CharsToUnicodeString("1\\u202F235 JPY")); // Yen
1034
1035 expectCurrency(*fmt, Locale("fr", "CH", ""),
1036 1234.56, CharsToUnicodeString("1\\u202F234,56 CHF")); // no more 0.05 rounding here, see cldrbug 5548
1037
1038 expectCurrency(*fmt, Locale::getUS(),
1039 1234.56, CharsToUnicodeString("1\\u202F234,56 $US"));
1040
1041 expectCurrency(*fmt, Locale::getFrance(),
1042 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC")); // Euro
1043
1044 delete fmt;
1045}
1046
1047// -------------------------------------
1048
1049/**
1050 * Do rudimentary testing of parsing.
1051 */
1052void
1053NumberFormatTest::TestParse(void)
1054{
1055 UErrorCode status = U_ZERO_ERROR;
1056 UnicodeString arg("0");
1057 DecimalFormat* format = new DecimalFormat("00", status);
1058 //try {
1059 Formattable n; format->parse(arg, n, status);
1060 logln((UnicodeString)"parse(" + arg + ") = " + n.getLong());
1061 if (n.getType() != Formattable::kLong ||
1062 n.getLong() != 0) errln((UnicodeString)"FAIL: Expected 0");
1063 delete format;
1064 if (U_FAILURE(status)) errcheckln(status, (UnicodeString)"FAIL: Status " + u_errorName(status));
1065 //}
1066 //catch(Exception e) {
1067 // errln((UnicodeString)"Exception caught: " + e);
1068 //}
1069}
1070
1071// -------------------------------------
1072
1073static const char *lenientAffixTestCases[] = {
1074 "(1)",
1075 "( 1)",
1076 "(1 )",
1077 "( 1 )"
1078};
1079
1080static const char *lenientMinusTestCases[] = {
1081 "-5",
1082 "\\u22125",
1083 "\\u27965"
1084};
1085
1086static const char *lenientCurrencyTestCases[] = {
1087 "$1,000",
1088 "$ 1,000",
1089 "$1000",
1090 "$ 1000",
1091 "$1 000.00",
1092 "$ 1 000.00",
1093 "$ 1\\u00A0000.00",
1094 "1000.00"
1095};
1096
1097// changed from () to - per cldrbug 5674
1098static const char *lenientNegativeCurrencyTestCases[] = {
1099 "-$1,000",
1100 "-$ 1,000",
1101 "-$1000",
1102 "-$ 1000",
1103 "-$1 000.00",
1104 "-$ 1 000.00",
1105 "- $ 1,000.00 ",
1106 "-$ 1\\u00A0000.00",
1107 "-1000.00"
1108};
1109
1110static const char *lenientPercentTestCases[] = {
1111 "25%",
1112 " 25%",
1113 " 25 %",
1114 "25 %",
1115 "25\\u00A0%",
1116 "25"
1117};
1118
1119static const char *lenientNegativePercentTestCases[] = {
1120 "-25%",
1121 " -25%",
1122 " - 25%",
1123 "- 25 %",
1124 " - 25 %",
1125 "-25 %",
1126 "-25\\u00A0%",
1127 "-25",
1128 "- 25"
1129};
1130
1131static const char *strictFailureTestCases[] = {
1132 " 1000",
1133 "10,00",
1134 "1,000,.0"
1135};
1136
1137/**
1138 * Test lenient parsing.
1139 */
1140void
1141NumberFormatTest::TestLenientParse(void)
1142{
1143 UErrorCode status = U_ZERO_ERROR;
1144 DecimalFormat *format = new DecimalFormat("(#,##0)", status);
1145 Formattable n;
1146
1147 if (format == NULL || U_FAILURE(status)) {
1148 dataerrln("Unable to create DecimalFormat (#,##0) - %s", u_errorName(status));
1149 } else {
Frank Tang1f164ee2022-11-08 12:31:27 -08001150 format->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08001151 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientAffixTestCases); t += 1) {
1152 UnicodeString testCase = ctou(lenientAffixTestCases[t]);
1153
1154 format->parse(testCase, n, status);
1155 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1156
1157 if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
1158 n.getLong() != 1) {
1159 dataerrln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t]
1160 + (UnicodeString) "\"; error code = " + u_errorName(status));
1161 status = U_ZERO_ERROR;
1162 }
1163 }
1164 delete format;
1165 }
1166
1167 Locale en_US("en_US");
1168 Locale sv_SE("sv_SE");
1169
1170 NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, UNUM_DECIMAL, status);
1171
1172 if (mFormat == NULL || U_FAILURE(status)) {
1173 dataerrln("Unable to create NumberFormat (sv_SE, UNUM_DECIMAL) - %s", u_errorName(status));
1174 } else {
Frank Tang1f164ee2022-11-08 12:31:27 -08001175 mFormat->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08001176 for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1177 UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1178
1179 mFormat->parse(testCase, n, status);
1180 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1181
1182 if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1183 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1184 + (UnicodeString) "\"; error code = " + u_errorName(status));
1185 status = U_ZERO_ERROR;
1186 }
1187 }
1188 delete mFormat;
1189 }
1190
1191 mFormat = NumberFormat::createInstance(en_US, UNUM_DECIMAL, status);
1192
1193 if (mFormat == NULL || U_FAILURE(status)) {
1194 dataerrln("Unable to create NumberFormat (en_US, UNUM_DECIMAL) - %s", u_errorName(status));
1195 } else {
Frank Tang1f164ee2022-11-08 12:31:27 -08001196 mFormat->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08001197 for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1198 UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1199
1200 mFormat->parse(testCase, n, status);
1201 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1202
1203 if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1204 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1205 + (UnicodeString) "\"; error code = " + u_errorName(status));
1206 status = U_ZERO_ERROR;
1207 }
1208 }
1209 delete mFormat;
1210 }
1211
1212 NumberFormat *cFormat = NumberFormat::createInstance(en_US, UNUM_CURRENCY, status);
1213
1214 if (cFormat == NULL || U_FAILURE(status)) {
1215 dataerrln("Unable to create NumberFormat (en_US, UNUM_CURRENCY) - %s", u_errorName(status));
1216 } else {
Frank Tang1f164ee2022-11-08 12:31:27 -08001217 cFormat->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08001218 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientCurrencyTestCases); t += 1) {
1219 UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
1220
1221 cFormat->parse(testCase, n, status);
1222 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1223
1224 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1225 n.getLong() != 1000) {
1226 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t]
1227 + (UnicodeString) "\"; error code = " + u_errorName(status));
1228 status = U_ZERO_ERROR;
1229 }
1230 }
1231
1232 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativeCurrencyTestCases); t += 1) {
1233 UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
1234
1235 cFormat->parse(testCase, n, status);
1236 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1237
1238 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1239 n.getLong() != -1000) {
1240 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t]
1241 + (UnicodeString) "\"; error code = " + u_errorName(status));
1242 status = U_ZERO_ERROR;
1243 }
1244 }
1245
1246 delete cFormat;
1247 }
1248
1249 NumberFormat *pFormat = NumberFormat::createPercentInstance(en_US, status);
1250
1251 if (pFormat == NULL || U_FAILURE(status)) {
1252 dataerrln("Unable to create NumberFormat::createPercentInstance (en_US) - %s", u_errorName(status));
1253 } else {
Frank Tang1f164ee2022-11-08 12:31:27 -08001254 pFormat->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08001255 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientPercentTestCases); t += 1) {
1256 UnicodeString testCase = ctou(lenientPercentTestCases[t]);
1257
1258 pFormat->parse(testCase, n, status);
1259 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1260
1261 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1262 n.getDouble() != 0.25) {
1263 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t]
1264 + (UnicodeString) "\"; error code = " + u_errorName(status)
1265 + "; got: " + n.getDouble(status));
1266 status = U_ZERO_ERROR;
1267 }
1268 }
1269
1270 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativePercentTestCases); t += 1) {
1271 UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
1272
1273 pFormat->parse(testCase, n, status);
1274 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1275
1276 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1277 n.getDouble() != -0.25) {
1278 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t]
1279 + (UnicodeString) "\"; error code = " + u_errorName(status)
1280 + "; got: " + n.getDouble(status));
1281 status = U_ZERO_ERROR;
1282 }
1283 }
1284
1285 delete pFormat;
1286 }
1287
1288 // Test cases that should fail with a strict parse and pass with a
1289 // lenient parse.
1290 NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);
1291
1292 if (nFormat == NULL || U_FAILURE(status)) {
1293 dataerrln("Unable to create NumberFormat (en_US) - %s", u_errorName(status));
1294 } else {
1295 // first, make sure that they fail with a strict parse
1296 for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1297 UnicodeString testCase = ctou(strictFailureTestCases[t]);
1298
1299 nFormat->parse(testCase, n, status);
1300 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1301
1302 if (! U_FAILURE(status)) {
1303 errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t]
1304 + (UnicodeString) "\"; error code = " + u_errorName(status));
1305 }
1306
1307 status = U_ZERO_ERROR;
1308 }
1309
1310 // then, make sure that they pass with a lenient parse
Frank Tang1f164ee2022-11-08 12:31:27 -08001311 nFormat->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08001312 for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1313 UnicodeString testCase = ctou(strictFailureTestCases[t]);
1314
1315 nFormat->parse(testCase, n, status);
1316 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1317
1318 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1319 n.getLong() != 1000) {
1320 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t]
1321 + (UnicodeString) "\"; error code = " + u_errorName(status));
1322 status = U_ZERO_ERROR;
1323 }
1324 }
1325
1326 delete nFormat;
1327 }
1328}
1329
1330// -------------------------------------
1331
1332/**
1333 * Test proper rounding by the format method.
1334 */
1335void
1336NumberFormatTest::TestRounding487(void)
1337{
1338 UErrorCode status = U_ZERO_ERROR;
1339 NumberFormat *nf = NumberFormat::createInstance(status);
1340 if (U_FAILURE(status)) {
1341 dataerrln("Error calling NumberFormat::createInstance()");
1342 return;
1343 }
1344
1345 roundingTest(*nf, 0.00159999, 4, "0.0016");
1346 roundingTest(*nf, 0.00995, 4, "0.01");
1347
1348 roundingTest(*nf, 12.3995, 3, "12.4");
1349
1350 roundingTest(*nf, 12.4999, 0, "12");
1351 roundingTest(*nf, - 19.5, 0, "-20");
1352 delete nf;
1353 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
1354}
1355
1356/**
1357 * Test the functioning of the secondary grouping value.
1358 */
1359void NumberFormatTest::TestSecondaryGrouping(void) {
1360 UErrorCode status = U_ZERO_ERROR;
1361 DecimalFormatSymbols US(Locale::getUS(), status);
1362 CHECK(status, "DecimalFormatSymbols ct");
1363
1364 DecimalFormat f("#,##,###", US, status);
1365 CHECK(status, "DecimalFormat ct");
1366
1367 expect2(f, (int32_t)123456789L, "12,34,56,789");
1368 expectPat(f, "#,##,##0");
1369 f.applyPattern("#,###", status);
1370 CHECK(status, "applyPattern");
1371
1372 f.setSecondaryGroupingSize(4);
1373 expect2(f, (int32_t)123456789L, "12,3456,789");
1374 expectPat(f, "#,####,##0");
1375 NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
1376 CHECK_DATA(status, "createInstance(hi_IN)");
1377
1378 UnicodeString out;
1379 int32_t l = (int32_t)1876543210L;
1380 g->format(l, out);
1381 delete g;
1382 // expect "1,87,65,43,210", but with Hindi digits
1383 // 01234567890123
Frank Tang1f164ee2022-11-08 12:31:27 -08001384 UBool ok = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -08001385 if (out.length() != 14) {
Frank Tang1f164ee2022-11-08 12:31:27 -08001386 ok = false;
Frank Tang3e05d9d2021-11-08 14:04:04 -08001387 } else {
1388 for (int32_t i=0; i<out.length(); ++i) {
Frank Tang1f164ee2022-11-08 12:31:27 -08001389 UBool expectGroup = false;
Frank Tang3e05d9d2021-11-08 14:04:04 -08001390 switch (i) {
1391 case 1:
1392 case 4:
1393 case 7:
1394 case 10:
Frank Tang1f164ee2022-11-08 12:31:27 -08001395 expectGroup = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -08001396 break;
1397 }
1398 // Later -- fix this to get the actual grouping
1399 // character from the resource bundle.
1400 UBool isGroup = (out.charAt(i) == 0x002C);
1401 if (isGroup != expectGroup) {
Frank Tang1f164ee2022-11-08 12:31:27 -08001402 ok = false;
Frank Tang3e05d9d2021-11-08 14:04:04 -08001403 break;
1404 }
1405 }
1406 }
1407 if (!ok) {
1408 errln((UnicodeString)"FAIL Expected " + l +
1409 " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
1410 escape(out) + "\"");
1411 } else {
1412 logln((UnicodeString)"Ok " + l +
1413 " x hi_IN -> \"" +
1414 escape(out) + "\"");
1415 }
1416}
1417
1418void NumberFormatTest::TestWhiteSpaceParsing(void) {
1419 UErrorCode ec = U_ZERO_ERROR;
1420 DecimalFormatSymbols US(Locale::getUS(), ec);
1421 DecimalFormat fmt("a b#0c ", US, ec);
1422 if (U_FAILURE(ec)) {
1423 errcheckln(ec, "FAIL: Constructor - %s", u_errorName(ec));
1424 return;
1425 }
1426 // From ICU 62, flexible whitespace needs lenient mode
Frank Tang1f164ee2022-11-08 12:31:27 -08001427 fmt.setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08001428 int32_t n = 1234;
1429 expect(fmt, "a b1234c ", n);
1430 expect(fmt, "a b1234c ", n);
1431}
1432
1433/**
1434 * Test currencies whose display name is a ChoiceFormat.
1435 */
1436void NumberFormatTest::TestComplexCurrency() {
1437
1438// UErrorCode ec = U_ZERO_ERROR;
1439// Locale loc("kn", "IN", "");
1440// NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
1441// if (U_SUCCESS(ec)) {
1442// expect2(*fmt, 1.0, CharsToUnicodeString("Re.\\u00A01.00"));
1443// Use .00392625 because that's 2^-8. Any value less than 0.005 is fine.
1444// expect(*fmt, 1.00390625, CharsToUnicodeString("Re.\\u00A01.00")); // tricky
1445// expect2(*fmt, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
1446// expect2(*fmt, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
1447// expect2(*fmt, -1.0, CharsToUnicodeString("-Re.\\u00A01.00"));
1448// expect2(*fmt, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
1449// } else {
1450// errln("FAIL: getCurrencyInstance(kn_IN)");
1451// }
1452// delete fmt;
1453
1454}
1455
1456// -------------------------------------
1457
1458void
1459NumberFormatTest::roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)
1460{
1461 nf.setMaximumFractionDigits(maxFractionDigits);
1462 UnicodeString out; nf.format(x, out);
1463 logln((UnicodeString)"" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
1464 if (!(out==expected)) errln((UnicodeString)"FAIL: Expected " + expected);
1465}
1466
1467/**
1468 * Upgrade to alphaWorks
1469 */
1470void NumberFormatTest::TestExponent(void) {
1471 UErrorCode status = U_ZERO_ERROR;
1472 DecimalFormatSymbols US(Locale::getUS(), status);
1473 CHECK(status, "DecimalFormatSymbols constructor");
1474 DecimalFormat fmt1(UnicodeString("0.###E0"), US, status);
1475 CHECK(status, "DecimalFormat(0.###E0)");
1476 DecimalFormat fmt2(UnicodeString("0.###E+0"), US, status);
1477 CHECK(status, "DecimalFormat(0.###E+0)");
1478 int32_t n = 1234;
1479 expect2(fmt1, n, "1.234E3");
1480 expect2(fmt2, n, "1.234E+3");
1481 expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
1482}
1483
1484/**
1485 * Upgrade to alphaWorks
1486 */
1487void NumberFormatTest::TestScientific(void) {
1488 UErrorCode status = U_ZERO_ERROR;
1489 DecimalFormatSymbols US(Locale::getUS(), status);
1490 CHECK(status, "DecimalFormatSymbols constructor");
1491
1492 // Test pattern round-trip
1493 const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
1494 "0.###E0;[0.###E0]" };
1495 int32_t PAT_length = UPRV_LENGTHOF(PAT);
1496 int32_t DIGITS[] = {
1497 // min int, max int, min frac, max frac
1498 1, 1, 0, 0, // "#E0"
1499 1, 1, 0, 4, // "0.####E0"
1500 2, 2, 3, 3, // "00.000E00"
1501 1, 3, 0, 4, // "##0.####E000"
1502 1, 1, 0, 3, // "0.###E0;[0.###E0]"
1503 };
1504 for (int32_t i=0; i<PAT_length; ++i) {
1505 UnicodeString pat(PAT[i]);
1506 DecimalFormat df(pat, US, status);
1507 CHECK(status, "DecimalFormat constructor");
1508 UnicodeString pat2;
1509 df.toPattern(pat2);
1510 if (pat == pat2) {
1511 logln(UnicodeString("Ok Pattern rt \"") +
1512 pat + "\" -> \"" +
1513 pat2 + "\"");
1514 } else {
1515 errln(UnicodeString("FAIL Pattern rt \"") +
1516 pat + "\" -> \"" +
1517 pat2 + "\"");
1518 }
1519 // Make sure digit counts match what we expect
1520 if (df.getMinimumIntegerDigits() != DIGITS[4*i] ||
1521 df.getMaximumIntegerDigits() != DIGITS[4*i+1] ||
1522 df.getMinimumFractionDigits() != DIGITS[4*i+2] ||
1523 df.getMaximumFractionDigits() != DIGITS[4*i+3]) {
1524 errln(UnicodeString("FAIL \"" + pat +
1525 "\" min/max int; min/max frac = ") +
1526 df.getMinimumIntegerDigits() + "/" +
1527 df.getMaximumIntegerDigits() + ";" +
1528 df.getMinimumFractionDigits() + "/" +
1529 df.getMaximumFractionDigits() + ", expect " +
1530 DIGITS[4*i] + "/" +
1531 DIGITS[4*i+1] + ";" +
1532 DIGITS[4*i+2] + "/" +
1533 DIGITS[4*i+3]);
1534 }
1535 }
1536
1537
1538 // Test the constructor for default locale. We have to
1539 // manually set the default locale, as there is no
1540 // guarantee that the default locale has the same
1541 // scientific format.
1542 Locale def = Locale::getDefault();
1543 Locale::setDefault(Locale::getUS(), status);
1544 expect2(NumberFormat::createScientificInstance(status),
1545 12345.678901,
1546 "1.2345678901E4", status);
1547 Locale::setDefault(def, status);
1548
1549 expect2(new DecimalFormat("#E0", US, status),
1550 12345.0,
1551 "1.2345E4", status);
1552 expect(new DecimalFormat("0E0", US, status),
1553 12345.0,
1554 "1E4", status);
1555 expect2(NumberFormat::createScientificInstance(Locale::getUS(), status),
1556 12345.678901,
1557 "1.2345678901E4", status);
1558 expect(new DecimalFormat("##0.###E0", US, status),
1559 12345.0,
1560 "12.34E3", status);
1561 expect(new DecimalFormat("##0.###E0", US, status),
1562 12345.00001,
1563 "12.35E3", status);
1564 expect2(new DecimalFormat("##0.####E0", US, status),
1565 (int32_t) 12345,
1566 "12.345E3", status);
1567 expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status),
1568 12345.678901,
1569 "1,2345678901E4", status);
1570 expect(new DecimalFormat("##0.####E0", US, status),
1571 789.12345e-9,
1572 "789.12E-9", status);
1573 expect2(new DecimalFormat("##0.####E0", US, status),
1574 780.e-9,
1575 "780E-9", status);
1576 expect(new DecimalFormat(".###E0", US, status),
1577 45678.0,
1578 ".457E5", status);
1579 expect2(new DecimalFormat(".###E0", US, status),
1580 (int32_t) 0,
1581 ".0E0", status);
1582 /*
1583 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
1584 new DecimalFormat("##E0", US),
1585 new DecimalFormat("####E0", US),
1586 new DecimalFormat("0E0", US),
1587 new DecimalFormat("00E0", US),
1588 new DecimalFormat("000E0", US),
1589 },
1590 new Long(45678000),
1591 new String[] { "4.5678E7",
1592 "45.678E6",
1593 "4567.8E4",
1594 "5E7",
1595 "46E6",
1596 "457E5",
1597 }
1598 );
1599 !
1600 ! Unroll this test into individual tests below...
1601 !
1602 */
1603 expect2(new DecimalFormat("#E0", US, status),
1604 (int32_t) 45678000, "4.5678E7", status);
1605 expect2(new DecimalFormat("##E0", US, status),
1606 (int32_t) 45678000, "45.678E6", status);
1607 expect2(new DecimalFormat("####E0", US, status),
1608 (int32_t) 45678000, "4567.8E4", status);
1609 expect(new DecimalFormat("0E0", US, status),
1610 (int32_t) 45678000, "5E7", status);
1611 expect(new DecimalFormat("00E0", US, status),
1612 (int32_t) 45678000, "46E6", status);
1613 expect(new DecimalFormat("000E0", US, status),
1614 (int32_t) 45678000, "457E5", status);
1615 /*
1616 expect(new DecimalFormat("###E0", US, status),
1617 new Object[] { new Double(0.0000123), "12.3E-6",
1618 new Double(0.000123), "123E-6",
1619 new Double(0.00123), "1.23E-3",
1620 new Double(0.0123), "12.3E-3",
1621 new Double(0.123), "123E-3",
1622 new Double(1.23), "1.23E0",
1623 new Double(12.3), "12.3E0",
1624 new Double(123), "123E0",
1625 new Double(1230), "1.23E3",
1626 });
1627 !
1628 ! Unroll this test into individual tests below...
1629 !
1630 */
1631 expect2(new DecimalFormat("###E0", US, status),
1632 0.0000123, "12.3E-6", status);
1633 expect2(new DecimalFormat("###E0", US, status),
1634 0.000123, "123E-6", status);
1635 expect2(new DecimalFormat("###E0", US, status),
1636 0.00123, "1.23E-3", status);
1637 expect2(new DecimalFormat("###E0", US, status),
1638 0.0123, "12.3E-3", status);
1639 expect2(new DecimalFormat("###E0", US, status),
1640 0.123, "123E-3", status);
1641 expect2(new DecimalFormat("###E0", US, status),
1642 1.23, "1.23E0", status);
1643 expect2(new DecimalFormat("###E0", US, status),
1644 12.3, "12.3E0", status);
1645 expect2(new DecimalFormat("###E0", US, status),
1646 123.0, "123E0", status);
1647 expect2(new DecimalFormat("###E0", US, status),
1648 1230.0, "1.23E3", status);
1649 /*
1650 expect(new DecimalFormat("0.#E+00", US, status),
1651 new Object[] { new Double(0.00012), "1.2E-04",
1652 new Long(12000), "1.2E+04",
1653 });
1654 !
1655 ! Unroll this test into individual tests below...
1656 !
1657 */
1658 expect2(new DecimalFormat("0.#E+00", US, status),
1659 0.00012, "1.2E-04", status);
1660 expect2(new DecimalFormat("0.#E+00", US, status),
1661 (int32_t) 12000, "1.2E+04", status);
1662}
1663
1664/**
1665 * Upgrade to alphaWorks
1666 */
1667void NumberFormatTest::TestPad(void) {
1668 UErrorCode status = U_ZERO_ERROR;
1669 DecimalFormatSymbols US(Locale::getUS(), status);
1670 CHECK(status, "DecimalFormatSymbols constructor");
1671
1672 expect2(new DecimalFormat("*^##.##", US, status),
1673 int32_t(0), "^^^^0", status);
1674 expect2(new DecimalFormat("*^##.##", US, status),
1675 -1.3, "^-1.3", status);
1676 expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1677 int32_t(0), "0.0E0______ g-m/s^2", status);
1678 expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1679 1.0/3, "333.333E-3_ g-m/s^2", status);
1680 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1681 int32_t(0), "0.0______ g-m/s^2", status);
1682 expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1683 1.0/3, "0.33333__ g-m/s^2", status);
1684
1685 // Test padding before a sign
1686 const char *formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1687 expect2(new DecimalFormat(formatStr, US, status),
1688 int32_t(-10), "xxxxxxxxxx(10.0)", status);
1689 expect2(new DecimalFormat(formatStr, US, status),
1690 int32_t(-1000),"xxxxxxx(1,000.0)", status);
1691 expect2(new DecimalFormat(formatStr, US, status),
1692 int32_t(-1000000),"xxx(1,000,000.0)", status);
1693 expect2(new DecimalFormat(formatStr, US, status),
1694 -100.37, "xxxxxxxx(100.37)", status);
1695 expect2(new DecimalFormat(formatStr, US, status),
1696 -10456.37, "xxxxx(10,456.37)", status);
1697 expect2(new DecimalFormat(formatStr, US, status),
1698 -1120456.37, "xx(1,120,456.37)", status);
1699 expect2(new DecimalFormat(formatStr, US, status),
1700 -112045600.37, "(112,045,600.37)", status);
1701 expect2(new DecimalFormat(formatStr, US, status),
1702 -1252045600.37,"(1,252,045,600.37)", status);
1703
1704 expect2(new DecimalFormat(formatStr, US, status),
1705 int32_t(10), "xxxxxxxxxxxx10.0", status);
1706 expect2(new DecimalFormat(formatStr, US, status),
1707 int32_t(1000),"xxxxxxxxx1,000.0", status);
1708 expect2(new DecimalFormat(formatStr, US, status),
1709 int32_t(1000000),"xxxxx1,000,000.0", status);
1710 expect2(new DecimalFormat(formatStr, US, status),
1711 100.37, "xxxxxxxxxx100.37", status);
1712 expect2(new DecimalFormat(formatStr, US, status),
1713 10456.37, "xxxxxxx10,456.37", status);
1714 expect2(new DecimalFormat(formatStr, US, status),
1715 1120456.37, "xxxx1,120,456.37", status);
1716 expect2(new DecimalFormat(formatStr, US, status),
1717 112045600.37, "xx112,045,600.37", status);
1718 expect2(new DecimalFormat(formatStr, US, status),
1719 10252045600.37,"10,252,045,600.37", status);
1720
1721
1722 // Test padding between a sign and a number
1723 const char *formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1724 expect2(new DecimalFormat(formatStr2, US, status),
1725 int32_t(-10), "(10.0xxxxxxxxxx)", status);
1726 expect2(new DecimalFormat(formatStr2, US, status),
1727 int32_t(-1000),"(1,000.0xxxxxxx)", status);
1728 expect2(new DecimalFormat(formatStr2, US, status),
1729 int32_t(-1000000),"(1,000,000.0xxx)", status);
1730 expect2(new DecimalFormat(formatStr2, US, status),
1731 -100.37, "(100.37xxxxxxxx)", status);
1732 expect2(new DecimalFormat(formatStr2, US, status),
1733 -10456.37, "(10,456.37xxxxx)", status);
1734 expect2(new DecimalFormat(formatStr2, US, status),
1735 -1120456.37, "(1,120,456.37xx)", status);
1736 expect2(new DecimalFormat(formatStr2, US, status),
1737 -112045600.37, "(112,045,600.37)", status);
1738 expect2(new DecimalFormat(formatStr2, US, status),
1739 -1252045600.37,"(1,252,045,600.37)", status);
1740
1741 expect2(new DecimalFormat(formatStr2, US, status),
1742 int32_t(10), "10.0xxxxxxxxxxxx", status);
1743 expect2(new DecimalFormat(formatStr2, US, status),
1744 int32_t(1000),"1,000.0xxxxxxxxx", status);
1745 expect2(new DecimalFormat(formatStr2, US, status),
1746 int32_t(1000000),"1,000,000.0xxxxx", status);
1747 expect2(new DecimalFormat(formatStr2, US, status),
1748 100.37, "100.37xxxxxxxxxx", status);
1749 expect2(new DecimalFormat(formatStr2, US, status),
1750 10456.37, "10,456.37xxxxxxx", status);
1751 expect2(new DecimalFormat(formatStr2, US, status),
1752 1120456.37, "1,120,456.37xxxx", status);
1753 expect2(new DecimalFormat(formatStr2, US, status),
1754 112045600.37, "112,045,600.37xx", status);
1755 expect2(new DecimalFormat(formatStr2, US, status),
1756 10252045600.37,"10,252,045,600.37", status);
1757
1758 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1759 DecimalFormat fmt("#", US, status);
1760 CHECK(status, "DecimalFormat constructor");
1761 UnicodeString padString("P");
1762 fmt.setPadCharacter(padString);
1763 expectPad(fmt, "*P##.##", DecimalFormat::kPadBeforePrefix, 5, padString);
1764 fmt.setPadCharacter((UnicodeString)"^");
1765 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, (UnicodeString)"^");
1766 //commented until implementation is complete
1767 /* fmt.setPadCharacter((UnicodeString)"^^^");
1768 expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1769 padString.remove();
1770 padString.append((UChar)0x0061);
1771 padString.append((UChar)0x0302);
1772 fmt.setPadCharacter(padString);
1773 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1774 UnicodeString pattern(patternChars);
1775 expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1776 */
1777
1778}
1779
1780/**
1781 * Upgrade to alphaWorks
1782 */
1783void NumberFormatTest::TestPatterns2(void) {
1784 UErrorCode status = U_ZERO_ERROR;
1785 DecimalFormatSymbols US(Locale::getUS(), status);
1786 CHECK(status, "DecimalFormatSymbols constructor");
1787
1788 DecimalFormat fmt("#", US, status);
1789 CHECK(status, "DecimalFormat constructor");
1790
1791 UChar hat = 0x005E; /*^*/
1792
1793 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, hat);
1794 expectPad(fmt, "$*^#", DecimalFormat::kPadAfterPrefix, 2, hat);
1795 expectPad(fmt, "#*^", DecimalFormat::kPadBeforeSuffix, 1, hat);
1796 expectPad(fmt, "#$*^", DecimalFormat::kPadAfterSuffix, 2, hat);
1797 expectPad(fmt, "$*^$#", ILLEGAL);
1798 expectPad(fmt, "#$*^$", ILLEGAL);
1799 expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix,
1800 12, (UChar)0x0078 /*x*/);
1801 expectPad(fmt, "''#0*x", DecimalFormat::kPadBeforeSuffix,
1802 3, (UChar)0x0078 /*x*/);
1803 expectPad(fmt, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix,
1804 10, (UChar)0x0061 /*a*/);
1805
1806 fmt.applyPattern("AA#,##0.00ZZ", status);
1807 CHECK(status, "applyPattern");
1808 fmt.setPadCharacter(hat);
1809
1810 fmt.setFormatWidth(10);
1811
1812 fmt.setPadPosition(DecimalFormat::kPadBeforePrefix);
1813 expectPat(fmt, "*^AA#,##0.00ZZ");
1814
1815 fmt.setPadPosition(DecimalFormat::kPadBeforeSuffix);
1816 expectPat(fmt, "AA#,##0.00*^ZZ");
1817
1818 fmt.setPadPosition(DecimalFormat::kPadAfterSuffix);
1819 expectPat(fmt, "AA#,##0.00ZZ*^");
1820
1821 // 12 3456789012
1822 UnicodeString exp("AA*^#,##0.00ZZ", "");
1823 fmt.setFormatWidth(12);
1824 fmt.setPadPosition(DecimalFormat::kPadAfterPrefix);
1825 expectPat(fmt, exp);
1826
1827 fmt.setFormatWidth(13);
1828 // 12 34567890123
1829 expectPat(fmt, "AA*^##,##0.00ZZ");
1830
1831 fmt.setFormatWidth(14);
1832 // 12 345678901234
1833 expectPat(fmt, "AA*^###,##0.00ZZ");
1834
1835 fmt.setFormatWidth(15);
1836 // 12 3456789012345
1837 expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1838
1839 fmt.setFormatWidth(16);
1840 // 12 34567890123456
1841 expectPat(fmt, "AA*^#####,##0.00ZZ");
1842}
1843
1844void NumberFormatTest::TestSurrogateSupport(void) {
1845 UErrorCode status = U_ZERO_ERROR;
1846 DecimalFormatSymbols custom(Locale::getUS(), status);
1847 CHECK(status, "DecimalFormatSymbols constructor");
1848
1849 custom.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, "decimal");
1850 custom.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, "plus");
1851 custom.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, " minus ");
1852 custom.setSymbol(DecimalFormatSymbols::kExponentialSymbol, "exponent");
1853
1854 UnicodeString patternStr("*\\U00010000##.##", "");
1855 patternStr = patternStr.unescape();
1856 UnicodeString expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1857 expStr = expStr.unescape();
1858 expect2(new DecimalFormat(patternStr, custom, status),
1859 int32_t(0), expStr, status);
1860
1861 status = U_ZERO_ERROR;
1862 expect2(new DecimalFormat("*^##.##", custom, status),
1863 int32_t(0), "^^^^0", status);
1864 status = U_ZERO_ERROR;
1865 expect2(new DecimalFormat("##.##", custom, status),
1866 -1.3, " minus 1decimal3", status);
1867 status = U_ZERO_ERROR;
1868 expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1869 int32_t(0), "0decimal0exponent0 g-m/s^2", status);
1870 status = U_ZERO_ERROR;
1871 expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1872 1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
1873 status = U_ZERO_ERROR;
1874 expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1875 int32_t(0), "0decimal0 g-m/s^2", status);
1876 status = U_ZERO_ERROR;
1877 expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1878 1.0/3, "0decimal33333 g-m/s^2", status);
1879
1880 UnicodeString zero((UChar32)0x10000);
1881 UnicodeString one((UChar32)0x10001);
1882 UnicodeString two((UChar32)0x10002);
1883 UnicodeString five((UChar32)0x10005);
1884 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
1885 custom.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, one);
1886 custom.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, two);
1887 custom.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, five);
1888 expStr = UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1889 expStr = expStr.unescape();
1890 status = U_ZERO_ERROR;
1891 expect2(new DecimalFormat("##0.000", custom, status),
1892 1.25, expStr, status);
1893
1894 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
1895 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
1896 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
1897 patternStr = UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
1898 patternStr = patternStr.unescape();
1899 expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1900 status = U_ZERO_ERROR;
1901 expect2(new DecimalFormat(patternStr, custom, status),
1902 int32_t(-20), expStr, status);
1903
1904 custom.setSymbol(DecimalFormatSymbols::kPercentSymbol, "percent");
1905 patternStr = "'You''ve lost ' -0.00 %' of your money today'";
1906 patternStr = patternStr.unescape();
1907 expStr = UnicodeString(" minus You've lost minus 2000decimal00 percent of your money today", "");
1908 status = U_ZERO_ERROR;
1909 expect2(new DecimalFormat(patternStr, custom, status),
1910 int32_t(-20), expStr, status);
1911}
1912
1913void NumberFormatTest::TestCurrencyPatterns(void) {
1914 int32_t i, locCount;
1915 const Locale* locs = NumberFormat::getAvailableLocales(locCount);
1916 for (i=0; i<locCount; ++i) {
1917 UErrorCode ec = U_ZERO_ERROR;
1918 NumberFormat* nf = NumberFormat::createCurrencyInstance(locs[i], ec);
1919 if (U_FAILURE(ec)) {
1920 errln("FAIL: Can't create NumberFormat(%s) - %s", locs[i].getName(), u_errorName(ec));
1921 } else {
1922 // Make sure currency formats do not have a variable number
1923 // of fraction digits
1924 int32_t min = nf->getMinimumFractionDigits();
1925 int32_t max = nf->getMaximumFractionDigits();
1926 if (min != max) {
1927 UnicodeString a, b;
1928 nf->format(1.0, a);
1929 nf->format(1.125, b);
1930 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1931 " min fraction digits != max fraction digits; "
1932 "x 1.0 => " + escape(a) +
1933 "; x 1.125 => " + escape(b));
1934 }
1935
1936 // Make sure EURO currency formats have exactly 2 fraction digits
1937 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
1938 if (df != NULL) {
1939 if (u_strcmp(EUR, df->getCurrency()) == 0) {
1940 if (min != 2 || max != 2) {
1941 UnicodeString a;
1942 nf->format(1.0, a);
1943 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1944 " is a EURO format but it does not have 2 fraction digits; "
1945 "x 1.0 => " +
1946 escape(a));
1947 }
1948 }
1949 }
1950 }
1951 delete nf;
1952 }
1953}
1954
1955void NumberFormatTest::TestRegCurrency(void) {
1956#if !UCONFIG_NO_SERVICE
1957 UErrorCode status = U_ZERO_ERROR;
1958 UChar USD[4];
1959 ucurr_forLocale("en_US", USD, 4, &status);
1960 UChar YEN[4];
1961 ucurr_forLocale("ja_JP", YEN, 4, &status);
1962 UChar TMP[4];
1963
1964 if(U_FAILURE(status)) {
1965 errcheckln(status, "Unable to get currency for locale, error %s", u_errorName(status));
1966 return;
1967 }
1968
1969 UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
1970
1971 ucurr_forLocale("en_US", TMP, 4, &status);
1972 if (u_strcmp(YEN, TMP) != 0) {
1973 errln("FAIL: didn't return YEN registered for en_US");
1974 }
1975
1976 int32_t fallbackLen = ucurr_forLocale("en_XX_BAR", TMP, 4, &status);
1977 if (fallbackLen) {
1978 errln("FAIL: tried to fallback en_XX_BAR");
1979 }
1980 status = U_ZERO_ERROR; // reset
1981
1982 if (!ucurr_unregister(enkey, &status)) {
1983 errln("FAIL: couldn't unregister enkey");
1984 }
1985
1986 ucurr_forLocale("en_US", TMP, 4, &status);
1987 if (u_strcmp(USD, TMP) != 0) {
1988 errln("FAIL: didn't return USD for en_US after unregister of en_US");
1989 }
1990 status = U_ZERO_ERROR; // reset
1991
1992 ucurr_forLocale("en_US_BLAH", TMP, 4, &status);
1993 if (u_strcmp(USD, TMP) != 0) {
1994 errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1995 }
1996 status = U_ZERO_ERROR; // reset
1997#endif
1998}
1999
2000void NumberFormatTest::TestCurrencyNames(void) {
2001 // Do a basic check of getName()
2002 // USD { "US$", "US Dollar" } // 04/04/1792-
2003 UErrorCode ec = U_ZERO_ERROR;
2004 static const UChar USD[] = {0x55, 0x53, 0x44, 0}; /*USD*/
2005 static const UChar USX[] = {0x55, 0x53, 0x58, 0}; /*USX*/
2006 static const UChar CAD[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
2007 static const UChar ITL[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
2008 UBool isChoiceFormat;
2009 int32_t len;
Frank Tang1f164ee2022-11-08 12:31:27 -08002010 const UBool possibleDataError = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -08002011 // Warning: HARD-CODED LOCALE DATA in this test. If it fails, CHECK
2012 // THE LOCALE DATA before diving into the code.
2013 assertEquals("USD.getName(SYMBOL_NAME, en)",
2014 UnicodeString("$"),
2015 UnicodeString(ucurr_getName(USD, "en",
2016 UCURR_SYMBOL_NAME,
2017 &isChoiceFormat, &len, &ec)),
2018 possibleDataError);
2019 assertEquals("USD.getName(NARROW_SYMBOL_NAME, en)",
2020 UnicodeString("$"),
2021 UnicodeString(ucurr_getName(USD, "en",
2022 UCURR_NARROW_SYMBOL_NAME,
2023 &isChoiceFormat, &len, &ec)),
2024 possibleDataError);
2025 assertEquals("USD.getName(LONG_NAME, en)",
2026 UnicodeString("US Dollar"),
2027 UnicodeString(ucurr_getName(USD, "en",
2028 UCURR_LONG_NAME,
2029 &isChoiceFormat, &len, &ec)),
2030 possibleDataError);
2031 assertEquals("CAD.getName(SYMBOL_NAME, en)",
2032 UnicodeString("CA$"),
2033 UnicodeString(ucurr_getName(CAD, "en",
2034 UCURR_SYMBOL_NAME,
2035 &isChoiceFormat, &len, &ec)),
2036 possibleDataError);
2037 assertEquals("CAD.getName(NARROW_SYMBOL_NAME, en)",
2038 UnicodeString("$"),
2039 UnicodeString(ucurr_getName(CAD, "en",
2040 UCURR_NARROW_SYMBOL_NAME,
2041 &isChoiceFormat, &len, &ec)),
2042 possibleDataError);
2043 assertEquals("CAD.getName(SYMBOL_NAME, en_CA)",
2044 UnicodeString("$"),
2045 UnicodeString(ucurr_getName(CAD, "en_CA",
2046 UCURR_SYMBOL_NAME,
2047 &isChoiceFormat, &len, &ec)),
2048 possibleDataError);
2049 assertEquals("USD.getName(SYMBOL_NAME, en_CA)",
2050 UnicodeString("US$"),
2051 UnicodeString(ucurr_getName(USD, "en_CA",
2052 UCURR_SYMBOL_NAME,
2053 &isChoiceFormat, &len, &ec)),
2054 possibleDataError);
2055 assertEquals("USD.getName(NARROW_SYMBOL_NAME, en_CA)",
Frank Tang1f164ee2022-11-08 12:31:27 -08002056 UnicodeString("US$"),
Frank Tang3e05d9d2021-11-08 14:04:04 -08002057 UnicodeString(ucurr_getName(USD, "en_CA",
2058 UCURR_NARROW_SYMBOL_NAME,
2059 &isChoiceFormat, &len, &ec)),
2060 possibleDataError);
2061 assertEquals("USD.getName(SYMBOL_NAME) in en_NZ",
2062 UnicodeString("US$"),
2063 UnicodeString(ucurr_getName(USD, "en_NZ",
2064 UCURR_SYMBOL_NAME,
2065 &isChoiceFormat, &len, &ec)),
2066 possibleDataError);
2067 assertEquals("CAD.getName(SYMBOL_NAME)",
2068 UnicodeString("CA$"),
2069 UnicodeString(ucurr_getName(CAD, "en_NZ",
2070 UCURR_SYMBOL_NAME,
2071 &isChoiceFormat, &len, &ec)),
2072 possibleDataError);
2073 assertEquals("USX.getName(SYMBOL_NAME)",
2074 UnicodeString("USX"),
2075 UnicodeString(ucurr_getName(USX, "en_US",
2076 UCURR_SYMBOL_NAME,
2077 &isChoiceFormat, &len, &ec)),
2078 possibleDataError);
2079 assertEquals("USX.getName(NARROW_SYMBOL_NAME)",
2080 UnicodeString("USX"),
2081 UnicodeString(ucurr_getName(USX, "en_US",
2082 UCURR_NARROW_SYMBOL_NAME,
2083 &isChoiceFormat, &len, &ec)),
2084 possibleDataError);
2085 assertEquals("USX.getName(LONG_NAME)",
2086 UnicodeString("USX"),
2087 UnicodeString(ucurr_getName(USX, "en_US",
2088 UCURR_LONG_NAME,
2089 &isChoiceFormat, &len, &ec)),
2090 possibleDataError);
2091 assertSuccess("ucurr_getName", ec);
2092
2093 ec = U_ZERO_ERROR;
2094
2095 // Test that a default or fallback warning is being returned. JB 4239.
2096 ucurr_getName(CAD, "es_ES", UCURR_LONG_NAME, &isChoiceFormat,
2097 &len, &ec);
2098 assertTrue("ucurr_getName (es_ES fallback)",
Frank Tang1f164ee2022-11-08 12:31:27 -08002099 U_USING_FALLBACK_WARNING == ec, true, possibleDataError);
Frank Tang3e05d9d2021-11-08 14:04:04 -08002100
2101 ucurr_getName(CAD, "zh_TW", UCURR_LONG_NAME, &isChoiceFormat,
2102 &len, &ec);
2103 assertTrue("ucurr_getName (zh_TW fallback)",
Frank Tang1f164ee2022-11-08 12:31:27 -08002104 U_USING_FALLBACK_WARNING == ec, true, possibleDataError);
Frank Tang3e05d9d2021-11-08 14:04:04 -08002105
2106 ucurr_getName(CAD, "en_US", UCURR_LONG_NAME, &isChoiceFormat,
2107 &len, &ec);
2108 assertTrue("ucurr_getName (en_US default)",
Frank Tang1f164ee2022-11-08 12:31:27 -08002109 U_USING_DEFAULT_WARNING == ec || U_USING_FALLBACK_WARNING == ec, true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08002110
2111 ucurr_getName(CAD, "ti", UCURR_LONG_NAME, &isChoiceFormat,
2112 &len, &ec);
2113 assertTrue("ucurr_getName (ti default)",
Frank Tang1f164ee2022-11-08 12:31:27 -08002114 U_USING_DEFAULT_WARNING == ec, true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08002115
2116 // Test that a default warning is being returned when falling back to root. JB 4536.
2117 ucurr_getName(ITL, "cy", UCURR_LONG_NAME, &isChoiceFormat,
2118 &len, &ec);
2119 assertTrue("ucurr_getName (cy default to root)",
Frank Tang1f164ee2022-11-08 12:31:27 -08002120 U_USING_DEFAULT_WARNING == ec, true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08002121
2122 // TODO add more tests later
2123}
2124
2125void NumberFormatTest::TestCurrencyVariants(){
2126 IcuTestErrorCode status(*this, "TestCurrencyVariants");
2127
2128 struct TestCase {
2129 const char* locale;
2130 const char16_t* isoCode;
2131 const char16_t* expectedShort;
2132 const char16_t* expectedNarrow;
2133 const char16_t* expectedFormal;
2134 const char16_t* expectedVariant;
2135 UErrorCode expectedNarrowError;
2136 } cases[] = {
2137 {"en-US", u"CAD", u"CA$", u"$", u"CA$", u"CA$", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2138 {"en-US", u"CDF", u"CDF", u"CDF", u"CDF", u"CDF", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2139 {"sw-CD", u"CDF", u"FC", u"FC", u"FC", u"FC", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2140 {"en-US", u"GEL", u"GEL", u"₾", u"GEL", u"GEL", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2141 {"ka-GE", u"GEL", u"₾", u"₾", u"₾", u"₾", U_USING_FALLBACK_WARNING}, // narrow: fallback to ka
2142 {"ka", u"GEL", u"₾", u"₾", u"₾", u"₾", U_ZERO_ERROR}, // no fallback on narrow
2143 {"zh-TW", u"TWD", u"$", u"$", u"NT$", u"$", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2144 {"ccp", u"TRY", u"TRY", u"₺", u"TRY", u"TL", U_ZERO_ERROR}, // no fallback on variant
2145 };
2146 for (const auto& cas : cases) {
2147 status.setScope(cas.isoCode);
2148 UBool choiceFormatIgnored;
2149 int32_t lengthIgnored;
2150 const UChar* actualShort = ucurr_getName(
2151 cas.isoCode,
2152 cas.locale,
2153 UCURR_SYMBOL_NAME,
2154 &choiceFormatIgnored,
2155 &lengthIgnored,
2156 status);
2157 const UChar* actualFormal = ucurr_getName(
2158 cas.isoCode,
2159 cas.locale,
2160 UCURR_FORMAL_SYMBOL_NAME,
2161 &choiceFormatIgnored,
2162 &lengthIgnored,
2163 status);
2164 const UChar* actualVarant = ucurr_getName(
2165 cas.isoCode,
2166 cas.locale,
2167 UCURR_VARIANT_SYMBOL_NAME,
2168 &choiceFormatIgnored,
2169 &lengthIgnored,
2170 status);
2171 status.errIfFailureAndReset();
2172 const UChar* actualNarrow = ucurr_getName(
2173 cas.isoCode,
2174 cas.locale,
2175 UCURR_NARROW_SYMBOL_NAME,
2176 &choiceFormatIgnored,
2177 &lengthIgnored,
2178 status);
2179 status.expectErrorAndReset(cas.expectedNarrowError);
2180 assertEquals(UnicodeString("Short symbol: ") + cas.locale + u": " + cas.isoCode,
2181 cas.expectedShort, actualShort);
2182 assertEquals(UnicodeString("Narrow symbol: ") + cas.locale + u": " + cas.isoCode,
2183 cas.expectedNarrow, actualNarrow);
2184 assertEquals(UnicodeString("Formal symbol: ") + cas.locale + u": " + cas.isoCode,
2185 cas.expectedFormal, actualFormal);
2186 assertEquals(UnicodeString("Variant symbol: ") + cas.locale + u": " + cas.isoCode,
2187 cas.expectedVariant, actualVarant);
2188 }
2189}
2190
2191void NumberFormatTest::TestCurrencyUnit(void){
2192 UErrorCode ec = U_ZERO_ERROR;
2193 static const UChar USD[] = u"USD";
2194 static const char USD8[] = "USD";
2195 static const UChar BAD[] = u"???";
2196 static const UChar BAD2[] = u"??A";
2197 static const UChar XXX[] = u"XXX";
2198 static const char XXX8[] = "XXX";
2199 static const UChar XYZ[] = u"XYZ";
2200 static const char XYZ8[] = "XYZ";
2201 static const UChar INV[] = u"{$%";
2202 static const char INV8[] = "{$%";
2203 static const UChar ZZZ[] = u"zz";
2204 static const char ZZZ8[] = "zz";
2205 static const UChar JPY[] = u"JPY";
2206 static const char JPY8[] = "JPY";
2207 static const UChar jpy[] = u"jpy";
2208 static const char jpy8[] = "jpy";
2209
2210 UChar* EUR = (UChar*) malloc(6);
2211 EUR[0] = u'E';
2212 EUR[1] = u'U';
2213 EUR[2] = u'R';
2214 char* EUR8 = (char*) malloc(3);
2215 EUR8[0] = 'E';
2216 EUR8[1] = 'U';
2217 EUR8[2] = 'R';
2218
2219 CurrencyUnit cu(USD, ec);
2220 assertSuccess("CurrencyUnit", ec);
2221 assertEquals("getISOCurrency()", USD, cu.getISOCurrency());
2222 assertEquals("getSubtype()", USD8, cu.getSubtype());
2223
2224 // Test XYZ, a valid but non-standard currency.
2225 // Note: Country code XY is private-use, so XYZ should remain unallocated.
2226 CurrencyUnit extended(XYZ, ec);
2227 assertSuccess("non-standard", ec);
2228 assertEquals("non-standard", XYZ, extended.getISOCurrency());
2229 assertEquals("non-standard", XYZ8, extended.getSubtype());
2230
2231 CurrencyUnit inv(INV, ec);
2232 assertEquals("non-invariant", U_INVARIANT_CONVERSION_ERROR, ec);
2233 assertEquals("non-invariant", XXX, inv.getISOCurrency());
2234 ec = U_ZERO_ERROR;
2235
2236 CurrencyUnit zzz(ZZZ, ec);
2237 assertEquals("too short", U_ILLEGAL_ARGUMENT_ERROR, ec);
2238 assertEquals("too short", XXX, zzz.getISOCurrency());
2239 ec = U_ZERO_ERROR;
2240
2241 CurrencyUnit eur(EUR, ec);
2242 assertEquals("non-nul-terminated", u"EUR", eur.getISOCurrency());
2243 assertEquals("non-nul-terminated", "EUR", eur.getSubtype());
2244
2245 // Test StringPiece constructor
2246 CurrencyUnit cu8(USD8, ec);
2247 assertEquals("StringPiece constructor", USD, cu8.getISOCurrency());
2248
2249 CurrencyUnit inv8(INV8, ec);
2250 assertEquals("non-invariant 8", U_INVARIANT_CONVERSION_ERROR, ec);
2251 assertEquals("non-invariant 8", XXX, inv8.getISOCurrency());
2252 ec = U_ZERO_ERROR;
2253
2254 CurrencyUnit zzz8(ZZZ8, ec);
2255 assertEquals("too short 8", U_ILLEGAL_ARGUMENT_ERROR, ec);
2256 assertEquals("too short 8", XXX, zzz8.getISOCurrency());
2257 ec = U_ZERO_ERROR;
2258
2259 CurrencyUnit zzz8b({ZZZ8, 3}, ec);
2260 assertEquals("too short 8b", U_ILLEGAL_ARGUMENT_ERROR, ec);
2261 assertEquals("too short 8b", XXX, zzz8b.getISOCurrency());
2262 ec = U_ZERO_ERROR;
2263
2264 CurrencyUnit eur8({EUR8, 3}, ec);
2265 assertEquals("non-nul-terminated 8", u"EUR", eur8.getISOCurrency());
2266 assertEquals("non-nul-terminated 8", "EUR", eur8.getSubtype());
2267
2268 CurrencyUnit cu2(cu);
2269 if (!(cu2 == cu)){
2270 errln("CurrencyUnit copy constructed object should be same");
2271 }
2272
2273 CurrencyUnit * cu3 = cu.clone();
2274 if (!(*cu3 == cu)){
2275 errln("CurrencyUnit cloned object should be same");
2276 }
2277 CurrencyUnit bad(BAD, ec);
2278 assertSuccess("CurrencyUnit", ec);
2279 if (cu.getOffset() == bad.getOffset()) {
2280 errln("Indexes of different currencies should differ.");
2281 }
2282 CurrencyUnit bad2(BAD2, ec);
2283 assertSuccess("CurrencyUnit", ec);
2284 if (bad2.getOffset() != bad.getOffset()) {
2285 errln("Indexes of unrecognized currencies should be the same.");
2286 }
2287 if (bad == bad2) {
2288 errln("Different unrecognized currencies should not be equal.");
2289 }
2290 bad = bad2;
2291 if (bad != bad2) {
2292 errln("Currency unit assignment should be the same.");
2293 }
2294 delete cu3;
2295
2296 // Test default constructor
2297 CurrencyUnit def;
2298 assertEquals("Default currency", XXX, def.getISOCurrency());
2299 assertEquals("Default currency as subtype", XXX8, def.getSubtype());
2300
2301 // Test slicing
2302 MeasureUnit sliced1 = cu;
2303 MeasureUnit sliced2 = cu;
2304 MeasureUnit sliced3 = extended;
2305 assertEquals("Subtype after slicing 1", USD8, sliced1.getSubtype());
2306 assertEquals("Subtype after slicing 2", USD8, sliced2.getSubtype());
2307 assertEquals("Subtype after slicing 3", XYZ8, sliced3.getSubtype());
2308 CurrencyUnit restored1(sliced1, ec);
2309 CurrencyUnit restored2(sliced2, ec);
2310 CurrencyUnit restored3(sliced3, ec);
2311 assertSuccess("Restoring from MeasureUnit", ec);
2312 assertEquals("Subtype after restoring 1", USD8, restored1.getSubtype());
2313 assertEquals("Subtype after restoring 2", USD8, restored2.getSubtype());
2314 assertEquals("Subtype after restoring 3", XYZ8, restored3.getSubtype());
2315 assertEquals("ISO Code after restoring 1", USD, restored1.getISOCurrency());
2316 assertEquals("ISO Code after restoring 2", USD, restored2.getISOCurrency());
2317 assertEquals("ISO Code after restoring 3", XYZ, restored3.getISOCurrency());
2318
2319 // Test copy constructor failure
2320 LocalPointer<MeasureUnit> meter(MeasureUnit::createMeter(ec));
2321 assertSuccess("Creating meter", ec);
2322 CurrencyUnit failure(*meter, ec);
2323 assertEquals("Copying from meter should fail", ec, U_ILLEGAL_ARGUMENT_ERROR);
2324 assertEquals("Copying should not give uninitialized ISO code", u"", failure.getISOCurrency());
2325
2326 // Test equality
2327 ec = U_ZERO_ERROR;
2328 assertFalse("FAIL: USD == JPY", CurrencyUnit(USD, ec) == CurrencyUnit(JPY, ec));
2329 assertTrue("FAIL: USD != USD", CurrencyUnit(USD, ec) == CurrencyUnit(USD, ec));
2330 assertTrue("FAIL: JPY != jpy", CurrencyUnit(JPY, ec) == CurrencyUnit(jpy, ec));
2331 assertTrue("FAIL: jpy != JPY", CurrencyUnit(jpy, ec) == CurrencyUnit(JPY, ec));
2332
2333 // Test equality with system charset instances
2334 assertFalse("FAIL: USD8 == JPY8", CurrencyUnit(USD8, ec) == CurrencyUnit(JPY8, ec));
2335 assertTrue("FAIL: USD8 != USD8", CurrencyUnit(USD8, ec) == CurrencyUnit(USD8, ec));
2336 assertTrue("FAIL: JPY8 != jpy8", CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy8, ec));
2337 assertTrue("FAIL: jpy8 != JPY8", CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY8, ec));
2338
2339 // Test equality between UTF-16 and system charset instances
2340 assertTrue("FAIL: USD != USD8", CurrencyUnit(USD, ec) == CurrencyUnit(USD8, ec));
2341 assertTrue("FAIL: USD8 != USD", CurrencyUnit(USD8, ec) == CurrencyUnit(USD, ec));
2342 assertTrue("FAIL: JPY != jpy8", CurrencyUnit(JPY, ec) == CurrencyUnit(jpy8, ec));
2343 assertTrue("FAIL: JPY8 != jpy", CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy, ec));
2344 assertTrue("FAIL: jpy != JPY8", CurrencyUnit(jpy, ec) == CurrencyUnit(JPY8, ec));
2345 assertTrue("FAIL: jpy8 != JPY", CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY, ec));
2346
2347 free(EUR);
2348 free(EUR8);
2349}
2350
2351void NumberFormatTest::TestCurrencyAmount(void){
2352 UErrorCode ec = U_ZERO_ERROR;
2353 static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
2354 CurrencyAmount ca(9, USD, ec);
2355 assertSuccess("CurrencyAmount", ec);
2356
2357 CurrencyAmount ca2(ca);
2358 if (!(ca2 == ca)){
2359 errln("CurrencyAmount copy constructed object should be same");
2360 }
2361
2362 ca2=ca;
2363 if (!(ca2 == ca)){
2364 errln("CurrencyAmount assigned object should be same");
2365 }
2366
2367 CurrencyAmount *ca3 = ca.clone();
2368 if (!(*ca3 == ca)){
2369 errln("CurrencyAmount cloned object should be same");
2370 }
2371 delete ca3;
2372}
2373
2374void NumberFormatTest::TestSymbolsWithBadLocale(void) {
2375 Locale locDefault;
2376 static const char *badLocales[] = {
2377 // length < ULOC_FULLNAME_CAPACITY
2378 "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME",
2379
2380 // length > ULOC_FULLNAME_CAPACITY
2381 "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"
2382 }; // expect U_USING_DEFAULT_WARNING for both
2383
2384 unsigned int i;
2385 for (i = 0; i < UPRV_LENGTHOF(badLocales); i++) {
2386 const char *localeName = badLocales[i];
2387 Locale locBad(localeName);
2388 assertTrue(WHERE, !locBad.isBogus());
2389 UErrorCode status = U_ZERO_ERROR;
2390 UnicodeString intlCurrencySymbol((UChar)0xa4);
2391
2392 intlCurrencySymbol.append((UChar)0xa4);
2393
2394 logln("Current locale is %s", Locale::getDefault().getName());
2395 Locale::setDefault(locBad, status);
2396 logln("Current locale is %s", Locale::getDefault().getName());
2397 DecimalFormatSymbols mySymbols(status);
2398 if (status != U_USING_DEFAULT_WARNING) {
2399 errln("DecimalFormatSymbols should return U_USING_DEFAULT_WARNING.");
2400 }
2401 if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
2402 errln("DecimalFormatSymbols does not have the right locale.", locBad.getName());
2403 }
2404 int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
2405 for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
2406 UnicodeString symbolString = mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum);
2407 logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ") + prettify(symbolString));
2408 if (symbolString.length() == 0
2409 && symbolEnum != (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
2410 && symbolEnum != (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol)
2411 {
2412 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
2413 }
2414 }
2415
2416 status = U_ZERO_ERROR;
2417 Locale::setDefault(locDefault, status);
2418 logln("Current locale is %s", Locale::getDefault().getName());
2419 }
2420}
2421
2422/**
2423 * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
2424 * behave the same, except for memory ownership semantics. (No
2425 * version of this test on Java, since Java has only one method.)
2426 */
2427void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
2428 UErrorCode ec = U_ZERO_ERROR;
2429 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2430 if (U_FAILURE(ec)) {
2431 errcheckln(ec, "Fail: DecimalFormatSymbols constructor - %s", u_errorName(ec));
2432 delete sym;
2433 return;
2434 }
2435 UnicodeString pat(" #,##0.00");
2436 pat.insert(0, (UChar)0x00A4);
2437 DecimalFormat fmt(pat, sym, ec);
2438 if (U_FAILURE(ec)) {
2439 errln("Fail: DecimalFormat constructor");
2440 return;
2441 }
2442
2443 UnicodeString str;
2444 fmt.format(2350.75, str);
2445 if (str == "$ 2,350.75") {
2446 logln(str);
2447 } else {
2448 dataerrln("Fail: " + str + ", expected $ 2,350.75");
2449 }
2450
2451 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2452 if (U_FAILURE(ec)) {
2453 errln("Fail: DecimalFormatSymbols constructor");
2454 delete sym;
2455 return;
2456 }
2457 sym->setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2458 fmt.adoptDecimalFormatSymbols(sym);
2459
2460 str.truncate(0);
2461 fmt.format(2350.75, str);
2462 if (str == "Q 2,350.75") {
2463 logln(str);
2464 } else {
2465 dataerrln("Fail: adoptDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2466 }
2467
2468 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2469 if (U_FAILURE(ec)) {
2470 errln("Fail: DecimalFormatSymbols constructor");
2471 delete sym;
2472 return;
2473 }
2474 DecimalFormat fmt2(pat, sym, ec);
2475 if (U_FAILURE(ec)) {
2476 errln("Fail: DecimalFormat constructor");
2477 return;
2478 }
2479
2480 DecimalFormatSymbols sym2(Locale::getUS(), ec);
2481 if (U_FAILURE(ec)) {
2482 errln("Fail: DecimalFormatSymbols constructor");
2483 return;
2484 }
2485 sym2.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2486 fmt2.setDecimalFormatSymbols(sym2);
2487
2488 str.truncate(0);
2489 fmt2.format(2350.75, str);
2490 if (str == "Q 2,350.75") {
2491 logln(str);
2492 } else {
2493 dataerrln("Fail: setDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2494 }
2495}
2496
2497void NumberFormatTest::TestPerMill() {
2498 UErrorCode ec = U_ZERO_ERROR;
2499 UnicodeString str;
2500 DecimalFormat fmt(ctou("###.###\\u2030"), ec);
2501 if (!assertSuccess("DecimalFormat ct", ec)) return;
2502 assertEquals("0.4857 x ###.###\\u2030",
2503 ctou("485.7\\u2030"), fmt.format(0.4857, str), true);
2504
2505 DecimalFormatSymbols sym(Locale::getUS(), ec);
2506 if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2507 return;
2508 }
2509 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
2510 DecimalFormat fmt2("", sym, ec);
2511 if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2512 return;
2513 }
2514 fmt2.applyLocalizedPattern("###.###m", ec);
2515 if (!assertSuccess("setup", ec)) return;
2516 str.truncate(0);
2517 assertEquals("0.4857 x ###.###m",
2518 "485.7m", fmt2.format(0.4857, str));
2519}
2520
2521/**
2522 * Generic test for patterns that should be legal/illegal.
2523 */
2524void NumberFormatTest::TestIllegalPatterns() {
2525 // Test cases:
2526 // Prefix with "-:" for illegal patterns
2527 // Prefix with "+:" for legal patterns
2528 const char* DATA[] = {
2529 // Unquoted special characters in the suffix are illegal
2530 "-:000.000|###",
2531 "+:000.000'|###'",
2532 0
2533 };
2534 for (int32_t i=0; DATA[i]; ++i) {
2535 const char* pat=DATA[i];
2536 UBool valid = (*pat) == '+';
2537 pat += 2;
2538 UErrorCode ec = U_ZERO_ERROR;
2539 DecimalFormat fmt(pat, ec); // locale doesn't matter here
2540 if (U_SUCCESS(ec) == valid) {
2541 logln("Ok: pattern \"%s\": %s",
2542 pat, u_errorName(ec));
2543 } else {
2544 errcheckln(ec, "FAIL: pattern \"%s\" should have %s; got %s",
2545 pat, (valid?"succeeded":"failed"),
2546 u_errorName(ec));
2547 }
2548 }
2549}
2550
2551//----------------------------------------------------------------------
2552
2553static const char* KEYWORDS[] = {
2554 /*0*/ "ref=", // <reference pattern to parse numbers>
2555 /*1*/ "loc=", // <locale for formats>
2556 /*2*/ "f:", // <pattern or '-'> <number> <exp. string>
2557 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number>
2558 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string>
2559 /*5*/ "p:", // <pattern or '-'> <string> <exp. number>
2560 /*6*/ "perr:", // <pattern or '-'> <invalid string>
2561 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
2562 /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2563 0
2564};
2565
2566/**
2567 * Return an integer representing the next token from this
2568 * iterator. The integer will be an index into the given list, or
2569 * -1 if there are no more tokens, or -2 if the token is not on
2570 * the list.
2571 */
2572static int32_t keywordIndex(const UnicodeString& tok) {
2573 for (int32_t i=0; KEYWORDS[i]!=0; ++i) {
2574 if (tok==KEYWORDS[i]) {
2575 return i;
2576 }
2577 }
2578 return -1;
2579}
2580
2581/**
2582 * Parse a CurrencyAmount using the given NumberFormat, with
2583 * the 'delim' character separating the number and the currency.
2584 */
2585static void parseCurrencyAmount(const UnicodeString& str,
2586 const NumberFormat& fmt,
2587 UChar delim,
2588 Formattable& result,
2589 UErrorCode& ec) {
2590 UnicodeString num, cur;
2591 int32_t i = str.indexOf(delim);
2592 str.extractBetween(0, i, num);
2593 str.extractBetween(i+1, INT32_MAX, cur);
2594 Formattable n;
2595 fmt.parse(num, n, ec);
2596 result.adoptObject(new CurrencyAmount(n, cur.getTerminatedBuffer(), ec));
2597}
2598
2599void NumberFormatTest::TestCases() {
2600 UErrorCode ec = U_ZERO_ERROR;
2601 TextFile reader("NumberFormatTestCases.txt", "UTF8", ec);
2602 if (U_FAILURE(ec)) {
2603 dataerrln("Couldn't open NumberFormatTestCases.txt");
2604 return;
2605 }
2606 TokenIterator tokens(&reader);
2607
2608 Locale loc("en", "US", "");
2609 DecimalFormat *ref = 0, *fmt = 0;
2610 MeasureFormat *mfmt = 0;
2611 UnicodeString pat, tok, mloc, str, out, where, currAmt;
2612 Formattable n;
2613
2614 for (;;) {
2615 ec = U_ZERO_ERROR;
2616 if (!tokens.next(tok, ec)) {
2617 break;
2618 }
2619 where = UnicodeString("(") + tokens.getLineNumber() + ") ";
2620 int32_t cmd = keywordIndex(tok);
2621 switch (cmd) {
2622 case 0:
2623 // ref= <reference pattern>
2624 if (!tokens.next(tok, ec)) goto error;
2625 delete ref;
2626 ref = new DecimalFormat(tok,
2627 new DecimalFormatSymbols(Locale::getUS(), ec), ec);
2628 if (U_FAILURE(ec)) {
2629 dataerrln("Error constructing DecimalFormat");
2630 goto error;
2631 }
2632 break;
2633 case 1:
2634 // loc= <locale>
2635 if (!tokens.next(tok, ec)) goto error;
2636 loc = Locale::createFromName(CharString().appendInvariantChars(tok, ec).data());
2637 break;
2638 case 2: // f:
2639 case 3: // fp:
2640 case 4: // rt:
2641 case 5: // p:
2642 if (!tokens.next(tok, ec)) goto error;
2643 if (tok != "-") {
2644 pat = tok;
2645 delete fmt;
2646 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc, ec), ec);
2647 if (U_FAILURE(ec)) {
2648 errln("FAIL: " + where + "Pattern \"" + pat + "\": " + u_errorName(ec));
2649 ec = U_ZERO_ERROR;
2650 if (!tokens.next(tok, ec)) goto error;
2651 if (!tokens.next(tok, ec)) goto error;
2652 if (cmd == 3) {
2653 if (!tokens.next(tok, ec)) goto error;
2654 }
2655 continue;
2656 }
2657 }
2658 if (cmd == 2 || cmd == 3 || cmd == 4) {
2659 // f: <pattern or '-'> <number> <exp. string>
2660 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
2661 // rt: <pattern or '-'> <number> <string>
2662 UnicodeString num;
2663 if (!tokens.next(num, ec)) goto error;
2664 if (!tokens.next(str, ec)) goto error;
2665 ref->parse(num, n, ec);
2666 assertSuccess("parse", ec);
2667 assertEquals(where + "\"" + pat + "\".format(" + num + ")",
2668 str, fmt->format(n, out.remove(), ec));
2669 assertSuccess("format", ec);
2670 if (cmd == 3) { // fp:
2671 if (!tokens.next(num, ec)) goto error;
2672 ref->parse(num, n, ec);
2673 assertSuccess("parse", ec);
2674 }
2675 if (cmd != 2) { // != f:
2676 Formattable m;
2677 fmt->parse(str, m, ec);
2678 assertSuccess("parse", ec);
2679 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2680 n, m);
2681 }
2682 }
2683 // p: <pattern or '-'> <string to parse> <exp. number>
2684 else {
2685 UnicodeString expstr;
2686 if (!tokens.next(str, ec)) goto error;
2687 if (!tokens.next(expstr, ec)) goto error;
2688 Formattable exp, n;
2689 ref->parse(expstr, exp, ec);
2690 assertSuccess("parse", ec);
2691 fmt->parse(str, n, ec);
2692 assertSuccess("parse", ec);
2693 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2694 exp, n);
2695 }
2696 break;
2697 case 8: // fpc:
2698 if (!tokens.next(tok, ec)) goto error;
2699 if (tok != "-") {
2700 mloc = tok;
2701 delete mfmt;
2702 mfmt = MeasureFormat::createCurrencyFormat(
2703 Locale::createFromName(
2704 CharString().appendInvariantChars(mloc, ec).data()), ec);
2705 if (U_FAILURE(ec)) {
2706 errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
2707 ec = U_ZERO_ERROR;
2708 if (!tokens.next(tok, ec)) goto error;
2709 if (!tokens.next(tok, ec)) goto error;
2710 if (!tokens.next(tok, ec)) goto error;
2711 continue;
2712 }
2713 } else if (mfmt == NULL) {
2714 errln("FAIL: " + where + "Loc \"" + mloc + "\": skip case using previous locale, no valid MeasureFormat");
2715 if (!tokens.next(tok, ec)) goto error;
2716 if (!tokens.next(tok, ec)) goto error;
2717 if (!tokens.next(tok, ec)) goto error;
2718 continue;
2719 }
2720 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2721 if (!tokens.next(currAmt, ec)) goto error;
2722 if (!tokens.next(str, ec)) goto error;
2723 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2724 if (assertSuccess("parseCurrencyAmount", ec)) {
2725 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
2726 str, mfmt->format(n, out.remove(), ec));
2727 assertSuccess("format", ec);
2728 }
2729 if (!tokens.next(currAmt, ec)) goto error;
2730 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2731 if (assertSuccess("parseCurrencyAmount", ec)) {
2732 Formattable m;
2733
2734 mfmt->parseObject(str, m, ec);
2735 if (assertSuccess("parseCurrency", ec)) {
2736 assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
2737 n, m);
2738 } else {
2739 errln("FAIL: source " + str);
2740 }
2741 }
2742 break;
2743 case 6:
2744 // perr: <pattern or '-'> <invalid string>
2745 errln("FAIL: Under construction");
2746 goto done;
2747 case 7: {
2748 // pat: <pattern> <exp. toPattern, or '-' or 'err'>
2749 UnicodeString testpat;
2750 UnicodeString exppat;
2751 if (!tokens.next(testpat, ec)) goto error;
2752 if (!tokens.next(exppat, ec)) goto error;
2753 UBool err = exppat == "err";
Frank Tang1f164ee2022-11-08 12:31:27 -08002754 UBool existingPat = false;
Frank Tang3e05d9d2021-11-08 14:04:04 -08002755 if (testpat == "-") {
2756 if (err) {
2757 errln("FAIL: " + where + "Invalid command \"pat: - err\"");
2758 continue;
2759 }
Frank Tang1f164ee2022-11-08 12:31:27 -08002760 existingPat = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -08002761 testpat = pat;
2762 }
2763 if (exppat == "-") exppat = testpat;
2764 DecimalFormat* f = 0;
2765 UErrorCode ec2 = U_ZERO_ERROR;
2766 if (existingPat) {
2767 f = fmt;
2768 } else {
2769 f = new DecimalFormat(testpat, ec2);
2770 }
2771 if (U_SUCCESS(ec2)) {
2772 if (err) {
2773 errln("FAIL: " + where + "Invalid pattern \"" + testpat +
2774 "\" was accepted");
2775 } else {
2776 UnicodeString pat2;
2777 assertEquals(where + "\"" + testpat + "\".toPattern()",
2778 exppat, f->toPattern(pat2));
2779 }
2780 } else {
2781 if (err) {
2782 logln("Ok: " + where + "Invalid pattern \"" + testpat +
2783 "\" failed: " + u_errorName(ec2));
2784 } else {
2785 errln("FAIL: " + where + "Valid pattern \"" + testpat +
2786 "\" failed: " + u_errorName(ec2));
2787 }
2788 }
2789 if (!existingPat) delete f;
2790 } break;
2791 case -1:
2792 errln("FAIL: " + where + "Unknown command \"" + tok + "\"");
2793 goto done;
2794 }
2795 }
2796 goto done;
2797
2798 error:
2799 if (U_SUCCESS(ec)) {
2800 errln("FAIL: Unexpected EOF");
2801 } else {
2802 errcheckln(ec, "FAIL: " + where + "Unexpected " + u_errorName(ec));
2803 }
2804
2805 done:
2806 delete mfmt;
2807 delete fmt;
2808 delete ref;
2809}
2810
2811
2812//----------------------------------------------------------------------
2813// Support methods
2814//----------------------------------------------------------------------
2815
2816UBool NumberFormatTest::equalValue(const Formattable& a, const Formattable& b) {
2817 if (a.getType() == b.getType()) {
2818 return a == b;
2819 }
2820
2821 if (a.getType() == Formattable::kLong) {
2822 if (b.getType() == Formattable::kInt64) {
2823 return a.getLong() == b.getLong();
2824 } else if (b.getType() == Formattable::kDouble) {
2825 return (double) a.getLong() == b.getDouble(); // TODO check use of double instead of long
2826 }
2827 } else if (a.getType() == Formattable::kDouble) {
2828 if (b.getType() == Formattable::kLong) {
2829 return a.getDouble() == (double) b.getLong();
2830 } else if (b.getType() == Formattable::kInt64) {
2831 return a.getDouble() == (double)b.getInt64();
2832 }
2833 } else if (a.getType() == Formattable::kInt64) {
2834 if (b.getType() == Formattable::kLong) {
2835 return a.getInt64() == (int64_t)b.getLong();
2836 } else if (b.getType() == Formattable::kDouble) {
2837 return a.getInt64() == (int64_t)b.getDouble();
2838 }
2839 }
Frank Tang1f164ee2022-11-08 12:31:27 -08002840 return false;
Frank Tang3e05d9d2021-11-08 14:04:04 -08002841}
2842
2843void NumberFormatTest::expect3(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2844 // Don't round-trip format test, since we explicitly do it
Frank Tang1f164ee2022-11-08 12:31:27 -08002845 expect_rbnf(fmt, n, str, false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08002846 expect_rbnf(fmt, str, n);
2847}
2848
2849void NumberFormatTest::expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2850 // Don't round-trip format test, since we explicitly do it
Frank Tang1f164ee2022-11-08 12:31:27 -08002851 expect(fmt, n, str, false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08002852 expect(fmt, str, n);
2853}
2854
2855void NumberFormatTest::expect2(NumberFormat* fmt, const Formattable& n,
2856 const UnicodeString& exp,
2857 UErrorCode status) {
2858 if (fmt == NULL || U_FAILURE(status)) {
2859 dataerrln("FAIL: NumberFormat constructor");
2860 } else {
2861 expect2(*fmt, n, exp);
2862 }
2863 delete fmt;
2864}
2865
2866void NumberFormatTest::expect(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2867 UErrorCode status = U_ZERO_ERROR;
2868 Formattable num;
2869 fmt.parse(str, num, status);
2870 if (U_FAILURE(status)) {
2871 dataerrln(UnicodeString("FAIL: Parse failed for \"") + str + "\" - " + u_errorName(status));
2872 return;
2873 }
2874 UnicodeString pat;
2875 ((DecimalFormat*) &fmt)->toPattern(pat);
2876 if (equalValue(num, n)) {
2877 logln(UnicodeString("Ok \"") + str + "\" x " +
2878 pat + " = " +
2879 toString(num));
2880 } else {
2881 dataerrln(UnicodeString("FAIL \"") + str + "\" x " +
2882 pat + " = " +
2883 toString(num) + ", expected " + toString(n));
2884 }
2885}
2886
2887void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2888 UErrorCode status = U_ZERO_ERROR;
2889 Formattable num;
2890 fmt.parse(str, num, status);
2891 if (U_FAILURE(status)) {
2892 errln(UnicodeString("FAIL: Parse failed for \"") + str + "\"");
2893 return;
2894 }
2895 if (equalValue(num, n)) {
2896 logln(UnicodeString("Ok \"") + str + " = " +
2897 toString(num));
2898 } else {
2899 errln(UnicodeString("FAIL \"") + str + " = " +
2900 toString(num) + ", expected " + toString(n));
2901 }
2902}
2903
2904void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const Formattable& n,
2905 const UnicodeString& exp, UBool rt) {
2906 UnicodeString saw;
2907 FieldPosition pos;
2908 UErrorCode status = U_ZERO_ERROR;
2909 fmt.format(n, saw, pos, status);
2910 CHECK(status, "NumberFormat::format");
2911 if (saw == exp) {
2912 logln(UnicodeString("Ok ") + toString(n) +
2913 " = \"" +
2914 escape(saw) + "\"");
2915 // We should be able to round-trip the formatted string =>
2916 // number => string (but not the other way around: number
2917 // => string => number2, might have number2 != number):
2918 if (rt) {
2919 Formattable n2;
2920 fmt.parse(exp, n2, status);
2921 if (U_FAILURE(status)) {
2922 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\"");
2923 return;
2924 }
2925 UnicodeString saw2;
2926 fmt.format(n2, saw2, pos, status);
2927 CHECK(status, "NumberFormat::format");
2928 if (saw2 != exp) {
2929 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2930 " => \"" + saw2 + "\"");
2931 }
2932 }
2933 } else {
2934 errln(UnicodeString("FAIL ") + toString(n) +
2935 " = \"" +
2936 escape(saw) + "\", expected \"" + exp + "\"");
2937 }
2938}
2939
2940void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
2941 const UnicodeString& exp, UBool rt) {
2942 UnicodeString saw;
2943 FieldPosition pos;
2944 UErrorCode status = U_ZERO_ERROR;
2945 fmt.format(n, saw, pos, status);
2946 CHECK(status, "NumberFormat::format");
2947 UnicodeString pat;
2948 ((DecimalFormat*) &fmt)->toPattern(pat);
2949 if (saw == exp) {
2950 logln(UnicodeString("Ok ") + toString(n) + " x " +
2951 escape(pat) + " = \"" +
2952 escape(saw) + "\"");
2953 // We should be able to round-trip the formatted string =>
2954 // number => string (but not the other way around: number
2955 // => string => number2, might have number2 != number):
2956 if (rt) {
2957 Formattable n2;
2958 fmt.parse(exp, n2, status);
2959 if (U_FAILURE(status)) {
2960 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\" - " + u_errorName(status));
2961 return;
2962 }
2963 UnicodeString saw2;
2964 fmt.format(n2, saw2, pos, status);
2965 CHECK(status, "NumberFormat::format");
2966 if (saw2 != exp) {
2967 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2968 " => \"" + saw2 + "\"");
2969 }
2970 }
2971 } else {
2972 dataerrln(UnicodeString("FAIL ") + toString(n) + " x " +
2973 escape(pat) + " = \"" +
2974 escape(saw) + "\", expected \"" + exp + "\"");
2975 }
2976}
2977
2978void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
2979 const UnicodeString& exp, UBool rt,
2980 UErrorCode status) {
2981 if (fmt == NULL || U_FAILURE(status)) {
2982 dataerrln("FAIL: NumberFormat constructor");
2983 } else {
2984 expect(*fmt, n, exp, rt);
2985 }
2986 delete fmt;
2987}
2988
2989void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
2990 double value, const UnicodeString& string) {
2991 UErrorCode ec = U_ZERO_ERROR;
2992 DecimalFormat& fmt = * (DecimalFormat*) &nf;
2993 const UChar DEFAULT_CURR[] = {45/*-*/,0};
2994 UChar curr[4];
2995 u_strcpy(curr, DEFAULT_CURR);
2996 if (*locale.getLanguage() != 0) {
2997 ucurr_forLocale(locale.getName(), curr, 4, &ec);
2998 assertSuccess("ucurr_forLocale", ec);
2999 fmt.setCurrency(curr, ec);
3000 assertSuccess("DecimalFormat::setCurrency", ec);
3001 fmt.setCurrency(curr); //Deprecated variant, for coverage only
3002 }
3003 UnicodeString s;
3004 fmt.format(value, s);
3005 s.findAndReplace((UChar32)0x00A0, (UChar32)0x0020);
3006
3007 // Default display of the number yields "1234.5599999999999"
3008 // instead of "1234.56". Use a formatter to fix this.
3009 NumberFormat* f =
3010 NumberFormat::createInstance(Locale::getUS(), ec);
3011 UnicodeString v;
3012 if (U_FAILURE(ec)) {
3013 // Oops; bad formatter. Use default op+= display.
3014 v = (UnicodeString)"" + value;
3015 } else {
3016 f->setMaximumFractionDigits(4);
Frank Tang1f164ee2022-11-08 12:31:27 -08003017 f->setGroupingUsed(false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08003018 f->format(value, v);
3019 }
3020 delete f;
3021
3022 if (s == string) {
3023 logln((UnicodeString)"Ok: " + v + " x " + curr + " => " + prettify(s));
3024 } else {
3025 errln((UnicodeString)"FAIL: " + v + " x " + curr + " => " + prettify(s) +
3026 ", expected " + prettify(string));
3027 }
3028}
3029
3030void NumberFormatTest::expectPat(DecimalFormat& fmt, const UnicodeString& exp) {
3031 UnicodeString pat;
3032 fmt.toPattern(pat);
3033 if (pat == exp) {
3034 logln(UnicodeString("Ok \"") + pat + "\"");
3035 } else {
3036 errln(UnicodeString("FAIL \"") + pat + "\", expected \"" + exp + "\"");
3037 }
3038}
3039
3040void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3041 int32_t pos) {
3042 expectPad(fmt, pat, pos, 0, (UnicodeString)"");
3043}
3044void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3045 int32_t pos, int32_t width, UChar pad) {
3046 expectPad(fmt, pat, pos, width, UnicodeString(pad));
3047}
3048void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3049 int32_t pos, int32_t width, const UnicodeString& pad) {
3050 int32_t apos = 0, awidth = 0;
3051 UnicodeString apadStr;
3052 UErrorCode status = U_ZERO_ERROR;
3053 fmt.applyPattern(pat, status);
3054 if (U_SUCCESS(status)) {
3055 apos = fmt.getPadPosition();
3056 awidth = fmt.getFormatWidth();
3057 apadStr=fmt.getPadCharacterString();
3058 } else {
3059 apos = -1;
3060 awidth = width;
3061 apadStr = pad;
3062 }
3063 if (apos == pos && awidth == width && apadStr == pad) {
3064 UnicodeString infoStr;
3065 if (pos == ILLEGAL) {
3066 infoStr = UnicodeString(" width=", "") + awidth + UnicodeString(" pad=", "") + apadStr;
3067 }
3068 logln(UnicodeString("Ok \"") + pat + "\" pos=" + apos + infoStr);
3069 } else {
3070 errln(UnicodeString("FAIL \"") + pat + "\" pos=" + apos +
3071 " width=" + awidth + " pad=" + apadStr +
3072 ", expected " + pos + " " + width + " " + pad);
3073 }
3074}
3075
3076// This test is flaky b/c the symbols for CNY and JPY are equivalent in this locale - FIXME
3077void NumberFormatTest::TestCompatibleCurrencies() {
3078/*
3079 static const UChar JPY[] = {0x4A, 0x50, 0x59, 0};
3080 static const UChar CNY[] = {0x43, 0x4E, 0x59, 0};
3081 UErrorCode status = U_ZERO_ERROR;
3082 LocalPointer<NumberFormat> fmt(
3083 NumberFormat::createCurrencyInstance(Locale::getUS(), status));
3084 if (U_FAILURE(status)) {
3085 errln("Could not create number format instance.");
3086 return;
3087 }
3088 logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3089 expectParseCurrency(*fmt, JPY, 1235, "\\u00A51,235");
3090 logln("%s:%d - testing parse of fullwidth yen sign\n", __FILE__, __LINE__);
3091 expectParseCurrency(*fmt, JPY, 1235, "\\uFFE51,235");
3092 logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3093 expectParseCurrency(*fmt, CNY, 1235, "CN\\u00A51,235");
3094
3095 LocalPointer<NumberFormat> fmtTW(
3096 NumberFormat::createCurrencyInstance(Locale::getTaiwan(), status));
3097
3098 logln("%s:%d - testing parse of halfwidth yen sign in TW\n", __FILE__, __LINE__);
3099 expectParseCurrency(*fmtTW, CNY, 1235, "\\u00A51,235");
3100 logln("%s:%d - testing parse of fullwidth yen sign in TW\n", __FILE__, __LINE__);
3101 expectParseCurrency(*fmtTW, CNY, 1235, "\\uFFE51,235");
3102
3103 LocalPointer<NumberFormat> fmtJP(
3104 NumberFormat::createCurrencyInstance(Locale::getJapan(), status));
3105
3106 logln("%s:%d - testing parse of halfwidth yen sign in JP\n", __FILE__, __LINE__);
3107 expectParseCurrency(*fmtJP, JPY, 1235, "\\u00A51,235");
3108 logln("%s:%d - testing parse of fullwidth yen sign in JP\n", __FILE__, __LINE__);
3109 expectParseCurrency(*fmtJP, JPY, 1235, "\\uFFE51,235");
3110
3111 // more..
3112*/
3113}
3114
3115void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text) {
3116 ParsePosition ppos;
3117 UnicodeString utext = ctou(text);
3118 LocalPointer<CurrencyAmount> currencyAmount(fmt.parseCurrency(utext, ppos));
3119 if (!ppos.getIndex()) {
3120 errln(UnicodeString("Parse of ") + utext + " should have succeeded.");
3121 return;
3122 }
3123 UErrorCode status = U_ZERO_ERROR;
3124
3125 char theInfo[100];
3126 sprintf(theInfo, "For locale %s, string \"%s\", currency ",
3127 fmt.getLocale(ULOC_ACTUAL_LOCALE, status).getBaseName(),
3128 text);
3129 u_austrcpy(theInfo+uprv_strlen(theInfo), currency);
3130
3131 char theOperation[100];
3132
3133 uprv_strcpy(theOperation, theInfo);
3134 uprv_strcat(theOperation, ", check amount:");
3135 assertTrue(theOperation, amount == currencyAmount->getNumber().getDouble(status));
3136
3137 uprv_strcpy(theOperation, theInfo);
3138 uprv_strcat(theOperation, ", check currency:");
3139 assertEquals(theOperation, currency, currencyAmount->getISOCurrency());
3140}
3141
3142
3143void NumberFormatTest::TestJB3832(){
3144 const char* localeID = "pt_PT@currency=PTE";
3145 Locale loc(localeID);
3146 UErrorCode status = U_ZERO_ERROR;
3147 UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0\\u200B")); // per cldrbug 7670
3148 UnicodeString s;
3149 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
3150 if(U_FAILURE(status)){
3151 dataerrln("Could not create currency formatter for locale %s - %s", localeID, u_errorName(status));
3152 return;
3153 }
3154 currencyFmt->format(1150.50, s);
3155 if(s!=expected){
3156 errln(UnicodeString("FAIL: Expected: ")+expected
3157 + UnicodeString(" Got: ") + s
3158 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
3159 }
3160 if (U_FAILURE(status)){
3161 errln("FAIL: Status %s", u_errorName(status));
3162 }
3163 delete currencyFmt;
3164}
3165
3166void NumberFormatTest::TestHost()
3167{
3168#if U_PLATFORM_USES_ONLY_WIN32_API
3169 Win32NumberTest::testLocales(this);
3170#endif
3171 Locale loc("en_US@compat=host");
3172 for (UNumberFormatStyle k = UNUM_DECIMAL;
3173 k < UNUM_FORMAT_STYLE_COUNT; k = (UNumberFormatStyle)(k+1)) {
3174 UErrorCode status = U_ZERO_ERROR;
3175 LocalPointer<NumberFormat> full(NumberFormat::createInstance(loc, k, status));
3176 if (!NumberFormat::isStyleSupported(k)) {
3177 if (status != U_UNSUPPORTED_ERROR) {
3178 errln("FAIL: expected style %d to be unsupported - %s",
3179 k, u_errorName(status));
3180 }
3181 continue;
3182 }
3183 if (full.isNull() || U_FAILURE(status)) {
3184 dataerrln("FAIL: Can't create number instance of style %d for host - %s",
3185 k, u_errorName(status));
3186 return;
3187 }
3188 UnicodeString result1;
3189 Formattable number(10.00);
3190 full->format(number, result1, status);
3191 if (U_FAILURE(status)) {
3192 errln("FAIL: Can't format for host");
3193 return;
3194 }
3195 Formattable formattable;
3196 full->parse(result1, formattable, status);
3197 if (U_FAILURE(status)) {
3198 errln("FAIL: Can't parse for host");
3199 return;
3200 }
3201 }
3202}
3203
3204void NumberFormatTest::TestHostClone()
3205{
3206 /*
3207 Verify that a cloned formatter gives the same results
3208 and is useable after the original has been deleted.
3209 */
3210 // This is mainly important on Windows.
3211 UErrorCode status = U_ZERO_ERROR;
3212 Locale loc("en_US@compat=host");
3213 UDate now = Calendar::getNow();
3214 NumberFormat *full = NumberFormat::createInstance(loc, status);
3215 if (full == NULL || U_FAILURE(status)) {
3216 dataerrln("FAIL: Can't create NumberFormat date instance - %s", u_errorName(status));
3217 return;
3218 }
3219 UnicodeString result1;
3220 full->format(now, result1, status);
3221 Format *fullClone = full->clone();
3222 delete full;
3223 full = NULL;
3224
3225 UnicodeString result2;
3226 fullClone->format(now, result2, status);
3227 if (U_FAILURE(status)) {
3228 errln("FAIL: format failure.");
3229 }
3230 if (result1 != result2) {
3231 errln("FAIL: Clone returned different result from non-clone.");
3232 }
3233 delete fullClone;
3234}
3235
3236void NumberFormatTest::TestCurrencyFormat()
3237{
3238 // This test is here to increase code coverage.
3239 UErrorCode status = U_ZERO_ERROR;
3240 MeasureFormat *cloneObj;
3241 UnicodeString str;
3242 Formattable toFormat, result;
3243 static const UChar ISO_CODE[4] = {0x0047, 0x0042, 0x0050, 0};
3244
3245 Locale saveDefaultLocale = Locale::getDefault();
3246 Locale::setDefault( Locale::getUK(), status );
3247 if (U_FAILURE(status)) {
3248 errln("couldn't set default Locale!");
3249 return;
3250 }
3251
3252 MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
3253 Locale::setDefault( saveDefaultLocale, status );
3254 if (U_FAILURE(status)){
3255 dataerrln("FAIL: Status %s", u_errorName(status));
3256 return;
3257 }
3258 cloneObj = measureObj->clone();
3259 if (cloneObj == NULL) {
3260 errln("Clone doesn't work");
3261 return;
3262 }
3263 toFormat.adoptObject(new CurrencyAmount(1234.56, ISO_CODE, status));
3264 measureObj->format(toFormat, str, status);
3265 measureObj->parseObject(str, result, status);
3266 if (U_FAILURE(status)){
3267 errln("FAIL: Status %s", u_errorName(status));
3268 }
3269 if (result != toFormat) {
3270 errln("measureObj does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3271 }
3272 status = U_ZERO_ERROR;
3273 str.truncate(0);
3274 cloneObj->format(toFormat, str, status);
3275 cloneObj->parseObject(str, result, status);
3276 if (U_FAILURE(status)){
3277 errln("FAIL: Status %s", u_errorName(status));
3278 }
3279 if (result != toFormat) {
3280 errln("Clone does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3281 }
3282 if (*measureObj != *cloneObj) {
3283 errln("Cloned object is not equal to the original object");
3284 }
3285 delete measureObj;
3286 delete cloneObj;
3287
3288 status = U_USELESS_COLLATOR_ERROR;
3289 if (MeasureFormat::createCurrencyFormat(status) != NULL) {
3290 errln("createCurrencyFormat should have returned NULL.");
3291 }
3292}
3293
3294/* Port of ICU4J rounding test. */
3295void NumberFormatTest::TestRounding() {
3296 UErrorCode status = U_ZERO_ERROR;
3297 DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3298
3299 if (U_FAILURE(status)) {
3300 dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3301 return;
3302 }
3303
3304 int roundingIncrements[]={1, 2, 5, 20, 50, 100};
3305 int testValues[]={0, 300};
3306
3307 for (int j=0; j<2; j++) {
3308 for (int mode=DecimalFormat::kRoundUp;mode<DecimalFormat::kRoundHalfEven;mode++) {
3309 df->setRoundingMode((DecimalFormat::ERoundingMode)mode);
3310 for (int increment=0; increment<6; increment++) {
3311 double base=testValues[j];
3312 double rInc=roundingIncrements[increment];
3313 checkRounding(df, base, 20, rInc);
3314 rInc=1.000000000/rInc;
3315 checkRounding(df, base, 20, rInc);
3316 }
3317 }
3318 }
3319 delete df;
3320}
3321
3322void NumberFormatTest::TestRoundingPattern() {
3323 UErrorCode status = U_ZERO_ERROR;
3324 struct {
3325 UnicodeString pattern;
3326 double testCase;
3327 UnicodeString expected;
3328 } tests[] = {
3329 { (UnicodeString)"##0.65", 1.234, (UnicodeString)"1.30" },
3330 { (UnicodeString)"#50", 1230, (UnicodeString)"1250" }
3331 };
3332 int32_t numOfTests = UPRV_LENGTHOF(tests);
3333 UnicodeString result;
3334
3335 DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3336 if (U_FAILURE(status)) {
3337 dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3338 return;
3339 }
3340
3341 for (int32_t i = 0; i < numOfTests; i++) {
3342 result.remove();
3343
3344 df->applyPattern(tests[i].pattern, status);
3345 if (U_FAILURE(status)) {
3346 errln("Unable to apply pattern to decimal formatter. - %s", u_errorName(status));
3347 }
3348
3349 df->format(tests[i].testCase, result);
3350
3351 if (result != tests[i].expected) {
3352 errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
3353 }
3354 }
3355
3356 delete df;
3357}
3358
3359void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
3360 df->setRoundingIncrement(increment);
Frank Tangd2858cb2022-04-08 20:34:12 -07003361 assertEquals("Rounding increment round-trip", increment, df->getRoundingIncrement());
Frank Tang3e05d9d2021-11-08 14:04:04 -08003362 double lastParsed=INT32_MIN; //Intger.MIN_VALUE
3363 for (int i=-iterations; i<=iterations;i++) {
3364 double iValue=base+(increment*(i*0.1));
3365 double smallIncrement=0.00000001;
3366 if (iValue!=0) {
3367 smallIncrement*=iValue;
3368 }
3369 //we not only test the value, but some values in a small range around it
3370 lastParsed=checkRound(df, iValue-smallIncrement, lastParsed);
3371 lastParsed=checkRound(df, iValue, lastParsed);
3372 lastParsed=checkRound(df, iValue+smallIncrement, lastParsed);
3373 }
3374}
3375
3376double NumberFormatTest::checkRound(DecimalFormat* df, double iValue, double lastParsed) {
3377 UErrorCode status=U_ZERO_ERROR;
3378 UnicodeString formattedDecimal;
3379 double parsed;
3380 Formattable result;
3381 df->format(iValue, formattedDecimal, status);
3382
3383 if (U_FAILURE(status)) {
3384 errln("Error formatting number.");
3385 }
3386
3387 df->parse(formattedDecimal, result, status);
3388
3389 if (U_FAILURE(status)) {
3390 errln("Error parsing number.");
3391 }
3392
3393 parsed=result.getDouble();
3394
3395 if (lastParsed>parsed) {
3396 errln("Rounding wrong direction! %d > %d", lastParsed, parsed);
3397 }
3398
3399 return lastParsed;
3400}
3401
3402void NumberFormatTest::TestNonpositiveMultiplier() {
3403 UErrorCode status = U_ZERO_ERROR;
3404 DecimalFormatSymbols US(Locale::getUS(), status);
3405 CHECK(status, "DecimalFormatSymbols constructor");
3406 DecimalFormat df(UnicodeString("0"), US, status);
3407 CHECK(status, "DecimalFormat(0)");
3408
3409 // test zero multiplier
3410
3411 int32_t mult = df.getMultiplier();
3412 df.setMultiplier(0);
3413 if (df.getMultiplier() != mult) {
3414 errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
3415 }
3416
3417 // test negative multiplier
3418
3419 df.setMultiplier(-1);
3420 if (df.getMultiplier() != -1) {
3421 errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
3422 return;
3423 }
3424
3425 expect(df, "1122.123", -1122.123);
3426 expect(df, "-1122.123", 1122.123);
3427 expect(df, "1.2", -1.2);
3428 expect(df, "-1.2", 1.2);
3429
Frank Tang1f164ee2022-11-08 12:31:27 -08003430 // Note: the tests with the final parameter of false will not round trip.
Frank Tang3e05d9d2021-11-08 14:04:04 -08003431 // The initial numeric value will format correctly, after the multiplier.
3432 // Parsing the formatted text will be out-of-range for an int64, however.
3433 // The expect() function could be modified to detect this and fall back
3434 // to looking at the decimal parsed value, but it doesn't.
Frank Tang1f164ee2022-11-08 12:31:27 -08003435 expect(df, U_INT64_MIN, "9223372036854775808", false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08003436 expect(df, U_INT64_MIN+1, "9223372036854775807");
3437 expect(df, (int64_t)-123, "123");
3438 expect(df, (int64_t)123, "-123");
3439 expect(df, U_INT64_MAX-1, "-9223372036854775806");
3440 expect(df, U_INT64_MAX, "-9223372036854775807");
3441
3442 df.setMultiplier(-2);
3443 expect(df, -(U_INT64_MIN/2)-1, "-9223372036854775806");
3444 expect(df, -(U_INT64_MIN/2), "-9223372036854775808");
Frank Tang1f164ee2022-11-08 12:31:27 -08003445 expect(df, -(U_INT64_MIN/2)+1, "-9223372036854775810", false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08003446
3447 df.setMultiplier(-7);
Frank Tang1f164ee2022-11-08 12:31:27 -08003448 expect(df, -(U_INT64_MAX/7)-1, "9223372036854775814", false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08003449 expect(df, -(U_INT64_MAX/7), "9223372036854775807");
3450 expect(df, -(U_INT64_MAX/7)+1, "9223372036854775800");
3451
3452 // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
3453 // (right now the big numbers get turned into doubles and lose tons of accuracy)
3454 //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
3455 //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
3456 //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
3457 //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
3458
3459 // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
3460 //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3461 //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3462 //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3463 //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3464}
3465
3466typedef struct {
3467 const char * stringToParse;
3468 int parsedPos;
3469 int errorIndex;
3470 UBool lenient;
3471} TestSpaceParsingItem;
3472
3473void
3474NumberFormatTest::TestSpaceParsing() {
3475 // the data are:
3476 // the string to be parsed, parsed position, parsed error index
3477 const TestSpaceParsingItem DATA[] = {
Frank Tang1f164ee2022-11-08 12:31:27 -08003478 {"$124", 4, -1, false},
3479 {"$124 $124", 4, -1, false},
3480 {"$124 ", 4, -1, false},
3481 {"$ 124 ", 0, 1, false},
3482 {"$\\u00A0124 ", 5, -1, false},
3483 {" $ 124 ", 0, 0, false},
3484 {"124$", 0, 4, false},
3485 {"124 $", 0, 3, false},
3486 {"$124", 4, -1, true},
3487 {"$124 $124", 4, -1, true},
3488 {"$124 ", 4, -1, true},
3489 {"$ 124 ", 5, -1, true},
3490 {"$\\u00A0124 ", 5, -1, true},
3491 {" $ 124 ", 6, -1, true},
3492 {"124$", 4, -1, true},
3493 {"124$", 4, -1, true},
3494 {"124 $", 5, -1, true},
3495 {"124 $", 5, -1, true},
Frank Tang3e05d9d2021-11-08 14:04:04 -08003496 };
3497 UErrorCode status = U_ZERO_ERROR;
3498 Locale locale("en_US");
3499 NumberFormat* foo = NumberFormat::createCurrencyInstance(locale, status);
3500
3501 if (U_FAILURE(status)) {
3502 delete foo;
3503 return;
3504 }
3505 for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3506 ParsePosition parsePosition(0);
3507 UnicodeString stringToBeParsed = ctou(DATA[i].stringToParse);
3508 int parsedPosition = DATA[i].parsedPos;
3509 int errorIndex = DATA[i].errorIndex;
3510 foo->setLenient(DATA[i].lenient);
3511 Formattable result;
3512 foo->parse(stringToBeParsed, result, parsePosition);
3513 logln("Parsing: " + stringToBeParsed);
3514 if (parsePosition.getIndex() != parsedPosition ||
3515 parsePosition.getErrorIndex() != errorIndex) {
3516 errln("FAILED parse " + stringToBeParsed + "; lenient: " + DATA[i].lenient + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
3517 }
3518 if (parsePosition.getErrorIndex() == -1 &&
3519 result.getType() == Formattable::kLong &&
3520 result.getLong() != 124) {
3521 errln("FAILED parse " + stringToBeParsed + "; wrong number, expect: 124, got " + result.getLong());
3522 }
3523 }
3524 delete foo;
3525}
3526
3527/**
3528 * Test using various numbering systems and numbering system keyword.
3529 */
3530typedef struct {
3531 const char *localeName;
3532 double value;
3533 UBool isRBNF;
3534 const char *expectedResult;
3535} TestNumberingSystemItem;
3536
3537void NumberFormatTest::TestNumberingSystems() {
3538
3539 const TestNumberingSystemItem DATA[] = {
Frank Tang1f164ee2022-11-08 12:31:27 -08003540 { "en_US@numbers=thai", 1234.567, false, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" },
3541 { "en_US@numbers=hebr", 5678.0, true, "\\u05D4\\u05F3\\u05EA\\u05E8\\u05E2\\u05F4\\u05D7" },
3542 { "en_US@numbers=arabext", 1234.567, false, "\\u06F1\\u066c\\u06F2\\u06F3\\u06F4\\u066b\\u06F5\\u06F6\\u06F7" },
3543 { "ar_EG", 1234.567, false, "\\u0661\\u066C\\u0662\\u0663\\u0664\\u066b\\u0665\\u0666\\u0667" },
3544 { "th_TH@numbers=traditional", 1234.567, false, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" }, // fall back to native per TR35
3545 { "ar_MA", 1234.567, false, "1.234,567" },
3546 { "en_US@numbers=hanidec", 1234.567, false, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3547 { "ta_IN@numbers=native", 1234.567, false, "\\u0BE7,\\u0BE8\\u0BE9\\u0BEA.\\u0BEB\\u0BEC\\u0BED" },
3548 { "ta_IN@numbers=traditional", 1235.0, true, "\\u0BF2\\u0BE8\\u0BF1\\u0BE9\\u0BF0\\u0BEB" },
3549 { "ta_IN@numbers=finance", 1234.567, false, "1,234.567" }, // fall back to default per TR35
3550 { "zh_TW@numbers=native", 1234.567, false, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3551 { "zh_TW@numbers=traditional", 1234.567, true, "\\u4E00\\u5343\\u4E8C\\u767E\\u4E09\\u5341\\u56DB\\u9EDE\\u4E94\\u516D\\u4E03" },
3552 { "zh_TW@numbers=finance", 1234.567, true, "\\u58F9\\u4EDF\\u8CB3\\u4F70\\u53C3\\u62FE\\u8086\\u9EDE\\u4F0D\\u9678\\u67D2" },
3553 { NULL, 0, false, NULL }
Frank Tang3e05d9d2021-11-08 14:04:04 -08003554 };
3555
3556 UErrorCode ec;
3557
3558 const TestNumberingSystemItem *item;
3559 for (item = DATA; item->localeName != NULL; item++) {
3560 ec = U_ZERO_ERROR;
3561 Locale loc = Locale::createFromName(item->localeName);
3562
3563 NumberFormat *origFmt = NumberFormat::createInstance(loc,ec);
3564 if (U_FAILURE(ec)) {
3565 dataerrln("FAIL: getInstance(%s) - %s", item->localeName, u_errorName(ec));
3566 continue;
3567 }
3568 // Clone to test ticket #10682
3569 NumberFormat *fmt = origFmt->clone();
3570 delete origFmt;
3571
3572
3573 if (item->isRBNF) {
3574 expect3(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3575 } else {
3576 expect2(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3577 }
3578 delete fmt;
3579 }
3580
3581
3582 // Test bogus keyword value
3583 ec = U_ZERO_ERROR;
3584 Locale loc4 = Locale::createFromName("en_US@numbers=foobar");
3585 NumberFormat* fmt4= NumberFormat::createInstance(loc4, ec);
3586 if ( ec != U_UNSUPPORTED_ERROR ) {
3587 errln("FAIL: getInstance(en_US@numbers=foobar) should have returned U_UNSUPPORTED_ERROR");
3588 delete fmt4;
3589 }
3590
3591 ec = U_ZERO_ERROR;
3592 NumberingSystem *ns = NumberingSystem::createInstance(ec);
3593 if (U_FAILURE(ec)) {
3594 dataerrln("FAIL: NumberingSystem::createInstance(ec); - %s", u_errorName(ec));
3595 }
3596
3597 if ( ns != NULL ) {
3598 ns->getDynamicClassID();
3599 ns->getStaticClassID();
3600 } else {
3601 errln("FAIL: getInstance() returned NULL.");
3602 }
3603
3604 NumberingSystem *ns1 = new NumberingSystem(*ns);
3605 if (ns1 == NULL) {
3606 errln("FAIL: NumberSystem copy constructor returned NULL.");
3607 }
3608
3609 delete ns1;
3610 delete ns;
3611
3612}
3613
3614
3615void
3616NumberFormatTest::TestMultiCurrencySign() {
3617 const char* DATA[][6] = {
3618 // the fields in the following test are:
3619 // locale,
3620 // currency pattern (with negative pattern),
3621 // currency number to be formatted,
3622 // currency format using currency symbol name, such as "$" for USD,
3623 // currency format using currency ISO name, such as "USD",
3624 // currency format using plural name, such as "US dollars".
3625 // for US locale
3626 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1234.56", "$1,234.56", "USD\\u00A01,234.56", "US dollars\\u00A01,234.56"},
3627 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD\\u00A01,234.56", "-US dollars\\u00A01,234.56"},
3628 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD\\u00A01.00", "US dollars\\u00A01.00"},
3629 // for CHINA locale
3630 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\u00A51,234.56", "CNY\\u00A01,234.56", "\\u4EBA\\u6C11\\u5E01\\u00A01,234.56"},
3631 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\u00A51,234.56)", "(CNY\\u00A01,234.56)", "(\\u4EBA\\u6C11\\u5E01\\u00A01,234.56)"},
3632 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\u00A51.00", "CNY\\u00A01.00", "\\u4EBA\\u6C11\\u5E01\\u00A01.00"}
3633 };
3634
3635 const UChar doubleCurrencySign[] = {0xA4, 0xA4, 0};
3636 UnicodeString doubleCurrencyStr(doubleCurrencySign);
3637 const UChar tripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
3638 UnicodeString tripleCurrencyStr(tripleCurrencySign);
3639
3640 for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3641 const char* locale = DATA[i][0];
3642 UnicodeString pat = ctou(DATA[i][1]);
3643 double numberToBeFormat = atof(DATA[i][2]);
3644 UErrorCode status = U_ZERO_ERROR;
3645 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale(locale), status);
3646 if (U_FAILURE(status)) {
3647 delete sym;
3648 continue;
3649 }
3650 for (int j=1; j<=3; ++j) {
3651 // j represents the number of currency sign in the pattern.
3652 if (j == 2) {
3653 pat = pat.findAndReplace(ctou("\\u00A4"), doubleCurrencyStr);
3654 } else if (j == 3) {
3655 pat = pat.findAndReplace(ctou("\\u00A4\\u00A4"), tripleCurrencyStr);
3656 }
3657
3658 DecimalFormat* fmt = new DecimalFormat(pat, new DecimalFormatSymbols(*sym), status);
3659 if (U_FAILURE(status)) {
3660 errln("FAILED init DecimalFormat ");
3661 delete fmt;
3662 continue;
3663 }
3664 UnicodeString s;
3665 ((NumberFormat*) fmt)->format(numberToBeFormat, s);
3666 // DATA[i][3] is the currency format result using a
3667 // single currency sign.
3668 // DATA[i][4] is the currency format result using
3669 // double currency sign.
3670 // DATA[i][5] is the currency format result using
3671 // triple currency sign.
3672 // DATA[i][j+2] is the currency format result using
3673 // 'j' number of currency sign.
3674 UnicodeString currencyFormatResult = ctou(DATA[i][2+j]);
3675 if (s.compare(currencyFormatResult)) {
3676 errln("FAIL format: Expected " + currencyFormatResult + "; Got " + s);
3677 }
3678 // mix style parsing
3679 for (int k=3; k<=5; ++k) {
3680 // DATA[i][3] is the currency format result using a
3681 // single currency sign.
3682 // DATA[i][4] is the currency format result using
3683 // double currency sign.
3684 // DATA[i][5] is the currency format result using
3685 // triple currency sign.
3686 UnicodeString oneCurrencyFormat = ctou(DATA[i][k]);
3687 UErrorCode status = U_ZERO_ERROR;
3688 Formattable parseRes;
3689 fmt->parse(oneCurrencyFormat, parseRes, status);
3690 if (U_FAILURE(status) ||
3691 (parseRes.getType() == Formattable::kDouble &&
3692 parseRes.getDouble() != numberToBeFormat) ||
3693 (parseRes.getType() == Formattable::kLong &&
3694 parseRes.getLong() != numberToBeFormat)) {
3695 errln("FAILED parse " + oneCurrencyFormat + "; (i, j, k): " +
3696 i + ", " + j + ", " + k);
3697 }
3698 }
3699 delete fmt;
3700 }
3701 delete sym;
3702 }
3703}
3704
3705
3706void
3707NumberFormatTest::TestCurrencyFormatForMixParsing() {
3708 UErrorCode status = U_ZERO_ERROR;
3709 MeasureFormat* curFmt = MeasureFormat::createCurrencyFormat(Locale("en_US"), status);
3710 if (U_FAILURE(status)) {
3711 delete curFmt;
3712 return;
3713 }
3714 const char* formats[] = {
3715 "$1,234.56", // string to be parsed
3716 "USD1,234.56",
3717 "US dollars1,234.56",
3718 // "1,234.56 US dollars" // Fails in 62 because currency format is not compatible with pattern.
3719 };
3720 const CurrencyAmount* curramt = NULL;
3721 for (uint32_t i = 0; i < UPRV_LENGTHOF(formats); ++i) {
3722 UnicodeString stringToBeParsed = ctou(formats[i]);
3723 logln(UnicodeString("stringToBeParsed: ") + stringToBeParsed);
3724 Formattable result;
3725 UErrorCode status = U_ZERO_ERROR;
3726 curFmt->parseObject(stringToBeParsed, result, status);
3727 if (U_FAILURE(status)) {
3728 errln("FAIL: measure format parsing: '%s' ec: %s", formats[i], u_errorName(status));
3729 } else if (result.getType() != Formattable::kObject ||
3730 (curramt = dynamic_cast<const CurrencyAmount*>(result.getObject())) == NULL ||
3731 curramt->getNumber().getDouble() != 1234.56 ||
3732 UnicodeString(curramt->getISOCurrency()).compare(ISO_CURRENCY_USD)
3733 ) {
3734 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number ");
3735 if (curramt->getNumber().getDouble() != 1234.56) {
3736 errln((UnicodeString)"wong number, expect: 1234.56" + ", got: " + curramt->getNumber().getDouble());
3737 }
3738 if (curramt->getISOCurrency() != ISO_CURRENCY_USD) {
3739 errln((UnicodeString)"wong currency, expect: USD" + ", got: " + curramt->getISOCurrency());
3740 }
3741 }
3742 }
3743 delete curFmt;
3744}
3745
3746
3747/** Starting in ICU 62, strict mode is actually strict with currency formats. */
3748void NumberFormatTest::TestMismatchedCurrencyFormatFail() {
3749 IcuTestErrorCode status(*this, "TestMismatchedCurrencyFormatFail");
3750 LocalPointer<DecimalFormat> df(
3751 dynamic_cast<DecimalFormat*>(DecimalFormat::createCurrencyInstance("en", status)), status);
3752 if (!assertSuccess("createCurrencyInstance() failed.", status, true, __FILE__, __LINE__)) {return;}
3753 UnicodeString pattern;
3754 assertEquals("Test assumes that currency sign is at the beginning",
3755 u"\u00A4#,##0.00",
3756 df->toPattern(pattern));
3757 // Should round-trip on the correct currency format:
3758 expect2(*df, 1.23, u"\u00A41.23");
3759 df->setCurrency(u"EUR", status);
3760 expect2(*df, 1.23, u"\u20AC1.23");
3761 // Should parse with currency in the wrong place in lenient mode
Frank Tang1f164ee2022-11-08 12:31:27 -08003762 df->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08003763 expect(*df, u"1.23\u20AC", 1.23);
3764 expectParseCurrency(*df, u"EUR", 1.23, "1.23\\u20AC");
3765 // Should NOT parse with currency in the wrong place in STRICT mode
Frank Tang1f164ee2022-11-08 12:31:27 -08003766 df->setLenient(false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08003767 {
3768 Formattable result;
3769 ErrorCode failStatus;
3770 df->parse(u"1.23\u20AC", result, failStatus);
3771 assertEquals("Should fail to parse", U_INVALID_FORMAT_ERROR, failStatus);
3772 }
3773 {
3774 ParsePosition ppos;
3775 df->parseCurrency(u"1.23\u20AC", ppos);
3776 assertEquals("Should fail to parse currency", 0, ppos.getIndex());
3777 }
3778}
3779
3780
3781void
3782NumberFormatTest::TestDecimalFormatCurrencyParse() {
3783 // Locale.US
3784 UErrorCode status = U_ZERO_ERROR;
3785 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale("en_US"), status);
3786 if (U_FAILURE(status)) {
3787 delete sym;
3788 return;
3789 }
3790 UnicodeString pat;
3791 UChar currency = 0x00A4;
3792 // "\xA4#,##0.00;-\xA4#,##0.00"
3793 pat.append(currency).append(currency).append(currency).append("#,##0.00;-").append(currency).append(currency).append(currency).append("#,##0.00");
3794 DecimalFormat* fmt = new DecimalFormat(pat, sym, status);
3795 if (U_FAILURE(status)) {
3796 delete fmt;
3797 errln("failed to new DecimalFormat in TestDecimalFormatCurrencyParse");
3798 return;
3799 }
3800 const char* DATA[][2] = {
3801 // the data are:
3802 // string to be parsed, the parsed result (number)
3803 {"$1.00", "1"},
3804 {"USD1.00", "1"},
3805 {"1.00 US dollar", "1"},
3806 {"$1,234.56", "1234.56"},
3807 {"USD1,234.56", "1234.56"},
3808 {"1,234.56 US dollar", "1234.56"},
3809 };
3810 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
Frank Tang1f164ee2022-11-08 12:31:27 -08003811 fmt->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08003812 for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3813 UnicodeString stringToBeParsed = ctou(DATA[i][0]);
3814 double parsedResult = atof(DATA[i][1]);
3815 UErrorCode status = U_ZERO_ERROR;
3816 Formattable result;
3817 fmt->parse(stringToBeParsed, result, status);
3818 logln((UnicodeString)"Input: " + stringToBeParsed + "; output: " + result.getDouble(status));
3819 if (U_FAILURE(status) ||
3820 (result.getType() == Formattable::kDouble &&
3821 result.getDouble() != parsedResult) ||
3822 (result.getType() == Formattable::kLong &&
3823 result.getLong() != parsedResult)) {
3824 errln((UnicodeString)"FAIL parse: Expected " + parsedResult);
3825 }
3826 }
3827 delete fmt;
3828}
3829
3830
3831void
3832NumberFormatTest::TestCurrencyIsoPluralFormat() {
3833 static const char* DATA[][6] = {
3834 // the data are:
3835 // locale,
3836 // currency amount to be formatted,
3837 // currency ISO code to be formatted,
3838 // format result using CURRENCYSTYLE,
3839 // format result using ISOCURRENCYSTYLE,
3840 // format result using PLURALCURRENCYSTYLE,
3841
3842 {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3843 {"en_US", "1234.56", "USD", "$1,234.56", "USD\\u00A01,234.56", "1,234.56 US dollars"},
3844 {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD\\u00A01,234.56", "-1,234.56 US dollars"},
3845 {"zh_CN", "1", "USD", "US$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7F8E\\u5143"},
3846 {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD\\u00A01,234.56", "1,234.56\\u00A0\\u7F8E\\u5143"},
3847 {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A01.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3848 {"zh_CN", "1234.56", "CNY", "\\u00A51,234.56", "CNY\\u00A01,234.56", "1,234.56\\u00A0\\u4EBA\\u6C11\\u5E01"},
3849 {"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"},
3850 {"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"},
3851 {"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"},
3852 // test locale without currency information
3853 {"root", "-1.23", "USD", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"},
3854 // test choice format
3855 {"es_AR", "1", "INR", "INR\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"},
3856 };
3857 static const UNumberFormatStyle currencyStyles[] = {
3858 UNUM_CURRENCY,
3859 UNUM_CURRENCY_ISO,
3860 UNUM_CURRENCY_PLURAL
3861 };
3862
3863 for (int32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3864 const char* localeString = DATA[i][0];
3865 double numberToBeFormat = atof(DATA[i][1]);
3866 const char* currencyISOCode = DATA[i][2];
3867 logln(UnicodeString(u"Locale: ") + localeString + "; amount: " + numberToBeFormat);
3868 Locale locale(localeString);
3869 for (int32_t kIndex = 0; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3870 UNumberFormatStyle k = currencyStyles[kIndex];
3871 logln(UnicodeString(u"UNumberFormatStyle: ") + k);
3872 UErrorCode status = U_ZERO_ERROR;
3873 NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3874 if (U_FAILURE(status)) {
3875 delete numFmt;
3876 dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3877 continue;
3878 }
3879 UChar currencyCode[4];
3880 u_charsToUChars(currencyISOCode, currencyCode, 4);
3881 numFmt->setCurrency(currencyCode, status);
3882 if (U_FAILURE(status)) {
3883 delete numFmt;
3884 errln((UnicodeString)"can not set currency:" + currencyISOCode);
3885 continue;
3886 }
3887
3888 UnicodeString strBuf;
3889 numFmt->format(numberToBeFormat, strBuf);
3890 int resultDataIndex = 3 + kIndex;
3891 // DATA[i][resultDataIndex] is the currency format result
3892 // using 'k' currency style.
3893 UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
3894 if (strBuf.compare(formatResult)) {
3895 errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
3896 }
3897 // test parsing, and test parsing for all currency formats.
3898 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
Frank Tang1f164ee2022-11-08 12:31:27 -08003899 numFmt->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08003900 for (int j = 3; j < 6; ++j) {
3901 // DATA[i][3] is the currency format result using
3902 // CURRENCYSTYLE formatter.
3903 // DATA[i][4] is the currency format result using
3904 // ISOCURRENCYSTYLE formatter.
3905 // DATA[i][5] is the currency format result using
3906 // PLURALCURRENCYSTYLE formatter.
3907 UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
3908 UErrorCode status = U_ZERO_ERROR;
3909 Formattable parseResult;
3910 numFmt->parse(oneCurrencyFormatResult, parseResult, status);
3911 if (U_FAILURE(status) ||
3912 (parseResult.getType() == Formattable::kDouble &&
3913 parseResult.getDouble() != numberToBeFormat) ||
3914 (parseResult.getType() == Formattable::kLong &&
3915 parseResult.getLong() != numberToBeFormat)) {
3916 errln((UnicodeString)"FAIL: getCurrencyFormat of locale " +
3917 localeString + " failed roundtripping the number");
3918 if (parseResult.getType() == Formattable::kDouble) {
3919 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getDouble());
3920 } else {
3921 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getLong());
3922 }
3923 }
3924 }
3925 delete numFmt;
3926 }
3927 }
3928}
3929
3930void
3931NumberFormatTest::TestCurrencyParsing() {
3932 static const char* DATA[][6] = {
3933 // the data are:
3934 // locale,
3935 // currency amount to be formatted,
3936 // currency ISO code to be formatted,
3937 // format result using CURRENCYSTYLE,
3938 // format result using ISOCURRENCYSTYLE,
3939 // format result using PLURALCURRENCYSTYLE,
3940 {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3941 {"pa_IN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\u0a2f\\u0a42.\\u0a10\\u0a38. \\u0a21\\u0a3e\\u0a32\\u0a30"},
3942 {"es_AR", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 d\\u00f3lar estadounidense"},
3943 {"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"},
3944 {"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"},
3945 {"he_IL", "1", "USD", "\\u200f1.00\\u00a0$", "\\u200f1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
3946 {"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 ameri\\u010Dkih dolara"},
3947 {"id_ID", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 Dolar Amerika Serikat"},
3948 {"it_IT", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 dollari statunitensi"},
3949 {"ko_KR", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
3950 {"ja_JP", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7c73\\u30c9\\u30eb"},
3951 {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A001.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3952 {"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3953 {"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3954 {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1 \\u65E5\\u5713"},
3955 {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3956 // ICU 62 requires #parseCurrency() to recognize variants when parsing
3957 // {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3958 {"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"}
3959 };
3960 static const UNumberFormatStyle currencyStyles[] = {
3961 UNUM_CURRENCY,
3962 UNUM_CURRENCY_ISO,
3963 UNUM_CURRENCY_PLURAL
3964 };
3965 static const char* currencyStyleNames[] = {
3966 "UNUM_CURRENCY",
3967 "UNUM_CURRENCY_ISO",
3968 "UNUM_CURRENCY_PLURAL"
3969 };
3970
3971#ifdef NUMFMTST_CACHE_DEBUG
3972int deadloop = 0;
3973for (;;) {
3974 printf("loop: %d\n", deadloop++);
3975#endif
3976 for (uint32_t i=0; i< UPRV_LENGTHOF(DATA); ++i) { /* i = test case # - should be i=0*/
3977 for (int32_t kIndex = 2; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3978 UNumberFormatStyle k = currencyStyles[kIndex]; /* k = style */
3979 const char* localeString = DATA[i][0];
3980 double numberToBeFormat = atof(DATA[i][1]);
3981 const char* currencyISOCode = DATA[i][2];
3982 Locale locale(localeString);
3983 UErrorCode status = U_ZERO_ERROR;
3984 NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3985 logln("#%d NumberFormat(%s, %s) Currency=%s\n",
3986 i, localeString, currencyStyleNames[kIndex],
3987 currencyISOCode);
3988
3989 if (U_FAILURE(status)) {
3990 delete numFmt;
3991 dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3992 continue;
3993 }
3994 UChar currencyCode[4];
3995 u_charsToUChars(currencyISOCode, currencyCode, 4);
3996 numFmt->setCurrency(currencyCode, status);
3997 if (U_FAILURE(status)) {
3998 delete numFmt;
3999 errln((UnicodeString)"can not set currency:" + currencyISOCode);
4000 continue;
4001 }
4002
4003 UnicodeString strBuf;
4004 numFmt->format(numberToBeFormat, strBuf);
4005 int resultDataIndex = 3 + kIndex;
4006 // DATA[i][resultDataIndex] is the currency format result
4007 // using 'k' currency style.
4008 UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
4009 if (strBuf.compare(formatResult)) {
4010 errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
4011 }
4012 // test parsing, and test parsing for all currency formats.
4013 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
Frank Tang1f164ee2022-11-08 12:31:27 -08004014 numFmt->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08004015 for (int j = 3; j < 6; ++j) {
4016 // DATA[i][3] is the currency format result using
4017 // CURRENCYSTYLE formatter.
4018 // DATA[i][4] is the currency format result using
4019 // ISOCURRENCYSTYLE formatter.
4020 // DATA[i][5] is the currency format result using
4021 // PLURALCURRENCYSTYLE formatter.
4022 UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
4023 UErrorCode status = U_ZERO_ERROR;
4024 Formattable parseResult;
4025 logln("parse(%s)", DATA[i][j]);
4026 numFmt->parse(oneCurrencyFormatResult, parseResult, status);
4027 if (U_FAILURE(status) ||
4028 (parseResult.getType() == Formattable::kDouble &&
4029 parseResult.getDouble() != numberToBeFormat) ||
4030 (parseResult.getType() == Formattable::kLong &&
4031 parseResult.getLong() != numberToBeFormat)) {
4032 errln((UnicodeString)"FAIL: NumberFormat(" + localeString +", " + currencyStyleNames[kIndex] +
4033 "), Currency="+currencyISOCode+", parse("+DATA[i][j]+") returned error " + (UnicodeString)u_errorName(status)+". Testcase: data[" + i + "][" + currencyStyleNames[j-3] +"="+j+"]");
4034 if (parseResult.getType() == Formattable::kDouble) {
4035 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (double): " +parseResult.getDouble());
4036 } else {
4037 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (long): " +parseResult.getLong());
4038 }
4039 errln((UnicodeString)" round-trip would be: " + strBuf);
4040 }
4041 }
4042 delete numFmt;
4043 }
4044 }
4045#ifdef NUMFMTST_CACHE_DEBUG
4046}
4047#endif
4048}
4049
4050
4051void
4052NumberFormatTest::TestParseCurrencyInUCurr() {
4053 const char* DATA[] = {
4054 "1.00 US DOLLAR", // case in-sensitive
4055 "$1.00",
4056 "USD1.00",
4057 "usd1.00", // case in-sensitive: #13696
4058 "US dollar1.00",
4059 "US dollars1.00",
4060 "$1.00",
4061 "A$1.00",
4062 "ADP1.00",
4063 "ADP1.00",
4064 "AED1.00",
4065 "AED1.00",
4066 "AFA1.00",
4067 "AFA1.00",
4068 "AFN1.00",
4069 "ALL1.00",
4070 "AMD1.00",
4071 "ANG1.00",
4072 "AOA1.00",
4073 "AOK1.00",
4074 "AOK1.00",
4075 "AON1.00",
4076 "AON1.00",
4077 "AOR1.00",
4078 "AOR1.00",
4079 "ARS1.00",
4080 "ARA1.00",
4081 "ARA1.00",
4082 "ARP1.00",
4083 "ARP1.00",
4084 "ARS1.00",
4085 "ATS1.00",
4086 "ATS1.00",
4087 "AUD1.00",
4088 "AWG1.00",
4089 "AZM1.00",
4090 "AZM1.00",
4091 "AZN1.00",
4092 "Afghan Afghani (1927\\u20132002)1.00",
4093 "Afghan afghani (1927\\u20132002)1.00",
4094 "Afghan Afghani1.00",
4095 "Afghan Afghanis1.00",
4096 "Albanian Lek1.00",
4097 "Albanian lek1.00",
4098 "Albanian lek\\u00eb1.00",
4099 "Algerian Dinar1.00",
4100 "Algerian dinar1.00",
4101 "Algerian dinars1.00",
4102 "Andorran Peseta1.00",
4103 "Andorran peseta1.00",
4104 "Andorran pesetas1.00",
4105 "Angolan Kwanza (1977\\u20131991)1.00",
4106 "Angolan Readjusted Kwanza (1995\\u20131999)1.00",
4107 "Angolan Kwanza1.00",
4108 "Angolan New Kwanza (1990\\u20132000)1.00",
4109 "Angolan kwanza (1977\\u20131991)1.00",
4110 "Angolan readjusted kwanza (1995\\u20131999)1.00",
4111 "Angolan kwanza1.00",
4112 "Angolan kwanzas (1977\\u20131991)1.00",
4113 "Angolan readjusted kwanzas (1995\\u20131999)1.00",
4114 "Angolan kwanzas1.00",
4115 "Angolan new kwanza (1990\\u20132000)1.00",
4116 "Angolan new kwanzas (1990\\u20132000)1.00",
4117 "Argentine Austral1.00",
4118 "Argentine Peso (1983\\u20131985)1.00",
4119 "Argentine Peso1.00",
4120 "Argentine austral1.00",
4121 "Argentine australs1.00",
4122 "Argentine peso (1983\\u20131985)1.00",
4123 "Argentine peso1.00",
4124 "Argentine pesos (1983\\u20131985)1.00",
4125 "Argentine pesos1.00",
4126 "Armenian Dram1.00",
4127 "Armenian dram1.00",
4128 "Armenian drams1.00",
4129 "Aruban Florin1.00",
4130 "Aruban florin1.00",
4131 "Australian Dollar1.00",
4132 "Australian dollar1.00",
4133 "Australian dollars1.00",
4134 "Austrian Schilling1.00",
4135 "Austrian schilling1.00",
4136 "Austrian schillings1.00",
4137 "Azerbaijani Manat (1993\\u20132006)1.00",
4138 "Azerbaijani Manat1.00",
4139 "Azerbaijani manat (1993\\u20132006)1.00",
4140 "Azerbaijani manat1.00",
4141 "Azerbaijani manats (1993\\u20132006)1.00",
4142 "Azerbaijani manats1.00",
4143 "BAD1.00",
4144 "BAD1.00",
4145 "BAM1.00",
4146 "BBD1.00",
4147 "BDT1.00",
4148 "BEC1.00",
4149 "BEC1.00",
4150 "BEF1.00",
4151 "BEL1.00",
4152 "BEL1.00",
4153 "BGL1.00",
4154 "BGN1.00",
4155 "BGN1.00",
4156 "BHD1.00",
4157 "BIF1.00",
4158 "BMD1.00",
4159 "BND1.00",
4160 "BOB1.00",
4161 "BOP1.00",
4162 "BOP1.00",
4163 "BOV1.00",
4164 "BOV1.00",
4165 "BRB1.00",
4166 "BRB1.00",
4167 "BRC1.00",
4168 "BRC1.00",
4169 "BRE1.00",
4170 "BRE1.00",
4171 "BRL1.00",
4172 "BRN1.00",
4173 "BRN1.00",
4174 "BRR1.00",
4175 "BRR1.00",
4176 "BSD1.00",
4177 "BSD1.00",
4178 "BTN1.00",
4179 "BUK1.00",
4180 "BUK1.00",
4181 "BWP1.00",
4182 "BYB1.00",
4183 "BYB1.00",
4184 "BYR1.00",
4185 "BZD1.00",
4186 "Bahamian Dollar1.00",
4187 "Bahamian dollar1.00",
4188 "Bahamian dollars1.00",
4189 "Bahraini Dinar1.00",
4190 "Bahraini dinar1.00",
4191 "Bahraini dinars1.00",
4192 "Bangladeshi Taka1.00",
4193 "Bangladeshi taka1.00",
4194 "Bangladeshi takas1.00",
4195 "Barbadian Dollar1.00",
4196 "Barbadian dollar1.00",
4197 "Barbadian dollars1.00",
4198 "Belarusian Ruble (1994\\u20131999)1.00",
4199 "Belarusian Ruble1.00",
4200 "Belarusian ruble (1994\\u20131999)1.00",
4201 "Belarusian rubles (1994\\u20131999)1.00",
4202 "Belarusian ruble1.00",
4203 "Belarusian rubles1.00",
4204 "Belgian Franc (convertible)1.00",
4205 "Belgian Franc (financial)1.00",
4206 "Belgian Franc1.00",
4207 "Belgian franc (convertible)1.00",
4208 "Belgian franc (financial)1.00",
4209 "Belgian franc1.00",
4210 "Belgian francs (convertible)1.00",
4211 "Belgian francs (financial)1.00",
4212 "Belgian francs1.00",
4213 "Belize Dollar1.00",
4214 "Belize dollar1.00",
4215 "Belize dollars1.00",
4216 "Bermudan Dollar1.00",
4217 "Bermudan dollar1.00",
4218 "Bermudan dollars1.00",
4219 "Bhutanese Ngultrum1.00",
4220 "Bhutanese ngultrum1.00",
4221 "Bhutanese ngultrums1.00",
4222 "Bolivian Mvdol1.00",
4223 "Bolivian Peso1.00",
4224 "Bolivian mvdol1.00",
4225 "Bolivian mvdols1.00",
4226 "Bolivian peso1.00",
4227 "Bolivian pesos1.00",
4228 "Bolivian Boliviano1.00",
4229 "Bolivian Boliviano1.00",
4230 "Bolivian Bolivianos1.00",
4231 "Bosnia-Herzegovina Convertible Mark1.00",
4232 "Bosnia-Herzegovina Dinar (1992\\u20131994)1.00",
4233 "Bosnia-Herzegovina convertible mark1.00",
4234 "Bosnia-Herzegovina convertible marks1.00",
4235 "Bosnia-Herzegovina dinar (1992\\u20131994)1.00",
4236 "Bosnia-Herzegovina dinars (1992\\u20131994)1.00",
4237 "Botswanan Pula1.00",
4238 "Botswanan pula1.00",
4239 "Botswanan pulas1.00",
4240 "Brazilian New Cruzado (1989\\u20131990)1.00",
4241 "Brazilian Cruzado (1986\\u20131989)1.00",
4242 "Brazilian Cruzeiro (1990\\u20131993)1.00",
4243 "Brazilian New Cruzeiro (1967\\u20131986)1.00",
4244 "Brazilian Cruzeiro (1993\\u20131994)1.00",
4245 "Brazilian Real1.00",
4246 "Brazilian new cruzado (1989\\u20131990)1.00",
4247 "Brazilian new cruzados (1989\\u20131990)1.00",
4248 "Brazilian cruzado (1986\\u20131989)1.00",
4249 "Brazilian cruzados (1986\\u20131989)1.00",
4250 "Brazilian cruzeiro (1990\\u20131993)1.00",
4251 "Brazilian new cruzeiro (1967\\u20131986)1.00",
4252 "Brazilian cruzeiro (1993\\u20131994)1.00",
4253 "Brazilian cruzeiros (1990\\u20131993)1.00",
4254 "Brazilian new cruzeiros (1967\\u20131986)1.00",
4255 "Brazilian cruzeiros (1993\\u20131994)1.00",
4256 "Brazilian real1.00",
4257 "Brazilian reals1.00",
4258 "British Pound1.00",
4259 "British pound1.00",
4260 "British pounds1.00",
4261 "Brunei Dollar1.00",
4262 "Brunei dollar1.00",
4263 "Brunei dollars1.00",
4264 "Bulgarian Hard Lev1.00",
4265 "Bulgarian Lev1.00",
4266 "Bulgarian Leva1.00",
4267 "Bulgarian hard lev1.00",
4268 "Bulgarian hard leva1.00",
4269 "Bulgarian lev1.00",
4270 "Burmese Kyat1.00",
4271 "Burmese kyat1.00",
4272 "Burmese kyats1.00",
4273 "Burundian Franc1.00",
4274 "Burundian franc1.00",
4275 "Burundian francs1.00",
4276 "CA$1.00",
4277 "CAD1.00",
4278 "CDF1.00",
4279 "CDF1.00",
4280 "West African CFA Franc1.00",
4281 "Central African CFA Franc1.00",
4282 "West African CFA franc1.00",
4283 "Central African CFA franc1.00",
4284 "West African CFA francs1.00",
4285 "Central African CFA francs1.00",
4286 "CFP Franc1.00",
4287 "CFP franc1.00",
4288 "CFP francs1.00",
4289 "CFPF1.00",
4290 "CHE1.00",
4291 "CHE1.00",
4292 "CHF1.00",
4293 "CHW1.00",
4294 "CHW1.00",
4295 "CLF1.00",
4296 "CLF1.00",
4297 "CLP1.00",
4298 "CNY1.00",
4299 "COP1.00",
4300 "COU1.00",
4301 "COU1.00",
4302 "CRC1.00",
4303 "CSD1.00",
4304 "CSD1.00",
4305 "CSK1.00",
4306 "CSK1.00",
4307 "CUP1.00",
4308 "CUP1.00",
4309 "CVE1.00",
4310 "CYP1.00",
4311 "CZK1.00",
4312 "Cambodian Riel1.00",
4313 "Cambodian riel1.00",
4314 "Cambodian riels1.00",
4315 "Canadian Dollar1.00",
4316 "Canadian dollar1.00",
4317 "Canadian dollars1.00",
4318 "Cape Verdean Escudo1.00",
4319 "Cape Verdean escudo1.00",
4320 "Cape Verdean escudos1.00",
4321 "Cayman Islands Dollar1.00",
4322 "Cayman Islands dollar1.00",
4323 "Cayman Islands dollars1.00",
4324 "Chilean Peso1.00",
4325 "Chilean Unit of Account (UF)1.00",
4326 "Chilean peso1.00",
4327 "Chilean pesos1.00",
4328 "Chilean unit of account (UF)1.00",
4329 "Chilean units of account (UF)1.00",
4330 "Chinese Yuan1.00",
4331 "Chinese yuan1.00",
4332 "Colombian Peso1.00",
4333 "Colombian peso1.00",
4334 "Colombian pesos1.00",
4335 "Comorian Franc1.00",
4336 "Comorian franc1.00",
4337 "Comorian francs1.00",
4338 "Congolese Franc1.00",
4339 "Congolese franc1.00",
4340 "Congolese francs1.00",
4341 "Costa Rican Col\\u00f3n1.00",
4342 "Costa Rican col\\u00f3n1.00",
4343 "Costa Rican col\\u00f3ns1.00",
4344 "Croatian Dinar1.00",
4345 "Croatian Kuna1.00",
4346 "Croatian dinar1.00",
4347 "Croatian dinars1.00",
4348 "Croatian kuna1.00",
4349 "Croatian kunas1.00",
4350 "Cuban Peso1.00",
4351 "Cuban peso1.00",
4352 "Cuban pesos1.00",
4353 "Cypriot Pound1.00",
4354 "Cypriot pound1.00",
4355 "Cypriot pounds1.00",
4356 "Czech Koruna1.00",
4357 "Czech koruna1.00",
4358 "Czech korunas1.00",
4359 "Czechoslovak Hard Koruna1.00",
4360 "Czechoslovak hard koruna1.00",
4361 "Czechoslovak hard korunas1.00",
4362 "DDM1.00",
4363 "DDM1.00",
4364 "DEM1.00",
4365 "DEM1.00",
4366 "DJF1.00",
4367 "DKK1.00",
4368 "DOP1.00",
4369 "DZD1.00",
4370 "Danish Krone1.00",
4371 "Danish krone1.00",
4372 "Danish kroner1.00",
4373 "German Mark1.00",
4374 "German mark1.00",
4375 "German marks1.00",
4376 "Djiboutian Franc1.00",
4377 "Djiboutian franc1.00",
4378 "Djiboutian francs1.00",
4379 "Dominican Peso1.00",
4380 "Dominican peso1.00",
4381 "Dominican pesos1.00",
4382 "EC$1.00",
4383 "ECS1.00",
4384 "ECS1.00",
4385 "ECV1.00",
4386 "ECV1.00",
4387 "EEK1.00",
4388 "EEK1.00",
4389 "EGP1.00",
4390 "EGP1.00",
4391 "ERN1.00",
4392 "ERN1.00",
4393 "ESA1.00",
4394 "ESA1.00",
4395 "ESB1.00",
4396 "ESB1.00",
4397 "ESP1.00",
4398 "ETB1.00",
4399 "EUR1.00",
4400 "East Caribbean Dollar1.00",
4401 "East Caribbean dollar1.00",
4402 "East Caribbean dollars1.00",
4403 "East German Mark1.00",
4404 "East German mark1.00",
4405 "East German marks1.00",
4406 "Ecuadorian Sucre1.00",
4407 "Ecuadorian Unit of Constant Value1.00",
4408 "Ecuadorian sucre1.00",
4409 "Ecuadorian sucres1.00",
4410 "Ecuadorian unit of constant value1.00",
4411 "Ecuadorian units of constant value1.00",
4412 "Egyptian Pound1.00",
4413 "Egyptian pound1.00",
4414 "Egyptian pounds1.00",
4415 "Salvadoran Col\\u00f3n1.00",
4416 "Salvadoran col\\u00f3n1.00",
4417 "Salvadoran colones1.00",
4418 "Equatorial Guinean Ekwele1.00",
4419 "Equatorial Guinean ekwele1.00",
4420 "Eritrean Nakfa1.00",
4421 "Eritrean nakfa1.00",
4422 "Eritrean nakfas1.00",
4423 "Estonian Kroon1.00",
4424 "Estonian kroon1.00",
4425 "Estonian kroons1.00",
4426 "Ethiopian Birr1.00",
4427 "Ethiopian birr1.00",
4428 "Ethiopian birrs1.00",
4429 "Euro1.00",
4430 "European Composite Unit1.00",
4431 "European Currency Unit1.00",
4432 "European Monetary Unit1.00",
4433 "European Unit of Account (XBC)1.00",
4434 "European Unit of Account (XBD)1.00",
4435 "European composite unit1.00",
4436 "European composite units1.00",
4437 "European currency unit1.00",
4438 "European currency units1.00",
4439 "European monetary unit1.00",
4440 "European monetary units1.00",
4441 "European unit of account (XBC)1.00",
4442 "European unit of account (XBD)1.00",
4443 "European units of account (XBC)1.00",
4444 "European units of account (XBD)1.00",
4445 "FIM1.00",
4446 "FIM1.00",
4447 "FJD1.00",
4448 "FKP1.00",
4449 "FKP1.00",
4450 "FRF1.00",
4451 "FRF1.00",
4452 "Falkland Islands Pound1.00",
4453 "Falkland Islands pound1.00",
4454 "Falkland Islands pounds1.00",
4455 "Fijian Dollar1.00",
4456 "Fijian dollar1.00",
4457 "Fijian dollars1.00",
4458 "Finnish Markka1.00",
4459 "Finnish markka1.00",
4460 "Finnish markkas1.00",
4461 "CHF1.00",
4462 "French Franc1.00",
4463 "French Gold Franc1.00",
4464 "French UIC-Franc1.00",
4465 "French UIC-franc1.00",
4466 "French UIC-francs1.00",
4467 "French franc1.00",
4468 "French francs1.00",
4469 "French gold franc1.00",
4470 "French gold francs1.00",
4471 "GBP1.00",
4472 "GEK1.00",
4473 "GEK1.00",
4474 "GEL1.00",
4475 "GHC1.00",
4476 "GHC1.00",
4477 "GHS1.00",
4478 "GIP1.00",
4479 "GIP1.00",
4480 "GMD1.00",
4481 "GMD1.00",
4482 "GNF1.00",
4483 "GNS1.00",
4484 "GNS1.00",
4485 "GQE1.00",
4486 "GQE1.00",
4487 "GRD1.00",
4488 "GRD1.00",
4489 "GTQ1.00",
4490 "GWE1.00",
4491 "GWE1.00",
4492 "GWP1.00",
4493 "GWP1.00",
4494 "GYD1.00",
4495 "Gambian Dalasi1.00",
4496 "Gambian dalasi1.00",
4497 "Gambian dalasis1.00",
4498 "Georgian Kupon Larit1.00",
4499 "Georgian Lari1.00",
4500 "Georgian kupon larit1.00",
4501 "Georgian kupon larits1.00",
4502 "Georgian lari1.00",
4503 "Georgian laris1.00",
4504 "Ghanaian Cedi (1979\\u20132007)1.00",
4505 "Ghanaian Cedi1.00",
4506 "Ghanaian cedi (1979\\u20132007)1.00",
4507 "Ghanaian cedi1.00",
4508 "Ghanaian cedis (1979\\u20132007)1.00",
4509 "Ghanaian cedis1.00",
4510 "Gibraltar Pound1.00",
4511 "Gibraltar pound1.00",
4512 "Gibraltar pounds1.00",
4513 "Gold1.00",
4514 "Gold1.00",
4515 "Greek Drachma1.00",
4516 "Greek drachma1.00",
4517 "Greek drachmas1.00",
4518 "Guatemalan Quetzal1.00",
4519 "Guatemalan quetzal1.00",
4520 "Guatemalan quetzals1.00",
4521 "Guinean Franc1.00",
4522 "Guinean Syli1.00",
4523 "Guinean franc1.00",
4524 "Guinean francs1.00",
4525 "Guinean syli1.00",
4526 "Guinean sylis1.00",
4527 "Guinea-Bissau Peso1.00",
4528 "Guinea-Bissau peso1.00",
4529 "Guinea-Bissau pesos1.00",
4530 "Guyanaese Dollar1.00",
4531 "Guyanaese dollar1.00",
4532 "Guyanaese dollars1.00",
4533 "HK$1.00",
4534 "HKD1.00",
4535 "HNL1.00",
4536 "HRD1.00",
4537 "HRD1.00",
4538 "HRK1.00",
4539 "HRK1.00",
4540 "HTG1.00",
4541 "HTG1.00",
4542 "HUF1.00",
4543 "Haitian Gourde1.00",
4544 "Haitian gourde1.00",
4545 "Haitian gourdes1.00",
4546 "Honduran Lempira1.00",
4547 "Honduran lempira1.00",
4548 "Honduran lempiras1.00",
4549 "Hong Kong Dollar1.00",
4550 "Hong Kong dollar1.00",
4551 "Hong Kong dollars1.00",
4552 "Hungarian Forint1.00",
4553 "Hungarian forint1.00",
4554 "Hungarian forints1.00",
4555 "IDR1.00",
4556 "IEP1.00",
4557 "ILP1.00",
4558 "ILP1.00",
4559 "ILS1.00",
4560 "INR1.00",
4561 "IQD1.00",
4562 "IRR1.00",
4563 "ISK1.00",
4564 "ISK1.00",
4565 "ITL1.00",
4566 "Icelandic Kr\\u00f3na1.00",
4567 "Icelandic kr\\u00f3na1.00",
4568 "Icelandic kr\\u00f3nur1.00",
4569 "Indian Rupee1.00",
4570 "Indian rupee1.00",
4571 "Indian rupees1.00",
4572 "Indonesian Rupiah1.00",
4573 "Indonesian rupiah1.00",
4574 "Indonesian rupiahs1.00",
4575 "Iranian Rial1.00",
4576 "Iranian rial1.00",
4577 "Iranian rials1.00",
4578 "Iraqi Dinar1.00",
4579 "Iraqi dinar1.00",
4580 "Iraqi dinars1.00",
4581 "Irish Pound1.00",
4582 "Irish pound1.00",
4583 "Irish pounds1.00",
4584 "Israeli Pound1.00",
4585 "Israeli new shekel1.00",
4586 "Israeli pound1.00",
4587 "Israeli pounds1.00",
4588 "Italian Lira1.00",
4589 "Italian lira1.00",
4590 "Italian liras1.00",
4591 "JMD1.00",
4592 "JOD1.00",
4593 "JPY1.00",
4594 "Jamaican Dollar1.00",
4595 "Jamaican dollar1.00",
4596 "Jamaican dollars1.00",
4597 "Japanese Yen1.00",
4598 "Japanese yen1.00",
4599 "Jordanian Dinar1.00",
4600 "Jordanian dinar1.00",
4601 "Jordanian dinars1.00",
4602 "KES1.00",
4603 "KGS1.00",
4604 "KHR1.00",
4605 "KMF1.00",
4606 "KPW1.00",
4607 "KPW1.00",
4608 "KRW1.00",
4609 "KWD1.00",
4610 "KYD1.00",
4611 "KYD1.00",
4612 "KZT1.00",
4613 "Kazakhstani Tenge1.00",
4614 "Kazakhstani tenge1.00",
4615 "Kazakhstani tenges1.00",
4616 "Kenyan Shilling1.00",
4617 "Kenyan shilling1.00",
4618 "Kenyan shillings1.00",
4619 "Kuwaiti Dinar1.00",
4620 "Kuwaiti dinar1.00",
4621 "Kuwaiti dinars1.00",
4622 "Kyrgystani Som1.00",
4623 "Kyrgystani som1.00",
4624 "Kyrgystani soms1.00",
4625 "HNL1.00",
4626 "LAK1.00",
4627 "LAK1.00",
4628 "LBP1.00",
4629 "LKR1.00",
4630 "LRD1.00",
4631 "LRD1.00",
4632 "LSL1.00",
4633 "LTL1.00",
4634 "LTL1.00",
4635 "LTT1.00",
4636 "LTT1.00",
4637 "LUC1.00",
4638 "LUC1.00",
4639 "LUF1.00",
4640 "LUF1.00",
4641 "LUL1.00",
4642 "LUL1.00",
4643 "LVL1.00",
4644 "LVL1.00",
4645 "LVR1.00",
4646 "LVR1.00",
4647 "LYD1.00",
4648 "Laotian Kip1.00",
4649 "Laotian kip1.00",
4650 "Laotian kips1.00",
4651 "Latvian Lats1.00",
4652 "Latvian Ruble1.00",
4653 "Latvian lats1.00",
4654 "Latvian lati1.00",
4655 "Latvian ruble1.00",
4656 "Latvian rubles1.00",
4657 "Lebanese Pound1.00",
4658 "Lebanese pound1.00",
4659 "Lebanese pounds1.00",
4660 "Lesotho Loti1.00",
4661 "Lesotho loti1.00",
4662 "Lesotho lotis1.00",
4663 "Liberian Dollar1.00",
4664 "Liberian dollar1.00",
4665 "Liberian dollars1.00",
4666 "Libyan Dinar1.00",
4667 "Libyan dinar1.00",
4668 "Libyan dinars1.00",
4669 "Lithuanian Litas1.00",
4670 "Lithuanian Talonas1.00",
4671 "Lithuanian litas1.00",
4672 "Lithuanian litai1.00",
4673 "Lithuanian talonas1.00",
4674 "Lithuanian talonases1.00",
4675 "Luxembourgian Convertible Franc1.00",
4676 "Luxembourg Financial Franc1.00",
4677 "Luxembourgian Franc1.00",
4678 "Luxembourgian convertible franc1.00",
4679 "Luxembourgian convertible francs1.00",
4680 "Luxembourg financial franc1.00",
4681 "Luxembourg financial francs1.00",
4682 "Luxembourgian franc1.00",
4683 "Luxembourgian francs1.00",
4684 "MAD1.00",
4685 "MAD1.00",
4686 "MAF1.00",
4687 "MAF1.00",
4688 "MDL1.00",
4689 "MDL1.00",
4690 "MX$1.00",
4691 "MGA1.00",
4692 "MGA1.00",
4693 "MGF1.00",
4694 "MGF1.00",
4695 "MKD1.00",
4696 "MLF1.00",
4697 "MLF1.00",
4698 "MMK1.00",
4699 "MMK1.00",
4700 "MNT1.00",
4701 "MOP1.00",
4702 "MOP1.00",
4703 "MRO1.00",
4704 "MTL1.00",
4705 "MTP1.00",
4706 "MTP1.00",
4707 "MUR1.00",
4708 "MUR1.00",
4709 "MVR1.00",
4710 "MVR1.00",
4711 "MWK1.00",
4712 "MXN1.00",
4713 "MXP1.00",
4714 "MXP1.00",
4715 "MXV1.00",
4716 "MXV1.00",
4717 "MYR1.00",
4718 "MZE1.00",
4719 "MZE1.00",
4720 "MZM1.00",
4721 "MZN1.00",
4722 "Macanese Pataca1.00",
4723 "Macanese pataca1.00",
4724 "Macanese patacas1.00",
4725 "Macedonian Denar1.00",
4726 "Macedonian denar1.00",
4727 "Macedonian denari1.00",
4728 "Malagasy Ariaries1.00",
4729 "Malagasy Ariary1.00",
4730 "Malagasy Ariary1.00",
4731 "Malagasy Franc1.00",
4732 "Malagasy franc1.00",
4733 "Malagasy francs1.00",
4734 "Malawian Kwacha1.00",
4735 "Malawian Kwacha1.00",
4736 "Malawian Kwachas1.00",
4737 "Malaysian Ringgit1.00",
4738 "Malaysian ringgit1.00",
4739 "Malaysian ringgits1.00",
4740 "Maldivian Rufiyaa1.00",
4741 "Maldivian rufiyaa1.00",
4742 "Maldivian rufiyaas1.00",
4743 "Malian Franc1.00",
4744 "Malian franc1.00",
4745 "Malian francs1.00",
4746 "Maltese Lira1.00",
4747 "Maltese Pound1.00",
4748 "Maltese lira1.00",
4749 "Maltese lira1.00",
4750 "Maltese pound1.00",
4751 "Maltese pounds1.00",
4752 "Mauritanian Ouguiya1.00",
4753 "Mauritanian ouguiya1.00",
4754 "Mauritanian ouguiyas1.00",
4755 "Mauritian Rupee1.00",
4756 "Mauritian rupee1.00",
4757 "Mauritian rupees1.00",
4758 "Mexican Peso1.00",
4759 "Mexican Silver Peso (1861\\u20131992)1.00",
4760 "Mexican Investment Unit1.00",
4761 "Mexican peso1.00",
4762 "Mexican pesos1.00",
4763 "Mexican silver peso (1861\\u20131992)1.00",
4764 "Mexican silver pesos (1861\\u20131992)1.00",
4765 "Mexican investment unit1.00",
4766 "Mexican investment units1.00",
4767 "Moldovan Leu1.00",
4768 "Moldovan leu1.00",
4769 "Moldovan lei1.00",
4770 "Mongolian Tugrik1.00",
4771 "Mongolian tugrik1.00",
4772 "Mongolian tugriks1.00",
4773 "Moroccan Dirham1.00",
4774 "Moroccan Franc1.00",
4775 "Moroccan dirham1.00",
4776 "Moroccan dirhams1.00",
4777 "Moroccan franc1.00",
4778 "Moroccan francs1.00",
4779 "Mozambican Escudo1.00",
4780 "Mozambican Metical1.00",
4781 "Mozambican escudo1.00",
4782 "Mozambican escudos1.00",
4783 "Mozambican metical1.00",
4784 "Mozambican meticals1.00",
4785 "Myanmar Kyat1.00",
4786 "Myanmar kyat1.00",
4787 "Myanmar kyats1.00",
4788 "NAD1.00",
4789 "NGN1.00",
4790 "NIC1.00",
4791 "NIO1.00",
4792 "NIO1.00",
4793 "NLG1.00",
4794 "NLG1.00",
4795 "NOK1.00",
4796 "NPR1.00",
4797 "NT$1.00",
4798 "NZ$1.00",
4799 "NZD1.00",
4800 "Namibian Dollar1.00",
4801 "Namibian dollar1.00",
4802 "Namibian dollars1.00",
4803 "Nepalese Rupee1.00",
4804 "Nepalese rupee1.00",
4805 "Nepalese rupees1.00",
4806 "Netherlands Antillean Guilder1.00",
4807 "Netherlands Antillean guilder1.00",
4808 "Netherlands Antillean guilders1.00",
4809 "Dutch Guilder1.00",
4810 "Dutch guilder1.00",
4811 "Dutch guilders1.00",
4812 "Israeli New Shekel1.00",
4813 "Israeli New Shekels1.00",
4814 "New Zealand Dollar1.00",
4815 "New Zealand dollar1.00",
4816 "New Zealand dollars1.00",
4817 "Nicaraguan C\\u00f3rdoba1.00",
4818 "Nicaraguan C\\u00f3rdoba (1988\\u20131991)1.00",
4819 "Nicaraguan c\\u00f3rdoba1.00",
4820 "Nicaraguan c\\u00f3rdobas1.00",
4821 "Nicaraguan c\\u00f3rdoba (1988\\u20131991)1.00",
4822 "Nicaraguan c\\u00f3rdobas (1988\\u20131991)1.00",
4823 "Nigerian Naira1.00",
4824 "Nigerian naira1.00",
4825 "Nigerian nairas1.00",
4826 "North Korean Won1.00",
4827 "North Korean won1.00",
4828 "North Korean won1.00",
4829 "Norwegian Krone1.00",
4830 "Norwegian krone1.00",
4831 "Norwegian kroner1.00",
4832 "OMR1.00",
4833 "Mozambican Metical (1980\\u20132006)1.00",
4834 "Mozambican metical (1980\\u20132006)1.00",
4835 "Mozambican meticals (1980\\u20132006)1.00",
4836 "Romanian Lei (1952\\u20132006)1.00",
4837 "Romanian Leu (1952\\u20132006)1.00",
4838 "Romanian leu (1952\\u20132006)1.00",
4839 "Serbian Dinar (2002\\u20132006)1.00",
4840 "Serbian dinar (2002\\u20132006)1.00",
4841 "Serbian dinars (2002\\u20132006)1.00",
4842 "Sudanese Dinar (1992\\u20132007)1.00",
4843 "Sudanese Pound (1957\\u20131998)1.00",
4844 "Sudanese dinar (1992\\u20132007)1.00",
4845 "Sudanese dinars (1992\\u20132007)1.00",
4846 "Sudanese pound (1957\\u20131998)1.00",
4847 "Sudanese pounds (1957\\u20131998)1.00",
4848 "Turkish Lira (1922\\u20132005)1.00",
4849 "Turkish Lira (1922\\u20132005)1.00",
4850 "Omani Rial1.00",
4851 "Omani rial1.00",
4852 "Omani rials1.00",
4853 "PAB1.00",
4854 "PAB1.00",
4855 "PEI1.00",
4856 "PEI1.00",
4857 "PEN1.00",
4858 "PEN1.00",
4859 "PES1.00",
4860 "PES1.00",
4861 "PGK1.00",
4862 "PGK1.00",
4863 "PHP1.00",
4864 "PKR1.00",
4865 "PLN1.00",
4866 "PLZ1.00",
4867 "PLZ1.00",
4868 "PTE1.00",
4869 "PTE1.00",
4870 "PYG1.00",
4871 "Pakistani Rupee1.00",
4872 "Pakistani rupee1.00",
4873 "Pakistani rupees1.00",
4874 "Palladium1.00",
4875 "Palladium1.00",
4876 "Panamanian Balboa1.00",
4877 "Panamanian balboa1.00",
4878 "Panamanian balboas1.00",
4879 "Papua New Guinean Kina1.00",
4880 "Papua New Guinean kina1.00",
4881 "Papua New Guinean kina1.00",
4882 "Paraguayan Guarani1.00",
4883 "Paraguayan guarani1.00",
4884 "Paraguayan guaranis1.00",
4885 "Peruvian Inti1.00",
4886 "Peruvian Sol1.00",
4887 "Peruvian Sol (1863\\u20131965)1.00",
4888 "Peruvian inti1.00",
4889 "Peruvian intis1.00",
4890 "Peruvian sol1.00",
4891 "Peruvian soles1.00",
4892 "Peruvian sol (1863\\u20131965)1.00",
4893 "Peruvian soles (1863\\u20131965)1.00",
Frank Tangd2858cb2022-04-08 20:34:12 -07004894 "Philippine Peso1.00",
4895 "Philippine peso1.00",
4896 "Philippine pesos1.00",
Frank Tang3e05d9d2021-11-08 14:04:04 -08004897 "Platinum1.00",
4898 "Platinum1.00",
4899 "Polish Zloty (1950\\u20131995)1.00",
4900 "Polish Zloty1.00",
4901 "Polish zlotys1.00",
4902 "Polish zloty (PLZ)1.00",
4903 "Polish zloty1.00",
4904 "Polish zlotys (PLZ)1.00",
4905 "Portuguese Escudo1.00",
4906 "Portuguese Guinea Escudo1.00",
4907 "Portuguese Guinea escudo1.00",
4908 "Portuguese Guinea escudos1.00",
4909 "Portuguese escudo1.00",
4910 "Portuguese escudos1.00",
4911 "GTQ1.00",
4912 "QAR1.00",
Frank Tang1f164ee2022-11-08 12:31:27 -08004913 "Qatari Riyal1.00",
4914 "Qatari riyal1.00",
4915 "Qatari riyals1.00",
Frank Tang3e05d9d2021-11-08 14:04:04 -08004916 "RHD1.00",
4917 "RHD1.00",
4918 "RINET Funds1.00",
4919 "RINET Funds1.00",
4920 "CN\\u00a51.00",
4921 "ROL1.00",
4922 "ROL1.00",
4923 "RON1.00",
4924 "RON1.00",
4925 "RSD1.00",
4926 "RSD1.00",
4927 "RUB1.00",
4928 "RUR1.00",
4929 "RUR1.00",
4930 "RWF1.00",
4931 "RWF1.00",
4932 "Rhodesian Dollar1.00",
4933 "Rhodesian dollar1.00",
4934 "Rhodesian dollars1.00",
4935 "Romanian Leu1.00",
4936 "Romanian lei1.00",
4937 "Romanian leu1.00",
4938 "Russian Ruble (1991\\u20131998)1.00",
4939 "Russian Ruble1.00",
4940 "Russian ruble (1991\\u20131998)1.00",
4941 "Russian ruble1.00",
4942 "Russian rubles (1991\\u20131998)1.00",
4943 "Russian rubles1.00",
4944 "Rwandan Franc1.00",
4945 "Rwandan franc1.00",
4946 "Rwandan francs1.00",
4947 "SAR1.00",
4948 "SBD1.00",
4949 "SCR1.00",
4950 "SDD1.00",
4951 "SDD1.00",
4952 "SDG1.00",
4953 "SDG1.00",
4954 "SDP1.00",
4955 "SDP1.00",
4956 "SEK1.00",
4957 "SGD1.00",
4958 "SHP1.00",
4959 "SHP1.00",
4960 "SIT1.00",
4961 "SIT1.00",
4962 "SKK1.00",
4963 "SLL1.00",
4964 "SLL1.00",
4965 "SOS1.00",
4966 "SRD1.00",
4967 "SRD1.00",
4968 "SRG1.00",
4969 "STD1.00",
4970 "SUR1.00",
4971 "SUR1.00",
4972 "SVC1.00",
4973 "SVC1.00",
4974 "SYP1.00",
4975 "SZL1.00",
4976 "St. Helena Pound1.00",
4977 "St. Helena pound1.00",
4978 "St. Helena pounds1.00",
4979 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra1.00",
4980 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra1.00",
4981 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras1.00",
4982 "Saudi Riyal1.00",
4983 "Saudi riyal1.00",
4984 "Saudi riyals1.00",
4985 "Serbian Dinar1.00",
4986 "Serbian dinar1.00",
4987 "Serbian dinars1.00",
4988 "Seychellois Rupee1.00",
4989 "Seychellois rupee1.00",
4990 "Seychellois rupees1.00",
4991 "Sierra Leonean Leone1.00",
4992 "Sierra Leonean leone1.00",
4993 "Sierra Leonean leones1.00",
4994 "Silver1.00",
4995 "Silver1.00",
4996 "Singapore Dollar1.00",
4997 "Singapore dollar1.00",
4998 "Singapore dollars1.00",
4999 "Slovak Koruna1.00",
5000 "Slovak koruna1.00",
5001 "Slovak korunas1.00",
5002 "Slovenian Tolar1.00",
5003 "Slovenian tolar1.00",
5004 "Slovenian tolars1.00",
5005 "Solomon Islands Dollar1.00",
5006 "Solomon Islands dollar1.00",
5007 "Solomon Islands dollars1.00",
5008 "Somali Shilling1.00",
5009 "Somali shilling1.00",
5010 "Somali shillings1.00",
5011 "South African Rand (financial)1.00",
5012 "South African Rand1.00",
5013 "South African rand (financial)1.00",
5014 "South African rand1.00",
5015 "South African rands (financial)1.00",
5016 "South African rand1.00",
5017 "South Korean Won1.00",
5018 "South Korean won1.00",
5019 "South Korean won1.00",
5020 "Soviet Rouble1.00",
5021 "Soviet rouble1.00",
5022 "Soviet roubles1.00",
5023 "Spanish Peseta (A account)1.00",
5024 "Spanish Peseta (convertible account)1.00",
5025 "Spanish Peseta1.00",
5026 "Spanish peseta (A account)1.00",
5027 "Spanish peseta (convertible account)1.00",
5028 "Spanish peseta1.00",
5029 "Spanish pesetas (A account)1.00",
5030 "Spanish pesetas (convertible account)1.00",
5031 "Spanish pesetas1.00",
5032 "Special Drawing Rights1.00",
5033 "Sri Lankan Rupee1.00",
5034 "Sri Lankan rupee1.00",
5035 "Sri Lankan rupees1.00",
5036 "Sudanese Pound1.00",
5037 "Sudanese pound1.00",
5038 "Sudanese pounds1.00",
5039 "Surinamese Dollar1.00",
5040 "Surinamese dollar1.00",
5041 "Surinamese dollars1.00",
5042 "Surinamese Guilder1.00",
5043 "Surinamese guilder1.00",
5044 "Surinamese guilders1.00",
5045 "Swazi Lilangeni1.00",
5046 "Swazi lilangeni1.00",
5047 "Swazi emalangeni1.00",
5048 "Swedish Krona1.00",
5049 "Swedish krona1.00",
5050 "Swedish kronor1.00",
5051 "Swiss Franc1.00",
5052 "Swiss franc1.00",
5053 "Swiss francs1.00",
5054 "Syrian Pound1.00",
5055 "Syrian pound1.00",
5056 "Syrian pounds1.00",
5057 "THB1.00",
5058 "TJR1.00",
5059 "TJR1.00",
5060 "TJS1.00",
5061 "TJS1.00",
5062 "TMM1.00",
5063 "TMM1.00",
5064 "TND1.00",
5065 "TND1.00",
5066 "TOP1.00",
5067 "TPE1.00",
5068 "TPE1.00",
5069 "TRL1.00",
5070 "TRY1.00",
5071 "TRY1.00",
5072 "TTD1.00",
5073 "TWD1.00",
5074 "TZS1.00",
5075 "New Taiwan Dollar1.00",
5076 "New Taiwan dollar1.00",
5077 "New Taiwan dollars1.00",
5078 "Tajikistani Ruble1.00",
5079 "Tajikistani Somoni1.00",
5080 "Tajikistani ruble1.00",
5081 "Tajikistani rubles1.00",
5082 "Tajikistani somoni1.00",
5083 "Tajikistani somonis1.00",
5084 "Tanzanian Shilling1.00",
5085 "Tanzanian shilling1.00",
5086 "Tanzanian shillings1.00",
5087 "Testing Currency Code1.00",
5088 "Testing Currency Code1.00",
5089 "Thai Baht1.00",
5090 "Thai baht1.00",
5091 "Thai baht1.00",
5092 "Timorese Escudo1.00",
5093 "Timorese escudo1.00",
5094 "Timorese escudos1.00",
5095 "Tongan Pa\\u02bbanga1.00",
5096 "Tongan pa\\u02bbanga1.00",
5097 "Tongan pa\\u02bbanga1.00",
5098 "Trinidad & Tobago Dollar1.00",
5099 "Trinidad & Tobago dollar1.00",
5100 "Trinidad & Tobago dollars1.00",
5101 "Tunisian Dinar1.00",
5102 "Tunisian dinar1.00",
5103 "Tunisian dinars1.00",
5104 "Turkish Lira1.00",
5105 "Turkish Lira1.00",
5106 "Turkish lira1.00",
5107 "Turkmenistani Manat1.00",
5108 "Turkmenistani manat1.00",
5109 "Turkmenistani manat1.00",
5110 "UAE dirham1.00",
5111 "UAE dirhams1.00",
5112 "UAH1.00",
5113 "UAK1.00",
5114 "UAK1.00",
5115 "UGS1.00",
5116 "UGS1.00",
5117 "UGX1.00",
5118 "US Dollar (Next day)1.00",
5119 "US Dollar (Same day)1.00",
5120 "US Dollar1.00",
5121 "US dollar (next day)1.00",
5122 "US dollar (same day)1.00",
5123 "US dollar1.00",
5124 "US dollars (next day)1.00",
5125 "US dollars (same day)1.00",
5126 "US dollars1.00",
5127 "USD1.00",
5128 "USN1.00",
5129 "USN1.00",
5130 "USS1.00",
5131 "USS1.00",
5132 "UYI1.00",
5133 "UYI1.00",
5134 "UYP1.00",
5135 "UYP1.00",
5136 "UYU1.00",
5137 "UZS1.00",
5138 "UZS1.00",
5139 "Ugandan Shilling (1966\\u20131987)1.00",
5140 "Ugandan Shilling1.00",
5141 "Ugandan shilling (1966\\u20131987)1.00",
5142 "Ugandan shilling1.00",
5143 "Ugandan shillings (1966\\u20131987)1.00",
5144 "Ugandan shillings1.00",
5145 "Ukrainian Hryvnia1.00",
5146 "Ukrainian Karbovanets1.00",
5147 "Ukrainian hryvnia1.00",
5148 "Ukrainian hryvnias1.00",
5149 "Ukrainian karbovanets1.00",
5150 "Ukrainian karbovantsiv1.00",
5151 "Colombian Real Value Unit1.00",
5152 "United Arab Emirates Dirham1.00",
5153 "Unknown Currency1.00",
5154 "Uruguayan Peso (1975\\u20131993)1.00",
5155 "Uruguayan Peso1.00",
5156 "Uruguayan Peso (Indexed Units)1.00",
5157 "Uruguayan peso (1975\\u20131993)1.00",
5158 "Uruguayan peso (indexed units)1.00",
5159 "Uruguayan peso1.00",
5160 "Uruguayan pesos (1975\\u20131993)1.00",
5161 "Uruguayan pesos (indexed units)1.00",
5162 "Uruguayan pesos1.00",
5163 "Uzbekistani Som1.00",
5164 "Uzbekistani som1.00",
5165 "Uzbekistani som1.00",
5166 "VEB1.00",
5167 "VEF1.00",
5168 "VND1.00",
5169 "VUV1.00",
5170 "Vanuatu Vatu1.00",
5171 "Vanuatu vatu1.00",
5172 "Vanuatu vatus1.00",
5173 "Venezuelan Bol\\u00edvar1.00",
5174 "Venezuelan Bol\\u00edvar (1871\\u20132008)1.00",
5175 "Venezuelan bol\\u00edvar1.00",
5176 "Venezuelan bol\\u00edvars1.00",
5177 "Venezuelan bol\\u00edvar (1871\\u20132008)1.00",
5178 "Venezuelan bol\\u00edvars (1871\\u20132008)1.00",
5179 "Vietnamese Dong1.00",
5180 "Vietnamese dong1.00",
5181 "Vietnamese dong1.00",
5182 "WIR Euro1.00",
5183 "WIR Franc1.00",
5184 "WIR euro1.00",
5185 "WIR euros1.00",
5186 "WIR franc1.00",
5187 "WIR francs1.00",
5188 "WST1.00",
5189 "WST1.00",
5190 "Samoan Tala1.00",
5191 "Samoan tala1.00",
5192 "Samoan tala1.00",
5193 "XAF1.00",
5194 "XAF1.00",
5195 "XAG1.00",
5196 "XAG1.00",
5197 "XAU1.00",
5198 "XAU1.00",
5199 "XBA1.00",
5200 "XBA1.00",
5201 "XBB1.00",
5202 "XBB1.00",
5203 "XBC1.00",
5204 "XBC1.00",
5205 "XBD1.00",
5206 "XBD1.00",
5207 "XCD1.00",
5208 "XDR1.00",
5209 "XDR1.00",
5210 "XEU1.00",
5211 "XEU1.00",
5212 "XFO1.00",
5213 "XFO1.00",
5214 "XFU1.00",
5215 "XFU1.00",
5216 "XOF1.00",
5217 "XOF1.00",
5218 "XPD1.00",
5219 "XPD1.00",
5220 "XPF1.00",
5221 "XPT1.00",
5222 "XPT1.00",
5223 "XRE1.00",
5224 "XRE1.00",
5225 "XTS1.00",
5226 "XTS1.00",
5227 "XXX1.00",
5228 "XXX1.00",
5229 "YDD1.00",
5230 "YDD1.00",
5231 "YER1.00",
5232 "YUD1.00",
5233 "YUD1.00",
5234 "YUM1.00",
5235 "YUM1.00",
5236 "YUN1.00",
5237 "YUN1.00",
5238 "Yemeni Dinar1.00",
5239 "Yemeni Rial1.00",
5240 "Yemeni dinar1.00",
5241 "Yemeni dinars1.00",
5242 "Yemeni rial1.00",
5243 "Yemeni rials1.00",
5244 "Yugoslavian Convertible Dinar (1990\\u20131992)1.00",
5245 "Yugoslavian Hard Dinar (1966\\u20131990)1.00",
5246 "Yugoslavian New Dinar (1994\\u20132002)1.00",
5247 "Yugoslavian convertible dinar (1990\\u20131992)1.00",
5248 "Yugoslavian convertible dinars (1990\\u20131992)1.00",
5249 "Yugoslavian hard dinar (1966\\u20131990)1.00",
5250 "Yugoslavian hard dinars (1966\\u20131990)1.00",
5251 "Yugoslavian new dinar (1994\\u20132002)1.00",
5252 "Yugoslavian new dinars (1994\\u20132002)1.00",
5253 "ZAL1.00",
5254 "ZAL1.00",
5255 "ZAR1.00",
5256 "ZMK1.00",
5257 "ZMK1.00",
5258 "ZRN1.00",
5259 "ZRN1.00",
5260 "ZRZ1.00",
5261 "ZRZ1.00",
5262 "ZWD1.00",
5263 "Zairean New Zaire (1993\\u20131998)1.00",
5264 "Zairean Zaire (1971\\u20131993)1.00",
5265 "Zairean new zaire (1993\\u20131998)1.00",
5266 "Zairean new zaires (1993\\u20131998)1.00",
5267 "Zairean zaire (1971\\u20131993)1.00",
5268 "Zairean zaires (1971\\u20131993)1.00",
5269 "Zambian Kwacha1.00",
5270 "Zambian kwacha1.00",
5271 "Zambian kwachas1.00",
5272 "Zimbabwean Dollar (1980\\u20132008)1.00",
5273 "Zimbabwean dollar (1980\\u20132008)1.00",
5274 "Zimbabwean dollars (1980\\u20132008)1.00",
5275 "euro1.00",
5276 "euros1.00",
5277 "Turkish lira (1922\\u20132005)1.00",
5278 "special drawing rights1.00",
5279 "Colombian real value unit1.00",
5280 "Colombian real value units1.00",
5281 "unknown currency1.00",
5282 "\\u00a31.00",
5283 "\\u00a51.00",
5284 "\\u20ab1.00",
5285 "\\u20aa1.00",
5286 "\\u20ac1.00",
5287 "\\u20b91.00",
5288 //
5289 // Following has extra text, should be parsed correctly too
5290 "$1.00 random",
5291 "USD1.00 random",
5292 "1.00 US dollar random",
5293 "1.00 US dollars random",
5294 "1.00 Afghan Afghani random",
5295 "1.00 Afghan Afghani random",
5296 "1.00 Afghan Afghanis (1927\\u20131992) random",
5297 "1.00 Afghan Afghanis random",
5298 "1.00 Albanian Lek random",
5299 "1.00 Albanian lek random",
5300 "1.00 Albanian lek\\u00eb random",
5301 "1.00 Algerian Dinar random",
5302 "1.00 Algerian dinar random",
5303 "1.00 Algerian dinars random",
5304 "1.00 Andorran Peseta random",
5305 "1.00 Andorran peseta random",
5306 "1.00 Andorran pesetas random",
5307 "1.00 Angolan Kwanza (1977\\u20131990) random",
5308 "1.00 Angolan Readjusted Kwanza (1995\\u20131999) random",
5309 "1.00 Angolan Kwanza random",
5310 "1.00 Angolan New Kwanza (1990\\u20132000) random",
5311 "1.00 Angolan kwanza (1977\\u20131991) random",
5312 "1.00 Angolan readjusted kwanza (1995\\u20131999) random",
5313 "1.00 Angolan kwanza random",
5314 "1.00 Angolan kwanzas (1977\\u20131991) random",
5315 "1.00 Angolan readjusted kwanzas (1995\\u20131999) random",
5316 "1.00 Angolan kwanzas random",
5317 "1.00 Angolan new kwanza (1990\\u20132000) random",
5318 "1.00 Angolan new kwanzas (1990\\u20132000) random",
5319 "1.00 Argentine Austral random",
5320 "1.00 Argentine Peso (1983\\u20131985) random",
5321 "1.00 Argentine Peso random",
5322 "1.00 Argentine austral random",
5323 "1.00 Argentine australs random",
5324 "1.00 Argentine peso (1983\\u20131985) random",
5325 "1.00 Argentine peso random",
5326 "1.00 Argentine pesos (1983\\u20131985) random",
5327 "1.00 Argentine pesos random",
5328 "1.00 Armenian Dram random",
5329 "1.00 Armenian dram random",
5330 "1.00 Armenian drams random",
5331 "1.00 Aruban Florin random",
5332 "1.00 Aruban florin random",
5333 "1.00 Australian Dollar random",
5334 "1.00 Australian dollar random",
5335 "1.00 Australian dollars random",
5336 "1.00 Austrian Schilling random",
5337 "1.00 Austrian schilling random",
5338 "1.00 Austrian schillings random",
5339 "1.00 Azerbaijani Manat (1993\\u20132006) random",
5340 "1.00 Azerbaijani Manat random",
5341 "1.00 Azerbaijani manat (1993\\u20132006) random",
5342 "1.00 Azerbaijani manat random",
5343 "1.00 Azerbaijani manats (1993\\u20132006) random",
5344 "1.00 Azerbaijani manats random",
5345 "1.00 Bahamian Dollar random",
5346 "1.00 Bahamian dollar random",
5347 "1.00 Bahamian dollars random",
5348 "1.00 Bahraini Dinar random",
5349 "1.00 Bahraini dinar random",
5350 "1.00 Bahraini dinars random",
5351 "1.00 Bangladeshi Taka random",
5352 "1.00 Bangladeshi taka random",
5353 "1.00 Bangladeshi takas random",
5354 "1.00 Barbadian Dollar random",
5355 "1.00 Barbadian dollar random",
5356 "1.00 Barbadian dollars random",
5357 "1.00 Belarusian Ruble (1994\\u20131999) random",
5358 "1.00 Belarusian Ruble random",
5359 "1.00 Belarusian ruble (1994\\u20131999) random",
5360 "1.00 Belarusian rubles (1994\\u20131999) random",
5361 "1.00 Belarusian ruble random",
5362 "1.00 Belarusian rubles random",
5363 "1.00 Belgian Franc (convertible) random",
5364 "1.00 Belgian Franc (financial) random",
5365 "1.00 Belgian Franc random",
5366 "1.00 Belgian franc (convertible) random",
5367 "1.00 Belgian franc (financial) random",
5368 "1.00 Belgian franc random",
5369 "1.00 Belgian francs (convertible) random",
5370 "1.00 Belgian francs (financial) random",
5371 "1.00 Belgian francs random",
5372 "1.00 Belize Dollar random",
5373 "1.00 Belize dollar random",
5374 "1.00 Belize dollars random",
5375 "1.00 Bermudan Dollar random",
5376 "1.00 Bermudan dollar random",
5377 "1.00 Bermudan dollars random",
5378 "1.00 Bhutanese Ngultrum random",
5379 "1.00 Bhutanese ngultrum random",
5380 "1.00 Bhutanese ngultrums random",
5381 "1.00 Bolivian Mvdol random",
5382 "1.00 Bolivian Peso random",
5383 "1.00 Bolivian mvdol random",
5384 "1.00 Bolivian mvdols random",
5385 "1.00 Bolivian peso random",
5386 "1.00 Bolivian pesos random",
5387 "1.00 Bolivian Boliviano random",
5388 "1.00 Bolivian Boliviano random",
5389 "1.00 Bolivian Bolivianos random",
5390 "1.00 Bosnia-Herzegovina Convertible Mark random",
5391 "1.00 Bosnia-Herzegovina Dinar (1992\\u20131994) random",
5392 "1.00 Bosnia-Herzegovina convertible mark random",
5393 "1.00 Bosnia-Herzegovina convertible marks random",
5394 "1.00 Bosnia-Herzegovina dinar (1992\\u20131994) random",
5395 "1.00 Bosnia-Herzegovina dinars (1992\\u20131994) random",
5396 "1.00 Botswanan Pula random",
5397 "1.00 Botswanan pula random",
5398 "1.00 Botswanan pulas random",
5399 "1.00 Brazilian New Cruzado (1989\\u20131990) random",
5400 "1.00 Brazilian Cruzado (1986\\u20131989) random",
5401 "1.00 Brazilian Cruzeiro (1990\\u20131993) random",
5402 "1.00 Brazilian New Cruzeiro (1967\\u20131986) random",
5403 "1.00 Brazilian Cruzeiro (1993\\u20131994) random",
5404 "1.00 Brazilian Real random",
5405 "1.00 Brazilian new cruzado (1989\\u20131990) random",
5406 "1.00 Brazilian new cruzados (1989\\u20131990) random",
5407 "1.00 Brazilian cruzado (1986\\u20131989) random",
5408 "1.00 Brazilian cruzados (1986\\u20131989) random",
5409 "1.00 Brazilian cruzeiro (1990\\u20131993) random",
5410 "1.00 Brazilian new cruzeiro (1967\\u20131986) random",
5411 "1.00 Brazilian cruzeiro (1993\\u20131994) random",
5412 "1.00 Brazilian cruzeiros (1990\\u20131993) random",
5413 "1.00 Brazilian new cruzeiros (1967\\u20131986) random",
5414 "1.00 Brazilian cruzeiros (1993\\u20131994) random",
5415 "1.00 Brazilian real random",
5416 "1.00 Brazilian reals random",
5417 "1.00 British Pound random",
5418 "1.00 British pound random",
5419 "1.00 British pounds random",
5420 "1.00 Brunei Dollar random",
5421 "1.00 Brunei dollar random",
5422 "1.00 Brunei dollars random",
5423 "1.00 Bulgarian Hard Lev random",
5424 "1.00 Bulgarian Lev random",
5425 "1.00 Bulgarian Leva random",
5426 "1.00 Bulgarian hard lev random",
5427 "1.00 Bulgarian hard leva random",
5428 "1.00 Bulgarian lev random",
5429 "1.00 Burmese Kyat random",
5430 "1.00 Burmese kyat random",
5431 "1.00 Burmese kyats random",
5432 "1.00 Burundian Franc random",
5433 "1.00 Burundian franc random",
5434 "1.00 Burundian francs random",
5435 "1.00 Cambodian Riel random",
5436 "1.00 Cambodian riel random",
5437 "1.00 Cambodian riels random",
5438 "1.00 Canadian Dollar random",
5439 "1.00 Canadian dollar random",
5440 "1.00 Canadian dollars random",
5441 "1.00 Cape Verdean Escudo random",
5442 "1.00 Cape Verdean escudo random",
5443 "1.00 Cape Verdean escudos random",
5444 "1.00 Cayman Islands Dollar random",
5445 "1.00 Cayman Islands dollar random",
5446 "1.00 Cayman Islands dollars random",
5447 "1.00 Chilean Peso random",
5448 "1.00 Chilean Unit of Account (UF) random",
5449 "1.00 Chilean peso random",
5450 "1.00 Chilean pesos random",
5451 "1.00 Chilean unit of account (UF) random",
5452 "1.00 Chilean units of account (UF) random",
5453 "1.00 Chinese Yuan random",
5454 "1.00 Chinese yuan random",
5455 "1.00 Colombian Peso random",
5456 "1.00 Colombian peso random",
5457 "1.00 Colombian pesos random",
5458 "1.00 Comorian Franc random",
5459 "1.00 Comorian franc random",
5460 "1.00 Comorian francs random",
5461 "1.00 Congolese Franc Congolais random",
5462 "1.00 Congolese franc Congolais random",
5463 "1.00 Congolese francs Congolais random",
5464 "1.00 Costa Rican Col\\u00f3n random",
5465 "1.00 Costa Rican col\\u00f3n random",
5466 "1.00 Costa Rican col\\u00f3ns random",
5467 "1.00 Croatian Dinar random",
5468 "1.00 Croatian Kuna random",
5469 "1.00 Croatian dinar random",
5470 "1.00 Croatian dinars random",
5471 "1.00 Croatian kuna random",
5472 "1.00 Croatian kunas random",
5473 "1.00 Cuban Peso random",
5474 "1.00 Cuban peso random",
5475 "1.00 Cuban pesos random",
5476 "1.00 Cypriot Pound random",
5477 "1.00 Cypriot pound random",
5478 "1.00 Cypriot pounds random",
5479 "1.00 Czech Koruna random",
5480 "1.00 Czech koruna random",
5481 "1.00 Czech korunas random",
5482 "1.00 Czechoslovak Hard Koruna random",
5483 "1.00 Czechoslovak hard koruna random",
5484 "1.00 Czechoslovak hard korunas random",
5485 "1.00 Danish Krone random",
5486 "1.00 Danish krone random",
5487 "1.00 Danish kroner random",
5488 "1.00 German Mark random",
5489 "1.00 German mark random",
5490 "1.00 German marks random",
5491 "1.00 Djiboutian Franc random",
5492 "1.00 Djiboutian franc random",
5493 "1.00 Djiboutian francs random",
5494 "1.00 Dominican Peso random",
5495 "1.00 Dominican peso random",
5496 "1.00 Dominican pesos random",
5497 "1.00 East Caribbean Dollar random",
5498 "1.00 East Caribbean dollar random",
5499 "1.00 East Caribbean dollars random",
5500 "1.00 East German Mark random",
5501 "1.00 East German mark random",
5502 "1.00 East German marks random",
5503 "1.00 Ecuadorian Sucre random",
5504 "1.00 Ecuadorian Unit of Constant Value random",
5505 "1.00 Ecuadorian sucre random",
5506 "1.00 Ecuadorian sucres random",
5507 "1.00 Ecuadorian unit of constant value random",
5508 "1.00 Ecuadorian units of constant value random",
5509 "1.00 Egyptian Pound random",
5510 "1.00 Egyptian pound random",
5511 "1.00 Egyptian pounds random",
5512 "1.00 Salvadoran Col\\u00f3n random",
5513 "1.00 Salvadoran col\\u00f3n random",
5514 "1.00 Salvadoran colones random",
5515 "1.00 Equatorial Guinean Ekwele random",
5516 "1.00 Equatorial Guinean ekwele random",
5517 "1.00 Eritrean Nakfa random",
5518 "1.00 Eritrean nakfa random",
5519 "1.00 Eritrean nakfas random",
5520 "1.00 Estonian Kroon random",
5521 "1.00 Estonian kroon random",
5522 "1.00 Estonian kroons random",
5523 "1.00 Ethiopian Birr random",
5524 "1.00 Ethiopian birr random",
5525 "1.00 Ethiopian birrs random",
5526 "1.00 European Composite Unit random",
5527 "1.00 European Currency Unit random",
5528 "1.00 European Monetary Unit random",
5529 "1.00 European Unit of Account (XBC) random",
5530 "1.00 European Unit of Account (XBD) random",
5531 "1.00 European composite unit random",
5532 "1.00 European composite units random",
5533 "1.00 European currency unit random",
5534 "1.00 European currency units random",
5535 "1.00 European monetary unit random",
5536 "1.00 European monetary units random",
5537 "1.00 European unit of account (XBC) random",
5538 "1.00 European unit of account (XBD) random",
5539 "1.00 European units of account (XBC) random",
5540 "1.00 European units of account (XBD) random",
5541 "1.00 Falkland Islands Pound random",
5542 "1.00 Falkland Islands pound random",
5543 "1.00 Falkland Islands pounds random",
5544 "1.00 Fijian Dollar random",
5545 "1.00 Fijian dollar random",
5546 "1.00 Fijian dollars random",
5547 "1.00 Finnish Markka random",
5548 "1.00 Finnish markka random",
5549 "1.00 Finnish markkas random",
5550 "1.00 French Franc random",
5551 "1.00 French Gold Franc random",
5552 "1.00 French UIC-Franc random",
5553 "1.00 French UIC-franc random",
5554 "1.00 French UIC-francs random",
5555 "1.00 French franc random",
5556 "1.00 French francs random",
5557 "1.00 French gold franc random",
5558 "1.00 French gold francs random",
5559 "1.00 Gambian Dalasi random",
5560 "1.00 Gambian dalasi random",
5561 "1.00 Gambian dalasis random",
5562 "1.00 Georgian Kupon Larit random",
5563 "1.00 Georgian Lari random",
5564 "1.00 Georgian kupon larit random",
5565 "1.00 Georgian kupon larits random",
5566 "1.00 Georgian lari random",
5567 "1.00 Georgian laris random",
5568 "1.00 Ghanaian Cedi (1979\\u20132007) random",
5569 "1.00 Ghanaian Cedi random",
5570 "1.00 Ghanaian cedi (1979\\u20132007) random",
5571 "1.00 Ghanaian cedi random",
5572 "1.00 Ghanaian cedis (1979\\u20132007) random",
5573 "1.00 Ghanaian cedis random",
5574 "1.00 Gibraltar Pound random",
5575 "1.00 Gibraltar pound random",
5576 "1.00 Gibraltar pounds random",
5577 "1.00 Gold random",
5578 "1.00 Gold random",
5579 "1.00 Greek Drachma random",
5580 "1.00 Greek drachma random",
5581 "1.00 Greek drachmas random",
5582 "1.00 Guatemalan Quetzal random",
5583 "1.00 Guatemalan quetzal random",
5584 "1.00 Guatemalan quetzals random",
5585 "1.00 Guinean Franc random",
5586 "1.00 Guinean Syli random",
5587 "1.00 Guinean franc random",
5588 "1.00 Guinean francs random",
5589 "1.00 Guinean syli random",
5590 "1.00 Guinean sylis random",
5591 "1.00 Guinea-Bissau Peso random",
5592 "1.00 Guinea-Bissau peso random",
5593 "1.00 Guinea-Bissau pesos random",
5594 "1.00 Guyanaese Dollar random",
5595 "1.00 Guyanaese dollar random",
5596 "1.00 Guyanaese dollars random",
5597 "1.00 Haitian Gourde random",
5598 "1.00 Haitian gourde random",
5599 "1.00 Haitian gourdes random",
5600 "1.00 Honduran Lempira random",
5601 "1.00 Honduran lempira random",
5602 "1.00 Honduran lempiras random",
5603 "1.00 Hong Kong Dollar random",
5604 "1.00 Hong Kong dollar random",
5605 "1.00 Hong Kong dollars random",
5606 "1.00 Hungarian Forint random",
5607 "1.00 Hungarian forint random",
5608 "1.00 Hungarian forints random",
5609 "1.00 Icelandic Kr\\u00f3na random",
5610 "1.00 Icelandic kr\\u00f3na random",
5611 "1.00 Icelandic kr\\u00f3nur random",
5612 "1.00 Indian Rupee random",
5613 "1.00 Indian rupee random",
5614 "1.00 Indian rupees random",
5615 "1.00 Indonesian Rupiah random",
5616 "1.00 Indonesian rupiah random",
5617 "1.00 Indonesian rupiahs random",
5618 "1.00 Iranian Rial random",
5619 "1.00 Iranian rial random",
5620 "1.00 Iranian rials random",
5621 "1.00 Iraqi Dinar random",
5622 "1.00 Iraqi dinar random",
5623 "1.00 Iraqi dinars random",
5624 "1.00 Irish Pound random",
5625 "1.00 Irish pound random",
5626 "1.00 Irish pounds random",
5627 "1.00 Israeli Pound random",
5628 "1.00 Israeli new shekel random",
5629 "1.00 Israeli pound random",
5630 "1.00 Israeli pounds random",
5631 "1.00 Italian Lira random",
5632 "1.00 Italian lira random",
5633 "1.00 Italian liras random",
5634 "1.00 Jamaican Dollar random",
5635 "1.00 Jamaican dollar random",
5636 "1.00 Jamaican dollars random",
5637 "1.00 Japanese Yen random",
5638 "1.00 Japanese yen random",
5639 "1.00 Jordanian Dinar random",
5640 "1.00 Jordanian dinar random",
5641 "1.00 Jordanian dinars random",
5642 "1.00 Kazakhstani Tenge random",
5643 "1.00 Kazakhstani tenge random",
5644 "1.00 Kazakhstani tenges random",
5645 "1.00 Kenyan Shilling random",
5646 "1.00 Kenyan shilling random",
5647 "1.00 Kenyan shillings random",
5648 "1.00 Kuwaiti Dinar random",
5649 "1.00 Kuwaiti dinar random",
5650 "1.00 Kuwaiti dinars random",
5651 "1.00 Kyrgystani Som random",
5652 "1.00 Kyrgystani som random",
5653 "1.00 Kyrgystani soms random",
5654 "1.00 Laotian Kip random",
5655 "1.00 Laotian kip random",
5656 "1.00 Laotian kips random",
5657 "1.00 Latvian Lats random",
5658 "1.00 Latvian Ruble random",
5659 "1.00 Latvian lats random",
5660 "1.00 Latvian lati random",
5661 "1.00 Latvian ruble random",
5662 "1.00 Latvian rubles random",
5663 "1.00 Lebanese Pound random",
5664 "1.00 Lebanese pound random",
5665 "1.00 Lebanese pounds random",
5666 "1.00 Lesotho Loti random",
5667 "1.00 Lesotho loti random",
5668 "1.00 Lesotho lotis random",
5669 "1.00 Liberian Dollar random",
5670 "1.00 Liberian dollar random",
5671 "1.00 Liberian dollars random",
5672 "1.00 Libyan Dinar random",
5673 "1.00 Libyan dinar random",
5674 "1.00 Libyan dinars random",
5675 "1.00 Lithuanian Litas random",
5676 "1.00 Lithuanian Talonas random",
5677 "1.00 Lithuanian litas random",
5678 "1.00 Lithuanian litai random",
5679 "1.00 Lithuanian talonas random",
5680 "1.00 Lithuanian talonases random",
5681 "1.00 Luxembourgian Convertible Franc random",
5682 "1.00 Luxembourg Financial Franc random",
5683 "1.00 Luxembourgian Franc random",
5684 "1.00 Luxembourgian convertible franc random",
5685 "1.00 Luxembourgian convertible francs random",
5686 "1.00 Luxembourg financial franc random",
5687 "1.00 Luxembourg financial francs random",
5688 "1.00 Luxembourgian franc random",
5689 "1.00 Luxembourgian francs random",
5690 "1.00 Macanese Pataca random",
5691 "1.00 Macanese pataca random",
5692 "1.00 Macanese patacas random",
5693 "1.00 Macedonian Denar random",
5694 "1.00 Macedonian denar random",
5695 "1.00 Macedonian denari random",
5696 "1.00 Malagasy Ariaries random",
5697 "1.00 Malagasy Ariary random",
5698 "1.00 Malagasy Ariary random",
5699 "1.00 Malagasy Franc random",
5700 "1.00 Malagasy franc random",
5701 "1.00 Malagasy francs random",
5702 "1.00 Malawian Kwacha random",
5703 "1.00 Malawian Kwacha random",
5704 "1.00 Malawian Kwachas random",
5705 "1.00 Malaysian Ringgit random",
5706 "1.00 Malaysian ringgit random",
5707 "1.00 Malaysian ringgits random",
5708 "1.00 Maldivian Rufiyaa random",
5709 "1.00 Maldivian rufiyaa random",
5710 "1.00 Maldivian rufiyaas random",
5711 "1.00 Malian Franc random",
5712 "1.00 Malian franc random",
5713 "1.00 Malian francs random",
5714 "1.00 Maltese Lira random",
5715 "1.00 Maltese Pound random",
5716 "1.00 Maltese lira random",
5717 "1.00 Maltese liras random",
5718 "1.00 Maltese pound random",
5719 "1.00 Maltese pounds random",
5720 "1.00 Mauritanian Ouguiya random",
5721 "1.00 Mauritanian ouguiya random",
5722 "1.00 Mauritanian ouguiyas random",
5723 "1.00 Mauritian Rupee random",
5724 "1.00 Mauritian rupee random",
5725 "1.00 Mauritian rupees random",
5726 "1.00 Mexican Peso random",
5727 "1.00 Mexican Silver Peso (1861\\u20131992) random",
5728 "1.00 Mexican Investment Unit random",
5729 "1.00 Mexican peso random",
5730 "1.00 Mexican pesos random",
5731 "1.00 Mexican silver peso (1861\\u20131992) random",
5732 "1.00 Mexican silver pesos (1861\\u20131992) random",
5733 "1.00 Mexican investment unit random",
5734 "1.00 Mexican investment units random",
5735 "1.00 Moldovan Leu random",
5736 "1.00 Moldovan leu random",
5737 "1.00 Moldovan lei random",
5738 "1.00 Mongolian Tugrik random",
5739 "1.00 Mongolian tugrik random",
5740 "1.00 Mongolian tugriks random",
5741 "1.00 Moroccan Dirham random",
5742 "1.00 Moroccan Franc random",
5743 "1.00 Moroccan dirham random",
5744 "1.00 Moroccan dirhams random",
5745 "1.00 Moroccan franc random",
5746 "1.00 Moroccan francs random",
5747 "1.00 Mozambican Escudo random",
5748 "1.00 Mozambican Metical random",
5749 "1.00 Mozambican escudo random",
5750 "1.00 Mozambican escudos random",
5751 "1.00 Mozambican metical random",
5752 "1.00 Mozambican meticals random",
5753 "1.00 Myanmar Kyat random",
5754 "1.00 Myanmar kyat random",
5755 "1.00 Myanmar kyats random",
5756 "1.00 Namibian Dollar random",
5757 "1.00 Namibian dollar random",
5758 "1.00 Namibian dollars random",
5759 "1.00 Nepalese Rupee random",
5760 "1.00 Nepalese rupee random",
5761 "1.00 Nepalese rupees random",
5762 "1.00 Netherlands Antillean Guilder random",
5763 "1.00 Netherlands Antillean guilder random",
5764 "1.00 Netherlands Antillean guilders random",
5765 "1.00 Dutch Guilder random",
5766 "1.00 Dutch guilder random",
5767 "1.00 Dutch guilders random",
5768 "1.00 Israeli New Shekel random",
5769 "1.00 Israeli new shekels random",
5770 "1.00 New Zealand Dollar random",
5771 "1.00 New Zealand dollar random",
5772 "1.00 New Zealand dollars random",
5773 "1.00 Nicaraguan C\\u00f3rdoba random",
5774 "1.00 Nicaraguan C\\u00f3rdoba (1988\\u20131991) random",
5775 "1.00 Nicaraguan c\\u00f3rdoba random",
5776 "1.00 Nicaraguan c\\u00f3rdoba random",
5777 "1.00 Nicaraguan c\\u00f3rdoba (1988\\u20131991) random",
5778 "1.00 Nicaraguan c\\u00f3rdobas (1988\\u20131991) random",
5779 "1.00 Nigerian Naira random",
5780 "1.00 Nigerian naira random",
5781 "1.00 Nigerian nairas random",
5782 "1.00 North Korean Won random",
5783 "1.00 North Korean won random",
5784 "1.00 North Korean won random",
5785 "1.00 Norwegian Krone random",
5786 "1.00 Norwegian krone random",
5787 "1.00 Norwegian kroner random",
5788 "1.00 Mozambican Metical (1980\\u20132006) random",
5789 "1.00 Mozambican metical (1980\\u20132006) random",
5790 "1.00 Mozambican meticals (1980\\u20132006) random",
5791 "1.00 Romanian Lei (1952\\u20132006) random",
5792 "1.00 Romanian Leu (1952\\u20132006) random",
5793 "1.00 Romanian leu (1952\\u20132006) random",
5794 "1.00 Serbian Dinar (2002\\u20132006) random",
5795 "1.00 Serbian dinar (2002\\u20132006) random",
5796 "1.00 Serbian dinars (2002\\u20132006) random",
5797 "1.00 Sudanese Dinar (1992\\u20132007) random",
5798 "1.00 Sudanese Pound (1957\\u20131998) random",
5799 "1.00 Sudanese dinar (1992\\u20132007) random",
5800 "1.00 Sudanese dinars (1992\\u20132007) random",
5801 "1.00 Sudanese pound (1957\\u20131998) random",
5802 "1.00 Sudanese pounds (1957\\u20131998) random",
5803 "1.00 Turkish Lira (1922\\u20132005) random",
5804 "1.00 Turkish Lira (1922\\u20132005) random",
5805 "1.00 Omani Rial random",
5806 "1.00 Omani rial random",
5807 "1.00 Omani rials random",
5808 "1.00 Pakistani Rupee random",
5809 "1.00 Pakistani rupee random",
5810 "1.00 Pakistani rupees random",
5811 "1.00 Palladium random",
5812 "1.00 Palladium random",
5813 "1.00 Panamanian Balboa random",
5814 "1.00 Panamanian balboa random",
5815 "1.00 Panamanian balboas random",
5816 "1.00 Papua New Guinean Kina random",
5817 "1.00 Papua New Guinean kina random",
5818 "1.00 Papua New Guinean kina random",
5819 "1.00 Paraguayan Guarani random",
5820 "1.00 Paraguayan guarani random",
5821 "1.00 Paraguayan guaranis random",
5822 "1.00 Peruvian Inti random",
5823 "1.00 Peruvian Sol random",
5824 "1.00 Peruvian Sol (1863\\u20131965) random",
5825 "1.00 Peruvian inti random",
5826 "1.00 Peruvian intis random",
5827 "1.00 Peruvian sol random",
5828 "1.00 Peruvian soles random",
5829 "1.00 Peruvian sol (1863\\u20131965) random",
5830 "1.00 Peruvian soles (1863\\u20131965) random",
Frank Tangd2858cb2022-04-08 20:34:12 -07005831 "1.00 Philippine Peso random",
5832 "1.00 Philippine peso random",
5833 "1.00 Philippine pesos random",
Frank Tang3e05d9d2021-11-08 14:04:04 -08005834 "1.00 Platinum random",
5835 "1.00 Platinum random",
5836 "1.00 Polish Zloty (1950\\u20131995) random",
5837 "1.00 Polish Zloty random",
5838 "1.00 Polish zlotys random",
5839 "1.00 Polish zloty (PLZ) random",
5840 "1.00 Polish zloty random",
5841 "1.00 Polish zlotys (PLZ) random",
5842 "1.00 Portuguese Escudo random",
5843 "1.00 Portuguese Guinea Escudo random",
5844 "1.00 Portuguese Guinea escudo random",
5845 "1.00 Portuguese Guinea escudos random",
5846 "1.00 Portuguese escudo random",
5847 "1.00 Portuguese escudos random",
Frank Tang1f164ee2022-11-08 12:31:27 -08005848 "1.00 Qatari Riyal random",
5849 "1.00 Qatari riyal random",
5850 "1.00 Qatari riyals random",
Frank Tang3e05d9d2021-11-08 14:04:04 -08005851 "1.00 RINET Funds random",
5852 "1.00 RINET Funds random",
5853 "1.00 Rhodesian Dollar random",
5854 "1.00 Rhodesian dollar random",
5855 "1.00 Rhodesian dollars random",
5856 "1.00 Romanian Leu random",
5857 "1.00 Romanian lei random",
5858 "1.00 Romanian leu random",
5859 "1.00 Russian Ruble (1991\\u20131998) random",
5860 "1.00 Russian Ruble random",
5861 "1.00 Russian ruble (1991\\u20131998) random",
5862 "1.00 Russian ruble random",
5863 "1.00 Russian rubles (1991\\u20131998) random",
5864 "1.00 Russian rubles random",
5865 "1.00 Rwandan Franc random",
5866 "1.00 Rwandan franc random",
5867 "1.00 Rwandan francs random",
5868 "1.00 St. Helena Pound random",
5869 "1.00 St. Helena pound random",
5870 "1.00 St. Helena pounds random",
5871 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra random",
5872 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra random",
5873 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras random",
5874 "1.00 Saudi Riyal random",
5875 "1.00 Saudi riyal random",
5876 "1.00 Saudi riyals random",
5877 "1.00 Serbian Dinar random",
5878 "1.00 Serbian dinar random",
5879 "1.00 Serbian dinars random",
5880 "1.00 Seychellois Rupee random",
5881 "1.00 Seychellois rupee random",
5882 "1.00 Seychellois rupees random",
5883 "1.00 Sierra Leonean Leone random",
5884 "1.00 Sierra Leonean leone random",
5885 "1.00 Sierra Leonean leones random",
5886 "1.00 Singapore Dollar random",
5887 "1.00 Singapore dollar random",
5888 "1.00 Singapore dollars random",
5889 "1.00 Slovak Koruna random",
5890 "1.00 Slovak koruna random",
5891 "1.00 Slovak korunas random",
5892 "1.00 Slovenian Tolar random",
5893 "1.00 Slovenian tolar random",
5894 "1.00 Slovenian tolars random",
5895 "1.00 Solomon Islands Dollar random",
5896 "1.00 Solomon Islands dollar random",
5897 "1.00 Solomon Islands dollars random",
5898 "1.00 Somali Shilling random",
5899 "1.00 Somali shilling random",
5900 "1.00 Somali shillings random",
5901 "1.00 South African Rand (financial) random",
5902 "1.00 South African Rand random",
5903 "1.00 South African rand (financial) random",
5904 "1.00 South African rand random",
5905 "1.00 South African rands (financial) random",
5906 "1.00 South African rand random",
5907 "1.00 South Korean Won random",
5908 "1.00 South Korean won random",
5909 "1.00 South Korean won random",
5910 "1.00 Soviet Rouble random",
5911 "1.00 Soviet rouble random",
5912 "1.00 Soviet roubles random",
5913 "1.00 Spanish Peseta (A account) random",
5914 "1.00 Spanish Peseta (convertible account) random",
5915 "1.00 Spanish Peseta random",
5916 "1.00 Spanish peseta (A account) random",
5917 "1.00 Spanish peseta (convertible account) random",
5918 "1.00 Spanish peseta random",
5919 "1.00 Spanish pesetas (A account) random",
5920 "1.00 Spanish pesetas (convertible account) random",
5921 "1.00 Spanish pesetas random",
5922 "1.00 Special Drawing Rights random",
5923 "1.00 Sri Lankan Rupee random",
5924 "1.00 Sri Lankan rupee random",
5925 "1.00 Sri Lankan rupees random",
5926 "1.00 Sudanese Pound random",
5927 "1.00 Sudanese pound random",
5928 "1.00 Sudanese pounds random",
5929 "1.00 Surinamese Dollar random",
5930 "1.00 Surinamese dollar random",
5931 "1.00 Surinamese dollars random",
5932 "1.00 Surinamese Guilder random",
5933 "1.00 Surinamese guilder random",
5934 "1.00 Surinamese guilders random",
5935 "1.00 Swazi Lilangeni random",
5936 "1.00 Swazi lilangeni random",
5937 "1.00 Swazi emalangeni random",
5938 "1.00 Swedish Krona random",
5939 "1.00 Swedish krona random",
5940 "1.00 Swedish kronor random",
5941 "1.00 Swiss Franc random",
5942 "1.00 Swiss franc random",
5943 "1.00 Swiss francs random",
5944 "1.00 Syrian Pound random",
5945 "1.00 Syrian pound random",
5946 "1.00 Syrian pounds random",
5947 "1.00 New Taiwan Dollar random",
5948 "1.00 New Taiwan dollar random",
5949 "1.00 New Taiwan dollars random",
5950 "1.00 Tajikistani Ruble random",
5951 "1.00 Tajikistani Somoni random",
5952 "1.00 Tajikistani ruble random",
5953 "1.00 Tajikistani rubles random",
5954 "1.00 Tajikistani somoni random",
5955 "1.00 Tajikistani somonis random",
5956 "1.00 Tanzanian Shilling random",
5957 "1.00 Tanzanian shilling random",
5958 "1.00 Tanzanian shillings random",
5959 "1.00 Testing Currency Code random",
5960 "1.00 Testing Currency Code random",
5961 "1.00 Thai Baht random",
5962 "1.00 Thai baht random",
5963 "1.00 Thai baht random",
5964 "1.00 Timorese Escudo random",
5965 "1.00 Timorese escudo random",
5966 "1.00 Timorese escudos random",
5967 "1.00 Trinidad & Tobago Dollar random",
5968 "1.00 Trinidad & Tobago dollar random",
5969 "1.00 Trinidad & Tobago dollars random",
5970 "1.00 Tunisian Dinar random",
5971 "1.00 Tunisian dinar random",
5972 "1.00 Tunisian dinars random",
5973 "1.00 Turkish Lira random",
5974 "1.00 Turkish Lira random",
5975 "1.00 Turkish lira random",
5976 "1.00 Turkmenistani Manat random",
5977 "1.00 Turkmenistani manat random",
5978 "1.00 Turkmenistani manat random",
5979 "1.00 US Dollar (Next day) random",
5980 "1.00 US Dollar (Same day) random",
5981 "1.00 US Dollar random",
5982 "1.00 US dollar (next day) random",
5983 "1.00 US dollar (same day) random",
5984 "1.00 US dollar random",
5985 "1.00 US dollars (next day) random",
5986 "1.00 US dollars (same day) random",
5987 "1.00 US dollars random",
5988 "1.00 Ugandan Shilling (1966\\u20131987) random",
5989 "1.00 Ugandan Shilling random",
5990 "1.00 Ugandan shilling (1966\\u20131987) random",
5991 "1.00 Ugandan shilling random",
5992 "1.00 Ugandan shillings (1966\\u20131987) random",
5993 "1.00 Ugandan shillings random",
5994 "1.00 Ukrainian Hryvnia random",
5995 "1.00 Ukrainian Karbovanets random",
5996 "1.00 Ukrainian hryvnia random",
5997 "1.00 Ukrainian hryvnias random",
5998 "1.00 Ukrainian karbovanets random",
5999 "1.00 Ukrainian karbovantsiv random",
6000 "1.00 Colombian Real Value Unit random",
6001 "1.00 United Arab Emirates Dirham random",
6002 "1.00 Unknown Currency random",
6003 "1.00 Uruguayan Peso (1975\\u20131993) random",
6004 "1.00 Uruguayan Peso random",
6005 "1.00 Uruguayan Peso (Indexed Units) random",
6006 "1.00 Uruguayan peso (1975\\u20131993) random",
6007 "1.00 Uruguayan peso (indexed units) random",
6008 "1.00 Uruguayan peso random",
6009 "1.00 Uruguayan pesos (1975\\u20131993) random",
6010 "1.00 Uruguayan pesos (indexed units) random",
6011 "1.00 Uzbekistani Som random",
6012 "1.00 Uzbekistani som random",
6013 "1.00 Uzbekistani som random",
6014 "1.00 Vanuatu Vatu random",
6015 "1.00 Vanuatu vatu random",
6016 "1.00 Vanuatu vatus random",
6017 "1.00 Venezuelan Bol\\u00edvar random",
6018 "1.00 Venezuelan Bol\\u00edvar (1871\\u20132008) random",
6019 "1.00 Venezuelan bol\\u00edvar random",
6020 "1.00 Venezuelan bol\\u00edvars random",
6021 "1.00 Venezuelan bol\\u00edvar (1871\\u20132008) random",
6022 "1.00 Venezuelan bol\\u00edvars (1871\\u20132008) random",
6023 "1.00 Vietnamese Dong random",
6024 "1.00 Vietnamese dong random",
6025 "1.00 Vietnamese dong random",
6026 "1.00 WIR Euro random",
6027 "1.00 WIR Franc random",
6028 "1.00 WIR euro random",
6029 "1.00 WIR euros random",
6030 "1.00 WIR franc random",
6031 "1.00 WIR francs random",
6032 "1.00 Samoan Tala random",
6033 "1.00 Samoan tala random",
6034 "1.00 Samoan tala random",
6035 "1.00 Yemeni Dinar random",
6036 "1.00 Yemeni Rial random",
6037 "1.00 Yemeni dinar random",
6038 "1.00 Yemeni dinars random",
6039 "1.00 Yemeni rial random",
6040 "1.00 Yemeni rials random",
6041 "1.00 Yugoslavian Convertible Dinar (1990\\u20131992) random",
6042 "1.00 Yugoslavian Hard Dinar (1966\\u20131990) random",
6043 "1.00 Yugoslavian New Dinar (1994\\u20132002) random",
6044 "1.00 Yugoslavian convertible dinar (1990\\u20131992) random",
6045 "1.00 Yugoslavian convertible dinars (1990\\u20131992) random",
6046 "1.00 Yugoslavian hard dinar (1966\\u20131990) random",
6047 "1.00 Yugoslavian hard dinars (1966\\u20131990) random",
6048 "1.00 Yugoslavian new dinar (1994\\u20132002) random",
6049 "1.00 Yugoslavian new dinars (1994\\u20132002) random",
6050 "1.00 Zairean New Zaire (1993\\u20131998) random",
6051 "1.00 Zairean Zaire (1971\\u20131993) random",
6052 "1.00 Zairean new zaire (1993\\u20131998) random",
6053 "1.00 Zairean new zaires (1993\\u20131998) random",
6054 "1.00 Zairean zaire (1971\\u20131993) random",
6055 "1.00 Zairean zaires (1971\\u20131993) random",
6056 "1.00 Zambian Kwacha random",
6057 "1.00 Zambian kwacha random",
6058 "1.00 Zambian kwachas random",
6059 "1.00 Zimbabwean Dollar (1980\\u20132008) random",
6060 "1.00 Zimbabwean dollar (1980\\u20132008) random",
6061 "1.00 Zimbabwean dollars (1980\\u20132008) random",
6062 "1.00 euro random",
6063 "1.00 euros random",
6064 "1.00 Turkish lira (1922\\u20132005) random",
6065 "1.00 special drawing rights random",
6066 "1.00 Colombian real value unit random",
6067 "1.00 Colombian real value units random",
6068 "1.00 unknown currency random",
6069 };
6070
6071 const char* WRONG_DATA[] = {
6072 // Following are missing one last char in the currency name
6073 "1.00 Nicaraguan Cordob",
6074 "1.00 Namibian Dolla",
6075 "1.00 Namibian dolla",
6076 "1.00 Nepalese Rupe",
6077 "1.00 Nepalese rupe",
6078 "1.00 Netherlands Antillean Guilde",
6079 "1.00 Netherlands Antillean guilde",
6080 "1.00 Dutch Guilde",
6081 "1.00 Dutch guilde",
6082 "1.00 Israeli New Sheqe",
6083 "1.00 New Zealand Dolla",
6084 "1.00 New Zealand dolla",
6085 "1.00 Nicaraguan cordob",
6086 "1.00 Nigerian Nair",
6087 "1.00 Nigerian nair",
6088 "1.00 North Korean Wo",
6089 "1.00 North Korean wo",
6090 "1.00 Norwegian Kron",
6091 "1.00 Norwegian kron",
6092 "1.00 US dolla",
6093 "1.00",
6094 "A1.00",
6095 "AD1.00",
6096 "AE1.00",
6097 "AF1.00",
6098 "AL1.00",
6099 "AM1.00",
6100 "AN1.00",
6101 "AO1.00",
6102 "AR1.00",
6103 "AT1.00",
6104 "AU1.00",
6105 "AW1.00",
6106 "AZ1.00",
6107 "Afghan Afghan1.00",
6108 "Afghan Afghani (1927\\u201320021.00",
6109 "Afl1.00",
6110 "Albanian Le1.00",
6111 "Algerian Dina1.00",
6112 "Andorran Peset1.00",
6113 "Angolan Kwanz1.00",
6114 "Angolan Kwanza (1977\\u201319901.00",
6115 "Angolan Readjusted Kwanza (1995\\u201319991.00",
6116 "Angolan New Kwanza (1990\\u201320001.00",
6117 "Argentine Austra1.00",
6118 "Argentine Pes1.00",
6119 "Argentine Peso (1983\\u201319851.00",
6120 "Armenian Dra1.00",
6121 "Aruban Flori1.00",
6122 "Australian Dolla1.00",
6123 "Austrian Schillin1.00",
6124 "Azerbaijani Mana1.00",
6125 "Azerbaijani Manat (1993\\u201320061.00",
6126 "B1.00",
6127 "BA1.00",
6128 "BB1.00",
6129 "BE1.00",
6130 "BG1.00",
6131 "BH1.00",
6132 "BI1.00",
6133 "BM1.00",
6134 "BN1.00",
6135 "BO1.00",
6136 "BR1.00",
6137 "BS1.00",
6138 "BT1.00",
6139 "BU1.00",
6140 "BW1.00",
6141 "BY1.00",
6142 "BZ1.00",
6143 "Bahamian Dolla1.00",
6144 "Bahraini Dina1.00",
6145 "Bangladeshi Tak1.00",
6146 "Barbadian Dolla1.00",
6147 "Bds1.00",
6148 "Belarusian Ruble (1994\\u201319991.00",
6149 "Belarusian Rubl1.00",
6150 "Belgian Fran1.00",
6151 "Belgian Franc (convertible1.00",
6152 "Belgian Franc (financial1.00",
6153 "Belize Dolla1.00",
6154 "Bermudan Dolla1.00",
6155 "Bhutanese Ngultru1.00",
6156 "Bolivian Mvdo1.00",
6157 "Bolivian Pes1.00",
6158 "Bolivian Bolivian1.00",
6159 "Bosnia-Herzegovina Convertible Mar1.00",
6160 "Bosnia-Herzegovina Dina1.00",
6161 "Botswanan Pul1.00",
6162 "Brazilian Cruzad1.00",
6163 "Brazilian Cruzado Nov1.00",
6164 "Brazilian Cruzeir1.00",
6165 "Brazilian Cruzeiro (1990\\u201319931.00",
6166 "Brazilian New Cruzeiro (1967\\u201319861.00",
6167 "Brazilian Rea1.00",
6168 "British Pound Sterlin1.00",
6169 "Brunei Dolla1.00",
6170 "Bulgarian Hard Le1.00",
6171 "Bulgarian Le1.00",
6172 "Burmese Kya1.00",
6173 "Burundian Fran1.00",
6174 "C1.00",
6175 "CA1.00",
6176 "CD1.00",
6177 "CFP Fran1.00",
6178 "CFP1.00",
6179 "CH1.00",
6180 "CL1.00",
6181 "CN1.00",
6182 "CO1.00",
6183 "CS1.00",
6184 "CU1.00",
6185 "CV1.00",
6186 "CY1.00",
6187 "CZ1.00",
6188 "Cambodian Rie1.00",
6189 "Canadian Dolla1.00",
6190 "Cape Verdean Escud1.00",
6191 "Cayman Islands Dolla1.00",
6192 "Chilean Pes1.00",
6193 "Chilean Unit of Accoun1.00",
6194 "Chinese Yua1.00",
6195 "Colombian Pes1.00",
6196 "Comoro Fran1.00",
6197 "Congolese Fran1.00",
6198 "Costa Rican Col\\u00f31.00",
6199 "Croatian Dina1.00",
6200 "Croatian Kun1.00",
6201 "Cuban Pes1.00",
6202 "Cypriot Poun1.00",
6203 "Czech Republic Korun1.00",
6204 "Czechoslovak Hard Korun1.00",
6205 "D1.00",
6206 "DD1.00",
6207 "DE1.00",
6208 "DJ1.00",
6209 "DK1.00",
6210 "DO1.00",
6211 "DZ1.00",
6212 "Danish Kron1.00",
6213 "German Mar1.00",
6214 "Djiboutian Fran1.00",
6215 "Dk1.00",
6216 "Dominican Pes1.00",
6217 "EC1.00",
6218 "EE1.00",
6219 "EG1.00",
6220 "EQ1.00",
6221 "ER1.00",
6222 "ES1.00",
6223 "ET1.00",
6224 "EU1.00",
6225 "East Caribbean Dolla1.00",
6226 "East German Ostmar1.00",
6227 "Ecuadorian Sucr1.00",
6228 "Ecuadorian Unit of Constant Valu1.00",
6229 "Egyptian Poun1.00",
6230 "Ekwel1.00",
6231 "Salvadoran Col\\u00f31.00",
6232 "Equatorial Guinean Ekwel1.00",
6233 "Eritrean Nakf1.00",
6234 "Es1.00",
6235 "Estonian Kroo1.00",
6236 "Ethiopian Bir1.00",
6237 "Eur1.00",
6238 "European Composite Uni1.00",
6239 "European Currency Uni1.00",
6240 "European Monetary Uni1.00",
6241 "European Unit of Account (XBC1.00",
6242 "European Unit of Account (XBD1.00",
6243 "F1.00",
6244 "FB1.00",
6245 "FI1.00",
6246 "FJ1.00",
6247 "FK1.00",
6248 "FR1.00",
6249 "Falkland Islands Poun1.00",
6250 "Fd1.00",
6251 "Fijian Dolla1.00",
6252 "Finnish Markk1.00",
6253 "Fr1.00",
6254 "French Fran1.00",
6255 "French Gold Fran1.00",
6256 "French UIC-Fran1.00",
6257 "G1.00",
6258 "GB1.00",
6259 "GE1.00",
6260 "GH1.00",
6261 "GI1.00",
6262 "GM1.00",
6263 "GN1.00",
6264 "GQ1.00",
6265 "GR1.00",
6266 "GT1.00",
6267 "GW1.00",
6268 "GY1.00",
6269 "Gambian Dalas1.00",
6270 "Georgian Kupon Lari1.00",
6271 "Georgian Lar1.00",
6272 "Ghanaian Ced1.00",
6273 "Ghanaian Cedi (1979\\u201320071.00",
6274 "Gibraltar Poun1.00",
6275 "Gol1.00",
6276 "Greek Drachm1.00",
6277 "Guatemalan Quetza1.00",
6278 "Guinean Fran1.00",
6279 "Guinean Syl1.00",
6280 "Guinea-Bissau Pes1.00",
6281 "Guyanaese Dolla1.00",
6282 "HK1.00",
6283 "HN1.00",
6284 "HR1.00",
6285 "HT1.00",
6286 "HU1.00",
6287 "Haitian Gourd1.00",
6288 "Honduran Lempir1.00",
6289 "Hong Kong Dolla1.00",
6290 "Hungarian Forin1.00",
6291 "I1.00",
6292 "IE1.00",
6293 "IL1.00",
6294 "IN1.00",
6295 "IQ1.00",
6296 "IR1.00",
6297 "IS1.00",
6298 "IT1.00",
6299 "Icelandic Kron1.00",
6300 "Indian Rupe1.00",
6301 "Indonesian Rupia1.00",
6302 "Iranian Ria1.00",
6303 "Iraqi Dina1.00",
6304 "Irish Poun1.00",
6305 "Israeli Poun1.00",
6306 "Italian Lir1.00",
6307 "J1.00",
6308 "JM1.00",
6309 "JO1.00",
6310 "JP1.00",
6311 "Jamaican Dolla1.00",
6312 "Japanese Ye1.00",
6313 "Jordanian Dina1.00",
6314 "K S1.00",
6315 "K1.00",
6316 "KE1.00",
6317 "KG1.00",
6318 "KH1.00",
6319 "KP1.00",
6320 "KR1.00",
6321 "KW1.00",
6322 "KY1.00",
6323 "KZ1.00",
6324 "Kazakhstani Teng1.00",
6325 "Kenyan Shillin1.00",
6326 "Kuwaiti Dina1.00",
6327 "Kyrgystani So1.00",
6328 "LA1.00",
6329 "LB1.00",
6330 "LK1.00",
6331 "LR1.00",
6332 "LT1.00",
6333 "LU1.00",
6334 "LV1.00",
6335 "LY1.00",
6336 "Laotian Ki1.00",
6337 "Latvian Lat1.00",
6338 "Latvian Rubl1.00",
6339 "Lebanese Poun1.00",
6340 "Lesotho Lot1.00",
6341 "Liberian Dolla1.00",
6342 "Libyan Dina1.00",
6343 "Lithuanian Lit1.00",
6344 "Lithuanian Talona1.00",
6345 "Luxembourgian Convertible Fran1.00",
6346 "Luxembourg Financial Fran1.00",
6347 "Luxembourgian Fran1.00",
6348 "MA1.00",
6349 "MD1.00",
6350 "MDe1.00",
6351 "MEX1.00",
6352 "MG1.00",
6353 "ML1.00",
6354 "MM1.00",
6355 "MN1.00",
6356 "MO1.00",
6357 "MR1.00",
6358 "MT1.00",
6359 "MU1.00",
6360 "MV1.00",
6361 "MW1.00",
6362 "MX1.00",
6363 "MY1.00",
6364 "MZ1.00",
6365 "Macanese Patac1.00",
6366 "Macedonian Dena1.00",
6367 "Malagasy Ariar1.00",
6368 "Malagasy Fran1.00",
6369 "Malawian Kwach1.00",
6370 "Malaysian Ringgi1.00",
6371 "Maldivian Rufiya1.00",
6372 "Malian Fran1.00",
6373 "Malot1.00",
6374 "Maltese Lir1.00",
6375 "Maltese Poun1.00",
6376 "Mauritanian Ouguiy1.00",
6377 "Mauritian Rupe1.00",
6378 "Mexican Pes1.00",
6379 "Mexican Silver Peso (1861\\u201319921.00",
6380 "Mexican Investment Uni1.00",
6381 "Moldovan Le1.00",
6382 "Mongolian Tugri1.00",
6383 "Moroccan Dirha1.00",
6384 "Moroccan Fran1.00",
6385 "Mozambican Escud1.00",
6386 "Mozambican Metica1.00",
6387 "Myanmar Kya1.00",
6388 "N1.00",
6389 "NA1.00",
6390 "NAf1.00",
6391 "NG1.00",
6392 "NI1.00",
6393 "NK1.00",
6394 "NL1.00",
6395 "NO1.00",
6396 "NP1.00",
6397 "NT1.00",
6398 "Namibian Dolla1.00",
6399 "Nepalese Rupe1.00",
6400 "Netherlands Antillean Guilde1.00",
6401 "Dutch Guilde1.00",
6402 "Israeli New Sheqe1.00",
6403 "New Zealand Dolla1.00",
6404 "Nicaraguan C\\u00f3rdoba (1988\\u201319911.00",
6405 "Nicaraguan C\\u00f3rdob1.00",
6406 "Nigerian Nair1.00",
6407 "North Korean Wo1.00",
6408 "Norwegian Kron1.00",
6409 "Nr1.00",
6410 "OM1.00",
6411 "Old Mozambican Metica1.00",
6412 "Romanian Leu (1952\\u201320061.00",
6413 "Serbian Dinar (2002\\u201320061.00",
6414 "Sudanese Dinar (1992\\u201320071.00",
6415 "Sudanese Pound (1957\\u201319981.00",
6416 "Turkish Lira (1922\\u201320051.00",
6417 "Omani Ria1.00",
6418 "PA1.00",
6419 "PE1.00",
6420 "PG1.00",
6421 "PH1.00",
6422 "PK1.00",
6423 "PL1.00",
6424 "PT1.00",
6425 "PY1.00",
6426 "Pakistani Rupe1.00",
6427 "Palladiu1.00",
6428 "Panamanian Balbo1.00",
6429 "Papua New Guinean Kin1.00",
6430 "Paraguayan Guaran1.00",
6431 "Peruvian Int1.00",
6432 "Peruvian Sol (1863\\u201319651.00",
6433 "Peruvian Sol Nuev1.00",
6434 "Philippine Pes1.00",
6435 "Platinu1.00",
6436 "Polish Zlot1.00",
6437 "Polish Zloty (1950\\u201319951.00",
6438 "Portuguese Escud1.00",
6439 "Portuguese Guinea Escud1.00",
6440 "Pr1.00",
6441 "QA1.00",
Frank Tang1f164ee2022-11-08 12:31:27 -08006442 "Qatari Riya1.00",
Frank Tang3e05d9d2021-11-08 14:04:04 -08006443 "RD1.00",
6444 "RH1.00",
6445 "RINET Fund1.00",
6446 "RS1.00",
6447 "RU1.00",
6448 "RW1.00",
6449 "Rb1.00",
6450 "Rhodesian Dolla1.00",
6451 "Romanian Le1.00",
6452 "Russian Rubl1.00",
6453 "Russian Ruble (1991\\u201319981.00",
6454 "Rwandan Fran1.00",
6455 "S1.00",
6456 "SA1.00",
6457 "SB1.00",
6458 "SC1.00",
6459 "SD1.00",
6460 "SE1.00",
6461 "SG1.00",
6462 "SH1.00",
6463 "SI1.00",
6464 "SK1.00",
6465 "SL R1.00",
6466 "SL1.00",
6467 "SO1.00",
6468 "ST1.00",
6469 "SU1.00",
6470 "SV1.00",
6471 "SY1.00",
6472 "SZ1.00",
6473 "St. Helena Poun1.00",
6474 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobr1.00",
6475 "Saudi Riya1.00",
6476 "Serbian Dina1.00",
6477 "Seychellois Rupe1.00",
6478 "Sh1.00",
6479 "Sierra Leonean Leon1.00",
6480 "Silve1.00",
6481 "Singapore Dolla1.00",
6482 "Slovak Korun1.00",
6483 "Slovenian Tola1.00",
6484 "Solomon Islands Dolla1.00",
6485 "Somali Shillin1.00",
6486 "South African Ran1.00",
6487 "South African Rand (financial1.00",
6488 "South Korean Wo1.00",
6489 "Soviet Roubl1.00",
6490 "Spanish Peset1.00",
6491 "Spanish Peseta (A account1.00",
6492 "Spanish Peseta (convertible account1.00",
6493 "Special Drawing Right1.00",
6494 "Sri Lankan Rupe1.00",
6495 "Sudanese Poun1.00",
6496 "Surinamese Dolla1.00",
6497 "Surinamese Guilde1.00",
6498 "Swazi Lilangen1.00",
6499 "Swedish Kron1.00",
6500 "Swiss Fran1.00",
6501 "Syrian Poun1.00",
6502 "T S1.00",
6503 "TH1.00",
6504 "TJ1.00",
6505 "TM1.00",
6506 "TN1.00",
6507 "TO1.00",
6508 "TP1.00",
6509 "TR1.00",
6510 "TT1.00",
6511 "TW1.00",
6512 "TZ1.00",
6513 "New Taiwan Dolla1.00",
6514 "Tajikistani Rubl1.00",
6515 "Tajikistani Somon1.00",
6516 "Tanzanian Shillin1.00",
6517 "Testing Currency Cod1.00",
6518 "Thai Bah1.00",
6519 "Timorese Escud1.00",
6520 "Tongan Pa\\u20bbang1.00",
6521 "Trinidad & Tobago Dolla1.00",
6522 "Tunisian Dina1.00",
6523 "Turkish Lir1.00",
6524 "Turkmenistani Mana1.00",
6525 "U S1.00",
6526 "U1.00",
6527 "UA1.00",
6528 "UG1.00",
6529 "US Dolla1.00",
6530 "US Dollar (Next day1.00",
6531 "US Dollar (Same day1.00",
6532 "US1.00",
6533 "UY1.00",
6534 "UZ1.00",
6535 "Ugandan Shillin1.00",
6536 "Ugandan Shilling (1966\\u201319871.00",
6537 "Ukrainian Hryvni1.00",
6538 "Ukrainian Karbovanet1.00",
6539 "Colombian Real Value Uni1.00",
6540 "United Arab Emirates Dirha1.00",
6541 "Unknown Currenc1.00",
6542 "Ur1.00",
6543 "Uruguay Peso (1975\\u201319931.00",
6544 "Uruguay Peso Uruguay1.00",
6545 "Uruguay Peso (Indexed Units1.00",
6546 "Uzbekistani So1.00",
6547 "V1.00",
6548 "VE1.00",
6549 "VN1.00",
6550 "VU1.00",
6551 "Vanuatu Vat1.00",
6552 "Venezuelan Bol\\u00edva1.00",
6553 "Venezuelan Bol\\u00edvar Fuert1.00",
6554 "Vietnamese Don1.00",
6555 "West African CFA Fran1.00",
6556 "Central African CFA Fran1.00",
6557 "WIR Eur1.00",
6558 "WIR Fran1.00",
6559 "WS1.00",
6560 "Samoa Tal1.00",
6561 "XA1.00",
6562 "XB1.00",
6563 "XC1.00",
6564 "XD1.00",
6565 "XE1.00",
6566 "XF1.00",
6567 "XO1.00",
6568 "XP1.00",
6569 "XR1.00",
6570 "XT1.00",
6571 "XX1.00",
6572 "YD1.00",
6573 "YE1.00",
6574 "YU1.00",
6575 "Yemeni Dina1.00",
6576 "Yemeni Ria1.00",
6577 "Yugoslavian Convertible Dina1.00",
6578 "Yugoslavian Hard Dinar (1966\\u201319901.00",
6579 "Yugoslavian New Dina1.00",
6580 "Z1.00",
6581 "ZA1.00",
6582 "ZM1.00",
6583 "ZR1.00",
6584 "ZW1.00",
6585 "Zairean New Zaire (1993\\u201319981.00",
6586 "Zairean Zair1.00",
6587 "Zambian Kwach1.00",
6588 "Zimbabwean Dollar (1980\\u201320081.00",
6589 "dra1.00",
6590 "lar1.00",
6591 "le1.00",
6592 "man1.00",
6593 "so1.00",
6594 };
6595
6596 Locale locale("en_US");
6597 for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
6598 UnicodeString formatted = ctou(DATA[i]);
6599 UErrorCode status = U_ZERO_ERROR;
6600 LocalPointer<NumberFormat> numFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status), status);
6601 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {
6602 return;
6603 }
6604 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
Frank Tang1f164ee2022-11-08 12:31:27 -08006605 numFmt->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08006606 ParsePosition parsePos;
6607 LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6608 if (parsePos.getIndex() > 0) {
6609 double doubleVal = currAmt->getNumber().getDouble(status);
6610 if ( doubleVal != 1.0 ) {
6611 errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
6612 }
6613 } else {
6614 errln("Failed to parse as currency: " + formatted);
6615 }
6616 }
6617
6618 for (uint32_t i=0; i<UPRV_LENGTHOF(WRONG_DATA); ++i) {
6619 UnicodeString formatted = ctou(WRONG_DATA[i]);
6620 UErrorCode status = U_ZERO_ERROR;
6621 NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6622 if (numFmt != NULL && U_SUCCESS(status)) {
6623 ParsePosition parsePos;
6624 LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6625 if (parsePos.getIndex() > 0) {
6626 double doubleVal = currAmt->getNumber().getDouble(status);
6627 errln("Parsed as currency, should not have: " + formatted + " -> " + doubleVal);
6628 }
6629 } else {
6630 dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));
6631 delete numFmt;
6632 break;
6633 }
6634 delete numFmt;
6635 }
6636}
6637
6638const char* attrString(int32_t);
6639
6640// UnicodeString s;
6641// std::string ss;
6642// std::cout << s.toUTF8String(ss)
6643void NumberFormatTest::expectPositions(FieldPositionIterator& iter, int32_t *values, int32_t tupleCount,
6644 const UnicodeString& str) {
6645 UBool found[10];
6646 FieldPosition fp;
6647
6648 if (tupleCount > 10) {
Frank Tang1f164ee2022-11-08 12:31:27 -08006649 assertTrue("internal error, tupleCount too large", false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08006650 } else {
6651 for (int i = 0; i < tupleCount; ++i) {
Frank Tang1f164ee2022-11-08 12:31:27 -08006652 found[i] = false;
Frank Tang3e05d9d2021-11-08 14:04:04 -08006653 }
6654 }
6655
6656 logln(str);
6657 while (iter.next(fp)) {
Frank Tang1f164ee2022-11-08 12:31:27 -08006658 UBool ok = false;
Frank Tang3e05d9d2021-11-08 14:04:04 -08006659 int32_t id = fp.getField();
6660 int32_t start = fp.getBeginIndex();
6661 int32_t limit = fp.getEndIndex();
6662
6663 // is there a logln using printf?
6664 char buf[128];
6665 sprintf(buf, "%24s %3d %3d %3d", attrString(id), id, start, limit);
6666 logln(buf);
6667
6668 for (int i = 0; i < tupleCount; ++i) {
6669 if (found[i]) {
6670 continue;
6671 }
6672 if (values[i*3] == id &&
6673 values[i*3+1] == start &&
6674 values[i*3+2] == limit) {
Frank Tang1f164ee2022-11-08 12:31:27 -08006675 found[i] = ok = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -08006676 break;
6677 }
6678 }
6679
6680 assertTrue((UnicodeString)"found [" + id + "," + start + "," + limit + "]", ok);
6681 }
6682
6683 // check that all were found
Frank Tang1f164ee2022-11-08 12:31:27 -08006684 UBool ok = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -08006685 for (int i = 0; i < tupleCount; ++i) {
6686 if (!found[i]) {
Frank Tang1f164ee2022-11-08 12:31:27 -08006687 ok = false;
Frank Tang3e05d9d2021-11-08 14:04:04 -08006688 assertTrue((UnicodeString) "missing [" + values[i*3] + "," + values[i*3+1] + "," + values[i*3+2] + "]", found[i]);
6689 }
6690 }
6691 assertTrue("no expected values were missing", ok);
6692}
6693
6694void NumberFormatTest::expectPosition(FieldPosition& pos, int32_t id, int32_t start, int32_t limit,
6695 const UnicodeString& str) {
6696 logln(str);
6697 assertTrue((UnicodeString)"id " + id + " == " + pos.getField(), id == pos.getField());
6698 assertTrue((UnicodeString)"begin " + start + " == " + pos.getBeginIndex(), start == pos.getBeginIndex());
6699 assertTrue((UnicodeString)"end " + limit + " == " + pos.getEndIndex(), limit == pos.getEndIndex());
6700}
6701
6702void NumberFormatTest::TestFieldPositionIterator() {
6703 // bug 7372
6704 UErrorCode status = U_ZERO_ERROR;
6705 FieldPositionIterator iter1;
6706 FieldPositionIterator iter2;
6707 FieldPosition pos;
6708
6709 DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(status);
Frank Tang1f164ee2022-11-08 12:31:27 -08006710 if (failure(status, "NumberFormat::createInstance", true)) return;
Frank Tang3e05d9d2021-11-08 14:04:04 -08006711
6712 double num = 1234.56;
6713 UnicodeString str1;
6714 UnicodeString str2;
6715
6716 assertTrue((UnicodeString)"self==", iter1 == iter1);
6717 assertTrue((UnicodeString)"iter1==iter2", iter1 == iter2);
6718
6719 decFmt->format(num, str1, &iter1, status);
6720 assertTrue((UnicodeString)"iter1 != iter2", iter1 != iter2);
6721 decFmt->format(num, str2, &iter2, status);
6722 assertTrue((UnicodeString)"iter1 == iter2 (2)", iter1 == iter2);
6723 iter1.next(pos);
6724 assertTrue((UnicodeString)"iter1 != iter2 (2)", iter1 != iter2);
6725 iter2.next(pos);
6726 assertTrue((UnicodeString)"iter1 == iter2 (3)", iter1 == iter2);
6727
6728 // should format ok with no iterator
6729 str2.remove();
6730 decFmt->format(num, str2, NULL, status);
6731 assertEquals("null fpiter", str1, str2);
6732
6733 delete decFmt;
6734}
6735
6736void NumberFormatTest::TestFormatAttributes() {
6737 Locale locale("en_US");
6738 UErrorCode status = U_ZERO_ERROR;
6739 DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
Frank Tang1f164ee2022-11-08 12:31:27 -08006740 if (failure(status, "NumberFormat::createInstance", true)) return;
Frank Tang3e05d9d2021-11-08 14:04:04 -08006741 double val = 12345.67;
6742
6743 {
6744 int32_t expected[] = {
6745 UNUM_CURRENCY_FIELD, 0, 1,
6746 UNUM_GROUPING_SEPARATOR_FIELD, 3, 4,
6747 UNUM_INTEGER_FIELD, 1, 7,
6748 UNUM_DECIMAL_SEPARATOR_FIELD, 7, 8,
6749 UNUM_FRACTION_FIELD, 8, 10,
6750 };
6751 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6752
6753 FieldPositionIterator posIter;
6754 UnicodeString result;
6755 decFmt->format(val, result, &posIter, status);
6756 expectPositions(posIter, expected, tupleCount, result);
6757 }
6758 {
6759 FieldPosition fp(UNUM_INTEGER_FIELD);
6760 UnicodeString result;
6761 decFmt->format(val, result, fp);
6762 expectPosition(fp, UNUM_INTEGER_FIELD, 1, 7, result);
6763 }
6764 {
6765 FieldPosition fp(UNUM_FRACTION_FIELD);
6766 UnicodeString result;
6767 decFmt->format(val, result, fp);
6768 expectPosition(fp, UNUM_FRACTION_FIELD, 8, 10, result);
6769 }
6770 delete decFmt;
6771
6772 decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_SCIENTIFIC, status);
6773 val = -0.0000123;
6774 {
6775 int32_t expected[] = {
6776 UNUM_SIGN_FIELD, 0, 1,
6777 UNUM_INTEGER_FIELD, 1, 2,
6778 UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3,
6779 UNUM_FRACTION_FIELD, 3, 5,
6780 UNUM_EXPONENT_SYMBOL_FIELD, 5, 6,
6781 UNUM_EXPONENT_SIGN_FIELD, 6, 7,
6782 UNUM_EXPONENT_FIELD, 7, 8
6783 };
6784 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6785
6786 FieldPositionIterator posIter;
6787 UnicodeString result;
6788 decFmt->format(val, result, &posIter, status);
6789 expectPositions(posIter, expected, tupleCount, result);
6790 }
6791 {
6792 FieldPosition fp(UNUM_INTEGER_FIELD);
6793 UnicodeString result;
6794 decFmt->format(val, result, fp);
6795 expectPosition(fp, UNUM_INTEGER_FIELD, 1, 2, result);
6796 }
6797 {
6798 FieldPosition fp(UNUM_FRACTION_FIELD);
6799 UnicodeString result;
6800 decFmt->format(val, result, fp);
6801 expectPosition(fp, UNUM_FRACTION_FIELD, 3, 5, result);
6802 }
6803 delete decFmt;
6804
6805 fflush(stderr);
6806}
6807
6808const char* attrString(int32_t attrId) {
6809 switch (attrId) {
6810 case UNUM_INTEGER_FIELD: return "integer";
6811 case UNUM_FRACTION_FIELD: return "fraction";
6812 case UNUM_DECIMAL_SEPARATOR_FIELD: return "decimal separator";
6813 case UNUM_EXPONENT_SYMBOL_FIELD: return "exponent symbol";
6814 case UNUM_EXPONENT_SIGN_FIELD: return "exponent sign";
6815 case UNUM_EXPONENT_FIELD: return "exponent";
6816 case UNUM_GROUPING_SEPARATOR_FIELD: return "grouping separator";
6817 case UNUM_CURRENCY_FIELD: return "currency";
6818 case UNUM_PERCENT_FIELD: return "percent";
6819 case UNUM_PERMILL_FIELD: return "permille";
6820 case UNUM_SIGN_FIELD: return "sign";
6821 default: return "";
6822 }
6823}
6824
6825//
6826// Test formatting & parsing of big decimals.
6827// API test, not a comprehensive test.
6828// See DecimalFormatTest/DataDrivenTests
6829//
6830#define ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \
6831 assertSuccess(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (status)); \
6832} UPRV_BLOCK_MACRO_END
6833#define ASSERT_EQUALS(expected, actual) UPRV_BLOCK_MACRO_BEGIN { \
6834 assertEquals(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (expected), (actual)); \
6835} UPRV_BLOCK_MACRO_END
6836
6837void NumberFormatTest::TestDecimal() {
6838 {
6839 UErrorCode status = U_ZERO_ERROR;
6840 Formattable f("12.345678999987654321E666", status);
6841 ASSERT_SUCCESS(status);
6842 StringPiece s = f.getDecimalNumber(status);
6843 ASSERT_SUCCESS(status);
6844 ASSERT_EQUALS("1.2345678999987654321E+667", s.data());
6845 //printf("%s\n", s.data());
6846 }
6847
6848 {
6849 UErrorCode status = U_ZERO_ERROR;
6850 Formattable f1("this is not a number", status);
6851 ASSERT_EQUALS(U_DECIMAL_NUMBER_SYNTAX_ERROR, status);
6852 }
6853
6854 {
6855 UErrorCode status = U_ZERO_ERROR;
6856 Formattable f;
6857 f.setDecimalNumber("123.45", status);
6858 ASSERT_SUCCESS(status);
6859 ASSERT_EQUALS( Formattable::kDouble, f.getType());
6860 ASSERT_EQUALS(123.45, f.getDouble());
6861 ASSERT_EQUALS(123.45, f.getDouble(status));
6862 ASSERT_SUCCESS(status);
6863 ASSERT_EQUALS("123.45", f.getDecimalNumber(status).data());
6864 ASSERT_SUCCESS(status);
6865
6866 f.setDecimalNumber("4.5678E7", status);
6867 int32_t n;
6868 n = f.getLong();
6869 ASSERT_EQUALS(45678000, n);
6870
6871 status = U_ZERO_ERROR;
6872 f.setDecimalNumber("-123", status);
6873 ASSERT_SUCCESS(status);
6874 ASSERT_EQUALS( Formattable::kLong, f.getType());
6875 ASSERT_EQUALS(-123, f.getLong());
6876 ASSERT_EQUALS(-123, f.getLong(status));
6877 ASSERT_SUCCESS(status);
6878 ASSERT_EQUALS("-123", f.getDecimalNumber(status).data());
6879 ASSERT_SUCCESS(status);
6880
6881 status = U_ZERO_ERROR;
6882 f.setDecimalNumber("1234567890123", status); // Number too big for 32 bits
6883 ASSERT_SUCCESS(status);
6884 ASSERT_EQUALS( Formattable::kInt64, f.getType());
6885 ASSERT_EQUALS(1234567890123LL, f.getInt64());
6886 ASSERT_EQUALS(1234567890123LL, f.getInt64(status));
6887 ASSERT_SUCCESS(status);
6888 ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status).data());
6889 ASSERT_SUCCESS(status);
6890 }
6891
6892 {
6893 UErrorCode status = U_ZERO_ERROR;
6894 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6895 if (U_FAILURE(status) || fmtr == NULL) {
6896 dataerrln("Unable to create NumberFormat");
6897 } else {
6898 UnicodeString formattedResult;
6899 StringPiece num("244444444444444444444444444444444444446.4");
6900 fmtr->format(num, formattedResult, NULL, status);
6901 ASSERT_SUCCESS(status);
6902 ASSERT_EQUALS("244,444,444,444,444,444,444,444,444,444,444,444,446.4", formattedResult);
6903 //std::string ss; std::cout << formattedResult.toUTF8String(ss);
6904 delete fmtr;
6905 }
6906 }
6907
6908 {
6909 // Check formatting a DigitList. DigitList is internal, but this is
6910 // a critical interface that must work.
6911 UErrorCode status = U_ZERO_ERROR;
6912 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6913 if (U_FAILURE(status) || fmtr == NULL) {
6914 dataerrln("Unable to create NumberFormat");
6915 } else {
6916 UnicodeString formattedResult;
6917 DecimalQuantity dl;
6918 StringPiece num("123.4566666666666666666666666666666666621E+40");
6919 dl.setToDecNumber(num, status);
6920 ASSERT_SUCCESS(status);
6921 fmtr->format(dl, formattedResult, NULL, status);
6922 ASSERT_SUCCESS(status);
6923 ASSERT_EQUALS("1,234,566,666,666,666,666,666,666,666,666,666,666,621,000", formattedResult);
6924
6925 status = U_ZERO_ERROR;
6926 num.set("666.666");
6927 dl.setToDecNumber(num, status);
6928 FieldPosition pos(NumberFormat::FRACTION_FIELD);
6929 ASSERT_SUCCESS(status);
6930 formattedResult.remove();
6931 fmtr->format(dl, formattedResult, pos, status);
6932 ASSERT_SUCCESS(status);
6933 ASSERT_EQUALS("666.666", formattedResult);
6934 ASSERT_EQUALS(4, pos.getBeginIndex());
6935 ASSERT_EQUALS(7, pos.getEndIndex());
6936 delete fmtr;
6937 }
6938 }
6939
6940 {
6941 // Check a parse with a formatter with a multiplier.
6942 UErrorCode status = U_ZERO_ERROR;
6943 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_PERCENT, status);
6944 if (U_FAILURE(status) || fmtr == NULL) {
6945 dataerrln("Unable to create NumberFormat");
6946 } else {
6947 UnicodeString input = "1.84%";
6948 Formattable result;
6949 fmtr->parse(input, result, status);
6950 ASSERT_SUCCESS(status);
6951 ASSERT_EQUALS("0.0184", result.getDecimalNumber(status).data());
6952 //std::cout << result.getDecimalNumber(status).data();
6953 delete fmtr;
6954 }
6955 }
6956
6957#if U_PLATFORM != U_PF_CYGWIN || defined(CYGWINMSVC)
6958 /*
6959 * This test fails on Cygwin (1.7.16) using GCC because of a rounding issue with strtod().
6960 * See #9463
6961 */
6962 {
6963 // Check that a parse returns a decimal number with full accuracy
6964 UErrorCode status = U_ZERO_ERROR;
6965 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6966 if (U_FAILURE(status) || fmtr == NULL) {
6967 dataerrln("Unable to create NumberFormat");
6968 } else {
6969 UnicodeString input = "1.002200044400088880000070000";
6970 Formattable result;
6971 fmtr->parse(input, result, status);
6972 ASSERT_SUCCESS(status);
6973 ASSERT_EQUALS(0, strcmp("1.00220004440008888000007", result.getDecimalNumber(status).data()));
6974 ASSERT_EQUALS(1.00220004440008888, result.getDouble());
6975 //std::cout << result.getDecimalNumber(status).data();
6976 delete fmtr;
6977 }
6978 }
6979#endif
6980
6981}
6982
6983void NumberFormatTest::TestCurrencyFractionDigits() {
6984 UErrorCode status = U_ZERO_ERROR;
6985 UnicodeString text1, text2;
6986 double value = 99.12345;
6987
6988 // Create currenct instance
6989 NumberFormat* fmt = NumberFormat::createCurrencyInstance("ja_JP", status);
6990 if (U_FAILURE(status) || fmt == NULL) {
6991 dataerrln("Unable to create NumberFormat");
6992 } else {
6993 fmt->format(value, text1);
6994
6995 // Reset the same currency and format the test value again
6996 fmt->setCurrency(fmt->getCurrency(), status);
6997 ASSERT_SUCCESS(status);
6998 fmt->format(value, text2);
6999
7000 if (text1 != text2) {
7001 errln((UnicodeString)"NumberFormat::format() should return the same result - text1="
7002 + text1 + " text2=" + text2);
7003 }
7004 }
7005 delete fmt;
7006}
7007
7008void NumberFormatTest::TestExponentParse() {
7009
7010 UErrorCode status = U_ZERO_ERROR;
7011 Formattable result;
7012 ParsePosition parsePos(0);
7013
7014 // set the exponent symbol
7015 status = U_ZERO_ERROR;
7016 DecimalFormatSymbols symbols(Locale::getDefault(), status);
7017 if(U_FAILURE(status)) {
7018 dataerrln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (Default)");
7019 return;
7020 }
7021
7022 // create format instance
7023 status = U_ZERO_ERROR;
7024 DecimalFormat fmt(u"#####", symbols, status);
7025 if(U_FAILURE(status)) {
7026 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
7027 }
7028
7029 // parse the text
7030 fmt.parse("5.06e-27", result, parsePos);
7031 if(result.getType() != Formattable::kDouble &&
7032 result.getDouble() != 5.06E-27 &&
7033 parsePos.getIndex() != 8
7034 )
7035 {
7036 errln("ERROR: parse failed - expected 5.06E-27, 8 - returned %d, %i",
7037 result.getDouble(), parsePos.getIndex());
7038 }
7039}
7040
7041void NumberFormatTest::TestExplicitParents() {
7042
7043 /* Test that number formats are properly inherited from es_419 */
7044 /* These could be subject to change if the CLDR data changes */
7045 static const char* parentLocaleTests[][2]= {
7046 /* locale ID */ /* expected */
7047 {"es_CO", "1.250,75" },
7048 {"es_ES", "1.250,75" },
7049 {"es_GQ", "1.250,75" },
7050 {"es_MX", "1,250.75" },
7051 {"es_US", "1,250.75" },
7052 {"es_VE", "1.250,75" },
7053 };
7054
7055 UnicodeString s;
7056
7057 for(int i=0; i < UPRV_LENGTHOF(parentLocaleTests); i++){
7058 UErrorCode status = U_ZERO_ERROR;
7059 const char *localeID = parentLocaleTests[i][0];
7060 UnicodeString expected(parentLocaleTests[i][1], -1, US_INV);
7061 expected = expected.unescape();
7062 char loc[256]={0};
7063 uloc_canonicalize(localeID, loc, 256, &status);
7064 NumberFormat *fmt= NumberFormat::createInstance(Locale(loc), status);
7065 if(U_FAILURE(status)){
7066 dataerrln("Could not create number formatter for locale %s - %s",localeID, u_errorName(status));
7067 continue;
7068 }
7069 s.remove();
7070 fmt->format(1250.75, s);
7071 if(s!=expected){
7072 errln(UnicodeString("FAIL: Expected: ")+expected
7073 + UnicodeString(" Got: ") + s
7074 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
7075 }
7076 if (U_FAILURE(status)){
7077 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
7078 }
7079 delete fmt;
7080 }
7081
7082}
7083
7084/**
7085 * Test available numbering systems API.
7086 */
7087void NumberFormatTest::TestAvailableNumberingSystems() {
7088 IcuTestErrorCode status(*this, "TestAvailableNumberingSystems");
7089 StringEnumeration *availableNumberingSystems = NumberingSystem::getAvailableNames(status);
7090 CHECK_DATA(status, "NumberingSystem::getAvailableNames()");
7091
7092 int32_t nsCount = availableNumberingSystems->count(status);
7093 if ( nsCount < 74 ) {
7094 errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 74, got %d",nsCount);
7095 }
7096
7097 /* A relatively simple test of the API. We call getAvailableNames() and cycle through */
7098 /* each name returned, attempting to create a numbering system based on that name and */
7099 /* verifying that the name returned from the resulting numbering system is the same */
7100 /* one that we initially thought. */
7101
7102 int32_t len;
7103 const char* prevName = nullptr;
7104 for ( int32_t i = 0 ; i < nsCount ; i++ ) {
7105 const char *nsname = availableNumberingSystems->next(&len,status);
7106 NumberingSystem* ns = NumberingSystem::createInstanceByName(nsname,status);
7107 logln("OK for ns = %s",nsname);
7108 if ( uprv_strcmp(nsname,ns->getName()) ) {
7109 errln("FAIL: Numbering system name didn't match for name = %s\n",nsname);
7110 }
7111 if (prevName != nullptr) {
7112 int comp = uprv_strcmp(prevName, nsname);
7113 assertTrue(
7114 UnicodeString(u"NS names should be in alphabetical order: ")
7115 + prevName + u" vs " + nsname,
7116 // TODO: Why are there duplicates? This doesn't work if comp < 0
7117 comp <= 0);
7118 }
7119 prevName = nsname;
7120
7121 delete ns;
7122 }
7123
7124 LocalPointer<NumberingSystem> dummy(NumberingSystem::createInstanceByName("dummy", status), status);
7125 status.expectErrorAndReset(U_UNSUPPORTED_ERROR);
7126 assertTrue("Non-existent numbering system should return null", dummy.isNull());
7127
7128 delete availableNumberingSystems;
7129}
7130
7131void
7132NumberFormatTest::Test9087(void)
7133{
7134 U_STRING_DECL(pattern,"#",1);
7135 U_STRING_INIT(pattern,"#",1);
7136
7137 U_STRING_DECL(infstr,"INF",3);
7138 U_STRING_INIT(infstr,"INF",3);
7139
7140 U_STRING_DECL(nanstr,"NAN",3);
7141 U_STRING_INIT(nanstr,"NAN",3);
7142
7143 UChar outputbuf[50] = {0};
7144 UErrorCode status = U_ZERO_ERROR;
7145 UNumberFormat* fmt = unum_open(UNUM_PATTERN_DECIMAL,pattern,1,NULL,NULL,&status);
7146 if ( U_FAILURE(status) ) {
7147 dataerrln("FAIL: error in unum_open() - %s", u_errorName(status));
7148 return;
7149 }
7150
7151 unum_setSymbol(fmt,UNUM_INFINITY_SYMBOL,infstr,3,&status);
7152 unum_setSymbol(fmt,UNUM_NAN_SYMBOL,nanstr,3,&status);
7153 if ( U_FAILURE(status) ) {
7154 errln("FAIL: error setting symbols");
7155 }
7156
7157 double inf = uprv_getInfinity();
7158
7159 unum_setAttribute(fmt,UNUM_ROUNDING_MODE,UNUM_ROUND_HALFEVEN);
7160 unum_setDoubleAttribute(fmt,UNUM_ROUNDING_INCREMENT,0);
7161
7162 UFieldPosition position = { 0, 0, 0};
7163 unum_formatDouble(fmt,inf,outputbuf,50,&position,&status);
7164
7165 if ( u_strcmp(infstr, outputbuf)) {
7166 errln((UnicodeString)"FAIL: unexpected result for infinity - expected " + infstr + " got " + outputbuf);
7167 }
7168
7169 unum_close(fmt);
7170}
7171
7172void NumberFormatTest::TestFormatFastpaths() {
7173 // get some additional case
7174 {
7175 UErrorCode status=U_ZERO_ERROR;
7176 DecimalFormat df(UnicodeString(u"0000"),status);
7177 if (U_FAILURE(status)) {
7178 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7179 } else {
7180 int64_t long_number = 1;
7181 UnicodeString expect = "0001";
7182 UnicodeString result;
7183 FieldPosition pos;
7184 df.format(long_number, result, pos);
7185 if(U_FAILURE(status)||expect!=result) {
7186 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s",
7187 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7188 } else {
7189 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
7190 }
7191 }
7192 }
7193 {
7194 UErrorCode status=U_ZERO_ERROR;
7195 DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7196 if (U_FAILURE(status)) {
7197 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7198 } else {
7199 int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
7200 // uint8_t bits[8];
7201 // memcpy(bits,&long_number,8);
7202 // for(int i=0;i<8;i++) {
7203 // logln("bits: %02X", (unsigned int)bits[i]);
7204 // }
7205 UnicodeString expect = "-9223372036854775808";
7206 UnicodeString result;
7207 FieldPosition pos;
7208 df.format(long_number, result, pos);
7209 if(U_FAILURE(status)||expect!=result) {
7210 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775808",
7211 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7212 } else {
7213 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
7214 }
7215 }
7216 }
7217 {
7218 UErrorCode status=U_ZERO_ERROR;
7219 DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7220 if (U_FAILURE(status)) {
7221 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7222 } else {
7223 int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
7224 // uint8_t bits[8];
7225 // memcpy(bits,&long_number,8);
7226 // for(int i=0;i<8;i++) {
7227 // logln("bits: %02X", (unsigned int)bits[i]);
7228 // }
7229 UnicodeString expect = "9223372036854775807";
7230 UnicodeString result;
7231 FieldPosition pos;
7232 df.format(long_number, result, pos);
7233 if(U_FAILURE(status)||expect!=result) {
7234 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on U_INT64_MAX",
7235 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7236 } else {
7237 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
7238 }
7239 }
7240 }
7241 {
7242 UErrorCode status=U_ZERO_ERROR;
7243 DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7244 if (U_FAILURE(status)) {
7245 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7246 } else {
7247 int64_t long_number = 0;
7248 // uint8_t bits[8];
7249 // memcpy(bits,&long_number,8);
7250 // for(int i=0;i<8;i++) {
7251 // logln("bits: %02X", (unsigned int)bits[i]);
7252 // }
7253 UnicodeString expect = "0000000000000000000";
7254 UnicodeString result;
7255 FieldPosition pos;
7256 df.format(long_number, result, pos);
7257 if(U_FAILURE(status)||expect!=result) {
7258 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on 0",
7259 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7260 } else {
7261 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
7262 }
7263 }
7264 }
7265 {
7266 UErrorCode status=U_ZERO_ERROR;
7267 DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7268 if (U_FAILURE(status)) {
7269 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7270 } else {
7271 int64_t long_number = U_INT64_MIN + 1;
7272 UnicodeString expect = "-9223372036854775807";
7273 UnicodeString result;
7274 FieldPosition pos;
7275 df.format(long_number, result, pos);
7276 if(U_FAILURE(status)||expect!=result) {
7277 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775807",
7278 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7279 } else {
7280 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
7281 }
7282 }
7283 }
7284}
7285
7286
7287void NumberFormatTest::TestFormattableSize(void) {
7288 if(sizeof(Formattable) > 112) {
7289 errln("Error: sizeof(Formattable)=%d, 112=%d\n",
7290 sizeof(Formattable), 112);
7291 } else if(sizeof(Formattable) < 112) {
7292 logln("Warning: sizeof(Formattable)=%d, 112=%d\n",
7293 sizeof(Formattable), 112);
7294 } else {
7295 logln("sizeof(Formattable)=%d, 112=%d\n",
7296 sizeof(Formattable), 112);
7297 }
7298}
7299
7300UBool NumberFormatTest::testFormattableAsUFormattable(const char *file, int line, Formattable &f) {
7301 UnicodeString fileLine = UnicodeString(file)+UnicodeString(":")+line+UnicodeString(": ");
7302
7303 UFormattable *u = f.toUFormattable();
7304 logln();
7305 if (u == NULL) {
7306 errln("%s:%d: Error: f.toUFormattable() retuned NULL.");
Frank Tang1f164ee2022-11-08 12:31:27 -08007307 return false;
Frank Tang3e05d9d2021-11-08 14:04:04 -08007308 }
7309 logln("%s:%d: comparing Formattable with UFormattable", file, line);
7310 logln(fileLine + toString(f));
7311
7312 UErrorCode status = U_ZERO_ERROR;
7313 UErrorCode valueStatus = U_ZERO_ERROR;
7314 UFormattableType expectUType = UFMT_COUNT; // invalid
7315
Frank Tang1f164ee2022-11-08 12:31:27 -08007316 UBool triedExact = false; // did we attempt an exact comparison?
7317 UBool exactMatch = false; // was the exact comparison true?
Frank Tang3e05d9d2021-11-08 14:04:04 -08007318
7319 switch( f.getType() ) {
7320 case Formattable::kDate:
7321 expectUType = UFMT_DATE;
7322 exactMatch = (f.getDate()==ufmt_getDate(u, &valueStatus));
Frank Tang1f164ee2022-11-08 12:31:27 -08007323 triedExact = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -08007324 break;
7325 case Formattable::kDouble:
7326 expectUType = UFMT_DOUBLE;
7327 exactMatch = (f.getDouble()==ufmt_getDouble(u, &valueStatus));
Frank Tang1f164ee2022-11-08 12:31:27 -08007328 triedExact = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -08007329 break;
7330 case Formattable::kLong:
7331 expectUType = UFMT_LONG;
7332 exactMatch = (f.getLong()==ufmt_getLong(u, &valueStatus));
Frank Tang1f164ee2022-11-08 12:31:27 -08007333 triedExact = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -08007334 break;
7335 case Formattable::kString:
7336 expectUType = UFMT_STRING;
7337 {
7338 UnicodeString str;
7339 f.getString(str);
7340 int32_t len;
7341 const UChar* uch = ufmt_getUChars(u, &len, &valueStatus);
7342 if(U_SUCCESS(valueStatus)) {
7343 UnicodeString str2(uch, len);
7344 assertTrue("UChar* NULL-terminated", uch[len]==0);
7345 exactMatch = (str == str2);
7346 }
Frank Tang1f164ee2022-11-08 12:31:27 -08007347 triedExact = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -08007348 }
7349 break;
7350 case Formattable::kArray:
7351 expectUType = UFMT_ARRAY;
Frank Tang1f164ee2022-11-08 12:31:27 -08007352 triedExact = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -08007353 {
7354 int32_t count = ufmt_getArrayLength(u, &valueStatus);
7355 int32_t count2;
7356 const Formattable *array2 = f.getArray(count2);
7357 exactMatch = assertEquals(fileLine + " array count", count, count2);
7358
7359 if(exactMatch) {
7360 for(int i=0;U_SUCCESS(valueStatus) && i<count;i++) {
7361 UFormattable *uu = ufmt_getArrayItemByIndex(u, i, &valueStatus);
7362 if(*Formattable::fromUFormattable(uu) != (array2[i])) {
7363 errln("%s:%d: operator== did not match at index[%d] - %p vs %p", file, line, i,
7364 (const void*)Formattable::fromUFormattable(uu), (const void*)&(array2[i]));
Frank Tang1f164ee2022-11-08 12:31:27 -08007365 exactMatch = false;
Frank Tang3e05d9d2021-11-08 14:04:04 -08007366 } else {
7367 if(!testFormattableAsUFormattable("(sub item)",i,*Formattable::fromUFormattable(uu))) {
Frank Tang1f164ee2022-11-08 12:31:27 -08007368 exactMatch = false;
Frank Tang3e05d9d2021-11-08 14:04:04 -08007369 }
7370 }
7371 }
7372 }
7373 }
7374 break;
7375 case Formattable::kInt64:
7376 expectUType = UFMT_INT64;
7377 exactMatch = (f.getInt64()==ufmt_getInt64(u, &valueStatus));
Frank Tang1f164ee2022-11-08 12:31:27 -08007378 triedExact = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -08007379 break;
7380 case Formattable::kObject:
7381 expectUType = UFMT_OBJECT;
7382 exactMatch = (f.getObject()==ufmt_getObject(u, &valueStatus));
Frank Tang1f164ee2022-11-08 12:31:27 -08007383 triedExact = true;
Frank Tang3e05d9d2021-11-08 14:04:04 -08007384 break;
7385 }
7386 UFormattableType uType = ufmt_getType(u, &status);
7387
7388 if(U_FAILURE(status)) {
7389 errln("%s:%d: Error calling ufmt_getType - %s", file, line, u_errorName(status));
Frank Tang1f164ee2022-11-08 12:31:27 -08007390 return false;
Frank Tang3e05d9d2021-11-08 14:04:04 -08007391 }
7392
7393 if(uType != expectUType) {
7394 errln("%s:%d: got type (%d) expected (%d) from ufmt_getType", file, line, (int) uType, (int) expectUType);
7395 }
7396
7397 if(triedExact) {
7398 if(U_FAILURE(valueStatus)) {
7399 errln("%s:%d: got err %s trying to ufmt_get...() for exact match check", file, line, u_errorName(valueStatus));
7400 } else if(!exactMatch) {
7401 errln("%s:%d: failed exact match for the Formattable type", file, line);
7402 } else {
7403 logln("%s:%d: exact match OK", file, line);
7404 }
7405 } else {
7406 logln("%s:%d: note, did not attempt exact match for this formattable type", file, line);
7407 }
7408
7409 if( assertEquals(fileLine + " isNumeric()", f.isNumeric(), ufmt_isNumeric(u))
7410 && f.isNumeric()) {
7411 UErrorCode convStatus = U_ZERO_ERROR;
7412
7413 if(uType != UFMT_INT64) { // may fail to compare
7414 assertTrue(fileLine + " as doubles ==", f.getDouble(convStatus)==ufmt_getDouble(u, &convStatus));
7415 }
7416
7417 if( assertSuccess(fileLine + " (numeric conversion status)", convStatus) ) {
7418 StringPiece fDecNum = f.getDecimalNumber(convStatus);
7419#if 1
7420 int32_t len;
7421 const char *decNumChars = ufmt_getDecNumChars(u, &len, &convStatus);
7422#else
7423 // copy version
7424 char decNumChars[200];
7425 int32_t len = ufmt_getDecNumChars(u, decNumChars, 200, &convStatus);
7426#endif
7427
7428 if( assertSuccess(fileLine + " (decNumbers conversion)", convStatus) ) {
7429 logln(fileLine + decNumChars);
7430 assertEquals(fileLine + " decNumChars length==", len, fDecNum.length());
7431 assertEquals(fileLine + " decNumChars digits", decNumChars, fDecNum.data());
7432 }
7433
7434 UErrorCode int64ConversionF = U_ZERO_ERROR;
7435 int64_t l = f.getInt64(int64ConversionF);
7436 UErrorCode int64ConversionU = U_ZERO_ERROR;
7437 int64_t r = ufmt_getInt64(u, &int64ConversionU);
7438
7439 if( (l==r)
7440 && ( uType != UFMT_INT64 ) // int64 better not overflow
7441 && (U_INVALID_FORMAT_ERROR==int64ConversionU)
7442 && (U_INVALID_FORMAT_ERROR==int64ConversionF) ) {
7443 logln("%s:%d: OK: 64 bit overflow", file, line);
7444 } else {
7445 assertEquals(fileLine + " as int64 ==", l, r);
7446 assertSuccess(fileLine + " Formattable.getnt64()", int64ConversionF);
7447 assertSuccess(fileLine + " ufmt_getInt64()", int64ConversionU);
7448 }
7449 }
7450 }
7451 return exactMatch || !triedExact;
7452}
7453
7454void NumberFormatTest::TestUFormattable(void) {
7455 {
7456 // test that a default formattable is equal to Formattable()
7457 UErrorCode status = U_ZERO_ERROR;
7458 LocalUFormattablePointer defaultUFormattable(ufmt_open(&status));
7459 assertSuccess("calling umt_open", status);
7460 Formattable defaultFormattable;
7461 assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7462 (defaultFormattable
7463 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7464 assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7465 (defaultFormattable
7466 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7467 assertTrue((UnicodeString)"comparing Formattable() round tripped through UFormattable",
7468 (defaultFormattable
7469 == *(Formattable::fromUFormattable(defaultFormattable.toUFormattable()))));
7470 assertTrue((UnicodeString)"comparing &Formattable() round tripped through UFormattable",
7471 ((&defaultFormattable)
7472 == Formattable::fromUFormattable(defaultFormattable.toUFormattable())));
7473 assertFalse((UnicodeString)"comparing &Formattable() with ufmt_open()",
7474 ((&defaultFormattable)
7475 == Formattable::fromUFormattable(defaultUFormattable.getAlias())));
7476 testFormattableAsUFormattable(__FILE__, __LINE__, defaultFormattable);
7477 }
7478 // test some random Formattables
7479 {
7480 Formattable f(ucal_getNow(), Formattable::kIsDate);
7481 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7482 }
7483 {
7484 Formattable f((double)1.61803398874989484820); // golden ratio
7485 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7486 }
7487 {
7488 Formattable f((int64_t)80994231587905127LL); // weight of the moon, in kilotons http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
7489 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7490 }
7491 {
7492 Formattable f((int32_t)4); // random number, source: http://www.xkcd.com/221/
7493 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7494 }
7495 {
7496 Formattable f("Hello world."); // should be invariant?
7497 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7498 }
7499 {
7500 UErrorCode status2 = U_ZERO_ERROR;
7501 Formattable f(StringPiece("73476730924573500000000.0"), status2); // weight of the moon, kg
7502 assertSuccess("Constructing a StringPiece", status2);
7503 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7504 }
7505 {
7506 UErrorCode status2 = U_ZERO_ERROR;
7507 UObject *obj = new Locale();
7508 Formattable f(obj);
7509 assertSuccess("Constructing a Formattable from a default constructed Locale()", status2);
7510 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7511 }
7512 {
7513 const Formattable array[] = {
7514 Formattable(ucal_getNow(), Formattable::kIsDate),
7515 Formattable((int32_t)4),
7516 Formattable((double)1.234),
7517 };
7518
7519 Formattable fa(array, 3);
7520 testFormattableAsUFormattable(__FILE__, __LINE__, fa);
7521 }
7522}
7523
7524void NumberFormatTest::TestSignificantDigits(void) {
7525 double input[] = {
7526 0, 0,
7527 0.1, -0.1,
7528 123, -123,
7529 12345, -12345,
7530 123.45, -123.45,
7531 123.44501, -123.44501,
7532 0.001234, -0.001234,
7533 0.00000000123, -0.00000000123,
7534 0.0000000000000000000123, -0.0000000000000000000123,
7535 1.2, -1.2,
7536 0.0000000012344501, -0.0000000012344501,
7537 123445.01, -123445.01,
7538 12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0,
7539 };
7540 const char* expected[] = {
7541 "0.00", "0.00",
7542 "0.100", "-0.100",
7543 "123", "-123",
7544 "12345", "-12345",
7545 "123.45", "-123.45",
7546 "123.45", "-123.45",
7547 "0.001234", "-0.001234",
7548 "0.00000000123", "-0.00000000123",
7549 "0.0000000000000000000123", "-0.0000000000000000000123",
7550 "1.20", "-1.20",
7551 "0.0000000012345", "-0.0000000012345",
7552 "123450", "-123450",
7553 "12345000000000000000000000000000000", "-12345000000000000000000000000000000",
7554 };
7555
7556 UErrorCode status = U_ZERO_ERROR;
7557 Locale locale("en_US");
7558 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7559 NumberFormat::createInstance(locale, status)));
7560 CHECK_DATA(status,"NumberFormat::createInstance");
7561
Frank Tang1f164ee2022-11-08 12:31:27 -08007562 numberFormat->setSignificantDigitsUsed(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007563 numberFormat->setMinimumSignificantDigits(3);
7564 numberFormat->setMaximumSignificantDigits(5);
7565 numberFormat->setGroupingUsed(false);
7566
7567 UnicodeString result;
7568 UnicodeString expectedResult;
7569 for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
7570 numberFormat->format(input[i], result);
7571 UnicodeString expectedResult(expected[i]);
7572 if (result != expectedResult) {
7573 errln((UnicodeString)"Expected: '" + expectedResult + "' got '" + result);
7574 }
7575 result.remove();
7576 }
7577
7578 // Test for ICU-20063
7579 {
7580 DecimalFormat df({"en-us", status}, status);
Frank Tang1f164ee2022-11-08 12:31:27 -08007581 df.setSignificantDigitsUsed(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007582 expect(df, 9.87654321, u"9.87654");
7583 df.setMaximumSignificantDigits(3);
7584 expect(df, 9.87654321, u"9.88");
7585 // setSignificantDigitsUsed with maxSig only
Frank Tang1f164ee2022-11-08 12:31:27 -08007586 df.setSignificantDigitsUsed(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007587 expect(df, 9.87654321, u"9.88");
7588 df.setMinimumSignificantDigits(2);
7589 expect(df, 9, u"9.0");
7590 // setSignificantDigitsUsed with both minSig and maxSig
Frank Tang1f164ee2022-11-08 12:31:27 -08007591 df.setSignificantDigitsUsed(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007592 expect(df, 9, u"9.0");
7593 // setSignificantDigitsUsed to false: should revert to fraction rounding
Frank Tang1f164ee2022-11-08 12:31:27 -08007594 df.setSignificantDigitsUsed(false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007595 expect(df, 9.87654321, u"9.876543");
7596 expect(df, 9, u"9");
Frank Tang1f164ee2022-11-08 12:31:27 -08007597 df.setSignificantDigitsUsed(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007598 df.setMinimumSignificantDigits(2);
7599 expect(df, 9.87654321, u"9.87654");
7600 expect(df, 9, u"9.0");
7601 // setSignificantDigitsUsed with minSig only
Frank Tang1f164ee2022-11-08 12:31:27 -08007602 df.setSignificantDigitsUsed(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007603 expect(df, 9.87654321, u"9.87654");
7604 expect(df, 9, u"9.0");
7605 }
7606}
7607
7608void NumberFormatTest::TestShowZero() {
7609 UErrorCode status = U_ZERO_ERROR;
7610 Locale locale("en_US");
7611 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7612 NumberFormat::createInstance(locale, status)));
7613 CHECK_DATA(status, "NumberFormat::createInstance");
7614
Frank Tang1f164ee2022-11-08 12:31:27 -08007615 numberFormat->setSignificantDigitsUsed(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007616 numberFormat->setMaximumSignificantDigits(3);
7617
7618 UnicodeString result;
7619 numberFormat->format(0.0, result);
7620 if (result != "0") {
7621 errln((UnicodeString)"Expected: 0, got " + result);
7622 }
7623}
7624
7625void NumberFormatTest::TestBug9936() {
7626 UErrorCode status = U_ZERO_ERROR;
7627 Locale locale("en_US");
7628 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7629 NumberFormat::createInstance(locale, status)));
7630 if (U_FAILURE(status)) {
7631 dataerrln("File %s, Line %d: status = %s.\n", __FILE__, __LINE__, u_errorName(status));
7632 return;
7633 }
7634
Frank Tang1f164ee2022-11-08 12:31:27 -08007635 if (numberFormat->areSignificantDigitsUsed() == true) {
7636 errln("File %s, Line %d: areSignificantDigitsUsed() was true, expected false.\n", __FILE__, __LINE__);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007637 }
Frank Tang1f164ee2022-11-08 12:31:27 -08007638 numberFormat->setSignificantDigitsUsed(true);
7639 if (numberFormat->areSignificantDigitsUsed() == false) {
7640 errln("File %s, Line %d: areSignificantDigitsUsed() was false, expected true.\n", __FILE__, __LINE__);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007641 }
7642
Frank Tang1f164ee2022-11-08 12:31:27 -08007643 numberFormat->setSignificantDigitsUsed(false);
7644 if (numberFormat->areSignificantDigitsUsed() == true) {
7645 errln("File %s, Line %d: areSignificantDigitsUsed() was true, expected false.\n", __FILE__, __LINE__);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007646 }
7647
7648 numberFormat->setMinimumSignificantDigits(3);
Frank Tang1f164ee2022-11-08 12:31:27 -08007649 if (numberFormat->areSignificantDigitsUsed() == false) {
7650 errln("File %s, Line %d: areSignificantDigitsUsed() was false, expected true.\n", __FILE__, __LINE__);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007651 }
7652
Frank Tang1f164ee2022-11-08 12:31:27 -08007653 numberFormat->setSignificantDigitsUsed(false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007654 numberFormat->setMaximumSignificantDigits(6);
Frank Tang1f164ee2022-11-08 12:31:27 -08007655 if (numberFormat->areSignificantDigitsUsed() == false) {
7656 errln("File %s, Line %d: areSignificantDigitsUsed() was false, expected true.\n", __FILE__, __LINE__);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007657 }
7658
7659}
7660
7661void NumberFormatTest::TestParseNegativeWithFaLocale() {
7662 UErrorCode status = U_ZERO_ERROR;
7663 DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status);
7664 CHECK_DATA(status, "NumberFormat::createInstance");
Frank Tang1f164ee2022-11-08 12:31:27 -08007665 test->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007666 Formattable af;
7667 ParsePosition ppos;
7668 UnicodeString value("\\u200e-0,5");
7669 value = value.unescape();
7670 test->parse(value, af, ppos);
7671 if (ppos.getIndex() == 0) {
7672 errln("Expected -0,5 to parse for Farsi.");
7673 }
7674 delete test;
7675}
7676
7677void NumberFormatTest::TestParseNegativeWithAlternateMinusSign() {
7678 UErrorCode status = U_ZERO_ERROR;
7679 DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("en", status);
7680 CHECK_DATA(status, "NumberFormat::createInstance");
Frank Tang1f164ee2022-11-08 12:31:27 -08007681 test->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08007682 Formattable af;
7683 ParsePosition ppos;
7684 UnicodeString value("\\u208B0.5");
7685 value = value.unescape();
7686 test->parse(value, af, ppos);
7687 if (ppos.getIndex() == 0) {
7688 errln(UnicodeString("Expected ") + value + UnicodeString(" to parse."));
7689 }
7690 delete test;
7691}
7692
7693void NumberFormatTest::TestCustomCurrencySignAndSeparator() {
7694 UErrorCode status = U_ZERO_ERROR;
7695 DecimalFormatSymbols custom(Locale::getUS(), status);
7696 CHECK(status, "DecimalFormatSymbols constructor");
7697
7698 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "*");
7699 custom.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, "^");
7700 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, ":");
7701
7702 UnicodeString pat(" #,##0.00");
7703 pat.insert(0, (UChar)0x00A4);
7704
7705 DecimalFormat fmt(pat, custom, status);
7706 CHECK(status, "DecimalFormat constructor");
7707
7708 UnicodeString numstr("* 1^234:56");
7709 expect2(fmt, (Formattable)((double)1234.56), numstr);
7710}
7711
7712typedef struct {
7713 const char * locale;
7714 UBool lenient;
7715 UnicodeString numString;
7716 double value;
7717} SignsAndMarksItem;
7718
7719
7720void NumberFormatTest::TestParseSignsAndMarks() {
7721 const SignsAndMarksItem items[] = {
7722 // locale lenient numString value
Frank Tang1f164ee2022-11-08 12:31:27 -08007723 { "en", false, CharsToUnicodeString("12"), 12 },
7724 { "en", true, CharsToUnicodeString("12"), 12 },
7725 { "en", false, CharsToUnicodeString("-23"), -23 },
7726 { "en", true, CharsToUnicodeString("-23"), -23 },
7727 { "en", true, CharsToUnicodeString("- 23"), -23 },
7728 { "en", false, CharsToUnicodeString("\\u200E-23"), -23 },
7729 { "en", true, CharsToUnicodeString("\\u200E-23"), -23 },
7730 { "en", true, CharsToUnicodeString("\\u200E- 23"), -23 },
Frank Tang3e05d9d2021-11-08 14:04:04 -08007731
Frank Tang1f164ee2022-11-08 12:31:27 -08007732 { "en@numbers=arab", false, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7733 { "en@numbers=arab", true, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7734 { "en@numbers=arab", false, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7735 { "en@numbers=arab", true, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7736 { "en@numbers=arab", true, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
7737 { "en@numbers=arab", false, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7738 { "en@numbers=arab", true, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7739 { "en@numbers=arab", true, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
Frank Tang3e05d9d2021-11-08 14:04:04 -08007740
Frank Tang1f164ee2022-11-08 12:31:27 -08007741 { "en@numbers=arabext", false, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7742 { "en@numbers=arabext", true, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7743 { "en@numbers=arabext", false, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7744 { "en@numbers=arabext", true, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7745 { "en@numbers=arabext", true, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
7746 { "en@numbers=arabext", false, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7747 { "en@numbers=arabext", true, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7748 { "en@numbers=arabext", true, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
Frank Tang3e05d9d2021-11-08 14:04:04 -08007749
Frank Tang1f164ee2022-11-08 12:31:27 -08007750 { "he", false, CharsToUnicodeString("12"), 12 },
7751 { "he", true, CharsToUnicodeString("12"), 12 },
7752 { "he", false, CharsToUnicodeString("-23"), -23 },
7753 { "he", true, CharsToUnicodeString("-23"), -23 },
7754 { "he", true, CharsToUnicodeString("- 23"), -23 },
7755 { "he", false, CharsToUnicodeString("\\u200E-23"), -23 },
7756 { "he", true, CharsToUnicodeString("\\u200E-23"), -23 },
7757 { "he", true, CharsToUnicodeString("\\u200E- 23"), -23 },
Frank Tang3e05d9d2021-11-08 14:04:04 -08007758
Frank Tang1f164ee2022-11-08 12:31:27 -08007759 { "ar", false, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7760 { "ar", true, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7761 { "ar", false, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7762 { "ar", true, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7763 { "ar", true, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
7764 { "ar", false, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7765 { "ar", true, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7766 { "ar", true, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
Frank Tang3e05d9d2021-11-08 14:04:04 -08007767
Frank Tang1f164ee2022-11-08 12:31:27 -08007768 { "ar_MA", false, CharsToUnicodeString("12"), 12 },
7769 { "ar_MA", true, CharsToUnicodeString("12"), 12 },
7770 { "ar_MA", false, CharsToUnicodeString("-23"), -23 },
7771 { "ar_MA", true, CharsToUnicodeString("-23"), -23 },
7772 { "ar_MA", true, CharsToUnicodeString("- 23"), -23 },
7773 { "ar_MA", false, CharsToUnicodeString("\\u200E-23"), -23 },
7774 { "ar_MA", true, CharsToUnicodeString("\\u200E-23"), -23 },
7775 { "ar_MA", true, CharsToUnicodeString("\\u200E- 23"), -23 },
Frank Tang3e05d9d2021-11-08 14:04:04 -08007776
Frank Tang1f164ee2022-11-08 12:31:27 -08007777 { "fa", false, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7778 { "fa", true, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7779 { "fa", false, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
7780 { "fa", true, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
7781 { "fa", true, CharsToUnicodeString("\\u2212 \\u06F6\\u06F7"), -67 },
7782 { "fa", false, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
7783 { "fa", true, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
7784 { "fa", true, CharsToUnicodeString("\\u200E\\u2212\\u200E \\u06F6\\u06F7"), -67 },
Frank Tang3e05d9d2021-11-08 14:04:04 -08007785
Frank Tang1f164ee2022-11-08 12:31:27 -08007786 { "ps", false, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7787 { "ps", true, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7788 { "ps", false, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7789 { "ps", true, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7790 { "ps", true, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
7791 { "ps", false, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7792 { "ps", true, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7793 { "ps", true, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
7794 { "ps", false, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
7795 { "ps", true, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
7796 { "ps", true, CharsToUnicodeString("-\\u200E \\u06F6\\u06F7"), -67 },
Frank Tang3e05d9d2021-11-08 14:04:04 -08007797 // terminator
7798 { NULL, 0, UnicodeString(""), 0 },
7799 };
7800
7801 const SignsAndMarksItem * itemPtr;
7802 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
7803 UErrorCode status = U_ZERO_ERROR;
7804 NumberFormat *numfmt = NumberFormat::createInstance(Locale(itemPtr->locale), status);
7805 if (U_SUCCESS(status)) {
7806 numfmt->setLenient(itemPtr->lenient);
7807 Formattable fmtobj;
7808 ParsePosition ppos;
7809 numfmt->parse(itemPtr->numString, fmtobj, ppos);
7810 if (ppos.getIndex() == itemPtr->numString.length()) {
7811 double parsedValue = fmtobj.getDouble(status);
7812 if (U_FAILURE(status) || parsedValue != itemPtr->value) {
7813 errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives value " + parsedValue);
7814 }
7815 } else {
7816 errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives position " + ppos.getIndex());
7817 }
7818 } else {
7819 dataerrln("FAIL: NumberFormat::createInstance for locale % gives error %s", itemPtr->locale, u_errorName(status));
7820 }
7821 delete numfmt;
7822 }
7823}
7824
7825typedef struct {
7826 DecimalFormat::ERoundingMode mode;
7827 double value;
7828 UnicodeString expected;
7829} Test10419Data;
7830
7831
7832// Tests that rounding works right when fractional digits is set to 0.
7833void NumberFormatTest::Test10419RoundingWith0FractionDigits() {
7834 const Test10419Data items[] = {
7835 { DecimalFormat::kRoundCeiling, 1.488, "2"},
7836 { DecimalFormat::kRoundDown, 1.588, "1"},
7837 { DecimalFormat::kRoundFloor, 1.888, "1"},
7838 { DecimalFormat::kRoundHalfDown, 1.5, "1"},
7839 { DecimalFormat::kRoundHalfEven, 2.5, "2"},
7840 { DecimalFormat::kRoundHalfUp, 2.5, "3"},
7841 { DecimalFormat::kRoundUp, 1.5, "2"},
7842 };
7843 UErrorCode status = U_ZERO_ERROR;
7844 LocalPointer<DecimalFormat> decfmt((DecimalFormat *) NumberFormat::createInstance(Locale("en_US"), status));
7845 if (U_FAILURE(status)) {
7846 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
7847 return;
7848 }
7849 for (int32_t i = 0; i < UPRV_LENGTHOF(items); ++i) {
7850 decfmt->setRoundingMode(items[i].mode);
7851 decfmt->setMaximumFractionDigits(0);
7852 UnicodeString actual;
7853 if (items[i].expected != decfmt->format(items[i].value, actual)) {
7854 errln("Expected " + items[i].expected + ", got " + actual);
7855 }
7856 }
7857}
7858
7859void NumberFormatTest::Test10468ApplyPattern() {
7860 // Padding char of fmt is now 'a'
7861 UErrorCode status = U_ZERO_ERROR;
7862 DecimalFormat fmt("'I''ll'*a###.##", status);
7863
7864 if (U_FAILURE(status)) {
7865 errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7866 return;
7867 }
7868
7869 assertEquals("Padding character should be 'a'.", u"a", fmt.getPadCharacterString());
7870
7871 // Padding char of fmt ought to be '*' since that is the default and no
7872 // explicit padding char is specified in the new pattern.
7873 fmt.applyPattern("AA#,##0.00ZZ", status);
7874
7875 // Oops this still prints 'a' even though we changed the pattern.
7876 assertEquals("applyPattern did not clear padding character.", u" ", fmt.getPadCharacterString());
7877}
7878
7879void NumberFormatTest::TestRoundingScientific10542() {
7880 UErrorCode status = U_ZERO_ERROR;
7881 DecimalFormat format("0.00E0", status);
7882 if (U_FAILURE(status)) {
7883 errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7884 return;
7885 }
7886
7887 DecimalFormat::ERoundingMode roundingModes[] = {
7888 DecimalFormat::kRoundCeiling,
7889 DecimalFormat::kRoundDown,
7890 DecimalFormat::kRoundFloor,
7891 DecimalFormat::kRoundHalfDown,
7892 DecimalFormat::kRoundHalfEven,
7893 DecimalFormat::kRoundHalfUp,
7894 DecimalFormat::kRoundUp};
7895 const char *descriptions[] = {
7896 "Round Ceiling",
7897 "Round Down",
7898 "Round Floor",
7899 "Round half down",
7900 "Round half even",
7901 "Round half up",
7902 "Round up"};
7903
7904 {
7905 double values[] = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016};
7906 // The order of these expected values correspond to the order of roundingModes and the order of values.
7907 const char *expected[] = {
7908 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.02E-3", "3.02E-3", "3.02E-3",
7909 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7910 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7911 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.02E-3",
7912 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7913 "-3.01E-3", "-3.01E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7914 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.02E-3", "3.02E-3", "3.02E-3"};
7915 verifyRounding(
7916 format,
7917 values,
7918 expected,
7919 roundingModes,
7920 descriptions,
7921 UPRV_LENGTHOF(values),
7922 UPRV_LENGTHOF(roundingModes));
7923 }
7924 {
7925 double values[] = {-3006.0, -3005, -3004, 3014, 3015, 3016};
7926 // The order of these expected values correspond to the order of roundingModes and the order of values.
7927 const char *expected[] = {
7928 "-3.00E3", "-3.00E3", "-3.00E3", "3.02E3", "3.02E3", "3.02E3",
7929 "-3.00E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.01E3",
7930 "-3.01E3", "-3.01E3", "-3.01E3", "3.01E3", "3.01E3", "3.01E3",
7931 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.02E3",
7932 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7933 "-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7934 "-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"};
7935 verifyRounding(
7936 format,
7937 values,
7938 expected,
7939 roundingModes,
7940 descriptions,
7941 UPRV_LENGTHOF(values),
7942 UPRV_LENGTHOF(roundingModes));
7943 }
7944/* Commented out for now until we decide how rounding to zero should work, +0 vs. -0
7945 {
7946 double values[] = {0.0, -0.0};
7947 // The order of these expected values correspond to the order of roundingModes and the order of values.
7948 const char *expected[] = {
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 "0.00E0", "-0.00E0",
7955 "0.00E0", "-0.00E0"};
7956 verifyRounding(
7957 format,
7958 values,
7959 expected,
7960 roundingModes,
7961 descriptions,
7962 UPRV_LENGTHOF(values),
7963 UPRV_LENGTHOF(roundingModes));
7964 }
7965*/
7966 {
7967
7968 double values[] = {1e25, 1e25 + 1e15, 1e25 - 1e15};
7969 // The order of these expected values correspond to the order of roundingModes and the order of values.
7970 const char *expected[] = {
7971 "1.00E25", "1.01E25", "1.00E25",
7972 "1.00E25", "1.00E25", "9.99E24",
7973 "1.00E25", "1.00E25", "9.99E24",
7974 "1.00E25", "1.00E25", "1.00E25",
7975 "1.00E25", "1.00E25", "1.00E25",
7976 "1.00E25", "1.00E25", "1.00E25",
7977 "1.00E25", "1.01E25", "1.00E25"};
7978 verifyRounding(
7979 format,
7980 values,
7981 expected,
7982 roundingModes,
7983 descriptions,
7984 UPRV_LENGTHOF(values),
7985 UPRV_LENGTHOF(roundingModes));
7986 }
7987 {
7988 double values[] = {-1e25, -1e25 + 1e15, -1e25 - 1e15};
7989 // The order of these expected values correspond to the order of roundingModes and the order of values.
7990 const char *expected[] = {
7991 "-1.00E25", "-9.99E24", "-1.00E25",
7992 "-1.00E25", "-9.99E24", "-1.00E25",
7993 "-1.00E25", "-1.00E25", "-1.01E25",
7994 "-1.00E25", "-1.00E25", "-1.00E25",
7995 "-1.00E25", "-1.00E25", "-1.00E25",
7996 "-1.00E25", "-1.00E25", "-1.00E25",
7997 "-1.00E25", "-1.00E25", "-1.01E25"};
7998 verifyRounding(
7999 format,
8000 values,
8001 expected,
8002 roundingModes,
8003 descriptions,
8004 UPRV_LENGTHOF(values),
8005 UPRV_LENGTHOF(roundingModes));
8006 }
8007 {
8008 double values[] = {1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
8009 // The order of these expected values correspond to the order of roundingModes and the order of values.
8010 const char *expected[] = {
8011 "1.00E-25", "1.01E-25", "1.00E-25",
8012 "1.00E-25", "1.00E-25", "9.99E-26",
8013 "1.00E-25", "1.00E-25", "9.99E-26",
8014 "1.00E-25", "1.00E-25", "1.00E-25",
8015 "1.00E-25", "1.00E-25", "1.00E-25",
8016 "1.00E-25", "1.00E-25", "1.00E-25",
8017 "1.00E-25", "1.01E-25", "1.00E-25"};
8018 verifyRounding(
8019 format,
8020 values,
8021 expected,
8022 roundingModes,
8023 descriptions,
8024 UPRV_LENGTHOF(values),
8025 UPRV_LENGTHOF(roundingModes));
8026 }
8027 {
8028 double values[] = {-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
8029 // The order of these expected values correspond to the order of roundingModes and the order of values.
8030 const char *expected[] = {
8031 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8032 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8033 "-1.00E-25", "-1.00E-25", "-1.01E-25",
8034 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8035 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8036 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8037 "-1.00E-25", "-1.00E-25", "-1.01E-25"};
8038 verifyRounding(
8039 format,
8040 values,
8041 expected,
8042 roundingModes,
8043 descriptions,
8044 UPRV_LENGTHOF(values),
8045 UPRV_LENGTHOF(roundingModes));
8046 }
8047}
8048
8049void NumberFormatTest::TestZeroScientific10547() {
8050 UErrorCode status = U_ZERO_ERROR;
8051 DecimalFormat fmt("0.00E0", status);
8052 if (!assertSuccess("Format creation", status)) {
8053 return;
8054 }
8055 UnicodeString out;
8056 fmt.format(-0.0, out);
8057 assertEquals("format", "-0.00E0", out, true);
8058}
8059
8060void NumberFormatTest::verifyRounding(
8061 DecimalFormat& format,
8062 const double *values,
8063 const char * const *expected,
8064 const DecimalFormat::ERoundingMode *roundingModes,
8065 const char * const *descriptions,
8066 int32_t valueSize,
8067 int32_t roundingModeSize) {
8068 for (int32_t i = 0; i < roundingModeSize; ++i) {
8069 format.setRoundingMode(roundingModes[i]);
8070 for (int32_t j = 0; j < valueSize; j++) {
8071 UnicodeString currentExpected(expected[i * valueSize + j]);
8072 currentExpected = currentExpected.unescape();
8073 UnicodeString actual;
8074 format.format(values[j], actual);
8075 if (currentExpected != actual) {
8076 dataerrln("For %s value %f, expected '%s', got '%s'",
8077 descriptions[i], values[j], CStr(currentExpected)(), CStr(actual)());
8078 }
8079 }
8080 }
8081}
8082
8083void NumberFormatTest::TestAccountingCurrency() {
8084 UErrorCode status = U_ZERO_ERROR;
8085 UNumberFormatStyle style = UNUM_CURRENCY_ACCOUNTING;
8086
8087 expect(NumberFormat::createInstance("en_US", style, status),
Frank Tang1f164ee2022-11-08 12:31:27 -08008088 (Formattable)(double)1234.5, "$1,234.50", true, status);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008089 expect(NumberFormat::createInstance("en_US", style, status),
Frank Tang1f164ee2022-11-08 12:31:27 -08008090 (Formattable)(double)-1234.5, "($1,234.50)", true, status);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008091 expect(NumberFormat::createInstance("en_US", style, status),
Frank Tang1f164ee2022-11-08 12:31:27 -08008092 (Formattable)(double)0, "$0.00", true, status);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008093 expect(NumberFormat::createInstance("en_US", style, status),
Frank Tang1f164ee2022-11-08 12:31:27 -08008094 (Formattable)(double)-0.2, "($0.20)", true, status);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008095 expect(NumberFormat::createInstance("ja_JP", style, status),
Frank Tang1f164ee2022-11-08 12:31:27 -08008096 (Formattable)(double)10000, UnicodeString("\\uFFE510,000").unescape(), true, status);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008097 expect(NumberFormat::createInstance("ja_JP", style, status),
Frank Tang1f164ee2022-11-08 12:31:27 -08008098 (Formattable)(double)-1000.5, UnicodeString("(\\uFFE51,000)").unescape(), false, status);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008099 expect(NumberFormat::createInstance("de_DE", style, status),
Frank Tang1f164ee2022-11-08 12:31:27 -08008100 (Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), true, status);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008101 expect(NumberFormat::createInstance("en_ID", style, status),
Frank Tang1f164ee2022-11-08 12:31:27 -08008102 (Formattable)(double)0, UnicodeString("IDR\\u00A00.00").unescape(), true, status);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008103 expect(NumberFormat::createInstance("en_ID", style, status),
Frank Tang1f164ee2022-11-08 12:31:27 -08008104 (Formattable)(double)-0.2, UnicodeString("(IDR\\u00A00.20)").unescape(), true, status);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008105 expect(NumberFormat::createInstance("sh_ME", style, status),
Frank Tang1f164ee2022-11-08 12:31:27 -08008106 (Formattable)(double)0, UnicodeString("0,00\\u00A0\\u20AC").unescape(), true, status);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008107 expect(NumberFormat::createInstance("sh_ME", style, status),
Frank Tang1f164ee2022-11-08 12:31:27 -08008108 (Formattable)(double)-0.2, UnicodeString("(0,20\\u00A0\\u20AC)").unescape(), true, status);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008109}
8110
8111/**
8112 * ICU4J has the behavior explained below, but ICU4C is not affected. Test is added to prevent regression.
8113 *
8114 * en_ID/sh_ME uses language only locales en/sh which requires NumberFormatServiceShim to fill in the currency, but
8115 * prior to ICU-20631, currency was not filled in for accounting, cash and standard, so currency placeholder was
8116 * used instead of the desired locale's currency.
8117 */
8118void NumberFormatTest::TestCurrencyFormatForMissingLocale() {
8119 IcuTestErrorCode status(*this, "TestCurrencyFormatForMissingLocale");
8120 Locale locale = Locale::createCanonical("sh_ME");
8121
8122 LocalPointer<NumberFormat> curFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status));
8123 // Fail here with missing data.
8124 if (!assertTrue(WHERE, curFmt.isValid(), false, true)) {return;};
8125 assertEquals("Currency instance is not for the desired locale for CURRENCYSTYLE", curFmt->getCurrency(), "EUR");
8126 UnicodeString currBuf;
8127 curFmt->format(-1234.5, currBuf);
8128 assertEquals("NumberFormat format outputs wrong value for CURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", currBuf);
8129
8130 LocalPointer<NumberFormat> accFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_ACCOUNTING, status));
8131 assertEquals("Currency instance is not for the desired locale for ACCOUNTINGCURRENCYSTYLE", accFmt->getCurrency(), "EUR");
8132 UnicodeString accBuf;
8133 accFmt->format(-1234.5, accBuf);
8134 assertEquals("NumberFormat format outputs wrong value for ACCOUNTINGCURRENCYSTYLE", u"(1.234,50\u00A0\u20AC)", accBuf);
8135
8136 LocalPointer<NumberFormat> cashFmt(NumberFormat::createInstance(locale, UNUM_CASH_CURRENCY, status));
8137 assertEquals("Currency instance is not for the desired locale for CASHCURRENCYSTYLE", cashFmt->getCurrency(), "EUR");
8138 UnicodeString cashBuf;
8139 cashFmt->format(-1234.5, cashBuf);
8140 assertEquals("NumberFormat format outputs wrong value for CASHCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", cashBuf);
8141
8142 LocalPointer<NumberFormat> stdFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_STANDARD, status));
8143 assertEquals("Currency instance is not for the desired locale for STANDARDCURRENCYSTYLE", stdFmt->getCurrency(), "EUR");
8144 UnicodeString stdBuf;
8145 stdFmt->format(-1234.5, stdBuf);
8146 assertEquals("NumberFormat format outputs wrong value for STANDARDCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", stdBuf);
8147}
8148
8149// for #5186
8150void NumberFormatTest::TestEquality() {
8151 UErrorCode status = U_ZERO_ERROR;
8152 DecimalFormatSymbols symbols(Locale("root"), status);
8153 if (U_FAILURE(status)) {
8154 dataerrln("Fail: can't create DecimalFormatSymbols for root");
8155 return;
8156 }
8157 UnicodeString pattern("#,##0.###");
8158 DecimalFormat fmtBase(pattern, symbols, status);
8159 if (U_FAILURE(status)) {
8160 dataerrln("Fail: can't create DecimalFormat using root symbols");
8161 return;
8162 }
8163
8164 DecimalFormat* fmtClone = fmtBase.clone();
8165 fmtClone->setFormatWidth(fmtBase.getFormatWidth() + 32);
8166 if (*fmtClone == fmtBase) {
8167 errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth");
8168 }
8169 delete fmtClone;
8170}
8171
8172void NumberFormatTest::TestCurrencyUsage() {
8173 double agent = 123.567;
8174
8175 UErrorCode status;
8176 DecimalFormat *fmt;
8177
8178 // compare the Currency and Currency Cash Digits
8179 // Note that as of CLDR 26:
8180 // * TWD and PKR switched from 0 decimals to 2; ISK still has 0, so change test to that
8181 // * CAD rounds to .05 in cash mode only
8182 // 1st time for getter/setter, 2nd time for factory method
8183 Locale enUS_ISK("en_US@currency=ISK");
8184
8185 for(int i=0; i<2; i++){
8186 status = U_ZERO_ERROR;
8187 if(i == 0){
8188 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CURRENCY, status);
Frank Tang1f164ee2022-11-08 12:31:27 -08008189 if (assertSuccess("en_US@currency=ISK/CURRENCY", status, true) == false) {
Frank Tang3e05d9d2021-11-08 14:04:04 -08008190 continue;
8191 }
8192
8193 UnicodeString original;
8194 fmt->format(agent,original);
8195 assertEquals("Test Currency Usage 1", u"ISK\u00A0124", original);
8196
8197 // test the getter here
8198 UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8199 assertEquals("Test usage getter - standard", (int32_t)curUsage, (int32_t)UCURR_USAGE_STANDARD);
8200
8201 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8202 }else{
8203 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CASH_CURRENCY, status);
Frank Tang1f164ee2022-11-08 12:31:27 -08008204 if (assertSuccess("en_US@currency=ISK/CASH", status, true) == false) {
Frank Tang3e05d9d2021-11-08 14:04:04 -08008205 continue;
8206 }
8207 }
8208
8209 // must be usage = cash
8210 UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8211 assertEquals("Test usage getter - cash", (int32_t)curUsage, (int32_t)UCURR_USAGE_CASH);
8212
8213 UnicodeString cash_currency;
8214 fmt->format(agent,cash_currency);
8215 assertEquals("Test Currency Usage 2", u"ISK\u00A0124", cash_currency);
8216 delete fmt;
8217 }
8218
8219 // compare the Currency and Currency Cash Rounding
8220 // 1st time for getter/setter, 2nd time for factory method
8221 Locale enUS_CAD("en_US@currency=CAD");
8222 for(int i=0; i<2; i++){
8223 status = U_ZERO_ERROR;
8224 if(i == 0){
8225 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
Frank Tang1f164ee2022-11-08 12:31:27 -08008226 if (assertSuccess("en_US@currency=CAD/CURRENCY", status, true) == false) {
Frank Tang3e05d9d2021-11-08 14:04:04 -08008227 continue;
8228 }
8229
8230 UnicodeString original_rounding;
8231 fmt->format(agent, original_rounding);
8232 assertEquals("Test Currency Usage 3", u"CA$123.57", original_rounding);
8233 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8234 }else{
8235 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
Frank Tang1f164ee2022-11-08 12:31:27 -08008236 if (assertSuccess("en_US@currency=CAD/CASH", status, true) == false) {
Frank Tang3e05d9d2021-11-08 14:04:04 -08008237 continue;
8238 }
8239 }
8240
8241 UnicodeString cash_rounding_currency;
8242 fmt->format(agent, cash_rounding_currency);
8243 assertEquals("Test Currency Usage 4", u"CA$123.55", cash_rounding_currency);
8244 delete fmt;
8245 }
8246
8247 // Test the currency change
8248 // 1st time for getter/setter, 2nd time for factory method
8249 const UChar CUR_PKR[] = {0x50, 0x4B, 0x52, 0};
8250 for(int i=0; i<2; i++){
8251 status = U_ZERO_ERROR;
8252 if(i == 0){
8253 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
Frank Tang1f164ee2022-11-08 12:31:27 -08008254 if (assertSuccess("en_US@currency=CAD/CURRENCY", status, true) == false) {
Frank Tang3e05d9d2021-11-08 14:04:04 -08008255 continue;
8256 }
8257 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8258 }else{
8259 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
Frank Tang1f164ee2022-11-08 12:31:27 -08008260 if (assertSuccess("en_US@currency=CAD/CASH", status, true) == false) {
Frank Tang3e05d9d2021-11-08 14:04:04 -08008261 continue;
8262 }
8263 }
8264
8265 UnicodeString cur_original;
8266 fmt->setCurrencyUsage(UCURR_USAGE_STANDARD, &status);
8267 fmt->format(agent, cur_original);
8268 assertEquals("Test Currency Usage 5", u"CA$123.57", cur_original);
8269
8270 fmt->setCurrency(CUR_PKR, status);
8271 assertSuccess("Set currency to PKR", status);
8272
8273 UnicodeString PKR_changed;
8274 fmt->format(agent, PKR_changed);
8275 assertEquals("Test Currency Usage 6", u"PKR\u00A0123.57", PKR_changed);
8276 delete fmt;
8277 }
8278}
8279
8280
8281// Check the constant MAX_INT64_IN_DOUBLE.
8282// The value should convert to a double with no loss of precision.
8283// A failure may indicate a platform with a different double format, requiring
8284// a revision to the constant.
8285//
8286// Note that this is actually hard to test, because the language standard gives
8287// compilers considerable flexibility to do unexpected things with rounding and
8288// with overflow in simple int to/from float conversions. Some compilers will completely optimize
8289// away a simple round-trip conversion from int64_t -> double -> int64_t.
8290
8291void NumberFormatTest::TestDoubleLimit11439() {
8292 char buf[50];
8293 for (int64_t num = MAX_INT64_IN_DOUBLE-10; num<=MAX_INT64_IN_DOUBLE; num++) {
8294 sprintf(buf, "%lld", (long long)num);
8295 double fNum = 0.0;
8296 sscanf(buf, "%lf", &fNum);
8297 int64_t rtNum = static_cast<int64_t>(fNum);
8298 if (num != rtNum) {
8299 errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8300 return;
8301 }
8302 }
8303 for (int64_t num = -MAX_INT64_IN_DOUBLE+10; num>=-MAX_INT64_IN_DOUBLE; num--) {
8304 sprintf(buf, "%lld", (long long)num);
8305 double fNum = 0.0;
8306 sscanf(buf, "%lf", &fNum);
8307 int64_t rtNum = static_cast<int64_t>(fNum);
8308 if (num != rtNum) {
8309 errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8310 return;
8311 }
8312 }
8313}
8314
8315void NumberFormatTest::TestGetAffixes() {
8316 UErrorCode status = U_ZERO_ERROR;
8317 DecimalFormatSymbols sym("en_US", status);
8318 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8319 pattern = pattern.unescape();
8320 DecimalFormat fmt(pattern, sym, status);
8321 if (U_FAILURE(status)) {
8322 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8323 return;
8324 }
8325 UnicodeString affixStr;
8326 assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8327 assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8328 assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8329 assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8330
8331 // Test equality with affixes. set affix methods can't capture special
8332 // characters which is why equality should fail.
8333 {
8334 DecimalFormat fmtCopy(fmt);
8335 assertTrue("", fmt == fmtCopy);
8336 UnicodeString someAffix;
8337 fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(someAffix));
8338 assertTrue("", fmt != fmtCopy);
8339 }
8340 {
8341 DecimalFormat fmtCopy(fmt);
8342 assertTrue("", fmt == fmtCopy);
8343 UnicodeString someAffix;
8344 fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(someAffix));
8345 assertTrue("", fmt != fmtCopy);
8346 }
8347 {
8348 DecimalFormat fmtCopy(fmt);
8349 assertTrue("", fmt == fmtCopy);
8350 UnicodeString someAffix;
8351 fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(someAffix));
8352 assertTrue("", fmt != fmtCopy);
8353 }
8354 {
8355 DecimalFormat fmtCopy(fmt);
8356 assertTrue("", fmt == fmtCopy);
8357 UnicodeString someAffix;
8358 fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(someAffix));
8359 assertTrue("", fmt != fmtCopy);
8360 }
8361 fmt.setPositivePrefix("Don't");
8362 fmt.setPositiveSuffix("do");
8363 UnicodeString someAffix("be''eet\\u00a4\\u00a4\\u00a4 it.");
8364 someAffix = someAffix.unescape();
8365 fmt.setNegativePrefix(someAffix);
8366 fmt.setNegativeSuffix("%");
8367 assertEquals("", "Don't", fmt.getPositivePrefix(affixStr));
8368 assertEquals("", "do", fmt.getPositiveSuffix(affixStr));
8369 assertEquals("", someAffix, fmt.getNegativePrefix(affixStr));
8370 assertEquals("", "%", fmt.getNegativeSuffix(affixStr));
8371}
8372
8373void NumberFormatTest::TestToPatternScientific11648() {
8374 UErrorCode status = U_ZERO_ERROR;
8375 Locale en("en");
8376 DecimalFormatSymbols sym(en, status);
8377 DecimalFormat fmt("0.00", sym, status);
8378 if (U_FAILURE(status)) {
8379 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8380 return;
8381 }
Frank Tang1f164ee2022-11-08 12:31:27 -08008382 fmt.setScientificNotation(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008383 UnicodeString pattern;
8384 assertEquals("", "0.00E0", fmt.toPattern(pattern));
8385 DecimalFormat fmt2(pattern, sym, status);
8386 assertSuccess("", status);
8387}
8388
8389void NumberFormatTest::TestBenchmark() {
8390/*
8391 UErrorCode status = U_ZERO_ERROR;
8392 Locale en("en");
8393 DecimalFormatSymbols sym(en, status);
8394 DecimalFormat fmt("0.0000000", new DecimalFormatSymbols(sym), status);
8395// DecimalFormat fmt("0.00000E0", new DecimalFormatSymbols(sym), status);
8396// DecimalFormat fmt("0", new DecimalFormatSymbols(sym), status);
8397 FieldPosition fpos(FieldPosition::DONT_CARE);
8398 clock_t start = clock();
8399 for (int32_t i = 0; i < 1000000; ++i) {
8400 UnicodeString append;
8401 fmt.format(3.0, append, fpos, status);
8402// fmt.format(4.6692016, append, fpos, status);
8403// fmt.format(1234567.8901, append, fpos, status);
8404// fmt.format(2.99792458E8, append, fpos, status);
8405// fmt.format(31, append);
8406 }
8407 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8408 assertSuccess("", status);
8409
8410 UErrorCode status = U_ZERO_ERROR;
8411 MessageFormat fmt("{0, plural, one {I have # friend.} other {I have # friends.}}", status);
8412 FieldPosition fpos(FieldPosition::DONT_CARE);
8413 Formattable one(1.0);
8414 Formattable three(3.0);
8415 clock_t start = clock();
8416 for (int32_t i = 0; i < 500000; ++i) {
8417 UnicodeString append;
8418 fmt.format(&one, 1, append, fpos, status);
8419 UnicodeString append2;
8420 fmt.format(&three, 1, append2, fpos, status);
8421 }
8422 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8423 assertSuccess("", status);
8424
8425 UErrorCode status = U_ZERO_ERROR;
8426 Locale en("en");
8427 Measure measureC(23, MeasureUnit::createCelsius(status), status);
8428 MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
8429 FieldPosition fpos(FieldPosition::DONT_CARE);
8430 clock_t start = clock();
8431 for (int32_t i = 0; i < 1000000; ++i) {
8432 UnicodeString appendTo;
8433 fmt.formatMeasures(
8434 &measureC, 1, appendTo, fpos, status);
8435 }
8436 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8437 assertSuccess("", status);
8438*/
8439}
8440
8441void NumberFormatTest::TestFractionalDigitsForCurrency() {
8442 UErrorCode status = U_ZERO_ERROR;
8443 LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance("en", status));
8444 if (U_FAILURE(status)) {
8445 dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8446 return;
8447 }
8448 UChar JPY[] = {0x4A, 0x50, 0x59, 0x0};
8449 fmt->setCurrency(JPY, status);
8450 if (!assertSuccess("", status)) {
8451 return;
8452 }
8453 assertEquals("", 0, fmt->getMaximumFractionDigits());
8454}
8455
8456
8457void NumberFormatTest::TestFormatCurrencyPlural() {
8458 UErrorCode status = U_ZERO_ERROR;
8459 Locale locale = Locale::createCanonical("en_US");
8460 NumberFormat *fmt = NumberFormat::createInstance(locale, UNUM_CURRENCY_PLURAL, status);
8461 if (U_FAILURE(status)) {
8462 dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8463 return;
8464 }
8465 UnicodeString formattedNum;
8466 fmt->format(11234.567, formattedNum, NULL, status);
8467 assertEquals("", "11,234.57 US dollars", formattedNum);
8468 delete fmt;
8469}
8470
8471void NumberFormatTest::TestCtorApplyPatternDifference() {
8472 UErrorCode status = U_ZERO_ERROR;
8473 DecimalFormatSymbols sym("en_US", status);
8474 UnicodeString pattern("\\u00a40");
8475 DecimalFormat fmt(pattern.unescape(), sym, status);
8476 if (U_FAILURE(status)) {
8477 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8478 return;
8479 }
8480 UnicodeString result;
8481 assertEquals(
8482 "ctor favors precision of currency",
8483 "$5.00",
8484 fmt.format((double)5, result));
8485 result.remove();
8486 fmt.applyPattern(pattern.unescape(), status);
8487 assertEquals(
8488 "applyPattern favors precision of pattern",
8489 "$5",
8490 fmt.format((double)5, result));
8491}
8492
8493void NumberFormatTest::Test11868() {
8494 double posAmt = 34.567;
8495 double negAmt = -9876.543;
8496
8497 Locale selectedLocale("en_US");
8498 UErrorCode status = U_ZERO_ERROR;
8499
8500 UnicodeString result;
8501 FieldPosition fpCurr(UNUM_CURRENCY_FIELD);
8502 LocalPointer<NumberFormat> fmt(
8503 NumberFormat::createInstance(
8504 selectedLocale, UNUM_CURRENCY_PLURAL, status));
8505 if (!assertSuccess("Format creation", status)) {
8506 return;
8507 }
8508 fmt->format(posAmt, result, fpCurr, status);
8509 assertEquals("", "34.57 US dollars", result);
8510 assertEquals("begin index", 6, fpCurr.getBeginIndex());
8511 assertEquals("end index", 16, fpCurr.getEndIndex());
8512
8513 // Test field position iterator
8514 {
8515 NumberFormatTest_Attributes attributes[] = {
8516 {UNUM_INTEGER_FIELD, 0, 2},
8517 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8518 {UNUM_FRACTION_FIELD, 3, 5},
8519 {UNUM_CURRENCY_FIELD, 6, 16},
8520 {0, -1, 0}};
8521 UnicodeString result;
8522 FieldPositionIterator iter;
8523 fmt->format(posAmt, result, &iter, status);
8524 assertEquals("", "34.57 US dollars", result);
8525 verifyFieldPositionIterator(attributes, iter);
8526 }
8527
8528 result.remove();
8529 fmt->format(negAmt, result, fpCurr, status);
8530 assertEquals("", "-9,876.54 US dollars", result);
8531 assertEquals("begin index", 10, fpCurr.getBeginIndex());
8532 assertEquals("end index", 20, fpCurr.getEndIndex());
8533
8534 // Test field position iterator
8535 {
8536 NumberFormatTest_Attributes attributes[] = {
8537 {UNUM_SIGN_FIELD, 0, 1},
8538 {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
8539 {UNUM_INTEGER_FIELD, 1, 6},
8540 {UNUM_DECIMAL_SEPARATOR_FIELD, 6, 7},
8541 {UNUM_FRACTION_FIELD, 7, 9},
8542 {UNUM_CURRENCY_FIELD, 10, 20},
8543 {0, -1, 0}};
8544 UnicodeString result;
8545 FieldPositionIterator iter;
8546 fmt->format(negAmt, result, &iter, status);
8547 assertEquals("", "-9,876.54 US dollars", result);
8548 verifyFieldPositionIterator(attributes, iter);
8549 }
8550}
8551
8552void NumberFormatTest::Test10727_RoundingZero() {
8553 IcuTestErrorCode status(*this, "Test10727_RoundingZero");
8554 DecimalQuantity dq;
8555 dq.setToDouble(-0.0);
8556 assertTrue("", dq.isNegative());
8557 dq.roundToMagnitude(0, UNUM_ROUND_HALFEVEN, status);
8558 assertTrue("", dq.isNegative());
8559}
8560
8561void NumberFormatTest::Test11739_ParseLongCurrency() {
8562 IcuTestErrorCode status(*this, "Test11739_ParseLongCurrency");
8563 LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("sr_BA", status));
8564 if (status.errDataIfFailureAndReset()) { return; }
8565 ((DecimalFormat*) nf.getAlias())->applyPattern(u"#,##0.0 ¤¤¤", status);
8566 ParsePosition ppos(0);
8567 LocalPointer<CurrencyAmount> result(nf->parseCurrency(u"1.500 амерички долар", ppos));
8568 assertEquals("Should parse to 1500 USD", -1, ppos.getErrorIndex());
8569 if (ppos.getErrorIndex() != -1) {
8570 return;
8571 }
8572 assertEquals("Should parse to 1500 USD", 1500LL, result->getNumber().getInt64(status));
8573 assertEquals("Should parse to 1500 USD", u"USD", result->getISOCurrency());
8574}
8575
8576void NumberFormatTest::Test13035_MultiCodePointPaddingInPattern() {
8577 IcuTestErrorCode status(*this, "Test13035_MultiCodePointPaddingInPattern");
8578 DecimalFormat df(u"a*'நி'###0b", status);
8579 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8580 UnicodeString result;
8581 df.format(12, result.remove());
8582 // TODO(13034): Re-enable this test when support is added in ICU4C.
8583 //assertEquals("Multi-codepoint padding should not be split", u"aநிநி12b", result);
8584 df = DecimalFormat(u"a*\U0001F601###0b", status);
8585 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8586 result = df.format(12, result.remove());
8587 assertEquals("Single-codepoint padding should not be split", u"a\U0001F601\U0001F60112b", result, true);
8588 df = DecimalFormat(u"a*''###0b", status);
8589 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8590 result = df.format(12, result.remove());
8591 assertEquals("Quote should be escapable in padding syntax", "a''12b", result, true);
8592}
8593
8594void NumberFormatTest::Test13737_ParseScientificStrict() {
8595 IcuTestErrorCode status(*this, "Test13737_ParseScientificStrict");
8596 LocalPointer<NumberFormat> df(NumberFormat::createScientificInstance("en", status), status);
8597 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
Frank Tang1f164ee2022-11-08 12:31:27 -08008598 df->setLenient(false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008599 // Parse Test
8600 expect(*df, u"1.2", 1.2);
8601}
8602
8603void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
8604 {
8605 const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8606 UErrorCode status = U_ZERO_ERROR;
8607 LocalPointer<NumberFormat> fmt(
8608 NumberFormat::createCurrencyInstance("en", status));
8609 if (!assertSuccess("", status)) {
8610 return;
8611 }
8612 DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8613 dfmt->setCurrency(USD);
8614 UnicodeString result;
8615
8616 // This line should be a no-op. I am setting the positive prefix
8617 // to be the same thing it was before.
8618 dfmt->setPositivePrefix(dfmt->getPositivePrefix(result));
8619
8620 UnicodeString appendTo;
8621 assertEquals("", "$3.78", dfmt->format(3.78, appendTo, status));
8622 assertSuccess("", status);
8623 }
8624 {
8625 const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8626 UErrorCode status = U_ZERO_ERROR;
8627 LocalPointer<NumberFormat> fmt(
8628 NumberFormat::createInstance("en", UNUM_CURRENCY_PLURAL, status));
8629 if (!assertSuccess("", status)) {
8630 return;
8631 }
8632 DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8633 UnicodeString result;
8634 assertEquals("", u" (unknown currency)", dfmt->getPositiveSuffix(result));
8635 dfmt->setCurrency(USD);
8636
8637 // getPositiveSuffix() always returns the suffix for the
8638 // "other" plural category
8639 assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8640 UnicodeString appendTo;
8641 assertEquals("", "3.78 US dollars", dfmt->format(3.78, appendTo, status));
8642 assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8643 dfmt->setPositiveSuffix("booya");
8644 appendTo.remove();
8645 assertEquals("", "3.78booya", dfmt->format(3.78, appendTo, status));
8646 assertEquals("", "booya", dfmt->getPositiveSuffix(result));
8647 }
8648}
8649
8650void NumberFormatTest::Test11475_signRecognition() {
8651 UErrorCode status = U_ZERO_ERROR;
8652 DecimalFormatSymbols sym("en", status);
8653 UnicodeString result;
8654 {
8655 DecimalFormat fmt("+0.00", sym, status);
8656 if (!assertSuccess("", status)) {
8657 return;
8658 }
8659 NumberFormatTest_Attributes attributes[] = {
8660 {UNUM_SIGN_FIELD, 0, 1},
8661 {UNUM_INTEGER_FIELD, 1, 2},
8662 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8663 {UNUM_FRACTION_FIELD, 3, 5},
8664 {0, -1, 0}};
8665 UnicodeString result;
8666 FieldPositionIterator iter;
8667 fmt.format(2.3, result, &iter, status);
8668 assertEquals("", "+2.30", result);
8669 verifyFieldPositionIterator(attributes, iter);
8670 }
8671 {
8672 DecimalFormat fmt("++0.00+;-(#)--", sym, status);
8673 if (!assertSuccess("", status)) {
8674 return;
8675 }
8676 {
8677 NumberFormatTest_Attributes attributes[] = {
8678 {UNUM_SIGN_FIELD, 0, 2},
8679 {UNUM_INTEGER_FIELD, 2, 3},
8680 {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8681 {UNUM_FRACTION_FIELD, 4, 6},
8682 {UNUM_SIGN_FIELD, 6, 7},
8683 {0, -1, 0}};
8684 UnicodeString result;
8685 FieldPositionIterator iter;
8686 fmt.format(2.3, result, &iter, status);
8687 assertEquals("", "++2.30+", result);
8688 verifyFieldPositionIterator(attributes, iter);
8689 }
8690 {
8691 NumberFormatTest_Attributes attributes[] = {
8692 {UNUM_SIGN_FIELD, 0, 1},
8693 {UNUM_INTEGER_FIELD, 2, 3},
8694 {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8695 {UNUM_FRACTION_FIELD, 4, 6},
8696 {UNUM_SIGN_FIELD, 7, 9},
8697 {0, -1, 0}};
8698 UnicodeString result;
8699 FieldPositionIterator iter;
8700 fmt.format(-2.3, result, &iter, status);
8701 assertEquals("", "-(2.30)--", result);
8702 verifyFieldPositionIterator(attributes, iter);
8703 }
8704 }
8705}
8706
8707void NumberFormatTest::Test11640_getAffixes() {
8708 UErrorCode status = U_ZERO_ERROR;
8709 DecimalFormatSymbols symbols("en_US", status);
8710 if (!assertSuccess("", status)) {
8711 return;
8712 }
8713 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8714 pattern = pattern.unescape();
8715 DecimalFormat fmt(pattern, symbols, status);
8716 if (!assertSuccess("", status)) {
8717 return;
8718 }
8719 UnicodeString affixStr;
8720 assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8721 assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8722 assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8723 assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8724}
8725
8726void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
8727 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
8728 pattern = pattern.unescape();
8729 UErrorCode status = U_ZERO_ERROR;
8730 DecimalFormat fmt(pattern, status);
8731 if (!assertSuccess("", status)) {
8732 return;
8733 }
8734 static UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8735 fmt.setCurrency(USD);
8736 UnicodeString appendTo;
8737
8738 assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
8739
8740 UnicodeString topattern;
8741 fmt.toPattern(topattern);
8742 DecimalFormat fmt2(topattern, status);
8743 if (!assertSuccess("", status)) {
8744 return;
8745 }
8746 fmt2.setCurrency(USD);
8747
8748 appendTo.remove();
8749 assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
8750}
8751
8752void NumberFormatTest::Test13327_numberingSystemBufferOverflow() {
8753 UErrorCode status = U_ZERO_ERROR;
8754 for (int runId = 0; runId < 2; runId++) {
8755 // Construct a locale string with a very long "numbers" value.
8756 // The first time, make the value length exactly equal to ULOC_KEYWORDS_CAPACITY.
8757 // The second time, make it exceed ULOC_KEYWORDS_CAPACITY.
8758 int extraLength = (runId == 0) ? 0 : 5;
8759
8760 CharString localeId("en@numbers=", status);
8761 for (int i = 0; i < ULOC_KEYWORDS_CAPACITY + extraLength; i++) {
8762 localeId.append('x', status);
8763 }
8764 assertSuccess("Constructing locale string", status);
8765 Locale locale(localeId.data());
8766
8767 LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(locale, status));
8768 assertFalse("Should not be null", ns.getAlias() == nullptr);
8769 assertSuccess("Should create with no error", status);
8770 }
8771}
8772
8773void NumberFormatTest::Test13391_chakmaParsing() {
8774 UErrorCode status = U_ZERO_ERROR;
8775 LocalPointer<DecimalFormat> df(dynamic_cast<DecimalFormat*>(
8776 NumberFormat::createInstance(Locale("ccp"), status)));
8777 if (df == nullptr) {
8778 dataerrln("%s %d Chakma df is null", __FILE__, __LINE__);
8779 return;
8780 }
8781 const UChar* expected = u"\U00011137\U00011138,\U00011139\U0001113A\U0001113B";
8782 UnicodeString actual;
8783 df->format(12345, actual, status);
8784 assertSuccess("Should not fail when formatting in ccp", status);
8785 assertEquals("Should produce expected output in ccp", expected, actual);
8786
8787 Formattable result;
8788 df->parse(expected, result, status);
8789 assertSuccess("Should not fail when parsing in ccp", status);
8790 assertEquals("Should parse to 12345 in ccp", 12345, result);
8791
8792 const UChar* expectedScientific = u"\U00011137.\U00011139E\U00011138";
8793 UnicodeString actualScientific;
8794 df.adoptInstead(static_cast<DecimalFormat*>(
8795 NumberFormat::createScientificInstance(Locale("ccp"), status)));
8796 df->format(130, actualScientific, status);
8797 assertSuccess("Should not fail when formatting scientific in ccp", status);
8798 assertEquals("Should produce expected scientific output in ccp",
8799 expectedScientific, actualScientific);
8800
8801 Formattable resultScientific;
8802 df->parse(expectedScientific, resultScientific, status);
8803 assertSuccess("Should not fail when parsing scientific in ccp", status);
8804 assertEquals("Should parse scientific to 130 in ccp", 130, resultScientific);
8805}
8806
8807
8808void NumberFormatTest::verifyFieldPositionIterator(
8809 NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
8810 int32_t idx = 0;
8811 FieldPosition fp;
8812 while (iter.next(fp)) {
8813 if (expected[idx].spos == -1) {
8814 errln("Iterator should have ended. got %d", fp.getField());
8815 return;
8816 }
8817 assertEquals("id", expected[idx].id, fp.getField());
8818 assertEquals("start", expected[idx].spos, fp.getBeginIndex());
8819 assertEquals("end", expected[idx].epos, fp.getEndIndex());
8820 ++idx;
8821 }
8822 if (expected[idx].spos != -1) {
8823 errln("Premature end of iterator. expected %d", expected[idx].id);
8824 }
8825}
8826
8827void NumberFormatTest::Test11735_ExceptionIssue() {
8828 IcuTestErrorCode status(*this, "Test11735_ExceptionIssue");
8829 Locale enLocale("en");
8830 DecimalFormatSymbols symbols(enLocale, status);
8831 if (status.isSuccess()) {
8832 DecimalFormat fmt("0", symbols, status);
8833 assertSuccess("Fail: Construct DecimalFormat formatter", status, true, __FILE__, __LINE__);
8834 ParsePosition ppos(0);
8835 fmt.parseCurrency("53.45", ppos); // NPE thrown here in ICU4J.
8836 assertEquals("Issue11735 ppos", 0, ppos.getIndex());
8837 }
8838}
8839
8840void NumberFormatTest::Test11035_FormatCurrencyAmount() {
8841 UErrorCode status = U_ZERO_ERROR;
8842 double amount = 12345.67;
8843 const char16_t* expected = u"12,345$67 ​";
8844
8845 // Test two ways to set a currency via API
8846
8847 Locale loc1 = Locale("pt_PT");
8848 LocalPointer<NumberFormat> fmt1(NumberFormat::createCurrencyInstance(loc1, status),
8849 status);
8850 if (U_FAILURE(status)) {
8851 dataerrln("%s %d NumberFormat instance fmt1 is null", __FILE__, __LINE__);
8852 return;
8853 }
8854 fmt1->setCurrency(u"PTE", status);
8855 assertSuccess("Setting currency on fmt1", status);
8856 UnicodeString actualSetCurrency;
8857 fmt1->format(amount, actualSetCurrency);
8858
8859 Locale loc2 = Locale("pt_PT@currency=PTE");
8860 LocalPointer<NumberFormat> fmt2(NumberFormat::createCurrencyInstance(loc2, status));
8861 assertSuccess("Creating fmt2", status);
8862 UnicodeString actualLocaleString;
8863 fmt2->format(amount, actualLocaleString);
8864
8865 assertEquals("Custom Currency Pattern, Set Currency", expected, actualSetCurrency);
8866 assertEquals("Custom Currency Pattern, Locale String", expected, actualLocaleString);
8867}
8868
8869void NumberFormatTest::Test11318_DoubleConversion() {
8870 IcuTestErrorCode status(*this, "Test11318_DoubleConversion");
8871 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
8872 if (U_FAILURE(status)) {
8873 dataerrln("%s %d Error in NumberFormat instance creation", __FILE__, __LINE__);
8874 return;
8875 }
8876 nf->setMaximumFractionDigits(40);
8877 nf->setMaximumIntegerDigits(40);
8878 UnicodeString appendTo;
8879 nf->format(999999999999999.9, appendTo);
8880 assertEquals("Should render all digits", u"999,999,999,999,999.9", appendTo);
8881}
8882
8883void NumberFormatTest::TestParsePercentRegression() {
8884 IcuTestErrorCode status(*this, "TestParsePercentRegression");
8885 LocalPointer<DecimalFormat> df1((DecimalFormat*) NumberFormat::createInstance("en", status), status);
8886 LocalPointer<DecimalFormat> df2((DecimalFormat*) NumberFormat::createPercentInstance("en", status), status);
8887 if (status.isFailure()) {return; }
Frank Tang1f164ee2022-11-08 12:31:27 -08008888 df1->setLenient(true);
8889 df2->setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08008890
8891 {
8892 ParsePosition ppos;
8893 Formattable result;
8894 df1->parse("50%", result, ppos);
8895 assertEquals("df1 should accept a number but not the percent sign", 2, ppos.getIndex());
8896 assertEquals("df1 should return the number as 50", 50.0, result.getDouble(status));
8897 }
8898 {
8899 ParsePosition ppos;
8900 Formattable result;
8901 df2->parse("50%", result, ppos);
8902 assertEquals("df2 should accept the percent sign", 3, ppos.getIndex());
8903 assertEquals("df2 should return the number as 0.5", 0.5, result.getDouble(status));
8904 }
8905 {
8906 ParsePosition ppos;
8907 Formattable result;
8908 df2->parse("50", result, ppos);
8909 assertEquals("df2 should return the number as 0.5 even though the percent sign is missing",
8910 0.5,
8911 result.getDouble(status));
8912 }
8913}
8914
8915void NumberFormatTest::TestMultiplierWithScale() {
8916 IcuTestErrorCode status(*this, "TestMultiplierWithScale");
8917
8918 // Test magnitude combined with multiplier, as shown in API docs
8919 DecimalFormat df("0", {"en", status}, status);
8920 if (status.isSuccess()) {
8921 df.setMultiplier(5);
8922 df.setMultiplierScale(-1);
8923 expect2(df, 100, u"50"); // round-trip test
8924 }
8925}
8926
8927void NumberFormatTest::TestFastFormatInt32() {
8928 IcuTestErrorCode status(*this, "TestFastFormatInt32");
8929
8930 // The two simplest formatters, old API and new API.
8931 // Old API should use the fastpath for ints.
8932 LocalizedNumberFormatter lnf = NumberFormatter::withLocale("en");
8933 LocalPointer<NumberFormat> df(NumberFormat::createInstance("en", status), status);
8934 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8935
8936 double nums[] = {
8937 0.0,
8938 -0.0,
8939 NAN,
8940 INFINITY,
8941 0.1,
8942 1.0,
8943 1.1,
8944 2.0,
8945 3.0,
8946 9.0,
8947 10.0,
8948 99.0,
8949 100.0,
8950 999.0,
8951 1000.0,
8952 9999.0,
8953 10000.0,
8954 99999.0,
8955 100000.0,
8956 999999.0,
8957 1000000.0,
8958 static_cast<double>(INT32_MAX) - 1,
8959 static_cast<double>(INT32_MAX),
8960 static_cast<double>(INT32_MAX) + 1,
8961 static_cast<double>(INT32_MIN) - 1,
8962 static_cast<double>(INT32_MIN),
8963 static_cast<double>(INT32_MIN) + 1};
8964
8965 for (auto num : nums) {
8966 UnicodeString expected = lnf.formatDouble(num, status).toString(status);
8967 UnicodeString actual;
8968 df->format(num, actual);
8969 assertEquals(UnicodeString("d = ") + num, expected, actual);
8970 }
8971}
8972
8973void NumberFormatTest::Test11646_Equality() {
8974 UErrorCode status = U_ZERO_ERROR;
8975 DecimalFormatSymbols symbols(Locale::getEnglish(), status);
8976 UnicodeString pattern(u"\u00a4\u00a4\u00a4 0.00 %\u00a4\u00a4");
8977 DecimalFormat fmt(pattern, symbols, status);
8978 if (!assertSuccess("", status)) return;
8979
8980 // Test equality with affixes. set affix methods can't capture special
8981 // characters which is why equality should fail.
8982 {
8983 DecimalFormat fmtCopy(fmt);
8984 assertTrue("", fmt == fmtCopy);
8985 UnicodeString positivePrefix;
8986 fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(positivePrefix));
8987 assertFalse("", fmt == fmtCopy);
8988 }
8989 {
8990 DecimalFormat fmtCopy = DecimalFormat(fmt);
8991 assertTrue("", fmt == fmtCopy);
8992 UnicodeString positivePrefix;
8993 fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(positivePrefix));
8994 assertFalse("", fmt == fmtCopy);
8995 }
8996 {
8997 DecimalFormat fmtCopy(fmt);
8998 assertTrue("", fmt == fmtCopy);
8999 UnicodeString negativePrefix;
9000 fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(negativePrefix));
9001 assertFalse("", fmt == fmtCopy);
9002 }
9003 {
9004 DecimalFormat fmtCopy(fmt);
9005 assertTrue("", fmt == fmtCopy);
9006 UnicodeString negativePrefix;
9007 fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(negativePrefix));
9008 assertFalse("", fmt == fmtCopy);
9009 }
9010}
9011
9012void NumberFormatTest::TestParseNaN() {
9013 IcuTestErrorCode status(*this, "TestParseNaN");
9014
9015 DecimalFormat df("0", { "en", status }, status);
9016 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9017 Formattable parseResult;
9018 df.parse(u"NaN", parseResult, status);
9019 assertEquals("NaN should parse successfully", NAN, parseResult.getDouble());
9020 assertFalse("Result NaN should be positive", std::signbit(parseResult.getDouble()));
9021 UnicodeString formatResult;
9022 df.format(parseResult.getDouble(), formatResult);
9023 assertEquals("NaN should round-trip", u"NaN", formatResult);
9024}
9025
9026void NumberFormatTest::TestFormatFailIfMoreThanMaxDigits() {
9027 IcuTestErrorCode status(*this, "TestFormatFailIfMoreThanMaxDigits");
9028
9029 DecimalFormat df("0", {"en-US", status}, status);
9030 if (status.errDataIfFailureAndReset()) {
9031 return;
9032 }
Frank Tang1f164ee2022-11-08 12:31:27 -08009033 assertEquals("Coverage for getter 1", (UBool) false, df.isFormatFailIfMoreThanMaxDigits());
9034 df.setFormatFailIfMoreThanMaxDigits(true);
9035 assertEquals("Coverage for getter 2", (UBool) true, df.isFormatFailIfMoreThanMaxDigits());
Frank Tang3e05d9d2021-11-08 14:04:04 -08009036 df.setMaximumIntegerDigits(2);
9037 UnicodeString result;
9038 df.format(1234, result, status);
9039 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
9040}
9041
9042void NumberFormatTest::TestParseCaseSensitive() {
9043 IcuTestErrorCode status(*this, "TestParseCaseSensitive");
9044
9045 DecimalFormat df(u"0", {"en-US", status}, status);
9046 if (status.errDataIfFailureAndReset()) {
9047 return;
9048 }
Frank Tang1f164ee2022-11-08 12:31:27 -08009049 assertEquals("Coverage for getter 1", (UBool) false, df.isParseCaseSensitive());
9050 df.setParseCaseSensitive(true);
9051 assertEquals("Coverage for getter 1", (UBool) true, df.isParseCaseSensitive());
Frank Tang3e05d9d2021-11-08 14:04:04 -08009052 Formattable result;
9053 ParsePosition ppos;
9054 df.parse(u"1e2", result, ppos);
9055 assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9056 assertEquals("Result should be 1", 1.0, result.getDouble(status));
9057}
9058
9059void NumberFormatTest::TestParseNoExponent() {
9060 IcuTestErrorCode status(*this, "TestParseNoExponent");
9061
9062 DecimalFormat df(u"0", {"en-US", status}, status);
9063 if (status.errDataIfFailureAndReset()) {
9064 return;
9065 }
Frank Tang1f164ee2022-11-08 12:31:27 -08009066 assertEquals("Coverage for getter 1", (UBool) false, df.isParseNoExponent());
9067 df.setParseNoExponent(true);
9068 assertEquals("Coverage for getter 1", (UBool) true, df.isParseNoExponent());
Frank Tang3e05d9d2021-11-08 14:04:04 -08009069 Formattable result;
9070 ParsePosition ppos;
9071 df.parse(u"1E2", result, ppos);
9072 assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9073 assertEquals("Result should be 1", 1.0, result.getDouble(status));
9074}
9075
9076void NumberFormatTest::TestSignAlwaysShown() {
9077 IcuTestErrorCode status(*this, "TestSignAlwaysShown");
9078
9079 DecimalFormat df(u"0", {"en-US", status}, status);
9080 if (status.errDataIfFailureAndReset()) {
9081 return;
9082 }
Frank Tang1f164ee2022-11-08 12:31:27 -08009083 assertEquals("Coverage for getter 1", (UBool) false, df.isSignAlwaysShown());
9084 df.setSignAlwaysShown(true);
9085 assertEquals("Coverage for getter 1", (UBool) true, df.isSignAlwaysShown());
Frank Tang3e05d9d2021-11-08 14:04:04 -08009086 UnicodeString result;
9087 df.format(1234, result, status);
9088 status.errIfFailureAndReset();
9089 assertEquals("Should show sign on positive number", u"+1234", result);
9090}
9091
9092void NumberFormatTest::TestMinimumGroupingDigits() {
9093 IcuTestErrorCode status(*this, "TestMinimumGroupingDigits");
9094
9095 DecimalFormat df(u"#,##0", {"en-US", status}, status);
9096 if (status.errDataIfFailureAndReset()) {
9097 return;
9098 }
9099 assertEquals("Coverage for getter 1", -1, df.getMinimumGroupingDigits());
9100 df.setMinimumGroupingDigits(2);
9101 assertEquals("Coverage for getter 1", 2, df.getMinimumGroupingDigits());
9102 UnicodeString result;
9103 df.format(1234, result, status);
9104 status.errIfFailureAndReset();
9105 assertEquals("Should not have grouping", u"1234", result);
9106 df.format(12345, result.remove(), status);
9107 status.errIfFailureAndReset();
9108 assertEquals("Should have grouping", u"12,345", result);
9109
9110
9111 // Test special values -1, UNUM_MINIMUM_GROUPING_DIGITS_AUTO and
9112 // UNUM_MINIMUM_GROUPING_DIGITS_MIN2
9113 struct TestCase {
9114 const char* locale;
9115 int32_t minGroup;
9116 double input;
9117 const char16_t* expected;
9118 } cases[] = {
9119 { "en-US", 1, 1000, u"1,000" },
9120 { "en-US", 1, 10000, u"10,000" },
9121 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1,000" },
9122 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10,000" },
9123 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9124 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10,000" },
9125
9126 { "es", 1, 1000, u"1.000" },
9127 { "es", 1, 10000, u"10.000" },
9128 { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1000" },
9129 { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10.000" },
9130 { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9131 { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10.000" },
9132 };
9133 for (const auto& cas : cases) {
9134 UnicodeString message = UnicodeString(cas.locale)
9135 + u" " + Int64ToUnicodeString(cas.minGroup)
9136 + u" " + DoubleToUnicodeString(cas.input);
9137 status.setScope(message);
9138 DecimalFormat df(u"#,##0", {cas.locale, status}, status);
9139 if (status.errIfFailureAndReset()) { continue; }
9140 df.setMinimumGroupingDigits(cas.minGroup);
9141 UnicodeString actual;
9142 df.format(cas.input, actual, status);
9143 if (status.errIfFailureAndReset()) { continue; }
9144 assertEquals(message, cas.expected, actual);
9145 }
9146}
9147
9148void NumberFormatTest::Test11897_LocalizedPatternSeparator() {
9149 IcuTestErrorCode status(*this, "Test11897_LocalizedPatternSeparator");
9150
9151 // In a locale with a different <list> symbol, like arabic,
9152 // kPatternSeparatorSymbol should still be ';'
9153 {
9154 DecimalFormatSymbols dfs("ar", status);
9155 assertEquals("pattern separator symbol should be ;",
9156 u";",
9157 dfs.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
9158 }
9159
9160 // However, the custom symbol should be used in localized notation
9161 // when set manually via API
9162 {
9163 DecimalFormatSymbols dfs("en", status);
Frank Tang1f164ee2022-11-08 12:31:27 -08009164 dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u"!", false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08009165 DecimalFormat df(u"0", dfs, status);
9166 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9167 df.applyPattern("a0;b0", status); // should not throw
9168 UnicodeString result;
9169 assertEquals("should apply the normal pattern",
9170 df.getNegativePrefix(result.remove()),
9171 "b");
9172 df.applyLocalizedPattern(u"c0!d0", status); // should not throw
9173 assertEquals("should apply the localized pattern",
9174 df.getNegativePrefix(result.remove()),
9175 "d");
9176 }
9177}
9178
9179void NumberFormatTest::Test13055_PercentageRounding() {
9180 IcuTestErrorCode status(*this, "PercentageRounding");
9181 UnicodeString actual;
9182 LocalPointer<NumberFormat>pFormat(NumberFormat::createPercentInstance("en_US", status));
9183 if (U_FAILURE(status)) {
9184 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9185 return;
9186 }
9187 pFormat->setMaximumFractionDigits(0);
9188 pFormat->setRoundingMode(DecimalFormat::kRoundHalfEven);
9189 pFormat->format(2.155, actual);
9190 assertEquals("Should round percent toward even number", "216%", actual);
9191}
9192
9193void NumberFormatTest::Test11839() {
9194 IcuTestErrorCode errorCode(*this, "Test11839");
9195 // Ticket #11839: DecimalFormat does not respect custom plus sign
9196 LocalPointer<DecimalFormatSymbols> dfs(new DecimalFormatSymbols(Locale::getEnglish(), errorCode), errorCode);
9197 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9198 dfs->setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"a∸");
9199 dfs->setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"b∔"); // ∔ U+2214 DOT PLUS
9200 DecimalFormat df(u"0.00+;0.00-", dfs.orphan(), errorCode);
9201 UnicodeString result;
9202 df.format(-1.234, result, errorCode);
9203 assertEquals("Locale-specific minus sign should be used", u"1.23a∸", result);
9204 df.format(1.234, result.remove(), errorCode);
9205 assertEquals("Locale-specific plus sign should be used", u"1.23b∔", result);
9206 // Test round-trip with parse
9207 expect2(df, -456, u"456.00a∸");
9208 expect2(df, 456, u"456.00b∔");
9209}
9210
9211void NumberFormatTest::Test10354() {
9212 IcuTestErrorCode errorCode(*this, "Test10354");
9213 // Ticket #10354: invalid FieldPositionIterator when formatting with empty NaN
9214 DecimalFormatSymbols dfs(errorCode);
9215 UnicodeString empty;
9216 dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, empty);
9217 DecimalFormat df(errorCode);
9218 df.setDecimalFormatSymbols(dfs);
9219 UnicodeString result;
9220 FieldPositionIterator positions;
9221 df.format(NAN, result, &positions, errorCode);
9222 errorCode.errIfFailureAndReset("DecimalFormat.format(NAN, FieldPositionIterator) failed");
9223 FieldPosition fp;
9224 while (positions.next(fp)) {
9225 // Should not loop forever
9226 }
9227}
9228
9229void NumberFormatTest::Test11645_ApplyPatternEquality() {
9230 IcuTestErrorCode status(*this, "Test11645_ApplyPatternEquality");
9231 const char16_t* pattern = u"#,##0.0#";
9232 LocalPointer<DecimalFormat> fmt((DecimalFormat*) NumberFormat::createInstance(status), status);
9233 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9234 fmt->applyPattern(pattern, status);
9235 LocalPointer<DecimalFormat> fmtCopy;
9236
9237 static const int32_t newMultiplier = 37;
9238 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9239 assertFalse("Value before setter", fmtCopy->getMultiplier() == newMultiplier);
9240 fmtCopy->setMultiplier(newMultiplier);
9241 assertEquals("Value after setter", fmtCopy->getMultiplier(), newMultiplier);
9242 fmtCopy->applyPattern(pattern, status);
9243 assertEquals("Value after applyPattern", fmtCopy->getMultiplier(), newMultiplier);
9244 assertFalse("multiplier", *fmt == *fmtCopy);
9245
9246 static const NumberFormat::ERoundingMode newRoundingMode = NumberFormat::ERoundingMode::kRoundCeiling;
9247 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9248 assertFalse("Value before setter", fmtCopy->getRoundingMode() == newRoundingMode);
9249 fmtCopy->setRoundingMode(newRoundingMode);
9250 assertEquals("Value after setter", fmtCopy->getRoundingMode(), newRoundingMode);
9251 fmtCopy->applyPattern(pattern, status);
9252 assertEquals("Value after applyPattern", fmtCopy->getRoundingMode(), newRoundingMode);
9253 assertFalse("roundingMode", *fmt == *fmtCopy);
9254
9255 static const char16_t *const newCurrency = u"EAT";
9256 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9257 assertFalse("Value before setter", fmtCopy->getCurrency() == newCurrency);
9258 fmtCopy->setCurrency(newCurrency);
9259 assertEquals("Value after setter", fmtCopy->getCurrency(), newCurrency);
9260 fmtCopy->applyPattern(pattern, status);
9261 assertEquals("Value after applyPattern", fmtCopy->getCurrency(), newCurrency);
9262 assertFalse("currency", *fmt == *fmtCopy);
9263
9264 static const UCurrencyUsage newCurrencyUsage = UCurrencyUsage::UCURR_USAGE_CASH;
9265 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9266 assertFalse("Value before setter", fmtCopy->getCurrencyUsage() == newCurrencyUsage);
9267 fmtCopy->setCurrencyUsage(newCurrencyUsage, status);
9268 assertEquals("Value after setter", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9269 fmtCopy->applyPattern(pattern, status);
9270 assertEquals("Value after applyPattern", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9271 assertFalse("currencyUsage", *fmt == *fmtCopy);
9272}
9273
9274void NumberFormatTest::Test12567() {
9275 IcuTestErrorCode errorCode(*this, "Test12567");
9276 // Ticket #12567: DecimalFormat.equals() may not be symmetric
9277 LocalPointer<DecimalFormat> df1((DecimalFormat *)
9278 NumberFormat::createInstance(Locale::getUS(), UNUM_CURRENCY, errorCode));
9279 LocalPointer<DecimalFormat> df2((DecimalFormat *)
9280 NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, errorCode));
9281 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9282 // NOTE: CurrencyPluralInfo equality not tested in C++ because its operator== is not defined.
9283 df1->applyPattern(u"0.00", errorCode);
9284 df2->applyPattern(u"0.00", errorCode);
9285 assertTrue("df1 == df2", *df1 == *df2);
9286 assertTrue("df2 == df1", *df2 == *df1);
9287 df2->setPositivePrefix(u"abc");
9288 assertTrue("df1 != df2", *df1 != *df2);
9289 assertTrue("df2 != df1", *df2 != *df1);
9290}
9291
9292void NumberFormatTest::Test11626_CustomizeCurrencyPluralInfo() {
9293 IcuTestErrorCode errorCode(*this, "Test11626_CustomizeCurrencyPluralInfo");
9294 // Ticket #11626: No unit test demonstrating how to use CurrencyPluralInfo to
9295 // change formatting spelled out currencies
9296 // Use locale sr because it has interesting plural rules.
9297 Locale locale("sr");
9298 LocalPointer<DecimalFormatSymbols> symbols(new DecimalFormatSymbols(locale, errorCode), errorCode);
9299 CurrencyPluralInfo info(locale, errorCode);
9300 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9301 info.setCurrencyPluralPattern(u"one", u"0 qwerty", errorCode);
9302 info.setCurrencyPluralPattern(u"few", u"0 dvorak", errorCode);
9303 DecimalFormat df(u"#", symbols.orphan(), UNUM_CURRENCY_PLURAL, errorCode);
9304 df.setCurrencyPluralInfo(info);
9305 df.setCurrency(u"USD");
9306 df.setMaximumFractionDigits(0);
9307
9308 UnicodeString result;
9309 assertEquals("Plural one", u"1 qwerty", df.format(1, result, errorCode));
9310 assertEquals("Plural few", u"3 dvorak", df.format(3, result.remove(), errorCode));
9311 assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9312
9313 info.setPluralRules(u"few: n is 1; one: n in 2..4", errorCode);
9314 df.setCurrencyPluralInfo(info);
9315 assertEquals("Plural one", u"1 dvorak", df.format(1, result.remove(), errorCode));
9316 assertEquals("Plural few", u"3 qwerty", df.format(3, result.remove(), errorCode));
9317 assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9318}
9319
9320void NumberFormatTest::Test20073_StrictPercentParseErrorIndex() {
9321 IcuTestErrorCode status(*this, "Test20073_StrictPercentParseErrorIndex");
9322 ParsePosition parsePosition(0);
9323 DecimalFormat df(u"0%", {"en-us", status}, status);
9324 if (U_FAILURE(status)) {
9325 dataerrln("Unable to create DecimalFormat instance.");
9326 return;
9327 }
Frank Tang1f164ee2022-11-08 12:31:27 -08009328 df.setLenient(false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08009329 Formattable result;
9330 df.parse(u"%2%", result, parsePosition);
9331 assertEquals("", 0, parsePosition.getIndex());
9332 assertEquals("", 0, parsePosition.getErrorIndex());
9333}
9334
9335void NumberFormatTest::Test13056_GroupingSize() {
9336 UErrorCode status = U_ZERO_ERROR;
9337 DecimalFormat df(u"#,##0", status);
9338 if (!assertSuccess("", status)) return;
9339 assertEquals("Primary grouping should return 3", 3, df.getGroupingSize());
9340 assertEquals("Secondary grouping should return 0", 0, df.getSecondaryGroupingSize());
9341 df.setSecondaryGroupingSize(3);
9342 assertEquals("Primary grouping should still return 3", 3, df.getGroupingSize());
9343 assertEquals("Secondary grouping should round-trip", 3, df.getSecondaryGroupingSize());
9344 df.setGroupingSize(4);
9345 assertEquals("Primary grouping should return 4", 4, df.getGroupingSize());
9346 assertEquals("Secondary should remember explicit setting and return 3", 3, df.getSecondaryGroupingSize());
9347}
9348
9349
9350void NumberFormatTest::Test11025_CurrencyPadding() {
9351 UErrorCode status = U_ZERO_ERROR;
9352 UnicodeString pattern(u"¤¤ **####0.00");
9353 DecimalFormatSymbols sym(Locale::getFrance(), status);
9354 if (!assertSuccess("", status)) return;
9355 DecimalFormat fmt(pattern, sym, status);
9356 if (!assertSuccess("", status)) return;
9357 UnicodeString result;
9358 fmt.format(433.0, result);
9359 assertEquals("Number should be padded to 11 characters", "EUR *433,00", result);
9360}
9361
9362void NumberFormatTest::Test11648_ExpDecFormatMalPattern() {
9363 UErrorCode status = U_ZERO_ERROR;
9364
9365 DecimalFormat fmt("0.00", {"en", status}, status);
9366 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
Frank Tang1f164ee2022-11-08 12:31:27 -08009367 fmt.setScientificNotation(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -08009368 UnicodeString pattern;
9369
9370 assertEquals("A valid scientific notation pattern should be produced",
9371 "0.00E0",
9372 fmt.toPattern(pattern));
9373
9374 DecimalFormat fmt2(pattern, status);
9375 assertSuccess("", status);
9376}
9377
9378void NumberFormatTest::Test11649_DecFmtCurrencies() {
9379 IcuTestErrorCode status(*this, "Test11649_DecFmtCurrencies");
9380 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
9381 pattern = pattern.unescape();
9382 DecimalFormat fmt(pattern, status);
9383 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9384 static const UChar USD[] = u"USD";
9385 fmt.setCurrency(USD);
9386 UnicodeString appendTo;
9387
9388 assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
9389 UnicodeString topattern;
9390
9391 assertEquals("", pattern, fmt.toPattern(topattern));
9392 DecimalFormat fmt2(topattern, status);
9393 fmt2.setCurrency(USD);
9394
9395 appendTo.remove();
9396 assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
9397}
9398
9399void NumberFormatTest::Test13148_ParseGroupingSeparators() {
9400 IcuTestErrorCode status(*this, "Test13148");
9401 LocalPointer<DecimalFormat> fmt(
9402 (DecimalFormat*)NumberFormat::createInstance("en-ZA", status), status);
9403 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9404
9405 DecimalFormatSymbols symbols = *fmt->getDecimalFormatSymbols();
9406
9407 symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'.');
9408 symbols.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u',');
9409 fmt->setDecimalFormatSymbols(symbols);
9410 Formattable number;
9411 fmt->parse(u"300,000", number, status);
9412 assertEquals("Should parse as 300000", 300000LL, number.getInt64(status));
9413}
9414
9415void NumberFormatTest::Test12753_PatternDecimalPoint() {
9416 UErrorCode status = U_ZERO_ERROR;
9417 DecimalFormatSymbols symbols(Locale::getUS(), status);
9418 symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"*", false);
9419 DecimalFormat df(u"0.00", symbols, status);
9420 if (!assertSuccess("", status)) return;
9421 df.setDecimalPatternMatchRequired(true);
9422 Formattable result;
9423 df.parse(u"123",result, status);
9424 assertEquals("Parsing integer succeeded even though setDecimalPatternMatchRequired was set",
9425 U_INVALID_FORMAT_ERROR, status);
9426 }
9427
9428 void NumberFormatTest::Test11647_PatternCurrencySymbols() {
9429 UErrorCode status = U_ZERO_ERROR;
9430 DecimalFormat df(status);
9431 df.applyPattern(u"¤¤¤¤#", status);
9432 if (!assertSuccess("", status)) return;
9433 UnicodeString actual;
9434 df.format(123, actual);
9435 assertEquals("Should replace 4 currency signs with U+FFFD", u"\uFFFD123", actual);
9436}
9437
9438void NumberFormatTest::Test11913_BigDecimal() {
9439 UErrorCode status = U_ZERO_ERROR;
9440 LocalPointer<NumberFormat> df(NumberFormat::createInstance(Locale::getEnglish(), status), status);
9441 if (!assertSuccess("", status)) return;
9442 UnicodeString result;
9443 df->format(StringPiece("1.23456789E400"), result, nullptr, status);
9444 assertSuccess("", status);
9445 assertEquals("Should format more than 309 digits", u"12,345,678", UnicodeString(result, 0, 10));
9446 assertEquals("Should format more than 309 digits", 534, result.length());
9447}
9448
9449void NumberFormatTest::Test11020_RoundingInScientificNotation() {
9450 UErrorCode status = U_ZERO_ERROR;
9451 DecimalFormatSymbols sym(Locale::getFrance(), status);
9452 DecimalFormat fmt(u"0.05E0", sym, status);
9453 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9454 assertSuccess("", status);
9455 UnicodeString result;
9456 fmt.format(12301.2, result);
9457 assertEquals("Rounding increment should be applied after magnitude scaling", u"1,25E4", result);
9458}
9459
9460void NumberFormatTest::Test11640_TripleCurrencySymbol() {
9461 IcuTestErrorCode status(*this, "Test11640_TripleCurrencySymbol");
9462 UnicodeString actual;
9463 DecimalFormat dFormat(u"¤¤¤ 0", status);
9464 if (U_FAILURE(status)) {
9465 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9466 return;
9467 }
9468 dFormat.setCurrency(u"USD");
9469 UnicodeString result;
9470 dFormat.getPositivePrefix(result);
9471 assertEquals("Triple-currency should give long name on getPositivePrefix",
9472 "US dollars ", result);
9473}
9474
9475
9476void NumberFormatTest::Test13763_FieldPositionIteratorOffset() {
9477 IcuTestErrorCode status(*this, "Test13763_FieldPositionIteratorOffset");
9478 FieldPositionIterator fpi;
9479 UnicodeString result(u"foo\U0001F4FBbar"); // 8 code units
9480 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9481 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9482 nf->format(5142.3, result, &fpi, status);
9483
9484 int32_t expected[] = {
9485 UNUM_GROUPING_SEPARATOR_FIELD, 9, 10,
9486 UNUM_INTEGER_FIELD, 8, 13,
9487 UNUM_DECIMAL_SEPARATOR_FIELD, 13, 14,
9488 UNUM_FRACTION_FIELD, 14, 15,
9489 };
9490 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
9491 expectPositions(fpi, expected, tupleCount, result);
9492}
9493
9494void NumberFormatTest::Test13777_ParseLongNameNonCurrencyMode() {
9495 IcuTestErrorCode status(*this, "Test13777_ParseLongNameNonCurrencyMode");
9496
9497 LocalPointer<NumberFormat> df(
9498 NumberFormat::createInstance("en-us", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9499 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9500 expect2(*df, 1.5, u"1.50 US dollars");
9501}
9502
9503void NumberFormatTest::Test13804_EmptyStringsWhenParsing() {
9504 IcuTestErrorCode status(*this, "Test13804_EmptyStringsWhenParsing");
9505
9506 DecimalFormatSymbols dfs("en", status);
9507 if (status.errIfFailureAndReset()) {
9508 return;
9509 }
Frank Tang1f164ee2022-11-08 12:31:27 -08009510 dfs.setSymbol(DecimalFormatSymbols::kCurrencySymbol, u"", false);
9511 dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"", false);
9512 dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u"", false);
9513 dfs.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, u"", false);
9514 dfs.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, u"", false);
9515 dfs.setSymbol(DecimalFormatSymbols::kThreeDigitSymbol, u"", false);
9516 dfs.setSymbol(DecimalFormatSymbols::kFourDigitSymbol, u"", false);
9517 dfs.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, u"", false);
9518 dfs.setSymbol(DecimalFormatSymbols::kSixDigitSymbol, u"", false);
9519 dfs.setSymbol(DecimalFormatSymbols::kSevenDigitSymbol, u"", false);
9520 dfs.setSymbol(DecimalFormatSymbols::kEightDigitSymbol, u"", false);
9521 dfs.setSymbol(DecimalFormatSymbols::kNineDigitSymbol, u"", false);
9522 dfs.setSymbol(DecimalFormatSymbols::kExponentMultiplicationSymbol, u"", false);
9523 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"", false);
9524 dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u"", false);
9525 dfs.setSymbol(DecimalFormatSymbols::kInfinitySymbol, u"", false);
9526 dfs.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, u"", false);
9527 dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"", false);
9528 dfs.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, u"", false);
9529 dfs.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, u"", false);
9530 dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, u"", false);
9531 dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, false, u"");
9532 dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, true, u"");
9533 dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u"", false);
9534 dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u"", false);
9535 dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"", false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08009536
9537 DecimalFormat df("0", dfs, status);
9538 if (status.errIfFailureAndReset()) {
9539 return;
9540 }
Frank Tang1f164ee2022-11-08 12:31:27 -08009541 df.setGroupingUsed(true);
9542 df.setScientificNotation(true);
9543 df.setLenient(true); // enable all matchers
Frank Tang3e05d9d2021-11-08 14:04:04 -08009544 {
9545 UnicodeString result;
9546 df.format(0, result); // should not crash or hit infinite loop
9547 }
9548 const char16_t* samples[] = {
9549 u"",
9550 u"123",
9551 u"$123",
9552 u"-",
9553 u"+",
9554 u"44%",
9555 u"1E+2.3"
9556 };
9557 for (auto& sample : samples) {
9558 logln(UnicodeString(u"Attempting parse on: ") + sample);
9559 status.setScope(sample);
9560 // We don't care about the results, only that we don't crash and don't loop.
9561 Formattable result;
9562 ParsePosition ppos(0);
9563 df.parse(sample, result, ppos);
9564 ppos = ParsePosition(0);
9565 LocalPointer<CurrencyAmount> curramt(df.parseCurrency(sample, ppos));
9566 status.errIfFailureAndReset();
9567 }
9568
9569 // Test with a nonempty exponent separator symbol to cover more code
Frank Tang1f164ee2022-11-08 12:31:27 -08009570 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"E", false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08009571 df.setDecimalFormatSymbols(dfs);
9572 {
9573 Formattable result;
9574 ParsePosition ppos(0);
9575 df.parse(u"1E+2.3", result, ppos);
9576 }
9577}
9578
9579void NumberFormatTest::Test20037_ScientificIntegerOverflow() {
9580 IcuTestErrorCode status(*this, "Test20037_ScientificIntegerOverflow");
9581
9582 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(status));
9583 if (U_FAILURE(status)) {
9584 dataerrln("Unable to create NumberFormat instance.");
9585 return;
9586 }
9587 Formattable result;
9588
9589 // Test overflow of exponent
9590 nf->parse(u"1E-2147483648", result, status);
9591 StringPiece sp = result.getDecimalNumber(status);
9592 assertEquals(u"Should snap to zero",
9593 u"0",
9594 {sp.data(), sp.length(), US_INV});
9595
9596 // Test edge case overflow of exponent
9597 result = Formattable();
9598 nf->parse(u"1E-2147483647E-1", result, status);
9599 sp = result.getDecimalNumber(status);
9600 assertEquals(u"Should not overflow and should parse only the first exponent",
9601 u"1E-2147483647",
9602 {sp.data(), sp.length(), US_INV});
9603
9604 // Test edge case overflow of exponent
9605 result = Formattable();
9606 nf->parse(u".0003e-2147483644", result, status);
9607 sp = result.getDecimalNumber(status);
9608 assertEquals(u"Should not overflow",
9609 u"3E-2147483648",
9610 {sp.data(), sp.length(), US_INV});
9611
9612 // Test largest parseable exponent
9613 result = Formattable();
9614 nf->parse(u"9876e2147483643", result, status);
9615 sp = result.getDecimalNumber(status);
9616 assertEquals(u"Should not overflow",
9617 u"9.876E+2147483646",
9618 {sp.data(), sp.length(), US_INV});
9619
9620 // Test max value as well
9621 const char16_t* infinityInputs[] = {
9622 u"9876e2147483644",
9623 u"9876e2147483645",
9624 u"9876e2147483646",
9625 u"9876e2147483647",
9626 u"9876e2147483648",
9627 u"9876e2147483649",
9628 };
9629 for (const auto& input : infinityInputs) {
9630 result = Formattable();
9631 nf->parse(input, result, status);
9632 sp = result.getDecimalNumber(status);
9633 assertEquals(UnicodeString("Should become Infinity: ") + input,
9634 u"Infinity",
9635 {sp.data(), sp.length(), US_INV});
9636 }
9637}
9638
9639void NumberFormatTest::Test13840_ParseLongStringCrash() {
9640 IcuTestErrorCode status(*this, "Test13840_ParseLongStringCrash");
9641
9642 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9643 if (status.errIfFailureAndReset()) { return; }
9644
9645 Formattable result;
9646 static const char16_t* bigString =
9647 u"111111111111111111111111111111111111111111111111111111111111111111111"
9648 u"111111111111111111111111111111111111111111111111111111111111111111111"
9649 u"111111111111111111111111111111111111111111111111111111111111111111111"
9650 u"111111111111111111111111111111111111111111111111111111111111111111111"
9651 u"111111111111111111111111111111111111111111111111111111111111111111111"
9652 u"111111111111111111111111111111111111111111111111111111111111111111111";
9653 nf->parse(bigString, result, status);
9654
9655 // Normalize the input string:
9656 CharString expectedChars;
9657 expectedChars.appendInvariantChars(bigString, status);
9658 DecimalQuantity expectedDQ;
9659 expectedDQ.setToDecNumber(expectedChars.toStringPiece(), status);
9660 UnicodeString expectedUString = expectedDQ.toScientificString();
9661
9662 // Get the output string:
9663 StringPiece actualChars = result.getDecimalNumber(status);
9664 UnicodeString actualUString = UnicodeString(actualChars.data(), actualChars.length(), US_INV);
9665
9666 assertEquals("Should round-trip without crashing", expectedUString, actualUString);
9667}
9668
9669void NumberFormatTest::Test13850_EmptyStringCurrency() {
9670 IcuTestErrorCode status(*this, "Test13840_EmptyStringCurrency");
9671
9672 struct TestCase {
9673 const char16_t* currencyArg;
9674 UErrorCode expectedError;
9675 } cases[] = {
9676 {u"", U_USING_FALLBACK_WARNING},
9677 {u"U", U_ILLEGAL_ARGUMENT_ERROR},
9678 {u"Us", U_ILLEGAL_ARGUMENT_ERROR},
9679 {nullptr, U_USING_FALLBACK_WARNING},
9680 {u"U$D", U_INVARIANT_CONVERSION_ERROR},
9681 {u"Xxx", U_USING_FALLBACK_WARNING}
9682 };
9683 for (const auto& cas : cases) {
9684 UnicodeString message(u"with currency arg: ");
9685 if (cas.currencyArg == nullptr) {
9686 message += u"nullptr";
9687 } else {
9688 message += UnicodeString(cas.currencyArg);
9689 }
9690 status.setScope(message);
9691 LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-US", status), status);
9692 if (status.errIfFailureAndReset()) { return; }
9693 UnicodeString actual;
9694 nf->format(1, actual, status);
9695 status.errIfFailureAndReset();
9696 assertEquals(u"Should format with US currency " + message, u"$1.00", actual);
9697 nf->setCurrency(cas.currencyArg, status);
9698 if (status.expectErrorAndReset(cas.expectedError)) {
9699 // If an error occurred, do not check formatting.
9700 continue;
9701 }
9702 nf->format(1, actual.remove(), status);
9703 assertEquals(u"Should unset the currency " + message, u"\u00A41.00", actual);
9704 status.errIfFailureAndReset();
9705 }
9706}
9707
9708void NumberFormatTest::Test20348_CurrencyPrefixOverride() {
9709 IcuTestErrorCode status(*this, "Test20348_CurrencyPrefixOverride");
9710 LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9711 NumberFormat::createCurrencyInstance("en", status)));
9712 if (status.errIfFailureAndReset()) { return; }
9713 UnicodeString result;
9714 assertEquals("Initial pattern",
9715 u"¤#,##0.00", fmt->toPattern(result.remove()));
9716 assertEquals("Initial prefix",
9717 u"¤", fmt->getPositivePrefix(result.remove()));
9718 assertEquals("Initial suffix",
9719 u"-¤", fmt->getNegativePrefix(result.remove()));
9720 assertEquals("Initial format",
9721 u"\u00A4100.00", fmt->format(100, result.remove(), NULL, status));
9722
9723 fmt->setPositivePrefix(u"$");
9724 assertEquals("Set positive prefix pattern",
9725 u"$#,##0.00;-\u00A4#,##0.00", fmt->toPattern(result.remove()));
9726 assertEquals("Set positive prefix prefix",
9727 u"$", fmt->getPositivePrefix(result.remove()));
9728 assertEquals("Set positive prefix suffix",
9729 u"-¤", fmt->getNegativePrefix(result.remove()));
9730 assertEquals("Set positive prefix format",
9731 u"$100.00", fmt->format(100, result.remove(), NULL, status));
9732
9733 fmt->setNegativePrefix(u"-$");
9734 assertEquals("Set negative prefix pattern",
9735 u"$#,##0.00;'-'$#,##0.00", fmt->toPattern(result.remove()));
9736 assertEquals("Set negative prefix prefix",
9737 u"$", fmt->getPositivePrefix(result.remove()));
9738 assertEquals("Set negative prefix suffix",
9739 u"-$", fmt->getNegativePrefix(result.remove()));
9740 assertEquals("Set negative prefix format",
9741 u"$100.00", fmt->format(100, result.remove(), NULL, status));
9742}
9743
9744void NumberFormatTest::Test20956_MonetarySymbolGetters() {
9745 IcuTestErrorCode status(*this, "Test20956_MonetarySymbolGetters");
9746 LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9747 NumberFormat::createCurrencyInstance("et", status)));
9748 if (status.errDataIfFailureAndReset()) {
9749 return;
9750 }
9751
9752 decimalFormat->setCurrency(u"EEK");
9753
9754 const DecimalFormatSymbols* decimalFormatSymbols = decimalFormat->getDecimalFormatSymbols();
9755 assertEquals("MONETARY DECIMAL SEPARATOR",
9756 u".",
9757 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
9758 assertEquals("DECIMAL SEPARATOR",
9759 u",",
9760 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol));
9761 assertEquals("MONETARY GROUPING SEPARATOR",
9762 u" ",
9763 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol));
9764 assertEquals("GROUPING SEPARATOR",
9765 u" ",
9766 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
9767 assertEquals("CURRENCY SYMBOL",
9768 u"kr",
9769 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
9770
9771 UnicodeString sb;
9772 decimalFormat->format(12345.12, sb, status);
9773 assertEquals("OUTPUT", u"12 345.12 kr", sb);
9774}
9775
9776void NumberFormatTest::Test20358_GroupingInPattern() {
9777 IcuTestErrorCode status(*this, "Test20358_GroupingInPattern");
9778 LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9779 NumberFormat::createInstance("en", status)));
9780 if (status.errIfFailureAndReset()) { return; }
9781 UnicodeString result;
9782 assertEquals("Initial pattern",
9783 u"#,##0.###", fmt->toPattern(result.remove()));
9784 assertTrue("Initial grouping",
9785 fmt->isGroupingUsed());
9786 assertEquals("Initial format",
9787 u"54,321", fmt->format(54321, result.remove(), NULL, status));
9788
9789 fmt->setGroupingUsed(false);
9790 assertEquals("Set grouping false",
9791 u"0.###", fmt->toPattern(result.remove()));
9792 assertFalse("Set grouping false grouping",
9793 fmt->isGroupingUsed());
9794 assertEquals("Set grouping false format",
9795 u"54321", fmt->format(54321, result.remove(), NULL, status));
9796
9797 fmt->setGroupingUsed(true);
9798 assertEquals("Set grouping true",
9799 u"#,##0.###", fmt->toPattern(result.remove()));
9800 assertTrue("Set grouping true grouping",
9801 fmt->isGroupingUsed());
9802 assertEquals("Set grouping true format",
9803 u"54,321", fmt->format(54321, result.remove(), NULL, status));
9804}
9805
9806void NumberFormatTest::Test13731_DefaultCurrency() {
9807 IcuTestErrorCode status(*this, "Test13731_DefaultCurrency");
9808 UnicodeString result;
9809 {
9810 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9811 "en", UNumberFormatStyle::UNUM_CURRENCY, status), status);
9812 if (status.errIfFailureAndReset()) { return; }
9813 assertEquals("symbol", u"¤1.10",
9814 nf->format(1.1, result.remove(), status));
9815 assertEquals("currency", u"XXX", nf->getCurrency());
9816 }
9817 {
9818 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9819 "en", UNumberFormatStyle::UNUM_CURRENCY_ISO, status), status);
9820 if (status.errIfFailureAndReset()) { return; }
9821 assertEquals("iso_code", u"XXX 1.10",
9822 nf->format(1.1, result.remove(), status));
9823 assertEquals("currency", u"XXX", nf->getCurrency());
9824 }
9825 {
9826 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9827 "en", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9828 if (status.errIfFailureAndReset()) { return; }
9829 assertEquals("plural", u"1.10 (unknown currency)",
9830 nf->format(1.1, result.remove(), status));
9831 assertEquals("currency", u"XXX", nf->getCurrency());
9832 }
9833}
9834
9835void NumberFormatTest::Test20499_CurrencyVisibleDigitsPlural() {
9836 IcuTestErrorCode status(*this, "Test20499_CurrencyVisibleDigitsPlural");
9837 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9838 "ro-RO", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9839 const char16_t* expected = u"24,00 lei românești";
9840 for (int32_t i=0; i<5; i++) {
9841 UnicodeString actual;
9842 nf->format(24, actual, status);
9843 assertEquals(UnicodeString(u"iteration ") + Int64ToUnicodeString(i),
9844 expected, actual);
9845 }
9846}
9847
9848void NumberFormatTest::Test13735_GroupingSizeGetter() {
9849 IcuTestErrorCode status(*this, "Test13735_GroupingSizeGetter");
9850 {
9851 DecimalFormat df("0", {"en", status}, status);
9852 assertEquals("pat 0: ", 0, df.getGroupingSize());
9853 df.setGroupingUsed(false);
9854 assertEquals("pat 0 then disabled: ", 0, df.getGroupingSize());
9855 df.setGroupingUsed(true);
9856 assertEquals("pat 0 then enabled: ", 0, df.getGroupingSize());
9857 }
9858 {
9859 DecimalFormat df("#,##0", {"en", status}, status);
9860 assertEquals("pat #,##0: ", 3, df.getGroupingSize());
9861 df.setGroupingUsed(false);
9862 assertEquals("pat #,##0 then disabled: ", 3, df.getGroupingSize());
9863 df.setGroupingUsed(true);
9864 assertEquals("pat #,##0 then enabled: ", 3, df.getGroupingSize());
9865 }
9866}
9867
9868void NumberFormatTest::Test13734_StrictFlexibleWhitespace() {
9869 IcuTestErrorCode status(*this, "Test13734_StrictFlexibleWhitespace");
9870 {
9871 DecimalFormat df("+0", {"en", status}, status);
Frank Tang1f164ee2022-11-08 12:31:27 -08009872 df.setLenient(false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08009873 Formattable result;
9874 ParsePosition ppos;
9875 df.parse("+ 33", result, ppos);
9876 assertEquals("ppos : ", 0, ppos.getIndex());
9877 assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9878 }
9879 {
9880 DecimalFormat df("+ 0", {"en", status}, status);
Frank Tang1f164ee2022-11-08 12:31:27 -08009881 df.setLenient(false);
Frank Tang3e05d9d2021-11-08 14:04:04 -08009882 Formattable result;
9883 ParsePosition ppos;
9884 df.parse("+ 33", result, ppos);
9885 assertEquals("ppos : ", 0, ppos.getIndex());
9886 assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9887 }
9888}
9889
9890void NumberFormatTest::Test20961_CurrencyPluralPattern() {
9891 IcuTestErrorCode status(*this, "Test20961_CurrencyPluralPattern");
9892 {
9893 LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9894 NumberFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9895 if (status.errDataIfFailureAndReset()) {
9896 return;
9897 }
9898 UnicodeString result;
9899 decimalFormat->toPattern(result);
9900 assertEquals("Currency pattern", u"#,##0.00 ¤¤¤", result);
9901 }
9902}
9903
9904void NumberFormatTest::Test21134_ToNumberFormatter() {
9905 IcuTestErrorCode status(*this, "Test21134_ToNumberFormatter");
9906 LocalizedNumberFormatter outer1;
9907 LocalizedNumberFormatter outer2;
9908 LocalPointer<LocalizedNumberFormatter> outer3;
9909 {
9910 // Case 1: new formatter object
9911 DecimalFormat inner(u"a0b", {"en", status}, status);
9912 if (auto ptr = inner.toNumberFormatter(status)) {
9913 // Copy assignment
9914 outer1 = *ptr;
9915 } else {
9916 status.errIfFailureAndReset();
9917 return;
9918 }
9919 }
9920 {
9921 // Case 2: compiled formatter object (used at least 3 times)
9922 DecimalFormat inner(u"c0d", {"en", status}, status);
9923 UnicodeString dummy;
9924 inner.format(100, dummy);
9925 inner.format(100, dummy);
9926 inner.format(100, dummy);
9927 if (auto ptr = inner.toNumberFormatter(status)) {
9928 // Copy assignment
9929 outer2 = *ptr;
9930 } else {
9931 status.errIfFailureAndReset();
9932 return;
9933 }
9934 }
9935 {
9936 // Case 3: currency plural info (different code path)
9937 LocalPointer<DecimalFormat> inner(static_cast<DecimalFormat*>(
9938 DecimalFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9939 if (auto ptr = inner->toNumberFormatter(status)) {
9940 // Copy constructor
9941 outer3.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(*ptr), status);
9942 } else {
9943 status.errIfFailureAndReset();
9944 return;
9945 }
9946 }
9947 auto result1 = outer1.formatDouble(99, status);
9948 assertEquals("Using NumberFormatter from DecimalFormat, new version",
9949 u"a99b",
9950 result1.toTempString(status));
9951 auto result2 = outer2.formatDouble(99, status);
9952 assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9953 u"c99d",
9954 result2.toTempString(status));
9955 auto result3 = outer3->formatDouble(99, status);
9956 assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9957 u"99.00 US dollars",
9958 result3.toTempString(status));
9959}
9960
9961void NumberFormatTest::Test13733_StrictAndLenient() {
9962 IcuTestErrorCode status(*this, "Test13733_StrictAndLenient");
9963
9964 static const struct TestCase {
9965 const char16_t* inputString;
9966 const char16_t* patternString;
9967 int64_t expectedStrictParse;
9968 int64_t expectedLenientParse;
9969 } cases[] = { {u"CA$ 12", u"¤ 0", 12, 12},
9970 {u"CA$12", u"¤0", 12, 12},
9971 {u"CAD 12", u"¤¤ 0", 12, 12},
9972 {u"12 CAD", u"0 ¤¤", 12, 12},
9973 {u"12 Canadian dollars", u"0 ¤¤¤", 12, 12},
9974 {u"$12 ", u"¤¤¤¤0", 12, 12},
9975 {u"12$", u"0¤¤¤¤", 12, 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"CA$12", u"0 ¤¤¤", 0, 12},
9985 {u"CA$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"CAD 12", u"¤¤¤¤0", 0, 12},
9990 {u"CAD 12", 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 CAD", u"¤¤¤¤0", 0, 12},
9995 {u"12 CAD", 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 Canadian dollars", u"¤¤¤¤0", 0, 12},
10000 {u"12 Canadian dollars", 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 {u"12$", u"0 ¤¤¤", 0, 12},
10011 {u"12$", u"¤¤¤¤0", 0, 12} };
10012 for (auto& cas : cases) {
10013 UnicodeString inputString(cas.inputString);
10014 UnicodeString patternString(cas.patternString);
10015 int64_t parsedStrictValue = 0;
10016 int64_t parsedLenientValue = 0;
10017 ParsePosition ppos;
10018
10019 DecimalFormatSymbols dfs(Locale::getEnglish(), status);
10020 if (status.errDataIfFailureAndReset()) {
10021 return;
10022 }
10023 DecimalFormat df(patternString, dfs, status);
10024 if (status.errDataIfFailureAndReset()) {
10025 return;
10026 }
Frank Tang1f164ee2022-11-08 12:31:27 -080010027 df.setLenient(false);
Frank Tang3e05d9d2021-11-08 14:04:04 -080010028 LocalPointer<CurrencyAmount> ca_strict(df.parseCurrency(inputString, ppos));
10029 if (ca_strict != nullptr) {
10030 parsedStrictValue = ca_strict->getNumber().getInt64();
10031 }
10032 assertEquals("Strict parse of " + inputString + " using " + patternString,
10033 parsedStrictValue, cas.expectedStrictParse);
10034
10035 ppos.setIndex(0);
Frank Tang1f164ee2022-11-08 12:31:27 -080010036 df.setLenient(true);
Frank Tang3e05d9d2021-11-08 14:04:04 -080010037 LocalPointer<CurrencyAmount> ca_lenient(df.parseCurrency(inputString, ppos));
10038 Formattable parsedNumber_lenient = ca_lenient->getNumber();
10039 if (ca_lenient != nullptr) {
10040 parsedLenientValue = ca_lenient->getNumber().getInt64();
10041 }
10042 assertEquals("Lenient parse of " + inputString + " using " + patternString,
10043 parsedLenientValue, cas.expectedLenientParse);
10044 }
10045}
10046
10047void NumberFormatTest::Test20425_IntegerIncrement() {
10048 IcuTestErrorCode status(*this, "Test20425_IntegerIncrement");
10049
10050 DecimalFormat df("##00", status);
10051 df.setRoundingIncrement(1);
10052 UnicodeString actual;
10053 df.format(1235.5, actual, status);
10054 assertEquals("Should round to integer", u"1236", actual);
10055}
10056
10057void NumberFormatTest::Test20425_FractionWithIntegerIncrement() {
10058 IcuTestErrorCode status(*this, "Test20425_FractionWithIntegerIncrement");
10059
10060 DecimalFormat df("0.0", status);
10061 df.setRoundingIncrement(1);
10062 UnicodeString actual;
10063 df.format(8.6, actual, status);
10064 assertEquals("Should have a fraction digit", u"9.0", actual);
10065}
10066
10067void NumberFormatTest::Test21232_ParseTimeout() {
10068 IcuTestErrorCode status(*this, "Test21232_ParseTimeout");
10069
10070 DecimalFormat df(status);
10071 if (status.errDataIfFailureAndReset()) {
10072 return;
10073 }
10074
10075 UnicodeString input = u"4444444444444444444444444444444444444444";
10076 if (quick) {
10077 for (int32_t i = 0; i < 5; i++) {
10078 input.append(input);
10079 }
10080 assertEquals("Somewhat long input of digits", 1280, input.length());
10081 } else {
10082 for (int32_t i = 0; i < 12; i++) {
10083 input.append(input);
10084 }
10085 assertEquals("Very long input of digits", 163840, input.length());
10086 }
10087 Formattable result;
10088 df.parse(input, result, status);
10089 // Should not hang
10090}
10091
10092void NumberFormatTest::Test10997_FormatCurrency() {
10093 IcuTestErrorCode status(*this, "Test10997_FormatCurrency");
10094
10095 LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance(Locale::getUS(), status));
10096 if (status.errDataIfFailureAndReset()) {
10097 return;
10098 }
10099 fmt->setMinimumFractionDigits(4);
10100 fmt->setMaximumFractionDigits(4);
10101
10102 FieldPosition fp;
10103
10104 UnicodeString str;
10105 Formattable usdAmnt(new CurrencyAmount(123.45, u"USD", status));
10106 fmt->format(usdAmnt, str, fp, status);
10107 assertEquals("minFrac 4 should be respected in default currency", u"$123.4500", str);
10108
10109 UnicodeString str2;
10110 Formattable eurAmnt(new CurrencyAmount(123.45, u"EUR", status));
10111 fmt->format(eurAmnt, str2, fp, status);
10112 assertEquals("minFrac 4 should be respected in different currency", u"€123.4500", str2);
10113}
10114
10115void NumberFormatTest::Test21556_CurrencyAsDecimal() {
10116 IcuTestErrorCode status(*this, "Test21556_CurrencyAsDecimal");
10117
10118 {
10119 DecimalFormat df(u"a0¤00b", status);
10120 if (status.errDataIfFailureAndReset()) {
10121 return;
10122 }
10123 df.setCurrency(u"EUR", status);
10124 UnicodeString result;
10125 FieldPosition fp(UNUM_CURRENCY_FIELD);
10126 df.format(3.141, result, fp);
10127 assertEquals("Basic test: format", u"a3€14b", result);
10128 UnicodeString pattern;
10129 assertEquals("Basic test: toPattern", u"a0¤00b", df.toPattern(pattern));
10130 assertEquals("Basic test: field position begin", 2, fp.getBeginIndex());
10131 assertEquals("Basic test: field position end", 3, fp.getEndIndex());
10132 }
10133
10134 {
10135 LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-GB", status));
10136 DecimalFormat* df = static_cast<DecimalFormat*>(nf.getAlias());
10137 df->applyPattern(u"a0¤00b", status);
10138 UnicodeString result;
10139 FieldPosition fp(UNUM_CURRENCY_FIELD);
10140 df->format(3.141, result, fp);
10141 assertEquals("Via applyPattern: format", u"a3£14b", result);
10142 UnicodeString pattern;
10143 assertEquals("Via applyPattern: toPattern", u"a0¤00b", df->toPattern(pattern));
10144 assertEquals("Via applyPattern: field position begin", 2, fp.getBeginIndex());
10145 assertEquals("Via applyPattern: field position end", 3, fp.getEndIndex());
10146 }
10147}
10148
Frank Tang1f164ee2022-11-08 12:31:27 -080010149void NumberFormatTest::Test22088_Ethiopic() {
10150 IcuTestErrorCode err(*this, "Test22088_Ethiopic");
10151 LocalPointer<NumberFormat> nf1(NumberFormat::createInstance(Locale("am_ET@numbers=ethi"), UNUM_DEFAULT, err));
10152 LocalPointer<NumberFormat> nf2(NumberFormat::createInstance(Locale("am_ET@numbers=ethi"), UNUM_NUMBERING_SYSTEM, err));
10153 LocalPointer<NumberFormat> nf3(NumberFormat::createInstance(Locale::getUS(), UNUM_NUMBERING_SYSTEM, err));
10154
10155 if (!err.errIfFailureAndReset("Creation of number formatters failed")) {
10156 UnicodeString result;
10157 assertEquals("Wrong result with UNUM_DEFAULT", u"፻፳፫", nf1->format(123, result));
10158 result.remove();
10159 assertEquals("Wrong result with UNUM_NUMBERING_SYSTEM", u"፻፳፫", nf2->format(123, result));
10160 result.remove();
10161 assertEquals("Wrong result with UNUM_NUMBERING_SYSTEM and English", u"123", nf3->format(123, result));
10162 }
10163}
10164
Frank Tang3e05d9d2021-11-08 14:04:04 -080010165#endif /* #if !UCONFIG_NO_FORMATTING */