]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/intltest/plurults.cpp
ICU-66108.tar.gz
[apple/icu.git] / icuSources / test / intltest / plurults.cpp
index 7d342287d980a3af7e23a541b24c5271f00b442e..a70c362b7ab66c144481a475a5b5c2b1fbd4d15e 100644 (file)
@@ -6,7 +6,7 @@
 * others. All Rights Reserved.
 ********************************************************************************
 
-* File PLURRULTS.cpp
+* File PLURULTS.cpp
 *
 ********************************************************************************
 */
 #include "unicode/localpointer.h"
 #include "unicode/plurrule.h"
 #include "unicode/stringpiece.h"
+#include "unicode/numberformatter.h"
 
 #include "cmemory.h"
-#include "digitlst.h"
 #include "plurrule_impl.h"
 #include "plurults.h"
 #include "uhash.h"
+#include "number_decimalquantity.h"
+
+using icu::number::impl::DecimalQuantity;
 
 void setupResult(const int32_t testSource[], char result[], int32_t* max);
 UBool checkEqual(const PluralRules &test, char *result, int32_t max);
@@ -51,6 +54,8 @@ void PluralRulesTest::runIndexedTest( int32_t index, UBool exec, const char* &na
     TESTCASE_AUTO(testAvailbleLocales);
     TESTCASE_AUTO(testParseErrors);
     TESTCASE_AUTO(testFixedDecimal);
+    TESTCASE_AUTO(testSelectTrailingZeros);
+    TESTCASE_AUTO(testLocaleExtension);
     TESTCASE_AUTO_END;
 }
 
@@ -64,9 +69,9 @@ class US {
     US(const UnicodeString &us) {
        int32_t bufLen = us.extract((int32_t)0, us.length(), (char *)NULL, (uint32_t)0) + 1;
        buf = (char *)uprv_malloc(bufLen);
-       us.extract(0, us.length(), buf, bufLen); };
-    const char *cstr() {return buf;};
-    ~US() { uprv_free(buf);};
+       us.extract(0, us.length(), buf, bufLen); }
+    const char *cstr() {return buf;}
+    ~US() { uprv_free(buf);}
 };
 
 
@@ -593,7 +598,7 @@ PluralRulesTest::testGetAllKeywordValues() {
 void PluralRulesTest::testOrdinal() {
     IcuTestErrorCode errorCode(*this, "testOrdinal");
     LocalPointer<PluralRules> pr(PluralRules::forLocale("en", UPLURAL_TYPE_ORDINAL, errorCode));
-    if (errorCode.logIfFailureAndReset("PluralRules::forLocale(en, UPLURAL_TYPE_ORDINAL) failed")) {
+    if (errorCode.errIfFailureAndReset("PluralRules::forLocale(en, UPLURAL_TYPE_ORDINAL) failed")) {
         return;
     }
     UnicodeString keyword = pr->select(2.);
@@ -633,16 +638,16 @@ void PluralRulesTest::checkSelect(const LocalPointer<PluralRules> &rules, UError
         }
 
         // DigitList is a convenient way to parse the decimal number string and get a double.
-        DigitList  dl;
-        dl.set(StringPiece(num), status);
+        DecimalQuantity  dl;
+        dl.setToDecNumber(StringPiece(num), status);
         if (U_FAILURE(status)) {
             errln("file %s, line %d, ICU error status: %s.", __FILE__, line, u_errorName(status));
             status = U_ZERO_ERROR;
             continue;
         }
-        double numDbl = dl.getDouble();
+        double numDbl = dl.toDouble();
         const char *decimalPoint = strchr(num, '.');
-        int fractionDigitCount = decimalPoint == NULL ? 0 : (num + strlen(num) - 1) - decimalPoint;
+        int fractionDigitCount = decimalPoint == NULL ? 0 : static_cast<int>((num + strlen(num) - 1) - decimalPoint);
         int fractionDigits = fractionDigitCount == 0 ? 0 : atoi(decimalPoint + 1);
         FixedDecimal ni(numDbl, fractionDigitCount, fractionDigits);
         
@@ -1002,5 +1007,64 @@ void PluralRulesTest::testFixedDecimal() {
 }
 
 
+void PluralRulesTest::testSelectTrailingZeros() {
+    IcuTestErrorCode status(*this, "testSelectTrailingZeros");
+    number::UnlocalizedNumberFormatter unf = number::NumberFormatter::with()
+            .precision(number::Precision::fixedFraction(2));
+    struct TestCase {
+        const char* localeName;
+        const char16_t* expectedDoubleKeyword;
+        const char16_t* expectedFormattedKeyword;
+        double number;
+    } cases[] = {
+        {"bs",  u"few",   u"other", 5.2},  // 5.2 => two, but 5.20 => other
+        {"si",  u"one",   u"one",   0.0},
+        {"si",  u"one",   u"one",   1.0},
+        {"si",  u"one",   u"other", 0.1},  // 0.1 => one, but 0.10 => other
+        {"si",  u"one",   u"one",   0.01}, // 0.01 => one
+        {"hsb", u"few",   u"few",   1.03}, // (f % 100 == 3) => few
+        {"hsb", u"few",   u"other", 1.3},  // 1.3 => few, but 1.30 => other
+    };
+    for (const auto& cas : cases) {
+        UnicodeString message(UnicodeString(cas.localeName) + u" " + DoubleToUnicodeString(cas.number));
+        status.setScope(message);
+        Locale locale(cas.localeName);
+        LocalPointer<PluralRules> rules(PluralRules::forLocale(locale, status));
+        assertEquals(message, cas.expectedDoubleKeyword, rules->select(cas.number));
+        number::FormattedNumber fn = unf.locale(locale).formatDouble(cas.number, status);
+        assertEquals(message, cas.expectedFormattedKeyword, rules->select(fn, status));
+        status.errIfFailureAndReset();
+    }
+}
+
+void PluralRulesTest::compareLocaleResults(const char* loc1, const char* loc2, const char* loc3) {
+    UErrorCode status = U_ZERO_ERROR;
+    LocalPointer<PluralRules> rules1(PluralRules::forLocale(loc1, status));
+    LocalPointer<PluralRules> rules2(PluralRules::forLocale(loc2, status));
+    LocalPointer<PluralRules> rules3(PluralRules::forLocale(loc3, status));
+    if (U_FAILURE(status)) {
+        dataerrln("Failed to create PluralRules for one of %s, %s, %s: %s\n", loc1, loc2, loc3, u_errorName(status));
+        return;
+    }
+    for (int32_t value = 0; value <= 12; value++) {
+        UnicodeString result1 = rules1->select(value);
+        UnicodeString result2 = rules2->select(value);
+        UnicodeString result3 = rules3->select(value);
+        if (result1 != result2 || result1 != result3) {
+            errln("PluralRules.select(%d) does not return the same values for %s, %s, %s\n", value, loc1, loc2, loc3);
+        }
+    }
+}
+
+void PluralRulesTest::testLocaleExtension() {
+    IcuTestErrorCode errorCode(*this, "testLocaleExtension");
+    LocalPointer<PluralRules> rules(PluralRules::forLocale("pt@calendar=gregorian", errorCode));
+    if (errorCode.errIfFailureAndReset("PluralRules::forLocale()")) { return; }
+    UnicodeString key = rules->select(1);
+    assertEquals("pt@calendar=gregorian select(1)", u"one", key);
+    compareLocaleResults("ar", "ar_SA", "ar_SA@calendar=gregorian");
+    compareLocaleResults("ru", "ru_UA", "ru-u-cu-RUB");
+    compareLocaleResults("fr", "fr_CH", "fr@ms=uksystem");
+}
 
 #endif /* #if !UCONFIG_NO_FORMATTING */