xref: /aosp_15_r20/external/icu/icu4c/source/test/intltest/messageformat2test_builtin.cpp (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
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