README.md
1# Test Data for CLDR MessageFormat 2.0 Tech Preview
2
3For information about MessageFormat 2.0, see [Unicode Locale Data Markup Language (LDML): Part 9: Message Format](../../../docs/ldml/tr35-messageFormat.md)
4
5The tests in the `./tests/` directory were originally copied from the [messageformat project](https://github.com/messageformat/messageformat/tree/11c95dab2b25db8454e49ff4daadb817e1d5b770/packages/mf2-messageformat/src/__fixtures)
6and are here relicensed by their original author (Eemeli Aro) under the Unicode License.
7
8These test files are intended to be useful for testing multiple different message processors in different ways:
9
10- `syntax.json` — Test cases that do not depend on any registry definitions.
11
12- `syntax-errors.json` — Strings that should produce a Syntax Error when parsed.
13
14- `data-model-errors.json` - Strings that should produce a Data Model Error when processed.
15 Error names are defined in ["MessageFormat 2.0 Errors"](../spec/errors.md) in the spec.
16
17- `functions/` — Test cases that correspond to built-in functions.
18 The behaviour of the built-in formatters is implementation-specific so the `exp` field is often
19 omitted and assertions are made on error cases.
20
21Some examples of test harnesses using these tests, from the source repository:
22
23- [CST parse/stringify tests](https://github.com/messageformat/messageformat/blob/11c95dab2b25db8454e49ff4daadb817e1d5b770/packages/mf2-messageformat/src/cst/cst.test.ts)
24- [Data model stringify tests](https://github.com/messageformat/messageformat/blob/11c95dab2b25db8454e49ff4daadb817e1d5b770/packages/mf2-messageformat/src/data-model/stringify.test.ts)
25- [Formatting tests](https://github.com/messageformat/messageformat/blob/11c95dab2b25db8454e49ff4daadb817e1d5b770/packages/mf2-messageformat/src/messageformat.test.ts)
26
27A [JSON schema](./schemas/) is included for the test files in this repository.
28## Error Codes
29
30The following table relates the error names used in the [JSON schema](./schemas/)
31to the error names used in ["MessageFormat 2.0 Errors"](../spec/errors.md) in the spec.
32
33| Spec | Schema |
34| --------------------------- | --------------------------- |
35| Bad Operand | bad-operand |
36| Bad Option | bad-option |
37| Bad Selector | bad-selector |
38| Bad Variant Key | bad-variant-key |
39| Duplicate Declaration | duplicate-declaration |
40| Duplicate Option Name | duplicate-option-name |
41| Duplicate Variant | duplicate-variant |
42| Missing Fallback Variant | missing-fallback-variant |
43| Missing Selector Annotation | missing-selector-annotation |
44| Syntax Error | syntax-error |
45| Unknown Function | unknown-function |
46| Unresolved Variable | unresolved-variable |
47| Variant Key Mismatch | variant-key-mismatch |
48
49The "Message Function Error" error name used in the spec
50is not included in the schema,
51as it is intended to be an umbrella category
52for implementation-specific errors.
53
54## Test Functions
55
56As the behaviour of some of the default registry _functions_
57such as `:number` and `:datetime`
58is dependent on locale-specific data and may vary between implementations,
59the following _functions_ are defined for **test use only**:
60
61### `:test:function`
62
63This function is valid both as a _selector_ and as a _formatter_.
64
65#### Operands
66
67The function `:test:function` requires a [Number Operand](/spec/registry.md#number-operands) as its _operand_.
68
69#### Options
70
71The following _options_ are available on `:test:function`:
72- `decimalPlaces`, a _digit size option_ for which only `0` and `1` are valid values.
73 - `0`
74 - `1`
75- `fails`
76 - `never` (default)
77 - `select`
78 - `format`
79 - `always`
80
81All other _options_ and their values are ignored.
82
83#### Behavior
84
85When resolving a `:test:function` expression,
86its `Input`, `DecimalPlaces`, `FailsFormat`, and `FailsSelect` values are determined as follows:
87
881. Let `DecimalPlaces` be 0.
891. Let `FailsFormat` be `false`.
901. Let `FailsSelect` be `false`.
911. Let `arg` be the resolved value of the _expression_ _operand_.
921. If `arg` is the resolved value of an _expression_
93 with a `:test:function`, `:test:select`, or `:test:format` _annotation_
94 for which resolution has succeeded, then
95 1. Let `Input` be the `Input` value of `arg`.
96 1. Set `DecimalPlaces` to be `DecimalPlaces` value of `arg`.
97 1. Set `FailsFormat` to be `FailsFormat` value of `arg`.
98 1. Set `FailsSelect` to be `FailsSelect` value of `arg`.
991. Else if `arg` is a numerical value
100 or a string matching the `number-literal` production, then
101 1. Let `Input` be the numerical value of `arg`.
1021. Else,
103 1. Emit "bad-input" _Resolution Error_.
104 1. Use a _fallback value_ as the resolved value of the _expression_.
105 Further steps of this algorithm are not followed.
1061. If the `decimalPlaces` _option_ is set, then
107 1. If its value resolves to a numerical integer value 0 or 1
108 or their corresponding string representations `'0'` or `'1'`, then
109 1. Set `DecimalPlaces` to be the numerical value of the _option_.
110 1. Else if its value is not an unresolved value set by _option resolution_,
111 1. Emit "bad-option" _Resolution Error_.
112 1. Use a _fallback value_ as the resolved value of the _expression_.
1131. If the `fails` _option_ is set, then
114 1. If its value resolves to the string `'always'`, then
115 1. Set `FailsFormat` to be `true`.
116 1. Set `FailsSelect` to be `true`.
117 1. Else if its value resolves to the string `'format'`, then
118 1. Set `FailsFormat` to be `true`.
119 1. Else if its value resolves to the string `'select'`, then
120 1. Set `FailsSelect` to be `true`.
121 1. Else if its value does not resolve to the string `'never'`, then
122 1. Emit "bad-option" _Resolution Error_.
123
124When `:test:function` is used as a _selector_,
125the behaviour of calling it as the `rv` value of MatchSelectorKeys(`rv`, `keys`)
126(see [Resolve Preferences](/spec/formatting.md#resolve-preferences) for more information)
127depends on its `Input`, `DecimalPlaces` and `FailsSelect` values.
128
129- If `FailsSelect` is `true`,
130 calling the method will fail and not return any value.
131- If the `Input` is 1 and `DecimalPlaces` is 1,
132 the method will return some slice of the list « `'1.0'`, `'1'` »,
133 depending on whether those values are included in `keys`.
134- If the `Input` is 1 and `DecimalPlaces` is 0,
135 the method will return the list « `'1'` » if `keys` includes `'1'`, or an empty list otherwise.
136- If the `Input` is any other value, the method will return an empty list.
137
138When an _expression_ with a `:test:function` _annotation_ is assigned to a _variable_ by a _declaration_
139and that _variable_ is used as an _option_ value,
140its resolved value is the `Input` value.
141
142When `:test:function` is used as a _formatter_,
143a _placeholder_ resolving to a value with a `:test:function` _expression_
144is formatted as a concatenation of the following parts:
145
1461. If `Input` is less than 0, the character `-` U+002D Hyphen-Minus.
1471. The truncated absolute integer value of `Input`, i.e. floor(abs(`Input`)),
148 formatted as a sequence of decimal digit characters (U+0030...U+0039).
1491. If `DecimalPlaces` is 1, then
150 1. The character `.` U+002E Full Stop.
151 1. The single decimal digit character representing the value floor((abs(`Input`) - floor(abs(`Input`))) \* 10)
152
153If the formatting target is a sequence of parts,
154each of the above parts will be emitted separately
155rather than being concatenated into a single string.
156
157If `FailsFormat` is `true`,
158attempting to format the _placeholder_ to any formatting target will fail.
159
160### `:test:select`
161
162This _function_ accepts the same _operands_ and _options_,
163and behaves exactly the same as `:test:function`,
164except that it cannot be used for formatting.
165
166When `:test:select` is used as a _formatter_,
167a "not-formattable" error is emitted and the _placeholder_ is formatted with
168a _fallback value_.
169
170### `:test:format`
171
172This _function_ accepts the same _operands_ and _options_,
173and behaves exactly the same as `:test:function`,
174except that it cannot be used for selection.
175
176When `:test:format` is used as a _selector_,
177the steps under 2.iii. of [Resolve Selectors](/spec/formatting.md#resolve-selectors) are followed.
178