+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2015, International Business Machines Corporation and
+ * Copyright (c) 1997-2016, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/* Modification History:
#if !UCONFIG_NO_FORMATTING
#include "numfmtst.h"
+#include "unicode/currpinf.h"
#include "unicode/dcfmtsym.h"
#include "unicode/decimfmt.h"
#include "unicode/localpointer.h"
#include "unicode/ustring.h"
#include "unicode/measfmt.h"
#include "unicode/curramt.h"
-#include "digitlst.h"
+#include "unicode/strenum.h"
#include "textfile.h"
#include "tokiter.h"
#include "charstr.h"
+#include "cstr.h"
#include "putilimp.h"
#include "winnmtst.h"
+#include <cmath>
#include <float.h>
#include <string.h>
#include <stdlib.h>
+#include "cmemory.h"
#include "cstring.h"
#include "unicode/numsys.h"
#include "fmtableimp.h"
+#include "numberformattesttuple.h"
+#include "unicode/msgfmt.h"
+#include "number_decimalquantity.h"
+#include "unicode/numberformatter.h"
+
+#if (U_PLATFORM == U_PF_AIX) || (U_PLATFORM == U_PF_OS390)
+// These should not be macros. If they are,
+// replace them with std::isnan and std::isinf
+#if defined(isnan)
+#undef isnan
+namespace std {
+ bool isnan(double x) {
+ return _isnan(x);
+ }
+}
+#endif
+#if defined(isinf)
+#undef isinf
+namespace std {
+ bool isinf(double x) {
+ return _isinf(x);
+ }
+}
+#endif
+#endif
+
+using icu::number::impl::DecimalQuantity;
+using namespace icu::number;
//#define NUMFMTST_CACHE_DEBUG 1
#include "stdio.h" /* for sprintf */
TESTCASE_AUTO(TestCurrencyAmount);
TESTCASE_AUTO(TestCurrencyUnit);
TESTCASE_AUTO(TestCoverage);
+ //TESTCASE_AUTO(TestLocalizedPatternSymbolCoverage);
TESTCASE_AUTO(TestJB3832);
TESTCASE_AUTO(TestHost);
TESTCASE_AUTO(TestHostClone);
TESTCASE_AUTO(TestSpaceParsing);
TESTCASE_AUTO(TestMultiCurrencySign);
TESTCASE_AUTO(TestCurrencyFormatForMixParsing);
+ //TESTCASE_AUTO(TestMismatchedCurrencyFormatFail);
TESTCASE_AUTO(TestDecimalFormatCurrencyParse);
TESTCASE_AUTO(TestCurrencyIsoPluralFormat);
TESTCASE_AUTO(TestCurrencyParsing);
TESTCASE_AUTO(TestFieldPositionIterator);
TESTCASE_AUTO(TestDecimal);
TESTCASE_AUTO(TestCurrencyFractionDigits);
- TESTCASE_AUTO(TestExponentParse);
- TESTCASE_AUTO(TestExplicitParents);
+ TESTCASE_AUTO(TestExponentParse);
+ TESTCASE_AUTO(TestExplicitParents);
TESTCASE_AUTO(TestLenientParse);
TESTCASE_AUTO(TestAvailableNumberingSystems);
TESTCASE_AUTO(TestRoundingPattern);
TESTCASE_AUTO(TestEquality);
TESTCASE_AUTO(TestCurrencyUsage);
TESTCASE_AUTO(TestDoubleLimit11439);
- TESTCASE_AUTO(TestFastPathConsistent11524);
+ TESTCASE_AUTO(TestGetAffixes);
+ TESTCASE_AUTO(TestToPatternScientific11648);
+ TESTCASE_AUTO(TestBenchmark);
+ TESTCASE_AUTO(TestCtorApplyPatternDifference);
+ TESTCASE_AUTO(TestFractionalDigitsForCurrency);
+ TESTCASE_AUTO(TestFormatCurrencyPlural);
+ TESTCASE_AUTO(Test11868);
+ TESTCASE_AUTO(Test11739_ParseLongCurrency);
+ //TESTCASE_AUTO(Test13035_MultiCodePointPaddingInPattern);
+ TESTCASE_AUTO(Test13737_ParseScientificStrict);
+ TESTCASE_AUTO(Test10727_RoundingZero);
+ TESTCASE_AUTO(Test11376_getAndSetPositivePrefix);
+ TESTCASE_AUTO(Test11475_signRecognition);
+ TESTCASE_AUTO(Test11640_getAffixes);
+ TESTCASE_AUTO(Test11649_toPatternWithMultiCurrency);
+ TESTCASE_AUTO(Test13327_numberingSystemBufferOverflow);
+ TESTCASE_AUTO(Test13391_chakmaParsing);
+ TESTCASE_AUTO(Test11735_ExceptionIssue);
+ TESTCASE_AUTO(Test11035_FormatCurrencyAmount);
+ TESTCASE_AUTO(Test11318_DoubleConversion);
+ TESTCASE_AUTO(TestParsePercentRegression);
+ TESTCASE_AUTO(TestMultiplierWithScale);
+ TESTCASE_AUTO(TestFastFormatInt32);
+ TESTCASE_AUTO(Test11646_Equality);
+ TESTCASE_AUTO(TestParseNaN);
+ TESTCASE_AUTO(Test11897_LocalizedPatternSeparator);
+ TESTCASE_AUTO(Test13055_PercentageRounding);
+ TESTCASE_AUTO(Test11839);
+ TESTCASE_AUTO(Test10354);
+ TESTCASE_AUTO(Test11645_ApplyPatternEquality);
+ TESTCASE_AUTO(Test12567);
+ TESTCASE_AUTO(Test11626_CustomizeCurrencyPluralInfo);
+ TESTCASE_AUTO(Test13056_GroupingSize);
+ TESTCASE_AUTO(Test11025_CurrencyPadding);
+ TESTCASE_AUTO(Test11648_ExpDecFormatMalPattern);
+ //TESTCASE_AUTO(Test11649_DecFmtCurrencies);
+ TESTCASE_AUTO(Test13148_ParseGroupingSeparators);
+ TESTCASE_AUTO(Test12753_PatternDecimalPoint);
+ TESTCASE_AUTO(Test11647_PatternCurrencySymbols);
+ TESTCASE_AUTO(Test11913_BigDecimal);
+ TESTCASE_AUTO(Test11020_RoundingInScientificNotation);
+ TESTCASE_AUTO(Test11640_TripleCurrencySymbol);
+ TESTCASE_AUTO(Test13763_FieldPositionIteratorOffset);
+ TESTCASE_AUTO(Test13777_ParseLongNameNonCurrencyMode);
+ TESTCASE_AUTO(Test13804_EmptyStringsWhenParsing);
TESTCASE_AUTO_END;
}
}
if(test != NULL) {
test->setMinimumIntegerDigits(10);
- test->setMaximumIntegerDigits(2);
+ test->setMaximumIntegerDigits(1);
test->setMinimumFractionDigits(10);
- test->setMaximumFractionDigits(2);
+ test->setMaximumFractionDigits(1);
UnicodeString result;
FieldPosition pos;
result.remove();
int64_t ll = 12;
test->format(ll, result);
- if (result != "12.00"){
- errln("format int64_t error");
- }
+ assertEquals("format int64_t error", u"2.0", result);
+
+ test->setMinimumIntegerDigits(4);
+ test->setMinimumFractionDigits(4);
+
+ result.remove();
+ test->format(ll, result);
+ assertEquals("format int64_t error", u"0,012.0000", result);
ParsePosition ppos;
LocalPointer<CurrencyAmount> currAmt(test->parseCurrency("",ppos));
};
}
+void NumberFormatTest::TestLocalizedPatternSymbolCoverage() {
+ IcuTestErrorCode errorCode(*this, "TestLocalizedPatternSymbolCoverage");
+ // Ticket #12961: DecimalFormat::toLocalizedPattern() is not working as designed.
+ DecimalFormatSymbols dfs(errorCode);
+ dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u'⁖');
+ dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'⁘');
+ dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u'⁙');
+ dfs.setSymbol(DecimalFormatSymbols::kDigitSymbol, u'▰');
+ dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u'໐');
+ dfs.setSymbol(DecimalFormatSymbols::kSignificantDigitSymbol, u'⁕');
+ dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u'†');
+ dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u'‡');
+ dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u'⁜');
+ dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u'‱');
+ dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"⁑⁑"); // tests multi-char sequence
+ dfs.setSymbol(DecimalFormatSymbols::kPadEscapeSymbol, u'⁂');
+
+ {
+ UnicodeString standardPattern(u"#,##0.05+%;#,##0.05-%");
+ UnicodeString localizedPattern(u"▰⁖▰▰໐⁘໐໕†⁜⁙▰⁖▰▰໐⁘໐໕‡⁜");
+
+ DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
+ df1.applyPattern(standardPattern, errorCode);
+ DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
+ df2.applyLocalizedPattern(localizedPattern, errorCode);
+ assertTrue("DecimalFormat instances should be equal", df1 == df2);
+ UnicodeString p2;
+ assertEquals("toPattern should match on localizedPattern instance",
+ standardPattern, df2.toPattern(p2));
+ UnicodeString lp1;
+ assertEquals("toLocalizedPattern should match on standardPattern instance",
+ localizedPattern, df1.toLocalizedPattern(lp1));
+ }
+
+ {
+ UnicodeString standardPattern(u"* @@@E0‰");
+ UnicodeString localizedPattern(u"⁂ ⁕⁕⁕⁑⁑໐‱");
+
+ DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
+ df1.applyPattern(standardPattern, errorCode);
+ DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
+ df2.applyLocalizedPattern(localizedPattern, errorCode);
+ assertTrue("DecimalFormat instances should be equal", df1 == df2);
+ UnicodeString p2;
+ assertEquals("toPattern should match on localizedPattern instance",
+ standardPattern, df2.toPattern(p2));
+ UnicodeString lp1;
+ assertEquals("toLocalizedPattern should match on standardPattern instance",
+ localizedPattern, df1.toLocalizedPattern(lp1));
+ }
+}
+
// Test various patterns
void
NumberFormatTest::TestPatterns(void)
if (U_FAILURE(status)) { errcheckln(status, "FAIL: Could not construct DecimalFormatSymbols - %s", u_errorName(status)); return; }
const char* pat[] = { "#.#", "#.", ".#", "#" };
- int32_t pat_length = (int32_t)(sizeof(pat) / sizeof(pat[0]));
- const char* newpat[] = { "#0.#", "#0.", "#.0", "#" };
+ int32_t pat_length = UPRV_LENGTHOF(pat);
+ const char* newpat[] = { "#0.#", "#0.", "#.0", "#" }; // use ICU 61 behavior
const char* num[] = { "0", "0.", ".0", "0" };
for (int32_t i=0; i<pat_length; ++i)
{
DecimalFormatSymbols sym(Locale::getUS(), status);
if (U_FAILURE(status)) { errcheckln(status, "FAIL: Bad status returned by DecimalFormatSymbols ct - %s", u_errorName(status)); return; }
const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
- int32_t pat_length = (int32_t)(sizeof(pat) / sizeof(pat[0]));
+ int32_t pat_length = UPRV_LENGTHOF(pat);
// The following #if statements allow this test to be built and run on
// platforms that do not have standard IEEE numerics. For example,
#if DBL_MAX_10_EXP > 300
double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
- int32_t val_length = (int32_t)(sizeof(val) / sizeof(val[0]));
+ int32_t val_length = UPRV_LENGTHOF(val);
const char* valFormat[] =
{
// 0.####E0
};
#elif DBL_MAX_10_EXP > 70
double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
- int32_t val_length = sizeof(val) / sizeof(val[0]);
+ int32_t val_length = UPRV_LENGTHOF(val);
char* valFormat[] =
{
// 0.####E0
#endif
int32_t lval[] = { 0, -1, 1, 123456789 };
- int32_t lval_length = (int32_t)(sizeof(lval) / sizeof(lval[0]));
+ int32_t lval_length = UPRV_LENGTHOF(lval);
const char* lvalFormat[] =
{
// 0.####E0
#endif
}
else {
- errln((UnicodeString)"FAIL: Non-numeric Formattable returned");
+ errln(UnicodeString("FAIL: Non-numeric Formattable returned: ") + pattern + " " + s);
continue;
}
if (pos.getIndex() == s.length())
(uprv_fabs(a - valParse[v+ival]) / a > (2*DBL_EPSILON))) ||
(!useEpsilon && a != valParse[v+ival]))
{
- errln((UnicodeString)"FAIL: Expected " + valParse[v+ival]);
+ errln((UnicodeString)"FAIL: Expected " + valParse[v+ival] + " but got " + a
+ + " on input " + s);
}
}
else {
{
logln((UnicodeString)" -parse-> " + a);
if (a != lvalParse[v+ilval])
- errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval]);
+ errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval] + " but got " + a);
}
else
errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
// jb 2552
UErrorCode status = U_ZERO_ERROR;
DecimalFormat fmt("##0.00E0",status);
- if (U_SUCCESS(status)) {
+ if (assertSuccess("", status, true, __FILE__, __LINE__)) {
expect(fmt, .01234, "12.3E-3");
expect(fmt, .1234, "123E-3");
expect(fmt, 1.234, "1.23E0");
NumberFormatTest::TestInt64() {
UErrorCode status = U_ZERO_ERROR;
DecimalFormat fmt("#.#E0",status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ return;
+ }
fmt.setMaximumFractionDigits(20);
if (U_SUCCESS(status)) {
expect(fmt, (Formattable)(int64_t)0, "0E0");
UnicodeString s; currencyFmt->format(1.50, s);
logln((UnicodeString)"Un pauvre ici a..........." + s);
if (!(s==CharsToUnicodeString("1,50\\u00A0$")))
- errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$");
+ errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$ but got " + s);
delete currencyFmt;
s.truncate(0);
char loc[256]={0};
currencyFmt->format(1.50, s);
logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
if (!(s==CharsToUnicodeString("1,50\\u00A0DM")))
- errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM");
+ errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM but got " + s);
delete currencyFmt;
s.truncate(0);
len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
if (U_FAILURE(status))
errln((UnicodeString)"FAIL: Status " + (int32_t)status);
- for(int i=0; i < (int)(sizeof(testCases)/sizeof(testCases[i])); i++){
+ for(int i=0; i < UPRV_LENGTHOF(testCases); i++){
status = U_ZERO_ERROR;
const char *localeID = testCases[i][0];
UnicodeString expected(testCases[i][1], -1, US_INV);
1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
expectCurrency(*fmt, Locale("fr", "CH", ""),
- 1234.56, "CHF1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
+ 1234.56, "CHF1,234.56"); // no more 0.05 rounding here, see cldrbug 5548 // use ICU 61 behavior
expectCurrency(*fmt, Locale::getUS(),
1234.56, "$1,234.56");
static const char *lenientMinusTestCases[] = {
"-5",
"\\u22125",
- "\\u20105"
+ "\\u27965"
};
static const char *lenientCurrencyTestCases[] = {
"1,000,.0"
};
-#define ARRAY_SIZE(array) ((int32_t) (sizeof (array) / sizeof(array[0])))
-
/**
* Test lenient parsing.
*/
dataerrln("Unable to create DecimalFormat (#,##0) - %s", u_errorName(status));
} else {
format->setLenient(TRUE);
- for (int32_t t = 0; t < ARRAY_SIZE (lenientAffixTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF (lenientAffixTestCases); t += 1) {
UnicodeString testCase = ctou(lenientAffixTestCases[t]);
format->parse(testCase, n, status);
if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
n.getLong() != 1) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t] + (UnicodeString) "\"");
+ dataerrln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
status = U_ZERO_ERROR;
}
}
Locale en_US("en_US");
Locale sv_SE("sv_SE");
-
+
NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, UNUM_DECIMAL, status);
-
+
if (mFormat == NULL || U_FAILURE(status)) {
dataerrln("Unable to create NumberFormat (sv_SE, UNUM_DECIMAL) - %s", u_errorName(status));
} else {
mFormat->setLenient(TRUE);
- for (int32_t t = 0; t < ARRAY_SIZE(lenientMinusTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
UnicodeString testCase = ctou(lenientMinusTestCases[t]);
-
+
mFormat->parse(testCase, n, status);
logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
-
+
if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
status = U_ZERO_ERROR;
}
}
delete mFormat;
}
-
+
mFormat = NumberFormat::createInstance(en_US, UNUM_DECIMAL, status);
-
+
if (mFormat == NULL || U_FAILURE(status)) {
dataerrln("Unable to create NumberFormat (en_US, UNUM_DECIMAL) - %s", u_errorName(status));
} else {
mFormat->setLenient(TRUE);
- for (int32_t t = 0; t < ARRAY_SIZE(lenientMinusTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
UnicodeString testCase = ctou(lenientMinusTestCases[t]);
-
+
mFormat->parse(testCase, n, status);
logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
-
+
if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
status = U_ZERO_ERROR;
}
}
delete mFormat;
}
-
+
NumberFormat *cFormat = NumberFormat::createInstance(en_US, UNUM_CURRENCY, status);
if (cFormat == NULL || U_FAILURE(status)) {
dataerrln("Unable to create NumberFormat (en_US, UNUM_CURRENCY) - %s", u_errorName(status));
} else {
cFormat->setLenient(TRUE);
- for (int32_t t = 0; t < ARRAY_SIZE (lenientCurrencyTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF (lenientCurrencyTestCases); t += 1) {
UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
cFormat->parse(testCase, n, status);
if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
n.getLong() != 1000) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
status = U_ZERO_ERROR;
}
}
- for (int32_t t = 0; t < ARRAY_SIZE (lenientNegativeCurrencyTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativeCurrencyTestCases); t += 1) {
UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
cFormat->parse(testCase, n, status);
if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
n.getLong() != -1000) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
status = U_ZERO_ERROR;
}
}
dataerrln("Unable to create NumberFormat::createPercentInstance (en_US) - %s", u_errorName(status));
} else {
pFormat->setLenient(TRUE);
- for (int32_t t = 0; t < ARRAY_SIZE (lenientPercentTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF (lenientPercentTestCases); t += 1) {
UnicodeString testCase = ctou(lenientPercentTestCases[t]);
pFormat->parse(testCase, n, status);
if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
n.getDouble() != 0.25) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status)
+ + "; got: " + n.getDouble(status));
status = U_ZERO_ERROR;
}
}
- for (int32_t t = 0; t < ARRAY_SIZE (lenientNegativePercentTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativePercentTestCases); t += 1) {
UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
pFormat->parse(testCase, n, status);
if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
n.getDouble() != -0.25) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status)
+ + "; got: " + n.getDouble(status));
status = U_ZERO_ERROR;
}
}
// Test cases that should fail with a strict parse and pass with a
// lenient parse.
NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);
-
+
if (nFormat == NULL || U_FAILURE(status)) {
dataerrln("Unable to create NumberFormat (en_US) - %s", u_errorName(status));
- } else {
+ } else {
// first, make sure that they fail with a strict parse
- for (int32_t t = 0; t < ARRAY_SIZE(strictFailureTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
UnicodeString testCase = ctou(strictFailureTestCases[t]);
nFormat->parse(testCase, n, status);
logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
if (! U_FAILURE(status)) {
- errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
}
status = U_ZERO_ERROR;
// then, make sure that they pass with a lenient parse
nFormat->setLenient(TRUE);
- for (int32_t t = 0; t < ARRAY_SIZE(strictFailureTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
UnicodeString testCase = ctou(strictFailureTestCases[t]);
nFormat->parse(testCase, n, status);
if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
n.getLong() != 1000) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
status = U_ZERO_ERROR;
}
}
CHECK(status, "DecimalFormat ct");
expect2(f, (int32_t)123456789L, "12,34,56,789");
- expectPat(f, "#,##,###");
+ expectPat(f, "#,##,###"); // use ICU 61 behavior
f.applyPattern("#,###", status);
CHECK(status, "applyPattern");
f.setSecondaryGroupingSize(4);
expect2(f, (int32_t)123456789L, "12,3456,789");
- expectPat(f, "#,####,###");
+ expectPat(f, "#,####,###"); // use ICU 61 behavior
NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
CHECK_DATA(status, "createInstance(hi_IN)");
errcheckln(ec, "FAIL: Constructor - %s", u_errorName(ec));
return;
}
+ // From ICU 62, flexible whitespace needs lenient mode
+ fmt.setLenient(TRUE);
int32_t n = 1234;
expect(fmt, "a b1234c ", n);
expect(fmt, "a b1234c ", n);
// Test pattern round-trip
const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
"0.###E0;[0.###E0]" };
- int32_t PAT_length = (int32_t)(sizeof(PAT) / sizeof(PAT[0]));
+ int32_t PAT_length = UPRV_LENGTHOF(PAT);
int32_t DIGITS[] = {
// min int, max int, min frac, max frac
- 0, 1, 0, 0, // "#E0"
+ 0, 1, 0, 0, // "#E0" // expect ICU 61 behavior
1, 1, 0, 4, // "0.####E0"
2, 2, 3, 3, // "00.000E00"
1, 3, 0, 4, // "##0.####E000"
fmt.setFormatWidth(16);
// 12 34567890123456
- expectPat(fmt, "AA*^#,###,##0.00ZZ");
+ expectPat(fmt, "AA*^#,###,##0.00ZZ"); // use ICU 61 behavior
}
void NumberFormatTest::TestSurrogateSupport(void) {
const UBool possibleDataError = TRUE;
// Warning: HARD-CODED LOCALE DATA in this test. If it fails, CHECK
// THE LOCALE DATA before diving into the code.
- assertEquals("USD.getName(SYMBOL_NAME)",
+ assertEquals("USD.getName(SYMBOL_NAME, en)",
UnicodeString("$"),
UnicodeString(ucurr_getName(USD, "en",
UCURR_SYMBOL_NAME,
&isChoiceFormat, &len, &ec)),
possibleDataError);
- assertEquals("USD.getName(LONG_NAME)",
+ assertEquals("USD.getName(NARROW_SYMBOL_NAME, en)",
+ UnicodeString("$"),
+ UnicodeString(ucurr_getName(USD, "en",
+ UCURR_NARROW_SYMBOL_NAME,
+ &isChoiceFormat, &len, &ec)),
+ possibleDataError);
+ assertEquals("USD.getName(LONG_NAME, en)",
UnicodeString("US Dollar"),
UnicodeString(ucurr_getName(USD, "en",
UCURR_LONG_NAME,
&isChoiceFormat, &len, &ec)),
possibleDataError);
- assertEquals("CAD.getName(SYMBOL_NAME)",
+ assertEquals("CAD.getName(SYMBOL_NAME, en)",
UnicodeString("CA$"),
UnicodeString(ucurr_getName(CAD, "en",
UCURR_SYMBOL_NAME,
&isChoiceFormat, &len, &ec)),
possibleDataError);
- assertEquals("CAD.getName(SYMBOL_NAME)",
+ assertEquals("CAD.getName(NARROW_SYMBOL_NAME, en)",
+ UnicodeString("$"),
+ UnicodeString(ucurr_getName(CAD, "en",
+ UCURR_NARROW_SYMBOL_NAME,
+ &isChoiceFormat, &len, &ec)),
+ possibleDataError);
+ assertEquals("CAD.getName(SYMBOL_NAME, en_CA)",
UnicodeString("$"),
UnicodeString(ucurr_getName(CAD, "en_CA",
UCURR_SYMBOL_NAME,
&isChoiceFormat, &len, &ec)),
possibleDataError);
- assertEquals("USD.getName(SYMBOL_NAME) in en_AU",
+ assertEquals("USD.getName(SYMBOL_NAME, en_CA)",
UnicodeString("US$"),
- UnicodeString(ucurr_getName(USD, "en_AU",
+ UnicodeString(ucurr_getName(USD, "en_CA",
+ UCURR_SYMBOL_NAME,
+ &isChoiceFormat, &len, &ec)),
+ possibleDataError);
+ assertEquals("USD.getName(NARROW_SYMBOL_NAME, en_CA)",
+ UnicodeString("$"),
+ UnicodeString(ucurr_getName(USD, "en_CA",
+ UCURR_NARROW_SYMBOL_NAME,
+ &isChoiceFormat, &len, &ec)),
+ possibleDataError);
+ assertEquals("USD.getName(SYMBOL_NAME) in en_NZ",
+ UnicodeString("US$"),
+ UnicodeString(ucurr_getName(USD, "en_NZ",
UCURR_SYMBOL_NAME,
&isChoiceFormat, &len, &ec)),
possibleDataError);
assertEquals("CAD.getName(SYMBOL_NAME)",
UnicodeString("CA$"),
- UnicodeString(ucurr_getName(CAD, "en_AU",
+ UnicodeString(ucurr_getName(CAD, "en_NZ",
+ UCURR_SYMBOL_NAME,
+ &isChoiceFormat, &len, &ec)),
+ possibleDataError);
+ assertEquals("USX.getName(SYMBOL_NAME)",
+ UnicodeString("USX"),
+ UnicodeString(ucurr_getName(USX, "en_US",
UCURR_SYMBOL_NAME,
&isChoiceFormat, &len, &ec)),
possibleDataError);
+ assertEquals("USX.getName(NARROW_SYMBOL_NAME)",
+ UnicodeString("USX"),
+ UnicodeString(ucurr_getName(USX, "en_US",
+ UCURR_NARROW_SYMBOL_NAME,
+ &isChoiceFormat, &len, &ec)),
+ possibleDataError);
assertEquals("USX.getName(LONG_NAME)",
UnicodeString("USX"),
UnicodeString(ucurr_getName(USX, "en_US",
void NumberFormatTest::TestCurrencyUnit(void){
UErrorCode ec = U_ZERO_ERROR;
- static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
- static const UChar BAD[] = {63, 63, 63, 0}; /*???*/
- static const UChar BAD2[] = {63, 63, 65, 0}; /*???*/
+ static const UChar USD[] = u"USD";
+ static const char USD8[] = "USD";
+ static const UChar BAD[] = u"???";
+ static const UChar BAD2[] = u"??A";
+ static const UChar XXX[] = u"XXX";
+ static const char XXX8[] = "XXX";
CurrencyUnit cu(USD, ec);
assertSuccess("CurrencyUnit", ec);
- const UChar * r = cu.getISOCurrency(); // who is the buffer owner ?
- assertEquals("getISOCurrency()", USD, r);
+ assertEquals("getISOCurrency()", USD, cu.getISOCurrency());
+ assertEquals("getSubtype()", USD8, cu.getSubtype());
CurrencyUnit cu2(cu);
if (!(cu2 == cu)){
errln("Currency unit assignment should be the same.");
}
delete cu3;
+
+ // Test default constructor
+ CurrencyUnit def;
+ assertEquals("Default currency", XXX, def.getISOCurrency());
+ assertEquals("Default currency as subtype", XXX8, def.getSubtype());
+
+ // Test slicing
+ MeasureUnit sliced1 = cu;
+ MeasureUnit sliced2 = cu;
+ assertEquals("Subtype after slicing 1", USD8, sliced1.getSubtype());
+ assertEquals("Subtype after slicing 2", USD8, sliced2.getSubtype());
+ CurrencyUnit restored1(sliced1, ec);
+ CurrencyUnit restored2(sliced2, ec);
+ assertSuccess("Restoring from MeasureUnit", ec);
+ assertEquals("Subtype after restoring 1", USD8, restored1.getSubtype());
+ assertEquals("Subtype after restoring 2", USD8, restored2.getSubtype());
+ assertEquals("ISO Code after restoring 1", USD, restored1.getISOCurrency());
+ assertEquals("ISO Code after restoring 2", USD, restored2.getISOCurrency());
+
+ // Test copy constructor failure
+ LocalPointer<MeasureUnit> meter(MeasureUnit::createMeter(ec));
+ assertSuccess("Creating meter", ec);
+ CurrencyUnit failure(*meter, ec);
+ assertEquals("Copying from meter should fail", ec, U_ILLEGAL_ARGUMENT_ERROR);
+ assertEquals("Copying should not give uninitialized ISO code", u"", failure.getISOCurrency());
}
void NumberFormatTest::TestCurrencyAmount(void){
}; // expect U_USING_DEFAULT_WARNING for both
unsigned int i;
- for (i = 0; i < sizeof(badLocales) / sizeof(char*); i++) {
+ for (i = 0; i < UPRV_LENGTHOF(badLocales); i++) {
const char *localeName = badLocales[i];
Locale locBad(localeName);
+ TEST_ASSERT_TRUE(!locBad.isBogus());
UErrorCode status = U_ZERO_ERROR;
UnicodeString intlCurrencySymbol((UChar)0xa4);
DecimalFormat fmt(ctou("###.###\\u2030"), ec);
if (!assertSuccess("DecimalFormat ct", ec)) return;
assertEquals("0.4857 x ###.###\\u2030",
- ctou("485.7\\u2030"), fmt.format(0.4857, str));
+ ctou("485.7\\u2030"), fmt.format(0.4857, str), true);
DecimalFormatSymbols sym(Locale::getUS(), ec);
+ if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
+ return;
+ }
sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
DecimalFormat fmt2("", sym, ec);
+ if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
+ return;
+ }
fmt2.applyLocalizedPattern("###.###m", ec);
if (!assertSuccess("setup", ec)) return;
str.truncate(0);
expectParseCurrency(*fmtJP, JPY, 1235, "\\u00A51,235");
logln("%s:%d - testing parse of fullwidth yen sign in JP\n", __FILE__, __LINE__);
expectParseCurrency(*fmtJP, JPY, 1235, "\\uFFE51,235");
-
+
// more..
*/
}
fmt.getLocale(ULOC_ACTUAL_LOCALE, status).getBaseName(),
text);
u_austrcpy(theInfo+uprv_strlen(theInfo), currency);
-
+
char theOperation[100];
uprv_strcpy(theOperation, theInfo);
uprv_strcat(theOperation, ", check currency:");
assertEquals(theOperation, currency, currencyAmount->getISOCurrency());
}
-
+
void NumberFormatTest::TestJB3832(){
const char* localeID = "pt_PT@currency=PTE";
UDate now = Calendar::getNow();
NumberFormat *full = NumberFormat::createInstance(loc, status);
if (full == NULL || U_FAILURE(status)) {
- dataerrln("FAIL: Can't create Relative date instance - %s", u_errorName(status));
+ dataerrln("FAIL: Can't create NumberFormat date instance - %s", u_errorName(status));
return;
}
UnicodeString result1;
}
MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
+ if (U_FAILURE(status)){
+ dataerrln("FAIL: MeasureFormat::createCurrencyFormat status %s", u_errorName(status));
+ return;
+ }
Locale::setDefault( saveDefaultLocale, status );
if (U_FAILURE(status)){
- dataerrln("FAIL: Status %s", u_errorName(status));
+ dataerrln("FAIL: Locale::setDefault status %s", u_errorName(status));
return;
}
cloneObj = (MeasureFormat *)measureObj->clone();
{ (UnicodeString)"##0.65", 1.234, (UnicodeString)"1.30" },
{ (UnicodeString)"#50", 1230, (UnicodeString)"1250" }
};
- int32_t numOfTests = (sizeof(tests)/sizeof(tests[0]));
+ int32_t numOfTests = UPRV_LENGTHOF(tests);
UnicodeString result;
DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
delete foo;
return;
}
- for (uint32_t i = 0; i < sizeof(DATA)/sizeof(DATA[0]); ++i) {
+ for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
ParsePosition parsePosition(0);
UnicodeString stringToBeParsed = ctou(DATA[i].stringToParse);
int parsedPosition = DATA[i].parsedPos;
foo->setLenient(DATA[i].lenient);
Formattable result;
foo->parse(stringToBeParsed, result, parsePosition);
+ logln("Parsing: " + stringToBeParsed);
if (parsePosition.getIndex() != parsedPosition ||
parsePosition.getErrorIndex() != errorIndex) {
errln("FAILED parse " + stringToBeParsed + "; lenient: " + DATA[i].lenient + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
NumberFormat *fmt = (NumberFormat *) origFmt->clone();
delete origFmt;
-
+
if (item->isRBNF) {
expect3(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
} else {
{"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD1,234.56", "-US dollars1,234.56"},
{"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD1.00", "US dollars1.00"},
// for CHINA locale
- {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\uFFE51,234.56", "CNY1,234.56", "\\u4EBA\\u6C11\\u5E011,234.56"},
- {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\uFFE51,234.56)", "(CNY1,234.56)", "(\\u4EBA\\u6C11\\u5E011,234.56)"},
- {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\uFFE51.00", "CNY1.00", "\\u4EBA\\u6C11\\u5E011.00"}
+ {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\u00A51,234.56", "CNY1,234.56", "\\u4EBA\\u6C11\\u5E011,234.56"},
+ {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\u00A51,234.56)", "(CNY1,234.56)", "(\\u4EBA\\u6C11\\u5E011,234.56)"},
+ {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\u00A51.00", "CNY1.00", "\\u4EBA\\u6C11\\u5E011.00"}
};
const UChar doubleCurrencySign[] = {0xA4, 0xA4, 0};
const UChar tripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
UnicodeString tripleCurrencyStr(tripleCurrencySign);
- for (uint32_t i=0; i<sizeof(DATA)/sizeof(DATA[0]); ++i) {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
const char* locale = DATA[i][0];
UnicodeString pat = ctou(DATA[i][1]);
double numberToBeFormat = atof(DATA[i][2]);
"$1,234.56", // string to be parsed
"USD1,234.56",
"US dollars1,234.56",
- "1,234.56 US dollars"
+ // "1,234.56 US dollars" // Fails in 62 because currency format is not compatible with pattern.
};
const CurrencyAmount* curramt = NULL;
- for (uint32_t i = 0; i < sizeof(formats)/sizeof(formats[0]); ++i) {
+ for (uint32_t i = 0; i < UPRV_LENGTHOF(formats); ++i) {
UnicodeString stringToBeParsed = ctou(formats[i]);
logln(UnicodeString("stringToBeParsed: ") + stringToBeParsed);
Formattable result;
}
+/** Starting in ICU 62, strict mode is actually strict with currency formats. */
+void NumberFormatTest::TestMismatchedCurrencyFormatFail() {
+ IcuTestErrorCode status(*this, "TestMismatchedCurrencyFormatFail");
+ LocalPointer<DecimalFormat> df(
+ dynamic_cast<DecimalFormat*>(DecimalFormat::createCurrencyInstance("en", status)), status);
+ if (!assertSuccess("createCurrencyInstance() failed.", status, true, __FILE__, __LINE__)) {return;}
+ UnicodeString pattern;
+ assertEquals("Test assumes that currency sign is at the beginning",
+ u"\u00A4#,##0.00",
+ df->toPattern(pattern));
+ // Should round-trip on the correct currency format:
+ expect2(*df, 1.23, u"XXX\u00A01.23");
+ df->setCurrency(u"EUR", status);
+ expect2(*df, 1.23, u"\u20AC1.23");
+ // Should parse with currency in the wrong place in lenient mode
+ df->setLenient(TRUE);
+ expect(*df, u"1.23\u20AC", 1.23);
+ expectParseCurrency(*df, u"EUR", 1.23, "1.23\\u20AC");
+ // Should NOT parse with currency in the wrong place in STRICT mode
+ df->setLenient(FALSE);
+ {
+ Formattable result;
+ ErrorCode failStatus;
+ df->parse(u"1.23\u20AC", result, failStatus);
+ assertEquals("Should fail to parse", U_INVALID_FORMAT_ERROR, failStatus);
+ }
+ {
+ ParsePosition ppos;
+ df->parseCurrency(u"1.23\u20AC", ppos);
+ assertEquals("Should fail to parse currency", 0, ppos.getIndex());
+ }
+}
+
+
void
NumberFormatTest::TestDecimalFormatCurrencyParse() {
// Locale.US
{"USD1,234.56", "1234.56"},
{"1,234.56 US dollar", "1234.56"},
};
- for (uint32_t i = 0; i < sizeof(DATA)/sizeof(DATA[0]); ++i) {
+ // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
+ fmt->setLenient(TRUE);
+ for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
UnicodeString stringToBeParsed = ctou(DATA[i][0]);
double parsedResult = atof(DATA[i][1]);
UErrorCode status = U_ZERO_ERROR;
Formattable result;
fmt->parse(stringToBeParsed, result, status);
+ logln((UnicodeString)"Input: " + stringToBeParsed + "; output: " + result.getDouble(status));
if (U_FAILURE(status) ||
(result.getType() == Formattable::kDouble &&
result.getDouble() != parsedResult) ||
{"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollars"},
{"en_US", "1234.56", "USD", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"},
{"en_US", "-1234.56", "USD", "-$1,234.56", "-USD1,234.56", "-1,234.56 US dollars"},
- {"zh_CN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00\\u7F8E\\u5143"},
- {"zh_CN", "1234.56", "USD", "US$\\u00A01,234.56", "USD\\u00A01,234.56", "1,234.56\\u7F8E\\u5143"},
- // wrong ISO code {"zh_CN", "1", "CHY", "CHY1.00", "CHY1.00", "1.00 CHY"},
- // wrong ISO code {"zh_CN", "1234.56", "CHY", "CHY1,234.56", "CHY1,234.56", "1,234.56 CHY"},
- {"zh_CN", "1", "CNY", "\\uFFE5\\u00A01.00", "CNY\\u00A01.00", "1.00\\u4EBA\\u6C11\\u5E01"},
- {"zh_CN", "1234.56", "CNY", "\\uFFE5\\u00A01,234.56", "CNY\\u00A01,234.56", "1,234.56\\u4EBA\\u6C11\\u5E01"},
+ {"zh_CN", "1", "USD", "US$1.00", "USD1.00", "1.00\\u7F8E\\u5143"},
+ {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD1,234.56", "1,234.56\\u7F8E\\u5143"},
+ {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY1.00", "1.00\\u4EBA\\u6C11\\u5E01"},
+ {"zh_CN", "1234.56", "CNY", "\\u00A51,234.56", "CNY1,234.56", "1,234.56\\u4EBA\\u6C11\\u5E01"},
{"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"},
{"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"},
{"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"},
// test locale without currency information
{"root", "-1.23", "USD", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"},
// test choice format
- {"es_AR", "1", "INR", "INR1,00", "INR1,00", "1,00 rupia india"},
+ {"es_AR", "1", "INR", "INR\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"},
};
static const UNumberFormatStyle currencyStyles[] = {
UNUM_CURRENCY,
};
for (int32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
+ const char* localeString = DATA[i][0];
+ double numberToBeFormat = atof(DATA[i][1]);
+ const char* currencyISOCode = DATA[i][2];
+ logln(UnicodeString(u"Locale: ") + localeString + "; amount: " + numberToBeFormat);
+ Locale locale(localeString);
for (int32_t kIndex = 0; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
UNumberFormatStyle k = currencyStyles[kIndex];
- const char* localeString = DATA[i][0];
- double numberToBeFormat = atof(DATA[i][1]);
- const char* currencyISOCode = DATA[i][2];
- Locale locale(localeString);
+ logln(UnicodeString(u"UNumberFormatStyle: ") + k);
UErrorCode status = U_ZERO_ERROR;
NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
if (U_FAILURE(status)) {
errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
}
// test parsing, and test parsing for all currency formats.
+ // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
+ numFmt->setLenient(TRUE);
for (int j = 3; j < 6; ++j) {
// DATA[i][3] is the currency format result using
// CURRENCYSTYLE formatter.
// format result using CURRENCYSTYLE,
// format result using ISOCURRENCYSTYLE,
// format result using PLURALCURRENCYSTYLE,
- {"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollar"},
+ {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
{"pa_IN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\u0a2f\\u0a42.\\u0a10\\u0a38. \\u0a21\\u0a3e\\u0a32\\u0a30"},
- {"es_AR", "1", "USD", "US$1,00", "USD1,00", "1,00 d\\u00f3lar estadounidense"},
+ {"es_AR", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 d\\u00f3lar estadounidense"},
{"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"},
- {"fa_CA", "1", "USD", "\\u200e$\\u06f1\\u066b\\u06f0\\u06f0", "\\u200eUSD\\u06f1\\u066b\\u06f0\\u06f0", "\\u200e\\u062f\\u0644\\u0627\\u0631 \\u0627\\u0645\\u0631\\u06cc\\u06a9\\u0627\\u06f1\\u066b\\u06f0\\u06f0"},
- {"he_IL", "1", "USD", "1.00\\u00a0$", "1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
- {"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 Ameri\\u010dki dolar"},
- {"id_ID", "1", "USD", "US$1,00", "USD1,00", "1,00 Dolar Amerika Serikat"},
- {"it_IT", "1", "USD", "1,00\\u00a0US$", "1,00\\u00a0USD", "1,00 Dollaro Statunitense"},
- {"ko_KR", "1", "USD", "US$1.00", "USD1.00", "1.00\\ubbf8\\uad6d \\ub2ec\\ub7ec"},
- {"ja_JP", "1", "USD", "$1.00", "USD1.00", "1.00\\u7c73\\u30c9\\u30eb"},
- {"zh_CN", "1", "CNY", "\\uFFE5\\u00a01.00", "CNY\\u00a01.00", "1.00\\u4EBA\\u6C11\\u5E01"},
- {"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY1.00", "1.00 \\u4eba\\u6c11\\u5e63"},
- {"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY1.00", "1.00 \\u4eba\\u6c11\\u5e63"},
- {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY1.00", "1.00 \\u65e5\\u5713"},
- {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY1.00", "1.00\\u65e5\\u672c\\u5186"},
- {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY1.00", "1.00\\u65e5\\u672c\\u5186"},
- {"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0420\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0439 \\u0440\\u0443\\u0431\\u043B\\u044C"}
+ {"fa_CA", "1", "USD", "\\u200e$\\u06f1\\u066b\\u06f0\\u06f0", "\\u200eUSD\\u06f1\\u066b\\u06f0\\u06f0", "\\u06f1\\u066b\\u06f0\\u06f0 \\u062f\\u0644\\u0627\\u0631 \\u0627\\u0645\\u0631\\u06cc\\u06a9\\u0627"},
+ {"he_IL", "1", "USD", "\\u200f1.00\\u00a0$", "\\u200f1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
+ {"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 ameri\\u010Dkih dolara"},
+ {"id_ID", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 Dolar Amerika Serikat"},
+ {"it_IT", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 dollari statunitensi"},
+ {"ko_KR", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
+ {"ja_JP", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00\\u7c73\\u30c9\\u30eb"},
+ {"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY\\u00A001.00", "1.00\\u4EBA\\u6C11\\u5E01"},
+ {"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
+ {"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
+ {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1 \\u65E5\\u5713"},
+ {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY\\u00A01.00", "1\\u5186"},
+ // ICU 62 requires #parseCurrency() to recognize variants when parsing
+ // {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
+ {"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"}
};
static const UNumberFormatStyle currencyStyles[] = {
UNUM_CURRENCY,
for (;;) {
printf("loop: %d\n", deadloop++);
#endif
- for (uint32_t i=0; i< sizeof(DATA)/sizeof(DATA[0]); ++i) { /* i = test case # - should be i=0*/
+ for (uint32_t i=0; i< UPRV_LENGTHOF(DATA); ++i) { /* i = test case # - should be i=0*/
for (int32_t kIndex = 2; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
UNumberFormatStyle k = currencyStyles[kIndex]; /* k = style */
const char* localeString = DATA[i][0];
UErrorCode status = U_ZERO_ERROR;
NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
logln("#%d NumberFormat(%s, %s) Currency=%s\n",
- i, localeString, currencyStyleNames[kIndex],
+ i, localeString, currencyStyleNames[kIndex],
currencyISOCode);
if (U_FAILURE(status)) {
UnicodeString strBuf;
numFmt->format(numberToBeFormat, strBuf);
- /*
int resultDataIndex = 3 + kIndex;
// DATA[i][resultDataIndex] is the currency format result
// using 'k' currency style.
if (strBuf.compare(formatResult)) {
errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
}
- */
// test parsing, and test parsing for all currency formats.
+ // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
+ numFmt->setLenient(TRUE);
for (int j = 3; j < 6; ++j) {
// DATA[i][3] is the currency format result using
// CURRENCYSTYLE formatter.
"Barbadian Dollar1.00",
"Barbadian dollar1.00",
"Barbadian dollars1.00",
- "Belarusian New Ruble (1994\\u20131999)1.00",
+ "Belarusian Ruble (1994\\u20131999)1.00",
"Belarusian Ruble1.00",
- "Belarusian new ruble (1994\\u20131999)1.00",
- "Belarusian new rubles (1994\\u20131999)1.00",
+ "Belarusian ruble (1994\\u20131999)1.00",
+ "Belarusian rubles (1994\\u20131999)1.00",
"Belarusian ruble1.00",
"Belarusian rubles1.00",
"Belgian Franc (convertible)1.00",
"Cypriot Pound1.00",
"Cypriot pound1.00",
"Cypriot pounds1.00",
- "Czech Republic Koruna1.00",
- "Czech Republic koruna1.00",
- "Czech Republic korunas1.00",
+ "Czech Koruna1.00",
+ "Czech koruna1.00",
+ "Czech korunas1.00",
"Czechoslovak Hard Koruna1.00",
"Czechoslovak hard koruna1.00",
"Czechoslovak hard korunas1.00",
"Irish pound1.00",
"Irish pounds1.00",
"Israeli Pound1.00",
- "Israeli new sheqel1.00",
+ "Israeli new shekel1.00",
"Israeli pound1.00",
"Israeli pounds1.00",
"Italian Lira1.00",
"Dutch Guilder1.00",
"Dutch guilder1.00",
"Dutch guilders1.00",
- "Israeli New Sheqel1.00",
- "Israeli New Sheqels1.00",
+ "Israeli New Shekel1.00",
+ "Israeli New Shekels1.00",
"New Zealand Dollar1.00",
"New Zealand dollar1.00",
"New Zealand dollars1.00",
"Paraguayan guarani1.00",
"Paraguayan guaranis1.00",
"Peruvian Inti1.00",
- "Peruvian Nuevo Sol1.00",
+ "Peruvian Sol1.00",
"Peruvian Sol (1863\\u20131965)1.00",
"Peruvian inti1.00",
"Peruvian intis1.00",
- "Peruvian nuevo sol1.00",
- "Peruvian nuevos soles1.00",
+ "Peruvian sol1.00",
+ "Peruvian soles1.00",
"Peruvian sol (1863\\u20131965)1.00",
"Peruvian soles (1863\\u20131965)1.00",
- "Philippine Peso1.00",
- "Philippine peso1.00",
- "Philippine pesos1.00",
+ "Philippine Piso1.00",
+ "Philippine piso1.00",
+ "Philippine pisos1.00",
"Platinum1.00",
"Platinum1.00",
"Polish Zloty (1950\\u20131995)1.00",
"RSD1.00",
"RSD1.00",
"RUB1.00",
- "RUB1.00",
"RUR1.00",
"RUR1.00",
"RWF1.00",
"1.00 Barbadian Dollar random",
"1.00 Barbadian dollar random",
"1.00 Barbadian dollars random",
- "1.00 Belarusian New Ruble (1994\\u20131999) random",
+ "1.00 Belarusian Ruble (1994\\u20131999) random",
"1.00 Belarusian Ruble random",
- "1.00 Belarusian new ruble (1994\\u20131999) random",
- "1.00 Belarusian new rubles (1994\\u20131999) random",
+ "1.00 Belarusian ruble (1994\\u20131999) random",
+ "1.00 Belarusian rubles (1994\\u20131999) random",
"1.00 Belarusian ruble random",
"1.00 Belarusian rubles random",
"1.00 Belgian Franc (convertible) random",
"1.00 Cypriot Pound random",
"1.00 Cypriot pound random",
"1.00 Cypriot pounds random",
- "1.00 Czech Republic Koruna random",
- "1.00 Czech Republic koruna random",
- "1.00 Czech Republic korunas random",
+ "1.00 Czech Koruna random",
+ "1.00 Czech koruna random",
+ "1.00 Czech korunas random",
"1.00 Czechoslovak Hard Koruna random",
"1.00 Czechoslovak hard koruna random",
"1.00 Czechoslovak hard korunas random",
"1.00 Irish pound random",
"1.00 Irish pounds random",
"1.00 Israeli Pound random",
- "1.00 Israeli new sheqel random",
+ "1.00 Israeli new shekel random",
"1.00 Israeli pound random",
"1.00 Israeli pounds random",
"1.00 Italian Lira random",
"1.00 Dutch Guilder random",
"1.00 Dutch guilder random",
"1.00 Dutch guilders random",
- "1.00 Israeli New Sheqel random",
- "1.00 Israeli new sheqels random",
+ "1.00 Israeli New Shekel random",
+ "1.00 Israeli new shekels random",
"1.00 New Zealand Dollar random",
"1.00 New Zealand dollar random",
"1.00 New Zealand dollars random",
"1.00 Paraguayan guarani random",
"1.00 Paraguayan guaranis random",
"1.00 Peruvian Inti random",
- "1.00 Peruvian Nuevo Sol random",
+ "1.00 Peruvian Sol random",
"1.00 Peruvian Sol (1863\\u20131965) random",
"1.00 Peruvian inti random",
"1.00 Peruvian intis random",
- "1.00 Peruvian nuevo sol random",
- "1.00 Peruvian nuevos soles random",
+ "1.00 Peruvian sol random",
+ "1.00 Peruvian soles random",
"1.00 Peruvian sol (1863\\u20131965) random",
"1.00 Peruvian soles (1863\\u20131965) random",
- "1.00 Philippine Peso random",
- "1.00 Philippine peso random",
- "1.00 Philippine pesos random",
+ "1.00 Philippine Piso random",
+ "1.00 Philippine piso random",
+ "1.00 Philippine pisos random",
"1.00 Platinum random",
"1.00 Platinum random",
"1.00 Polish Zloty (1950\\u20131995) random",
"Bangladeshi Tak1.00",
"Barbadian Dolla1.00",
"Bds1.00",
- "Belarusian New Ruble (1994\\u201319991.00",
+ "Belarusian Ruble (1994\\u201319991.00",
"Belarusian Rubl1.00",
"Belgian Fran1.00",
"Belgian Franc (convertible1.00",
};
Locale locale("en_US");
- for (uint32_t i=0; i<sizeof(DATA)/sizeof(DATA[0]); ++i) {
- UnicodeString formatted = ctou(DATA[i]);
- UErrorCode status = U_ZERO_ERROR;
- NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
- if (numFmt != NULL && U_SUCCESS(status)) {
- ParsePosition parsePos;
- LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
- if (parsePos.getIndex() > 0) {
- double doubleVal = currAmt->getNumber().getDouble(status);
- if ( doubleVal != 1.0 ) {
- errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
- }
- } else {
- errln("Failed to parse as currency: " + formatted);
- }
- } else {
- dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));
- delete numFmt;
- break;
- }
- delete numFmt;
+ for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
+ UnicodeString formatted = ctou(DATA[i]);
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> numFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) {
+ return;
+ }
+ // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
+ numFmt->setLenient(TRUE);
+ ParsePosition parsePos;
+ LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
+ if (parsePos.getIndex() > 0) {
+ double doubleVal = currAmt->getNumber().getDouble(status);
+ if ( doubleVal != 1.0 ) {
+ errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
+ }
+ } else {
+ errln("Failed to parse as currency: " + formatted);
+ }
}
- for (uint32_t i=0; i<sizeof(WRONG_DATA)/sizeof(WRONG_DATA[0]); ++i) {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(WRONG_DATA); ++i) {
UnicodeString formatted = ctou(WRONG_DATA[i]);
UErrorCode status = U_ZERO_ERROR;
NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
if (failure(status, "NumberFormat::createInstance", TRUE)) return;
double val = 12345.67;
-
+
{
int32_t expected[] = {
UNUM_CURRENCY_FIELD, 0, 1,
UNUM_DECIMAL_SEPARATOR_FIELD, 7, 8,
UNUM_FRACTION_FIELD, 8, 10,
};
- int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+ int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
FieldPositionIterator posIter;
UnicodeString result;
UNUM_EXPONENT_SIGN_FIELD, 6, 7,
UNUM_EXPONENT_FIELD, 7, 8
};
- int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+ int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
FieldPositionIterator posIter;
UnicodeString result;
//
// Test formatting & parsing of big decimals.
-// API test, not a comprehensive test.
+// API test, not a comprehensive test.
// See DecimalFormatTest/DataDrivenTests
//
-#define ASSERT_SUCCESS(status) {if (U_FAILURE(status)) errln("file %s, line %d: status: %s", \
- __FILE__, __LINE__, u_errorName(status));}
-#define ASSERT_EQUALS(expected, actual) {if ((expected) != (actual)) \
- errln("file %s, line %d: %s != %s", __FILE__, __LINE__, #expected, #actual);}
-
-static UBool operator != (const char *s1, UnicodeString &s2) {
- // This function lets ASSERT_EQUALS("literal", UnicodeString) work.
- UnicodeString us1(s1);
- return us1 != s2;
+#define ASSERT_SUCCESS(status) { \
+ assertSuccess(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (status)); \
+}
+#define ASSERT_EQUALS(expected, actual) { \
+ assertEquals(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (expected), (actual)); \
}
void NumberFormatTest::TestDecimal() {
ASSERT_SUCCESS(status);
StringPiece s = f.getDecimalNumber(status);
ASSERT_SUCCESS(status);
- ASSERT_EQUALS("1.2345678999987654321E+667", s);
+ ASSERT_EQUALS("1.2345678999987654321E+667", s.data());
//printf("%s\n", s.data());
}
ASSERT_EQUALS(123.45, f.getDouble());
ASSERT_EQUALS(123.45, f.getDouble(status));
ASSERT_SUCCESS(status);
- ASSERT_EQUALS("123.45", f.getDecimalNumber(status));
+ ASSERT_EQUALS("123.45", f.getDecimalNumber(status).data());
ASSERT_SUCCESS(status);
f.setDecimalNumber("4.5678E7", status);
ASSERT_EQUALS(-123, f.getLong());
ASSERT_EQUALS(-123, f.getLong(status));
ASSERT_SUCCESS(status);
- ASSERT_EQUALS("-123", f.getDecimalNumber(status));
+ ASSERT_EQUALS("-123", f.getDecimalNumber(status).data());
ASSERT_SUCCESS(status);
status = U_ZERO_ERROR;
ASSERT_EQUALS(1234567890123LL, f.getInt64());
ASSERT_EQUALS(1234567890123LL, f.getInt64(status));
ASSERT_SUCCESS(status);
- ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status));
+ ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status).data());
ASSERT_SUCCESS(status);
}
Formattable result;
fmtr->parse(input, result, status);
ASSERT_SUCCESS(status);
- ASSERT_EQUALS(0, strcmp("0.0184", result.getDecimalNumber(status).data()));
+ ASSERT_EQUALS("0.0184", result.getDecimalNumber(status).data());
//std::cout << result.getDecimalNumber(status).data();
delete fmtr;
}
}
-
+
#if U_PLATFORM != U_PF_CYGWIN || defined(CYGWINMSVC)
/*
* This test fails on Cygwin (1.7.16) using GCC because of a rounding issue with strtod().
errln((UnicodeString)"NumberFormat::format() should return the same result - text1="
+ text1 + " text2=" + text2);
}
- delete fmt;
}
+ delete fmt;
}
-void NumberFormatTest::TestExponentParse() {
-
- UErrorCode status = U_ZERO_ERROR;
- Formattable result;
- ParsePosition parsePos(0);
-
- // set the exponent symbol
- status = U_ZERO_ERROR;
- DecimalFormatSymbols *symbols = new DecimalFormatSymbols(Locale::getDefault(), status);
- if(U_FAILURE(status)) {
- dataerrln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (Default)");
- return;
- }
-
- // create format instance
- status = U_ZERO_ERROR;
- DecimalFormat fmt("#####", symbols, status);
- if(U_FAILURE(status)) {
- errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
- }
-
- // parse the text
- fmt.parse("5.06e-27", result, parsePos);
- if(result.getType() != Formattable::kDouble &&
- result.getDouble() != 5.06E-27 &&
- parsePos.getIndex() != 8
- )
- {
- errln("ERROR: parse failed - expected 5.06E-27, 8 - returned %d, %i",
- result.getDouble(), parsePos.getIndex());
- }
-}
+void NumberFormatTest::TestExponentParse() {
+
+ UErrorCode status = U_ZERO_ERROR;
+ Formattable result;
+ ParsePosition parsePos(0);
+
+ // set the exponent symbol
+ status = U_ZERO_ERROR;
+ DecimalFormatSymbols symbols(Locale::getDefault(), status);
+ if(U_FAILURE(status)) {
+ dataerrln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (Default)");
+ return;
+ }
+
+ // create format instance
+ status = U_ZERO_ERROR;
+ DecimalFormat fmt(u"#####", symbols, status);
+ if(U_FAILURE(status)) {
+ errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
+ }
+
+ // parse the text
+ fmt.parse("5.06e-27", result, parsePos);
+ if(result.getType() != Formattable::kDouble &&
+ result.getDouble() != 5.06E-27 &&
+ parsePos.getIndex() != 8
+ )
+ {
+ errln("ERROR: parse failed - expected 5.06E-27, 8 - returned %d, %i",
+ result.getDouble(), parsePos.getIndex());
+ }
+}
void NumberFormatTest::TestExplicitParents() {
static const char* parentLocaleTests[][2]= {
/* locale ID */ /* expected */
{"es_CO", "1.250,75" },
- {"es_CR", "1.250,75" },
{"es_ES", "1.250,75" },
{"es_GQ", "1.250,75" },
{"es_MX", "1,250.75" },
UnicodeString s;
- for(int i=0; i < (int)(sizeof(parentLocaleTests)/sizeof(parentLocaleTests[i])); i++){
+ for(int i=0; i < UPRV_LENGTHOF(parentLocaleTests); i++){
UErrorCode status = U_ZERO_ERROR;
const char *localeID = parentLocaleTests[i][0];
UnicodeString expected(parentLocaleTests[i][1], -1, US_INV);
CHECK_DATA(status, "NumberingSystem::getAvailableNames()")
int32_t nsCount = availableNumberingSystems->count(status);
- if ( nsCount < 36 ) {
- errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 36, got %d",nsCount);
+ if ( nsCount < 74 ) {
+ errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 74, got %d",nsCount);
}
/* A relatively simple test of the API. We call getAvailableNames() and cycle through */
for ( int32_t i = 0 ; i < nsCount ; i++ ) {
const char *nsname = availableNumberingSystems->next(&len,status);
NumberingSystem* ns = NumberingSystem::createInstanceByName(nsname,status);
+ logln("OK for ns = %s",nsname);
if ( uprv_strcmp(nsname,ns->getName()) ) {
errln("FAIL: Numbering system name didn't match for name = %s\n",nsname);
}
{
U_STRING_DECL(pattern,"#",1);
U_STRING_INIT(pattern,"#",1);
-
+
U_STRING_DECL(infstr,"INF",3);
U_STRING_INIT(infstr,"INF",3);
U_STRING_DECL(nanstr,"NAN",3);
U_STRING_INIT(nanstr,"NAN",3);
-
+
UChar outputbuf[50] = {0};
UErrorCode status = U_ZERO_ERROR;
UNumberFormat* fmt = unum_open(UNUM_PATTERN_DECIMAL,pattern,1,NULL,NULL,&status);
UFieldPosition position = { 0, 0, 0};
unum_formatDouble(fmt,inf,outputbuf,50,&position,&status);
-
+
if ( u_strcmp(infstr, outputbuf)) {
errln((UnicodeString)"FAIL: unexpected result for infinity - expected " + infstr + " got " + outputbuf);
}
unum_close(fmt);
}
-#include "dcfmtimp.h"
-
void NumberFormatTest::TestFormatFastpaths() {
-#if UCONFIG_FORMAT_FASTPATHS_49
- logln("Sizeof DecimalFormat = %d, Sizeof DecimalFormatInternal=%d, UNUM_DECIMALFORMAT_INTERNAL_SIZE=%d\n",
- sizeof(DecimalFormat), sizeof(DecimalFormatInternal), UNUM_DECIMALFORMAT_INTERNAL_SIZE);
- if(UNUM_DECIMALFORMAT_INTERNAL_SIZE < sizeof(DecimalFormatInternal)) {
- errln("Error: sizeof(DecimalFormatInternal)=%d but UNUM_DECIMALFORMAT_INTERNAL_SIZE is only %d. Increase the #define?\n", sizeof(DecimalFormatInternal), UNUM_DECIMALFORMAT_INTERNAL_SIZE);
- } else if(UNUM_DECIMALFORMAT_INTERNAL_SIZE > (sizeof(DecimalFormatInternal)+16)) {
- infoln("Note: sizeof(DecimalFormatInternal)=%d but UNUM_DECIMALFORMAT_INTERNAL_SIZE is %d. Decrease the #define? sizeof(DecimalFormat)=%d\n", sizeof(DecimalFormatInternal), UNUM_DECIMALFORMAT_INTERNAL_SIZE, sizeof(DecimalFormat));
- }
-#else
- infoln("NOTE: UCONFIG_FORMAT_FASTPATHS not set, test skipped.");
-#endif
-
// get some additional case
{
UErrorCode status=U_ZERO_ERROR;
- DecimalFormat df(UnicodeString("0000",""),status);
- int64_t long_number = 1;
- UnicodeString expect = "0001";
- UnicodeString result;
- FieldPosition pos;
- df.format(long_number, result, pos);
- if(U_FAILURE(status)||expect!=result) {
- errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),""));
+ DecimalFormat df(UnicodeString(u"0000"),status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
} else {
- logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
+ int64_t long_number = 1;
+ UnicodeString expect = "0001";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s",
+ __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
+ }
}
}
{
UErrorCode status=U_ZERO_ERROR;
- DecimalFormat df(UnicodeString("0000000000000000000",""),status);
- int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
- // uint8_t bits[8];
- // memcpy(bits,&long_number,8);
- // for(int i=0;i<8;i++) {
- // logln("bits: %02X", (unsigned int)bits[i]);
- // }
- UnicodeString expect = "-9223372036854775808";
- UnicodeString result;
- FieldPosition pos;
- df.format(long_number, result, pos);
- if(U_FAILURE(status)||expect!=result) {
- errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
+ DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
} else {
- logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
+ int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
+ // uint8_t bits[8];
+ // memcpy(bits,&long_number,8);
+ // for(int i=0;i<8;i++) {
+ // logln("bits: %02X", (unsigned int)bits[i]);
+ // }
+ UnicodeString expect = "-9223372036854775808";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775808",
+ __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
+ }
}
}
{
UErrorCode status=U_ZERO_ERROR;
- DecimalFormat df(UnicodeString("0000000000000000000",""),status);
- int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
- // uint8_t bits[8];
- // memcpy(bits,&long_number,8);
- // for(int i=0;i<8;i++) {
- // logln("bits: %02X", (unsigned int)bits[i]);
- // }
- UnicodeString expect = "9223372036854775807";
- UnicodeString result;
- FieldPosition pos;
- df.format(long_number, result, pos);
- if(U_FAILURE(status)||expect!=result) {
- errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
+ DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
} else {
- logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
+ int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
+ // uint8_t bits[8];
+ // memcpy(bits,&long_number,8);
+ // for(int i=0;i<8;i++) {
+ // logln("bits: %02X", (unsigned int)bits[i]);
+ // }
+ UnicodeString expect = "9223372036854775807";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on U_INT64_MAX",
+ __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
+ }
}
}
{
UErrorCode status=U_ZERO_ERROR;
DecimalFormat df(UnicodeString("0000000000000000000",""),status);
- int64_t long_number = 0;
- // uint8_t bits[8];
- // memcpy(bits,&long_number,8);
- // for(int i=0;i<8;i++) {
- // logln("bits: %02X", (unsigned int)bits[i]);
- // }
- UnicodeString expect = "0000000000000000000";
- UnicodeString result;
- FieldPosition pos;
- df.format(long_number, result, pos);
- if(U_FAILURE(status)||expect!=result) {
- errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
} else {
- logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
+ int64_t long_number = 0;
+ // uint8_t bits[8];
+ // memcpy(bits,&long_number,8);
+ // for(int i=0;i<8;i++) {
+ // logln("bits: %02X", (unsigned int)bits[i]);
+ // }
+ UnicodeString expect = "0000000000000000000";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on 0",
+ __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
+ }
}
}
{
UErrorCode status=U_ZERO_ERROR;
DecimalFormat df(UnicodeString("0000000000000000000",""),status);
- int64_t long_number = U_INT64_MIN + 1;
- UnicodeString expect = "-9223372036854775807";
- UnicodeString result;
- FieldPosition pos;
- df.format(long_number, result, pos);
- if(U_FAILURE(status)||expect!=result) {
- errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
} else {
- logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
+ int64_t long_number = U_INT64_MIN + 1;
+ UnicodeString expect = "-9223372036854775807";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775807",
+ __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
+ }
}
}
}
-void NumberFormatTest::TestFormattableSize(void) {
+void NumberFormatTest::TestFormattableSize(void) { // test ICU 61 behavior
if(sizeof(FmtStackData) > UNUM_INTERNAL_STACKARRAY_SIZE) {
errln("Error: sizeof(FmtStackData)=%d, UNUM_INTERNAL_STACKARRAY_SIZE=%d\n",
sizeof(FmtStackData), UNUM_INTERNAL_STACKARRAY_SIZE);
logln("Warning: sizeof(FmtStackData)=%d, UNUM_INTERNAL_STACKARRAY_SIZE=%d\n",
sizeof(FmtStackData), UNUM_INTERNAL_STACKARRAY_SIZE);
} else {
- logln("sizeof(FmtStackData)=%d, UNUM_INTERNAL_STACKARRAY_SIZE=%d\n",
- sizeof(FmtStackData), UNUM_INTERNAL_STACKARRAY_SIZE);
+ logln("sizeof(Formattable)=%d, 112=%d\n",
+ sizeof(Formattable), 112);
}
}
UErrorCode int64ConversionU = U_ZERO_ERROR;
int64_t r = ufmt_getInt64(u, &int64ConversionU);
- if( (l==r)
+ if( (l==r)
&& ( uType != UFMT_INT64 ) // int64 better not overflow
- && (U_INVALID_FORMAT_ERROR==int64ConversionU)
+ && (U_INVALID_FORMAT_ERROR==int64ConversionU)
&& (U_INVALID_FORMAT_ERROR==int64ConversionF) ) {
logln("%s:%d: OK: 64 bit overflow", file, line);
} else {
numberFormat->setMinimumSignificantDigits(3);
numberFormat->setMaximumSignificantDigits(5);
numberFormat->setGroupingUsed(false);
-
+
UnicodeString result;
UnicodeString expectedResult;
- for (unsigned int i = 0; i < sizeof(input)/sizeof(double); ++i) {
+ for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
numberFormat->format(input[i], result);
UnicodeString expectedResult(expected[i]);
if (result != expectedResult) {
numberFormat->setSignificantDigitsUsed(TRUE);
numberFormat->setMaximumSignificantDigits(3);
-
+
UnicodeString result;
numberFormat->format(0.0, result);
if (result != "0") {
dataerrln("File %s, Line %d: status = %s.\n", __FILE__, __LINE__, u_errorName(status));
return;
}
-
+
if (numberFormat->areSignificantDigitsUsed() == TRUE) {
errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
}
if (numberFormat->areSignificantDigitsUsed() == FALSE) {
errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
}
-
+
}
void NumberFormatTest::TestParseNegativeWithFaLocale() {
{ "en@numbers=arabext", FALSE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
{ "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
{ "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
-
+
{ "he", FALSE, CharsToUnicodeString("12"), 12 },
{ "he", TRUE, CharsToUnicodeString("12"), 12 },
{ "he", FALSE, CharsToUnicodeString("-23"), -23 },
dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
return;
}
- for (int32_t i = 0; i < (int32_t) (sizeof(items) / sizeof(items[0])); ++i) {
+ for (int32_t i = 0; i < UPRV_LENGTHOF(items); ++i) {
decfmt->setRoundingMode(items[i].mode);
decfmt->setMaximumFractionDigits(0);
UnicodeString actual;
return;
}
- if (fmt.getPadCharacterString() != UnicodeString("a")) {
- errln("Padding character should be 'a'.");
- return;
- }
+ assertEquals("Padding character should be 'a'.", u"a", fmt.getPadCharacterString());
// Padding char of fmt ought to be '*' since that is the default and no
// explicit padding char is specified in the new pattern.
fmt.applyPattern("AA#,##0.00ZZ", status);
- // Oops this still prints 'a' even though we changed the pattern.
- if (fmt.getPadCharacterString() != UnicodeString("*")) {
- errln("applyPattern did not clear padding character.");
- }
+ // Oops this still prints 'a' even though we changed the pattern.
+ assertEquals("applyPattern did not clear padding character.", u" ", fmt.getPadCharacterString());
}
void NumberFormatTest::TestRoundingScientific10542() {
errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
return;
}
-
+
DecimalFormat::ERoundingMode roundingModes[] = {
DecimalFormat::kRoundCeiling,
DecimalFormat::kRoundDown,
"Round half even",
"Round half up",
"Round up"};
-
+
{
double values[] = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016};
// The order of these expected values correspond to the order of roundingModes and the order of values.
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
{
double values[] = {-3006.0, -3005, -3004, 3014, 3015, 3016};
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
/* Commented out for now until we decide how rounding to zero should work, +0 vs. -0
{
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
*/
{
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
{
double values[] = {-1e25, -1e25 + 1e15, -1e25 - 1e15};
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
{
double values[] = {1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
{
double values[] = {-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
}
void NumberFormatTest::TestZeroScientific10547() {
UErrorCode status = U_ZERO_ERROR;
DecimalFormat fmt("0.00E0", status);
- if (!assertSuccess("Formt creation", status)) {
+ if (!assertSuccess("Format creation", status)) {
return;
}
UnicodeString out;
fmt.format(-0.0, out);
- assertEquals("format", "-0.00E0", out);
+ assertEquals("format", "-0.00E0", out, true);
}
void NumberFormatTest::verifyRounding(
UnicodeString actual;
format.format(values[j], actual);
if (currentExpected != actual) {
- char buffer[256];
- sprintf(
- buffer,
- "For %s value %f, expected ",
- descriptions[i],
- values[j]);
- errln(UnicodeString(buffer) + currentExpected + ", got " + actual);
+ dataerrln("For %s value %f, expected '%s', got '%s'",
+ descriptions[i], values[j], CStr(currentExpected)(), CStr(actual)());
}
}
}
UNumberFormatStyle style = UNUM_CURRENCY_ACCOUNTING;
expect(NumberFormat::createInstance("en_US", style, status),
- (Formattable)1234.5, "$1,234.50", TRUE, status);
+ (Formattable)(double)1234.5, "$1,234.50", TRUE, status);
expect(NumberFormat::createInstance("en_US", style, status),
- (Formattable)-1234.5, "($1,234.50)", TRUE, status);
+ (Formattable)(double)-1234.5, "($1,234.50)", TRUE, status);
expect(NumberFormat::createInstance("en_US", style, status),
- (Formattable)0, "$0.00", TRUE, status);
+ (Formattable)(double)0, "$0.00", TRUE, status);
expect(NumberFormat::createInstance("en_US", style, status),
- (Formattable)-0.2, "($0.20)", TRUE, status);
+ (Formattable)(double)-0.2, "($0.20)", TRUE, status);
expect(NumberFormat::createInstance("ja_JP", style, status),
(Formattable)10000, UnicodeString("\\u00A510,000").unescape(), TRUE, status);
expect(NumberFormat::createInstance("ja_JP", style, status),
(Formattable)-1000.5, UnicodeString("(\\u00A51,000)").unescape(), FALSE, status);
expect(NumberFormat::createInstance("de_DE", style, status),
- (Formattable)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status);
+ (Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status);
}
// for #5186
void NumberFormatTest::TestEquality() {
UErrorCode status = U_ZERO_ERROR;
- DecimalFormatSymbols* symbols = new DecimalFormatSymbols(Locale("root"), status);
+ DecimalFormatSymbols symbols(Locale("root"), status);
if (U_FAILURE(status)) {
dataerrln("Fail: can't create DecimalFormatSymbols for root");
return;
}
UnicodeString pattern("#,##0.###");
- DecimalFormat* fmtBase = new DecimalFormat(pattern, symbols, status);
+ DecimalFormat fmtBase(pattern, symbols, status);
if (U_FAILURE(status)) {
dataerrln("Fail: can't create DecimalFormat using root symbols");
return;
}
- DecimalFormat* fmtClone = (DecimalFormat*)fmtBase->clone();
- fmtClone->setFormatWidth(fmtBase->getFormatWidth() + 32);
- if (*fmtClone == *fmtBase) {
+ DecimalFormat* fmtClone = (DecimalFormat*)fmtBase.clone();
+ fmtClone->setFormatWidth(fmtBase.getFormatWidth() + 32);
+ if (*fmtClone == fmtBase) {
errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth");
}
delete fmtClone;
-
- delete fmtBase;
}
void NumberFormatTest::TestCurrencyUsage() {
// compare the Currency and Currency Cash Digits
// Note that as of CLDR 26:
// * TWD switches from 0 decimals to 2; PKR still has 0, so change test to that
- // * CAD and all other currencies that rounded to .05 no longer do
+ // * CAD rounds to .05 in cash mode only
// 1st time for getter/setter, 2nd time for factory method
Locale enUS_PKR("en_US@currency=PKR");
UnicodeString original;
fmt->format(agent,original);
- assertEquals("Test Currency Usage 1", UnicodeString("PKR124"), original);
+ assertEquals("Test Currency Usage 1", u"PKR124", original); // use ICU 61 behavior
// test the getter here
UCurrencyUsage curUsage = fmt->getCurrencyUsage();
- assertEquals("Test usage getter - standard", curUsage, UCURR_USAGE_STANDARD);
+ assertEquals("Test usage getter - standard", (int32_t)curUsage, (int32_t)UCURR_USAGE_STANDARD);
fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
}else{
// must be usage = cash
UCurrencyUsage curUsage = fmt->getCurrencyUsage();
- assertEquals("Test usage getter - cash", curUsage, UCURR_USAGE_CASH);
+ assertEquals("Test usage getter - cash", (int32_t)curUsage, (int32_t)UCURR_USAGE_CASH);
UnicodeString cash_currency;
fmt->format(agent,cash_currency);
- assertEquals("Test Currency Usage 2", UnicodeString("PKR124"), cash_currency);
+ assertEquals("Test Currency Usage 2", u"PKR124", cash_currency); // use ICU 61 behavior
delete fmt;
}
UnicodeString original_rounding;
fmt->format(agent, original_rounding);
- assertEquals("Test Currency Usage 3", UnicodeString("CA$123.57"), original_rounding);
+ assertEquals("Test Currency Usage 3", u"CA$123.57", original_rounding);
fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
}else{
- fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
+ fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
continue;
}
UnicodeString cash_rounding_currency;
fmt->format(agent, cash_rounding_currency);
- assertEquals("Test Currency Usage 4", UnicodeString("CA$123.57"), cash_rounding_currency);
+ assertEquals("Test Currency Usage 4", u"CA$123.55", cash_rounding_currency);
delete fmt;
}
}
UnicodeString cur_original;
+ fmt->setCurrencyUsage(UCURR_USAGE_STANDARD, &status);
fmt->format(agent, cur_original);
- assertEquals("Test Currency Usage 5", UnicodeString("CA$123.57"), cur_original);
+ assertEquals("Test Currency Usage 5", u"CA$123.57", cur_original);
fmt->setCurrency(CUR_PKR, status);
assertSuccess("Set currency to PKR", status);
UnicodeString PKR_changed;
fmt->format(agent, PKR_changed);
- assertEquals("Test Currency Usage 6", UnicodeString("PKR124"), PKR_changed);
+ assertEquals("Test Currency Usage 6", u"PKR124", PKR_changed); // use ICU 61 behavior
delete fmt;
}
}
sprintf(buf, "%lld", (long long)num);
double fNum = 0.0;
sscanf(buf, "%lf", &fNum);
- int64_t rtNum = fNum;
+ int64_t rtNum = static_cast<int64_t>(fNum);
if (num != rtNum) {
errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
return;
sprintf(buf, "%lld", (long long)num);
double fNum = 0.0;
sscanf(buf, "%lf", &fNum);
- int64_t rtNum = fNum;
+ int64_t rtNum = static_cast<int64_t>(fNum);
if (num != rtNum) {
errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
return;
}
}
-void NumberFormatTest::TestFastPathConsistent11524() {
+void NumberFormatTest::TestGetAffixes() {
UErrorCode status = U_ZERO_ERROR;
- NumberFormat *fmt = NumberFormat::createInstance("en", status);
- if (U_FAILURE(status) || fmt == NULL) {
- dataerrln("Failed call to NumberFormat::createInstance() - %s", u_errorName(status));
+ DecimalFormatSymbols sym("en_US", status);
+ UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
+ pattern = pattern.unescape();
+ DecimalFormat fmt(pattern, sym, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ return;
+ }
+ UnicodeString affixStr;
+ assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
+ assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
+ assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
+ assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
+
+ // Test equality with affixes. set affix methods can't capture special
+ // characters which is why equality should fail.
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString someAffix;
+ fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(someAffix));
+ assertTrue("", fmt != fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString someAffix;
+ fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(someAffix));
+ assertTrue("", fmt != fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString someAffix;
+ fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(someAffix));
+ assertTrue("", fmt != fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString someAffix;
+ fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(someAffix));
+ assertTrue("", fmt != fmtCopy);
+ }
+ fmt.setPositivePrefix("Don't");
+ fmt.setPositiveSuffix("do");
+ UnicodeString someAffix("be''eet\\u00a4\\u00a4\\u00a4 it.");
+ someAffix = someAffix.unescape();
+ fmt.setNegativePrefix(someAffix);
+ fmt.setNegativeSuffix("%");
+ assertEquals("", "Don't", fmt.getPositivePrefix(affixStr));
+ assertEquals("", "do", fmt.getPositiveSuffix(affixStr));
+ assertEquals("", someAffix, fmt.getNegativePrefix(affixStr));
+ assertEquals("", "%", fmt.getNegativeSuffix(affixStr));
+}
+
+void NumberFormatTest::TestToPatternScientific11648() {
+ UErrorCode status = U_ZERO_ERROR;
+ Locale en("en");
+ DecimalFormatSymbols sym(en, status);
+ DecimalFormat fmt("0.00", sym, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ return;
+ }
+ fmt.setScientificNotation(TRUE);
+ UnicodeString pattern;
+ assertEquals("", "0.00E0", fmt.toPattern(pattern));
+ DecimalFormat fmt2(pattern, sym, status);
+ assertSuccess("", status);
+}
+
+void NumberFormatTest::TestBenchmark() {
+/*
+ UErrorCode status = U_ZERO_ERROR;
+ Locale en("en");
+ DecimalFormatSymbols sym(en, status);
+ DecimalFormat fmt("0.0000000", new DecimalFormatSymbols(sym), status);
+// DecimalFormat fmt("0.00000E0", new DecimalFormatSymbols(sym), status);
+// DecimalFormat fmt("0", new DecimalFormatSymbols(sym), status);
+ FieldPosition fpos(FieldPosition::DONT_CARE);
+ clock_t start = clock();
+ for (int32_t i = 0; i < 1000000; ++i) {
+ UnicodeString append;
+ fmt.format(3.0, append, fpos, status);
+// fmt.format(4.6692016, append, fpos, status);
+// fmt.format(1234567.8901, append, fpos, status);
+// fmt.format(2.99792458E8, append, fpos, status);
+// fmt.format(31, append);
+ }
+ errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
+ assertSuccess("", status);
+
+ UErrorCode status = U_ZERO_ERROR;
+ MessageFormat fmt("{0, plural, one {I have # friend.} other {I have # friends.}}", status);
+ FieldPosition fpos(FieldPosition::DONT_CARE);
+ Formattable one(1.0);
+ Formattable three(3.0);
+ clock_t start = clock();
+ for (int32_t i = 0; i < 500000; ++i) {
+ UnicodeString append;
+ fmt.format(&one, 1, append, fpos, status);
+ UnicodeString append2;
+ fmt.format(&three, 1, append2, fpos, status);
+ }
+ errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
+ assertSuccess("", status);
+
+ UErrorCode status = U_ZERO_ERROR;
+ Locale en("en");
+ Measure measureC(23, MeasureUnit::createCelsius(status), status);
+ MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
+ FieldPosition fpos(FieldPosition::DONT_CARE);
+ clock_t start = clock();
+ for (int32_t i = 0; i < 1000000; ++i) {
+ UnicodeString appendTo;
+ fmt.formatMeasures(
+ &measureC, 1, appendTo, fpos, status);
+ }
+ errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
+ assertSuccess("", status);
+*/
+}
+
+void NumberFormatTest::TestFractionalDigitsForCurrency() {
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance("en", status));
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating NumberFormat - %s", u_errorName(status));
+ return;
+ }
+ UChar JPY[] = {0x4A, 0x50, 0x59, 0x0};
+ fmt->setCurrency(JPY, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ assertEquals("", 0, fmt->getMaximumFractionDigits());
+}
+
+
+void NumberFormatTest::TestFormatCurrencyPlural() {
+ UErrorCode status = U_ZERO_ERROR;
+ Locale locale = Locale::createCanonical("en_US");
+ NumberFormat *fmt = NumberFormat::createInstance(locale, UNUM_CURRENCY_PLURAL, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating NumberFormat - %s", u_errorName(status));
+ return;
+ }
+ UnicodeString formattedNum;
+ fmt->format(11234.567, formattedNum, NULL, status);
+ assertEquals("", "11,234.57 US dollars", formattedNum);
+ delete fmt;
+}
+
+void NumberFormatTest::TestCtorApplyPatternDifference() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols sym("en_US", status);
+ UnicodeString pattern("\\u00a40");
+ DecimalFormat fmt(pattern.unescape(), sym, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ return;
+ }
+ UnicodeString result;
+ assertEquals(
+ "ctor favors precision of currency",
+ "$5.00",
+ fmt.format((double)5, result));
+ result.remove();
+ fmt.applyPattern(pattern.unescape(), status);
+ assertEquals(
+ "applyPattern favors precision of pattern",
+ "$5",
+ fmt.format((double)5, result));
+}
+
+void NumberFormatTest::Test11868() {
+ double posAmt = 34.567;
+ double negAmt = -9876.543;
+
+ Locale selectedLocale("en_US");
+ UErrorCode status = U_ZERO_ERROR;
+
+ UnicodeString result;
+ FieldPosition fpCurr(UNUM_CURRENCY_FIELD);
+ LocalPointer<NumberFormat> fmt(
+ NumberFormat::createInstance(
+ selectedLocale, UNUM_CURRENCY_PLURAL, status));
+ if (!assertSuccess("Format creation", status)) {
+ return;
+ }
+ fmt->format(posAmt, result, fpCurr, status);
+ assertEquals("", "34.57 US dollars", result);
+ assertEquals("begin index", 6, fpCurr.getBeginIndex());
+ assertEquals("end index", 16, fpCurr.getEndIndex());
+
+ // Test field position iterator
+ {
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_INTEGER_FIELD, 0, 2},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
+ {UNUM_FRACTION_FIELD, 3, 5},
+ {UNUM_CURRENCY_FIELD, 6, 16},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt->format(posAmt, result, &iter, status);
+ assertEquals("", "34.57 US dollars", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+
+ result.remove();
+ fmt->format(negAmt, result, fpCurr, status);
+ assertEquals("", "-9,876.54 US dollars", result);
+ assertEquals("begin index", 10, fpCurr.getBeginIndex());
+ assertEquals("end index", 20, fpCurr.getEndIndex());
+
+ // Test field position iterator
+ {
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_SIGN_FIELD, 0, 1},
+ {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
+ {UNUM_INTEGER_FIELD, 1, 6},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 6, 7},
+ {UNUM_FRACTION_FIELD, 7, 9},
+ {UNUM_CURRENCY_FIELD, 10, 20},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt->format(negAmt, result, &iter, status);
+ assertEquals("", "-9,876.54 US dollars", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+}
+
+void NumberFormatTest::Test10727_RoundingZero() {
+ IcuTestErrorCode status(*this, "Test10727_RoundingZero");
+ DecimalQuantity dq;
+ dq.setToDouble(-0.0);
+ assertTrue("", dq.isNegative());
+ dq.roundToMagnitude(0, UNUM_ROUND_HALFEVEN, status);
+ assertTrue("", dq.isNegative());
+}
+
+void NumberFormatTest::Test11739_ParseLongCurrency() {
+ IcuTestErrorCode status(*this, "Test11739_ParseLongCurrency");
+ LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("sr_BA", status));
+ if (status.errDataIfFailureAndReset()) { return; }
+ ((DecimalFormat*) nf.getAlias())->applyPattern(u"#,##0.0 ¤¤¤", status);
+ ParsePosition ppos(0);
+ LocalPointer<CurrencyAmount> result(nf->parseCurrency(u"1.500 амерички долар", ppos));
+ assertEquals("Should parse to 1500 USD", -1, ppos.getErrorIndex());
+ assertEquals("Should parse to 1500 USD", 1500LL, result->getNumber().getInt64(status));
+ assertEquals("Should parse to 1500 USD", u"USD", result->getISOCurrency());
+}
+
+void NumberFormatTest::Test13035_MultiCodePointPaddingInPattern() {
+ IcuTestErrorCode status(*this, "Test13035_MultiCodePointPaddingInPattern");
+ DecimalFormat df(u"a*'நி'###0b", status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ UnicodeString result;
+ df.format(12, result.remove());
+ // TODO(13034): Re-enable this test when support is added in ICU4C.
+ //assertEquals("Multi-codepoint padding should not be split", u"aநிநி12b", result);
+ df = DecimalFormat(u"a*\U0001F601###0b", status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ result = df.format(12, result.remove());
+ assertEquals("Single-codepoint padding should not be split", u"a\U0001F601\U0001F60112b", result, true);
+ df = DecimalFormat(u"a*''###0b", status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ result = df.format(12, result.remove());
+ assertEquals("Quote should be escapable in padding syntax", "a''12b", result, true);
+}
+
+void NumberFormatTest::Test13737_ParseScientificStrict() {
+ IcuTestErrorCode status(*this, "Test13737_ParseScientificStrict");
+ LocalPointer<NumberFormat> df(NumberFormat::createScientificInstance("en", status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
+ df->setLenient(FALSE);
+ // Parse Test
+ expect(*df, u"1.2", 1.2);
+}
+
+void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
+ {
+ const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> fmt(
+ NumberFormat::createCurrencyInstance("en", status));
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
+ dfmt->setCurrency(USD);
+ UnicodeString result;
+
+ // This line should be a no-op. I am setting the positive prefix
+ // to be the same thing it was before.
+ dfmt->setPositivePrefix(dfmt->getPositivePrefix(result));
+
+ UnicodeString appendTo;
+ assertEquals("", "$3.78", dfmt->format(3.78, appendTo, status));
+ assertSuccess("", status);
+ }
+ {
+ const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> fmt(
+ NumberFormat::createInstance("en", UNUM_CURRENCY_PLURAL, status));
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
+ UnicodeString result;
+ UnicodeString tripleIntlCurrency(" \\u00a4\\u00a4\\u00a4");
+ tripleIntlCurrency = tripleIntlCurrency.unescape();
+ assertEquals("", tripleIntlCurrency, dfmt->getPositiveSuffix(result)); // use ICU 61 behavior
+ dfmt->setCurrency(USD);
+
+ // getPositiveSuffix() always returns the suffix for the
+ // "other" plural category
+ assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
+ UnicodeString appendTo;
+ assertEquals("", "3.78 US dollars", dfmt->format(3.78, appendTo, status));
+ assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
+ dfmt->setPositiveSuffix("booya");
+ appendTo.remove();
+ assertEquals("", "3.78booya", dfmt->format(3.78, appendTo, status));
+ assertEquals("", "booya", dfmt->getPositiveSuffix(result));
+ }
+}
+
+void NumberFormatTest::Test11475_signRecognition() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols sym("en", status);
+ UnicodeString result;
+ {
+ DecimalFormat fmt("+0.00", sym, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_SIGN_FIELD, 0, 1},
+ {UNUM_INTEGER_FIELD, 1, 2},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
+ {UNUM_FRACTION_FIELD, 3, 5},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt.format(2.3, result, &iter, status);
+ assertEquals("", "+2.30", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+ {
+ DecimalFormat fmt("++0.00+;-(#)--", sym, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ {
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_SIGN_FIELD, 0, 2},
+ {UNUM_INTEGER_FIELD, 2, 3},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
+ {UNUM_FRACTION_FIELD, 4, 6},
+ {UNUM_SIGN_FIELD, 6, 7},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt.format(2.3, result, &iter, status);
+ assertEquals("", "++2.30+", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+ {
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_SIGN_FIELD, 0, 1},
+ {UNUM_INTEGER_FIELD, 2, 3},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
+ {UNUM_FRACTION_FIELD, 4, 6},
+ {UNUM_SIGN_FIELD, 7, 9},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt.format(-2.3, result, &iter, status);
+ assertEquals("", "-(2.30)--", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+ }
+}
+
+void NumberFormatTest::Test11640_getAffixes() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols symbols("en_US", status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
+ pattern = pattern.unescape();
+ DecimalFormat fmt(pattern, symbols, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ UnicodeString affixStr;
+ assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
+ assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
+ assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
+ assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
+}
+
+void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
+ UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
+ pattern = pattern.unescape();
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat fmt(pattern, status);
+ if (!assertSuccess("", status)) {
return;
}
- fmt->setMaximumIntegerDigits(INT32_MIN);
+ static UChar USD[] = {0x55, 0x53, 0x44, 0x0};
+ fmt.setCurrency(USD);
UnicodeString appendTo;
- assertEquals("", "0", fmt->format(123, appendTo));
+
+ assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
+
+ UnicodeString topattern;
+ fmt.toPattern(topattern);
+ DecimalFormat fmt2(topattern, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ fmt2.setCurrency(USD);
+
appendTo.remove();
- assertEquals("", "0", fmt->format(12345, appendTo));
- delete fmt;
+ assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
+}
+
+void NumberFormatTest::Test13327_numberingSystemBufferOverflow() {
+ UErrorCode status = U_ZERO_ERROR;
+ for (int runId = 0; runId < 2; runId++) {
+ // Construct a locale string with a very long "numbers" value.
+ // The first time, make the value length exactly equal to ULOC_KEYWORDS_CAPACITY.
+ // The second time, make it exceed ULOC_KEYWORDS_CAPACITY.
+ int extraLength = (runId == 0) ? 0 : 5;
+
+ CharString localeId("en@numbers=", status);
+ for (int i = 0; i < ULOC_KEYWORDS_CAPACITY + extraLength; i++) {
+ localeId.append('x', status);
+ }
+ assertSuccess("Constructing locale string", status);
+ Locale locale(localeId.data());
+
+ LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(locale, status));
+ assertFalse("Should not be null", ns.getAlias() == nullptr);
+ assertSuccess("Should create with no error", status);
+ }
+}
+
+void NumberFormatTest::Test13391_chakmaParsing() {
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<DecimalFormat> df(dynamic_cast<DecimalFormat*>(
+ NumberFormat::createInstance(Locale("ccp"), status)));
+ if (df == nullptr) {
+ dataerrln("%s %d Chakma df is null", __FILE__, __LINE__);
+ return;
+ }
+ const UChar* expected = u"\U00011137\U00011138,\U00011139\U0001113A\U0001113B";
+ UnicodeString actual;
+ df->format(12345, actual, status);
+ assertSuccess("Should not fail when formatting in ccp", status);
+ assertEquals("Should produce expected output in ccp", expected, actual);
+
+ Formattable result;
+ df->parse(expected, result, status);
+ assertSuccess("Should not fail when parsing in ccp", status);
+ assertEquals("Should parse to 12345 in ccp", 12345, result);
+
+ const UChar* expectedScientific = u"\U00011137.\U00011139E\U00011138";
+ UnicodeString actualScientific;
+ df.adoptInstead(static_cast<DecimalFormat*>(
+ NumberFormat::createScientificInstance(Locale("ccp"), status)));
+ df->format(130, actualScientific, status);
+ assertSuccess("Should not fail when formatting scientific in ccp", status);
+ assertEquals("Should produce expected scientific output in ccp",
+ expectedScientific, actualScientific);
+
+ Formattable resultScientific;
+ df->parse(expectedScientific, resultScientific, status);
+ assertSuccess("Should not fail when parsing scientific in ccp", status);
+ assertEquals("Should parse scientific to 130 in ccp", 130, resultScientific);
}
+void NumberFormatTest::verifyFieldPositionIterator(
+ NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
+ int32_t idx = 0;
+ FieldPosition fp;
+ while (iter.next(fp)) {
+ if (expected[idx].spos == -1) {
+ errln("Iterator should have ended. got %d", fp.getField());
+ return;
+ }
+ assertEquals("id", expected[idx].id, fp.getField());
+ assertEquals("start", expected[idx].spos, fp.getBeginIndex());
+ assertEquals("end", expected[idx].epos, fp.getEndIndex());
+ ++idx;
+ }
+ if (expected[idx].spos != -1) {
+ errln("Premature end of iterator. expected %d", expected[idx].id);
+ }
+}
+
+void NumberFormatTest::Test11735_ExceptionIssue() {
+ IcuTestErrorCode status(*this, "Test11735_ExceptionIssue");
+ Locale enLocale("en");
+ DecimalFormatSymbols symbols(enLocale, status);
+ if (status.isSuccess()) {
+ DecimalFormat fmt("0", symbols, status);
+ assertSuccess("Fail: Construct DecimalFormat formatter", status, true, __FILE__, __LINE__);
+ ParsePosition ppos(0);
+ fmt.parseCurrency("53.45", ppos); // NPE thrown here in ICU4J.
+ assertEquals("Issue11735 ppos", 0, ppos.getIndex());
+ }
+}
+
+void NumberFormatTest::Test11035_FormatCurrencyAmount() {
+ UErrorCode status = U_ZERO_ERROR;
+ double amount = 12345.67;
+ const char16_t* expected = u"12,345$67 ";
+
+ // Test two ways to set a currency via API
+
+ Locale loc1 = Locale("pt_PT");
+ LocalPointer<NumberFormat> fmt1(NumberFormat::createCurrencyInstance("loc1", status),
+ status);
+ if (U_FAILURE(status)) {
+ dataerrln("%s %d NumberFormat instance fmt1 is null", __FILE__, __LINE__);
+ return;
+ }
+ fmt1->setCurrency(u"PTE", status);
+ assertSuccess("Setting currency on fmt1", status);
+ UnicodeString actualSetCurrency;
+ fmt1->format(amount, actualSetCurrency);
+
+ Locale loc2 = Locale("pt_PT@currency=PTE");
+ LocalPointer<NumberFormat> fmt2(NumberFormat::createCurrencyInstance(loc2, status));
+ assertSuccess("Creating fmt2", status);
+ UnicodeString actualLocaleString;
+ fmt2->format(amount, actualLocaleString);
+
+ // TODO: The following test will fail until DecimalFormat wraps NumberFormatter.
+ if (!logKnownIssue("13574")) {
+ assertEquals("Custom Currency Pattern, Set Currency", expected, actualSetCurrency);
+ }
+}
+
+void NumberFormatTest::Test11318_DoubleConversion() {
+ IcuTestErrorCode status(*this, "Test11318_DoubleConversion");
+ LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
+ if (U_FAILURE(status)) {
+ dataerrln("%s %d Error in NumberFormat instance creation", __FILE__, __LINE__);
+ return;
+ }
+ nf->setMaximumFractionDigits(40);
+ nf->setMaximumIntegerDigits(40);
+ DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf.getAlias());
+ if (df != NULL) {
+ UErrorCode status = U_ZERO_ERROR;
+ df->setAttribute(UNUM_FORMAT_WITH_FULL_PRECISION, TRUE, status); // Apple
+ }
+ UnicodeString appendTo;
+ nf->format(999999999999999.9, appendTo);
+ assertEquals("Should render all digits", u"999,999,999,999,999.9", appendTo);
+}
+
+void NumberFormatTest::TestParsePercentRegression() {
+ IcuTestErrorCode status(*this, "TestParsePercentRegression");
+ LocalPointer<DecimalFormat> df1((DecimalFormat*) NumberFormat::createInstance("en", status), status);
+ LocalPointer<DecimalFormat> df2((DecimalFormat*) NumberFormat::createPercentInstance("en", status), status);
+ if (status.isFailure()) {return; }
+ df1->setLenient(TRUE);
+ df2->setLenient(TRUE);
+
+ {
+ ParsePosition ppos;
+ Formattable result;
+ df1->parse("50%", result, ppos);
+ assertEquals("df1 should accept a number but not the percent sign", 2, ppos.getIndex());
+ assertEquals("df1 should return the number as 50", 50.0, result.getDouble(status));
+ }
+ {
+ ParsePosition ppos;
+ Formattable result;
+ df2->parse("50%", result, ppos);
+ assertEquals("df2 should accept the percent sign", 3, ppos.getIndex());
+ assertEquals("df2 should return the number as 0.5", 0.5, result.getDouble(status));
+ }
+ {
+ ParsePosition ppos;
+ Formattable result;
+ df2->parse("50", result, ppos);
+ assertEquals("df2 should return the number as 0.5 even though the percent sign is missing",
+ 0.5,
+ result.getDouble(status));
+ }
+}
+
+void NumberFormatTest::TestMultiplierWithScale() {
+ // to be added
+}
+
+void NumberFormatTest::TestFastFormatInt32() {
+ IcuTestErrorCode status(*this, "TestFastFormatInt32");
+
+ // The two simplest formatters, old API and new API.
+ // Old API should use the fastpath for ints.
+ LocalizedNumberFormatter lnf = NumberFormatter::withLocale("en");
+ LocalPointer<NumberFormat> df(NumberFormat::createInstance("en", status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
+
+ double nums[] = {
+ 0.0,
+ -0.0,
+ NAN,
+ INFINITY,
+ 0.1,
+ 1.0,
+ 1.1,
+ 2.0,
+ 3.0,
+ 9.0,
+ 10.0,
+ 99.0,
+ 100.0,
+ 999.0,
+ 1000.0,
+ 9999.0,
+ 10000.0,
+ 99999.0,
+ 100000.0,
+ 999999.0,
+ 1000000.0,
+ static_cast<double>(INT32_MAX) - 1,
+ static_cast<double>(INT32_MAX),
+ static_cast<double>(INT32_MAX) + 1,
+ static_cast<double>(INT32_MIN) - 1,
+ static_cast<double>(INT32_MIN),
+ static_cast<double>(INT32_MIN) + 1};
+
+ for (auto num : nums) {
+ UnicodeString expected = lnf.formatDouble(num, status).toString();
+ UnicodeString actual;
+ df->format(num, actual);
+ assertEquals(UnicodeString("d = ") + num, expected, actual);
+ }
+}
+
+void NumberFormatTest::Test11646_Equality() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols symbols(Locale::getEnglish(), status);
+ UnicodeString pattern(u"\u00a4\u00a4\u00a4 0.00 %\u00a4\u00a4");
+ DecimalFormat fmt(pattern, symbols, status);
+ if (!assertSuccess("", status)) return;
+
+ // Test equality with affixes. set affix methods can't capture special
+ // characters which is why equality should fail.
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString positivePrefix;
+ fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(positivePrefix));
+ assertFalse("", fmt == fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy = DecimalFormat(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString positivePrefix;
+ fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(positivePrefix));
+ assertFalse("", fmt == fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString negativePrefix;
+ fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(negativePrefix));
+ assertFalse("", fmt == fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString negativePrefix;
+ fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(negativePrefix));
+ assertFalse("", fmt == fmtCopy);
+ }
+}
+
+void NumberFormatTest::TestParseNaN() {
+ IcuTestErrorCode status(*this, "TestParseNaN");
+
+ DecimalFormat df("0", { "en", status }, status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ Formattable parseResult;
+ df.parse(u"NaN", parseResult, status);
+ assertEquals("NaN should parse successfully", NAN, parseResult.getDouble());
+ assertFalse("Result NaN should be positive", std::signbit(parseResult.getDouble()));
+ UnicodeString formatResult;
+ df.format(parseResult.getDouble(), formatResult);
+ assertEquals("NaN should round-trip", u"NaN", formatResult);
+}
+
+void NumberFormatTest::Test11897_LocalizedPatternSeparator() {
+ IcuTestErrorCode status(*this, "Test11897_LocalizedPatternSeparator");
+
+ // In a locale with a different <list> symbol, like arabic,
+ // kPatternSeparatorSymbol should still be ';'
+ {
+ DecimalFormatSymbols dfs("ar", status);
+ assertEquals("pattern separator symbol should be ;",
+ u";",
+ dfs.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
+ }
+
+ // However, the custom symbol should be used in localized notation
+ // when set manually via API
+ {
+ DecimalFormatSymbols dfs("en", status);
+ dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u"!", FALSE);
+ DecimalFormat df(u"0", dfs, status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ df.applyPattern("a0;b0", status); // should not throw
+ UnicodeString result;
+ assertEquals("should apply the normal pattern",
+ df.getNegativePrefix(result.remove()),
+ "b");
+ df.applyLocalizedPattern(u"c0!d0", status); // should not throw
+ assertEquals("should apply the localized pattern",
+ df.getNegativePrefix(result.remove()),
+ "d");
+ }
+}
+
+void NumberFormatTest::Test13055_PercentageRounding() {
+ IcuTestErrorCode status(*this, "PercentageRounding");
+ UnicodeString actual;
+ LocalPointer<NumberFormat>pFormat(NumberFormat::createPercentInstance("en_US", status));
+ if (U_FAILURE(status)) {
+ dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
+ return;
+ }
+ pFormat->setMaximumFractionDigits(0);
+ pFormat->setRoundingMode(DecimalFormat::kRoundHalfEven);
+ pFormat->format(2.155, actual);
+ assertEquals("Should round percent toward even number", "216%", actual);
+}
+
+void NumberFormatTest::Test11839() {
+ IcuTestErrorCode errorCode(*this, "Test11839");
+ // Ticket #11839: DecimalFormat does not respect custom plus sign
+ LocalPointer<DecimalFormatSymbols> dfs(new DecimalFormatSymbols(Locale::getEnglish(), errorCode), errorCode);
+ if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
+ dfs->setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"a∸");
+ dfs->setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"b∔"); // ∔ U+2214 DOT PLUS
+ DecimalFormat df(u"0.00+;0.00-", dfs.orphan(), errorCode);
+ UnicodeString result;
+ df.format(-1.234, result, errorCode);
+ assertEquals("Locale-specific minus sign should be used", u"1.23a∸", result);
+ df.format(1.234, result.remove(), errorCode);
+ assertEquals("Locale-specific plus sign should be used", u"1.23b∔", result);
+ // Test round-trip with parse
+ expect2(df, -456, u"456.00a∸");
+ expect2(df, 456, u"456.00b∔");
+}
+
+void NumberFormatTest::Test10354() {
+ IcuTestErrorCode errorCode(*this, "Test10354");
+ // Ticket #10354: invalid FieldPositionIterator when formatting with empty NaN
+ DecimalFormatSymbols dfs(errorCode);
+ UnicodeString empty;
+ dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, empty);
+ DecimalFormat df(errorCode);
+ df.setDecimalFormatSymbols(dfs);
+ UnicodeString result;
+ FieldPositionIterator positions;
+ df.format(NAN, result, &positions, errorCode);
+ errorCode.errIfFailureAndReset("DecimalFormat.format(NAN, FieldPositionIterator) failed");
+ FieldPosition fp;
+ while (positions.next(fp)) {
+ // Should not loop forever
+ }
+}
+
+void NumberFormatTest::Test11645_ApplyPatternEquality() {
+ IcuTestErrorCode status(*this, "Test11645_ApplyPatternEquality");
+ const char16_t* pattern = u"#,##0.0#";
+ LocalPointer<DecimalFormat> fmt((DecimalFormat*) NumberFormat::createInstance(status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ fmt->applyPattern(pattern, status);
+ LocalPointer<DecimalFormat> fmtCopy;
+
+ static const int32_t newMultiplier = 37;
+ fmtCopy.adoptInstead(new DecimalFormat(*fmt));
+ assertFalse("Value before setter", fmtCopy->getMultiplier() == newMultiplier);
+ fmtCopy->setMultiplier(newMultiplier);
+ assertEquals("Value after setter", fmtCopy->getMultiplier(), newMultiplier);
+ fmtCopy->applyPattern(pattern, status);
+ //assertEquals("Value after applyPattern", fmtCopy->getMultiplier(), newMultiplier);
+ //assertFalse("multiplier", *fmt == *fmtCopy);
+
+ static const NumberFormat::ERoundingMode newRoundingMode = NumberFormat::ERoundingMode::kRoundCeiling;
+ fmtCopy.adoptInstead(new DecimalFormat(*fmt));
+ assertFalse("Value before setter", fmtCopy->getRoundingMode() == newRoundingMode);
+ fmtCopy->setRoundingMode(newRoundingMode);
+ assertEquals("Value after setter", fmtCopy->getRoundingMode(), newRoundingMode);
+ fmtCopy->applyPattern(pattern, status);
+ assertEquals("Value after applyPattern", fmtCopy->getRoundingMode(), newRoundingMode);
+ assertFalse("roundingMode", *fmt == *fmtCopy);
+
+ static const char16_t *const newCurrency = u"EAT";
+ fmtCopy.adoptInstead(new DecimalFormat(*fmt));
+ assertFalse("Value before setter", fmtCopy->getCurrency() == newCurrency);
+ fmtCopy->setCurrency(newCurrency);
+ assertEquals("Value after setter", fmtCopy->getCurrency(), newCurrency);
+ fmtCopy->applyPattern(pattern, status);
+ assertEquals("Value after applyPattern", fmtCopy->getCurrency(), newCurrency);
+ assertFalse("currency", *fmt == *fmtCopy);
+
+ static const UCurrencyUsage newCurrencyUsage = UCurrencyUsage::UCURR_USAGE_CASH;
+ fmtCopy.adoptInstead(new DecimalFormat(*fmt));
+ assertFalse("Value before setter", fmtCopy->getCurrencyUsage() == newCurrencyUsage);
+ fmtCopy->setCurrencyUsage(newCurrencyUsage, status);
+ assertEquals("Value after setter", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
+ fmtCopy->applyPattern(pattern, status);
+ assertEquals("Value after applyPattern", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
+ assertFalse("currencyUsage", *fmt == *fmtCopy);
+}
+
+void NumberFormatTest::Test12567() {
+ IcuTestErrorCode errorCode(*this, "Test12567");
+ // Ticket #12567: DecimalFormat.equals() may not be symmetric
+ LocalPointer<DecimalFormat> df1((DecimalFormat *)
+ NumberFormat::createInstance(Locale::getUS(), UNUM_CURRENCY, errorCode));
+ LocalPointer<DecimalFormat> df2((DecimalFormat *)
+ NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, errorCode));
+ if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
+ // NOTE: CurrencyPluralInfo equality not tested in C++ because its operator== is not defined.
+ df1->applyPattern(u"0.00", errorCode);
+ df2->applyPattern(u"0.00", errorCode);
+ //assertTrue("df1 == df2", *df1 == *df2);
+ //assertTrue("df2 == df1", *df2 == *df1);
+ df2->setPositivePrefix(u"abc");
+ assertTrue("df1 != df2", *df1 != *df2);
+ assertTrue("df2 != df1", *df2 != *df1);
+}
+
+void NumberFormatTest::Test11626_CustomizeCurrencyPluralInfo() {
+ IcuTestErrorCode errorCode(*this, "Test11626_CustomizeCurrencyPluralInfo");
+ // Ticket #11626: No unit test demonstrating how to use CurrencyPluralInfo to
+ // change formatting spelled out currencies
+ // Use locale sr because it has interesting plural rules.
+ Locale locale("sr");
+ LocalPointer<DecimalFormatSymbols> symbols(new DecimalFormatSymbols(locale, errorCode), errorCode);
+ CurrencyPluralInfo info(locale, errorCode);
+ if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
+ info.setCurrencyPluralPattern(u"one", u"0 qwerty", errorCode);
+ info.setCurrencyPluralPattern(u"few", u"0 dvorak", errorCode);
+ DecimalFormat df(u"#", symbols.orphan(), UNUM_CURRENCY_PLURAL, errorCode);
+ df.setCurrencyPluralInfo(info);
+ df.setCurrency(u"USD");
+ df.setMaximumFractionDigits(0);
+
+ UnicodeString result;
+ //assertEquals("Plural one", u"1 qwerty", df.format(1, result, errorCode));
+ //assertEquals("Plural few", u"3 dvorak", df.format(3, result.remove(), errorCode));
+ assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
+
+ info.setPluralRules(u"few: n is 1; one: n in 2..4", errorCode);
+ df.setCurrencyPluralInfo(info);
+ //assertEquals("Plural one", u"1 dvorak", df.format(1, result.remove(), errorCode));
+ //assertEquals("Plural few", u"3 qwerty", df.format(3, result.remove(), errorCode));
+ assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
+}
+
+void NumberFormatTest::Test13056_GroupingSize() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat df(u"#,##0", status);
+ if (!assertSuccess("", status)) return;
+ assertEquals("Primary grouping should return 3", 3, df.getGroupingSize());
+ assertEquals("Secondary grouping should return 0", 0, df.getSecondaryGroupingSize());
+ df.setSecondaryGroupingSize(3);
+ assertEquals("Primary grouping should still return 3", 3, df.getGroupingSize());
+ assertEquals("Secondary grouping should round-trip", 3, df.getSecondaryGroupingSize());
+ df.setGroupingSize(4);
+ assertEquals("Primary grouping should return 4", 4, df.getGroupingSize());
+ assertEquals("Secondary should remember explicit setting and return 3", 3, df.getSecondaryGroupingSize());
+}
+
+
+void NumberFormatTest::Test11025_CurrencyPadding() {
+ UErrorCode status = U_ZERO_ERROR;
+ UnicodeString pattern(u"¤¤ **####0.00");
+ DecimalFormatSymbols sym(Locale::getFrance(), status);
+ if (!assertSuccess("", status)) return;
+ DecimalFormat fmt(pattern, sym, status);
+ if (!assertSuccess("", status)) return;
+ UnicodeString result;
+ fmt.format(433.0, result);
+ assertEquals("Number should be padded to 11 characters", "EUR *433,00", result);
+}
+
+void NumberFormatTest::Test11648_ExpDecFormatMalPattern() {
+ UErrorCode status = U_ZERO_ERROR;
+
+ DecimalFormat fmt("0.00", {"en", status}, status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ fmt.setScientificNotation(TRUE);
+ UnicodeString pattern;
+
+ assertEquals("A valid scientific notation pattern should be produced",
+ "0.00E0",
+ fmt.toPattern(pattern));
+
+ DecimalFormat fmt2(pattern, status);
+ assertSuccess("", status);
+}
+
+void NumberFormatTest::Test11649_DecFmtCurrencies() {
+ IcuTestErrorCode status(*this, "Test11649_DecFmtCurrencies");
+ UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
+ pattern = pattern.unescape();
+ DecimalFormat fmt(pattern, status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ static const UChar USD[] = u"USD";
+ fmt.setCurrency(USD);
+ UnicodeString appendTo;
+
+ assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
+ UnicodeString topattern;
+
+ // assertEquals("", pattern, fmt.toPattern(topattern));
+ DecimalFormat fmt2(topattern, status);
+ fmt2.setCurrency(USD);
+
+ appendTo.remove();
+ assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
+}
+
+void NumberFormatTest::Test13148_ParseGroupingSeparators() {
+ IcuTestErrorCode status(*this, "Test13148");
+ LocalPointer<DecimalFormat> fmt(
+ (DecimalFormat*)NumberFormat::createInstance("en-ZA", status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+
+ DecimalFormatSymbols symbols = *fmt->getDecimalFormatSymbols();
+
+ symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'.');
+ symbols.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u',');
+ fmt->setDecimalFormatSymbols(symbols);
+ Formattable number;
+ fmt->parse(u"300,000", number, status);
+ assertEquals("Should parse as 300000", 300000LL, number.getInt64(status));
+}
+
+void NumberFormatTest::Test12753_PatternDecimalPoint() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols symbols(Locale::getUS(), status);
+ symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"*", false);
+ DecimalFormat df(u"0.00", symbols, status);
+ if (!assertSuccess("", status)) return;
+ df.setDecimalPatternMatchRequired(true);
+ Formattable result;
+ df.parse(u"123",result, status);
+ assertEquals("Parsing integer succeeded even though setDecimalPatternMatchRequired was set",
+ U_INVALID_FORMAT_ERROR, status);
+ }
+
+ void NumberFormatTest::Test11647_PatternCurrencySymbols() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat df(status);
+ df.applyPattern(u"¤¤¤¤#", status);
+ if (!assertSuccess("", status)) return;
+ UnicodeString actual;
+ df.format(123, actual);
+ //assertEquals("Should replace 4 currency signs with U+FFFD", u"\uFFFD123", actual);
+}
+
+void NumberFormatTest::Test11913_BigDecimal() {
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> df(NumberFormat::createInstance(Locale::getEnglish(), status), status);
+ if (!assertSuccess("", status)) return;
+ UnicodeString result;
+ df->format(StringPiece("1.23456789E400"), result, nullptr, status);
+ assertSuccess("", status);
+ assertEquals("Should format more than 309 digits", u"12,345,678", UnicodeString(result, 0, 10));
+ assertEquals("Should format more than 309 digits", 534, result.length());
+}
+
+void NumberFormatTest::Test11020_RoundingInScientificNotation() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols sym(Locale::getFrance(), status);
+ DecimalFormat fmt(u"0.05E0", sym, status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ assertSuccess("", status);
+ UnicodeString result;
+ fmt.format(12301.2, result);
+ assertEquals("Rounding increment should be applied after magnitude scaling", u"1,25E4", result);
+}
+
+void NumberFormatTest::Test11640_TripleCurrencySymbol() {
+ IcuTestErrorCode status(*this, "Test11640_TripleCurrencySymbol");
+ UnicodeString actual;
+ DecimalFormat dFormat(u"¤¤¤ 0", status);
+ if (U_FAILURE(status)) {
+ dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
+ return;
+ }
+ dFormat.setCurrency(u"USD");
+ UnicodeString result;
+ dFormat.getPositivePrefix(result);
+ assertEquals("Triple-currency should give long name on getPositivePrefix",
+ "US dollars ", result);
+}
+
+
+void NumberFormatTest::Test13763_FieldPositionIteratorOffset() {
+ IcuTestErrorCode status(*this, "Test13763_FieldPositionIteratorOffset");
+ FieldPositionIterator fpi;
+ UnicodeString result(u"foo\U0001F4FBbar"); // 8 code units
+ LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ nf->format(5142.3, result, &fpi, status);
+
+ int32_t expected[] = {
+ UNUM_GROUPING_SEPARATOR_FIELD, 9, 10,
+ UNUM_INTEGER_FIELD, 8, 13,
+ UNUM_DECIMAL_SEPARATOR_FIELD, 13, 14,
+ UNUM_FRACTION_FIELD, 14, 15,
+ };
+ int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
+ expectPositions(fpi, expected, tupleCount, result);
+}
+
+void NumberFormatTest::Test13777_ParseLongNameNonCurrencyMode() {
+ IcuTestErrorCode status(*this, "Test13777_ParseLongNameNonCurrencyMode");
+
+ LocalPointer<NumberFormat> df(
+ NumberFormat::createInstance("en-us", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ expect2(*df, 1.5, u"1.50 US dollars");
+}
+
+void NumberFormatTest::Test13804_EmptyStringsWhenParsing() {
+ IcuTestErrorCode status(*this, "Test13804_EmptyStringsWhenParsing");
+
+ DecimalFormatSymbols dfs("en", status);
+ if (status.errIfFailureAndReset()) {
+ return;
+ }
+ dfs.setSymbol(DecimalFormatSymbols::kCurrencySymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kThreeDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kFourDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kSixDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kSevenDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kEightDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kNineDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kExponentMultiplicationSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kInfinitySymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, u"", FALSE);
+ dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, FALSE, u"");
+ dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, TRUE, u"");
+ dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"", FALSE);
+
+ DecimalFormat df("0", dfs, status);
+ if (status.errIfFailureAndReset()) {
+ return;
+ }
+ df.setGroupingUsed(TRUE);
+ df.setScientificNotation(TRUE);
+ df.setLenient(TRUE); // enable all matchers
+ {
+ UnicodeString result;
+ df.format(0, result); // should not crash or hit infinite loop
+ }
+ const char16_t* samples[] = {
+ u"",
+ u"123",
+ u"$123",
+ u"-",
+ u"+",
+ u"44%",
+ u"1E+2.3"
+ };
+ for (auto& sample : samples) {
+ logln(UnicodeString(u"Attempting parse on: ") + sample);
+ status.setScope(sample);
+ // We don't care about the results, only that we don't crash and don't loop.
+ Formattable result;
+ ParsePosition ppos(0);
+ df.parse(sample, result, ppos);
+ ppos = ParsePosition(0);
+ LocalPointer<CurrencyAmount> curramt(df.parseCurrency(sample, ppos));
+ status.errIfFailureAndReset();
+ }
+
+ // Test with a nonempty exponent separator symbol to cover more code
+ dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"E", FALSE);
+ df.setDecimalFormatSymbols(dfs);
+ {
+ Formattable result;
+ ParsePosition ppos(0);
+ df.parse(u"1E+2.3", result, ppos);
+ }
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */