summaryrefslogtreecommitdiff
path: root/Build/source/libs/icu/icu-src/source/test/intltest
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/icu/icu-src/source/test/intltest')
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/csdetest.cpp23
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/csdetest.h1
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/dtfmttst.cpp2
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/dtifmtts.cpp41
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.cpp149
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.h10
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/icusvtst.cpp2
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/incaltst.cpp2
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/intltest.cpp12
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.cpp59
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.h1
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/lstmbetst.cpp4
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/measfmttest.cpp5
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/numbertest.h6
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/numbertest_api.cpp519
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/numbertest_decimalquantity.cpp58
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/numbertest_range.cpp22
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/numfmtst.cpp13
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/plurults.cpp6
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.cpp48
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.h4
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/strcase.cpp103
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/tmsgfmt.cpp4
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/transtst.cpp31
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/tztest.cpp64
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/units_test.cpp56
-rw-r--r--Build/source/libs/icu/icu-src/source/test/intltest/ustrtest.cpp12
27 files changed, 1134 insertions, 123 deletions
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.cpp
index 66f9340b83a..95f19d43d1a 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.cpp
@@ -109,6 +109,10 @@ void CharsetDetectionTest::runIndexedTest( int32_t index, UBool exec, const char
if (exec) Ticket6954Test();
break;
+ case 10: name = "Ticket21823Test";
+ if (exec) Ticket21823Test();
+ break;
+
default: name = "";
break; //needed to end loop
}
@@ -839,3 +843,22 @@ void CharsetDetectionTest::Ticket6954Test() {
TEST_ASSERT(strcmp(name1, "windows-1252")==0);
#endif
}
+
+
+// Ticket 21823 - Issue with Charset Detector for ill-formed input strings.
+// Its fix involves returning a failure based error code
+// (U_INVALID_CHAR_FOUND) incase no charsets appear to match the input data.
+void CharsetDetectionTest::Ticket21823Test() {
+ UErrorCode status = U_ZERO_ERROR;
+ std::string str = "\x80";
+ UCharsetDetector* csd = ucsdet_open(&status);
+
+ ucsdet_setText(csd, str.data(), str.length(), &status);
+ const UCharsetMatch* match = ucsdet_detect(csd, &status);
+
+ if (match == NULL) {
+ TEST_ASSERT(U_FAILURE(status));
+ }
+
+ ucsdet_close(csd);
+}
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.h b/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.h
index 72d1ca92aea..8893b88e591 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.h
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.h
@@ -33,6 +33,7 @@ public:
virtual void IBM420Test();
virtual void Ticket6394Test();
virtual void Ticket6954Test();
+ virtual void Ticket21823Test();
private:
void checkEncoding(const UnicodeString &testString,
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/dtfmttst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/dtfmttst.cpp
index 16f3002a95e..920ec75c8b9 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/dtfmttst.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/dtfmttst.cpp
@@ -190,7 +190,7 @@ void DateFormatTest::TestPatterns() {
{UDAT_ABBR_UTC_TZ, "ZZZZ", "en", "ZZZZ"},
{UDAT_YEAR_NUM_MONTH_DAY UDAT_ABBR_UTC_TZ, "yMdZZZZ", "en", "M/d/y, ZZZZ"},
- {UDAT_MONTH_DAY UDAT_LOCATION_TZ, "MMMMdVVVV", "en", "MMMM d, VVVV"}
+ {UDAT_MONTH_DAY UDAT_LOCATION_TZ, "MMMMdVVVV", "en", "MMMM d 'at' VVVV"}
};
IcuTestErrorCode errorCode(*this, "TestPatterns()");
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/dtifmtts.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/dtifmtts.cpp
index dc9a78dbe16..605eae43614 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/dtifmtts.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/dtifmtts.cpp
@@ -1107,8 +1107,23 @@ void DateIntervalFormatTest::testHourMetacharacters() {
"de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00\\u201301 Uhr",
// k and K (ICU-21154 and ICU-21156)
- "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "0 \\u2013 1 AM",
- "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "24\\u201301 Uhr",
+ // (should behave the same as h and H if not overridden in locale ID)
+ "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 AM",
+ "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00\\u201301 Uhr",
+ // (overriding hour cycle in locale ID should affect both h and K [or both H and k])
+ "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "0 \\u2013 1 AM",
+ "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "0 \\u2013 1 AM",
+ "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "24\\u201301 Uhr",
+ "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "24\\u201301 Uhr",
+ // (overriding hour cycle to h11 should NOT affect H and k; overriding to h24 should NOT affect h and K)
+ "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00 \\u2013 01",
+ "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00 \\u2013 01",
+ "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00 \\u2013 01",
+ "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00 \\u2013 01",
+ "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 Uhr AM",
+ "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 Uhr AM",
+ "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 Uhr AM",
+ "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 Uhr AM",
// different lengths of the 'a' field
"en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "ha", "10 AM \\u2013 1 PM",
@@ -1163,14 +1178,22 @@ void DateIntervalFormatTest::testHourMetacharacters() {
"hi_IN", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "\\u0938\\u0941\\u092C\\u0939 10 \\u2013 \\u0926\\u094B\\u092A\\u0939\\u0930 1",
"hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "\\u0930\\u093E\\u0924 12\\u20131",
- // regression test for ICU-21342
- "en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 10:00:00", "kk", "24\\u201310",
- "en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 11:00:00", "kk", "24\\u201311",
- "en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 12:00:00", "kk", "24\\u201312",
- "en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 13:00:00", "kk", "24\\u201313",
+ // regression test for ICU-21342
+ "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 10:00:00", "kk", "24\\u201310",
+ "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 11:00:00", "kk", "24\\u201311",
+ "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 12:00:00", "kk", "24\\u201312",
+ "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 13:00:00", "kk", "24\\u201313",
- // regression test for ICU-21343
- "de", "CE 2010 09 27 01:00:00", "CE 2010 09 27 10:00:00", "KK", "1 \\u2013 10 Uhr AM",
+ // regression test for ICU-21343
+ "de", "CE 2010 09 27 01:00:00", "CE 2010 09 27 10:00:00", "KK", "1 \\u2013 10 Uhr AM",
+
+ // regression test for ICU-21154 (single-date ranges should use the same hour cycle as multi-date ranges)
+ "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "hh", "12 AM",
+ "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 AM",
+ "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "KK", "12 AM",
+ "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 AM", // (this was producing "0 - 1 AM" before)
+ "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "jj", "12 AM",
+ "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "12 \\u2013 1 AM",
};
expect(DATA, UPRV_LENGTHOF(DATA));
}
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.cpp
index 6fe8af05b60..dde9d4dd3ac 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.cpp
@@ -46,6 +46,7 @@ void IntlTestDateTimePatternGeneratorAPI::runIndexedTest( int32_t index, UBool e
TESTCASE(10, testGetDefaultHourCycle_OnEmptyInstance);
TESTCASE(11, test_jConsistencyOddLocales);
TESTCASE(12, testBestPattern);
+ TESTCASE(13, testDateTimePatterns);
default: name = ""; break;
}
}
@@ -530,7 +531,7 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/)
format->applyPattern(gen->getBestPattern(UnicodeString("MMMMdHmm"), status));
dateReturned.remove();
dateReturned = format->format(sampleDate, dateReturned, status);
- expectedResult=UnicodeString("14. von Oktober, 08:58", -1, US_INV);
+ expectedResult=UnicodeString("14. von Oktober um 08:58", -1, US_INV);
if ( dateReturned != expectedResult ) {
errln(UnicodeString("ERROR: Simple test addPattern failed!: d\'. von\' MMMM Got: ") + dateReturned + UnicodeString(" Expected: ") + expectedResult);
}
@@ -1631,4 +1632,150 @@ void IntlTestDateTimePatternGeneratorAPI::testBestPattern() {
}
}
+void IntlTestDateTimePatternGeneratorAPI::testDateTimePatterns() {
+ UnicodeString skeletons[kNumDateTimePatterns] = {
+ UnicodeString("yMMMMEEEEdjmm"), // full date, short time
+ UnicodeString("yMMMMdjmm"), // long date, short time
+ UnicodeString("yMMMdjmm"), // medium date, short time
+ UnicodeString("yMdjmm") // short date, short time
+ };
+ // The following tests some locales in which there are differences between the
+ // DateTimePatterns of various length styles.
+ DTPLocaleAndResults localeAndResults[] = {
+ { "en", { UnicodeString(u"EEEE, MMMM d, y 'at' h:mm a"), // long != medium
+ UnicodeString(u"MMMM d, y 'at' h:mm a"),
+ UnicodeString(u"MMM d, y, h:mm a"),
+ UnicodeString(u"M/d/y, h:mm a") } },
+ { "fr", { UnicodeString(u"EEEE d MMMM y 'à' HH:mm"), // medium != short
+ UnicodeString(u"d MMMM y 'à' HH:mm"),
+ UnicodeString(u"d MMM y, HH:mm"),
+ UnicodeString(u"dd/MM/y HH:mm") } },
+ { "ha", { UnicodeString(u"EEEE d MMMM, y HH:mm"), // full != long
+ UnicodeString(u"d MMMM, y 'da' HH:mm"),
+ UnicodeString(u"d MMM, y, HH:mm"),
+ UnicodeString(u"y-MM-dd, HH:mm") } },
+ { nullptr, { UnicodeString(""), UnicodeString(""), // terminator
+ UnicodeString(""), UnicodeString("") } },
+ };
+
+ UnicodeString enDTPatterns[kNumDateTimePatterns] = {
+ UnicodeString(u"{1} 'at' {0}"),
+ UnicodeString(u"{1} 'at' {0}"),
+ UnicodeString(u"{1}, {0}"),
+ UnicodeString(u"{1}, {0}")
+ };
+ UnicodeString modDTPatterns[kNumDateTimePatterns] = {
+ UnicodeString(u"{1} _0_ {0}"),
+ UnicodeString(u"{1} _1_ {0}"),
+ UnicodeString(u"{1} _2_ {0}"),
+ UnicodeString(u"{1} _3_ {0}")
+ };
+ DTPLocaleAndResults enModResults = { "en", { UnicodeString(u"EEEE, MMMM d, y _0_ h:mm a"),
+ UnicodeString(u"MMMM d, y _1_ h:mm a"),
+ UnicodeString(u"MMM d, y _2_ h:mm a"),
+ UnicodeString(u"M/d/y _3_ h:mm a") }
+ };
+
+ // Test various locales with standard data
+ UErrorCode status;
+ LocalPointer<DateTimePatternGenerator> dtpg;
+ DTPLocaleAndResults* localeAndResultsPtr = localeAndResults;
+ for (; localeAndResultsPtr->localeID != nullptr; localeAndResultsPtr++) {
+ status = U_ZERO_ERROR;
+ Locale locale(localeAndResultsPtr->localeID);
+ dtpg.adoptInstead(DateTimePatternGenerator::createInstance(locale, status));
+ if (U_FAILURE(status)) {
+ dataerrln("FAIL: DateTimePatternGenerator::createInstance for locale %s: %s",
+ localeAndResultsPtr->localeID, u_errorName(status));
+ } else {
+ doDTPatternTest(dtpg.getAlias(), skeletons, localeAndResultsPtr);
+ }
+ }
+ // Test getting and modifying date-time combining patterns
+ status = U_ZERO_ERROR;
+ dtpg.adoptInstead(DateTimePatternGenerator::createInstance(Locale::getEnglish(), status));
+ if (U_FAILURE(status)) {
+ dataerrln("FAIL: DateTimePatternGenerator::createInstance #2 for locale en: %s", u_errorName(status));
+ } else {
+ char bExpect[64];
+ char bGet[64];
+ // Test style out of range
+ status = U_ZERO_ERROR;
+ const UnicodeString& dtFormat0 = dtpg->getDateTimeFormat(UDAT_NONE, status);
+ int32_t dtFormat0Len = dtFormat0.length();
+ if (status != U_ILLEGAL_ARGUMENT_ERROR || dtFormat0Len != 0) {
+ errln("ERROR: getDateTimeFormat with invalid style, expected U_ILLEGAL_ARGUMENT_ERROR and lero-length string, "
+ "got %s with length %d", u_errorName(status), dtFormat0Len);
+ }
+ // Test normal getting and setting
+ for (int32_t patStyle = 0; patStyle < kNumDateTimePatterns; patStyle++) {
+ status = U_ZERO_ERROR;
+ const UnicodeString& dtFormat1 = dtpg->getDateTimeFormat((UDateFormatStyle)patStyle, status);
+ if (U_FAILURE(status)) {
+ errln("FAIL: getDateTimeFormat for en before mod, style %d, get %s", patStyle, u_errorName(status));
+ } else if (dtFormat1 != enDTPatterns[patStyle]) {
+ enDTPatterns[patStyle].extract(0, enDTPatterns[patStyle].length(), bExpect, 64);
+ dtFormat1.extract(0, dtFormat1.length(), bGet, 64);
+ errln("ERROR: getDateTimeFormat for en before mod, style %d, expect \"%s\", get \"%s\"",
+ patStyle, bExpect, bGet);
+ }
+ status = U_ZERO_ERROR;
+ dtpg->setDateTimeFormat((UDateFormatStyle)patStyle, modDTPatterns[patStyle], status);
+ if (U_FAILURE(status)) {
+ errln("FAIL: setDateTimeFormat for en, style %d, get %s", patStyle, u_errorName(status));
+ } else {
+ const UnicodeString& dtFormat2 = dtpg->getDateTimeFormat((UDateFormatStyle)patStyle, status);
+ if (U_FAILURE(status)) {
+ errln("FAIL: getDateTimeFormat for en after mod, style %d, get %s", patStyle, u_errorName(status));
+ } else if (dtFormat2 != modDTPatterns[patStyle]) {
+ modDTPatterns[patStyle].extract(0, modDTPatterns[patStyle].length(), bExpect, 64);
+ dtFormat2.extract(0, dtFormat2.length(), bGet, 64);
+ errln("ERROR: getDateTimeFormat for en after mod, style %d, expect \"%s\", get \"%s\"",
+ patStyle, bExpect, bGet);
+ }
+ }
+ }
+ // Test result of setting
+ doDTPatternTest(dtpg.getAlias(), skeletons, &enModResults);
+ // Test old get/set functions
+ const UnicodeString& dtFormat3 = dtpg->getDateTimeFormat();
+ if (dtFormat3 != modDTPatterns[UDAT_MEDIUM]) {
+ modDTPatterns[UDAT_MEDIUM].extract(0, modDTPatterns[UDAT_MEDIUM].length(), bExpect, 64);
+ dtFormat3.extract(0, dtFormat3.length(), bGet, 64);
+ errln("ERROR: old getDateTimeFormat for en after mod, expect \"%s\", get \"%s\"", bExpect, bGet);
+ }
+ dtpg->setDateTimeFormat(modDTPatterns[UDAT_SHORT]); // set all dateTimePatterns to the short format
+ modDTPatterns[UDAT_SHORT].extract(0, modDTPatterns[UDAT_SHORT].length(), bExpect, 64);
+ for (int32_t patStyle = 0; patStyle < kNumDateTimePatterns; patStyle++) {
+ status = U_ZERO_ERROR;
+ const UnicodeString& dtFormat4 = dtpg->getDateTimeFormat((UDateFormatStyle)patStyle, status);
+ if (U_FAILURE(status)) {
+ errln("FAIL: getDateTimeFormat for en after second mod, style %d, get %s", patStyle, u_errorName(status));
+ } else if (dtFormat4 != modDTPatterns[UDAT_SHORT]) {
+ dtFormat4.extract(0, dtFormat4.length(), bGet, 64);
+ errln("ERROR: getDateTimeFormat for en after second mod, style %d, expect \"%s\", get \"%s\"",
+ patStyle, bExpect, bGet);
+ }
+ }
+ }
+}
+
+void IntlTestDateTimePatternGeneratorAPI::doDTPatternTest(DateTimePatternGenerator* dtpg, UnicodeString* skeletons, DTPLocaleAndResults* localeAndResultsPtr) {
+ for (int32_t patStyle = 0; patStyle < kNumDateTimePatterns; patStyle++) {
+ UErrorCode status = U_ZERO_ERROR;
+ UnicodeString getPat = dtpg->getBestPattern(skeletons[patStyle], UDATPG_MATCH_NO_OPTIONS, status);
+ if (U_FAILURE(status)) {
+ errln("FAIL: DateTimePatternGenerator::getBestPattern locale %s, style %d: %s",
+ localeAndResultsPtr->localeID, patStyle, u_errorName(status));
+ } else if (getPat != localeAndResultsPtr->expectPat[patStyle]) {
+ char bExpect[64];
+ char bGet[64];
+ localeAndResultsPtr->expectPat[patStyle].extract(0, localeAndResultsPtr->expectPat[patStyle].length(), bExpect, 64);
+ getPat.extract(0, getPat.length(), bGet, 64);
+ errln("ERROR: DateTimePatternGenerator::getBestPattern locale %s, style %d, expect \"%s\", get \"%s\"",
+ localeAndResultsPtr->localeID, patStyle, bExpect, bGet);
+ }
+ }
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.h b/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.h
index 4650fd7fcf6..ec700603eb1 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.h
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.h
@@ -13,6 +13,8 @@
#if !UCONFIG_NO_FORMATTING
+#include "unicode/dtptngen.h"
+#include "unicode/ustring.h"
#include "intltest.h"
/**
@@ -38,6 +40,14 @@ private:
void testGetDefaultHourCycle_OnEmptyInstance();
void test_jConsistencyOddLocales();
void testBestPattern();
+ void testDateTimePatterns();
+
+ enum { kNumDateTimePatterns = 4 };
+ typedef struct {
+ const char* localeID;
+ const UnicodeString expectPat[kNumDateTimePatterns];
+ } DTPLocaleAndResults;
+ void doDTPatternTest(DateTimePatternGenerator* dtpg, UnicodeString* skeletons, DTPLocaleAndResults* localeAndResultsPtr);
};
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/icusvtst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/icusvtst.cpp
index aa2d9ca05ce..cb863c5b71b 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/icusvtst.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/icusvtst.cpp
@@ -558,7 +558,7 @@ class TestMultipleKeyStringFactory : public ICUServiceFactory {
, _factoryID(factoryID + ": ")
{
for (int i = 0; i < count; ++i) {
- _ids.addElementX(new UnicodeString(ids[i]), _status);
+ _ids.adoptElement(new UnicodeString(ids[i]), _status);
}
}
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/incaltst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/incaltst.cpp
index ad75f185f63..250b61c7ac0 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/incaltst.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/incaltst.cpp
@@ -988,7 +988,7 @@ void IntlCalendarTest::TestConsistencyEthiopicAmeteAlem() {
}
void IntlCalendarTest::checkConsistency(const char* locale) {
// Check 2.5 years in quick mode and 8000 years in exhaustive mode.
- int32_t numOfDaysToTest = (quick ? 2.5 : 8000) * 365;
+ int32_t numOfDaysToTest = static_cast<int32_t>((quick ? 2.5 : 8000) * 365);
constexpr int32_t msInADay = 1000*60*60*24;
std::string msg("TestConsistency");
IcuTestErrorCode status(*this, (msg + locale).c_str());
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/intltest.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/intltest.cpp
index 7ff28961271..f2956ebcb48 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/intltest.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/intltest.cpp
@@ -2188,14 +2188,20 @@ UBool IntlTest::assertEqualsNear(const char* message,
double expected,
double actual,
double delta) {
+ bool bothNaN = std::isnan(expected) && std::isnan(actual);
+ bool bothPosInf = uprv_isPositiveInfinity(expected) && uprv_isPositiveInfinity(actual);
+ bool bothNegInf = uprv_isNegativeInfinity(expected) && uprv_isNegativeInfinity(actual);
+ if (bothPosInf || bothNegInf || bothNaN) {
+ // We don't care about delta in these cases
+ return TRUE;
+ }
if (std::isnan(delta) || std::isinf(delta)) {
errln((UnicodeString)("FAIL: ") + message + "; nonsensical delta " + delta +
- " - delta may not be NaN or Inf");
+ " - delta may not be NaN or Inf. (Got " + actual + "; expected " + expected + ".)");
return FALSE;
}
- bool bothNaN = std::isnan(expected) && std::isnan(actual);
double difference = std::abs(expected - actual);
- if (expected != actual && (difference > delta || std::isnan(difference)) && !bothNaN) {
+ if (expected != actual && (difference > delta || std::isnan(difference))) {
errln((UnicodeString)("FAIL: ") + message + "; got " + actual + "; expected " + expected +
"; acceptable delta " + delta);
return FALSE;
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.cpp
index 831642241e6..1a4ec97f37d 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.cpp
@@ -49,6 +49,7 @@ void ListFormatterTest::runIndexedTest(int32_t index, UBool exec,
TESTCASE_AUTO(TestContextual);
TESTCASE_AUTO(TestNextPosition);
TESTCASE_AUTO(TestInt32Overflow);
+ TESTCASE_AUTO(Test21871);
TESTCASE_AUTO_END;
}
@@ -276,7 +277,7 @@ void ListFormatterTest::RunTestFieldPositionIteratorWithNItemsPatternShift(
const char* testName) {
IcuTestErrorCode errorCode(*this, testName);
LocalPointer<ListFormatter> formatter(ListFormatter::createInstance(
- Locale("ur", "IN"),
+ Locale("ur", "IN"), // in CLDR 41 alpha1 the "backwards order" patterns in this and other locales were removed.
ULISTFMT_TYPE_UNITS,
ULISTFMT_WIDTH_NARROW,
errorCode));
@@ -329,21 +330,21 @@ void ListFormatterTest::TestFieldPositionIteratorWith3Items() {
}
void ListFormatterTest::TestFieldPositionIteratorWith3ItemsPatternShift() {
- // 0 1
- // 012345678901234
- // "cc bbb a"
+ // Note: In CLDR 41 alpha1 the "backwards order" patterns in ur_IN (and one or two
+ // other locales) were removed, ur_IN now just inherits list patterns from ur.
+ // So this test may no longer be interesting.
UnicodeString data[3] = {"a", "bbb", "cc"};
int32_t expected[] = {
- ULISTFMT_ELEMENT_FIELD, 7, 8,
- ULISTFMT_LITERAL_FIELD, 6, 7,
+ ULISTFMT_ELEMENT_FIELD, 0, 1,
+ ULISTFMT_LITERAL_FIELD, 1, 3,
ULISTFMT_ELEMENT_FIELD, 3, 6,
- ULISTFMT_LITERAL_FIELD, 2, 3,
- ULISTFMT_ELEMENT_FIELD, 0, 2
+ ULISTFMT_LITERAL_FIELD, 6, 12,
+ ULISTFMT_ELEMENT_FIELD, 12, 14
};
int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
RunTestFieldPositionIteratorWithNItemsPatternShift(
data, 3, expected, tupleCount,
- u"cc bbb a",
+ u"a، bbb، اور cc",
"TestFieldPositionIteratorWith3ItemsPatternShift");
}
@@ -365,19 +366,19 @@ void ListFormatterTest::TestFieldPositionIteratorWith2Items() {
}
void ListFormatterTest::TestFieldPositionIteratorWith2ItemsPatternShift() {
- // 0 1
- // 01234567890
- // "cc bbb"
+ // Note: In CLDR 41 alpha1 the "backwards order" patterns in ur_IN (and one or two
+ // other locales) were removed, ur_IN now just inherits list patterns from ur.
+ // So this test may no longer be interesting.
UnicodeString data[2] = {"bbb", "cc"};
int32_t expected[] = {
- ULISTFMT_ELEMENT_FIELD, 3, 6,
- ULISTFMT_LITERAL_FIELD, 2, 3,
- ULISTFMT_ELEMENT_FIELD, 0, 2
+ ULISTFMT_ELEMENT_FIELD, 0, 3,
+ ULISTFMT_LITERAL_FIELD, 3, 8,
+ ULISTFMT_ELEMENT_FIELD, 8, 10
};
int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
RunTestFieldPositionIteratorWithNItemsPatternShift(
data, 2, expected, tupleCount,
- u"cc bbb",
+ u"bbb اور cc",
"TestFieldPositionIteratorWith2ItemsPatternShift");
}
@@ -840,4 +841,30 @@ void ListFormatterTest::TestInt32Overflow() {
status.expectErrorAndReset(U_INPUT_TOO_LONG_ERROR);
}
+
+void ListFormatterTest::Test21871() {
+ IcuTestErrorCode status(*this, "Test21871");
+ LocalPointer<ListFormatter> fmt(ListFormatter::createInstance("en", status), status);
+ {
+ UnicodeString strings[] = {{u"A"}, {u""}};
+ FormattedList result = fmt->formatStringsToValue(strings, 2, status);
+ ConstrainedFieldPosition cfp;
+ cfp.constrainField(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD);
+ assertTrue("nextPosition 1", result.nextPosition(cfp, status));
+ assertEquals("start", cfp.getStart(), 0);
+ assertEquals("limit", cfp.getLimit(), 1);
+ assertFalse("nextPosition 2", result.nextPosition(cfp, status));
+ }
+ {
+ UnicodeString strings[] = {{u""}, {u"B"}};
+ FormattedList result = fmt->formatStringsToValue(strings, 2, status);
+ ConstrainedFieldPosition cfp;
+ cfp.constrainField(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD);
+ assertTrue("nextPosition 1", result.nextPosition(cfp, status));
+ assertEquals("start", cfp.getStart(), 5);
+ assertEquals("limit", cfp.getLimit(), 6);
+ assertFalse("nextPosition 2", result.nextPosition(cfp, status));
+ }
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.h b/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.h
index d6bf3bc0d68..0f0390010e4 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.h
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.h
@@ -56,6 +56,7 @@ class ListFormatterTest : public IntlTestWithFieldPosition {
void TestContextual();
void TestNextPosition();
void TestInt32Overflow();
+ void Test21871();
private:
void CheckFormatting(
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/lstmbetst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/lstmbetst.cpp
index 6c5d5d0ad61..0ffc0fa20e5 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/lstmbetst.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/lstmbetst.cpp
@@ -153,7 +153,7 @@ void LSTMBETest::runTestFromFile(const char* filename) {
dataerrln("%s:%d Error %s Could not allocate UVextor32", __FILE__, __LINE__, u_errorName(status));
return;
}
- engine->findBreaks(&ut, 0, value.length(), actual, status);
+ engine->findBreaks(&ut, 0, value.length(), actual, false, status);
if (U_FAILURE(status)) {
dataerrln("%s:%d Error %s findBreaks failed", __FILE__, __LINE__, u_errorName(status));
return;
@@ -288,7 +288,7 @@ void LSTMBETest::runTestWithLargeMemory( const char* model, UScriptCode script)
return;
}
- engine->findBreaks(&ut, 0, text.length(), actual, status);
+ engine->findBreaks(&ut, 0, text.length(), actual, false, status);
utext_close(&ut);
text += text;
}
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/measfmttest.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/measfmttest.cpp
index 003804db9a4..05488b7c360 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/measfmttest.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/measfmttest.cpp
@@ -2683,7 +2683,7 @@ void MeasureFormatTest::TestCompatible69() {
assertSuccess("", status);
}
-void MeasureFormatTest::TestCompatible70() {
+void MeasureFormatTest::TestCompatible70() { // TestCompatible71 would be identical
UErrorCode status = U_ZERO_ERROR;
LocalPointer<MeasureUnit> measureUnit;
MeasureUnit measureUnitValue;
@@ -3064,6 +3064,9 @@ void MeasureFormatTest::TestCompatible70() {
assertSuccess("", status);
}
+// TestCompatible71 would be identical to TestCompatible70,
+// no need to add it
+
void MeasureFormatTest::TestBasic() {
UErrorCode status = U_ZERO_ERROR;
MeasureUnit *ptr1 = MeasureUnit::createArcMinute(status);
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest.h b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest.h
index d6d71543fb6..c0f2e6fd58a 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest.h
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest.h
@@ -66,6 +66,7 @@ class NumberFormatterApiTest : public IntlTestWithFieldPosition {
void unitUsageSkeletons();
void unitCurrency();
void unitInflections();
+ void unitNounClass();
void unitGender();
void unitNotConvertible();
void unitPercent();
@@ -75,6 +76,7 @@ class NumberFormatterApiTest : public IntlTestWithFieldPosition {
void roundingFractionFigures();
void roundingOther();
void roundingIncrementRegressionTest();
+ void roundingPriorityCoverageTest();
void grouping();
void padding();
void integerWidth();
@@ -99,7 +101,8 @@ class NumberFormatterApiTest : public IntlTestWithFieldPosition {
void toObject();
void toDecimalNumber();
void microPropsInternals();
-
+ void formatUnitsAliases();
+
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override;
private:
@@ -206,6 +209,7 @@ class DecimalQuantityTest : public IntlTest {
void testNickelRounding();
void testScientificAndCompactSuppressedExponent();
void testSuppressedExponentUnchangedByInitialScaling();
+ void testDecimalQuantityParseFormatRoundTrip();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override;
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_api.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_api.cpp
index cf8fecc0a28..b477a16e93e 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_api.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_api.cpp
@@ -87,6 +87,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha
TESTCASE_AUTO(unitUsageSkeletons);
TESTCASE_AUTO(unitCurrency);
TESTCASE_AUTO(unitInflections);
+ TESTCASE_AUTO(unitNounClass);
TESTCASE_AUTO(unitGender);
TESTCASE_AUTO(unitNotConvertible);
TESTCASE_AUTO(unitPercent);
@@ -99,6 +100,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha
TESTCASE_AUTO(roundingFractionFigures);
TESTCASE_AUTO(roundingOther);
TESTCASE_AUTO(roundingIncrementRegressionTest);
+ TESTCASE_AUTO(roundingPriorityCoverageTest);
TESTCASE_AUTO(grouping);
TESTCASE_AUTO(padding);
TESTCASE_AUTO(integerWidth);
@@ -127,6 +129,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha
TESTCASE_AUTO(toObject);
TESTCASE_AUTO(toDecimalNumber);
TESTCASE_AUTO(microPropsInternals);
+ TESTCASE_AUTO(formatUnitsAliases);
TESTCASE_AUTO_END;
}
@@ -1747,6 +1750,46 @@ void NumberFormatterApiTest::unitUsage() {
30500,
u"350 m");
+ assertFormatSingle(u"Fuel consumption: inverted units", //
+ u"unit/liter-per-100-kilometer usage/vehicle-fuel", //
+ u"unit/liter-per-100-kilometer usage/vehicle-fuel", //
+ NumberFormatter::with() //
+ .unit(MeasureUnit::forIdentifier("liter-per-100-kilometer", status)) //
+ .usage("vehicle-fuel"), //
+ Locale("en-US"), //
+ 6.6, //
+ "36 mpg");
+
+ assertFormatSingle(u"Fuel consumption: inverted units, divide-by-zero, en-US", //
+ u"unit/liter-per-100-kilometer usage/vehicle-fuel", //
+ u"unit/liter-per-100-kilometer usage/vehicle-fuel", //
+ NumberFormatter::with() //
+ .unit(MeasureUnit::forIdentifier("liter-per-100-kilometer", status)) //
+ .usage("vehicle-fuel"), //
+ Locale("en-US"), //
+ 0, //
+ u"∞ mpg");
+
+ assertFormatSingle(u"Fuel consumption: inverted units, divide-by-zero, en-ZA", //
+ u"unit/mile-per-gallon usage/vehicle-fuel", //
+ u"unit/mile-per-gallon usage/vehicle-fuel", //
+ NumberFormatter::with() //
+ .unit(MeasureUnit::forIdentifier("mile-per-gallon", status)) //
+ .usage("vehicle-fuel"), //
+ Locale("en-ZA"), //
+ 0, //
+ u"∞ l/100 km");
+
+ assertFormatSingle(u"Fuel consumption: inverted units, divide-by-inf", //
+ u"unit/mile-per-gallon usage/vehicle-fuel", //
+ u"unit/mile-per-gallon usage/vehicle-fuel", //
+ NumberFormatter::with() //
+ .unit(MeasureUnit::forIdentifier("mile-per-gallon", status)) //
+ .usage("vehicle-fuel"), //
+ Locale("de-CH"), //
+ uprv_getInfinity(), //
+ u"0 L/100 km");
+
// Test calling `.usage("")` should unset the existing usage.
// First: without usage
assertFormatSingle(u"Rounding Mode propagates: rounding up",
@@ -1853,10 +1896,6 @@ void NumberFormatterApiTest::unitUsage() {
Locale("en-US"), //
1, //
"0.019 psi");
-
- // TODO(icu-units#38): improve unit testing coverage. E.g. add vehicle-fuel
- // triggering inversion conversion code. Test with 0 too, to see
- // divide-by-zero behaviour.
}
void NumberFormatterApiTest::unitUsageErrorCodes() {
@@ -2384,7 +2423,7 @@ void NumberFormatterApiTest::unitInflections() {
{"centimeter", "de", nullptr, 1, u"1 Zentimeter"},
{"centimeter", "de", "genitive", 1, u"1 Zentimeters"},
{"centimeter", "de", "dative", 10, u"10 Zentimetern"},
- // TODO(CLDR-14502): check that these inflections are correct, and
+ // TODO(CLDR-14582): check that these inflections are correct, and
// whether CLDR needs any rules for them (presumably CLDR spec
// should mention it, if it's a consistent rule):
{"meter-and-centimeter", "de", nullptr, 1.01, u"1 Meter, 1 Zentimeter"},
@@ -2401,6 +2440,307 @@ void NumberFormatterApiTest::unitInflections() {
// TODO: look at "↑↑↑" cases: check that inheritance is done right.
}
+using icu::NounClass;
+void NumberFormatterApiTest::unitNounClass() {
+ IcuTestErrorCode status(*this, "unitNounClass");
+ const struct TestCase {
+ const char *locale;
+ const char *unitIdentifier;
+ const NounClass expectedNounClass;
+ } cases[] = {
+ {"de", "inch", NounClass::MASCULINE},
+ {"de", "yard", NounClass::NEUTER},
+ {"de", "meter", NounClass::MASCULINE},
+ {"de", "liter", NounClass::MASCULINE},
+ {"de", "second", NounClass::FEMININE},
+ {"de", "minute", NounClass::FEMININE},
+ {"de", "hour", NounClass::FEMININE},
+ {"de", "day", NounClass::MASCULINE},
+ {"de", "year", NounClass::NEUTER},
+ {"de", "gram", NounClass::NEUTER},
+ {"de", "watt", NounClass::NEUTER},
+ {"de", "bit", NounClass::NEUTER},
+ {"de", "byte", NounClass::NEUTER},
+
+ {"fr", "inch", NounClass::MASCULINE},
+ {"fr", "yard", NounClass::MASCULINE},
+ {"fr", "meter", NounClass::MASCULINE},
+ {"fr", "liter", NounClass::MASCULINE},
+ {"fr", "second", NounClass::FEMININE},
+ {"fr", "minute", NounClass::FEMININE},
+ {"fr", "hour", NounClass::FEMININE},
+ {"fr", "day", NounClass::MASCULINE},
+ {"fr", "year", NounClass::MASCULINE},
+ {"fr", "gram", NounClass::MASCULINE},
+
+ // grammaticalFeatures deriveCompound "per" rule takes the gender of the
+ // numerator unit:
+ {"de", "meter-per-hour", NounClass::MASCULINE},
+ {"fr", "meter-per-hour", NounClass::MASCULINE},
+ {"af", "meter-per-hour", NounClass::OTHER}, // ungendered language
+
+ // French "times" takes gender from first value, German takes the
+ // second. Prefix and power does not have impact on gender for these
+ // languages:
+ {"de", "square-decimeter-square-second", NounClass::FEMININE},
+ {"fr", "square-decimeter-square-second", NounClass::MASCULINE},
+
+ // TODO(icu-units#149): percent and permille bypasses LongNameHandler
+ // when unitWidth is not FULL_NAME:
+ // // Gender of per-second might be that of percent? TODO(icu-units#28)
+ // {"de", "percent", NounClass::NEUTER},
+ // {"fr", "percent", NounClass::MASCULINE},
+
+ // Built-in units whose simple units lack gender in the CLDR data file
+ {"de", "kilopascal", NounClass::NEUTER},
+ {"fr", "kilopascal", NounClass::MASCULINE},
+ // {"de", "pascal", NounClass::OTHER},
+ // {"fr", "pascal", NounClass::OTHER},
+
+ // Built-in units that lack gender in the CLDR data file
+ // {"de", "revolution", NounClass::OTHER},
+ // {"de", "radian", NounClass::OTHER},
+ // {"de", "arc-minute", NounClass::OTHER},
+ // {"de", "arc-second", NounClass::OTHER},
+ {"de", "square-yard", NounClass::NEUTER}, // POWER
+ {"de", "square-inch", NounClass::MASCULINE}, // POWER
+ // {"de", "dunam", NounClass::OTHER},
+ // {"de", "karat", NounClass::OTHER},
+ // {"de", "milligram-ofglucose-per-deciliter", NounClass::OTHER}, // COMPOUND, ofglucose
+ // {"de", "millimole-per-liter", NounClass::OTHER}, // COMPOUND, mole
+ // {"de", "permillion", NounClass::OTHER},
+ // {"de", "permille", NounClass::OTHER},
+ // {"de", "permyriad", NounClass::OTHER},
+ // {"de", "mole", NounClass::OTHER},
+ {"de", "liter-per-kilometer", NounClass::MASCULINE}, // COMPOUND
+ {"de", "petabyte", NounClass::NEUTER}, // PREFIX
+ {"de", "terabit", NounClass::NEUTER}, // PREFIX
+ // {"de", "century", NounClass::OTHER},
+ // {"de", "decade", NounClass::OTHER},
+ {"de", "millisecond", NounClass::FEMININE}, // PREFIX
+ {"de", "microsecond", NounClass::FEMININE}, // PREFIX
+ {"de", "nanosecond", NounClass::FEMININE}, // PREFIX
+ // {"de", "ampere", NounClass::OTHER},
+ // {"de", "milliampere", NounClass::OTHER}, // PREFIX, ampere
+ // {"de", "ohm", NounClass::OTHER},
+ // {"de", "calorie", NounClass::OTHER},
+ // {"de", "kilojoule", NounClass::OTHER}, // PREFIX, joule
+ // {"de", "joule", NounClass::OTHER},
+ {"de", "kilowatt-hour", NounClass::FEMININE}, // COMPOUND
+ // {"de", "electronvolt", NounClass::OTHER},
+ // {"de", "british-thermal-unit", NounClass::OTHER},
+ // {"de", "therm-us", NounClass::OTHER},
+ // {"de", "pound-force", NounClass::OTHER},
+ // {"de", "newton", NounClass::OTHER},
+ // {"de", "gigahertz", NounClass::OTHER}, // PREFIX, hertz
+ // {"de", "megahertz", NounClass::OTHER}, // PREFIX, hertz
+ // {"de", "kilohertz", NounClass::OTHER}, // PREFIX, hertz
+ // {"de", "hertz", NounClass::OTHER},
+ // {"de", "em", NounClass::OTHER},
+ // {"de", "pixel", NounClass::OTHER},
+ // {"de", "megapixel", NounClass::OTHER},
+ // {"de", "pixel-per-centimeter", NounClass::OTHER}, // COMPOUND, pixel
+ // {"de", "pixel-per-inch", NounClass::OTHER}, // COMPOUND, pixel
+ // {"de", "dot-per-centimeter", NounClass::OTHER}, // COMPOUND, dot
+ // {"de", "dot-per-inch", NounClass::OTHER}, // COMPOUND, dot
+ // {"de", "dot", NounClass::OTHER},
+ // {"de", "earth-radius", NounClass::OTHER},
+ {"de", "decimeter", NounClass::MASCULINE}, // PREFIX
+ {"de", "micrometer", NounClass::MASCULINE}, // PREFIX
+ {"de", "nanometer", NounClass::MASCULINE}, // PREFIX
+ // {"de", "light-year", NounClass::OTHER},
+ // {"de", "astronomical-unit", NounClass::OTHER},
+ // {"de", "furlong", NounClass::OTHER},
+ // {"de", "fathom", NounClass::OTHER},
+ // {"de", "nautical-mile", NounClass::OTHER},
+ // {"de", "mile-scandinavian", NounClass::OTHER},
+ // {"de", "point", NounClass::OTHER},
+ // {"de", "lux", NounClass::OTHER},
+ // {"de", "candela", NounClass::OTHER},
+ // {"de", "lumen", NounClass::OTHER},
+ // {"de", "metric-ton", NounClass::OTHER},
+ // {"de", "microgram", NounClass::NEUTER}, // PREFIX
+ // {"de", "ton", NounClass::OTHER},
+ // {"de", "stone", NounClass::OTHER},
+ // {"de", "ounce-troy", NounClass::OTHER},
+ // {"de", "carat", NounClass::OTHER},
+ {"de", "gigawatt", NounClass::NEUTER}, // PREFIX
+ {"de", "milliwatt", NounClass::NEUTER}, // PREFIX
+ // {"de", "horsepower", NounClass::OTHER},
+ // {"de", "millimeter-ofhg", NounClass::OTHER},
+ // {"de", "pound-force-per-square-inch", NounClass::OTHER}, // COMPOUND, pound-force
+ // {"de", "inch-ofhg", NounClass::OTHER},
+ // {"de", "bar", NounClass::OTHER},
+ // {"de", "millibar", NounClass::OTHER}, // PREFIX, bar
+ // {"de", "atmosphere", NounClass::OTHER},
+ // {"de", "pascal", NounClass::OTHER}, // PREFIX, kilopascal? neuter?
+ // {"de", "hectopascal", NounClass::OTHER}, // PREFIX, pascal, neuter?
+ // {"de", "megapascal", NounClass::OTHER}, // PREFIX, pascal, neuter?
+ // {"de", "knot", NounClass::OTHER},
+ {"de", "pound-force-foot", NounClass::MASCULINE}, // COMPOUND
+ {"de", "newton-meter", NounClass::MASCULINE}, // COMPOUND
+ {"de", "cubic-kilometer", NounClass::MASCULINE}, // POWER
+ {"de", "cubic-yard", NounClass::NEUTER}, // POWER
+ {"de", "cubic-inch", NounClass::MASCULINE}, // POWER
+ {"de", "megaliter", NounClass::MASCULINE}, // PREFIX
+ {"de", "hectoliter", NounClass::MASCULINE}, // PREFIX
+ // {"de", "pint-metric", NounClass::OTHER},
+ // {"de", "cup-metric", NounClass::OTHER},
+ {"de", "acre-foot", NounClass::MASCULINE}, // COMPOUND
+ // {"de", "bushel", NounClass::OTHER},
+ // {"de", "barrel", NounClass::OTHER},
+ // Units missing gender in German also misses gender in French:
+ // {"fr", "revolution", NounClass::OTHER},
+ // {"fr", "radian", NounClass::OTHER},
+ // {"fr", "arc-minute", NounClass::OTHER},
+ // {"fr", "arc-second", NounClass::OTHER},
+ {"fr", "square-yard", NounClass::MASCULINE}, // POWER
+ {"fr", "square-inch", NounClass::MASCULINE}, // POWER
+ // {"fr", "dunam", NounClass::OTHER},
+ // {"fr", "karat", NounClass::OTHER},
+ {"fr", "milligram-ofglucose-per-deciliter", NounClass::MASCULINE}, // COMPOUND
+ // {"fr", "millimole-per-liter", NounClass::OTHER}, // COMPOUND, mole
+ // {"fr", "permillion", NounClass::OTHER},
+ // {"fr", "permille", NounClass::OTHER},
+ // {"fr", "permyriad", NounClass::OTHER},
+ // {"fr", "mole", NounClass::OTHER},
+ {"fr", "liter-per-kilometer", NounClass::MASCULINE}, // COMPOUND
+ // {"fr", "petabyte", NounClass::OTHER}, // PREFIX
+ // {"fr", "terabit", NounClass::OTHER}, // PREFIX
+ // {"fr", "century", NounClass::OTHER},
+ // {"fr", "decade", NounClass::OTHER},
+ {"fr", "millisecond", NounClass::FEMININE}, // PREFIX
+ {"fr", "microsecond", NounClass::FEMININE}, // PREFIX
+ {"fr", "nanosecond", NounClass::FEMININE}, // PREFIX
+ // {"fr", "ampere", NounClass::OTHER},
+ // {"fr", "milliampere", NounClass::OTHER}, // PREFIX, ampere
+ // {"fr", "ohm", NounClass::OTHER},
+ // {"fr", "calorie", NounClass::OTHER},
+ // {"fr", "kilojoule", NounClass::OTHER}, // PREFIX, joule
+ // {"fr", "joule", NounClass::OTHER},
+ // {"fr", "kilowatt-hour", NounClass::OTHER}, // COMPOUND
+ // {"fr", "electronvolt", NounClass::OTHER},
+ // {"fr", "british-thermal-unit", NounClass::OTHER},
+ // {"fr", "therm-us", NounClass::OTHER},
+ // {"fr", "pound-force", NounClass::OTHER},
+ // {"fr", "newton", NounClass::OTHER},
+ // {"fr", "gigahertz", NounClass::OTHER}, // PREFIX, hertz
+ // {"fr", "megahertz", NounClass::OTHER}, // PREFIX, hertz
+ // {"fr", "kilohertz", NounClass::OTHER}, // PREFIX, hertz
+ // {"fr", "hertz", NounClass::OTHER},
+ // {"fr", "em", NounClass::OTHER},
+ // {"fr", "pixel", NounClass::OTHER},
+ // {"fr", "megapixel", NounClass::OTHER},
+ // {"fr", "pixel-per-centimeter", NounClass::OTHER}, // COMPOUND, pixel
+ // {"fr", "pixel-per-inch", NounClass::OTHER}, // COMPOUND, pixel
+ // {"fr", "dot-per-centimeter", NounClass::OTHER}, // COMPOUND, dot
+ // {"fr", "dot-per-inch", NounClass::OTHER}, // COMPOUND, dot
+ // {"fr", "dot", NounClass::OTHER},
+ // {"fr", "earth-radius", NounClass::OTHER},
+ {"fr", "decimeter", NounClass::MASCULINE}, // PREFIX
+ {"fr", "micrometer", NounClass::MASCULINE}, // PREFIX
+ {"fr", "nanometer", NounClass::MASCULINE}, // PREFIX
+ // {"fr", "light-year", NounClass::OTHER},
+ // {"fr", "astronomical-unit", NounClass::OTHER},
+ // {"fr", "furlong", NounClass::OTHER},
+ // {"fr", "fathom", NounClass::OTHER},
+ // {"fr", "nautical-mile", NounClass::OTHER},
+ // {"fr", "mile-scandinavian", NounClass::OTHER},
+ // {"fr", "point", NounClass::OTHER},
+ // {"fr", "lux", NounClass::OTHER},
+ // {"fr", "candela", NounClass::OTHER},
+ // {"fr", "lumen", NounClass::OTHER},
+ // {"fr", "metric-ton", NounClass::OTHER},
+ // {"fr", "microgram", NounClass::MASCULINE}, // PREFIX
+ // {"fr", "ton", NounClass::OTHER},
+ // {"fr", "stone", NounClass::OTHER},
+ // {"fr", "ounce-troy", NounClass::OTHER},
+ // {"fr", "carat", NounClass::OTHER},
+ // {"fr", "gigawatt", NounClass::OTHER}, // PREFIX
+ // {"fr", "milliwatt", NounClass::OTHER},
+ // {"fr", "horsepower", NounClass::OTHER},
+ {"fr", "millimeter-ofhg", NounClass::MASCULINE},
+ // {"fr", "pound-force-per-square-inch", NounClass::OTHER}, // COMPOUND, pound-force
+ {"fr", "inch-ofhg", NounClass::MASCULINE},
+ // {"fr", "bar", NounClass::OTHER},
+ // {"fr", "millibar", NounClass::OTHER}, // PREFIX, bar
+ // {"fr", "atmosphere", NounClass::OTHER},
+ // {"fr", "pascal", NounClass::OTHER}, // PREFIX, kilopascal?
+ // {"fr", "hectopascal", NounClass::OTHER}, // PREFIX, pascal
+ // {"fr", "megapascal", NounClass::OTHER}, // PREFIX, pascal
+ // {"fr", "knot", NounClass::OTHER},
+ // {"fr", "pound-force-foot", NounClass::OTHER},
+ // {"fr", "newton-meter", NounClass::OTHER},
+ {"fr", "cubic-kilometer", NounClass::MASCULINE}, // POWER
+ {"fr", "cubic-yard", NounClass::MASCULINE}, // POWER
+ {"fr", "cubic-inch", NounClass::MASCULINE}, // POWER
+ {"fr", "megaliter", NounClass::MASCULINE}, // PREFIX
+ {"fr", "hectoliter", NounClass::MASCULINE}, // PREFIX
+ // {"fr", "pint-metric", NounClass::OTHER},
+ // {"fr", "cup-metric", NounClass::OTHER},
+ {"fr", "acre-foot", NounClass::FEMININE}, // COMPOUND
+ // {"fr", "bushel", NounClass::OTHER},
+ // {"fr", "barrel", NounClass::OTHER},
+ // Some more French units missing gender:
+ // {"fr", "degree", NounClass::OTHER},
+ {"fr", "square-meter", NounClass::MASCULINE}, // POWER
+ // {"fr", "terabyte", NounClass::OTHER}, // PREFIX, byte
+ // {"fr", "gigabyte", NounClass::OTHER}, // PREFIX, byte
+ // {"fr", "gigabit", NounClass::OTHER}, // PREFIX, bit
+ // {"fr", "megabyte", NounClass::OTHER}, // PREFIX, byte
+ // {"fr", "megabit", NounClass::OTHER}, // PREFIX, bit
+ // {"fr", "kilobyte", NounClass::OTHER}, // PREFIX, byte
+ // {"fr", "kilobit", NounClass::OTHER}, // PREFIX, bit
+ // {"fr", "byte", NounClass::OTHER},
+ // {"fr", "bit", NounClass::OTHER},
+ // {"fr", "volt", NounClass::OTHER},
+ // {"fr", "watt", NounClass::OTHER},
+ {"fr", "cubic-meter", NounClass::MASCULINE}, // POWER
+
+ // gender-lacking builtins within compound units
+ {"de", "newton-meter-per-second", NounClass::MASCULINE},
+
+ // TODO(ICU-21494): determine whether list genders behave as follows,
+ // and implement proper getListGender support (covering more than just
+ // two genders):
+ // // gender rule for lists of people: de "neutral", fr "maleTaints"
+ // {"de", "day-and-hour-and-minute", NounClass::NEUTER},
+ // {"de", "hour-and-minute", NounClass::FEMININE},
+ // {"fr", "day-and-hour-and-minute", NounClass::MASCULINE},
+ // {"fr", "hour-and-minute", NounClass::FEMININE},
+ };
+
+ LocalizedNumberFormatter formatter;
+ FormattedNumber fn;
+ for (const TestCase &t : cases) {
+ formatter = NumberFormatter::with()
+ .unit(MeasureUnit::forIdentifier(t.unitIdentifier, status))
+ .locale(Locale(t.locale));
+ fn = formatter.formatDouble(1.1, status);
+ assertEquals(UnicodeString("Testing NounClass with default width, unit: ") + t.unitIdentifier +
+ ", locale: " + t.locale,
+ t.expectedNounClass, fn.getNounClass(status));
+ status.assertSuccess();
+
+ formatter = NumberFormatter::with()
+ .unit(MeasureUnit::forIdentifier(t.unitIdentifier, status))
+ .unitWidth(UNUM_UNIT_WIDTH_FULL_NAME)
+ .locale(Locale(t.locale));
+ fn = formatter.formatDouble(1.1, status);
+ assertEquals(UnicodeString("Testing NounClass with UNUM_UNIT_WIDTH_FULL_NAME, unit: ") +
+ t.unitIdentifier + ", locale: " + t.locale,
+ t.expectedNounClass, fn.getNounClass(status));
+ status.assertSuccess();
+ }
+
+ // Make sure getNounClass does not return garbage for languages without noun classes.
+ formatter = NumberFormatter::with().locale(Locale::getEnglish());
+ fn = formatter.formatDouble(1.1, status);
+ status.assertSuccess();
+ assertEquals("getNounClasses for a not supported language", NounClass::OTHER,
+ fn.getNounClass(status));
+}
+
void NumberFormatterApiTest::unitGender() {
IcuTestErrorCode status(*this, "unitGender");
@@ -2975,6 +3315,28 @@ void NumberFormatterApiTest::roundingFraction() {
Locale::getEnglish(),
1,
"1");
+
+ assertFormatSingle(
+ u"Hide If Whole with Rounding Mode A (ICU-21881)",
+ u".00/w rounding-mode-floor",
+ u".00/w rounding-mode-floor",
+ NumberFormatter::with().precision(Precision::fixedFraction(2)
+ .trailingZeroDisplay(UNUM_TRAILING_ZERO_HIDE_IF_WHOLE))
+ .roundingMode(UNUM_ROUND_FLOOR),
+ Locale::getEnglish(),
+ 3.009,
+ "3");
+
+ assertFormatSingle(
+ u"Hide If Whole with Rounding Mode B (ICU-21881)",
+ u".00/w rounding-mode-half-up",
+ u".00/w rounding-mode-half-up",
+ NumberFormatter::with().precision(Precision::fixedFraction(2)
+ .trailingZeroDisplay(UNUM_TRAILING_ZERO_HIDE_IF_WHOLE))
+ .roundingMode(UNUM_ROUND_HALFUP),
+ Locale::getEnglish(),
+ 3.001,
+ "3");
}
void NumberFormatterApiTest::roundingFigures() {
@@ -2997,6 +3359,15 @@ void NumberFormatterApiTest::roundingFigures() {
u"-98.8");
assertFormatSingle(
+ u"Fixed Significant at rounding boundary",
+ u"@@@",
+ u"@@@",
+ NumberFormatter::with().precision(Precision::fixedSignificantDigits(3)),
+ Locale::getEnglish(),
+ 9.999,
+ u"10.0");
+
+ assertFormatSingle(
u"Fixed Significant Zero",
u"@@@",
u"@@@",
@@ -3156,7 +3527,7 @@ void NumberFormatterApiTest::roundingFractionFigures() {
assertFormatDescending(
u"FracSig withSignificantDigits STRICT",
u"precision-integer/@#s",
- u"./@#",
+ u"./@#s",
NumberFormatter::with().precision(Precision::maxFraction(0)
.withSignificantDigits(1, 2, UNUM_ROUNDING_PRIORITY_STRICT)),
Locale::getEnglish(),
@@ -3180,7 +3551,7 @@ void NumberFormatterApiTest::roundingFractionFigures() {
1,
u"1.00");
- // Trailing zeros are always retained:
+ // Trailing zeros follow the strategy that was chosen:
assertFormatSingle(
u"FracSig withSignificantDigits Trailing Zeros STRICT",
u".0/@@@s",
@@ -3189,7 +3560,7 @@ void NumberFormatterApiTest::roundingFractionFigures() {
.withSignificantDigits(3, 3, UNUM_ROUNDING_PRIORITY_STRICT)),
Locale::getEnglish(),
1,
- u"1.00");
+ u"1.0");
assertFormatSingle(
u"FracSig withSignificantDigits at rounding boundary",
@@ -3199,7 +3570,7 @@ void NumberFormatterApiTest::roundingFractionFigures() {
.withSignificantDigits(3, 3, UNUM_ROUNDING_PRIORITY_STRICT)),
Locale::getEnglish(),
9.99,
- u"10.0");
+ u"10");
assertFormatSingle(
u"FracSig with Trailing Zero Display",
@@ -3397,6 +3768,42 @@ void NumberFormatterApiTest::roundingOther() {
u"0.0",
u"0.0");
+ assertFormatSingle(
+ u"Large integer increment",
+ u"precision-increment/24000000000000000000000",
+ u"precision-increment/24000000000000000000000",
+ NumberFormatter::with().precision(Precision::incrementExact(24, 21)),
+ Locale::getEnglish(),
+ 3.1e22,
+ u"24,000,000,000,000,000,000,000");
+
+ assertFormatSingle(
+ u"Quarter rounding",
+ u"precision-increment/250",
+ u"precision-increment/250",
+ NumberFormatter::with().precision(Precision::incrementExact(250, 0)),
+ Locale::getEnglish(),
+ 700,
+ u"750");
+
+ assertFormatSingle(
+ u"ECMA-402 limit",
+ u"precision-increment/.00000000000000000020",
+ u"precision-increment/.00000000000000000020",
+ NumberFormatter::with().precision(Precision::incrementExact(20, -20)),
+ Locale::getEnglish(),
+ 333e-20,
+ u"0.00000000000000000340");
+
+ assertFormatSingle(
+ u"ECMA-402 limit with increment = 1",
+ u"precision-increment/.00000000000000000001",
+ u"precision-increment/.00000000000000000001",
+ NumberFormatter::with().precision(Precision::incrementExact(1, -20)),
+ Locale::getEnglish(),
+ 4321e-21,
+ u"0.00000000000000000432");
+
assertFormatDescending(
u"Currency Standard",
u"currency/CZK precision-currency-standard",
@@ -3583,6 +3990,67 @@ void NumberFormatterApiTest::roundingIncrementRegressionTest() {
assertEquals("ICU-21668", u"5,000", increment);
}
+void NumberFormatterApiTest::roundingPriorityCoverageTest() {
+ IcuTestErrorCode status(*this, "roundingPriorityCoverageTest");
+ struct TestCase {
+ double input;
+ const char16_t* expectedRelaxed0113;
+ const char16_t* expectedStrict0113;
+ const char16_t* expectedRelaxed1133;
+ const char16_t* expectedStrict1133;
+ } cases[] = {
+ { 0.9999, u"1", u"1", u"1.00", u"1.0" },
+ { 9.9999, u"10", u"10", u"10.0", u"10.0" },
+ { 99.999, u"100", u"100", u"100.0", u"100" },
+ { 999.99, u"1000", u"1000", u"1000.0", u"1000" },
+
+ { 0, u"0", u"0", u"0.00", u"0.0" },
+
+ { 9.876, u"9.88", u"9.9", u"9.88", u"9.9" },
+ { 9.001, u"9", u"9", u"9.00", u"9.0" },
+ };
+ for (const auto& cas : cases) {
+ auto precisionRelaxed0113 = Precision::minMaxFraction(0, 1)
+ .withSignificantDigits(1, 3, UNUM_ROUNDING_PRIORITY_RELAXED);
+ auto precisionStrict0113 = Precision::minMaxFraction(0, 1)
+ .withSignificantDigits(1, 3, UNUM_ROUNDING_PRIORITY_STRICT);
+ auto precisionRelaxed1133 = Precision::minMaxFraction(1, 1)
+ .withSignificantDigits(3, 3, UNUM_ROUNDING_PRIORITY_RELAXED);
+ auto precisionStrict1133 = Precision::minMaxFraction(1, 1)
+ .withSignificantDigits(3, 3, UNUM_ROUNDING_PRIORITY_STRICT);
+
+ auto messageBase = DoubleToUnicodeString(cas.input);
+
+ auto check = [&](
+ const char16_t* name,
+ const UnicodeString& expected,
+ const Precision& precision
+ ) {
+ assertEquals(
+ messageBase + name,
+ expected,
+ NumberFormatter::withLocale(Locale::getEnglish())
+ .precision(precision)
+ .grouping(UNUM_GROUPING_OFF)
+ .formatDouble(cas.input, status)
+ .toString(status)
+ );
+ };
+
+ check(u" Relaxed 0113", cas.expectedRelaxed0113, precisionRelaxed0113);
+ if (status.errIfFailureAndReset()) continue;
+
+ check(u" Strict 0113", cas.expectedStrict0113, precisionStrict0113);
+ if (status.errIfFailureAndReset()) continue;
+
+ check(u" Relaxed 1133", cas.expectedRelaxed1133, precisionRelaxed1133);
+ if (status.errIfFailureAndReset()) continue;
+
+ check(u" Strict 1133", cas.expectedStrict1133, precisionStrict1133);
+ if (status.errIfFailureAndReset()) continue;
+ }
+}
+
void NumberFormatterApiTest::grouping() {
assertFormatDescendingBig(
u"Western Grouping",
@@ -5707,6 +6175,37 @@ void NumberFormatterApiTest::microPropsInternals() {
assertEquals("Copy Assigned capacity", 4, copyAssigned.mixedMeasures.getCapacity());
}
+void NumberFormatterApiTest::formatUnitsAliases() {
+ IcuTestErrorCode status(*this, "formatUnitsAliases");
+
+ struct TestCase {
+ const MeasureUnit measureUnit;
+ const UnicodeString expectedFormat;
+ } testCases[]{
+ // Aliases
+ {MeasureUnit::getMilligramPerDeciliter(), u"2 milligrams per deciliter"},
+ {MeasureUnit::getLiterPer100Kilometers(), u"2 liters per 100 kilometers"},
+ {MeasureUnit::getPartPerMillion(), u"2 parts per million"},
+ {MeasureUnit::getMillimeterOfMercury(), u"2 millimeters of mercury"},
+
+ // Replacements
+ {MeasureUnit::getMilligramOfglucosePerDeciliter(), u"2 milligrams per deciliter"},
+ {MeasureUnit::forIdentifier("millimeter-ofhg", status), u"2 millimeters of mercury"},
+ {MeasureUnit::forIdentifier("liter-per-100-kilometer", status), u"2 liters per 100 kilometers"},
+ {MeasureUnit::forIdentifier("permillion", status), u"2 parts per million"},
+ };
+
+ for (const auto &testCase : testCases) {
+ UnicodeString actualFormat = NumberFormatter::withLocale(icu::Locale::getEnglish())
+ .unit(testCase.measureUnit)
+ .unitWidth(UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME)
+ .formatDouble(2.0, status)
+ .toString(status);
+
+ assertEquals("test unit aliases", testCase.expectedFormat, actualFormat);
+ }
+}
+
/* For skeleton comparisons: this checks the toSkeleton output for `f` and for
* `conciseSkeleton` against the normalized version of `uskeleton` - this does
* not round-trip uskeleton itself.
@@ -5882,7 +6381,7 @@ NumberFormatterApiTest::assertFormatSingle(
// Only compare normalized skeletons: the tests need not provide the normalized forms.
// Use the normalized form to construct the testing formatter to ensure no loss of info.
UnicodeString normalized = NumberFormatter::forSkeleton(skeleton, status).toSkeleton(status);
- assertEquals(message + ": Skeleton:", normalized, f.toSkeleton(status));
+ assertEquals(message + ": Skeleton", normalized, f.toSkeleton(status));
LocalizedNumberFormatter l3 = NumberFormatter::forSkeleton(normalized, status).locale(locale);
UnicodeString actual3 = l3.formatDouble(input, status).toString(status);
assertEquals(message + ": Skeleton Path: '" + normalized + "': " + input, expected, actual3);
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_decimalquantity.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_decimalquantity.cpp
index 7403dda7e75..87cd7707b55 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_decimalquantity.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_decimalquantity.cpp
@@ -33,6 +33,7 @@ void DecimalQuantityTest::runIndexedTest(int32_t index, UBool exec, const char *
TESTCASE_AUTO(testNickelRounding);
TESTCASE_AUTO(testScientificAndCompactSuppressedExponent);
TESTCASE_AUTO(testSuppressedExponentUnchangedByInitialScaling);
+ TESTCASE_AUTO(testDecimalQuantityParseFormatRoundTrip);
TESTCASE_AUTO_END;
}
@@ -101,8 +102,11 @@ void DecimalQuantityTest::testDecimalQuantityBehaviorStandalone() {
assertToStringAndHealth(fq, u"<DecimalQuantity 2:-3 long 987654321E-6>");
fq.roundToInfinity();
assertToStringAndHealth(fq, u"<DecimalQuantity 2:-3 long 987654321E-6>");
- fq.roundToIncrement(0.005, RoundingMode::UNUM_ROUND_HALFEVEN, status);
+ fq.roundToIncrement(4, -3, RoundingMode::UNUM_ROUND_HALFEVEN, status);
assertSuccess("Rounding to increment", status);
+ assertToStringAndHealth(fq, u"<DecimalQuantity 2:-3 long 987656E-3>");
+ fq.roundToNickel(-3, RoundingMode::UNUM_ROUND_HALFEVEN, status);
+ assertSuccess("Rounding to nickel", status);
assertToStringAndHealth(fq, u"<DecimalQuantity 2:-3 long 987655E-3>");
fq.roundToMagnitude(-2, RoundingMode::UNUM_ROUND_HALFEVEN, status);
assertSuccess("Rounding to magnitude", status);
@@ -317,7 +321,7 @@ void DecimalQuantityTest::testUseApproximateDoubleWhenAble() {
{1.235, 3, RoundingMode::UNUM_ROUND_CEILING, true}};
UErrorCode status = U_ZERO_ERROR;
- for (TestCase cas : cases) {
+ for (const TestCase& cas : cases) {
DecimalQuantity fq;
fq.setToDouble(cas.d);
assertTrue("Should be using approximate double", !fq.isExplicitExactDouble());
@@ -623,7 +627,7 @@ void DecimalQuantityTest::testScientificAndCompactSuppressedExponent() {
// test the actual computed values of the plural operands
double expectedNOperand = cas.expectedDouble;
- double expectedIOperand = cas.expectedLong;
+ double expectedIOperand = static_cast<double>(cas.expectedLong);
double expectedEOperand = cas.expectedSuppressedScientificExponent;
double expectedCOperand = cas.expectedSuppressedCompactExponent;
double actualNOperand = dq.getPluralOperand(PLURAL_OPERAND_N);
@@ -721,4 +725,52 @@ void DecimalQuantityTest::testSuppressedExponentUnchangedByInitialScaling() {
}
}
+
+void DecimalQuantityTest::testDecimalQuantityParseFormatRoundTrip() {
+ IcuTestErrorCode status(*this, "testDecimalQuantityParseFormatRoundTrip");
+
+ struct TestCase {
+ UnicodeString numberString;
+ } cases[] = {
+ // number string
+ { u"0" },
+ { u"1" },
+ { u"1.0" },
+ { u"1.00" },
+ { u"1.1" },
+ { u"1.10" },
+ { u"-1.10" },
+ { u"0.0" },
+ { u"1c5" },
+ { u"1.0c5" },
+ { u"1.1c5" },
+ { u"1.10c5" },
+ { u"0.00" },
+ { u"0.1" },
+ { u"1c-1" },
+ { u"1.0c-1" }
+ };
+
+ for (const auto& cas : cases) {
+ UnicodeString numberString = cas.numberString;
+
+ DecimalQuantity dq = DecimalQuantity::fromExponentString(numberString, status);
+ UnicodeString roundTrip = dq.toExponentString();
+
+ assertEquals("DecimalQuantity format(parse(s)) should equal original s", numberString, roundTrip);
+ }
+
+ DecimalQuantity dq = DecimalQuantity::fromExponentString(u"1c0", status);
+ assertEquals("Zero ignored for visible exponent",
+ u"1",
+ dq.toExponentString());
+
+ dq.clear();
+ dq = DecimalQuantity::fromExponentString(u"1.0c0", status);
+ assertEquals("Zero ignored for visible exponent",
+ u"1.0",
+ dq.toExponentString());
+
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_range.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_range.cpp
index 08e74df8f52..a47c675c974 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_range.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_range.cpp
@@ -811,6 +811,28 @@ void NumberRangeFormatterTest::testFieldPositions() {
expectedFieldPositions,
UPRV_LENGTHOF(expectedFieldPositions));
}
+
+ {
+ const char16_t* message = u"Field position with approximately sign";
+ const char16_t* expectedString = u"~-100";
+ FormattedNumberRange result = assertFormattedRangeEquals(
+ message,
+ NumberRangeFormatter::withLocale("en-us"),
+ -100,
+ -100,
+ expectedString);
+ static const UFieldPositionWithCategory expectedFieldPositions[] = {
+ // category, field, begin index, end index
+ {UFIELD_CATEGORY_NUMBER, UNUM_APPROXIMATELY_SIGN_FIELD, 0, 1},
+ {UFIELD_CATEGORY_NUMBER, UNUM_SIGN_FIELD, 1, 2},
+ {UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD, 2, 5}};
+ checkMixedFormattedValue(
+ message,
+ result,
+ expectedString,
+ expectedFieldPositions,
+ UPRV_LENGTHOF(expectedFieldPositions));
+ }
}
void NumberRangeFormatterTest::testCopyMove() {
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/numfmtst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/numfmtst.cpp
index 011cc32dd34..7f271cb3f66 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/numfmtst.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/numfmtst.cpp
@@ -3357,6 +3357,7 @@ void NumberFormatTest::TestRoundingPattern() {
void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
df->setRoundingIncrement(increment);
+ assertEquals("Rounding increment round-trip", increment, df->getRoundingIncrement());
double lastParsed=INT32_MIN; //Intger.MIN_VALUE
for (int i=-iterations; i<=iterations;i++) {
double iValue=base+(increment*(i*0.1));
@@ -4889,9 +4890,9 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
"Peruvian soles1.00",
"Peruvian sol (1863\\u20131965)1.00",
"Peruvian soles (1863\\u20131965)1.00",
- "Philippine Piso1.00",
- "Philippine piso1.00",
- "Philippine pisos1.00",
+ "Philippine Peso1.00",
+ "Philippine peso1.00",
+ "Philippine pesos1.00",
"Platinum1.00",
"Platinum1.00",
"Polish Zloty (1950\\u20131995)1.00",
@@ -5826,9 +5827,9 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
"1.00 Peruvian soles random",
"1.00 Peruvian sol (1863\\u20131965) random",
"1.00 Peruvian soles (1863\\u20131965) random",
- "1.00 Philippine Piso random",
- "1.00 Philippine piso random",
- "1.00 Philippine pisos random",
+ "1.00 Philippine Peso random",
+ "1.00 Philippine peso random",
+ "1.00 Philippine pesos random",
"1.00 Platinum random",
"1.00 Platinum random",
"1.00 Polish Zloty (1950\\u20131995) random",
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/plurults.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/plurults.cpp
index 9131d370317..54cc77a0c9e 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/plurults.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/plurults.cpp
@@ -919,7 +919,7 @@ PluralRulesTest::testDoubleValue() {
const int64_t inputNum = cas.inputNum;
const double expVal = cas.expVal;
- FixedDecimal fd(inputNum);
+ FixedDecimal fd(static_cast<double>(inputNum));
UnicodeString message(u"FixedDecimal::doubleValue() for" + Int64ToUnicodeString(inputNum));
assertEquals(message, expVal, fd.doubleValue());
}
@@ -963,7 +963,7 @@ PluralRulesTest::testLongValue() {
const int64_t inputNum = cas.inputNum;
const int64_t expVal = cas.expVal;
- FixedDecimal fd(inputNum);
+ FixedDecimal fd(static_cast<double>(inputNum));
UnicodeString message(u"FixedDecimal::longValue() for" + Int64ToUnicodeString(inputNum));
assertEquals(message, expVal, fd.longValue());
}
@@ -982,7 +982,7 @@ PluralRulesTest::testLongValue() {
const double inputNum = cas.inputNum;
const int64_t expVal = cas.expVal;
- FixedDecimal fd(inputNum);
+ FixedDecimal fd(static_cast<double>(inputNum));
UnicodeString message(u"FixedDecimal::longValue() for" + DoubleToUnicodeString(inputNum));
assertEquals(message, expVal, fd.longValue());
}
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.cpp
index 73d4393843b..69db5db018c 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.cpp
@@ -149,6 +149,10 @@ void RBBITest::runIndexedTest( int32_t index, UBool exec, const char* &name, cha
TESTCASE_AUTO(TestTraceCreateLineNormal);
TESTCASE_AUTO(TestTraceCreateLineLoose);
TESTCASE_AUTO(TestTraceCreateLineStrict);
+ TESTCASE_AUTO(TestTraceCreateLineNormalPhrase);
+ TESTCASE_AUTO(TestTraceCreateLineLoosePhrase);
+ TESTCASE_AUTO(TestTraceCreateLineStrictPhrase);
+ TESTCASE_AUTO(TestTraceCreateLinePhrase);
TESTCASE_AUTO(TestTraceCreateBreakEngine);
#endif
@@ -5144,7 +5148,7 @@ void RBBITest::TestTraceCreateLine(void) {
LocalPointer<BreakIterator> brkitr(
BreakIterator::createLineInstance("zh-CN", status));
status.errIfFailureAndReset();
- assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "");
+ assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line");
}
void RBBITest::TestTraceCreateLineStrict(void) {
@@ -5153,7 +5157,7 @@ void RBBITest::TestTraceCreateLineStrict(void) {
LocalPointer<BreakIterator> brkitr(
BreakIterator::createLineInstance("zh-CN-u-lb-strict", status));
status.errIfFailureAndReset();
- assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "strict");
+ assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_strict");
}
void RBBITest::TestTraceCreateLineNormal(void) {
@@ -5162,7 +5166,7 @@ void RBBITest::TestTraceCreateLineNormal(void) {
LocalPointer<BreakIterator> brkitr(
BreakIterator::createLineInstance("zh-CN-u-lb-normal", status));
status.errIfFailureAndReset();
- assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "normal");
+ assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_normal");
}
void RBBITest::TestTraceCreateLineLoose(void) {
@@ -5171,7 +5175,43 @@ void RBBITest::TestTraceCreateLineLoose(void) {
LocalPointer<BreakIterator> brkitr(
BreakIterator::createLineInstance("zh-CN-u-lb-loose", status));
status.errIfFailureAndReset();
- assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "loose");
+ assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_loose");
+}
+
+void RBBITest::TestTraceCreateLineLoosePhrase(void) {
+ SetupTestTrace();
+ IcuTestErrorCode status(*this, "TestTraceCreateLineLoosePhrase");
+ LocalPointer<BreakIterator> brkitr(
+ BreakIterator::createLineInstance("ja-u-lb-loose-lw-phrase", status));
+ status.errIfFailureAndReset();
+ assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_loose_phrase");
+}
+
+void RBBITest::TestTraceCreateLineNormalPhrase(void) {
+ SetupTestTrace();
+ IcuTestErrorCode status(*this, "TestTraceCreateLineNormalPhrase");
+ LocalPointer<BreakIterator> brkitr(
+ BreakIterator::createLineInstance("ja-u-lb-normal-lw-phrase", status));
+ status.errIfFailureAndReset();
+ assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_normal_phrase");
+}
+
+void RBBITest::TestTraceCreateLineStrictPhrase(void) {
+ SetupTestTrace();
+ IcuTestErrorCode status(*this, "TestTraceCreateLineStrictPhrase");
+ LocalPointer<BreakIterator> brkitr(
+ BreakIterator::createLineInstance("ja-u-lb-strict-lw-phrase", status));
+ status.errIfFailureAndReset();
+ assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_strict_phrase");
+}
+
+void RBBITest::TestTraceCreateLinePhrase(void) {
+ SetupTestTrace();
+ IcuTestErrorCode status(*this, "TestTraceCreateLinePhrase");
+ LocalPointer<BreakIterator> brkitr(
+ BreakIterator::createLineInstance("ja-u-lw-phrase", status));
+ status.errIfFailureAndReset();
+ assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_phrase");
}
void RBBITest::TestTraceCreateBreakEngine(void) {
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.h b/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.h
index acb3e82bbec..d5d52119bc0 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.h
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.h
@@ -105,6 +105,10 @@ public:
void TestTraceCreateLineNormal();
void TestTraceCreateLineStrict();
void TestTraceCreateLineLoose();
+ void TestTraceCreateLineNormalPhrase();
+ void TestTraceCreateLineLoosePhrase();
+ void TestTraceCreateLineStrictPhrase();
+ void TestTraceCreateLinePhrase();
void TestTraceCreateBreakEngine();
#endif
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/strcase.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/strcase.cpp
index 006bcd64ed3..b5eff9f0af8 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/strcase.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/strcase.cpp
@@ -51,6 +51,7 @@ public:
void *iter, const char *localeID, uint32_t options);
void TestCasing();
void TestTitleOptions();
+ void TestDutchTitle();
void TestFullCaseFoldingIterator();
void TestGreekUpper();
void TestArmenian();
@@ -95,6 +96,7 @@ StringCaseTest::runIndexedTest(int32_t index, UBool exec, const char *&name, cha
#if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
TESTCASE_AUTO(TestCasing);
TESTCASE_AUTO(TestTitleOptions);
+ TESTCASE_AUTO(TestDutchTitle);
#endif
TESTCASE_AUTO(TestFullCaseFoldingIterator);
TESTCASE_AUTO(TestGreekUpper);
@@ -451,6 +453,7 @@ StringCaseTest::TestCasingImpl(const UnicodeString &input,
}
if(result!=output) {
dataerrln("error: UnicodeString.%s() got a wrong result for a test case from casing.res", name);
+ dataerrln(UnicodeString("input = [") + input + "], expected = [" + output + "], actual = [" + result + "]");
}
#if !UCONFIG_NO_BREAK_ITERATION
if(whichCase==TEST_TITLE && options==0) {
@@ -667,6 +670,106 @@ StringCaseTest::TestTitleOptions() {
#endif
}
+#if !UCONFIG_NO_BREAK_ITERATION
+void StringCaseTest::TestDutchTitle() {
+ IcuTestErrorCode errorCode(*this, "TestDutchTitle");
+
+ Locale nl("nl"); // Dutch
+ LocalPointer<BreakIterator> iter(
+ BreakIterator::createWordInstance(nl, errorCode));
+
+ // Dutch titlecase check in English
+ TestCasingImpl(
+ u"ijssel igloo IJMUIDEN",
+ u"Ijssel Igloo Ijmuiden",
+ TEST_TITLE,
+ nullptr,
+ "en",
+ 0);
+
+ // Dutch titlecase check in Dutch
+ TestCasingImpl(
+ u"ijssel igloo IJMUIDEN",
+ u"IJssel Igloo IJmuiden",
+ TEST_TITLE,
+ nullptr,
+ "nl",
+ 0);
+
+ // Dutch titlecase check in Dutch with nolowercase option
+ if (U_SUCCESS(errorCode)) {
+ iter->setText(u"ijssel igloo IjMUIdEN iPoD ijenough");
+ TestCasingImpl(
+ u"ijssel igloo IjMUIdEN iPoD ijenough",
+ u"IJssel Igloo IJMUIdEN IPoD IJenough",
+ TEST_TITLE,
+ nullptr,
+ "nl",
+ U_TITLECASE_NO_LOWERCASE);
+ }
+
+ errorCode.reset();
+
+ // Accented IJ testing
+
+ struct dutchTitleTestCase {
+ const UnicodeString input;
+ const UnicodeString expectedFull;
+ const UnicodeString expectedOnlyChanged;
+ } dutchTitleTestCases[] = {
+ // input, expectedFull, expectedOnlyChanged
+ {u"ij", u"IJ", u"IJ"},
+ {u"IJ", u"IJ", u""},
+ {u"íj́", u"ÍJ́", u"ÍJ"},
+ {u"ÍJ́", u"ÍJ́", u""},
+ {u"íJ́", u"ÍJ́", u"Í"},
+ {u"Ij́", u"Ij́", u""},
+ {u"ij́", u"Ij́", u"I"},
+ {u"ïj́", u"Ïj́", u"Ï"},
+ {u"íj\u0308", u"Íj\u0308", u"Í"},
+ {u"íj́\U0001D16E", u"Íj́\U0001D16E", u"Í"},
+ {u"íj\u1ABE", u"Íj\u1ABE", u"Í"},
+
+ {u"ijabc", u"IJabc", u"IJ"},
+ {u"IJabc", u"IJabc", u""},
+ {u"íj́abc", u"ÍJ́abc", u"ÍJ"},
+ {u"ÍJ́abc", u"ÍJ́abc", u""},
+ {u"íJ́abc", u"ÍJ́abc", u"Í"},
+ {u"Ij́abc", u"Ij́abc", u""},
+ {u"ij́abc", u"Ij́abc", u"I"},
+ {u"ïj́abc", u"Ïj́abc", u"Ï"},
+ {u"íjabc\u0308", u"Íjabc\u0308", u"Í"},
+ {u"íj́abc\U0001D16E", u"ÍJ́abc\U0001D16E", u"ÍJ"},
+ {u"íjabc\u1ABE", u"Íjabc\u1ABE", u"Í"},
+
+ // Bug ICU-21919
+ {u"Í", u"Í", u""},
+ };
+
+ for (const auto& cas : dutchTitleTestCases) {
+ const UnicodeString &input = cas.input;
+ const UnicodeString &expectedFull = cas.expectedFull;
+ const UnicodeString &expectedOnlyChanged = cas.expectedOnlyChanged;
+
+ for (const auto& isOnlyChanged : {true, false}) {
+ uint32_t testOptions = U_TITLECASE_NO_LOWERCASE
+ | (isOnlyChanged ? U_OMIT_UNCHANGED_TEXT : 0);
+
+ const UnicodeString &expected = isOnlyChanged ? expectedOnlyChanged : expectedFull;
+
+ TestCasingImpl(
+ input,
+ expected,
+ TEST_TITLE,
+ nullptr,
+ "nl",
+ testOptions
+ );
+ }
+ }
+}
+#endif
+
void
StringCaseTest::TestFullCaseFoldingIterator() {
UnicodeString ffi=UNICODE_STRING_SIMPLE("ffi");
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/tmsgfmt.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/tmsgfmt.cpp
index e55aa8fbe37..66f49822217 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/tmsgfmt.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/tmsgfmt.cpp
@@ -2051,7 +2051,7 @@ void TestMessageFormat::TestMessageFormatDateSkeleton() {
UDate date = LocaleTest::date(2021-1900, UCAL_NOVEMBER, 23, 16, 42, 55);
doTheRealDateTimeSkeletonTesting(date, u"{0,date,::MMMMd}", "en", u"November 23", status);
- doTheRealDateTimeSkeletonTesting(date, u"{0,date,::yMMMMdjm}", "en", u"November 23, 2021, 4:42 PM", status);
+ doTheRealDateTimeSkeletonTesting(date, u"{0,date,::yMMMMdjm}", "en", u"November 23, 2021 at 4:42 PM", status);
doTheRealDateTimeSkeletonTesting(date, u"{0,date, :: yMMMMd }", "en", u"November 23, 2021", status);
doTheRealDateTimeSkeletonTesting(date, u"{0,date,::yMMMMd}", "fr", u"23 novembre 2021", status);
doTheRealDateTimeSkeletonTesting(date, u"Expiration: {0,date,::yMMM}!", "en", u"Expiration: Nov 2021!", status);
@@ -2065,7 +2065,7 @@ void TestMessageFormat::TestMessageFormatTimeSkeleton() {
UDate date = LocaleTest::date(2021-1900, UCAL_NOVEMBER, 23, 16, 42, 55);
doTheRealDateTimeSkeletonTesting(date, u"{0,time,::MMMMd}", "en", u"November 23", status);
- doTheRealDateTimeSkeletonTesting(date, u"{0,time,::yMMMMdjm}", "en", u"November 23, 2021, 4:42 PM", status);
+ doTheRealDateTimeSkeletonTesting(date, u"{0,time,::yMMMMdjm}", "en", u"November 23, 2021 at 4:42 PM", status);
doTheRealDateTimeSkeletonTesting(date, u"{0,time, :: yMMMMd }", "en", u"November 23, 2021", status);
doTheRealDateTimeSkeletonTesting(date, u"{0,time,::yMMMMd}", "fr", u"23 novembre 2021", status);
doTheRealDateTimeSkeletonTesting(date, u"Expiration: {0,time,::yMMM}!", "en", u"Expiration: Nov 2021!", status);
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/transtst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/transtst.cpp
index 8a81b5b3377..aaf283f7a4e 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/transtst.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/transtst.cpp
@@ -3639,7 +3639,7 @@ void TransliteratorTest::TestIncrementalProgress(void) {
Transliterator *t = Transliterator::createInstance(id, UTRANS_FORWARD, err, status);
if (U_FAILURE(status)) {
- dataerrln((UnicodeString)"FAIL: Could not create " + id);
+ dataerrln((UnicodeString)"FAIL: Could not create " + id + ", status " + u_errorName(status));
delete t;
continue;
}
@@ -3654,19 +3654,38 @@ void TransliteratorTest::TestIncrementalProgress(void) {
// 1. Devanagari-Arabic
// 2. Any-*/BGN
// 2a. Any-*/BGN_1981
- // 3. Any-*/UNGEGN
- // 4. Any-*/MNS
- // If UCONFIG_NO_BREAK_ITERATION is on, Latin-Thai is also not expected to work.
+ // 3. Any-*/MNS
+ //
+ // 4. If UCONFIG_NO_BREAK_ITERATION is on, Latin-Thai is also not expected to work.
+ //
+ // The following are direction="both" transforms with variants, inverting the Any-Xxxx/Variant for
+ // any of these does not work; see ICU-21911 (not sure whether this is intentional or an ICU bug).
+ // Unfortunately we do not easily have the info at this point as to whether the original transform
+ // had direction="both" specified.
+ // 5. Any-*/UNGEGN
+ // 6. Any-Ethiopic/*
+ // 7. Any-Braille/*
+ // 8. Any-*/Gurage_2013
+ // 9. Any-*/Gutgarts
+ // 10. Any-*/Tekie_Alibekit
+ // 11. Any-*/Xaleget
+ //
if ( id.compare((UnicodeString)"Devanagari-Arabic/") != 0
&& !(id.startsWith((UnicodeString)"Any-") &&
- (id.endsWith((UnicodeString)"/BGN") || id.endsWith((UnicodeString)"/BGN_1981") || id.endsWith((UnicodeString)"/UNGEGN") || id.endsWith((UnicodeString)"/MNS"))
+ (id.endsWith((UnicodeString)"/BGN") || id.endsWith((UnicodeString)"/BGN_1981") || id.endsWith((UnicodeString)"/MNS"))
)
#if UCONFIG_NO_BREAK_ITERATION
&& id.compare((UnicodeString)"Latin-Thai/") != 0
#endif
+ && !(logKnownIssue("21911", "ICU4C cannot create inverse of Any-Xxxx/Variant transform created from both-direction transform") &&
+ id.startsWith((UnicodeString)"Any-") &&
+ (id.endsWith((UnicodeString)"/UNGEGN") || id.startsWith((UnicodeString)"Any-Ethiopic/") || id.startsWith((UnicodeString)"Any-Braille/") ||
+ id.endsWith((UnicodeString)"/Gurage_2013") || id.endsWith((UnicodeString)"/Gutgarts") || id.endsWith((UnicodeString)"/Tekie_Alibekit") ||
+ id.endsWith((UnicodeString)"/Xaleget"))
+ )
)
{
- errln((UnicodeString)"FAIL: Could not create inverse of " + id);
+ errln((UnicodeString)"FAIL: Could not create inverse of " + id + ", status " + u_errorName(status));
}
delete t;
delete inv;
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/tztest.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/tztest.cpp
index 0d58bab197d..5ae9ae7175c 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/tztest.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/tztest.cpp
@@ -906,7 +906,7 @@ void TimeZoneTest::TestShortZoneIDs()
{"AET", 600, TRUE}, // ICU Link - Australia/Sydney
{"SST", 660, FALSE}, // ICU Link - Pacific/Guadalcanal
{"NST", 720, TRUE}, // ICU Link - Pacific/Auckland
- {"MIT", 780, TRUE}, // ICU Link - Pacific/Apia
+ {"MIT", 780, FALSE}, // ICU Link - Pacific/Apia
{"Etc/Unknown", 0, FALSE}, // CLDR
@@ -2036,12 +2036,20 @@ void TimeZoneTest::TestCanonicalIDAPI() {
void TimeZoneTest::TestCanonicalID() {
- // Some canonical IDs in CLDR are defined as "Link"
- // in Olson tzdata.
+ // Olson (IANA) tzdata used to have very few "Link"s long time ago.
+ // This test case was written when most of CLDR canonical time zones are
+ // defined as independent "Zone" in the TZ database.
+ // Since then, the TZ maintainer found some historic rules in mid 20th century
+ // were not really reliable, and many zones are now sharing rules.
+ // As of TZ database release 2022a, there are quite a lot of zones defined
+ // by "Link" to another zone, so the exception table below becomes really
+ // big. It might be still useful to make sure CLDR zone aliases are consistent
+ // with zone rules.
static const struct {
- const char *alias;
- const char *zone;
+ const char *alias; // link-from
+ const char *zone; // link-to (A zone ID with "Zone" rule)
} excluded1[] = {
+ {"Africa/Accra", "Africa/Abidjan"},
{"Africa/Addis_Ababa", "Africa/Nairobi"},
{"Africa/Asmera", "Africa/Nairobi"},
{"Africa/Bamako", "Africa/Abidjan"},
@@ -2076,35 +2084,43 @@ void TimeZoneTest::TestCanonicalID() {
{"Africa/Ouagadougou", "Africa/Abidjan"},
{"Africa/Porto-Novo", "Africa/Lagos"},
{"Africa/Sao_Tome", "Africa/Abidjan"},
- {"America/Antigua", "America/Port_of_Spain"},
- {"America/Anguilla", "America/Port_of_Spain"},
+ {"America/Antigua", "America/Puerto_Rico"},
+ {"America/Anguilla", "America/Puerto_Rico"},
+ {"America/Aruba", "America/Puerto_Rico"},
+ {"America/Atikokan", "America/Panama"},
+ {"America/Blanc-Sablon", "America/Puerto_Rico"},
{"America/Cayman", "America/Panama"},
{"America/Coral_Harbour", "America/Panama"},
- {"America/Curacao", "America/Aruba"},
- {"America/Dominica", "America/Port_of_Spain"},
- {"America/Grenada", "America/Port_of_Spain"},
- {"America/Guadeloupe", "America/Port_of_Spain"},
- {"America/Kralendijk", "America/Aruba"},
- {"America/Lower_Princes", "America/Aruba"},
- {"America/Marigot", "America/Port_of_Spain"},
- {"America/Montserrat", "America/Port_of_Spain"},
+ {"America/Creston", "America/Phoenix"},
+ {"America/Curacao", "America/Puerto_Rico"},
+ {"America/Dominica", "America/Puerto_Rico"},
+ {"America/Grenada", "America/Puerto_Rico"},
+ {"America/Guadeloupe", "America/Puerto_Rico"},
+ {"America/Kralendijk", "America/Puerto_Rico"},
+ {"America/Lower_Princes", "America/Puerto_Rico"},
+ {"America/Marigot", "America/Puerto_Rico"},
+ {"America/Montreal", "America/Toronto"},
+ {"America/Montserrat", "America/Puerto_Rico"},
+ {"America/Nassau", "America/Toronto"},
+ {"America/Port_of_Spain", "America/Puerto_Rico"},
{"America/Santa_Isabel", "America/Tijuana"},
{"America/Shiprock", "America/Denver"},
- {"America/St_Barthelemy", "America/Port_of_Spain"},
- {"America/St_Kitts", "America/Port_of_Spain"},
- {"America/St_Lucia", "America/Port_of_Spain"},
- {"America/St_Thomas", "America/Port_of_Spain"},
- {"America/St_Vincent", "America/Port_of_Spain"},
- {"America/Toronto", "America/Montreal"},
- {"America/Tortola", "America/Port_of_Spain"},
+ {"America/St_Barthelemy", "America/Puerto_Rico"},
+ {"America/St_Kitts", "America/Puerto_Rico"},
+ {"America/St_Lucia", "America/Puerto_Rico"},
+ {"America/St_Thomas", "America/Puerto_Rico"},
+ {"America/St_Vincent", "America/Puerto_Rico"},
+ {"America/Tortola", "America/Puerto_Rico"},
{"America/Virgin", "America/Puerto_Rico"},
+ {"Antarctica/DumontDUrville", "Pacific/Port_Moresby"},
{"Antarctica/South_Pole", "Antarctica/McMurdo"},
+ {"Antarctica/Syowa", "Asia/Riyadh"},
{"Arctic/Longyearbyen", "Europe/Oslo"},
- {"Asia/Kuwait", "Asia/Aden"},
+ {"Asia/Aden", "Asia/Riyadh"},
+ {"Asia/Kuwait", "Asia/Riyadh"},
{"Asia/Muscat", "Asia/Dubai"},
{"Asia/Phnom_Penh", "Asia/Bangkok"},
{"Asia/Qatar", "Asia/Bahrain"},
- {"Asia/Riyadh", "Asia/Aden"},
{"Asia/Vientiane", "Asia/Bangkok"},
{"Atlantic/Jan_Mayen", "Europe/Oslo"},
{"Atlantic/St_Helena", "Africa/Abidjan"},
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/units_test.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/units_test.cpp
index c65a5e03229..ca41e3b0d03 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/units_test.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/units_test.cpp
@@ -325,6 +325,12 @@ void UnitsTest::testConverter() {
// Fuel Consumption
{"cubic-meter-per-meter", "mile-per-gallon", 2.1383143939394E-6, 1.1},
{"cubic-meter-per-meter", "mile-per-gallon", 2.6134953703704E-6, 0.9},
+ {"liter-per-100-kilometer", "mile-per-gallon", 6.6, 35.6386},
+ {"liter-per-100-kilometer", "mile-per-gallon", 0, uprv_getInfinity()},
+ {"mile-per-gallon", "liter-per-100-kilometer", 0, uprv_getInfinity()},
+ {"mile-per-gallon", "liter-per-100-kilometer", uprv_getInfinity(), 0},
+ // We skip testing -Inf, because the inverse conversion loses the sign:
+ // {"mile-per-gallon", "liter-per-100-kilometer", -uprv_getInfinity(), 0},
// Test Aliases
// Alias is just another name to the same unit. Therefore, converting
@@ -348,54 +354,42 @@ void UnitsTest::testConverter() {
continue;
}
+ double maxDelta = 1e-6 * uprv_fabs(testCase.expectedValue);
+ if (testCase.expectedValue == 0) {
+ maxDelta = 1e-12;
+ }
+ double inverseMaxDelta = 1e-6 * uprv_fabs(testCase.inputValue);
+ if (testCase.inputValue == 0) {
+ inverseMaxDelta = 1e-12;
+ }
+
ConversionRates conversionRates(status);
if (status.errIfFailureAndReset("conversionRates(status)")) {
continue;
}
+
UnitsConverter converter(source, target, conversionRates, status);
if (status.errIfFailureAndReset("UnitsConverter(<%s>, <%s>, ...)", testCase.source,
testCase.target)) {
continue;
}
-
- double maxDelta = 1e-6 * uprv_fabs(testCase.expectedValue);
- if (testCase.expectedValue == 0) {
- maxDelta = 1e-12;
- }
assertEqualsNear(UnicodeString("testConverter: ") + testCase.source + " to " + testCase.target,
testCase.expectedValue, converter.convert(testCase.inputValue), maxDelta);
-
- maxDelta = 1e-6 * uprv_fabs(testCase.inputValue);
- if (testCase.inputValue == 0) {
- maxDelta = 1e-12;
- }
assertEqualsNear(
UnicodeString("testConverter inverse: ") + testCase.target + " back to " + testCase.source,
- testCase.inputValue, converter.convertInverse(testCase.expectedValue), maxDelta);
+ testCase.inputValue, converter.convertInverse(testCase.expectedValue), inverseMaxDelta);
-
- // TODO: Test UnitsConverter created using CLDR separately.
// Test UnitsConverter created by CLDR unit identifiers
UnitsConverter converter2(testCase.source, testCase.target, status);
if (status.errIfFailureAndReset("UnitsConverter(<%s>, <%s>, ...)", testCase.source,
testCase.target)) {
continue;
}
-
- maxDelta = 1e-6 * uprv_fabs(testCase.expectedValue);
- if (testCase.expectedValue == 0) {
- maxDelta = 1e-12;
- }
assertEqualsNear(UnicodeString("testConverter2: ") + testCase.source + " to " + testCase.target,
testCase.expectedValue, converter2.convert(testCase.inputValue), maxDelta);
-
- maxDelta = 1e-6 * uprv_fabs(testCase.inputValue);
- if (testCase.inputValue == 0) {
- maxDelta = 1e-12;
- }
assertEqualsNear(
UnicodeString("testConverter2 inverse: ") + testCase.target + " back to " + testCase.source,
- testCase.inputValue, converter2.convertInverse(testCase.expectedValue), maxDelta);
+ testCase.inputValue, converter2.convertInverse(testCase.expectedValue), inverseMaxDelta);
}
}
@@ -647,6 +641,16 @@ void UnitsTest::testComplexUnitsConverter() {
Measure(2.1, MeasureUnit::createMeter(status), status)},
2,
0.001},
+
+ // Negative numbers
+ {"Negative number conversion",
+ "yard",
+ "mile-and-yard",
+ -1800,
+ {Measure(-1, MeasureUnit::createMile(status), status),
+ Measure(-40, MeasureUnit::createYard(status), status)},
+ 2,
+ 1e-10},
};
status.assertSuccess();
@@ -694,11 +698,7 @@ void UnitsTest::testComplexUnitsConverter() {
ComplexUnitsConverter converter2( testCase.input, testCase.output, status);
testATestCase(converter2, "ComplexUnitsConverter #1 " , testCase);
}
-
-
status.assertSuccess();
-
- // TODO(icu-units#63): test negative numbers!
}
void UnitsTest::testComplexUnitsConverterSorting() {
diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/ustrtest.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/ustrtest.cpp
index cd9751d761b..309a29713d7 100644
--- a/Build/source/libs/icu/icu-src/source/test/intltest/ustrtest.cpp
+++ b/Build/source/libs/icu/icu-src/source/test/intltest/ustrtest.cpp
@@ -1653,6 +1653,16 @@ UnicodeStringTest::TestBogus() {
if(test1>=test2 || !(test2>test1) || test1.compare(test2)>=0 || !(test2.compare(test1)>0)) {
errln("bogus<empty failed");
}
+
+ // test that copy constructor of bogus is bogus & clone of bogus is nullptr
+ {
+ test3.setToBogus();
+ UnicodeString test3Copy(test3);
+ UnicodeString *test3Clone = test3.clone();
+ assertTrue(WHERE, test3.isBogus());
+ assertTrue(WHERE, test3Copy.isBogus());
+ assertTrue(WHERE, test3Clone == nullptr);
+ }
}
// StringEnumeration ------------------------------------------------------- ***
@@ -2354,7 +2364,7 @@ void UnicodeStringTest::TestLargeAppend() {
} else if (total <= INT32_MAX) {
// Check that a string of exactly the maximum size works
UnicodeString str2;
- int32_t remain = INT32_MAX - total;
+ int32_t remain = static_cast<int32_t>(INT32_MAX - total);
char16_t *buf2 = str2.getBuffer(remain);
if (buf2 == nullptr) {
// if somehow memory allocation fail, return the test