+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2016, International Business Machines Corporation and
#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 "unicode/numsys.h"
#include "fmtableimp.h"
#include "numberformattesttuple.h"
-#include "datadrivennumberformattestsuite.h"
#include "unicode/msgfmt.h"
-
-class NumberFormatTestDataDriven : public DataDrivenNumberFormatTestSuite {
-protected:
-UBool isFormatPass(
- const NumberFormatTestTuple &tuple,
- UnicodeString &appendErrorMessage,
- UErrorCode &status);
-UBool isToPatternPass(
- const NumberFormatTestTuple &tuple,
- UnicodeString &appendErrorMessage,
- UErrorCode &status);
-UBool isParsePass(
- const NumberFormatTestTuple &tuple,
- UnicodeString &appendErrorMessage,
- UErrorCode &status);
-UBool isParseCurrencyPass(
- const NumberFormatTestTuple &tuple,
- UnicodeString &appendErrorMessage,
- UErrorCode &status);
-};
-
-static DigitList &strToDigitList(
- const UnicodeString &str,
- DigitList &digitList,
- UErrorCode &status) {
- if (U_FAILURE(status)) {
- return digitList;
- }
- if (str == "NaN") {
- digitList.set(uprv_getNaN());
- return digitList;
- }
- if (str == "-Inf") {
- digitList.set(-1*uprv_getInfinity());
- return digitList;
- }
- if (str == "Inf") {
- digitList.set(uprv_getInfinity());
- return digitList;
- }
- CharString formatValue;
- formatValue.appendInvariantChars(str, status);
- digitList.set(StringPiece(formatValue.data()), status, 0);
- return digitList;
-}
-
-static UnicodeString &format(
- const DecimalFormat &fmt,
- const DigitList &digitList,
- UnicodeString &appendTo,
- UErrorCode &status) {
- if (U_FAILURE(status)) {
- return appendTo;
- }
- FieldPosition fpos(FieldPosition::DONT_CARE);
- return fmt.format(digitList, appendTo, fpos, status);
-}
-
-template<class T>
-static UnicodeString &format(
- const DecimalFormat &fmt,
- T value,
- UnicodeString &appendTo,
- UErrorCode &status) {
- if (U_FAILURE(status)) {
- return appendTo;
- }
- FieldPosition fpos(FieldPosition::DONT_CARE);
- return fmt.format(value, appendTo, fpos, status);
+#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);
+ }
}
-
-static void adjustDecimalFormat(
- const NumberFormatTestTuple &tuple,
- DecimalFormat &fmt,
- UnicodeString &appendErrorMessage) {
- if (tuple.minIntegerDigitsFlag) {
- fmt.setMinimumIntegerDigits(tuple.minIntegerDigits);
- }
- if (tuple.maxIntegerDigitsFlag) {
- fmt.setMaximumIntegerDigits(tuple.maxIntegerDigits);
- }
- if (tuple.minFractionDigitsFlag) {
- fmt.setMinimumFractionDigits(tuple.minFractionDigits);
- }
- if (tuple.maxFractionDigitsFlag) {
- fmt.setMaximumFractionDigits(tuple.maxFractionDigits);
- }
- if (tuple.currencyFlag) {
- UErrorCode status = U_ZERO_ERROR;
- UnicodeString currency(tuple.currency);
- const UChar *terminatedCurrency = currency.getTerminatedBuffer();
- fmt.setCurrency(terminatedCurrency, status);
- if (U_FAILURE(status)) {
- appendErrorMessage.append("Error setting currency.");
- }
- }
- if (tuple.minGroupingDigitsFlag) {
- fmt.setMinimumGroupingDigits(tuple.minGroupingDigits);
- }
- if (tuple.useSigDigitsFlag) {
- fmt.setSignificantDigitsUsed(tuple.useSigDigits != 0);
- }
- if (tuple.minSigDigitsFlag) {
- fmt.setMinimumSignificantDigits(tuple.minSigDigits);
- }
- if (tuple.maxSigDigitsFlag) {
- fmt.setMaximumSignificantDigits(tuple.maxSigDigits);
- }
- if (tuple.useGroupingFlag) {
- fmt.setGroupingUsed(tuple.useGrouping != 0);
- }
- if (tuple.multiplierFlag) {
- fmt.setMultiplier(tuple.multiplier);
- }
- if (tuple.roundingIncrementFlag) {
- fmt.setRoundingIncrement(tuple.roundingIncrement);
- }
- if (tuple.formatWidthFlag) {
- fmt.setFormatWidth(tuple.formatWidth);
- }
- if (tuple.padCharacterFlag) {
- fmt.setPadCharacter(tuple.padCharacter);
- }
- if (tuple.useScientificFlag) {
- fmt.setScientificNotation(tuple.useScientific != 0);
- }
- if (tuple.groupingFlag) {
- fmt.setGroupingSize(tuple.grouping);
- }
- if (tuple.grouping2Flag) {
- fmt.setSecondaryGroupingSize(tuple.grouping2);
- }
- if (tuple.roundingModeFlag) {
- fmt.setRoundingMode(tuple.roundingMode);
- }
- if (tuple.currencyUsageFlag) {
- UErrorCode status = U_ZERO_ERROR;
- fmt.setCurrencyUsage(tuple.currencyUsage, &status);
- if (U_FAILURE(status)) {
- appendErrorMessage.append("CurrencyUsage: error setting.");
- }
- }
- if (tuple.minimumExponentDigitsFlag) {
- fmt.setMinimumExponentDigits(tuple.minimumExponentDigits);
- }
- if (tuple.exponentSignAlwaysShownFlag) {
- fmt.setExponentSignAlwaysShown(tuple.exponentSignAlwaysShown != 0);
- }
- if (tuple.decimalSeparatorAlwaysShownFlag) {
- fmt.setDecimalSeparatorAlwaysShown(
- tuple.decimalSeparatorAlwaysShown != 0);
- }
- if (tuple.padPositionFlag) {
- fmt.setPadPosition(tuple.padPosition);
- }
- if (tuple.positivePrefixFlag) {
- fmt.setPositivePrefix(tuple.positivePrefix);
- }
- if (tuple.positiveSuffixFlag) {
- fmt.setPositiveSuffix(tuple.positiveSuffix);
- }
- if (tuple.negativePrefixFlag) {
- fmt.setNegativePrefix(tuple.negativePrefix);
- }
- if (tuple.negativeSuffixFlag) {
- fmt.setNegativeSuffix(tuple.negativeSuffix);
- }
- if (tuple.localizedPatternFlag) {
- UErrorCode status = U_ZERO_ERROR;
- fmt.applyLocalizedPattern(tuple.localizedPattern, status);
- if (U_FAILURE(status)) {
- appendErrorMessage.append("Error setting localized pattern.");
- }
- }
- fmt.setLenient(NFTT_GET_FIELD(tuple, lenient, 1) != 0);
- if (tuple.parseIntegerOnlyFlag) {
- fmt.setParseIntegerOnly(tuple.parseIntegerOnly != 0);
- }
- if (tuple.decimalPatternMatchRequiredFlag) {
- fmt.setDecimalPatternMatchRequired(
- tuple.decimalPatternMatchRequired != 0);
- }
- if (tuple.parseNoExponentFlag) {
- UErrorCode status = U_ZERO_ERROR;
- fmt.setAttribute(
- UNUM_PARSE_NO_EXPONENT,
- tuple.parseNoExponent,
- status);
- if (U_FAILURE(status)) {
- appendErrorMessage.append("Error setting parse no exponent flag.");
- }
- }
-}
-
-static DecimalFormat *newDecimalFormat(
- const Locale &locale,
- const UnicodeString &pattern,
- UErrorCode &status) {
- if (U_FAILURE(status)) {
- return NULL;
- }
- LocalPointer<DecimalFormatSymbols> symbols(
- new DecimalFormatSymbols(locale, status), status);
- if (U_FAILURE(status)) {
- return NULL;
- }
- UParseError perror;
- LocalPointer<DecimalFormat> result(new DecimalFormat(
- pattern, symbols.getAlias(), perror, status), status);
- if (!result.isNull()) {
- symbols.orphan();
- }
- if (U_FAILURE(status)) {
- return NULL;
- }
- return result.orphan();
-}
-
-static DecimalFormat *newDecimalFormat(
- const NumberFormatTestTuple &tuple,
- UErrorCode &status) {
- if (U_FAILURE(status)) {
- return NULL;
- }
- Locale en("en");
- return newDecimalFormat(
- NFTT_GET_FIELD(tuple, locale, en),
- NFTT_GET_FIELD(tuple, pattern, "0"),
- status);
-}
-
-UBool NumberFormatTestDataDriven::isFormatPass(
- const NumberFormatTestTuple &tuple,
- UnicodeString &appendErrorMessage,
- UErrorCode &status) {
- if (U_FAILURE(status)) {
- return FALSE;
- }
- LocalPointer<DecimalFormat> fmtPtr(newDecimalFormat(tuple, status));
- if (U_FAILURE(status)) {
- appendErrorMessage.append("Error creating DecimalFormat.");
- return FALSE;
- }
- adjustDecimalFormat(tuple, *fmtPtr, appendErrorMessage);
- if (appendErrorMessage.length() > 0) {
- return FALSE;
- }
- DigitList digitList;
- strToDigitList(tuple.format, digitList, status);
- {
- UnicodeString appendTo;
- format(*fmtPtr, digitList, appendTo, status);
- if (U_FAILURE(status)) {
- appendErrorMessage.append("Error formatting.");
- return FALSE;
- }
- if (appendTo != tuple.output) {
- appendErrorMessage.append(
- UnicodeString("Expected: ") + tuple.output + ", got: " + appendTo);
- return FALSE;
- }
- }
- double doubleVal = digitList.getDouble();
- {
- UnicodeString appendTo;
- format(*fmtPtr, doubleVal, appendTo, status);
- if (U_FAILURE(status)) {
- appendErrorMessage.append("Error formatting.");
- return FALSE;
- }
- if (appendTo != tuple.output) {
- appendErrorMessage.append(
- UnicodeString("double Expected: ") + tuple.output + ", got: " + appendTo);
- return FALSE;
- }
- }
- if (!uprv_isNaN(doubleVal) && !uprv_isInfinite(doubleVal) && doubleVal == uprv_floor(doubleVal)) {
- int64_t intVal = digitList.getInt64();
- {
- UnicodeString appendTo;
- format(*fmtPtr, intVal, appendTo, status);
- if (U_FAILURE(status)) {
- appendErrorMessage.append("Error formatting.");
- return FALSE;
- }
- if (appendTo != tuple.output) {
- appendErrorMessage.append(
- UnicodeString("int64 Expected: ") + tuple.output + ", got: " + appendTo);
- return FALSE;
- }
- }
- }
- return TRUE;
-}
-
-UBool NumberFormatTestDataDriven::isToPatternPass(
- const NumberFormatTestTuple &tuple,
- UnicodeString &appendErrorMessage,
- UErrorCode &status) {
- if (U_FAILURE(status)) {
- return FALSE;
- }
- LocalPointer<DecimalFormat> fmtPtr(newDecimalFormat(tuple, status));
- if (U_FAILURE(status)) {
- appendErrorMessage.append("Error creating DecimalFormat.");
- return FALSE;
- }
- adjustDecimalFormat(tuple, *fmtPtr, appendErrorMessage);
- if (appendErrorMessage.length() > 0) {
- return FALSE;
- }
- if (tuple.toPatternFlag) {
- UnicodeString actual;
- fmtPtr->toPattern(actual);
- if (actual != tuple.toPattern) {
- appendErrorMessage.append(
- UnicodeString("Expected: ") + tuple.toPattern + ", got: " + actual + ". ");
- }
- }
- if (tuple.toLocalizedPatternFlag) {
- UnicodeString actual;
- fmtPtr->toLocalizedPattern(actual);
- if (actual != tuple.toLocalizedPattern) {
- appendErrorMessage.append(
- UnicodeString("Expected: ") + tuple.toLocalizedPattern + ", got: " + actual + ". ");
- }
- }
- return appendErrorMessage.length() == 0;
-}
-
-UBool NumberFormatTestDataDriven::isParsePass(
- const NumberFormatTestTuple &tuple,
- UnicodeString &appendErrorMessage,
- UErrorCode &status) {
- if (U_FAILURE(status)) {
- return FALSE;
- }
- LocalPointer<DecimalFormat> fmtPtr(newDecimalFormat(tuple, status));
- if (U_FAILURE(status)) {
- appendErrorMessage.append("Error creating DecimalFormat.");
- return FALSE;
- }
- adjustDecimalFormat(tuple, *fmtPtr, appendErrorMessage);
- if (appendErrorMessage.length() > 0) {
- return FALSE;
- }
- Formattable result;
- ParsePosition ppos;
- fmtPtr->parse(tuple.parse, result, ppos);
- if (ppos.getIndex() == 0) {
- if (tuple.output != "fail") {
- appendErrorMessage.append("Parse failed but was expected to succeed.");
- return FALSE;
- }
- return TRUE;
- }
- UnicodeString resultStr(UnicodeString::fromUTF8(result.getDecimalNumber(status)));
- if (tuple.output == "fail") {
- appendErrorMessage.append(UnicodeString("Parse succeeded: ") + resultStr + ", but was expected to fail.");
- return FALSE;
- }
- DigitList expected;
- strToDigitList(tuple.output, expected, status);
- if (U_FAILURE(status)) {
- appendErrorMessage.append("Error parsing.");
- return FALSE;
- }
- if (expected != *result.getDigitList()) {
- appendErrorMessage.append(
- UnicodeString("Expected: ") + tuple.output + ", got: " + resultStr + ". ");
- return FALSE;
- }
- return TRUE;
+#endif
+#if defined(isinf)
+#undef isinf
+namespace std {
+ bool isinf(double x) {
+ return _isinf(x);
+ }
}
+#endif
+#endif
-UBool NumberFormatTestDataDriven::isParseCurrencyPass(
- const NumberFormatTestTuple &tuple,
- UnicodeString &appendErrorMessage,
- UErrorCode &status) {
- if (U_FAILURE(status)) {
- return FALSE;
- }
- LocalPointer<DecimalFormat> fmtPtr(newDecimalFormat(tuple, status));
- if (U_FAILURE(status)) {
- appendErrorMessage.append("Error creating DecimalFormat.");
- return FALSE;
- }
- adjustDecimalFormat(tuple, *fmtPtr, appendErrorMessage);
- if (appendErrorMessage.length() > 0) {
- return FALSE;
- }
- ParsePosition ppos;
- LocalPointer<CurrencyAmount> currAmt(
- fmtPtr->parseCurrency(tuple.parse, ppos));
- if (ppos.getIndex() == 0) {
- if (tuple.output != "fail") {
- appendErrorMessage.append("Parse failed but was expected to succeed.");
- return FALSE;
- }
- return TRUE;
- }
- UnicodeString currStr(currAmt->getISOCurrency());
- Formattable resultFormattable(currAmt->getNumber());
- UnicodeString resultStr(UnicodeString::fromUTF8(resultFormattable.getDecimalNumber(status)));
- if (tuple.output == "fail") {
- appendErrorMessage.append(UnicodeString("Parse succeeded: ") + resultStr + ", but was expected to fail.");
- return FALSE;
- }
- DigitList expected;
- strToDigitList(tuple.output, expected, status);
- if (U_FAILURE(status)) {
- appendErrorMessage.append("Error parsing.");
- return FALSE;
- }
- if (expected != *currAmt->getNumber().getDigitList()) {
- appendErrorMessage.append(
- UnicodeString("Expected: ") + tuple.output + ", got: " + resultStr + ". ");
- return FALSE;
- }
- if (currStr != tuple.outputCurrency) {
- appendErrorMessage.append(UnicodeString(
- "Expected currency: ") + tuple.outputCurrency + ", got: " + currStr + ". ");
- return FALSE;
- }
- return TRUE;
-}
+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(TestAccountingCurrency);
TESTCASE_AUTO(TestEquality);
TESTCASE_AUTO(TestCurrencyUsage);
- TESTCASE_AUTO(TestNumberFormatTestTuple);
- TESTCASE_AUTO(TestDataDriven);
TESTCASE_AUTO(TestDoubleLimit11439);
- TESTCASE_AUTO(TestFastPathConsistent11524);
TESTCASE_AUTO(TestGetAffixes);
TESTCASE_AUTO(TestToPatternScientific11648);
TESTCASE_AUTO(TestBenchmark);
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)
const char* pat[] = { "#.#", "#.", ".#", "#" };
int32_t pat_length = UPRV_LENGTHOF(pat);
- const char* newpat[] = { "#0.#", "#0.", "#.0", "#" };
+ 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)
{
#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");
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);
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[] = {
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 < 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 < 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)) {
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;
}
}
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;
}
}
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;
}
}
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 < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
UnicodeString testCase = ctou(strictFailureTestCases[t]);
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;
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);
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, en_CA)",
+ UnicodeString("US$"),
+ 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("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){
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();
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};
"$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 < UPRV_LENGTHOF(formats); ++i) {
}
+/** 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"},
};
+ // 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", "-1234.56", "USD", "-$1,234.56", "-USD1,234.56", "-1,234.56 US dollars"},
{"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", "\\uFFE51.00", "CNY1.00", "1.00\\u4EBA\\u6C11\\u5E01"},
- {"zh_CN", "1234.56", "CNY", "\\uFFE51,234.56", "CNY1,234.56", "1,234.56\\u4EBA\\u6C11\\u5E01"},
+ {"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"},
};
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$\\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", "\\uFFE51.00", "CNY01.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,
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",
"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<UPRV_LENGTHOF(DATA); ++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;
+ 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<UPRV_LENGTHOF(WRONG_DATA); ++i) {
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,
//
// 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() {
{
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);
+ DecimalFormat df(UnicodeString(u"0000"),status);
if (U_FAILURE(status)) {
dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
} else {
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),""));
- } else {
+ 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);
+ DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
if (U_FAILURE(status)) {
dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
} else {
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");
+ 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);
+ DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
if (U_FAILURE(status)) {
dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
} else {
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");
+ 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");
}
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");
+ 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");
}
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");
+ 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 < UPRV_LENGTHOF(input); ++i) {
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 },
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.
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() {
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.55"), 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;
}
}
-void NumberFormatTest::TestNumberFormatTestTuple() {
- NumberFormatTestTuple tuple;
- UErrorCode status = U_ZERO_ERROR;
-
- tuple.setField(
- NumberFormatTestTuple::getFieldByName("locale"),
- "en",
- status);
- tuple.setField(
- NumberFormatTestTuple::getFieldByName("pattern"),
- "#,##0.00",
- status);
- tuple.setField(
- NumberFormatTestTuple::getFieldByName("minIntegerDigits"),
- "-10",
- status);
- if (!assertSuccess("", status)) {
- return;
- }
-
- // only what we set should be set.
- assertEquals("", "en", tuple.locale.getName());
- assertEquals("", "#,##0.00", tuple.pattern);
- assertEquals("", -10, tuple.minIntegerDigits);
- assertTrue("", tuple.localeFlag);
- assertTrue("", tuple.patternFlag);
- assertTrue("", tuple.minIntegerDigitsFlag);
- assertFalse("", tuple.formatFlag);
-
- UnicodeString appendTo;
- assertEquals(
- "",
- "{locale: en, pattern: #,##0.00, minIntegerDigits: -10}",
- tuple.toString(appendTo));
-
- tuple.clear();
- appendTo.remove();
- assertEquals(
- "",
- "{}",
- tuple.toString(appendTo));
- tuple.setField(
- NumberFormatTestTuple::getFieldByName("aBadFieldName"),
- "someValue",
- status);
- if (status != U_ILLEGAL_ARGUMENT_ERROR) {
- errln("Expected U_ILLEGAL_ARGUMENT_ERROR");
- }
- status = U_ZERO_ERROR;
- tuple.setField(
- NumberFormatTestTuple::getFieldByName("minIntegerDigits"),
- "someBadValue",
- status);
- if (status != U_ILLEGAL_ARGUMENT_ERROR) {
- errln("Expected U_ILLEGAL_ARGUMENT_ERROR");
- }
-}
-
-void
-NumberFormatTest::TestDataDriven() {
- NumberFormatTestDataDriven dd;
- dd.setCaller(this);
- dd.run("numberformattestspecification.txt", FALSE);
-}
-
// Check the constant MAX_INT64_IN_DOUBLE.
// The value should convert to a double with no loss of precision.
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() {
- 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));
- return;
- }
- fmt->setMaximumIntegerDigits(INT32_MIN);
- UnicodeString appendTo;
- assertEquals("", "0", fmt->format(123, appendTo));
- appendTo.remove();
- assertEquals("", "0", fmt->format(12345, appendTo));
- delete fmt;
-}
-
void NumberFormatTest::TestGetAffixes() {
UErrorCode status = U_ZERO_ERROR;
DecimalFormatSymbols sym("en_US", 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(0);
+ FieldPosition fpos(FieldPosition::DONT_CARE);
clock_t start = clock();
for (int32_t i = 0; i < 1000000; ++i) {
UnicodeString append;
UErrorCode status = U_ZERO_ERROR;
MessageFormat fmt("{0, plural, one {I have # friend.} other {I have # friends.}}", status);
- FieldPosition fpos(0);
+ FieldPosition fpos(FieldPosition::DONT_CARE);
Formattable one(1.0);
Formattable three(3.0);
clock_t start = clock();
Locale en("en");
Measure measureC(23, MeasureUnit::createCelsius(status), status);
MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
- FieldPosition fpos(0);
+ FieldPosition fpos(FieldPosition::DONT_CARE);
clock_t start = clock();
for (int32_t i = 0; i < 1000000; ++i) {
UnicodeString appendTo;
assertEquals(
"ctor favors precision of currency",
"$5.00",
- fmt.format(5, result));
+ fmt.format((double)5, result));
result.remove();
fmt.applyPattern(pattern.unescape(), status);
assertEquals(
"applyPattern favors precision of pattern",
"$5",
- fmt.format(5, result));
+ fmt.format((double)5, result));
}
void NumberFormatTest::Test11868() {
}
void NumberFormatTest::Test10727_RoundingZero() {
- DigitList d;
- d.set(-0.0);
- assertFalse("", d.isPositive());
- d.round(3);
- assertFalse("", d.isPositive());
+ 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() {
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 result;
UnicodeString tripleIntlCurrency(" \\u00a4\\u00a4\\u00a4");
tripleIntlCurrency = tripleIntlCurrency.unescape();
- assertEquals("", tripleIntlCurrency, dfmt->getPositiveSuffix(result));
+ assertEquals("", tripleIntlCurrency, dfmt->getPositiveSuffix(result)); // use ICU 61 behavior
dfmt->setCurrency(USD);
// getPositiveSuffix() always returns the suffix for the
static UChar USD[] = {0x55, 0x53, 0x44, 0x0};
fmt.setCurrency(USD);
UnicodeString appendTo;
-
+
assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
UnicodeString topattern;
return;
}
fmt2.setCurrency(USD);
-
+
appendTo.remove();
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) {
}
}
-void NumberFormatTest::checkExceptionIssue11735() {
- UErrorCode status;
+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)) {
- errln((UnicodeString)
- "Fail: Construct DecimalFormatSymbols");
+ 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);
}
+}
- DecimalFormat fmt("0", symbols, status);
+void NumberFormatTest::Test11318_DoubleConversion() {
+ IcuTestErrorCode status(*this, "Test11318_DoubleConversion");
+ LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
if (U_FAILURE(status)) {
- errln((UnicodeString)
- "Fail: Construct DecimalFormat formatter");
+ 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);
+}
- ParsePosition ppos(0);
- fmt.parseCurrency("53.45", ppos); // NPE thrown here in ICU4J.
- assertEquals("Issue11735 ppos", 0, ppos.getIndex());
+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 */