+
+#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);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ } else {
+ int64_t long_number = 1;
+ UnicodeString expect = "0001";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),""));
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
+ }
+ }
+ }
+ {
+ UErrorCode status=U_ZERO_ERROR;
+ DecimalFormat df(UnicodeString("0000000000000000000",""),status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ } else {
+ int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
+ // uint8_t bits[8];
+ // memcpy(bits,&long_number,8);
+ // for(int i=0;i<8;i++) {
+ // logln("bits: %02X", (unsigned int)bits[i]);
+ // }
+ UnicodeString expect = "-9223372036854775808";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
+ }
+ }
+ }
+ {
+ UErrorCode status=U_ZERO_ERROR;
+ DecimalFormat df(UnicodeString("0000000000000000000",""),status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ } else {
+ int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
+ // uint8_t bits[8];
+ // memcpy(bits,&long_number,8);
+ // for(int i=0;i<8;i++) {
+ // logln("bits: %02X", (unsigned int)bits[i]);
+ // }
+ UnicodeString expect = "9223372036854775807";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
+ }
+ }
+ }
+ {
+ UErrorCode status=U_ZERO_ERROR;
+ DecimalFormat df(UnicodeString("0000000000000000000",""),status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ } else {
+ int64_t long_number = 0;
+ // uint8_t bits[8];
+ // memcpy(bits,&long_number,8);
+ // for(int i=0;i<8;i++) {
+ // logln("bits: %02X", (unsigned int)bits[i]);
+ // }
+ UnicodeString expect = "0000000000000000000";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
+ }
+ }
+ }
+ {
+ UErrorCode status=U_ZERO_ERROR;
+ DecimalFormat df(UnicodeString("0000000000000000000",""),status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ } else {
+ int64_t long_number = U_INT64_MIN + 1;
+ UnicodeString expect = "-9223372036854775807";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
+ }
+ }
+ }
+}
+
+
+void NumberFormatTest::TestFormattableSize(void) {
+ if(sizeof(FmtStackData) > UNUM_INTERNAL_STACKARRAY_SIZE) {
+ errln("Error: sizeof(FmtStackData)=%d, UNUM_INTERNAL_STACKARRAY_SIZE=%d\n",
+ sizeof(FmtStackData), UNUM_INTERNAL_STACKARRAY_SIZE);
+ } else if(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);
+ }
+}
+
+UBool NumberFormatTest::testFormattableAsUFormattable(const char *file, int line, Formattable &f) {
+ UnicodeString fileLine = UnicodeString(file)+UnicodeString(":")+line+UnicodeString(": ");
+
+ UFormattable *u = f.toUFormattable();
+ logln();
+ if (u == NULL) {
+ errln("%s:%d: Error: f.toUFormattable() retuned NULL.");
+ return FALSE;
+ }
+ logln("%s:%d: comparing Formattable with UFormattable", file, line);
+ logln(fileLine + toString(f));
+
+ UErrorCode status = U_ZERO_ERROR;
+ UErrorCode valueStatus = U_ZERO_ERROR;
+ UFormattableType expectUType = UFMT_COUNT; // invalid
+
+ UBool triedExact = FALSE; // did we attempt an exact comparison?
+ UBool exactMatch = FALSE; // was the exact comparison true?
+
+ switch( f.getType() ) {
+ case Formattable::kDate:
+ expectUType = UFMT_DATE;
+ exactMatch = (f.getDate()==ufmt_getDate(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ case Formattable::kDouble:
+ expectUType = UFMT_DOUBLE;
+ exactMatch = (f.getDouble()==ufmt_getDouble(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ case Formattable::kLong:
+ expectUType = UFMT_LONG;
+ exactMatch = (f.getLong()==ufmt_getLong(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ case Formattable::kString:
+ expectUType = UFMT_STRING;
+ {
+ UnicodeString str;
+ f.getString(str);
+ int32_t len;
+ const UChar* uch = ufmt_getUChars(u, &len, &valueStatus);
+ if(U_SUCCESS(valueStatus)) {
+ UnicodeString str2(uch, len);
+ assertTrue("UChar* NULL-terminated", uch[len]==0);
+ exactMatch = (str == str2);
+ }
+ triedExact = TRUE;
+ }
+ break;
+ case Formattable::kArray:
+ expectUType = UFMT_ARRAY;
+ triedExact = TRUE;
+ {
+ int32_t count = ufmt_getArrayLength(u, &valueStatus);
+ int32_t count2;
+ const Formattable *array2 = f.getArray(count2);
+ exactMatch = assertEquals(fileLine + " array count", count, count2);
+
+ if(exactMatch) {
+ for(int i=0;U_SUCCESS(valueStatus) && i<count;i++) {
+ UFormattable *uu = ufmt_getArrayItemByIndex(u, i, &valueStatus);
+ if(*Formattable::fromUFormattable(uu) != (array2[i])) {
+ errln("%s:%d: operator== did not match at index[%d] - %p vs %p", file, line, i,
+ (const void*)Formattable::fromUFormattable(uu), (const void*)&(array2[i]));
+ exactMatch = FALSE;
+ } else {
+ if(!testFormattableAsUFormattable("(sub item)",i,*Formattable::fromUFormattable(uu))) {
+ exactMatch = FALSE;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case Formattable::kInt64:
+ expectUType = UFMT_INT64;
+ exactMatch = (f.getInt64()==ufmt_getInt64(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ case Formattable::kObject:
+ expectUType = UFMT_OBJECT;
+ exactMatch = (f.getObject()==ufmt_getObject(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ }
+ UFormattableType uType = ufmt_getType(u, &status);
+
+ if(U_FAILURE(status)) {
+ errln("%s:%d: Error calling ufmt_getType - %s", file, line, u_errorName(status));
+ return FALSE;
+ }
+
+ if(uType != expectUType) {
+ errln("%s:%d: got type (%d) expected (%d) from ufmt_getType", file, line, (int) uType, (int) expectUType);
+ }
+
+ if(triedExact) {
+ if(U_FAILURE(valueStatus)) {
+ errln("%s:%d: got err %s trying to ufmt_get...() for exact match check", file, line, u_errorName(valueStatus));
+ } else if(!exactMatch) {
+ errln("%s:%d: failed exact match for the Formattable type", file, line);
+ } else {
+ logln("%s:%d: exact match OK", file, line);
+ }
+ } else {
+ logln("%s:%d: note, did not attempt exact match for this formattable type", file, line);
+ }
+
+ if( assertEquals(fileLine + " isNumeric()", f.isNumeric(), ufmt_isNumeric(u))
+ && f.isNumeric()) {
+ UErrorCode convStatus = U_ZERO_ERROR;
+
+ if(uType != UFMT_INT64) { // may fail to compare
+ assertTrue(fileLine + " as doubles ==", f.getDouble(convStatus)==ufmt_getDouble(u, &convStatus));
+ }
+
+ if( assertSuccess(fileLine + " (numeric conversion status)", convStatus) ) {
+ StringPiece fDecNum = f.getDecimalNumber(convStatus);
+#if 1
+ int32_t len;
+ const char *decNumChars = ufmt_getDecNumChars(u, &len, &convStatus);
+#else
+ // copy version
+ char decNumChars[200];
+ int32_t len = ufmt_getDecNumChars(u, decNumChars, 200, &convStatus);
+#endif
+
+ if( assertSuccess(fileLine + " (decNumbers conversion)", convStatus) ) {
+ logln(fileLine + decNumChars);
+ assertEquals(fileLine + " decNumChars length==", len, fDecNum.length());
+ assertEquals(fileLine + " decNumChars digits", decNumChars, fDecNum.data());
+ }
+
+ UErrorCode int64ConversionF = U_ZERO_ERROR;
+ int64_t l = f.getInt64(int64ConversionF);
+ UErrorCode int64ConversionU = U_ZERO_ERROR;
+ int64_t r = ufmt_getInt64(u, &int64ConversionU);
+
+ if( (l==r)
+ && ( uType != UFMT_INT64 ) // int64 better not overflow
+ && (U_INVALID_FORMAT_ERROR==int64ConversionU)
+ && (U_INVALID_FORMAT_ERROR==int64ConversionF) ) {
+ logln("%s:%d: OK: 64 bit overflow", file, line);
+ } else {
+ assertEquals(fileLine + " as int64 ==", l, r);
+ assertSuccess(fileLine + " Formattable.getnt64()", int64ConversionF);
+ assertSuccess(fileLine + " ufmt_getInt64()", int64ConversionU);
+ }
+ }
+ }
+ return exactMatch || !triedExact;
+}
+
+void NumberFormatTest::TestUFormattable(void) {
+ {
+ // test that a default formattable is equal to Formattable()
+ UErrorCode status = U_ZERO_ERROR;
+ LocalUFormattablePointer defaultUFormattable(ufmt_open(&status));
+ assertSuccess("calling umt_open", status);
+ Formattable defaultFormattable;
+ assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
+ (defaultFormattable
+ == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
+ assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
+ (defaultFormattable
+ == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
+ assertTrue((UnicodeString)"comparing Formattable() round tripped through UFormattable",
+ (defaultFormattable
+ == *(Formattable::fromUFormattable(defaultFormattable.toUFormattable()))));
+ assertTrue((UnicodeString)"comparing &Formattable() round tripped through UFormattable",
+ ((&defaultFormattable)
+ == Formattable::fromUFormattable(defaultFormattable.toUFormattable())));
+ assertFalse((UnicodeString)"comparing &Formattable() with ufmt_open()",
+ ((&defaultFormattable)
+ == Formattable::fromUFormattable(defaultUFormattable.getAlias())));
+ testFormattableAsUFormattable(__FILE__, __LINE__, defaultFormattable);
+ }
+ // test some random Formattables
+ {
+ Formattable f(ucal_getNow(), Formattable::kIsDate);
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ Formattable f((double)1.61803398874989484820); // golden ratio
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ Formattable f((int64_t)80994231587905127LL); // weight of the moon, in kilotons http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ Formattable f((int32_t)4); // random number, source: http://www.xkcd.com/221/
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ Formattable f("Hello world."); // should be invariant?
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ UErrorCode status2 = U_ZERO_ERROR;
+ Formattable f(StringPiece("73476730924573500000000.0"), status2); // weight of the moon, kg
+ assertSuccess("Constructing a StringPiece", status2);
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ UErrorCode status2 = U_ZERO_ERROR;
+ UObject *obj = new Locale();
+ Formattable f(obj);
+ assertSuccess("Constructing a Formattable from a default constructed Locale()", status2);
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ const Formattable array[] = {
+ Formattable(ucal_getNow(), Formattable::kIsDate),
+ Formattable((int32_t)4),
+ Formattable((double)1.234),
+ };
+
+ Formattable fa(array, 3);
+ testFormattableAsUFormattable(__FILE__, __LINE__, fa);
+ }
+}
+
+void NumberFormatTest::TestSignificantDigits(void) {
+ double input[] = {
+ 0, 0,
+ 0.1, -0.1,
+ 123, -123,
+ 12345, -12345,
+ 123.45, -123.45,
+ 123.44501, -123.44501,
+ 0.001234, -0.001234,
+ 0.00000000123, -0.00000000123,
+ 0.0000000000000000000123, -0.0000000000000000000123,
+ 1.2, -1.2,
+ 0.0000000012344501, -0.0000000012344501,
+ 123445.01, -123445.01,
+ 12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0,
+ };
+ const char* expected[] = {
+ "0.00", "0.00",
+ "0.100", "-0.100",
+ "123", "-123",
+ "12345", "-12345",
+ "123.45", "-123.45",
+ "123.45", "-123.45",
+ "0.001234", "-0.001234",
+ "0.00000000123", "-0.00000000123",
+ "0.0000000000000000000123", "-0.0000000000000000000123",
+ "1.20", "-1.20",
+ "0.0000000012345", "-0.0000000012345",
+ "123450", "-123450",
+ "12345000000000000000000000000000000", "-12345000000000000000000000000000000",
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+ Locale locale("en_US");
+ LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
+ NumberFormat::createInstance(locale, status)));
+ CHECK_DATA(status,"NumberFormat::createInstance")
+
+ numberFormat->setSignificantDigitsUsed(TRUE);
+ numberFormat->setMinimumSignificantDigits(3);
+ numberFormat->setMaximumSignificantDigits(5);
+ numberFormat->setGroupingUsed(false);
+
+ UnicodeString result;
+ UnicodeString expectedResult;
+ for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
+ numberFormat->format(input[i], result);
+ UnicodeString expectedResult(expected[i]);
+ if (result != expectedResult) {
+ errln((UnicodeString)"Expected: '" + expectedResult + "' got '" + result);
+ }
+ result.remove();
+ }
+}
+
+void NumberFormatTest::TestShowZero() {
+ UErrorCode status = U_ZERO_ERROR;
+ Locale locale("en_US");
+ LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
+ NumberFormat::createInstance(locale, status)));
+ CHECK_DATA(status, "NumberFormat::createInstance")
+
+ numberFormat->setSignificantDigitsUsed(TRUE);
+ numberFormat->setMaximumSignificantDigits(3);
+
+ UnicodeString result;
+ numberFormat->format(0.0, result);
+ if (result != "0") {
+ errln((UnicodeString)"Expected: 0, got " + result);
+ }
+}
+
+void NumberFormatTest::TestBug9936() {
+ UErrorCode status = U_ZERO_ERROR;
+ Locale locale("en_US");
+ LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
+ NumberFormat::createInstance(locale, status)));
+ if (U_FAILURE(status)) {
+ 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__);
+ }
+ numberFormat->setSignificantDigitsUsed(TRUE);
+ if (numberFormat->areSignificantDigitsUsed() == FALSE) {
+ errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
+ }
+
+ numberFormat->setSignificantDigitsUsed(FALSE);
+ if (numberFormat->areSignificantDigitsUsed() == TRUE) {
+ errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
+ }
+
+ numberFormat->setMinimumSignificantDigits(3);
+ if (numberFormat->areSignificantDigitsUsed() == FALSE) {
+ errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
+ }
+
+ numberFormat->setSignificantDigitsUsed(FALSE);
+ numberFormat->setMaximumSignificantDigits(6);
+ if (numberFormat->areSignificantDigitsUsed() == FALSE) {
+ errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
+ }
+
+}
+
+void NumberFormatTest::TestParseNegativeWithFaLocale() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status);
+ CHECK_DATA(status, "NumberFormat::createInstance")
+ test->setLenient(TRUE);
+ Formattable af;
+ ParsePosition ppos;
+ UnicodeString value("\\u200e-0,5");
+ value = value.unescape();
+ test->parse(value, af, ppos);
+ if (ppos.getIndex() == 0) {
+ errln("Expected -0,5 to parse for Farsi.");
+ }
+ delete test;
+}
+
+void NumberFormatTest::TestParseNegativeWithAlternateMinusSign() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("en", status);
+ CHECK_DATA(status, "NumberFormat::createInstance")
+ test->setLenient(TRUE);
+ Formattable af;
+ ParsePosition ppos;
+ UnicodeString value("\\u208B0.5");
+ value = value.unescape();
+ test->parse(value, af, ppos);
+ if (ppos.getIndex() == 0) {
+ errln(UnicodeString("Expected ") + value + UnicodeString(" to parse."));
+ }
+ delete test;
+}
+
+void NumberFormatTest::TestCustomCurrencySignAndSeparator() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols custom(Locale::getUS(), status);
+ CHECK(status, "DecimalFormatSymbols constructor");
+
+ custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "*");
+ custom.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, "^");
+ custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, ":");
+
+ UnicodeString pat(" #,##0.00");
+ pat.insert(0, (UChar)0x00A4);
+
+ DecimalFormat fmt(pat, custom, status);
+ CHECK(status, "DecimalFormat constructor");
+
+ UnicodeString numstr("* 1^234:56");
+ expect2(fmt, (Formattable)((double)1234.56), numstr);
+}
+
+typedef struct {
+ const char * locale;
+ UBool lenient;
+ UnicodeString numString;
+ double value;
+} SignsAndMarksItem;
+
+
+void NumberFormatTest::TestParseSignsAndMarks() {
+ const SignsAndMarksItem items[] = {
+ // locale lenient numString value
+ { "en", FALSE, CharsToUnicodeString("12"), 12 },
+ { "en", TRUE, CharsToUnicodeString("12"), 12 },
+ { "en", FALSE, CharsToUnicodeString("-23"), -23 },
+ { "en", TRUE, CharsToUnicodeString("-23"), -23 },
+ { "en", TRUE, CharsToUnicodeString("- 23"), -23 },
+ { "en", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
+ { "en", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
+ { "en", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
+
+ { "en@numbers=arab", FALSE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
+ { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
+ { "en@numbers=arab", FALSE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
+ { "en@numbers=arab", TRUE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
+ { "en@numbers=arab", TRUE, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
+ { "en@numbers=arab", FALSE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
+ { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
+ { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
+
+ { "en@numbers=arabext", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
+ { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
+ { "en@numbers=arabext", FALSE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
+ { "en@numbers=arabext", TRUE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
+ { "en@numbers=arabext", TRUE, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
+ { "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 },
+ { "he", TRUE, CharsToUnicodeString("-23"), -23 },
+ { "he", TRUE, CharsToUnicodeString("- 23"), -23 },
+ { "he", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
+ { "he", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
+ { "he", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
+
+ { "ar", FALSE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
+ { "ar", TRUE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
+ { "ar", FALSE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
+ { "ar", TRUE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
+ { "ar", TRUE, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
+ { "ar", FALSE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
+ { "ar", TRUE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
+ { "ar", TRUE, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
+
+ { "ar_MA", FALSE, CharsToUnicodeString("12"), 12 },
+ { "ar_MA", TRUE, CharsToUnicodeString("12"), 12 },
+ { "ar_MA", FALSE, CharsToUnicodeString("-23"), -23 },
+ { "ar_MA", TRUE, CharsToUnicodeString("-23"), -23 },
+ { "ar_MA", TRUE, CharsToUnicodeString("- 23"), -23 },
+ { "ar_MA", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
+ { "ar_MA", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
+ { "ar_MA", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
+
+ { "fa", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
+ { "fa", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
+ { "fa", FALSE, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
+ { "fa", TRUE, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
+ { "fa", TRUE, CharsToUnicodeString("\\u2212 \\u06F6\\u06F7"), -67 },
+ { "fa", FALSE, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
+ { "fa", TRUE, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
+ { "fa", TRUE, CharsToUnicodeString("\\u200E\\u2212\\u200E \\u06F6\\u06F7"), -67 },
+
+ { "ps", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
+ { "ps", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
+ { "ps", FALSE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
+ { "ps", TRUE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
+ { "ps", TRUE, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
+ { "ps", FALSE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
+ { "ps", TRUE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
+ { "ps", TRUE, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
+ { "ps", FALSE, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
+ { "ps", TRUE, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
+ { "ps", TRUE, CharsToUnicodeString("-\\u200E \\u06F6\\u06F7"), -67 },
+ // terminator
+ { NULL, 0, UnicodeString(""), 0 },
+ };
+
+ const SignsAndMarksItem * itemPtr;
+ for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
+ UErrorCode status = U_ZERO_ERROR;
+ NumberFormat *numfmt = NumberFormat::createInstance(Locale(itemPtr->locale), status);
+ if (U_SUCCESS(status)) {
+ numfmt->setLenient(itemPtr->lenient);
+ Formattable fmtobj;
+ ParsePosition ppos;
+ numfmt->parse(itemPtr->numString, fmtobj, ppos);
+ if (ppos.getIndex() == itemPtr->numString.length()) {
+ double parsedValue = fmtobj.getDouble(status);
+ if (U_FAILURE(status) || parsedValue != itemPtr->value) {
+ errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives value " + parsedValue);
+ }
+ } else {
+ errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives position " + ppos.getIndex());
+ }
+ } else {
+ dataerrln("FAIL: NumberFormat::createInstance for locale % gives error %s", itemPtr->locale, u_errorName(status));
+ }
+ delete numfmt;
+ }
+}
+
+typedef struct {
+ DecimalFormat::ERoundingMode mode;
+ double value;
+ UnicodeString expected;
+} Test10419Data;
+
+
+// Tests that rounding works right when fractional digits is set to 0.
+void NumberFormatTest::Test10419RoundingWith0FractionDigits() {
+ const Test10419Data items[] = {
+ { DecimalFormat::kRoundCeiling, 1.488, "2"},
+ { DecimalFormat::kRoundDown, 1.588, "1"},
+ { DecimalFormat::kRoundFloor, 1.888, "1"},
+ { DecimalFormat::kRoundHalfDown, 1.5, "1"},
+ { DecimalFormat::kRoundHalfEven, 2.5, "2"},
+ { DecimalFormat::kRoundHalfUp, 2.5, "3"},
+ { DecimalFormat::kRoundUp, 1.5, "2"},
+ };
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<DecimalFormat> decfmt((DecimalFormat *) NumberFormat::createInstance(Locale("en_US"), status));
+ if (U_FAILURE(status)) {
+ dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
+ return;
+ }
+ for (int32_t i = 0; i < UPRV_LENGTHOF(items); ++i) {
+ decfmt->setRoundingMode(items[i].mode);
+ decfmt->setMaximumFractionDigits(0);
+ UnicodeString actual;
+ if (items[i].expected != decfmt->format(items[i].value, actual)) {
+ errln("Expected " + items[i].expected + ", got " + actual);
+ }
+ }
+}
+
+void NumberFormatTest::Test10468ApplyPattern() {
+ // Padding char of fmt is now 'a'
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat fmt("'I''ll'*a###.##", status);
+
+ if (U_FAILURE(status)) {
+ errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
+ return;
+ }
+
+ if (fmt.getPadCharacterString() != UnicodeString("a")) {
+ errln("Padding character should be 'a'.");
+ return;
+ }
+
+ // 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.");
+ }
+}
+
+void NumberFormatTest::TestRoundingScientific10542() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat format("0.00E0", status);
+ if (U_FAILURE(status)) {
+ errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
+ return;
+ }
+
+ DecimalFormat::ERoundingMode roundingModes[] = {
+ DecimalFormat::kRoundCeiling,
+ DecimalFormat::kRoundDown,
+ DecimalFormat::kRoundFloor,
+ DecimalFormat::kRoundHalfDown,
+ DecimalFormat::kRoundHalfEven,
+ DecimalFormat::kRoundHalfUp,
+ DecimalFormat::kRoundUp};
+ const char *descriptions[] = {
+ "Round Ceiling",
+ "Round Down",
+ "Round Floor",
+ "Round half down",
+ "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.
+ const char *expected[] = {
+ "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.02E-3", "3.02E-3", "3.02E-3",
+ "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.01E-3",
+ "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.01E-3", "3.01E-3", "3.01E-3",
+ "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.02E-3",
+ "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
+ "-3.01E-3", "-3.01E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
+ "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.02E-3", "3.02E-3", "3.02E-3"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+ {
+ double values[] = {-3006.0, -3005, -3004, 3014, 3015, 3016};
+ // The order of these expected values correspond to the order of roundingModes and the order of values.
+ const char *expected[] = {
+ "-3.00E3", "-3.00E3", "-3.00E3", "3.02E3", "3.02E3", "3.02E3",
+ "-3.00E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.01E3",
+ "-3.01E3", "-3.01E3", "-3.01E3", "3.01E3", "3.01E3", "3.01E3",
+ "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.02E3",
+ "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
+ "-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
+ "-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+/* Commented out for now until we decide how rounding to zero should work, +0 vs. -0
+ {
+ double values[] = {0.0, -0.0};
+ // The order of these expected values correspond to the order of roundingModes and the order of values.
+ const char *expected[] = {
+ "0.00E0", "-0.00E0",
+ "0.00E0", "-0.00E0",
+ "0.00E0", "-0.00E0",
+ "0.00E0", "-0.00E0",
+ "0.00E0", "-0.00E0",
+ "0.00E0", "-0.00E0",
+ "0.00E0", "-0.00E0"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+*/
+ {
+
+ double values[] = {1e25, 1e25 + 1e15, 1e25 - 1e15};
+ // The order of these expected values correspond to the order of roundingModes and the order of values.
+ const char *expected[] = {
+ "1.00E25", "1.01E25", "1.00E25",
+ "1.00E25", "1.00E25", "9.99E24",
+ "1.00E25", "1.00E25", "9.99E24",
+ "1.00E25", "1.00E25", "1.00E25",
+ "1.00E25", "1.00E25", "1.00E25",
+ "1.00E25", "1.00E25", "1.00E25",
+ "1.00E25", "1.01E25", "1.00E25"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+ {
+ double values[] = {-1e25, -1e25 + 1e15, -1e25 - 1e15};
+ // The order of these expected values correspond to the order of roundingModes and the order of values.
+ const char *expected[] = {
+ "-1.00E25", "-9.99E24", "-1.00E25",
+ "-1.00E25", "-9.99E24", "-1.00E25",
+ "-1.00E25", "-1.00E25", "-1.01E25",
+ "-1.00E25", "-1.00E25", "-1.00E25",
+ "-1.00E25", "-1.00E25", "-1.00E25",
+ "-1.00E25", "-1.00E25", "-1.00E25",
+ "-1.00E25", "-1.00E25", "-1.01E25"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+ {
+ double values[] = {1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
+ // The order of these expected values correspond to the order of roundingModes and the order of values.
+ const char *expected[] = {
+ "1.00E-25", "1.01E-25", "1.00E-25",
+ "1.00E-25", "1.00E-25", "9.99E-26",
+ "1.00E-25", "1.00E-25", "9.99E-26",
+ "1.00E-25", "1.00E-25", "1.00E-25",
+ "1.00E-25", "1.00E-25", "1.00E-25",
+ "1.00E-25", "1.00E-25", "1.00E-25",
+ "1.00E-25", "1.01E-25", "1.00E-25"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+ {
+ double values[] = {-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
+ // The order of these expected values correspond to the order of roundingModes and the order of values.
+ const char *expected[] = {
+ "-1.00E-25", "-9.99E-26", "-1.00E-25",
+ "-1.00E-25", "-9.99E-26", "-1.00E-25",
+ "-1.00E-25", "-1.00E-25", "-1.01E-25",
+ "-1.00E-25", "-1.00E-25", "-1.00E-25",
+ "-1.00E-25", "-1.00E-25", "-1.00E-25",
+ "-1.00E-25", "-1.00E-25", "-1.00E-25",
+ "-1.00E-25", "-1.00E-25", "-1.01E-25"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+}
+
+void NumberFormatTest::TestZeroScientific10547() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat fmt("0.00E0", status);
+ if (!assertSuccess("Formt creation", status)) {
+ return;
+ }
+ UnicodeString out;
+ fmt.format(-0.0, out);
+ assertEquals("format", "-0.00E0", out);
+}
+
+void NumberFormatTest::verifyRounding(
+ DecimalFormat& format,
+ const double *values,
+ const char * const *expected,
+ const DecimalFormat::ERoundingMode *roundingModes,
+ const char * const *descriptions,
+ int32_t valueSize,
+ int32_t roundingModeSize) {
+ for (int32_t i = 0; i < roundingModeSize; ++i) {
+ format.setRoundingMode(roundingModes[i]);
+ for (int32_t j = 0; j < valueSize; j++) {
+ UnicodeString currentExpected(expected[i * valueSize + j]);
+ currentExpected = currentExpected.unescape();
+ 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);
+ }
+ }
+ }
+}
+
+void NumberFormatTest::TestAccountingCurrency() {
+ UErrorCode status = U_ZERO_ERROR;
+ UNumberFormatStyle style = UNUM_CURRENCY_ACCOUNTING;
+
+ expect(NumberFormat::createInstance("en_US", style, status),
+ (Formattable)1234.5, "$1,234.50", TRUE, status);
+ expect(NumberFormat::createInstance("en_US", style, status),
+ (Formattable)-1234.5, "($1,234.50)", TRUE, status);
+ expect(NumberFormat::createInstance("en_US", style, status),
+ (Formattable)0, "$0.00", TRUE, status);
+ expect(NumberFormat::createInstance("en_US", style, status),
+ (Formattable)-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);
+}
+
+// for #5186
+void NumberFormatTest::TestEquality() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols* symbols = new DecimalFormatSymbols(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);
+ 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) {
+ errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth");
+ }
+ delete fmtClone;
+
+ delete fmtBase;
+}
+
+void NumberFormatTest::TestCurrencyUsage() {
+ double agent = 123.567;
+
+ UErrorCode status;
+ DecimalFormat *fmt;
+
+ // compare the Currency and Currency Cash Digits
+ // Note that as of CLDR 26:
+ // * TWD switches from 0 decimals to 2; PKR still has 0, so change test to that
+ // * CAD rounds to .05 in cash mode only
+ // 1st time for getter/setter, 2nd time for factory method
+ Locale enUS_PKR("en_US@currency=PKR");
+
+ for(int i=0; i<2; i++){
+ status = U_ZERO_ERROR;
+ if(i == 0){
+ fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_PKR, UNUM_CURRENCY, status);
+ if (assertSuccess("en_US@currency=PKR/CURRENCY", status, TRUE) == FALSE) {
+ continue;
+ }
+
+ UnicodeString original;
+ fmt->format(agent,original);
+ assertEquals("Test Currency Usage 1", UnicodeString("PKR124"), original);
+
+ // test the getter here
+ UCurrencyUsage curUsage = fmt->getCurrencyUsage();
+ assertEquals("Test usage getter - standard", curUsage, UCURR_USAGE_STANDARD);
+
+ fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
+ }else{
+ fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_PKR, UNUM_CASH_CURRENCY, status);
+ if (assertSuccess("en_US@currency=PKR/CASH", status, TRUE) == FALSE) {
+ continue;
+ }
+ }
+
+ // must be usage = cash
+ UCurrencyUsage curUsage = fmt->getCurrencyUsage();
+ assertEquals("Test usage getter - cash", curUsage, UCURR_USAGE_CASH);
+
+ UnicodeString cash_currency;
+ fmt->format(agent,cash_currency);
+ assertEquals("Test Currency Usage 2", UnicodeString("PKR124"), cash_currency);
+ delete fmt;
+ }
+
+ // compare the Currency and Currency Cash Rounding
+ // 1st time for getter/setter, 2nd time for factory method
+ Locale enUS_CAD("en_US@currency=CAD");
+ for(int i=0; i<2; i++){
+ status = U_ZERO_ERROR;
+ if(i == 0){
+ fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
+ if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
+ continue;
+ }
+
+ UnicodeString original_rounding;
+ fmt->format(agent, original_rounding);
+ assertEquals("Test Currency Usage 3", UnicodeString("CA$123.57"), original_rounding);
+ fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
+ }else{
+ 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);
+ delete fmt;
+ }
+
+ // Test the currency change
+ // 1st time for getter/setter, 2nd time for factory method
+ const UChar CUR_PKR[] = {0x50, 0x4B, 0x52, 0};
+ for(int i=0; i<2; i++){
+ status = U_ZERO_ERROR;
+ if(i == 0){
+ fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
+ if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
+ continue;
+ }
+ fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
+ }else{
+ fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
+ if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
+ continue;
+ }
+ }
+
+ 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);
+
+ 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);
+ 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.
+// A failure may indicate a platform with a different double format, requiring
+// a revision to the constant.
+//
+// Note that this is actually hard to test, because the language standard gives
+// compilers considerable flexibility to do unexpected things with rounding and
+// with overflow in simple int to/from float conversions. Some compilers will completely optimize
+// away a simple round-trip conversion from int64_t -> double -> int64_t.
+
+void NumberFormatTest::TestDoubleLimit11439() {
+ char buf[50];
+ for (int64_t num = MAX_INT64_IN_DOUBLE-10; num<=MAX_INT64_IN_DOUBLE; num++) {
+ sprintf(buf, "%lld", (long long)num);
+ double fNum = 0.0;
+ sscanf(buf, "%lf", &fNum);
+ int64_t rtNum = 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;
+ }
+ }
+ for (int64_t num = -MAX_INT64_IN_DOUBLE+10; num>=-MAX_INT64_IN_DOUBLE; num--) {
+ sprintf(buf, "%lld", (long long)num);
+ double fNum = 0.0;
+ sscanf(buf, "%lf", &fNum);
+ int64_t rtNum = 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);
+ UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
+ pattern = pattern.unescape();
+ DecimalFormat fmt(pattern, sym, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ return;
+ }
+ UnicodeString affixStr;
+ assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
+ assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
+ assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
+ assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
+
+ // Test equality with affixes. set affix methods can't capture special
+ // characters which is why equality should fail.
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString someAffix;
+ fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(someAffix));
+ assertTrue("", fmt != fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString someAffix;
+ fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(someAffix));
+ assertTrue("", fmt != fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString someAffix;
+ fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(someAffix));
+ assertTrue("", fmt != fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString someAffix;
+ fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(someAffix));
+ assertTrue("", fmt != fmtCopy);
+ }
+ fmt.setPositivePrefix("Don't");
+ fmt.setPositiveSuffix("do");
+ UnicodeString someAffix("be''eet\\u00a4\\u00a4\\u00a4 it.");
+ someAffix = someAffix.unescape();
+ fmt.setNegativePrefix(someAffix);
+ fmt.setNegativeSuffix("%");
+ assertEquals("", "Don't", fmt.getPositivePrefix(affixStr));
+ assertEquals("", "do", fmt.getPositiveSuffix(affixStr));
+ assertEquals("", someAffix, fmt.getNegativePrefix(affixStr));
+ assertEquals("", "%", fmt.getNegativeSuffix(affixStr));
+}
+
+void NumberFormatTest::TestToPatternScientific11648() {
+ UErrorCode status = U_ZERO_ERROR;
+ Locale en("en");
+ DecimalFormatSymbols sym(en, status);
+ DecimalFormat fmt("0.00", sym, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ return;
+ }
+ fmt.setScientificNotation(TRUE);
+ UnicodeString pattern;
+ assertEquals("", "0.00E0", fmt.toPattern(pattern));
+ DecimalFormat fmt2(pattern, sym, status);
+ assertSuccess("", status);
+}
+
+void NumberFormatTest::TestBenchmark() {
+/*
+ UErrorCode status = U_ZERO_ERROR;
+ Locale en("en");
+ DecimalFormatSymbols sym(en, status);
+ DecimalFormat fmt("0.0000000", new DecimalFormatSymbols(sym), status);
+// DecimalFormat fmt("0.00000E0", new DecimalFormatSymbols(sym), status);
+// DecimalFormat fmt("0", new DecimalFormatSymbols(sym), status);
+ FieldPosition fpos(0);
+ clock_t start = clock();
+ for (int32_t i = 0; i < 1000000; ++i) {
+ UnicodeString append;
+ fmt.format(3.0, append, fpos, status);
+// fmt.format(4.6692016, append, fpos, status);
+// fmt.format(1234567.8901, append, fpos, status);
+// fmt.format(2.99792458E8, append, fpos, status);
+// fmt.format(31, append);
+ }
+ errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
+ assertSuccess("", status);
+
+ UErrorCode status = U_ZERO_ERROR;
+ MessageFormat fmt("{0, plural, one {I have # friend.} other {I have # friends.}}", status);
+ FieldPosition fpos(0);
+ Formattable one(1.0);
+ Formattable three(3.0);
+ clock_t start = clock();
+ for (int32_t i = 0; i < 500000; ++i) {
+ UnicodeString append;
+ fmt.format(&one, 1, append, fpos, status);
+ UnicodeString append2;
+ fmt.format(&three, 1, append2, fpos, status);
+ }
+ errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
+ assertSuccess("", status);
+
+ UErrorCode status = U_ZERO_ERROR;
+ Locale en("en");
+ Measure measureC(23, MeasureUnit::createCelsius(status), status);
+ MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
+ FieldPosition fpos(0);
+ clock_t start = clock();
+ for (int32_t i = 0; i < 1000000; ++i) {
+ UnicodeString appendTo;
+ fmt.formatMeasures(
+ &measureC, 1, appendTo, fpos, status);
+ }
+ errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
+ assertSuccess("", status);
+*/
+}
+
+void NumberFormatTest::TestFractionalDigitsForCurrency() {
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance("en", status));
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating NumberFormat - %s", u_errorName(status));
+ return;
+ }
+ UChar JPY[] = {0x4A, 0x50, 0x59, 0x0};
+ fmt->setCurrency(JPY, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ assertEquals("", 0, fmt->getMaximumFractionDigits());
+}
+
+
+void NumberFormatTest::TestFormatCurrencyPlural() {
+ UErrorCode status = U_ZERO_ERROR;
+ Locale locale = Locale::createCanonical("en_US");
+ NumberFormat *fmt = NumberFormat::createInstance(locale, UNUM_CURRENCY_PLURAL, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating NumberFormat - %s", u_errorName(status));
+ return;
+ }
+ UnicodeString formattedNum;
+ fmt->format(11234.567, formattedNum, NULL, status);
+ assertEquals("", "11,234.57 US dollars", formattedNum);
+ delete fmt;
+}
+
+void NumberFormatTest::TestCtorApplyPatternDifference() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols sym("en_US", status);
+ UnicodeString pattern("\\u00a40");
+ DecimalFormat fmt(pattern.unescape(), sym, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ return;
+ }
+ UnicodeString result;
+ assertEquals(
+ "ctor favors precision of currency",
+ "$5.00",
+ fmt.format(5, result));
+ result.remove();
+ fmt.applyPattern(pattern.unescape(), status);
+ assertEquals(
+ "applyPattern favors precision of pattern",
+ "$5",
+ fmt.format(5, result));
+}
+
+void NumberFormatTest::Test11868() {
+ double posAmt = 34.567;
+ double negAmt = -9876.543;
+
+ Locale selectedLocale("en_US");
+ UErrorCode status = U_ZERO_ERROR;
+
+ UnicodeString result;
+ FieldPosition fpCurr(UNUM_CURRENCY_FIELD);
+ LocalPointer<NumberFormat> fmt(
+ NumberFormat::createInstance(
+ selectedLocale, UNUM_CURRENCY_PLURAL, status));
+ if (!assertSuccess("Format creation", status)) {
+ return;
+ }
+ fmt->format(posAmt, result, fpCurr, status);
+ assertEquals("", "34.57 US dollars", result);
+ assertEquals("begin index", 6, fpCurr.getBeginIndex());
+ assertEquals("end index", 16, fpCurr.getEndIndex());
+
+ // Test field position iterator
+ {
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_INTEGER_FIELD, 0, 2},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
+ {UNUM_FRACTION_FIELD, 3, 5},
+ {UNUM_CURRENCY_FIELD, 6, 16},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt->format(posAmt, result, &iter, status);
+ assertEquals("", "34.57 US dollars", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+
+ result.remove();
+ fmt->format(negAmt, result, fpCurr, status);
+ assertEquals("", "-9,876.54 US dollars", result);
+ assertEquals("begin index", 10, fpCurr.getBeginIndex());
+ assertEquals("end index", 20, fpCurr.getEndIndex());
+
+ // Test field position iterator
+ {
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_SIGN_FIELD, 0, 1},
+ {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
+ {UNUM_INTEGER_FIELD, 1, 6},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 6, 7},
+ {UNUM_FRACTION_FIELD, 7, 9},
+ {UNUM_CURRENCY_FIELD, 10, 20},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt->format(negAmt, result, &iter, status);
+ assertEquals("", "-9,876.54 US dollars", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+}
+
+void NumberFormatTest::Test10727_RoundingZero() {
+ DigitList d;
+ d.set(-0.0);
+ assertFalse("", d.isPositive());
+ d.round(3);
+ assertFalse("", d.isPositive());
+}
+
+void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
+ {
+ const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> fmt(
+ NumberFormat::createCurrencyInstance("en", status));
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
+ dfmt->setCurrency(USD);
+ UnicodeString result;
+
+ // This line should be a no-op. I am setting the positive prefix
+ // to be the same thing it was before.
+ dfmt->setPositivePrefix(dfmt->getPositivePrefix(result));
+
+ UnicodeString appendTo;
+ assertEquals("", "$3.78", dfmt->format(3.78, appendTo, status));
+ assertSuccess("", status);
+ }
+ {
+ const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> fmt(
+ NumberFormat::createInstance("en", UNUM_CURRENCY_PLURAL, status));
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
+ UnicodeString result;
+ UnicodeString tripleIntlCurrency(" \\u00a4\\u00a4\\u00a4");
+ tripleIntlCurrency = tripleIntlCurrency.unescape();
+ assertEquals("", tripleIntlCurrency, dfmt->getPositiveSuffix(result));
+ dfmt->setCurrency(USD);
+
+ // getPositiveSuffix() always returns the suffix for the
+ // "other" plural category
+ assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
+ UnicodeString appendTo;
+ assertEquals("", "3.78 US dollars", dfmt->format(3.78, appendTo, status));
+ assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
+ dfmt->setPositiveSuffix("booya");
+ appendTo.remove();
+ assertEquals("", "3.78booya", dfmt->format(3.78, appendTo, status));
+ assertEquals("", "booya", dfmt->getPositiveSuffix(result));
+ }
+}
+
+void NumberFormatTest::Test11475_signRecognition() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols sym("en", status);
+ UnicodeString result;
+ {
+ DecimalFormat fmt("+0.00", sym, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_SIGN_FIELD, 0, 1},
+ {UNUM_INTEGER_FIELD, 1, 2},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
+ {UNUM_FRACTION_FIELD, 3, 5},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt.format(2.3, result, &iter, status);
+ assertEquals("", "+2.30", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+ {
+ DecimalFormat fmt("++0.00+;-(#)--", sym, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ {
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_SIGN_FIELD, 0, 2},
+ {UNUM_INTEGER_FIELD, 2, 3},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
+ {UNUM_FRACTION_FIELD, 4, 6},
+ {UNUM_SIGN_FIELD, 6, 7},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt.format(2.3, result, &iter, status);
+ assertEquals("", "++2.30+", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+ {
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_SIGN_FIELD, 0, 1},
+ {UNUM_INTEGER_FIELD, 2, 3},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
+ {UNUM_FRACTION_FIELD, 4, 6},
+ {UNUM_SIGN_FIELD, 7, 9},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt.format(-2.3, result, &iter, status);
+ assertEquals("", "-(2.30)--", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+ }
+}
+
+void NumberFormatTest::Test11640_getAffixes() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols symbols("en_US", status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
+ pattern = pattern.unescape();
+ DecimalFormat fmt(pattern, symbols, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ UnicodeString affixStr;
+ assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
+ assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
+ assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
+ assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
+}
+
+void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
+ UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
+ pattern = pattern.unescape();
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat fmt(pattern, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ static UChar USD[] = {0x55, 0x53, 0x44, 0x0};
+ fmt.setCurrency(USD);
+ UnicodeString appendTo;
+
+ assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
+
+ UnicodeString topattern;
+ fmt.toPattern(topattern);
+ DecimalFormat fmt2(topattern, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ fmt2.setCurrency(USD);
+
+ appendTo.remove();
+ assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
+}
+
+
+void NumberFormatTest::verifyFieldPositionIterator(
+ NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
+ int32_t idx = 0;
+ FieldPosition fp;
+ while (iter.next(fp)) {
+ if (expected[idx].spos == -1) {
+ errln("Iterator should have ended. got %d", fp.getField());
+ return;
+ }
+ assertEquals("id", expected[idx].id, fp.getField());
+ assertEquals("start", expected[idx].spos, fp.getBeginIndex());
+ assertEquals("end", expected[idx].epos, fp.getEndIndex());
+ ++idx;
+ }
+ if (expected[idx].spos != -1) {
+ errln("Premature end of iterator. expected %d", expected[idx].id);
+ }
+}
+
+void NumberFormatTest::checkExceptionIssue11735() {
+ UErrorCode status;
+ Locale enLocale("en");
+ DecimalFormatSymbols symbols(enLocale, status);
+
+ if (U_FAILURE(status)) {
+ errln((UnicodeString)
+ "Fail: Construct DecimalFormatSymbols");
+ }
+
+ DecimalFormat fmt("0", symbols, status);
+ if (U_FAILURE(status)) {
+ errln((UnicodeString)
+ "Fail: Construct DecimalFormat formatter");
+ }
+
+ ParsePosition ppos(0);
+ fmt.parseCurrency("53.45", ppos); // NPE thrown here in ICU4J.
+ assertEquals("Issue11735 ppos", 0, ppos.getIndex());
+}
+