+void TestMessageFormat::testGetFormatNames() {
+ IcuTestErrorCode errorCode(*this, "testGetFormatNames");
+ MessageFormat msgfmt("Hello, {alice,number} {oops,date,full} {zip,spellout} World.", Locale::getRoot(), errorCode);
+ if(errorCode.logDataIfFailureAndReset("MessageFormat() failed")) {
+ return;
+ }
+ LocalPointer<StringEnumeration> names(msgfmt.getFormatNames(errorCode));
+ if(errorCode.logIfFailureAndReset("msgfmt.getFormatNames() failed")) {
+ return;
+ }
+ const UnicodeString *name;
+ name = names->snext(errorCode);
+ if (name == NULL || errorCode.isFailure()) {
+ errln("msgfmt.getFormatNames()[0] failed: %s", errorCode.errorName());
+ errorCode.reset();
+ return;
+ }
+ if (!assertEquals("msgfmt.getFormatNames()[0]", UNICODE_STRING_SIMPLE("alice"), *name)) {
+ return;
+ }
+ name = names->snext(errorCode);
+ if (name == NULL || errorCode.isFailure()) {
+ errln("msgfmt.getFormatNames()[1] failed: %s", errorCode.errorName());
+ errorCode.reset();
+ return;
+ }
+ if (!assertEquals("msgfmt.getFormatNames()[1]", UNICODE_STRING_SIMPLE("oops"), *name)) {
+ return;
+ }
+ name = names->snext(errorCode);
+ if (name == NULL || errorCode.isFailure()) {
+ errln("msgfmt.getFormatNames()[2] failed: %s", errorCode.errorName());
+ errorCode.reset();
+ return;
+ }
+ if (!assertEquals("msgfmt.getFormatNames()[2]", UNICODE_STRING_SIMPLE("zip"), *name)) {
+ return;
+ }
+ name = names->snext(errorCode);
+ if (name != NULL) {
+ errln(UnicodeString("msgfmt.getFormatNames()[3] should be NULL but is: ") + *name);
+ return;
+ }
+}
+
+void TestMessageFormat::TestTrimArgumentName() {
+ // ICU 4.8 allows and ignores white space around argument names and numbers.
+ IcuTestErrorCode errorCode(*this, "TestTrimArgumentName");
+ MessageFormat m("a { 0 , number , '#,#'#.0 } z", Locale::getEnglish(), errorCode);
+ if (errorCode.logDataIfFailureAndReset("Unable to instantiate MessageFormat")) {
+ return;
+ }
+ Formattable args[1] = { (int32_t)2 };
+ FieldPosition ignore(0);
+ UnicodeString result;
+ assertEquals("trim-numbered-arg format() failed", "a #,#2.0 z",
+ m.format(args, 1, result, ignore, errorCode));
+
+ m.applyPattern("x { _oOo_ , number , integer } y", errorCode);
+ UnicodeString argName = UNICODE_STRING_SIMPLE("_oOo_");
+ args[0].setLong(3);
+ result.remove();
+ assertEquals("trim-named-arg format() failed", "x 3 y",
+ m.format(&argName, args, 1, result, errorCode));
+}
+
+void TestMessageFormat::TestSelectOrdinal() {
+ IcuTestErrorCode errorCode(*this, "TestSelectOrdinal");
+ // Test plural & ordinal together,
+ // to make sure that we get the correct cached PluralSelector for each.
+ MessageFormat m(
+ "{0,plural,one{1 file}other{# files}}, "
+ "{0,selectordinal,one{#st file}two{#nd file}few{#rd file}other{#th file}}",
+ Locale::getEnglish(), errorCode);
+ if (errorCode.logDataIfFailureAndReset("Unable to instantiate MessageFormat")) {
+ return;
+ }
+ Formattable args[1] = { (int32_t)21 };
+ FieldPosition ignore(0);
+ UnicodeString result;
+ assertEquals("plural-and-ordinal format(21) failed", "21 files, 21st file",
+ m.format(args, 1, result, ignore, errorCode), TRUE);
+
+ args[0].setLong(2);
+ assertEquals("plural-and-ordinal format(2) failed", "2 files, 2nd file",
+ m.format(args, 1, result.remove(), ignore, errorCode), TRUE);
+
+ args[0].setLong(1);
+ assertEquals("plural-and-ordinal format(1) failed", "1 file, 1st file",
+ m.format(args, 1, result.remove(), ignore, errorCode), TRUE);
+
+ args[0].setLong(3);
+ assertEquals("plural-and-ordinal format(3) failed", "3 files, 3rd file",
+ m.format(args, 1, result.remove(), ignore, errorCode), TRUE);
+
+ errorCode.logDataIfFailureAndReset("");
+}
+
+void TestMessageFormat::TestDecimals() {
+ IcuTestErrorCode errorCode(*this, "TestDecimals");
+ // Simple number replacement.
+ MessageFormat m(
+ "{0,plural,one{one meter}other{# meters}}",
+ Locale::getEnglish(), errorCode);
+ Formattable args[1] = { (int32_t)1 };
+ FieldPosition ignore;
+ UnicodeString result;
+ assertEquals("simple format(1)", "one meter",
+ m.format(args, 1, result, ignore, errorCode), TRUE);
+
+ args[0] = (double)1.5;
+ result.remove();
+ assertEquals("simple format(1.5)", "1.5 meters",
+ m.format(args, 1, result, ignore, errorCode), TRUE);
+
+ // Simple but explicit.
+ MessageFormat m0(
+ "{0,plural,one{one meter}other{{0} meters}}",
+ Locale::getEnglish(), errorCode);
+ args[0] = (int32_t)1;
+ result.remove();
+ assertEquals("explicit format(1)", "one meter",
+ m0.format(args, 1, result, ignore, errorCode), TRUE);
+
+ args[0] = (double)1.5;
+ result.remove();
+ assertEquals("explicit format(1.5)", "1.5 meters",
+ m0.format(args, 1, result, ignore, errorCode), TRUE);
+
+ // With offset and specific simple format with optional decimals.
+ MessageFormat m1(
+ "{0,plural,offset:1 one{another meter}other{{0,number,00.#} meters}}",
+ Locale::getEnglish(), errorCode);
+ args[0] = (int32_t)1;
+ result.remove();
+ assertEquals("offset format(1)", "01 meters",
+ m1.format(args, 1, result, ignore, errorCode), TRUE);
+
+ args[0] = (int32_t)2;
+ result.remove();
+ assertEquals("offset format(1)", "another meter",
+ m1.format(args, 1, result, ignore, errorCode), TRUE);
+
+ args[0] = (double)2.5;
+ result.remove();
+ assertEquals("offset format(1)", "02.5 meters",
+ m1.format(args, 1, result, ignore, errorCode), TRUE);
+
+ // With offset and specific simple format with forced decimals.
+ MessageFormat m2(
+ "{0,plural,offset:1 one{another meter}other{{0,number,0.0} meters}}",
+ Locale::getEnglish(), errorCode);
+ args[0] = (int32_t)1;
+ result.remove();
+ assertEquals("offset-decimals format(1)", "1.0 meters",
+ m2.format(args, 1, result, ignore, errorCode), TRUE);
+
+ args[0] = (int32_t)2;
+ result.remove();
+ assertEquals("offset-decimals format(1)", "2.0 meters",
+ m2.format(args, 1, result, ignore, errorCode), TRUE);
+
+ args[0] = (double)2.5;
+ result.remove();
+ assertEquals("offset-decimals format(1)", "2.5 meters",
+ m2.format(args, 1, result, ignore, errorCode), TRUE);
+ errorCode.reset();
+}
+
+void TestMessageFormat::TestArgIsPrefixOfAnother() {
+ IcuTestErrorCode errorCode(*this, "TestArgIsPrefixOfAnother");
+ // Ticket #11952
+ MessageFormat mf1("{0,select,a{A}ab{AB}abc{ABC}other{?}}", Locale::getEnglish(), errorCode);
+ Formattable args[3];
+ FieldPosition ignore;
+ UnicodeString result;
+ args[0].setString("a");
+ assertEquals("a", "A", mf1.format(args, 1, result, ignore, errorCode));
+ args[0].setString("ab");
+ assertEquals("ab", "AB", mf1.format(args, 1, result.remove(), ignore, errorCode));
+ args[0].setString("abc");
+ assertEquals("abc", "ABC", mf1.format(args, 1, result.remove(), ignore, errorCode));
+
+ // Ticket #12172
+ MessageFormat mf2("{a} {aa} {aaa}", Locale::getEnglish(), errorCode);
+ UnicodeString argNames[3] = { "a", "aa", "aaa" };
+ args[0].setString("A");
+ args[1].setString("AB");
+ args[2].setString("ABC");
+ assertEquals("a aa aaa", "A AB ABC", mf2.format(argNames, args, 3, result.remove(), errorCode));
+
+ // Ticket #12172
+ MessageFormat mf3("{aa} {aaa}", Locale::getEnglish(), errorCode);
+ assertEquals("aa aaa", "AB ABC", mf3.format(argNames + 1, args + 1, 2, result.remove(), errorCode));
+}
+