From 9219c6ae038a3556dffca880e93d2f2ca00e685a Mon Sep 17 00:00:00 2001 From: John Wilcock Date: Tue, 23 Jun 2020 16:03:25 +0000 Subject: [PATCH] ICU-13733 Added test for mismatching currency format for strict-mode parsing See #1169 --- icu4c/source/test/intltest/numfmtst.cpp | 81 +++++++++++++++++++ icu4c/source/test/intltest/numfmtst.h | 1 + .../icu/dev/test/format/NumberFormatTest.java | 77 ++++++++++++++++++ 3 files changed, 159 insertions(+) diff --git a/icu4c/source/test/intltest/numfmtst.cpp b/icu4c/source/test/intltest/numfmtst.cpp index ebc9543e01e..ed912cf3ce1 100644 --- a/icu4c/source/test/intltest/numfmtst.cpp +++ b/icu4c/source/test/intltest/numfmtst.cpp @@ -246,6 +246,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n TESTCASE_AUTO(Test13734_StrictFlexibleWhitespace); TESTCASE_AUTO(Test20961_CurrencyPluralPattern); TESTCASE_AUTO(Test21134_ToNumberFormatter); + TESTCASE_AUTO(Test13733_StrictAndLenient); TESTCASE_AUTO_END; } @@ -9930,4 +9931,84 @@ void NumberFormatTest::Test21134_ToNumberFormatter() { result3.toTempString(status)); } +void NumberFormatTest::Test13733_StrictAndLenient() { + IcuTestErrorCode status(*this, "Test13733_StrictAndLenient"); + + static const struct TestCase { + const char16_t* inputString; + const char16_t* patternString; + int64_t expectedStrictParse; + int64_t expectedLenientParse; + } cases[] = { {u"CA$ 12", u"¤ 0", 12, 12}, + {u"CA$12", u"¤0", 12, 12}, + {u"CAD 12", u"¤¤ 0", 12, 12}, + {u"12 CAD", u"0 ¤¤", 12, 12}, + {u"12 Canadian dollars", u"0 ¤¤¤", 12, 12}, + {u"$12 ", u"¤¤¤¤0", 12, 12}, + {u"12$", u"0¤¤¤¤", 12, 12}, + {u"CA$ 12", u"¤0", 0, 12}, + {u"CA$ 12", u"0 ¤¤", 0, 12}, + {u"CA$ 12", u"0 ¤¤¤", 0, 12}, + {u"CA$ 12", u"¤¤¤¤0", 0, 12}, + {u"CA$ 12", u"0¤¤¤¤", 0, 12}, + {u"CA$12", u"¤ 0", 0, 12}, + {u"CA$12", u"¤¤ 0", 0, 12}, + {u"CA$12", u"0 ¤¤", 0, 12}, + {u"CA$12", u"0 ¤¤¤", 0, 12}, + {u"CA$12", u"0¤¤¤¤", 0, 12}, + {u"CAD 12", u"¤0", 0, 12}, + {u"CAD 12", u"0 ¤¤", 0, 12}, + {u"CAD 12", u"0 ¤¤¤", 0, 12}, + {u"CAD 12", u"¤¤¤¤0", 0, 12}, + {u"CAD 12", u"0¤¤¤¤", 0, 12}, + {u"12 CAD", u"¤ 0", 0, 12}, + {u"12 CAD", u"¤0", 0, 12}, + {u"12 CAD", u"¤¤ 0", 0, 12}, + {u"12 CAD", u"¤¤¤¤0", 0, 12}, + {u"12 CAD", u"0¤¤¤¤", 0, 12}, + {u"12 Canadian dollars", u"¤ 0", 0, 12}, + {u"12 Canadian dollars", u"¤0", 0, 12}, + {u"12 Canadian dollars", u"¤¤ 0", 0, 12}, + {u"12 Canadian dollars", u"¤¤¤¤0", 0, 12}, + {u"12 Canadian dollars", u"0¤¤¤¤", 0, 12}, + {u"$12 ", u"¤ 0", 0, 12}, + {u"$12 ", u"¤¤ 0", 0, 12}, + {u"$12 ", u"0 ¤¤", 0, 12}, + {u"$12 ", u"0 ¤¤¤", 0, 12}, + {u"$12 ", u"0¤¤¤¤", 0, 12}, + {u"12$", u"¤ 0", 0, 12}, + {u"12$", u"¤0", 0, 12}, + {u"12$", u"¤¤ 0", 0, 12}, + {u"12$", u"0 ¤¤", 0, 12}, + {u"12$", u"0 ¤¤¤", 0, 12}, + {u"12$", u"¤¤¤¤0", 0, 12} }; + for (auto& cas : cases) { + UnicodeString inputString(cas.inputString); + UnicodeString patternString(cas.patternString); + int64_t parsedStrictValue = 0; + int64_t parsedLenientValue = 0; + ParsePosition ppos; + + DecimalFormatSymbols dfs(Locale::getEnglish(), status); + DecimalFormat df(patternString, dfs, status); + df.setLenient(FALSE); + LocalPointer ca_strict(df.parseCurrency(inputString, ppos)); + if (ca_strict != nullptr) { + parsedStrictValue = ca_strict->getNumber().getInt64(); + } + assertEquals("Strict parse of " + inputString + " using " + patternString, + parsedStrictValue, cas.expectedStrictParse); + + ppos.setIndex(0); + df.setLenient(TRUE); + LocalPointer ca_lenient(df.parseCurrency(inputString, ppos)); + Formattable parsedNumber_lenient = ca_lenient->getNumber(); + if (ca_lenient != nullptr) { + parsedLenientValue = ca_lenient->getNumber().getInt64(); + } + assertEquals("Lenient parse of " + inputString + " using " + patternString, + parsedLenientValue, cas.expectedLenientParse); + } +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/test/intltest/numfmtst.h b/icu4c/source/test/intltest/numfmtst.h index bb8a1e486d4..309098c32aa 100644 --- a/icu4c/source/test/intltest/numfmtst.h +++ b/icu4c/source/test/intltest/numfmtst.h @@ -302,6 +302,7 @@ class NumberFormatTest: public CalendarTimeZoneTest { void Test13734_StrictFlexibleWhitespace(); void Test20961_CurrencyPluralPattern(); void Test21134_ToNumberFormatter(); + void Test13733_StrictAndLenient(); private: UBool testFormattableAsUFormattable(const char *file, int line, Formattable &f); diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java index d4a2bfaff53..babe1594910 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java @@ -6829,4 +6829,81 @@ public class NumberFormatTest extends TestFmwk { DecimalFormat decimalFormat = (DecimalFormat) NumberFormat.getInstance(ULocale.US, NumberFormat.PLURALCURRENCYSTYLE); assertEquals("Currency pattern", "#,##0.00 ¤¤¤", decimalFormat.toPattern()); } + + @Test + public void test13733_StrictAndLenient() { + Object[][] cases = { {"CA$ 12", "¤ 0", 12, 12}, + {"CA$12", "¤0", 12, 12}, + {"CAD 12", "¤¤ 0", 12, 12}, + {"12 CAD", "0 ¤¤", 12, 12}, + {"12 Canadian dollars", "0 ¤¤¤", 12, 12}, + {"$12 ", "¤¤¤¤0", 12, 12}, + {"12$", "0¤¤¤¤", 12, 12}, + {"CA$ 12", "¤0", 0, 12}, + {"CA$ 12", "0 ¤¤", 0, 12}, + {"CA$ 12", "0 ¤¤¤", 0, 12}, + {"CA$ 12", "¤¤¤¤0", 0, 12}, + {"CA$ 12", "0¤¤¤¤", 0, 12}, + {"CA$12", "¤ 0", 0, 12}, + {"CA$12", "¤¤ 0", 0, 12}, + {"CA$12", "0 ¤¤", 0, 12}, + {"CA$12", "0 ¤¤¤", 0, 12}, + {"CA$12", "0¤¤¤¤", 0, 12}, + {"CAD 12", "¤0", 0, 12}, + {"CAD 12", "0 ¤¤", 0, 12}, + {"CAD 12", "0 ¤¤¤", 0, 12}, + {"CAD 12", "¤¤¤¤0", 0, 12}, + {"CAD 12", "0¤¤¤¤", 0, 12}, + {"12 CAD", "¤ 0", 0, 12}, + {"12 CAD", "¤0", 0, 12}, + {"12 CAD", "¤¤ 0", 0, 12}, + {"12 CAD", "¤¤¤¤0", 0, 12}, + {"12 CAD", "0¤¤¤¤", 0, 12}, + {"12 Canadian dollars", "¤ 0", 0, 12}, + {"12 Canadian dollars", "¤0", 0, 12}, + {"12 Canadian dollars", "¤¤ 0", 0, 12}, + {"12 Canadian dollars", "¤¤¤¤0", 0, 12}, + {"12 Canadian dollars", "0¤¤¤¤", 0, 12}, + {"$12 ", "¤ 0", 0, 12}, + {"$12 ", "¤¤ 0", 0, 12}, + {"$12 ", "0 ¤¤", 0, 12}, + {"$12 ", "0 ¤¤¤", 0, 12}, + {"$12 ", "0¤¤¤¤", 0, 12}, + {"12$", "¤ 0", 0, 12}, + {"12$", "¤0", 0, 12}, + {"12$", "¤¤ 0", 0, 12}, + {"12$", "0 ¤¤", 0, 12}, + {"12$", "0 ¤¤¤", 0, 12}, + {"12$", "¤¤¤¤0", 0, 12} }; + + for (Object[] cas : cases) { + String inputString = (String) cas[0]; + String patternString = (String) cas[1]; + int expectedStrictParse = (int) cas[2]; + int expectedLenientParse = (int) cas[3]; + + int parsedStrictValue = 0; + int parsedLenientValue = 0; + ParsePosition ppos = new ParsePosition(0); + DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(ULocale.ENGLISH); + DecimalFormat df = new DecimalFormat(patternString, dfs); + + df.setParseStrict(true); + CurrencyAmount ca_strict = df.parseCurrency(inputString, ppos); + if (null != ca_strict) { + parsedStrictValue = ca_strict.getNumber().intValue(); + } + assertEquals("Strict parse of " + inputString + " using " + patternString, + parsedStrictValue, expectedStrictParse); + + ppos.setIndex(0); + df.setParseStrict(false); + CurrencyAmount ca_lenient = df.parseCurrency(inputString, ppos); + if (null != ca_lenient) { + parsedLenientValue = ca_lenient.getNumber().intValue(); + } + assertEquals("Strict parse of " + inputString + " using " + patternString, + parsedLenientValue, expectedLenientParse); + } + } } -- 2.40.0