1 // © 2024 and later: Unicode, Inc. and others.
2
3 #include "unicode/utypes.h"
4
5 #if !UCONFIG_NO_FORMATTING
6
7 #if !UCONFIG_NO_MF2
8
9 #include "unicode/calendar.h"
10 #include "messageformat2test.h"
11
12 using namespace icu::message2;
13
14 /*
15 Tests reflect the syntax specified in
16
17 https://github.com/unicode-org/message-format-wg/commits/main/spec/message.abnf
18
19 release LDML45-alpha:
20
21 https://github.com/unicode-org/message-format-wg/releases/tag/LDML45-alpha
22 */
23
testDateTime(IcuTestErrorCode & errorCode)24 void TestMessageFormat2::testDateTime(IcuTestErrorCode& errorCode) {
25 CHECK_ERROR(errorCode);
26
27 LocalPointer<Calendar> cal(Calendar::createInstance(errorCode));
28 TestCase::Builder testBuilder;
29
30 testBuilder.setName("testDateTime");
31 // November 23, 2022 at 7:42:37.123 PM
32 cal->set(2022, Calendar::NOVEMBER, 23, 19, 42, 37);
33 UDate TEST_DATE = cal->getTime(errorCode);
34 UnicodeString date = "date";
35 testBuilder.setLocale(Locale("ro"));
36
37 TestCase test = testBuilder.setPattern("Testing date formatting: {$date :datetime}.")
38 .setExpected("Testing date formatting: 23.11.2022, 19:42.")
39 .setDateArgument(date, TEST_DATE)
40 .build();
41 TestUtils::runTestCase(*this, test, errorCode);
42
43 // Formatted string as argument -- `:date` should format the source Formattable
44 test = testBuilder.setPattern(".local $dateStr = {$date :datetime}\n\
45 {{Testing date formatting: {$dateStr :datetime}}}")
46 .setExpected("Testing date formatting: 23.11.2022, 19:42.")
47 .setExpectSuccess()
48 .setDateArgument(date, TEST_DATE)
49 .build();
50 // Style
51
52 testBuilder.setLocale(Locale("en", "US"));
53
54 test = testBuilder.setPattern("Testing date formatting: {$date :date style=long}.")
55 .setExpected("Testing date formatting: November 23, 2022.")
56 .setDateArgument(date, TEST_DATE)
57 .build();
58 TestUtils::runTestCase(*this, test, errorCode);
59
60 test = testBuilder.setPattern("Testing date formatting: {$date :date style=medium}.")
61 .setExpected("Testing date formatting: Nov 23, 2022.")
62 .setDateArgument(date, TEST_DATE)
63 .build();
64 TestUtils::runTestCase(*this, test, errorCode);
65
66 test = testBuilder.setPattern("Testing date formatting: {$date :date style=short}.")
67 .setExpected("Testing date formatting: 11/23/22.")
68 .setDateArgument(date, TEST_DATE)
69 .build();
70 TestUtils::runTestCase(*this, test, errorCode);
71
72 test = testBuilder.setPattern("Testing date formatting: {$date :time style=long}.")
73 .setExpected(CharsToUnicodeString("Testing date formatting: 7:42:37\\u202FPM PST."))
74 .setDateArgument(date, TEST_DATE)
75 .build();
76 TestUtils::runTestCase(*this, test, errorCode);
77
78 test = testBuilder.setPattern("Testing date formatting: {$date :time style=medium}.")
79 .setExpected(CharsToUnicodeString("Testing date formatting: 7:42:37\\u202FPM."))
80 .setDateArgument(date, TEST_DATE)
81 .build();
82 TestUtils::runTestCase(*this, test, errorCode);
83
84 test = testBuilder.setPattern("Testing date formatting: {$date :time style=short}.")
85 .setExpected(CharsToUnicodeString("Testing date formatting: 7:42\\u202FPM."))
86 .setDateArgument(date, TEST_DATE)
87 .build();
88 TestUtils::runTestCase(*this, test, errorCode);
89
90 // Error cases
91 // Number as argument
92 test = testBuilder.setPattern(".local $num = {|42| :number}\n\
93 {{Testing date formatting: {$num :datetime}}}")
94 .clearArguments()
95 .setExpected("Testing date formatting: {|42|}")
96 .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
97 .build();
98 TestUtils::runTestCase(*this, test, errorCode);
99 // Literal string as argument
100 test = testBuilder.setPattern("Testing date formatting: {|horse| :datetime}")
101 .setExpected("Testing date formatting: {|horse|}")
102 .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
103 .build();
104
105 TestUtils::runTestCase(*this, test, errorCode);
106
107 }
108
testNumbers(IcuTestErrorCode & errorCode)109 void TestMessageFormat2::testNumbers(IcuTestErrorCode& errorCode) {
110 CHECK_ERROR(errorCode);
111
112 double value = 1234567890.97531;
113 UnicodeString val = "val";
114
115 TestCase::Builder testBuilder;
116 testBuilder.setName("testNumbers");
117
118 // Literals
119 TestCase test = testBuilder.setPattern("From literal: {123456789 :number}!")
120 .setArgument(val, value)
121 .setExpected("From literal: 123.456.789!")
122 .setLocale(Locale("ro"))
123 .build();
124 TestUtils::runTestCase(*this, test, errorCode);
125
126 test = testBuilder.setPattern("From literal: {|123456789.531| :number}!")
127 .setArgument(val, value)
128 .setExpected("From literal: 123.456.789,531!")
129 .build();
130 TestUtils::runTestCase(*this, test, errorCode);
131
132 // This should fail, because number literals are not treated
133 // as localized numbers
134 test = testBuilder.setPattern("From literal: {|123456789,531| :number}!")
135 .setArgument(val, value)
136 .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
137 .setExpected("From literal: {|123456789,531|}!")
138 .build();
139 TestUtils::runTestCase(*this, test, errorCode);
140
141 test = testBuilder.setPattern("From literal: {|123456789.531| :number}!")
142 .setArgument(val, value)
143 .setExpectSuccess()
144 .setExpected(CharsToUnicodeString("From literal: \\u1041\\u1042\\u1043,\\u1044\\u1045\\u1046,\\u1047\\u1048\\u1049.\\u1045\\u1043\\u1041!"))
145 .setLocale(Locale("my"))
146 .build();
147 TestUtils::runTestCase(*this, test, errorCode);
148
149
150 // Testing that the detection works for various types (without specifying :number)
151 test = testBuilder.setPattern("Default double: {$val}!")
152 .setLocale(Locale("en", "IN"))
153 .setArgument(val, value)
154 .setExpected("Default double: 1,23,45,67,890.97531!")
155 .build();
156 TestUtils::runTestCase(*this, test, errorCode);
157 test = testBuilder.setPattern("Default double: {$val}!")
158 .setLocale(Locale("ro"))
159 .setArgument(val, value)
160 .setExpected("Default double: 1.234.567.890,97531!")
161 .build();
162 TestUtils::runTestCase(*this, test, errorCode);
163 test = testBuilder.setPattern("Default float: {$val}!")
164 .setLocale(Locale("ro"))
165 .setArgument(val, 3.1415926535)
166 .setExpected("Default float: 3,141593!")
167 .build();
168 TestUtils::runTestCase(*this, test, errorCode);
169 test = testBuilder.setPattern("Default int64: {$val}!")
170 .setLocale(Locale("ro"))
171 .setArgument(val, (int64_t) 1234567890123456789)
172 .setExpected("Default int64: 1.234.567.890.123.456.789!")
173 .build();
174 TestUtils::runTestCase(*this, test, errorCode);
175 test = testBuilder.setPattern("Default number: {$val}!")
176 .setLocale(Locale("ro"))
177 .setDecimalArgument(val, "1234567890123456789.987654321", errorCode)
178 .setExpected("Default number: 1.234.567.890.123.456.789,987654!")
179 .build();
180 TestUtils::runTestCase(*this, test, errorCode);
181
182 // Omitted CurrencyAmount test from ICU4J since it's not supported by Formattable
183
184 }
185
testBuiltInFunctions()186 void TestMessageFormat2::testBuiltInFunctions() {
187 IcuTestErrorCode errorCode(*this, "testBuiltInFunctions");
188
189 testDateTime(errorCode);
190 testNumbers(errorCode);
191 }
192
193 #endif /* #if !UCONFIG_NO_MF2 */
194
195 #endif /* #if !UCONFIG_NO_FORMATTING */
196