X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/4388f060552cc537e71e957d32f35e9d75a61233..340931cb2e044a2141d11567dd0f782524e32994:/icuSources/test/intltest/numrgts.cpp diff --git a/icuSources/test/intltest/numrgts.cpp b/icuSources/test/intltest/numrgts.cpp index 8617bfc0..7bdb5f86 100644 --- a/icuSources/test/intltest/numrgts.cpp +++ b/icuSources/test/intltest/numrgts.cpp @@ -1,5 +1,7 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /*********************************************************************** - * Copyright (c) 1997-2012, International Business Machines Corporation + * Copyright (c) 1997-2016, International Business Machines Corporation * and others. All Rights Reserved. ***********************************************************************/ @@ -9,6 +11,7 @@ #include "numrgts.h" +#include // std::signbit #include // DBL_MIN, DBL_MAX #include @@ -19,7 +22,10 @@ #include "unicode/calendar.h" #include "unicode/datefmt.h" #include "unicode/ucurr.h" +#include "cmemory.h" +#include "cstr.h" #include "putilimp.h" +#include "uassert.h" class MyNumberFormatTest : public NumberFormat { @@ -29,10 +35,10 @@ public: virtual UnicodeString& format( double number, UnicodeString& toAppendTo, - FieldPosition& pos, + FieldPositionIterator* posIter, UErrorCode& status) const { - return NumberFormat::format(number, toAppendTo, pos, status); + return NumberFormat::format(number, toAppendTo, posIter, status); } /* Just keep this here to make some of the compilers happy */ @@ -72,7 +78,7 @@ public: { NumberFormat::parse(text, result, status); } - virtual Format* clone() const + virtual MyNumberFormatTest* clone() const { return NULL; } virtual UnicodeString& format(int32_t, @@ -170,6 +176,9 @@ NumberFormatRegressionTest::runIndexedTest( int32_t index, UBool exec, const cha CASE(60,TestJ691); CASE(61,Test8199); CASE(62,Test9109); + CASE(63,Test9780); + CASE(64,Test9677); + CASE(65,Test10361); default: name = ""; break; } @@ -287,15 +296,15 @@ void NumberFormatRegressionTest::Test4088161 (void) df->setMinimumFractionDigits(0); df->setMaximumFractionDigits(16); UnicodeString sBuf1; - FieldPosition fp1(0); + FieldPosition fp1(FieldPosition::DONT_CARE); logln(UnicodeString("d = ") + d); - logln("maxFractionDigits = " + df->getMaximumFractionDigits()); - + logln(UnicodeString("maxFractionDigits = ") + df->getMaximumFractionDigits()); + logln(" format(d) = '" + df->format(d, sBuf1, fp1) + "'"); df->setMaximumFractionDigits(17); UnicodeString sBuf2; - FieldPosition fp2(0); - logln("maxFractionDigits = " + df->getMaximumFractionDigits()); + FieldPosition fp2(FieldPosition::DONT_CARE); + logln(UnicodeString("maxFractionDigits = ") + df->getMaximumFractionDigits()); sBuf2 = df->format(d, sBuf2, fp2); if(sBuf2 != "100") errln(" format(d) = '" + sBuf2 + "'"); @@ -342,7 +351,10 @@ void NumberFormatRegressionTest::Test4087535 (void) { UErrorCode status = U_ZERO_ERROR; DecimalFormat *df = new DecimalFormat(status); - failure(status, "new DecimalFormat", ""); + if (U_FAILURE(status)) { + dataerrln("Error creating DecimalFormat - %s", u_errorName(status)); + return; + } df->setMinimumIntegerDigits(0); double n = 0; @@ -367,13 +379,16 @@ void NumberFormatRegressionTest::Test4088503 (void) { UErrorCode status = U_ZERO_ERROR; DecimalFormat *df = new DecimalFormat(status); - failure(status, "new DecimalFormat", ""); + if (U_FAILURE(status)) { + dataerrln("Error creating DecimalFormat - %s", u_errorName(status)); + return; + } df->setGroupingSize(0); UnicodeString sBuf; FieldPosition fp(FieldPosition::DONT_CARE); //try { logln(df->format((int32_t)123, sBuf, fp)); - //if(fp == FieldPosition(0)) + //if(fp == FieldPosition(FieldPosition::DONT_CARE)) // errln("Test for bug 4088503 failed."); /*} catch (Exception foo) { errln("Test for bug 4088503 failed."); @@ -534,8 +549,8 @@ void NumberFormatRegressionTest::Test4086575(void) // nbsp = \u00a0 //nf->applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)"); UChar patChars[] = { - 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x3b, - 0x28, 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x29 + 0x23, 0x202f, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x3b, + 0x28, 0x23, 0x202f, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x29 }; UnicodeString pat(patChars, 19, 19); nf->applyLocalizedPattern(pat, status); @@ -546,7 +561,7 @@ void NumberFormatRegressionTest::Test4086575(void) buffer = nf->format((int32_t)1234, buffer, pos); //if (buffer != UnicodeString("1\u00a0234,00")) UChar c[] = { - 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30 + 0x31, 0x202f, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30 }; UnicodeString cc(c, 8, 8); if (buffer != cc) @@ -555,7 +570,7 @@ void NumberFormatRegressionTest::Test4086575(void) buffer.remove(); buffer = nf->format((int32_t)-1234, buffer, pos); UChar c1[] = { - 0x28, 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30, 0x29 + 0x28, 0x31, 0x202f, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30, 0x29 }; UnicodeString cc1(c1, 10, 10); if (buffer != cc1) @@ -681,7 +696,7 @@ void NumberFormatRegressionTest::Test4090489 (void) double d = 1.000000000000001E7; //BigDecimal bd = new BigDecimal(d); UnicodeString sb; - FieldPosition fp(0); + FieldPosition fp(FieldPosition::DONT_CARE); logln(UnicodeString("d = ") + d); //logln("BigDecimal.toString(): " + bd.toString()); df->format(d, sb, fp); @@ -793,29 +808,29 @@ void NumberFormatRegressionTest::Test4092480 (void) dfFoo->applyPattern("0000;-000", status); failure(status, "dfFoo->applyPattern"); UnicodeString temp; - if (dfFoo->toPattern(temp) != UnicodeString("#0000")) - errln("dfFoo.toPattern : " + dfFoo->toPattern(temp)); + if (dfFoo->toPattern(temp) != UnicodeString("0000")) + errln("ERROR: dfFoo.toPattern : " + dfFoo->toPattern(temp)); FieldPosition pos(FieldPosition::DONT_CARE); logln(dfFoo->format((int32_t)42, temp, pos)); logln(dfFoo->format((int32_t)-42, temp, pos)); dfFoo->applyPattern("000;-000", status); failure(status, "dfFoo->applyPattern"); - if (dfFoo->toPattern(temp) != UnicodeString("#000")) - errln("dfFoo.toPattern : " + dfFoo->toPattern(temp)); + if (dfFoo->toPattern(temp) != UnicodeString("000")) + errln("ERROR: dfFoo.toPattern : " + dfFoo->toPattern(temp)); logln(dfFoo->format((int32_t)42,temp, pos)); logln(dfFoo->format((int32_t)-42, temp, pos)); dfFoo->applyPattern("000;-0000", status); failure(status, "dfFoo->applyPattern"); - if (dfFoo->toPattern(temp) != UnicodeString("#000")) - errln("dfFoo.toPattern : " + dfFoo->toPattern(temp)); + if (dfFoo->toPattern(temp) != UnicodeString("000")) + errln("ERROR: dfFoo.toPattern : " + dfFoo->toPattern(temp)); logln(dfFoo->format((int32_t)42, temp, pos)); logln(dfFoo->format((int32_t)-42, temp, pos)); dfFoo->applyPattern("0000;-000", status); failure(status, "dfFoo->applyPattern"); - if (dfFoo->toPattern(temp) != UnicodeString("#0000")) - errln("dfFoo.toPattern : " + dfFoo->toPattern(temp)); + if (dfFoo->toPattern(temp) != UnicodeString("0000")) + errln("ERROR: dfFoo.toPattern : " + dfFoo->toPattern(temp)); logln(dfFoo->format((int32_t)42, temp, pos)); logln(dfFoo->format((int32_t)-42, temp, pos)); /*} catch (Exception foo) { @@ -835,15 +850,15 @@ void NumberFormatRegressionTest::Test4092480 (void) void NumberFormatRegressionTest::Test4087244 (void) { UErrorCode status = U_ZERO_ERROR; char loc[256] = {0}; - uloc_canonicalize("pt_PT_PREEURO", loc, 256, &status); - Locale *de = new Locale(loc); - NumberFormat *nf = NumberFormat::createCurrencyInstance(*de, status); + + uloc_canonicalize("pt_PT@currency=PTE", loc, 256, &status); + Locale de(loc); + LocalPointer nf(NumberFormat::createCurrencyInstance(de, status)); if(U_FAILURE(status)) { - dataerrln("Error creating DecimalFormat: %s", u_errorName(status)); - delete nf; - return; + dataerrln("Error creating DecimalFormat: %s", u_errorName(status)); + return; } - DecimalFormat *df = dynamic_cast(nf); + DecimalFormat *df = dynamic_cast(nf.getAlias()); if(df == NULL) { errln("expected DecimalFormat!"); return; @@ -872,8 +887,6 @@ void NumberFormatRegressionTest::Test4087244 (void) { monStr + "\" and not \"" + decStr + '"'); } - delete de; - delete nf; } /* @bug 4070798 * Number format data rounding errors for locale FR @@ -884,18 +897,18 @@ void NumberFormatRegressionTest::Test4070798 (void) UnicodeString tempString; /* User error : - String expectedDefault = "-5\u00a0789,987"; - String expectedCurrency = "5\u00a0789,98\u00a0F"; - String expectedPercent = "-578\u00a0998%"; + String expectedDefault = "-5\u202f789,987"; + String expectedCurrency = "5\u202f789,98\u00a0F"; + String expectedPercent = "-578\u202f998%"; */ UChar chars1 [] = { - 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38 + 0x2d, 0x35, 0x202f, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38 }; UChar chars2 [] = { - 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46 + 0x35, 0x202f, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46 }; UChar chars3 [] = { - 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25 + 0x2d, 0x35, 0x37, 0x38, 0x202f, 0x39, 0x39, 0x39, 0x00a0, 0x25 }; UnicodeString expectedDefault(chars1, 10, 10); UnicodeString expectedCurrency(chars2, 10, 10); @@ -903,14 +916,15 @@ void NumberFormatRegressionTest::Test4070798 (void) UErrorCode status = U_ZERO_ERROR; char loc[256]={0}; - int len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status); + int len = uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status); + (void)len; // Suppress set but not used warning. formatter = NumberFormat::createInstance(Locale(loc), status); if(U_FAILURE(status)) { dataerrln("Error creating DecimalFormat: %s", u_errorName(status)); delete formatter; return; } - failure(status, "NumberFormat::createNumberInstance", loc); + failure(status, "NumberFormat::createInstance", loc); tempString = formatter->format (-5789.9876, tempString); if (tempString == expectedDefault) { @@ -921,7 +935,7 @@ void NumberFormatRegressionTest::Test4070798 (void) " Received " + tempString ); } delete formatter; - len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status); + len = uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status); formatter = NumberFormat::createCurrencyInstance(loc, status); failure(status, "NumberFormat::createCurrencyInstance", loc); tempString.remove(); @@ -936,7 +950,7 @@ void NumberFormatRegressionTest::Test4070798 (void) } delete formatter; - uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status); + uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status); formatter = NumberFormat::createPercentInstance(Locale(loc), status); failure(status, "NumberFormat::createPercentInstance", loc); tempString.remove(); @@ -979,10 +993,10 @@ void NumberFormatRegressionTest::Test4071005 (void) UErrorCode status = U_ZERO_ERROR; formatter = NumberFormat::createInstance(Locale::getCanadaFrench(), status); - if (failure(status, "NumberFormat::createNumberInstance", Locale::getCanadaFrench(), TRUE)){ + if (failure(status, "NumberFormat::createInstance", Locale::getCanadaFrench(), TRUE)){ delete formatter; return; - }; + } tempString = formatter->format (-5789.9876, tempString); if (tempString == expectedDefault) { @@ -1033,11 +1047,11 @@ void NumberFormatRegressionTest::Test4071014 (void) UnicodeString tempString; /* user error : String expectedDefault = "-5.789,987"; - String expectedCurrency = "5.789,98 DEM"; + String expectedCurrency = "5.789,98 DM"; String expectedPercent = "-578.998%"; */ UnicodeString expectedDefault("-5.789,988"); - UnicodeString expectedCurrency("5.789,99\\u00A0DEM"); + UnicodeString expectedCurrency("5.789,99\\u00A0DM"); UnicodeString expectedPercent("-578.999\\u00A0%"); expectedCurrency = expectedCurrency.unescape(); @@ -1045,9 +1059,9 @@ void NumberFormatRegressionTest::Test4071014 (void) UErrorCode status = U_ZERO_ERROR; char loc[256]={0}; - uloc_canonicalize("de_DE_PREEURO", loc, 256, &status); + uloc_canonicalize("de_DE@currency=DEM", loc, 256, &status); formatter = NumberFormat::createInstance(Locale(loc), status); - if (failure(status, "NumberFormat::createNumberInstance", loc, TRUE)){ + if (failure(status, "NumberFormat::createInstance", loc, TRUE)){ delete formatter; return; } @@ -1062,7 +1076,7 @@ void NumberFormatRegressionTest::Test4071014 (void) " Received " + tempString ); } delete formatter; - uloc_canonicalize("de_DE_PREEURO", loc, 256, &status); + uloc_canonicalize("de_DE@currency=DEM", loc, 256, &status); formatter = NumberFormat::createCurrencyInstance(Locale(loc), status); failure(status, "NumberFormat::createCurrencyInstance", loc); tempString.remove(); @@ -1111,12 +1125,12 @@ void NumberFormatRegressionTest::Test4071859 (void) UErrorCode status = U_ZERO_ERROR; char loc[256]={0}; - uloc_canonicalize("it_IT_PREEURO", loc, 256, &status); + uloc_canonicalize("it_IT@currency=ITL", loc, 256, &status); formatter = NumberFormat::createInstance(Locale(loc), status); if (failure(status, "NumberFormat::createNumberInstance", TRUE)){ delete formatter; return; - }; + } tempString = formatter->format (-5789.9876, tempString); if (tempString == expectedDefault) { @@ -1127,7 +1141,7 @@ void NumberFormatRegressionTest::Test4071859 (void) " Received " + tempString ); } delete formatter; - uloc_canonicalize("it_IT_PREEURO", loc, 256, &status); + uloc_canonicalize("it_IT@currency=ITL", loc, 256, &status); formatter = NumberFormat::createCurrencyInstance(Locale(loc), status); failure(status, "NumberFormat::createCurrencyInstance"); tempString.remove(); @@ -1141,7 +1155,7 @@ void NumberFormatRegressionTest::Test4071859 (void) " Received " + tempString ); } delete formatter; - uloc_canonicalize("it_IT_PREEURO", loc, 256, &status); + uloc_canonicalize("it_IT@currency=ITL", loc, 256, &status); formatter = NumberFormat::createPercentInstance(Locale(loc), status); failure(status, "NumberFormat::createPercentInstance"); tempString.remove(); @@ -1163,30 +1177,28 @@ void NumberFormatRegressionTest::Test4071859 (void) void NumberFormatRegressionTest::Test4093610(void) { UErrorCode status = U_ZERO_ERROR; - DecimalFormat *df = new DecimalFormat("#0.#", status); + DecimalFormat df("#0.#", status); if (!failure(status, "new DecimalFormat")) { UnicodeString s("12.4"); - roundingTest(df, 12.35, s); - roundingTest(df, 12.45, s); + roundingTest(&df, 12.35, s); + roundingTest(&df, 12.45, s); s = "12.5"; - roundingTest(df, 12.452,s); + roundingTest(&df, 12.452,s); s = "12.6"; - roundingTest(df, 12.55, s); - roundingTest(df, 12.65, s); + roundingTest(&df, 12.55, s); + roundingTest(&df, 12.65, s); s = "12.7"; - roundingTest(df, 12.652,s); + roundingTest(&df, 12.652,s); s = "12.8"; - roundingTest(df, 12.75, s); - roundingTest(df, 12.752,s); - roundingTest(df, 12.85, s); + roundingTest(&df, 12.75, s); + roundingTest(&df, 12.752,s); + roundingTest(&df, 12.85, s); s = "12.9"; - roundingTest(df, 12.852,s); + roundingTest(&df, 12.852,s); s = "13"; - roundingTest(df, 12.95, s); - roundingTest(df, 12.952,s); + roundingTest(&df, 12.95, s); + roundingTest(&df, 12.952,s); } - - delete df; } void NumberFormatRegressionTest::roundingTest(DecimalFormat *df, double x, UnicodeString& expected) @@ -1195,8 +1207,9 @@ void NumberFormatRegressionTest::roundingTest(DecimalFormat *df, double x, Unico FieldPosition pos(FieldPosition::DONT_CARE); out = df->format(x, out, pos); logln(UnicodeString("") + x + " formats with 1 fractional digits to " + out); - if (out != expected) - errln("FAIL: Expected " + expected); + if (out != expected) { + dataerrln("FAIL: Expected '%s'; got '%s'", CStr(expected)(), CStr(out)()); + } } /* @bug 4098741 * Tests the setMaximumFractionDigits limit. @@ -1306,7 +1319,7 @@ void NumberFormatRegressionTest::Test4101481(void) } failure(status, "new DecimalFormat"); if (sdf->getMinimumIntegerDigits() != 1) - errln("Minimum integer digits : " + sdf->getMinimumIntegerDigits()); + errln(UnicodeString("Minimum integer digits : ") + sdf->getMinimumIntegerDigits()); delete sdf; } /* @bug 4052223 (API addition request A27) @@ -1339,7 +1352,10 @@ void NumberFormatRegressionTest::Test4061302(void) { UErrorCode status = U_ZERO_ERROR; DecimalFormatSymbols *fmt = new DecimalFormatSymbols(status); - failure(status, "new DecimalFormatSymbols"); + if (U_FAILURE(status)) { + dataerrln("Error creating DecimalFormatSymbols - %s", u_errorName(status)); + return; + } UnicodeString currency(fmt->getSymbol(DecimalFormatSymbols::kCurrencySymbol)); UnicodeString intlCurrency(fmt->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)); UnicodeString monDecSeparator(fmt->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol)); @@ -1377,9 +1393,12 @@ void NumberFormatRegressionTest::Test4062486(void) { UErrorCode status = U_ZERO_ERROR; DecimalFormat *fmt = new DecimalFormat(UnicodeString("#,##0.00"), status); - failure(status, "new DecimalFormat"); + if (U_FAILURE(status)) { + dataerrln("Error creating DecimalFormat - %s", u_errorName(status)); + return; + } UnicodeString formatted; - FieldPosition field(0); + FieldPosition field(FieldPosition::DONT_CARE); double num = 1234.5; fmt->format(num, formatted, field); if (field.getBeginIndex() != 0 && field.getEndIndex() != 5) @@ -1618,7 +1637,7 @@ void NumberFormatRegressionTest::Test4110936(void) nf->setMaximumIntegerDigits(MAX_INT_DIGITS); logln("setMaximumIntegerDigits(MAX_INT_DIGITS)"); if (nf->getMaximumIntegerDigits() != MAX_INT_DIGITS) - errln("getMaximumIntegerDigits() returns " + + errln(UnicodeString("getMaximumIntegerDigits() returns ") + nf->getMaximumIntegerDigits()); delete nf; @@ -1671,6 +1690,12 @@ void NumberFormatRegressionTest::Test4122840(void) // Create a DecimalFormat using the pattern we got and format a number DecimalFormatSymbols *symbols = new DecimalFormatSymbols(locales[i], status); failure(status, "new DecimalFormatSymbols"); + + // Disable currency spacing for the purposes of this test. + // To do this, set the spacing insert to the empty string both before and after the symbol. + symbols->setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, FALSE, u""); + symbols->setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, TRUE, u""); + DecimalFormat *fmt1 = new DecimalFormat(pattern, *symbols, status); failure(status, "new DecimalFormat"); @@ -1866,9 +1891,11 @@ void NumberFormatRegressionTest::Test4134300(void) { void NumberFormatRegressionTest::Test4140009(void) { UErrorCode status = U_ZERO_ERROR; - DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getEnglish(), status); - failure(status, "new DecimalFormatSymbols"); - DecimalFormat *f = new DecimalFormat(UnicodeString(""), syms, status); + LocalPointer syms(new DecimalFormatSymbols(Locale::getEnglish(), status), status); + if (failure(status, "new DecimalFormatSymbols")) { + return; + } + DecimalFormat *f = new DecimalFormat(UnicodeString(u""), syms.orphan(), status); if (!failure(status, "new DecimalFormat")) { UnicodeString s; FieldPosition pos(FieldPosition::DONT_CARE); @@ -1913,7 +1940,7 @@ void NumberFormatRegressionTest::Test4145457() { if (failure(status, "NumberFormat::createInstance", TRUE)){ delete nff; return; - }; + } DecimalFormat *nf = dynamic_cast(nff); if(nf == NULL) { errln("DecimalFormat needed to continue"); @@ -1983,6 +2010,8 @@ void NumberFormatRegressionTest::Test4145457() { * DecimalFormat.applyPattern() sets minimum integer digits incorrectly. * CANNOT REPRODUCE * This bug is a duplicate of 4139344, which is a duplicate of 4134300 + * + * ICU 62: minInt is always at least one, and the getter should reflect that! */ void NumberFormatRegressionTest::Test4147295(void) { @@ -1993,7 +2022,7 @@ void NumberFormatRegressionTest::Test4147295(void) sdf->applyPattern(pattern, status); if (!failure(status, "sdf->applyPattern")) { int minIntDig = sdf->getMinimumIntegerDigits(); - if (minIntDig != 0) { + if (minIntDig != 1) { errln("Test failed"); errln(UnicodeString(" Minimum integer digits : ") + minIntDig); UnicodeString temp; @@ -2112,8 +2141,9 @@ NumberFormatRegressionTest::Test4162852(void) { UErrorCode status = U_ZERO_ERROR; for(int32_t i=0; i < 2; ++i) { - NumberFormat *f = (i == 0) ? NumberFormat::createInstance(status) - : NumberFormat::createPercentInstance(status); + LocalPointer f( + ((i == 0) ? NumberFormat::createInstance(status) : NumberFormat::createPercentInstance(status)), + status); if(U_FAILURE(status)) { dataerrln("Couldn't create number format - %s", u_errorName(status)); return; @@ -2124,20 +2154,19 @@ NumberFormatRegressionTest::Test4162852(void) f->format(d, s); Formattable n; f->parse(s, n, status); - if(U_FAILURE(status)) + if(U_FAILURE(status)) { errln("Couldn't parse!"); + return; + } double e = n.getDouble(); - logln(UnicodeString("") + - d + " -> " + - '"' + s + '"' + " -> " + e); + logln("%f -> \"%s\" -> %f", d, CStr(s)(), e); #if (U_PLATFORM == U_PF_OS390 && !defined(IEEE_754)) || U_PLATFORM == U_PF_OS400 if (e != 0.0) { #else - if (e != 0.0 || 1.0/e > 0.0) { + if (e != 0.0 || (std::signbit(e) == false)) { #endif - logln("Failed to parse negative zero"); + errln("Failed to parse negative zero"); } - delete f; } } @@ -2154,7 +2183,7 @@ void NumberFormatRegressionTest::Test4167494(void) { if (failure(status, "NumberFormat::createInstance", TRUE)){ delete fmt; return; - }; + } double a = DBL_MAX * 0.99; // DBL_MAX itself overflows to +Inf UnicodeString s; @@ -2185,26 +2214,31 @@ void NumberFormatRegressionTest::Test4167494(void) { * DecimalFormat.parse() fails when ParseIntegerOnly set to true */ void NumberFormatRegressionTest::Test4170798(void) { - UErrorCode status = U_ZERO_ERROR; - NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status); - if (failure(status, "NumberFormat::createInstance", TRUE)){ - delete nf; - return; - }; - DecimalFormat *df = dynamic_cast(nf); - if(df == NULL) { - errln("DecimalFormat needed to continue"); + IcuTestErrorCode status(*this, "Test4170798"); + LocalPointer df(dynamic_cast( + NumberFormat::createInstance(Locale::getUS(), status)), status); + if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; } + { + Formattable n; + ParsePosition pos(0); + df->parse("-0.0", n, pos); + if (n.getType() != Formattable::kDouble + || n.getDouble() != -0.0) { + errln(UnicodeString("FAIL: default parse(\"-0.0\") returns ") + toString(n)); + } + } df->setParseIntegerOnly(TRUE); - Formattable n; - ParsePosition pos(0); - df->parse("-0.0", n, pos); - if (n.getType() != Formattable::kLong - || n.getLong() != 0) { - errln(UnicodeString("FAIL: parse(\"-0.0\") returns ") + toString(n)); + { + Formattable n; + ParsePosition pos(0); + df->parse("-0.0", n, pos); + if (n.getType() != Formattable::kLong + || n.getLong() != 0) { + errln(UnicodeString("FAIL: integer parse(\"-0.0\") returns ") + toString(n)); + } } - delete nf; } /** @@ -2213,17 +2247,17 @@ void NumberFormatRegressionTest::Test4170798(void) { */ void NumberFormatRegressionTest::Test4176114(void) { const char* DATA[] = { - "00", "#00", - "000", "#000", // No grouping - "#000", "#000", // No grouping + "00", "00", + "000", "000", // No grouping + "#000", "000", // No grouping "#,##0", "#,##0", "#,000", "#,000", - "0,000", "#0,000", - "00,000", "#00,000", - "000,000", "#,000,000", - "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported + "0,000", "0,000", + "00,000", "00,000", + "000,000", "000,000", + "0,000,000,000,000.0000", "0,000,000,000,000.0000", // Reported }; - int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0])); + int DATA_length = UPRV_LENGTHOF(DATA); UErrorCode status = U_ZERO_ERROR; UnicodeString s; for (int i=0; i ") + s + - ", exp usd12.50"); + u", exp usd\u00A012.50"); } s.remove(); if (fmt.getPositivePrefix(s) != UnicodeString("usd")) { @@ -2368,9 +2402,9 @@ void NumberFormatRegressionTest::Test4212072(void) { sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "DOL"); fmt.setDecimalFormatSymbols(sym); s.remove(); - if (fmt.format(12.5, s, pos) != UnicodeString("DOL12.50")) { + if (fmt.format(12.5, s, pos) != UnicodeString(u"DOL\u00A012.50")) { errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s + - ", exp DOL12.50"); + u", exp DOL\u00A012.50"); } s.remove(); if (fmt.getPositivePrefix(s) != UnicodeString("DOL")) { @@ -2434,18 +2468,20 @@ void NumberFormatRegressionTest::Test4212072(void) { } // Test toLocalizedPattern/applyLocalizedPattern round trip - df->toLocalizedPattern(pat); - f2.applyLocalizedPattern(pat, status); +// TODO(refactor): don't worry about localized patterns for now. +// df->toLocalizedPattern(pat); +// f2.applyLocalizedPattern(pat, status); failure(status, UnicodeString("applyLocalizedPattern(") + pat + ")", avail[i]); if (U_FAILURE(status)) { continue; } +// TODO(refactor): don't worry about localized patterns for now. // Make sure we set the currency attributes appropriately - if (j == 1) { // Currency format - f2.setCurrency(f2.getCurrency(), status); - } +// if (j == 1) { // Currency format +// f2.setCurrency(f2.getCurrency(), status); +// } failure(status, UnicodeString("setCurrency() for (") + pat + ")", avail[i]); if (U_FAILURE(status)) { @@ -2477,9 +2513,9 @@ void NumberFormatRegressionTest::Test4216742(void) { if (failure(status, "createInstance", Locale::getUS(), TRUE)){ delete fmt; return; - }; + } int32_t DATA[] = { INT32_MIN, INT32_MAX, -100000000, 100000000 }; - int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0])); + int DATA_length = UPRV_LENGTHOF(DATA); for (int i=0; isetMaximumFractionDigits(2); for (int i=0; isetMinimumFractionDigits(1); nf->setMaximumFractionDigits(1); double a = -0.09; @@ -2568,7 +2604,7 @@ void NumberFormatRegressionTest::Test4243011(void) { if (!failure(status, "DecimalFormat ct", Locale::getUS())) { const double NUM[] = { -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5 }; const char* STR[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." }; - int32_t N = (int32_t)(sizeof(NUM) / sizeof(NUM[0])); + int32_t N = UPRV_LENGTHOF(NUM); for (int32_t i=0; i cal(Calendar::createInstance(loc, status)); if (U_FAILURE(status)) { dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString)u_errorName(status)); return; } // create a NumberFormat for this locale - NumberFormat *nf = NumberFormat::createInstance(loc, status); + LocalPointer nf(NumberFormat::createInstance(loc, status)); if (U_FAILURE(status)) { dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString)u_errorName(status)); return; @@ -2662,16 +2698,19 @@ void NumberFormatRegressionTest::TestJ691(void) { // *** Here's the key: We don't want to have to do THIS: // nf->setParseIntegerOnly(TRUE); + // or this (with changes to fr_CH per cldrbug:9370): + // nf->setGroupingUsed(FALSE); + // so they are done in DateFormat::adoptNumberFormat // create the DateFormat - DateFormat *df = DateFormat::createDateInstance(DateFormat::kShort, loc); + LocalPointer df(DateFormat::createDateInstance(DateFormat::kShort, loc)); if (U_FAILURE(status)) { errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString)u_errorName(status)); return; } - df->adoptCalendar(cal); - df->adoptNumberFormat(nf); + df->adoptCalendar(cal.orphan()); + df->adoptNumberFormat(nf.orphan()); // set parsing to lenient & parse df->setLenient(TRUE); @@ -2684,8 +2723,6 @@ void NumberFormatRegressionTest::TestJ691(void) { if (outString != exp) { errln("FAIL: " + udt + " => " + outString); } - - delete df; } //--------------------------------------------------------------------------- @@ -2693,16 +2730,28 @@ void NumberFormatRegressionTest::TestJ691(void) { // Error Checking / Reporting macros // //--------------------------------------------------------------------------- -#define TEST_CHECK_STATUS(status) \ - if (U_FAILURE(status)) {\ - errln("File %s, Line %d. status=%s\n", __FILE__, __LINE__, u_errorName(status));\ - return;\ - } - -#define TEST_ASSERT(expr) \ +#define TEST_CHECK_STATUS(status) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + if (status == U_MISSING_RESOURCE_ERROR) { \ + dataerrln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \ + } else { \ + errln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \ + } return; \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \ if ((expr)==FALSE) {\ errln("File %s, line %d: Assertion Failed: " #expr "\n", __FILE__, __LINE__);\ - } + } \ +} UPRV_BLOCK_MACRO_END +#define TEST_ASSERT_EQUALS(x,y) UPRV_BLOCK_MACRO_BEGIN { \ + char _msg[1000]; \ + int32_t len = sprintf (_msg,"File %s, line %d: " #x "==" #y, __FILE__, __LINE__); \ + (void)len; \ + U_ASSERT(len < (int32_t) sizeof(_msg)); \ + assertEquals((const char*) _msg, x,y); \ +} UPRV_BLOCK_MACRO_END // Ticket 8199: Parse failure for numbers in the range of 1E10 - 1E18 @@ -2723,10 +2772,10 @@ void NumberFormatRegressionTest::Test8199(void) { Formattable val; nf->parse(numStr, val, status); TEST_CHECK_STATUS(status); - TEST_ASSERT(Formattable::kDouble == val.getType()); - TEST_ASSERT(1000000000 == val.getInt64(status)); + TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType()); + TEST_ASSERT_EQUALS(1000000000LL, val.getInt64(status)); TEST_CHECK_STATUS(status); - TEST_ASSERT(1000000000.6 == val.getDouble(status)); + TEST_ASSERT_EQUALS(1000000000.6, val.getDouble(status)); TEST_CHECK_STATUS(status); numStr = "100000000000000001.1"; // approx 1E17, parses as a double rather @@ -2734,25 +2783,25 @@ void NumberFormatRegressionTest::Test8199(void) { // even though int64 is more precise. nf->parse(numStr, val, status); TEST_CHECK_STATUS(status); - TEST_ASSERT(Formattable::kDouble == val.getType()); - TEST_ASSERT(100000000000000001LL == val.getInt64(status)); + TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType()); + TEST_ASSERT_EQUALS(100000000000000001LL, val.getInt64(status)); TEST_CHECK_STATUS(status); - TEST_ASSERT(100000000000000000.0 == val.getDouble(status)); + TEST_ASSERT_EQUALS(100000000000000000.0, val.getDouble(status)); TEST_CHECK_STATUS(status); numStr = "1E17"; // Parses with the internal decimal number having non-zero exponent nf->parse(numStr, val, status); TEST_CHECK_STATUS(status); - TEST_ASSERT(Formattable::kInt64 == val.getType()); - TEST_ASSERT(100000000000000000LL == val.getInt64()); - TEST_ASSERT(1.0E17 == val.getDouble(status)); + TEST_ASSERT_EQUALS(Formattable::kInt64, val.getType()); + TEST_ASSERT_EQUALS(100000000000000000LL, val.getInt64()); + TEST_ASSERT_EQUALS(1.0E17, val.getDouble(status)); TEST_CHECK_STATUS(status); numStr = "9223372036854775807"; // largest int64_t nf->parse(numStr, val, status); TEST_CHECK_STATUS(status); - TEST_ASSERT(Formattable::kInt64 == val.getType()); - TEST_ASSERT(9223372036854775807LL == val.getInt64()); + TEST_ASSERT_EQUALS(Formattable::kInt64, val.getType()); + TEST_ASSERT_EQUALS(9223372036854775807LL, val.getInt64()); // In the following check, note that a substantial range of integers will // convert to the same double value. There are also platform variations // in the rounding at compile time of double constants. @@ -2763,31 +2812,31 @@ void NumberFormatRegressionTest::Test8199(void) { numStr = "-9223372036854775808"; // smallest int64_t nf->parse(numStr, val, status); TEST_CHECK_STATUS(status); - TEST_ASSERT(Formattable::kInt64 == val.getType()); - // TEST_ASSERT(-9223372036854775808LL == val.getInt64()); // Compiler chokes on constant. - TEST_ASSERT((int64_t)0x8000000000000000LL == val.getInt64()); - TEST_ASSERT(-9223372036854775808.0 == val.getDouble(status)); + TEST_ASSERT_EQUALS(Formattable::kInt64, val.getType()); + // TEST_ASSERT_EQUALS(-9223372036854775808LL, val.getInt64()); // Compiler chokes on constant. + TEST_ASSERT_EQUALS((int64_t)0x8000000000000000LL, val.getInt64()); + TEST_ASSERT_EQUALS(-9223372036854775808.0, val.getDouble(status)); TEST_CHECK_STATUS(status); numStr = "9223372036854775808"; // largest int64_t + 1 nf->parse(numStr, val, status); TEST_CHECK_STATUS(status); - TEST_ASSERT(Formattable::kDouble == val.getType()); - TEST_ASSERT(9223372036854775807LL == val.getInt64(status)); - TEST_ASSERT(status == U_INVALID_FORMAT_ERROR); + TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType()); + TEST_ASSERT_EQUALS(9223372036854775807LL, val.getInt64(status)); + TEST_ASSERT_EQUALS(status, U_INVALID_FORMAT_ERROR); status = U_ZERO_ERROR; - TEST_ASSERT(9223372036854775810.0 == val.getDouble(status)); + TEST_ASSERT_EQUALS(9223372036854775810.0, val.getDouble(status)); TEST_CHECK_STATUS(status); numStr = "-9223372036854775809"; // smallest int64_t - 1 nf->parse(numStr, val, status); TEST_CHECK_STATUS(status); - TEST_ASSERT(Formattable::kDouble == val.getType()); - // TEST_ASSERT(-9223372036854775808LL == val.getInt64(status)); // spurious compiler warnings - TEST_ASSERT((int64_t)0x8000000000000000LL == val.getInt64(status)); - TEST_ASSERT(status == U_INVALID_FORMAT_ERROR); + TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType()); + // TEST_ASSERT_EQUALS(-9223372036854775808LL, val.getInt64(status)); // spurious compiler warnings + TEST_ASSERT_EQUALS((int64_t)0x8000000000000000LL, val.getInt64(status)); + TEST_ASSERT_EQUALS(status, U_INVALID_FORMAT_ERROR); status = U_ZERO_ERROR; - TEST_ASSERT(-9223372036854775810.0 == val.getDouble(status)); + TEST_ASSERT_EQUALS(-9223372036854775810.0, val.getDouble(status)); TEST_CHECK_STATUS(status); // Test values near the limit of where doubles can represent all integers. @@ -2801,27 +2850,27 @@ void NumberFormatRegressionTest::Test8199(void) { nf->parse(numStr, val, status); TEST_CHECK_STATUS(status); // printf("getInt64() returns %lld\n", val.getInt64(status)); - TEST_ASSERT(Formattable::kDouble == val.getType()); - TEST_ASSERT(9007199254740991LL == val.getInt64(status)); - TEST_ASSERT(9007199254740991.0 == val.getDouble(status)); + TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType()); + TEST_ASSERT_EQUALS(9007199254740991LL, val.getInt64(status)); + TEST_ASSERT_EQUALS(9007199254740991.0, val.getDouble(status)); TEST_CHECK_STATUS(status); status = U_ZERO_ERROR; numStr = "9007199254740992.1"; // 54 bits for the int part. nf->parse(numStr, val, status); TEST_CHECK_STATUS(status); - TEST_ASSERT(Formattable::kDouble == val.getType()); - TEST_ASSERT(9007199254740992LL == val.getInt64(status)); - TEST_ASSERT(9007199254740992.0 == val.getDouble(status)); + TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType()); + TEST_ASSERT_EQUALS(9007199254740992LL, val.getInt64(status)); + TEST_ASSERT_EQUALS(9007199254740992.0, val.getDouble(status)); TEST_CHECK_STATUS(status); status = U_ZERO_ERROR; numStr = "9007199254740993.1"; // 54 bits for the int part. Double will round nf->parse(numStr, val, status); // the ones digit, putting it up to ...994 TEST_CHECK_STATUS(status); - TEST_ASSERT(Formattable::kDouble == val.getType()); - TEST_ASSERT(9007199254740993LL == val.getInt64(status)); - TEST_ASSERT(9007199254740994.0 == val.getDouble(status)); + TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType()); + TEST_ASSERT_EQUALS((int64_t)9007199254740993LL,val.getInt64(status)); + TEST_ASSERT_EQUALS((double)9007199254740994.0,(double)val.getDouble(status)); TEST_CHECK_STATUS(status); delete nf; @@ -2832,12 +2881,12 @@ void NumberFormatRegressionTest::Test9109(void) { Formattable val; ParsePosition pos; DecimalFormat fmt("+##", status); - fmt.setLenient(TRUE); - if (U_FAILURE(status)) { dataerrln("Failed to create DecimalFormat with pattern '+##' - %s", u_errorName(status)); + return; } + fmt.setLenient(TRUE); UnicodeString text("123"); int32_t expected = 123; int32_t expos = 3; @@ -2852,4 +2901,168 @@ void NumberFormatRegressionTest::Test9109(void) { } } + +void NumberFormatRegressionTest::Test9780(void) { + UErrorCode status = U_ZERO_ERROR; + NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status); + if (failure(status, "NumberFormat::createInstance", TRUE)){ + delete nf; + return; + } + DecimalFormat *df = dynamic_cast(nf); + if(df == NULL) { + errln("DecimalFormat needed to continue"); + return; + } + df->setParseIntegerOnly(TRUE); + + { + Formattable n; + ParsePosition pos(0); + UnicodeString toParse("1,234",""); + df->parse(toParse, n, pos); + if (n.getType() != Formattable::kLong + || n.getLong() != 1234) { + errln(UnicodeString("FAIL: parse(\"") + toParse + UnicodeString("\") returns ") + toString(n)); + } + } + // should still work in lenient mode, just won't get fastpath + df->setLenient(TRUE); + { + Formattable n; + ParsePosition pos(0); + UnicodeString toParse("1,234",""); + df->parse(toParse, n, pos); + if (n.getType() != Formattable::kLong + || n.getLong() != 1234) { + errln(UnicodeString("FAIL: parse(\"") + toParse + UnicodeString("\") returns ") + toString(n)); + } + } + delete nf; +} + + +void NumberFormatRegressionTest::Test9677(void) { + static const UChar pattern[] = { 0x23,0x23,0x23,0x23,0x2E,0x23,0x23,0x23,0x23,0 }; // "####.####" + static const UChar positivePrefix[] = { 0x40,0 }; // "@" + static const UChar negativePrefix[] = { 0x6E,0 }; // "n" + static const UChar text[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // 123456789 + static const UChar text2[] = { 0x6E, 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // n123456789 + + UErrorCode status = U_ZERO_ERROR; + LocalUNumberFormatPointer f(unum_open(UNUM_DEFAULT, NULL, 0, "en_US", NULL, &status)); + if (U_FAILURE(status)) { + dataerrln("Failure opening unum_open"); + return; + } + + if (U_SUCCESS(status)) { + unum_applyPattern(f.getAlias(), FALSE, pattern, -1, NULL, &status); + unum_setTextAttribute(f.getAlias(), UNUM_POSITIVE_PREFIX, positivePrefix, -1, &status); + assertSuccess("setting attributes", status); + } + + if(U_SUCCESS(status)) { + int32_t n = unum_parse(f.getAlias(), text, -1, NULL, &status); + logln("unum_parse status %s, result %d\n", u_errorName(status), n); + + if(U_FAILURE(status)) { + logln("Got expected parse error %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + } else { + errln("FAIL: unum_parse status %s, result %d - expected failure\n", u_errorName(status), n); + } + } + + if (U_SUCCESS(status)) { + unum_setTextAttribute(f.getAlias(), UNUM_POSITIVE_PREFIX, NULL, 0, &status); + assertSuccess("setting attributes", status); + logln("removed positive prefix"); + } + + if(U_SUCCESS(status)) { + int32_t n = unum_parse(f.getAlias(), text, -1, NULL, &status); + logln("unum_parse status %s, result %d\n", u_errorName(status), n); + + if(U_FAILURE(status)) { + errln("FAIL: with pos prefix removed, parse error %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + } else { + if(n!=123456789) { + errln("FAIL: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status), n); + } else { + logln("PASS: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status),n); + } + } + } + + if(U_SUCCESS(status)) { + int32_t n = unum_parse(f.getAlias(), text2, -1, NULL, &status); + logln("unum_parse status %s, result %d\n", u_errorName(status), n); + + if(U_FAILURE(status)) { + logln("text2: Got expected parse error %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + } else { + errln("FAIL: text2: unum_parse status %s, result %d - expected failure\n", u_errorName(status), n); + } + } + + if (U_SUCCESS(status)) { + unum_setTextAttribute(f.getAlias(), UNUM_NEGATIVE_PREFIX, negativePrefix, -1, &status); + assertSuccess("setting attributes", status); + logln("Set a different neg prefix prefix"); + } + + if(U_SUCCESS(status)) { + int32_t n = unum_parse(f.getAlias(), text2, -1, NULL, &status); + logln("unum_parse status %s, result %d\n", u_errorName(status), n); + + if(U_FAILURE(status)) { + errln("FAIL: with different neg prefix , parse error %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + } else { + if(n!=-123456789) { + errln("FAIL: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status), n); + } else { + logln("PASS: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status), n); + } + } + } +} + +void NumberFormatRegressionTest::Test10361(void) { + // DecimalFormat/NumberFormat were artificially limiting the number of digits, + // preventing formatting of big decimals. + UErrorCode status = U_ZERO_ERROR; + DecimalFormatSymbols symbols(Locale::getEnglish(), status); + LocalPointer df(new DecimalFormat("###.##", symbols, status), status); + TEST_CHECK_STATUS(status); + + // Create a decimal number with a million digits. + const int32_t NUMSIZE=1000000; + char *num = new char[NUMSIZE]; + for (int32_t i=0; iformat(fmtable, s, pos, status); + TEST_CHECK_STATUS(status); + TEST_ASSERT(999999 == s.length()); + TEST_ASSERT(999997 == pos.getBeginIndex()); + TEST_ASSERT(999998 == pos.getEndIndex()); + + UnicodeString expected(num, -1, US_INV); + TEST_ASSERT(expected == s); + delete [] num; +} + #endif /* #if !UCONFIG_NO_FORMATTING */