ICU-20631 Fix desired currency not set for some NumberFormat currency styles

This commit is contained in:
Azamshul Azizy 2019-05-30 18:53:13 +09:00 committed by Shane F. Carr
parent 2b611dbf6e
commit 5174ad5511
4 changed files with 90 additions and 2 deletions

View File

@ -169,6 +169,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
TESTCASE_AUTO(TestRoundingScientific10542);
TESTCASE_AUTO(TestZeroScientific10547);
TESTCASE_AUTO(TestAccountingCurrency);
TESTCASE_AUTO(TestCurrencyFormatForMissingLocale);
TESTCASE_AUTO(TestEquality);
TESTCASE_AUTO(TestCurrencyUsage);
TESTCASE_AUTO(TestDoubleLimit11439);
@ -8014,6 +8015,50 @@ void NumberFormatTest::TestAccountingCurrency() {
(Formattable)(double)-1000.5, UnicodeString("(\\uFFE51,000)").unescape(), FALSE, status);
expect(NumberFormat::createInstance("de_DE", style, status),
(Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status);
expect(NumberFormat::createInstance("en_ID", style, status),
(Formattable)(double)0, UnicodeString("IDR\\u00A00.00").unescape(), TRUE, status);
expect(NumberFormat::createInstance("en_ID", style, status),
(Formattable)(double)-0.2, UnicodeString("(IDR\\u00A00.20)").unescape(), TRUE, status);
expect(NumberFormat::createInstance("sh_ME", style, status),
(Formattable)(double)0, UnicodeString("0,00\\u00A0\\u20AC").unescape(), TRUE, status);
expect(NumberFormat::createInstance("sh_ME", style, status),
(Formattable)(double)-0.2, UnicodeString("(0,20\\u00A0\\u20AC)").unescape(), TRUE, status);
}
/**
* ICU4J has the behavior explained below, but ICU4C is not affected. Test is added to prevent regression.
*
* en_ID/sh_ME uses language only locales en/sh which requires NumberFormatServiceShim to fill in the currency, but
* prior to ICU-20631, currency was not filled in for accounting, cash and standard, so currency placeholder was
* used instead of the desired locale's currency.
*/
void NumberFormatTest::TestCurrencyFormatForMissingLocale() {
IcuTestErrorCode status(*this, "TestCurrencyFormatForMissingLocale");
Locale locale = Locale::createCanonical("sh_ME");
LocalPointer<NumberFormat> curFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status));
assertEquals("Currency instance is not for the desired locale for CURRENCYSTYLE", curFmt->getCurrency(), "EUR");
UnicodeString currBuf;
curFmt->format(-1234.5, currBuf);
assertEquals("NumberFormat format outputs wrong value for CURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", currBuf);
LocalPointer<NumberFormat> accFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_ACCOUNTING, status));
assertEquals("Currency instance is not for the desired locale for ACCOUNTINGCURRENCYSTYLE", accFmt->getCurrency(), "EUR");
UnicodeString accBuf;
accFmt->format(-1234.5, accBuf);
assertEquals("NumberFormat format outputs wrong value for ACCOUNTINGCURRENCYSTYLE", u"(1.234,50\u00A0\u20AC)", accBuf);
LocalPointer<NumberFormat> cashFmt(NumberFormat::createInstance(locale, UNUM_CASH_CURRENCY, status));
assertEquals("Currency instance is not for the desired locale for CASHCURRENCYSTYLE", cashFmt->getCurrency(), "EUR");
UnicodeString cashBuf;
cashFmt->format(-1234.5, cashBuf);
assertEquals("NumberFormat format outputs wrong value for CASHCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", cashBuf);
LocalPointer<NumberFormat> stdFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_STANDARD, status));
assertEquals("Currency instance is not for the desired locale for STANDARDCURRENCYSTYLE", stdFmt->getCurrency(), "EUR");
UnicodeString stdBuf;
stdFmt->format(-1234.5, stdBuf);
assertEquals("NumberFormat format outputs wrong value for STANDARDCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", stdBuf);
}
// for #5186

View File

@ -231,6 +231,7 @@ class NumberFormatTest: public CalendarTimeZoneTest {
void TestRoundingScientific10542();
void TestZeroScientific10547();
void TestAccountingCurrency();
void TestCurrencyFormatForMissingLocale();
void TestEquality();
void TestCurrencyUsage();

View File

@ -94,7 +94,10 @@ class NumberFormatServiceShim extends NumberFormat.NumberFormatShim {
// explicitly, since the actualLoc may be different than the desiredLocale
if ( choice == NumberFormat.CURRENCYSTYLE ||
choice == NumberFormat.ISOCURRENCYSTYLE ||
choice == NumberFormat.PLURALCURRENCYSTYLE) {
choice == NumberFormat.PLURALCURRENCYSTYLE ||
choice == NumberFormat.ACCOUNTINGCURRENCYSTYLE ||
choice == NumberFormat.CASHCURRENCYSTYLE ||
choice == NumberFormat.STANDARDCURRENCYSTYLE) {
fmt.setCurrency(Currency.getInstance(desiredLocale));
}

View File

@ -4416,6 +4416,18 @@ public class NumberFormatTest extends TestFmwk {
{"ja_JP", "-1000.5", "-¥1,000", "-¥1,000", "(¥1,000)", "false"},
{"ja_JP@cf=account", "-1000.5", "(¥1,000)", "-¥1,000", "(¥1,000)", "false"},
{"de_DE", "-23456.7", "-23.456,70\u00A0€", "-23.456,70\u00A0€", "-23.456,70\u00A0€", "true" },
{"en_ID", "1234.5", "IDR 1,234.50", "IDR 1,234.50", "IDR 1,234.50", "true"},
{"en_ID@cf=account", "1234.5", "IDR 1,234.50", "IDR 1,234.50", "IDR 1,234.50", "true"},
{"en_ID@cf=standard", "1234.5", "IDR 1,234.50", "IDR 1,234.50", "IDR 1,234.50", "true"},
{"en_ID", "-1234.5", "-IDR 1,234.50", "-IDR 1,234.50", "(IDR 1,234.50)", "true"},
{"en_ID@cf=account", "-1234.5", "(IDR 1,234.50)", "-IDR 1,234.50", "(IDR 1,234.50)", "true"},
{"en_ID@cf=standard", "-1234.5", "-IDR 1,234.50", "-IDR 1,234.50", "(IDR 1,234.50)", "true"},
{"sh_ME", "1234.5", "1.234,50 ", "1.234,50 ", "1.234,50 ", "true"},
{"sh_ME@cf=account", "1234.5", "1.234,50 ", "1.234,50 ", "1.234,50 ", "true"},
{"sh_ME@cf=standard", "1234.5", "1.234,50 ", "1.234,50 ", "1.234,50 ", "true"},
{"sh_ME", "-1234.5", "-1.234,50 ", "-1.234,50 ", "(1.234,50 €)", "true"},
{"sh_ME@cf=account", "-1234.5", "(1.234,50 €)", "-1.234,50 ", "(1.234,50 €)", "true"},
{"sh_ME@cf=standard", "-1234.5", "-1.234,50 ", "-1.234,50 ", "(1.234,50 €)", "true"},
};
for (String[] data : tests) {
ULocale loc = new ULocale(data[0]);
@ -4436,6 +4448,33 @@ public class NumberFormatTest extends TestFmwk {
}
}
/**
* en_ID/sh_ME uses language only locales en/sh which requires NumberFormatServiceShim to fill in the currency, but
* prior to ICU-20631, currency was not filled in for accounting, cash and standard, so currency placeholder was
* used instead of the desired locale's currency.
*/
@Test
public void TestCurrencyFormatForMissingLocale() {
ULocale loc = new ULocale("sh_ME");
Currency cur = Currency.getInstance(loc);
NumberFormat curFmt = NumberFormat.getInstance(loc, NumberFormat.CURRENCYSTYLE);
assertNotNull("NumberFormat is missing currency instance for CURRENCYSTYLE", curFmt.getCurrency());
assertEquals("Currency instance is not for the desired locale for CURRENCYSTYLE", cur, curFmt.getCurrency());
assertEquals("NumberFormat format outputs wrong value for CURRENCYSTYLE", "-1.234,50 ", curFmt.format(-1234.5d));
NumberFormat accFmt = NumberFormat.getInstance(loc, NumberFormat.ACCOUNTINGCURRENCYSTYLE);
assertNotNull("NumberFormat is missing currency instance for ACCOUNTINGCURRENCYSTYLE", accFmt.getCurrency());
assertEquals("Currency instance is not for the desired locale for ACCOUNTINGCURRENCYSTYLE", cur, accFmt.getCurrency());
assertEquals("NumberFormat format outputs wrong value for ACCOUNTINGCURRENCYSTYLE", "(1.234,50 €)", accFmt.format(-1234.5d));
NumberFormat cashFmt = NumberFormat.getInstance(loc, NumberFormat.CASHCURRENCYSTYLE);
assertNotNull("NumberFormat is missing currency instance for CASHCURRENCYSTYLE", cashFmt.getCurrency());
assertEquals("Currency instance is not for the desired locale for CASHCURRENCYSTYLE", cur, cashFmt.getCurrency());
assertEquals("NumberFormat format outputs wrong value for CASHCURRENCYSTYLE", "-1.234,50 ", cashFmt.format(-1234.5d));
NumberFormat stdFmt = NumberFormat.getInstance(loc, NumberFormat.STANDARDCURRENCYSTYLE);
assertNotNull("NumberFormat is missing currency instance for STANDARDCURRENCYSTYLE", stdFmt.getCurrency());
assertEquals("Currency instance is not for the desired locale for STANDARDCURRENCYSTYLE", cur, stdFmt.getCurrency());
assertEquals("NumberFormat format outputs wrong value for STANDARDCURRENCYSTYLE", "-1.234,50 ", stdFmt.format(-1234.5d));
}
@Test
public void TestCurrencyUsage() {
// the 1st one is checking setter/getter, while the 2nd one checks for getInstance