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