xref: /aosp_15_r20/external/icu/icu4c/source/test/intltest/messageformat2test_fromjson.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 "messageformat2test.h"
10 
11 using namespace icu::message2;
12 
13 /*
14   TODO: Tests need to be unified in a single format that
15   both ICU4C and ICU4J can use, rather than being embedded in code.
16 
17   Tests are included in their current state to give a sense of
18   how much test coverage has been achieved. Most of the testing is
19   of the parser/serializer; the formatter needs to be tested more
20   thoroughly.
21 */
22 
23 /*
24 Tests reflect the syntax specified in
25 
26   https://github.com/unicode-org/message-format-wg/commits/main/spec/message.abnf
27 
28 as of the following commit from 2023-05-09:
29   https://github.com/unicode-org/message-format-wg/commit/194f6efcec5bf396df36a19bd6fa78d1fa2e0867
30 
31 */
32 
33 /*
34   Transcribed from https://github.com/messageformat/messageformat/blob/main/packages/mf2-messageformat/src/__fixtures/test-messages.json
35 https://github.com/messageformat/messageformat/commit/6656c95d66414da29a332a6f5bbb225371f2b9a3
36 
37 */
jsonTests(IcuTestErrorCode & errorCode)38 void TestMessageFormat2::jsonTests(IcuTestErrorCode& errorCode) {
39     TestCase::Builder testBuilder;
40     testBuilder.setName("jsonTests");
41 
42     TestCase test = testBuilder.setPattern("hello")
43         .setExpected("hello")
44         .build();
45     TestUtils::runTestCase(*this, test, errorCode);
46 
47     test = testBuilder.setPattern("hello {|world|}")
48                                 .setExpected("hello world")
49                                 .build();
50     TestUtils::runTestCase(*this, test, errorCode);
51 
52     test = testBuilder.setPattern("hello {||}")
53                                 .setExpected("hello ")
54                                 .build();
55     TestUtils::runTestCase(*this, test, errorCode);
56 
57     test = testBuilder.setPattern("hello {$place}")
58                                 .setExpected("hello world")
59                                 .setArgument("place", "world")
60                                 .build();
61     TestUtils::runTestCase(*this, test, errorCode);
62 
63     test = testBuilder.setPattern("hello {$place-.}")
64                                 .setExpected("hello world")
65                                 .setArgument("place-.", "world")
66                                 .build();
67     TestUtils::runTestCase(*this, test, errorCode);
68 
69     test = testBuilder.setPattern("hello {$place}")
70                                 .setExpected("hello {$place}")
71                                 .clearArguments()
72                                 .setExpectedError(U_MF_UNRESOLVED_VARIABLE_ERROR)
73                                 .build();
74     TestUtils::runTestCase(*this, test, errorCode);
75 
76     test = testBuilder.setPattern("{$one} and {$two}")
77                                 .setExpected("1.3 and 4.2")
78                                 .setExpectSuccess()
79                                 .setArgument("one", 1.3)
80                                 .setArgument("two", 4.2)
81                                 .build();
82     TestUtils::runTestCase(*this, test, errorCode);
83     testBuilder.setArgument("one", "1.3").setArgument("two", "4.2");
84     test = testBuilder.build();
85     TestUtils::runTestCase(*this, test, errorCode);
86 
87     test = testBuilder.setPattern("{$one} et {$two}")
88                                 .setExpected("1,3 et 4,2")
89                                 .setLocale(Locale("fr"))
90                                 .setArgument("one", 1.3)
91                                 .setArgument("two", 4.2)
92                                 .build();
93     TestUtils::runTestCase(*this, test, errorCode);
94 
95     test = testBuilder.setPattern("hello {|4.2| :number}")
96                                 .setExpected("hello 4.2")
97                                 .setLocale(Locale("en"))
98                                 .build();
99     TestUtils::runTestCase(*this, test, errorCode);
100 
101     test = testBuilder.setPattern("hello {|foo| :number}")
102                                 .setExpected("hello {|foo|}")
103                                 .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
104                                 .build();
105     TestUtils::runTestCase(*this, test, errorCode);
106 
107     test = testBuilder.setPattern("hello {:number}")
108                                 .setExpected("hello {:number}")
109                                 .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
110                                 .build();
111     TestUtils::runTestCase(*this, test, errorCode);
112 
113 
114     test = testBuilder.setPattern("hello {|4.2| :number minimumFractionDigits=2}")
115                                 .setExpectSuccess()
116                                 .setExpected("hello 4.20")
117                                 .build();
118     TestUtils::runTestCase(*this, test, errorCode);
119 
120     test = testBuilder.setPattern("hello {|4.2| :number minimumFractionDigits=|2|}")
121                                 .setExpected("hello 4.20")
122                                 .build();
123     TestUtils::runTestCase(*this, test, errorCode);
124 
125     test = testBuilder.setPattern("hello {|4.2| :number minimumFractionDigits=$foo}")
126                                 .setExpected("hello 4.20")
127                                 .setArgument("foo", (int64_t) 2)
128                                 .build();
129     TestUtils::runTestCase(*this, test, errorCode);
130 
131     test = testBuilder.setPattern(".local $foo = {bar} {{bar {$foo}}}")
132                                 .setExpected("bar bar")
133                                 .build();
134     TestUtils::runTestCase(*this, test, errorCode);
135 
136     test = testBuilder.setPattern(".local $foo = {|bar|} {{bar {$foo}}}")
137                                 .setExpected("bar bar")
138                                 .build();
139     TestUtils::runTestCase(*this, test, errorCode);
140 
141     test = testBuilder.setPattern(".local $foo = {|bar|} {{bar {$foo}}}")
142                                 .setExpected("bar bar")
143                                 .setArgument("foo", "foo")
144                                 .build();
145     TestUtils::runTestCase(*this, test, errorCode);
146 
147     test = testBuilder.setPattern(".local $foo = {$bar} {{bar {$foo}}}")
148                                 .setExpected("bar foo")
149                                 .setArgument("bar", "foo")
150                                 .build();
151     TestUtils::runTestCase(*this, test, errorCode);
152 
153     test = testBuilder.setPattern(".local $foo = {$bar :number} {{bar {$foo}}}")
154                                 .setExpected("bar 4.2")
155                                 .setArgument("bar", 4.2)
156                                 .build();
157     TestUtils::runTestCase(*this, test, errorCode);
158 
159     test = testBuilder.setPattern(".local $foo = {$bar :number minimumFractionDigits=2} {{bar {$foo}}}")
160                                 .setExpected("bar 4.20")
161                                 .setArgument("bar", 4.2)
162                                 .build();
163     TestUtils::runTestCase(*this, test, errorCode);
164 
165     test = testBuilder.setPattern(".local $foo = {$bar :number} {{bar {$foo}}}")
166                                 .setExpected("bar {$bar}")
167                                 .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
168                                 .setArgument("bar", "foo")
169                                 .build();
170     TestUtils::runTestCase(*this, test, errorCode);
171 
172     test = testBuilder.setPattern(".local $foo = {$baz} .local $bar = {$foo} {{bar {$bar}}}")
173                                 .setExpectSuccess()
174                                 .setExpected("bar foo")
175                                 .setArgument("baz", "foo")
176                                 .build();
177     TestUtils::runTestCase(*this, test, errorCode);
178 
179     test = testBuilder.setPattern(".local $foo = {$foo} {{bar {$foo}}}")
180                                 .setExpectedError(U_MF_DUPLICATE_DECLARATION_ERROR)
181                                 .setExpected("bar foo")
182                                 .setArgument("foo", "foo")
183                                 .build();
184     TestUtils::runTestCase(*this, test, errorCode);
185 
186     // TODO(duplicates): currently the expected output is based on using
187     // the last definition of the duplicate-declared variable;
188     // perhaps it's better to remove all declarations for $foo before formatting.
189     // however if https://github.com/unicode-org/message-format-wg/pull/704 lands,
190     // it'll be a moot point since the output will be expected to be the fallback string
191     // (This applies to the expected output for all the U_DUPLICATE_DECLARATION_ERROR tests)
192     test = testBuilder.setPattern(".local $foo = {$foo} .local $foo = {42} {{bar {$foo}}}")
193                                 .setExpectedError(U_MF_DUPLICATE_DECLARATION_ERROR)
194                                 .setArgument("foo", "foo")
195                                 .setExpected("bar 42")
196                                 .build();
197     TestUtils::runTestCase(*this, test, errorCode);
198 
199     test = testBuilder.setPattern(".local $foo = {42} .local $foo = {$foo} {{bar {$foo}}}")
200                                 .setExpectedError(U_MF_DUPLICATE_DECLARATION_ERROR)
201                                 .setExpected("bar 42")
202                                 .setArgument("foo", "foo")
203                                 .build();
204     TestUtils::runTestCase(*this, test, errorCode);
205 
206     // see TODO(duplicates)
207     test = testBuilder.setPattern(".local $foo = {:unknown} .local $foo = {42} {{bar {$foo}}}")
208                                 .setExpectedError(U_MF_DUPLICATE_DECLARATION_ERROR)
209                                 .setExpected("bar 42")
210                                 .build();
211     TestUtils::runTestCase(*this, test, errorCode);
212 
213     // see TODO(duplicates)
214     test = testBuilder.setPattern(".local $x = {42} .local $y = {$x} .local $x = {13} {{{$x} {$y}}}")
215                                 .setExpectedError(U_MF_DUPLICATE_DECLARATION_ERROR)
216                                 .setExpected("13 42")
217                                 .build();
218     TestUtils::runTestCase(*this, test, errorCode);
219 
220 /*
221   Shouldn't this be "bar {$bar}"?
222 
223     test = testBuilder.setPattern(".local $foo = {$bar} .local $bar = {$baz} {{bar {$foo}}}")
224                                 .setExpected("bar foo")
225                                 .setArgument("baz", "foo", errorCode)
226                                 .build();
227     TestUtils::runTestCase(*this, test, errorCode);
228 */
229 
230     test = testBuilder.setPattern(".match {$foo :string}  |1| {{one}}  * {{other}}")
231                                 .setExpected("one")
232                                 .setExpectSuccess()
233                                 .setArgument("foo", (int64_t) 1)
234                                 .build();
235     TestUtils::runTestCase(*this, test, errorCode);
236 
237     test = testBuilder.setPattern(".match {$foo :number}  1 {{one}}  * {{other}}")
238                                 .setExpected("one")
239                                 .setArgument("foo", (int64_t) 1)
240                                 .build();
241     TestUtils::runTestCase(*this, test, errorCode);
242 
243 /*
244   This case can't be tested without a way to set the "foo" argument to null
245 
246     test = testBuilder.setPattern(".match {$foo :number}  1 {{one}}  * {{other}}")
247                                 .setExpected("other")
248                                 .setArgument("foo", "", errorCode)
249                                 .setExpectedError(U_MF_UNRESOLVED_VARIABLE_ERROR)
250                                 .build();
251     TestUtils::runTestCase(*this, test, errorCode);
252 */
253 
254     test = testBuilder.setPattern(".match {$foo :number}  one {{one}}  * {{other}}")
255                                 .setExpected("one")
256                                 .setArgument("foo", (int64_t) 1)
257                                 .build();
258     TestUtils::runTestCase(*this, test, errorCode);
259 
260     test = testBuilder.setPattern(".match {$foo :number}  1 {{=1}}  one {{one}}  * {{other}}")
261                                 .setExpected("=1")
262                                 .setArgument("foo", "1")
263                                 .build();
264     TestUtils::runTestCase(*this, test, errorCode);
265 
266     test = testBuilder.setPattern(".match {$foo :number}  1 {{=1}}  one {{one}}  * {{other}}")
267                                 .setExpected("=1")
268                                 .setArgument("foo", (int64_t) 1)
269                                 .build();
270     TestUtils::runTestCase(*this, test, errorCode);
271 
272     test = testBuilder.setPattern(".match {$foo :number}  one {{one}}  1 {{=1}}  * {{other}}")
273                                 .setExpected("=1")
274                                 .setArgument("foo", (int64_t) 1)
275                                 .build();
276     TestUtils::runTestCase(*this, test, errorCode);
277 
278     test = testBuilder.setPattern(".match {$foo :number} {$bar :number}  one one {{one one}}  one * {{one other}}  * * {{other}}")
279                                 .setExpected("one one")
280                                 .setArgument("foo", (int64_t) 1)
281                                 .setArgument("bar", (int64_t) 1)
282                                 .build();
283     TestUtils::runTestCase(*this, test, errorCode);
284 
285     test = testBuilder.setPattern(".match {$foo :number} {$bar :number}  one one {{one one}}  one * {{one other}}  * * {{other}}")
286                                 .setExpected("one other")
287                                 .setArgument("foo", (int64_t) 1)
288                                 .setArgument("bar", (int64_t) 2)
289                                 .build();
290     TestUtils::runTestCase(*this, test, errorCode);
291 
292     test = testBuilder.setPattern(".match {$foo :number} {$bar :number}  one one {{one one}}  one * {{one other}}  * * {{other}}")
293                                 .setExpected("other")
294                                 .setArgument("foo", (int64_t) 2)
295                                 .setArgument("bar", (int64_t) 2)
296                                 .build();
297     TestUtils::runTestCase(*this, test, errorCode);
298 
299     test = testBuilder.setPattern(".match {|foo| :string} *{{foo}}")
300                       .setExpectSuccess()
301                       .setExpected("foo")
302                       .build();
303     TestUtils::runTestCase(*this, test, errorCode);
304 
305 
306     test = testBuilder.setPattern(".local $foo = {$bar :number} .match {$foo}  one {{one}}  * {{other}}")
307                                 .setExpected("one")
308                                 .setArgument("bar", (int64_t) 1)
309                                 .build();
310     TestUtils::runTestCase(*this, test, errorCode);
311 
312     test = testBuilder.setPattern(".local $foo = {$bar :number} .match {$foo}  one {{one}}  * {{other}}")
313                                 .setExpected("other")
314                                 .setArgument("bar", (int64_t) 2)
315                                 .build();
316     TestUtils::runTestCase(*this, test, errorCode);
317 
318     test = testBuilder.setPattern(".local $bar = {$none} .match {$foo :number}  one {{one}}  * {{{$bar}}}")
319                                 .setExpected("one")
320                                 .setArgument("foo", (int64_t) 1)
321                                 .build();
322     TestUtils::runTestCase(*this, test, errorCode);
323 
324 /*
325   Note: this differs from https://github.com/messageformat/messageformat/blob/e0087bff312d759b67a9129eac135d318a1f0ce7/packages/mf2-messageformat/src/__fixtures/test-messages.json#L197
326 
327   The expected value in the test as defined there is "{$bar}".
328   The value should be "{$none}" per
329 https://github.com/unicode-org/message-format-wg/blob/main/spec/formatting.md#fallback-resolution -
330 " an error occurs in an expression with a variable operand and the variable refers to a local declaration, the fallback value is formatted based on the expression on the right-hand side of the declaration, rather than the expression in the selector or pattern."
331 */
332     test = testBuilder.setPattern(".local $bar = {$none} .match {$foo :number}  one {{one}}  * {{{$bar}}}")
333                                 .setExpected("{$none}")
334                                 .setArgument("foo", (int64_t) 2)
335                                 .setExpectedError(U_MF_UNRESOLVED_VARIABLE_ERROR)
336                                 .build();
337     TestUtils::runTestCase(*this, test, errorCode);
338 
339     // Missing '$' before `bar`
340     test = testBuilder.setPattern(".local bar = {|foo|} {{{$bar}}}")
341                                 .setExpected("{$bar}")
342                                 .clearArguments()
343                                 .setExpectedError(U_MF_SYNTAX_ERROR)
344                                 .build();
345     TestUtils::runTestCase(*this, test, errorCode);
346 
347     // Missing '=' after `bar`
348     /*
349       Spec is ambiguous -- see https://github.com/unicode-org/message-format-wg/issues/703 --
350       but we choose the '{$bar}' interpretation for the partial result
351      */
352     test = testBuilder.setPattern(".local $bar {|foo|} {{{$bar}}}")
353                                 .setExpected("{$bar}")
354                                 .setExpectedError(U_MF_SYNTAX_ERROR)
355                                 .build();
356     TestUtils::runTestCase(*this, test, errorCode);
357 
358     // Missing '{'/'}' around `foo`
359     test = testBuilder.setPattern(".local $bar = |foo| {{{$bar}}}")
360                                 .setExpected("{$bar}")
361                                 .setExpectedError(U_MF_SYNTAX_ERROR)
362                                 .build();
363     TestUtils::runTestCase(*this, test, errorCode);
364 
365     // Markup is ignored when formatting to string
366     test = testBuilder.setPattern("{#tag}")
367                                 .setExpectSuccess()
368                                 .setExpected("")
369                                 .build();
370     TestUtils::runTestCase(*this, test, errorCode);
371 
372     test = testBuilder.setPattern("{#tag/}")
373                                 .setExpected("")
374                                 .build();
375     TestUtils::runTestCase(*this, test, errorCode);
376 
377     test = testBuilder.setPattern("{/tag}")
378                                 .setExpected("")
379                                 .build();
380     TestUtils::runTestCase(*this, test, errorCode);
381 
382     test = testBuilder.setPattern("{#tag}content")
383                       .setExpected("content")
384                       .build();
385     TestUtils::runTestCase(*this, test, errorCode);
386 
387     test = testBuilder.setPattern("{#tag}content{/tag}")
388                       .setExpected("content")
389                       .build();
390     TestUtils::runTestCase(*this, test, errorCode);
391 
392     test = testBuilder.setPattern("{/tag}content")
393                       .setExpected("content")
394                       .build();
395     TestUtils::runTestCase(*this, test, errorCode);
396 
397     test = testBuilder.setPattern("{#tag foo=bar}")
398                       .setExpected("")
399                       .build();
400     TestUtils::runTestCase(*this, test, errorCode);
401 
402     test = testBuilder.setPattern("{#tag foo=bar/}")
403                       .setExpected("")
404                       .build();
405     TestUtils::runTestCase(*this, test, errorCode);
406 
407     test = testBuilder.setPattern("{#tag foo=|foo| bar=$bar}")
408                       .setArgument("bar", "b a r")
409                       .setExpected("")
410                       .build();
411     TestUtils::runTestCase(*this, test, errorCode);
412 
413     test = testBuilder.setPattern("{/tag foo=bar}")
414                       .setExpected("")
415                       .build();
416     TestUtils::runTestCase(*this, test, errorCode);
417 
418     test = testBuilder.setPattern("no braces")
419                       .setExpected("no braces")
420                       .build();
421     TestUtils::runTestCase(*this, test, errorCode);
422 
423     test = testBuilder.setPattern("no braces {$foo}")
424                       .setExpected("no braces 2")
425                       .setArgument("foo", (int64_t) 2)
426                       .build();
427     TestUtils::runTestCase(*this, test, errorCode);
428 
429     test = testBuilder.setPattern("{{missing end brace")
430                       .setExpected("missing end brace")
431                       .setExpectedError(U_MF_SYNTAX_ERROR)
432                       .build();
433     TestUtils::runTestCase(*this, test, errorCode);
434 
435     test = testBuilder.setPattern("{{missing end {$brace")
436                       .setExpected("missing end {$brace}")
437                       .setExpectedError(U_MF_SYNTAX_ERROR)
438                       .build();
439     TestUtils::runTestCase(*this, test, errorCode);
440 
441     test = testBuilder.setPattern("{extra} content")
442                       .setExpected("extra content")
443                       .setExpectSuccess()
444                       .build();
445     TestUtils::runTestCase(*this, test, errorCode);
446 
447     test = testBuilder.setPattern("{{extra}} content")
448                       .setExpected("extra") // Everything after the closing '{{' should be ignored
449                                             // per the `complex-body- production in the grammar
450                       .setExpectedError(U_MF_SYNTAX_ERROR)
451                       .build();
452     TestUtils::runTestCase(*this, test, errorCode);
453 
454     // "empty \0xfffd"
455     static constexpr UChar emptyWithReplacement[] = {
456         0x65, 0x6D, 0x70, 0x74, 0x79, 0x20, REPLACEMENT, 0
457     };
458 
459     test = testBuilder.setPattern("empty { }")
460                       .setExpectedError(U_MF_SYNTAX_ERROR)
461                       .setExpected(UnicodeString(emptyWithReplacement))
462                       .build();
463     TestUtils::runTestCase(*this, test, errorCode);
464 
465     test = testBuilder.setPattern("{{bad {:}}")
466                       .setExpected("bad {:}")
467                       .setExpectedError(U_MF_SYNTAX_ERROR)
468                       .build();
469     TestUtils::runTestCase(*this, test, errorCode);
470 
471     test = testBuilder.setPattern("unquoted {literal}")
472                       .setExpected("unquoted literal")
473                       .setExpectSuccess()
474                       .build();
475     TestUtils::runTestCase(*this, test, errorCode);
476 
477     test = testBuilder.setPattern(CharsToUnicodeString("bad {\\u0000placeholder}"))
478                       .clearExpected()
479                       .setExpectedError(U_MF_SYNTAX_ERROR)
480                       .build();
481     TestUtils::runTestCase(*this, test, errorCode);
482 
483     test = testBuilder.setPattern("no-equal {|42| :number minimumFractionDigits 2}")
484                       .setExpected("no-equal 42.00")
485                       .setExpectedError(U_MF_SYNTAX_ERROR)
486                       .build();
487     TestUtils::runTestCase(*this, test, errorCode);
488 
489     test = testBuilder.setPattern("bad {:placeholder option=}")
490                       .setExpected("bad {:placeholder}")
491                       .setExpectedError(U_MF_SYNTAX_ERROR)
492                       .build();
493     TestUtils::runTestCase(*this, test, errorCode);
494 
495     test = testBuilder.setPattern("bad {:placeholder option value}")
496                       .setExpected("bad {:placeholder}")
497                       .setExpectedError(U_MF_SYNTAX_ERROR)
498                       .build();
499     TestUtils::runTestCase(*this, test, errorCode);
500 
501     test = testBuilder.setPattern("bad {:placeholder option}")
502                       .setExpected("bad {:placeholder}")
503                       .setExpectedError(U_MF_SYNTAX_ERROR)
504                       .build();
505     TestUtils::runTestCase(*this, test, errorCode);
506 
507     test = testBuilder.setPattern("bad {$placeholder option}")
508                       .clearExpected()
509                       .setExpectedError(U_MF_SYNTAX_ERROR)
510                       .build();
511     TestUtils::runTestCase(*this, test, errorCode);
512 
513     test = testBuilder.setPattern("no {$placeholder end")
514                       .clearExpected()
515                       .setExpectedError(U_MF_SYNTAX_ERROR)
516                       .build();
517     TestUtils::runTestCase(*this, test, errorCode);
518 
519     test = testBuilder.setPattern(".match {}  * {{foo}}")
520                       .clearExpected()
521                       .setExpectedError(U_MF_SYNTAX_ERROR)
522                       .build();
523     TestUtils::runTestCase(*this, test, errorCode);
524 
525     // "empty \0xfffd"
526     static constexpr UChar replacement[] = {
527         REPLACEMENT, 0
528     };
529 
530     test = testBuilder.setPattern(".match {#foo}  * {{foo}}")
531                       .setExpected(UnicodeString(replacement))
532                       .setExpectedError(U_MF_SYNTAX_ERROR)
533                       .build();
534     TestUtils::runTestCase(*this, test, errorCode);
535 
536     test = testBuilder.setPattern(".match  * {{foo}}")
537                       .clearExpected()
538                       .setExpectedError(U_MF_SYNTAX_ERROR)
539                       .build();
540     TestUtils::runTestCase(*this, test, errorCode);
541 
542     test = testBuilder.setPattern(".match {|x|}  * foo")
543                       .clearExpected()
544                       .setExpectedError(U_MF_SYNTAX_ERROR)
545                       .build();
546     TestUtils::runTestCase(*this, test, errorCode);
547 
548     test = testBuilder.setPattern(".match {|x|}  * {{foo}} extra")
549                       .clearExpected()
550                       .setExpectedError(U_MF_SYNTAX_ERROR)
551                       .build();
552     TestUtils::runTestCase(*this, test, errorCode);
553 
554     test = testBuilder.setPattern(".match |x|  * {{foo}}")
555                       .clearExpected()
556                       .setExpectedError(U_MF_SYNTAX_ERROR)
557                       .build();
558     TestUtils::runTestCase(*this, test, errorCode);
559 
560     test = testBuilder.setPattern(".match {$foo :number}  * * {{foo}}")
561                       .clearExpected()
562                       .setExpectedError(U_MF_VARIANT_KEY_MISMATCH_ERROR)
563                       .build();
564     TestUtils::runTestCase(*this, test, errorCode);
565 
566     test = testBuilder.setPattern(".match {$foo :number} {$bar :number}  * {{foo}}")
567                       .clearExpected()
568                       .setExpectedError(U_MF_VARIANT_KEY_MISMATCH_ERROR)
569                       .build();
570     TestUtils::runTestCase(*this, test, errorCode);
571 }
572 
573 
574 /*
575 From https://github.com/unicode-org/message-format-wg/tree/main/test ,
576 alpha version
577 
578 */
runSpecTests(IcuTestErrorCode & errorCode)579 void TestMessageFormat2::runSpecTests(IcuTestErrorCode& errorCode) {
580     TestCase::Builder testBuilder;
581     testBuilder.setName("specTests");
582 
583     TestCase test = testBuilder.setPattern("hello {world}")
584         .setExpected("hello world")
585         .build();
586     TestUtils::runTestCase(*this, test, errorCode);
587 
588     test = testBuilder.setPattern("hello { world\t\n}")
589                                 .setExpected("hello world")
590                                 .build();
591     TestUtils::runTestCase(*this, test, errorCode);
592 
593     // TODO:
594     // For some reason, this test fails on Windows if
595     // `pattern` is replaced with "hello {\\u3000world\r}".
596     UnicodeString pattern("hello {");
597     pattern += ((UChar32) 0x3000);
598     pattern += "world\r}";
599     test = testBuilder.setPattern(pattern)
600                                 .setExpected("hello world")
601                                 .build();
602     TestUtils::runTestCase(*this, test, errorCode);
603 
604     test = testBuilder.setPattern("hello {$place-.}")
605                                 .setExpected("hello world")
606                                 .setArgument("place-.", "world")
607                                 .build();
608     TestUtils::runTestCase(*this, test, errorCode);
609 
610     test = testBuilder.setPattern(".input {$foo} .local $bar = {$foo} {{bar {$bar}}}")
611                                 .setExpected("bar foo")
612                                 .setArgument("foo", "foo")
613                                 .build();
614     TestUtils::runTestCase(*this, test, errorCode);
615 
616     test = testBuilder.setPattern(".input {$foo} .local $bar = {$foo} {{bar {$bar}}}")
617                                 .setExpected("bar foo")
618                                 .setArgument("foo", "foo")
619                                 .build();
620     TestUtils::runTestCase(*this, test, errorCode);
621 
622     test = testBuilder.setPattern(".local $x = {42} .local $y = {$x} {{{$x} {$y}}}")
623                                  .setExpected("42 42")
624                                  .build();
625     TestUtils::runTestCase(*this, test, errorCode);
626 
627     test = testBuilder.setPattern("{#tag}")
628                                  .setExpected("")
629                                  .build();
630     TestUtils::runTestCase(*this, test, errorCode);
631 
632     test = testBuilder.setPattern("{#tag}content")
633                                  .setExpected("content")
634                                  .build();
635     TestUtils::runTestCase(*this, test, errorCode);
636 
637     test = testBuilder.setPattern("{#ns:tag}content{/ns:tag}")
638                                  .setExpected("content")
639                                  .build();
640     TestUtils::runTestCase(*this, test, errorCode);
641 
642     test = testBuilder.setPattern("{/tag}content")
643                                  .setExpected("content")
644                                  .build();
645     TestUtils::runTestCase(*this, test, errorCode);
646 
647     test = testBuilder.setPattern("{#tag foo=bar}")
648                                  .setExpected("")
649                                  .build();
650     TestUtils::runTestCase(*this, test, errorCode);
651 
652     test = testBuilder.setPattern("{#tag a:foo=|foo| b:bar=$bar}")
653                                  .setArgument("bar", "b a r")
654                                  .setExpected("")
655                                  .build();
656     TestUtils::runTestCase(*this, test, errorCode);
657 
658     /*
659     test = testBuilder.setPattern("{42 @foo @bar=13}")
660                                  .clearArguments()
661                                  .setExpected("42")
662                                  .build();
663     TestUtils::runTestCase(*this, test, errorCode);
664 
665     test = testBuilder.setPattern("{42 @foo=$bar}")
666                                  .setExpected("42")
667                                  .build();
668     TestUtils::runTestCase(*this, test, errorCode);
669     */
670 
671     test = testBuilder.setPattern("foo {+reserved}")
672                                  .setExpected("foo {+}")
673                                  .setExpectedError(U_MF_UNSUPPORTED_EXPRESSION_ERROR)
674                                  .build();
675     TestUtils::runTestCase(*this, test, errorCode);
676 
677     test = testBuilder.setPattern("foo {&private}")
678                                  .setExpected("foo {&}")
679                                  .setExpectedError(U_MF_UNSUPPORTED_EXPRESSION_ERROR)
680                                  .build();
681     TestUtils::runTestCase(*this, test, errorCode);
682 
683     test = testBuilder.setPattern("foo {?reserved @a @b=$c}")
684                                  .setExpected("foo {?}")
685                                  .setExpectedError(U_MF_UNSUPPORTED_EXPRESSION_ERROR)
686                                  .build();
687     TestUtils::runTestCase(*this, test, errorCode);
688 
689     test = testBuilder.setPattern(".foo {42} {{bar}}")
690                                  .setExpected("bar")
691                                  .setExpectedError(U_MF_UNSUPPORTED_STATEMENT_ERROR)
692                                  .build();
693     TestUtils::runTestCase(*this, test, errorCode);
694 
695     test = testBuilder.setPattern(".foo {42}{{bar}}")
696                                  .setExpected("bar")
697                                  .setExpectedError(U_MF_UNSUPPORTED_STATEMENT_ERROR)
698                                  .build();
699     TestUtils::runTestCase(*this, test, errorCode);
700 
701     test = testBuilder.setPattern(".foo |}lit{| {42}{{bar}}")
702                                  .setExpected("bar")
703                                  .setExpectedError(U_MF_UNSUPPORTED_STATEMENT_ERROR)
704                                  .build();
705     TestUtils::runTestCase(*this, test, errorCode);
706 
707     /* var2 is implicitly declared and can't be overridden by the second `.input` */
708     test = testBuilder.setPattern(".input {$var :number minimumFractionDigits=$var2} .input {$var2 :number minimumFractionDigits=5} {{{$var} {$var2}}}")
709                                 .setExpectedError(U_MF_DUPLICATE_DECLARATION_ERROR)
710                                 .setArgument("var", (int64_t) 1)
711                                 .setArgument("var2", (int64_t) 3)
712         // Note: the more "correct" fallback output seems like it should be "1.000 3" (ignoring the
713         // overriding .input binding of $var2) but that's hard to achieve
714         // as so-called "implicit declarations" can only be detected after parsing, at which
715         // point the data model can't be modified.
716         // Probably this is going to change anyway so that any data model error gets replaced
717         // with a fallback for the whole message.
718                                 .setExpected("1.000 3.00000")
719                                 .build();
720     TestUtils::runTestCase(*this, test, errorCode);
721 
722     /* var2 is implicitly declared and can't be overridden by the second `.local` */
723     test = testBuilder.setPattern(".local $var = {$var2} .local $var2 = {1} {{{$var} {$var2}}}")
724                                 .setExpectedError(U_MF_DUPLICATE_DECLARATION_ERROR)
725                                 .setArgument("var2", (int64_t) 5)
726         // Same comment as above about the output
727                                 .setExpected("5 1")
728                                 .build();
729     TestUtils::runTestCase(*this, test, errorCode);
730 
731     /* var2 is provided as an argument but not used, and should have no effect on formatting */
732     test = testBuilder.setPattern(".local $var2 = {1} {{{$var2}}}")
733                                 .setExpectSuccess()
734                                 .setArgument("var2", (int64_t) 5)
735                                 .setExpected("1")
736                                 .build();
737     TestUtils::runTestCase(*this, test, errorCode);
738 
739     // Functions: integer
740     test = testBuilder.setPattern("hello {4.2 :integer}")
741                                 .setExpectSuccess()
742                                 .setExpected("hello 4")
743                                 .build();
744     TestUtils::runTestCase(*this, test, errorCode);
745 
746     test = testBuilder.setPattern("hello {-4.20 :integer}")
747                                 .setExpectSuccess()
748                                 .setExpected("hello -4")
749                                 .build();
750     TestUtils::runTestCase(*this, test, errorCode);
751 
752     test = testBuilder.setPattern("hello {0.42e+1 :integer}")
753                                 .setExpectSuccess()
754                                 .setExpected("hello 4")
755                                 .build();
756     TestUtils::runTestCase(*this, test, errorCode);
757 
758     test = testBuilder.setPattern(".match {$foo :integer} one {{one}} * {{other}}")
759                                 .setArgument("foo", 1.2)
760                                 .setExpectSuccess()
761                                 .setExpected("one")
762                                 .build();
763     TestUtils::runTestCase(*this, test, errorCode);
764 
765     // Functions: number (formatting)
766 
767     // TODO: Need more test coverage for all the :number and other built-in
768     // function options
769 
770     test = testBuilder.setPattern("hello {4.2 :number}")
771                                 .setExpectSuccess()
772                                 .setExpected("hello 4.2")
773                                 .build();
774     TestUtils::runTestCase(*this, test, errorCode);
775 
776     test = testBuilder.setPattern("hello {-4.20 :number}")
777                                 .setExpectSuccess()
778                                 .setExpected("hello -4.2")
779                                 .build();
780     TestUtils::runTestCase(*this, test, errorCode);
781 
782     test = testBuilder.setPattern("hello {0.42e+1 :number}")
783                                 .setExpectSuccess()
784                                 .setExpected("hello 4.2")
785                                 .build();
786     TestUtils::runTestCase(*this, test, errorCode);
787 
788     test = testBuilder.setPattern("hello {foo :number}")
789                                 .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
790                                 .setExpected("hello {|foo|}")
791                                 .build();
792     TestUtils::runTestCase(*this, test, errorCode);
793 
794     test = testBuilder.setPattern("hello {:number}")
795                                 .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
796                                 .setExpected("hello {:number}")
797                                 .build();
798     TestUtils::runTestCase(*this, test, errorCode);
799 
800     test = testBuilder.setPattern("hello {4.2 :number minimumFractionDigits=2}")
801                                 .setExpectSuccess()
802                                 .setExpected("hello 4.20")
803                                 .build();
804     TestUtils::runTestCase(*this, test, errorCode);
805 
806     test = testBuilder.setPattern("hello {4.2 :number minimumFractionDigits=|2|}")
807                                 .setExpectSuccess()
808                                 .setExpected("hello 4.20")
809                                 .build();
810     TestUtils::runTestCase(*this, test, errorCode);
811 
812     test = testBuilder.setPattern("hello {4.2 :number minimumFractionDigits=$foo}")
813                                 .setExpectSuccess()
814                                 .setArgument("foo", (int64_t) 2)
815                                 .setExpected("hello 4.20")
816                                 .build();
817     TestUtils::runTestCase(*this, test, errorCode);
818 
819     test = testBuilder.setPattern("hello {|4.2| :number minimumFractionDigits=$foo}")
820                                 .setExpectSuccess()
821                                 .setArgument("foo", (int64_t) 2)
822                                 .setExpected("hello 4.20")
823                                 .build();
824     TestUtils::runTestCase(*this, test, errorCode);
825 
826     test = testBuilder.setPattern(".local $foo = {$bar :number} {{bar {$foo}}}")
827                                 .setExpectSuccess()
828                                 .setArgument("bar", 4.2)
829                                 .setExpected("bar 4.2")
830                                 .build();
831     TestUtils::runTestCase(*this, test, errorCode);
832 
833     test = testBuilder.setPattern(".local $foo = {$bar :number minimumFractionDigits=2} {{bar {$foo}}}")
834                                 .setExpectSuccess()
835                                 .setArgument("bar", 4.2)
836                                 .setExpected("bar 4.20")
837                                 .build();
838     TestUtils::runTestCase(*this, test, errorCode);
839 
840     /*
841       This is underspecified -- commented out until https://github.com/unicode-org/message-format-wg/issues/738
842       is resolved
843 
844     test = testBuilder.setPattern(".local $foo = {$bar :number minimumFractionDigits=foo} {{bar {$foo}}}")
845                                 .setExpectedError(U_MF_FORMATTING_ERROR)
846                                 .setArgument("bar", 4.2)
847                                 .setExpected("bar {$bar}")
848                                 .build();
849     TestUtils::runTestCase(*this, test, errorCode);
850     */
851 
852     test = testBuilder.setPattern(".local $foo = {$bar :number} {{bar {$foo}}}")
853                                   .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
854                                   .setArgument("bar", "foo")
855                                   .setExpected("bar {$bar}")
856                                   .build();
857     TestUtils::runTestCase(*this, test, errorCode);
858 
859     test = testBuilder.setPattern(".input {$foo :number} {{bar {$foo}}}")
860                                   .setExpectSuccess()
861                                   .setArgument("foo", 4.2)
862                                   .setExpected("bar 4.2")
863                                   .build();
864     TestUtils::runTestCase(*this, test, errorCode);
865 
866     test = testBuilder.setPattern(".input {$foo :number minimumFractionDigits=2} {{bar {$foo}}}")
867                                   .setExpectSuccess()
868                                   .setArgument("foo", 4.2)
869                                   .setExpected("bar 4.20")
870                                   .build();
871     TestUtils::runTestCase(*this, test, errorCode);
872 
873     /*
874     This is underspecified -- commented out until https://github.com/unicode-org/message-format-wg/issues/738
875       is resolved
876 
877     test = testBuilder.setPattern(".input {$foo :number minimumFractionDigits=foo} {{bar {$foo}}}")
878                                 .setExpectedError(U_MF_FORMATTING_ERROR)
879                                 .setArgument("foo", 4.2)
880                                 .setExpected("bar {$foo}")
881                                 .build();
882     TestUtils::runTestCase(*this, test, errorCode);
883     */
884 
885     test = testBuilder.setPattern(".input {$foo :number} {{bar {$foo}}}")
886                                   .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
887                                   .setArgument("foo", "foo")
888                                   .setExpected("bar {$foo}")
889                                   .build();
890     TestUtils::runTestCase(*this, test, errorCode);
891 
892     // Functions: number (selection)
893 
894     test = testBuilder.setPattern(".match {$foo :number} one {{one}} * {{other}}")
895                                   .setExpectSuccess()
896                                   .setArgument("foo", (int64_t) 1)
897                                   .setExpected("one")
898                                   .build();
899     TestUtils::runTestCase(*this, test, errorCode);
900 
901     test = testBuilder.setPattern(".match {$foo :number} 1 {{=1}} one {{one}} * {{other}}")
902                                   .setExpectSuccess()
903                                   .setArgument("foo", (int64_t) 1)
904                                   .setExpected("=1")
905                                   .build();
906     TestUtils::runTestCase(*this, test, errorCode);
907 
908     test = testBuilder.setPattern(".match {$foo :number} one {{one}} 1 {{=1}} * {{other}}")
909                                   .setExpectSuccess()
910                                   .setArgument("foo", (int64_t) 1)
911                                   .setExpected("=1")
912                                   .build();
913     TestUtils::runTestCase(*this, test, errorCode);
914 
915     test = testBuilder.setPattern(".match {$foo :number} {$bar :number} one one {{one one}} one * {{one other}} * * {{other}}")
916                                   .setExpectSuccess()
917                                   .setArgument("foo", (int64_t) 1)
918                                   .setArgument("bar", (int64_t) 1)
919                                   .setExpected("one one")
920                                   .build();
921     TestUtils::runTestCase(*this, test, errorCode);
922 
923     test = testBuilder.setPattern(".match {$foo :number} {$bar :number} one one {{one one}} one * {{one other}} * * {{other}}")
924                                   .setExpectSuccess()
925                                   .setArgument("foo", (int64_t) 1)
926                                   .setArgument("bar", (int64_t) 2)
927                                   .setExpected("one other")
928                                   .build();
929     TestUtils::runTestCase(*this, test, errorCode);
930 
931     test = testBuilder.setPattern(".match {$foo :number} {$bar :number} one one {{one one}} one * {{one other}} * * {{other}}")
932                                   .setExpectSuccess()
933                                   .setArgument("foo", (int64_t) 2)
934                                   .setArgument("bar", (int64_t) 2)
935                                   .setExpected("other")
936                                   .build();
937     TestUtils::runTestCase(*this, test, errorCode);
938 
939     test = testBuilder.setPattern(".input {$foo :number} .match {$foo} one {{one}} * {{other}}")
940                                   .setExpectSuccess()
941                                   .setArgument("foo", (int64_t) 1)
942                                   .setExpected("one")
943                                   .build();
944     TestUtils::runTestCase(*this, test, errorCode);
945 
946     test = testBuilder.setPattern(".local $foo = {$bar :number} .match {$foo} one {{one}} * {{other}}")
947                                   .setExpectSuccess()
948                                   .setArgument("bar", (int64_t) 1)
949                                   .setExpected("one")
950                                   .build();
951     TestUtils::runTestCase(*this, test, errorCode);
952 
953     test = testBuilder.setPattern(".input {$foo :number} .local $bar = {$foo} .match {$bar} one {{one}} * {{other}}")
954                                   .setExpectSuccess()
955                                   .setArgument("foo", (int64_t) 1)
956                                   .setExpected("one")
957                                   .build();
958     TestUtils::runTestCase(*this, test, errorCode);
959 
960     test = testBuilder.setPattern(".input {$bar :number} .match {$bar} one {{one}} * {{other}}")
961                                   .setExpectSuccess()
962                                   .setArgument("bar", (int64_t) 2)
963                                   .setExpected("other")
964                                   .build();
965     TestUtils::runTestCase(*this, test, errorCode);
966 
967     test = testBuilder.setPattern(".input {$bar} .match {$bar :number} one {{one}} * {{other}}")
968                                   .setExpectSuccess()
969                                   .setArgument("bar", (int64_t) 1)
970                                   .setExpected("one")
971                                   .build();
972     TestUtils::runTestCase(*this, test, errorCode);
973 
974     test = testBuilder.setPattern(".input {$bar} .match {$bar :number} one {{one}} * {{other}}")
975                                   .setExpectSuccess()
976                                   .setArgument("bar", (int64_t) 2)
977                                   .setExpected("other")
978                                   .build();
979     TestUtils::runTestCase(*this, test, errorCode);
980 
981     test = testBuilder.setPattern(".input {$bar} .match {$bar :number} one {{one}} * {{other}}")
982                                   .setExpectSuccess()
983                                   .setArgument("bar", (int64_t) 1)
984                                   .setExpected("one")
985                                   .build();
986     TestUtils::runTestCase(*this, test, errorCode);
987 
988     test = testBuilder.setPattern(".input {$bar} .match {$bar :number} one {{one}} * {{other}}")
989                                   .setExpectSuccess()
990                                   .setArgument("bar", (int64_t) 2)
991                                   .setExpected("other")
992                                   .build();
993     TestUtils::runTestCase(*this, test, errorCode);
994 
995     test = testBuilder.setPattern(".input {$none} .match {$foo :number} one {{one}} * {{{$none}}}")
996                                   .setExpectSuccess()
997                                   .setArgument("foo", (int64_t) 1)
998                                   .setExpected("one")
999                                   .build();
1000     TestUtils::runTestCase(*this, test, errorCode);
1001 
1002     test = testBuilder.setPattern(".local $bar = {$none} .match {$foo :number} one {{one}} * {{{$bar}}}")
1003                                   .setExpectSuccess()
1004                                   .setArgument("foo", (int64_t) 1)
1005                                   .setExpected("one")
1006                                   .build();
1007     TestUtils::runTestCase(*this, test, errorCode);
1008 
1009     test = testBuilder.setPattern(".local $bar = {$none} .match {$foo :number} one {{one}} * {{{$bar}}}")
1010                                   .setExpectedError(U_MF_UNRESOLVED_VARIABLE_ERROR)
1011                                   .setArgument("foo", (int64_t) 2)
1012                                   .setExpected("{$none}")
1013                                   .build();
1014     TestUtils::runTestCase(*this, test, errorCode);
1015 
1016     test = testBuilder.setPattern("{42 :number @foo @bar=13}")
1017                                   .setExpectSuccess()
1018                                   .setExpected("42")
1019                                   .build();
1020     TestUtils::runTestCase(*this, test, errorCode);
1021 
1022     // Neither `ordinal` nor `selectordinal` exists in this spec version
1023     test = testBuilder.setPattern(".match {$foo :ordinal} one {{st}} two {{nd}} few {{rd}} * {{th}}")
1024                                   .setExpectedError(U_MF_UNKNOWN_FUNCTION_ERROR)
1025                                   .setArgument("foo", (int64_t) 1)
1026                                   .setExpected("th")
1027                                   .build();
1028     TestUtils::runTestCase(*this, test, errorCode);
1029 
1030     test = testBuilder.setPattern("hello {42 :ordinal}")
1031                                   .setExpectedError(U_MF_UNKNOWN_FUNCTION_ERROR)
1032                                   .setExpected("hello {|42|}")
1033                                   .build();
1034     TestUtils::runTestCase(*this, test, errorCode);
1035 
1036     test = testBuilder.setPattern(".match {$foo :stringordinal} one {{st}} two {{nd}} few {{rd}} * {{th}}")
1037                                   .setExpectedError(U_MF_UNKNOWN_FUNCTION_ERROR)
1038                                   .setArgument("foo", (int64_t) 1)
1039                                   .setExpected("th")
1040                                   .build();
1041     TestUtils::runTestCase(*this, test, errorCode);
1042 
1043     test = testBuilder.setPattern("hello {42 :stringordinal}")
1044                                   .setExpectedError(U_MF_UNKNOWN_FUNCTION_ERROR)
1045                                   .setExpected("hello {|42|}")
1046                                   .build();
1047     TestUtils::runTestCase(*this, test, errorCode);
1048 
1049 
1050     // Same for `plural`
1051 
1052     test = testBuilder.setPattern(".match {$foo :plural} one {{one}} * {{other}}")
1053                                   .setExpectedError(U_MF_UNKNOWN_FUNCTION_ERROR)
1054                                   .setArgument("foo", (int64_t) 1)
1055                                   .setExpected("other")
1056                                   .build();
1057     TestUtils::runTestCase(*this, test, errorCode);
1058 
1059     test = testBuilder.setPattern("hello {42 :plural}")
1060                                   .setExpectedError(U_MF_UNKNOWN_FUNCTION_ERROR)
1061                                   .setExpected("hello {|42|}")
1062                                   .build();
1063     TestUtils::runTestCase(*this, test, errorCode);
1064 
1065     // :string
1066 
1067     test = testBuilder.setPattern(".match {$foo :string} |1| {{one}} * {{other}}")
1068                                   .setExpectSuccess()
1069                                   .setArgument("foo", (int64_t) 1)
1070                                   .setExpected("one")
1071                                   .build();
1072     TestUtils::runTestCase(*this, test, errorCode);
1073 
1074     test = testBuilder.setPattern(".match {$foo :string} 1 {{one}} * {{other}}")
1075                                   .setExpectSuccess()
1076                                   .setArgument("foo", (int64_t) 1)
1077                                   .setExpected("one")
1078                                   .build();
1079     TestUtils::runTestCase(*this, test, errorCode);
1080 
1081     // The spec test with argument "foo" set to null is omitted, since
1082     // this implementation doesn't support null arguments
1083 
1084     test = testBuilder.setPattern(".match {$foo :string} 1 {{one}} * {{other}}")
1085                                   .setExpectSuccess()
1086                                   .setArgument("foo", (double) 42.5)
1087                                   .setExpected("other")
1088                                   .build();
1089     TestUtils::runTestCase(*this, test, errorCode);
1090 
1091     test = testBuilder.setPattern(".match {$foo :string} 1 {{one}} * {{other}}")
1092                                   .setExpectedError(U_MF_UNRESOLVED_VARIABLE_ERROR)
1093                                   .clearArguments()
1094                                   .setExpected("other")
1095                                   .build();
1096     TestUtils::runTestCase(*this, test, errorCode);
1097 
1098 
1099     // There is no `:select` in this version of the spec
1100     test = testBuilder.setPattern(".match {$foo :select} one {{one}} * {{other}}")
1101                                   .setExpectedError(U_MF_UNKNOWN_FUNCTION_ERROR)
1102                                   .setArgument("foo", (int64_t) 1)
1103                                   .setExpected("other")
1104                                   .build();
1105     TestUtils::runTestCase(*this, test, errorCode);
1106 
1107     // :date
1108     test = testBuilder.setPattern("{:date}")
1109                                   .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
1110                                   .setExpected("{:date}")
1111                                   .build();
1112     TestUtils::runTestCase(*this, test, errorCode);
1113 
1114     test = testBuilder.setPattern("{horse :date}")
1115                                   .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
1116                                   .setExpected("{|horse|}")
1117                                   .build();
1118     TestUtils::runTestCase(*this, test, errorCode);
1119 
1120     test = testBuilder.setPattern("{|2006-01-02| :date}")
1121                                   .setExpectSuccess()
1122                                   .setExpected("1/2/06")
1123                                   .build();
1124     TestUtils::runTestCase(*this, test, errorCode);
1125 
1126     test = testBuilder.setPattern("{|2006-01-02T15:04:06| :date}")
1127                                   .setExpectSuccess()
1128                                   .setExpected("1/2/06")
1129                                   .build();
1130     TestUtils::runTestCase(*this, test, errorCode);
1131 
1132     test = testBuilder.setPattern("{|2006-01-02| :date style=long}")
1133                                   .setExpectSuccess()
1134                                   .setExpected("January 2, 2006")
1135                                   .build();
1136     TestUtils::runTestCase(*this, test, errorCode);
1137 
1138     test = testBuilder.setPattern(".local $d = {|2006-01-02| :date style=long} {{{$d :date}}}")
1139                                   .setExpectSuccess()
1140                                   .setExpected("January 2, 2006")
1141                                   .build();
1142     TestUtils::runTestCase(*this, test, errorCode);
1143 
1144     test = testBuilder.setPattern(".local $t = {|2006-01-02T15:04:06| :time} {{{$t :date}}}")
1145                                   .setExpectSuccess()
1146                                   .setExpected("1/2/06")
1147                                   .build();
1148     TestUtils::runTestCase(*this, test, errorCode);
1149 
1150     // :time
1151     test = testBuilder.setPattern("{:time}")
1152                                   .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
1153                                   .setExpected("{:time}")
1154                                   .build();
1155     TestUtils::runTestCase(*this, test, errorCode);
1156 
1157     test = testBuilder.setPattern("{horse :time}")
1158                                   .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
1159                                   .setExpected("{|horse|}")
1160                                   .build();
1161     TestUtils::runTestCase(*this, test, errorCode);
1162 
1163     test = testBuilder.setPattern("{|2006-01-02T15:04:06| :time}")
1164                                   .setExpectSuccess()
1165                                   .setExpected(CharsToUnicodeString("3:04\\u202FPM"))
1166                                   .build();
1167     TestUtils::runTestCase(*this, test, errorCode);
1168 
1169     test = testBuilder.setPattern("{|2006-01-02T15:04:06| :time style=medium}")
1170                                   .setExpectSuccess()
1171                                   .setExpected(CharsToUnicodeString("3:04:06\\u202FPM"))
1172                                   .build();
1173     TestUtils::runTestCase(*this, test, errorCode);
1174 
1175     test = testBuilder.setPattern(".local $t = {|2006-01-02T15:04:06| :time style=medium} {{{$t :time}}}")
1176                                   .setExpectSuccess()
1177                                   .setExpected(CharsToUnicodeString("3:04:06\\u202FPM"))
1178                                   .build();
1179     TestUtils::runTestCase(*this, test, errorCode);
1180 
1181     test = testBuilder.setPattern(".local $t = {|2006-01-02T15:04:06| :date} {{{$t :time}}}")
1182                                   .setExpectSuccess()
1183                                   .setExpected(CharsToUnicodeString("3:04\\u202FPM"))
1184                                   .build();
1185     TestUtils::runTestCase(*this, test, errorCode);
1186 
1187 
1188     // :datetime
1189     test = testBuilder.setPattern("{:datetime}")
1190                                   .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
1191                                   .setExpected("{:datetime}")
1192                                   .build();
1193     TestUtils::runTestCase(*this, test, errorCode);
1194 
1195     test = testBuilder.setPattern("{$x :datetime}")
1196                                   .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
1197                                   .setExpected("{$x}")
1198                                   .setArgument("x", (int64_t) 1)
1199                                   .build();
1200     TestUtils::runTestCase(*this, test, errorCode);
1201 
1202     test = testBuilder.setPattern("{$x :datetime}")
1203                                   .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
1204                                   .setExpected("{$x}")
1205                                   .setArgument("x", "true")
1206                                   .build();
1207     TestUtils::runTestCase(*this, test, errorCode);
1208 
1209     test = testBuilder.setPattern("{horse :datetime}")
1210                                   .setExpectedError(U_MF_OPERAND_MISMATCH_ERROR)
1211                                   .setExpected("{|horse|}")
1212                                   .build();
1213     TestUtils::runTestCase(*this, test, errorCode);
1214 
1215     test = testBuilder.setPattern("{|2006-01-02T15:04:06| :datetime}")
1216                                   .setExpectSuccess()
1217                                   .setExpected(CharsToUnicodeString("1/2/06, 3:04\\u202FPM"))
1218                                   .build();
1219     TestUtils::runTestCase(*this, test, errorCode);
1220 
1221     test = testBuilder.setPattern("{|2006-01-02T15:04:06| :datetime year=numeric month=|2-digit|}")
1222                                   .setExpectSuccess()
1223                                   .setExpected("01/2006")
1224                                   .build();
1225     TestUtils::runTestCase(*this, test, errorCode);
1226 
1227     test = testBuilder.setPattern("{|2006-01-02T15:04:06| :datetime dateStyle=long}")
1228                                   .setExpectSuccess()
1229                                   .setExpected("January 2, 2006")
1230                                   .build();
1231     TestUtils::runTestCase(*this, test, errorCode);
1232 
1233     test = testBuilder.setPattern("{|2006-01-02T15:04:06| :datetime timeStyle=medium}")
1234                                   .setExpectSuccess()
1235                                   .setExpected(CharsToUnicodeString("3:04:06\\u202FPM"))
1236                                   .build();
1237     TestUtils::runTestCase(*this, test, errorCode);
1238 
1239     test = testBuilder.setPattern("{$dt :datetime}")
1240                                   .setArgument("dt", "2006-01-02T15:04:06")
1241                                   .setExpectSuccess()
1242                                   .setExpected(CharsToUnicodeString("1/2/06, 3:04\\u202FPM"))
1243                                   .build();
1244     TestUtils::runTestCase(*this, test, errorCode);
1245 
1246 /*
1247 TODO
1248 This can't work -- the "style" option is different from "dateStyle" and can't get used
1249 in the second call to `:datetime`
1250 See https://github.com/unicode-org/message-format-wg/issues/726
1251 
1252     test = testBuilder.setPattern(".input {$dt :time style=medium} {{{$dt :datetime dateStyle=long}}}")
1253                                   .setArgument("dt", "2006-01-02T15:04:06")
1254                                   .setExpectSuccess()
1255                                   .setExpected(CharsToUnicodeString("January 2, 2006 at 3:04:06\\u202FPM"))
1256                                   .build();
1257     TestUtils::runTestCase(*this, test, errorCode);
1258 */
1259 
1260     // TODO: tests for other function options?
1261 }
1262 
1263 #endif /* #if !UCONFIG_NO_MF2 */
1264 
1265 #endif /* #if !UCONFIG_NO_FORMATTING */
1266