From 2c6bc98b14fb63ea25bc6d74aca8e81d0ec05451 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Thu, 20 Jun 2013 22:09:42 +0000 Subject: [PATCH] ICU-10069 improve error messages, add commented-out case that passes on solaris and fails on others X-SVN-Rev: 33838 --- icu4c/source/i18n/decimfmt.cpp | 57 ++++++++++++++----- icu4c/source/i18n/ucurr.cpp | 34 ++++++++---- icu4c/source/test/intltest/numfmtst.cpp | 73 +++++++++++++++++++------ icu4c/source/test/intltest/numfmtst.h | 2 +- 4 files changed, 123 insertions(+), 43 deletions(-) diff --git a/icu4c/source/i18n/decimfmt.cpp b/icu4c/source/i18n/decimfmt.cpp index 4a52389996f..2ee00a55985 100644 --- a/icu4c/source/i18n/decimfmt.cpp +++ b/icu4c/source/i18n/decimfmt.cpp @@ -80,8 +80,26 @@ #undef round #endif + U_NAMESPACE_BEGIN +#ifdef FMT_DEBUG +#include +static void _debugout(const char *f, int l, const UnicodeString& s) { + char buf[2000]; + s.extract((int32_t) 0, s.length(), buf, "utf-8"); + printf("%s:%d: %s\n", f,l, buf); +} +#define debugout(x) _debugout(__FILE__,__LINE__,x) +#define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x); +static const UnicodeString dbg_null("",""); +#define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null)) +#else +#define debugout(x) +#define debug(x) +#endif + + /* == Fastpath calculation. == */ @@ -123,6 +141,15 @@ struct AffixPatternsForCurrency : public UMemory { posSuffixPatternForCurrency = posSuffix; patternType = type; } +#ifdef FMT_DEBUG + void dump() const { + debugout( UnicodeString("AffixPatternsForCurrency( -=\"") + + negPrefixPatternForCurrency + (UnicodeString)"\"/\"" + + negSuffixPatternForCurrency + (UnicodeString)"\" +=\"" + + posPrefixPatternForCurrency + (UnicodeString)"\"/\"" + + posSuffixPatternForCurrency + (UnicodeString)"\" )"); + } +#endif }; /* affix for currency formatting when the currency sign in the pattern @@ -150,6 +177,15 @@ struct AffixesForCurrency : public UMemory { posPrefixForCurrency = posPrefix; posSuffixForCurrency = posSuffix; } +#ifdef FMT_DEBUG + void dump() const { + debugout( UnicodeString("AffixesForCurrency( -=\"") + + negPrefixForCurrency + (UnicodeString)"\"/\"" + + negSuffixForCurrency + (UnicodeString)"\" +=\"" + + posPrefixForCurrency + (UnicodeString)"\"/\"" + + posSuffixForCurrency + (UnicodeString)"\" )"); + } +#endif }; U_CDECL_BEGIN @@ -197,21 +233,6 @@ U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2) { U_CDECL_END -#ifdef FMT_DEBUG -#include -static void _debugout(const char *f, int l, const UnicodeString& s) { - char buf[2000]; - s.extract((int32_t) 0, s.length(), buf); - printf("%s:%d: %s\n", f,l, buf); -} -#define debugout(x) _debugout(__FILE__,__LINE__,x) -#define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x); -static const UnicodeString dbg_null("",""); -#define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null)) -#else -#define debugout(x) -#define debug(x) -#endif @@ -2104,6 +2125,12 @@ DecimalFormat::parseForCurrency(const UnicodeString& text, UBool tmpStatus[fgStatusLength]; ParsePosition tmpPos(origPos); DigitList tmpDigitList; + +#ifdef FMT_DEBUG + debug("trying affix for currency.."); + affixPtn->dump(); +#endif + UBool result = subparse(text, &affixPtn->negPrefixPatternForCurrency, &affixPtn->negSuffixPatternForCurrency, diff --git a/icu4c/source/i18n/ucurr.cpp b/icu4c/source/i18n/ucurr.cpp index a13ddc7bb0f..941d9915885 100644 --- a/icu4c/source/i18n/ucurr.cpp +++ b/icu4c/source/i18n/ucurr.cpp @@ -28,7 +28,11 @@ #include "ulist.h" #include "ureslocs.h" -// #define UCURR_DEBUG 1 +//#define UCURR_DEBUG_EQUIV 1 +#ifdef UCURR_DEBUG_EQUIV +#include "stdio.h" +#endif +//#define UCURR_DEBUG 1 #ifdef UCURR_DEBUG #include "stdio.h" #endif @@ -220,6 +224,13 @@ static int32_t countEquivalent(const icu::Hashtable &hash, const icu::UnicodeStr while (iter.next() != NULL) { ++result; } +#ifdef UCURR_DEBUG_EQUIV + { + char tmp[200]; + s.extract(0,s.length(),tmp, "UTF-8"); + printf("CountEquivalent('%s') = %d\n", tmp, result); + } +#endif return result; } @@ -1140,22 +1151,20 @@ collectCurrencyNames(const char* locale, for (int32_t index = 0; index < *total_currency_name_count; ++index) { printf("index: %d\n", index); printf("iso: %s\n", (*currencyNames)[index].IsoCode); - printf("currencyName:"); - for (int32_t i = 0; i < (*currencyNames)[index].currencyNameLen; ++i) { - printf("%c", (unsigned char)(*currencyNames)[index].currencyName[i]); - } - printf("\n"); + char curNameBuf[1024]; + memset(curNameBuf, 0, 1024); + u_austrncpy(curNameBuf, (*currencyNames)[index].currencyName, (*currencyNames)[index].currencyNameLen); + printf("currencyName: %s\n", curNameBuf); printf("len: %d\n", (*currencyNames)[index].currencyNameLen); } printf("currency symbol count: %d\n", *total_currency_symbol_count); for (int32_t index = 0; index < *total_currency_symbol_count; ++index) { printf("index: %d\n", index); printf("iso: %s\n", (*currencySymbols)[index].IsoCode); - printf("currencySymbol:"); - for (int32_t i = 0; i < (*currencySymbols)[index].currencyNameLen; ++i) { - printf("%c", (unsigned char)(*currencySymbols)[index].currencyName[i]); - } - printf("\n"); + char curNameBuf[1024]; + memset(curNameBuf, 0, 1024); + u_austrncpy(curNameBuf, (*currencySymbols)[index].currencyName, (*currencySymbols)[index].currencyNameLen); + printf("currencySymbol: %s\n", curNameBuf); printf("len: %d\n", (*currencySymbols)[index].currencyNameLen); } #endif @@ -1543,6 +1552,9 @@ uprv_parseCurrency(const char* locale, #ifdef UCURR_DEBUG printf("search in symbols, maxInSymbol = %d, matchIndexInSymbol = %d\n", maxInSymbol, matchIndexInSymbol); + if(matchIndexInSymbol != -1) { + printf("== ISO=%s\n", currencySymbols[matchIndexInSymbol].IsoCode); + } #endif if (max >= maxInSymbol && matchIndex != -1) { diff --git a/icu4c/source/test/intltest/numfmtst.cpp b/icu4c/source/test/intltest/numfmtst.cpp index a7185437d30..0534b20f659 100644 --- a/icu4c/source/test/intltest/numfmtst.cpp +++ b/icu4c/source/test/intltest/numfmtst.cpp @@ -43,6 +43,7 @@ static const UChar EUR[] = {69,85,82,0}; // "EUR" static const UChar JPY[] = {0x4A, 0x50, 0x59, 0}; +static const UChar CNY[] = {0x43, 0x4E, 0x59, 0}; static const UChar ISO_CURRENCY_USD[] = {0x55, 0x53, 0x44, 0}; // "USD" @@ -174,9 +175,9 @@ NumberFormatTest::TestAPI(void) } } -class StubNumberForamt :public NumberFormat{ +class StubNumberFormat :public NumberFormat{ public: - StubNumberForamt(){}; + StubNumberFormat(){}; virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const { return appendTo; } @@ -204,7 +205,7 @@ public: void NumberFormatTest::TestCoverage(void){ - StubNumberForamt stub; + StubNumberFormat stub; UnicodeString agent("agent"); FieldPosition pos; int64_t num = 4; @@ -2626,11 +2627,33 @@ void NumberFormatTest::TestCompatibleCurrencies() { errln("Could not create number format instance."); return; } - expectParseCurrency(*fmt, JPY, "\\u00A51,235"); - expectParseCurrency(*fmt, JPY, "\\uFFE51,235"); + logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__); + expectParseCurrency(*fmt, JPY, 1235, "\\u00A51,235"); + logln("%s:%d - testing parse of fullwidth yen sign\n", __FILE__, __LINE__); + expectParseCurrency(*fmt, JPY, 1235, "\\uFFE51,235"); + logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__); + expectParseCurrency(*fmt, CNY, 1235, "CN\\u00A51,235"); + + LocalPointer fmtTW( + NumberFormat::createCurrencyInstance(Locale::getTaiwan(), status)); + + logln("%s:%d - testing parse of halfwidth yen sign in TW\n", __FILE__, __LINE__); + expectParseCurrency(*fmtTW, CNY, 1235, "\\u00A51,235"); + logln("%s:%d - testing parse of fullwidth yen sign in TW\n", __FILE__, __LINE__); + expectParseCurrency(*fmtTW, CNY, 1235, "\\uFFE51,235"); + + LocalPointer fmtJP( + NumberFormat::createCurrencyInstance(Locale::getJapan(), status)); + + logln("%s:%d - testing parse of halfwidth yen sign in JP\n", __FILE__, __LINE__); + expectParseCurrency(*fmtJP, JPY, 1235, "\\u00A51,235"); + logln("%s:%d - testing parse of fullwidth yen sign in JP\n", __FILE__, __LINE__); + expectParseCurrency(*fmtJP, JPY, 1235, "\\uFFE51,235"); + + // more.. } -void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* currency, const char *text) { +void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text) { ParsePosition ppos; UnicodeString utext = ctou(text); LocalPointer currencyAmount(fmt.parseCurrency(utext, ppos)); @@ -2638,6 +2661,8 @@ void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* errln(UnicodeString("Parse of ") + utext + " should have succeeded."); return; } + UErrorCode status = U_ZERO_ERROR; + assertTrue("amount", amount == currencyAmount->getNumber().getDouble(status)); assertEquals("currency", currency, currencyAmount->getISOCurrency()); } @@ -3411,28 +3436,43 @@ NumberFormatTest::TestCurrencyParsing() { {"ja_JP", "1", "USD", "$1.00", "USD1.00", "1.00 \\u7c73\\u30c9\\u30eb"}, {"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY1.00", "1.00\\u4EBA\\u6C11\\u5E01"}, {"zh_TW", "1", "CNY", "\\uFFE51.00", "CNY1.00", "1.00 \\u4eba\\u6c11\\u5e63"}, - {"ru_RU", "1", "RUB", "1,00\\u00A0\\u0440\\u0443\\u0431.", "1,00\\u00A0RUB", "1,00 \\u0420\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0439 \\u0440\\u0443\\u0431\\u043B\\u044C"}, + {"zh_Hant", "1", "CNY", "\\uFFE51.00", "CNY1.00", "1.00 \\u4eba\\u6c11\\u5e63"}, // This test case fails on Solaris/AIX, works on others - FIXME + {"zh_Hant", "1", "CNY", "\\u00A51.00", "CNY1.00", "1.00 \\u4eba\\u6c11\\u5e63"}, +// {"zh_Hant", "1", "JPY", "\\uFFE51.00", "JPY1.00", "1.00 \\u65e5\\u5713"}, // This test case passes on Solaris/AIX, breaks on others - FIXME +// {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY1.00", "1.00 \\u65e5\\u5713"}, // This test case passes on Solaris/AIX, breaks on others - FIXME + {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY1.00", "1.00 \\u65e5\\u672c\\u5186"}, + {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY1.00", "1.00 \\u65e5\\u672c\\u5186"}, + {"ru_RU", "1", "RUB", "1,00\\u00A0\\u0440\\u0443\\u0431.", "1,00\\u00A0RUB", "1,00 \\u0420\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0439 \\u0440\\u0443\\u0431\\u043B\\u044C"} }; static const UNumberFormatStyle currencyStyles[] = { UNUM_CURRENCY, UNUM_CURRENCY_ISO, UNUM_CURRENCY_PLURAL }; + static const char* currencyStyleNames[] = { + "UNUM_CURRENCY", + "UNUM_CURRENCY_ISO", + "UNUM_CURRENCY_PLURAL" + }; #ifdef NUMFMTST_CACHE_DEBUG int deadloop = 0; for (;;) { printf("loop: %d\n", deadloop++); #endif - for (uint32_t i=0; iformat(numberToBeFormat, strBuf); + /* int resultDataIndex = 3 + kIndex; // DATA[i][resultDataIndex] is the currency format result // using 'k' currency style. @@ -3469,20 +3509,21 @@ for (;;) { UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]); UErrorCode status = U_ZERO_ERROR; Formattable parseResult; + logln("parse(%s)", DATA[i][j]); numFmt->parse(oneCurrencyFormatResult, parseResult, status); if (U_FAILURE(status) || (parseResult.getType() == Formattable::kDouble && parseResult.getDouble() != numberToBeFormat) || (parseResult.getType() == Formattable::kLong && parseResult.getLong() != numberToBeFormat)) { - errln((UnicodeString)"FAIL: getCurrencyFormat of locale " + - localeString + " failed roundtripping the number" + - "(i,k,j): " + i + ", " + k + ", " + j); + errln((UnicodeString)"FAIL: NumberFormat(" + localeString +", " + currencyStyleNames[kIndex] + + "), Currency="+currencyISOCode+", parse("+DATA[i][j]+") returned error " + (UnicodeString)u_errorName(status)+". Testcase: data[" + i + "][" + currencyStyleNames[j-3] +"="+j+"]"); if (parseResult.getType() == Formattable::kDouble) { - errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getDouble()); + errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (double): " +parseResult.getDouble()); } else { - errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getLong()); + errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (long): " +parseResult.getLong()); } + errln((UnicodeString)" round-trip would be: " + strBuf); } } delete numFmt; diff --git a/icu4c/source/test/intltest/numfmtst.h b/icu4c/source/test/intltest/numfmtst.h index 95269d7340c..ada6f8418ea 100644 --- a/icu4c/source/test/intltest/numfmtst.h +++ b/icu4c/source/test/intltest/numfmtst.h @@ -169,7 +169,7 @@ class NumberFormatTest: public CalendarTimeZoneTest { void TestBug9936(); private: - void expectParseCurrency(const NumberFormat &fmt, const UChar* currency, const char *text); + void expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text); static UBool equalValue(const Formattable& a, const Formattable& b); -- 2.50.0