+ errorCode.errDataIfFailureAndReset("");
+}
+
+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));
+}
+
+void TestMessageFormat::TestMessageFormatNumberSkeleton() {
+ IcuTestErrorCode status(*this, "TestMessageFormatNumberSkeleton");
+
+ static const struct TestCase {
+ const char16_t* messagePattern;
+ const char* localeName;
+ double arg;
+ const char16_t* expected;
+ } cases[] = {
+ { u"{0,number,::percent}", "en", 50, u"50%" },
+ { u"{0,number,::percent scale/100}", "en", 0.5, u"50%" },
+ { u"{0,number, :: percent scale/100 }", "en", 0.5, u"50%" },
+ { u"{0,number,::currency/USD}", "en", 23, u"$23.00" },
+ { u"{0,number,::precision-integer}", "en", 514.23, u"514" },
+ { u"{0,number,::.000}", "en", 514.23, u"514.230" },
+ { u"{0,number,::.}", "en", 514.23, u"514" },
+ { u"{0,number,::}", "fr", 514.23, u"514,23" },
+ { u"Cost: {0,number,::currency/EUR}.", "en", 4.3, u"Cost: €4.30." },
+ { u"{0,number,'::'0.00}", "en", 50, u"::50.00" }, // pattern literal
+ };
+
+ for (auto& cas : cases) {
+ status.setScope(cas.messagePattern);
+ MessageFormat msgf(cas.messagePattern, cas.localeName, status);
+ UnicodeString sb;
+ FieldPosition fpos(0);
+ Formattable argsArray[] = {{cas.arg}};
+ Formattable args(argsArray, 1);
+ msgf.format(args, sb, status);
+
+ assertEquals(cas.messagePattern, cas.expected, sb);
+ }