| Index: source/test/intltest/itrbnf.cpp
|
| diff --git a/source/test/intltest/itrbnf.cpp b/source/test/intltest/itrbnf.cpp
|
| index 1e08e8272d45a090ad62d4926281927ec56dd420..fcd6cbf149fb554e00df5feaf171c1a66cd5a338 100644
|
| --- a/source/test/intltest/itrbnf.cpp
|
| +++ b/source/test/intltest/itrbnf.cpp
|
| @@ -1,6 +1,6 @@
|
| /*
|
| *******************************************************************************
|
| - * Copyright (C) 1996-2013, International Business Machines Corporation and *
|
| + * Copyright (C) 1996-2014, International Business Machines Corporation and *
|
| * others. All Rights Reserved. *
|
| *******************************************************************************
|
| */
|
| @@ -21,8 +21,6 @@
|
| #include "unicode/udata.h"
|
| #include "testutil.h"
|
|
|
| -//#include "llong.h"
|
| -
|
| #include <string.h>
|
|
|
| // import com.ibm.text.RuleBasedNumberFormat;
|
| @@ -67,6 +65,7 @@ void IntlTestRBNF::runIndexedTest(int32_t index, UBool exec, const char* &name,
|
| TESTCASE(17, TestPortugueseSpellout);
|
| TESTCASE(18, TestMultiplierSubstitution);
|
| TESTCASE(19, TestSetDecimalFormatSymbols);
|
| + TESTCASE(20, TestPluralRules);
|
| #else
|
| TESTCASE(0, TestRBNFDisabled);
|
| #endif
|
| @@ -1801,34 +1800,25 @@ IntlTestRBNF::TestAllLocales()
|
| {
|
| const char* names[] = {
|
| " (spellout) ",
|
| - " (ordinal) ",
|
| - " (duration) "
|
| + " (ordinal) "
|
| + // " (duration) " // This is English only, and it's not really supported in CLDR anymore.
|
| };
|
| double numbers[] = {45.678, 1, 2, 10, 11, 100, 110, 200, 1000, 1111, -1111};
|
|
|
| - // RBNF parse is extremely slow when lenient option is enabled.
|
| - // For non-exhaustive mode, we only test a few locales.
|
| - const char* parseLocales[] = {"en_US", "nl_NL", "be", NULL};
|
| -
|
| -
|
| int32_t count = 0;
|
| const Locale* locales = Locale::getAvailableLocales(count);
|
| for (int i = 0; i < count; ++i) {
|
| const Locale* loc = &locales[i];
|
| - UBool testParse = TRUE;
|
| - if (quick) {
|
| - testParse = FALSE;
|
| - for (int k = 0; parseLocales[k] != NULL; k++) {
|
| - if (strcmp(loc->getLanguage(), parseLocales[k]) == 0) {
|
| - testParse = TRUE;
|
| - break;
|
| - }
|
| - }
|
| - }
|
|
|
| - for (int j = 0; j < 3; ++j) {
|
| + for (int j = 0; j < 2; ++j) {
|
| UErrorCode status = U_ZERO_ERROR;
|
| RuleBasedNumberFormat* f = new RuleBasedNumberFormat((URBNFRuleSetTag)j, *loc, status);
|
| +
|
| + if (status == U_USING_DEFAULT_WARNING || status == U_USING_FALLBACK_WARNING) {
|
| + // Skip it.
|
| + delete f;
|
| + break;
|
| + }
|
| if (U_FAILURE(status)) {
|
| errln(UnicodeString(loc->getName()) + names[j]
|
| + "ERROR could not instantiate -> " + u_errorName(status));
|
| @@ -1840,40 +1830,58 @@ IntlTestRBNF::TestAllLocales()
|
| UnicodeString str;
|
| f->format(n, str);
|
|
|
| - logln(UnicodeString(loc->getName()) + names[j]
|
| - + "success: " + n + " -> " + str);
|
| + if (verbose) {
|
| + logln(UnicodeString(loc->getName()) + names[j]
|
| + + "success: " + n + " -> " + str);
|
| + }
|
|
|
| - if (testParse) {
|
| - // We do not validate the result in this test case,
|
| - // because there are cases which do not round trip by design.
|
| - Formattable num;
|
| + // We do not validate the result in this test case,
|
| + // because there are cases which do not round trip by design.
|
| + Formattable num;
|
|
|
| - // regular parse
|
| - status = U_ZERO_ERROR;
|
| - f->setLenient(FALSE);
|
| - f->parse(str, num, status);
|
| - if (U_FAILURE(status)) {
|
| - //TODO: We need to fix parse problems - see #6895 / #6896
|
| - if (status == U_INVALID_FORMAT_ERROR) {
|
| - logln(UnicodeString(loc->getName()) + names[j]
|
| - + "WARNING could not parse '" + str + "' -> " + u_errorName(status));
|
| - } else {
|
| - errln(UnicodeString(loc->getName()) + names[j]
|
| - + "ERROR could not parse '" + str + "' -> " + u_errorName(status));
|
| - }
|
| + // regular parse
|
| + status = U_ZERO_ERROR;
|
| + f->setLenient(FALSE);
|
| + f->parse(str, num, status);
|
| + if (U_FAILURE(status)) {
|
| + errln(UnicodeString(loc->getName()) + names[j]
|
| + + "ERROR could not parse '" + str + "' -> " + u_errorName(status));
|
| + }
|
| + // We only check the spellout. The behavior is undefined for numbers < 1 and fractional numbers.
|
| + if (j == 0) {
|
| + if (num.getType() == Formattable::kLong && num.getLong() != n) {
|
| + errln(UnicodeString(loc->getName()) + names[j]
|
| + + UnicodeString("ERROR could not roundtrip ") + n
|
| + + UnicodeString(" -> ") + str + UnicodeString(" -> ") + num.getLong());
|
| }
|
| + else if (num.getType() == Formattable::kDouble && (int64_t)(num.getDouble() * 1000) != (int64_t)(n*1000)) {
|
| + // The epsilon difference is too high.
|
| + errln(UnicodeString(loc->getName()) + names[j]
|
| + + UnicodeString("ERROR could not roundtrip ") + n
|
| + + UnicodeString(" -> ") + str + UnicodeString(" -> ") + num.getDouble());
|
| + }
|
| + }
|
| + if (!quick && !logKnownIssue("9503") ) {
|
| // lenient parse
|
| status = U_ZERO_ERROR;
|
| f->setLenient(TRUE);
|
| f->parse(str, num, status);
|
| if (U_FAILURE(status)) {
|
| - //TODO: We need to fix parse problems - see #6895 / #6896
|
| - if (status == U_INVALID_FORMAT_ERROR) {
|
| - logln(UnicodeString(loc->getName()) + names[j]
|
| - + "WARNING could not parse(lenient) '" + str + "' -> " + u_errorName(status));
|
| - } else {
|
| + errln(UnicodeString(loc->getName()) + names[j]
|
| + + "ERROR could not parse(lenient) '" + str + "' -> " + u_errorName(status));
|
| + }
|
| + // We only check the spellout. The behavior is undefined for numbers < 1 and fractional numbers.
|
| + if (j == 0) {
|
| + if (num.getType() == Formattable::kLong && num.getLong() != n) {
|
| + errln(UnicodeString(loc->getName()) + names[j]
|
| + + UnicodeString("ERROR could not roundtrip ") + n
|
| + + UnicodeString(" -> ") + str + UnicodeString(" -> ") + num.getLong());
|
| + }
|
| + else if (num.getType() == Formattable::kDouble && (int64_t)(num.getDouble() * 1000) != (int64_t)(n*1000)) {
|
| + // The epsilon difference is too high.
|
| errln(UnicodeString(loc->getName()) + names[j]
|
| - + "ERROR could not parse(lenient) '" + str + "' -> " + u_errorName(status));
|
| + + UnicodeString("ERROR could not roundtrip ") + n
|
| + + UnicodeString(" -> ") + str + UnicodeString(" -> ") + num.getDouble());
|
| }
|
| }
|
| }
|
| @@ -1886,27 +1894,27 @@ IntlTestRBNF::TestAllLocales()
|
|
|
| void
|
| IntlTestRBNF::TestMultiplierSubstitution(void) {
|
| - UnicodeString rules("=#,##0=;1,000,000: <##0.###< million;");
|
| - UErrorCode status = U_ZERO_ERROR;
|
| - UParseError parse_error;
|
| - RuleBasedNumberFormat *rbnf =
|
| - new RuleBasedNumberFormat(rules, Locale::getUS(), parse_error, status);
|
| - if (U_SUCCESS(status)) {
|
| - UnicodeString res;
|
| - FieldPosition pos;
|
| - double n = 1234000.0;
|
| - rbnf->format(n, res, pos);
|
| - delete rbnf;
|
| -
|
| - UnicodeString expected = UNICODE_STRING_SIMPLE("1.234 million");
|
| - if (expected != res) {
|
| - UnicodeString msg = "Expected: ";
|
| - msg.append(expected);
|
| - msg.append(" but got ");
|
| - msg.append(res);
|
| - errln(msg);
|
| + UnicodeString rules("=#,##0=;1,000,000: <##0.###< million;");
|
| + UErrorCode status = U_ZERO_ERROR;
|
| + UParseError parse_error;
|
| + RuleBasedNumberFormat *rbnf =
|
| + new RuleBasedNumberFormat(rules, Locale::getUS(), parse_error, status);
|
| + if (U_SUCCESS(status)) {
|
| + UnicodeString res;
|
| + FieldPosition pos;
|
| + double n = 1234000.0;
|
| + rbnf->format(n, res, pos);
|
| + delete rbnf;
|
| +
|
| + UnicodeString expected(UNICODE_STRING_SIMPLE("1.234 million"));
|
| + if (expected != res) {
|
| + UnicodeString msg = "Expected: ";
|
| + msg.append(expected);
|
| + msg.append(" but got ");
|
| + msg.append(res);
|
| + errln(msg);
|
| + }
|
| }
|
| - }
|
| }
|
|
|
| void
|
| @@ -1951,6 +1959,106 @@ IntlTestRBNF::TestSetDecimalFormatSymbols() {
|
| }
|
| }
|
|
|
| +void IntlTestRBNF::TestPluralRules() {
|
| + UErrorCode status = U_ZERO_ERROR;
|
| + UnicodeString enRules("%digits-ordinal:-x: ->>;0: =#,##0=$(ordinal,one{st}two{nd}few{rd}other{th})$;");
|
| + UParseError parseError;
|
| + RuleBasedNumberFormat enFormatter(enRules, Locale::getEnglish(), parseError, status);
|
| + if (U_FAILURE(status)) {
|
| + dataerrln("Unable to create RuleBasedNumberFormat - " + UnicodeString(u_errorName(status)));
|
| + return;
|
| + }
|
| + const char* const enTestData[][2] = {
|
| + { "1", "1st" },
|
| + { "2", "2nd" },
|
| + { "3", "3rd" },
|
| + { "4", "4th" },
|
| + { "11", "11th" },
|
| + { "12", "12th" },
|
| + { "13", "13th" },
|
| + { "14", "14th" },
|
| + { "21", "21st" },
|
| + { "22", "22nd" },
|
| + { "23", "23rd" },
|
| + { "24", "24th" },
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + doTest(&enFormatter, enTestData, TRUE);
|
| +
|
| + // This is trying to model the feminine form, but don't worry about the details too much.
|
| + // We're trying to test the plural rules.
|
| + UnicodeString ruRules("%spellout-numbering:"
|
| + "-x: minus >>;"
|
| + "x.x: << point >>;"
|
| + "0: zero;"
|
| + "1: one;"
|
| + "2: two;"
|
| + "3: three;"
|
| + "4: four;"
|
| + "5: five;"
|
| + "6: six;"
|
| + "7: seven;"
|
| + "8: eight;"
|
| + "9: nine;"
|
| + "10: ten;"
|
| + "11: eleven;"
|
| + "12: twelve;"
|
| + "13: thirteen;"
|
| + "14: fourteen;"
|
| + "15: fifteen;"
|
| + "16: sixteen;"
|
| + "17: seventeen;"
|
| + "18: eighteen;"
|
| + "19: nineteen;"
|
| + "20: twenty[->>];"
|
| + "30: thirty[->>];"
|
| + "40: forty[->>];"
|
| + "50: fifty[->>];"
|
| + "60: sixty[->>];"
|
| + "70: seventy[->>];"
|
| + "80: eighty[->>];"
|
| + "90: ninety[->>];"
|
| + "100: hundred[ >>];"
|
| + "200: << hundred[ >>];"
|
| + "300: << hundreds[ >>];"
|
| + "500: << hundredss[ >>];"
|
| + "1000: << $(cardinal,one{thousand}few{thousands}other{thousandss})$[ >>];"
|
| + "1000000: << $(cardinal,one{million}few{millions}other{millionss})$[ >>];");
|
| + RuleBasedNumberFormat ruFormatter(ruRules, Locale("ru"), parseError, status);
|
| + const char* const ruTestData[][2] = {
|
| + { "1", "one" },
|
| + { "100", "hundred" },
|
| + { "125", "hundred twenty-five" },
|
| + { "399", "three hundreds ninety-nine" },
|
| + { "1,000", "one thousand" },
|
| + { "1,001", "one thousand one" },
|
| + { "2,000", "two thousands" },
|
| + { "2,001", "two thousands one" },
|
| + { "2,002", "two thousands two" },
|
| + { "3,333", "three thousands three hundreds thirty-three" },
|
| + { "5,000", "five thousandss" },
|
| + { "11,000", "eleven thousandss" },
|
| + { "21,000", "twenty-one thousand" },
|
| + { "22,000", "twenty-two thousands" },
|
| + { "25,001", "twenty-five thousandss one" },
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + if (U_FAILURE(status)) {
|
| + errln("Unable to create RuleBasedNumberFormat - " + UnicodeString(u_errorName(status)));
|
| + return;
|
| + }
|
| + doTest(&ruFormatter, ruTestData, TRUE);
|
| +
|
| + // Make sure there are no divide by 0 errors.
|
| + UnicodeString result;
|
| + RuleBasedNumberFormat(ruRules, Locale("ru"), parseError, status).format(21000, result);
|
| + if (result.compare(UNICODE_STRING_SIMPLE("twenty-one thousand")) != 0) {
|
| + errln("Got " + result + " for 21000");
|
| + }
|
| +
|
| +}
|
|
|
| void
|
| IntlTestRBNF::doTest(RuleBasedNumberFormat* formatter, const char* const testData[][2], UBool testParsing)
|
|
|