These test files are intended to be useful for testing multiple different message processors in different ways:
-
syntax.json— Test cases that do not depend on any registry definitions. -
syntax-errors.json— Strings that should produce a Syntax Error when parsed.
Note
Tests for the disallowed uses of unpaired surrogate code points are not included
because JSON does not permit unpaired surrogate code points.
If your implementation uses UTF-16 based strings (such as JavaScript String or Java java.lang.String)
or otherwise allows unpaired surrogates in text or literals, you will need to implement tests equivalent
to the following for syntax errors:
{
"locale": "en-US",
"src": "{\ud800}",
"expErrors": [{ "type": "syntax-error" }]
}-
data-model-errors.json- Strings that should produce a Data Model Error when processed. Error names are defined in "MessageFormat 2.0 Errors" in the spec. -
u-options.json— Test cases for theu:options, using built-in functions. -
functions/— Test cases that correspond to built-in functions. The behaviour of the built-in formatters is implementation-specific so theexpfield is often omitted and assertions are made on error cases.
Some examples of test harnesses using these tests, from the source repository:
A JSON schema is included for the test files in this repository.
The following table relates the error names used in the JSON schema to the error names used in "MessageFormat 2.0 Errors" in the spec.
| Spec | Schema |
|---|---|
| Bad Operand | bad-operand |
| Bad Option | bad-option |
| Bad Selector | bad-selector |
| Bad Variant Key | bad-variant-key |
| Duplicate Declaration | duplicate-declaration |
| Duplicate Option Name | duplicate-option-name |
| Duplicate Variant | duplicate-variant |
| Missing Fallback Variant | missing-fallback-variant |
| Missing Selector Annotation | missing-selector-annotation |
| Syntax Error | syntax-error |
| Unknown Function | unknown-function |
| Unresolved Variable | unresolved-variable |
| Variant Key Mismatch | variant-key-mismatch |
The "Message Function Error" error name used in the spec is not included in the schema, as it is intended to be an umbrella category for implementation-specific errors.
Some of the tests are for functionality that is optional or for functionality that is not yet stable.
That is, the specification uses RFC2119 keywords such as SHOULD, SHOULD NOT, MAY, RECOMMENDED, or OPTIONAL,
or the specification says that given functionality is DRAFT and not yet stable.
Tests for such features have a tags array attached to them
to mark the features that they rely on.
This may include one or more of the following:
| Tag | Feature |
|---|---|
:currency |
The :currency function |
:percent |
The :percent function |
u:dir |
The u:dir option |
u:id |
The u:id option |
As the behaviour of some of the default registry functions
such as :number and :datetime
is dependent on locale-specific data and may vary between implementations,
the following functions are defined for test use only:
This function is valid both as a selector and as a formatter.
The function :test:function requires a Number Operand as its operand.
The following options are available on :test:function:
decimalPlaces, a digit size option for which only0and1are valid values.01
failsnever(default)selectformatalways
All other options and their values are ignored.
When resolving a :test:function expression,
its Input, DecimalPlaces, FailsFormat, and FailsSelect values are determined as follows:
- Let
DecimalPlacesbe 0. - Let
FailsFormatbefalse. - Let
FailsSelectbefalse. - Let
argbe the resolved value of the expression operand. - If
argis the resolved value of an expression with a:test:function,:test:select, or:test:formatannotation for which resolution has succeeded, then- Let
Inputbe theInputvalue ofarg. - Set
DecimalPlacesto beDecimalPlacesvalue ofarg. - Set
FailsFormatto beFailsFormatvalue ofarg. - Set
FailsSelectto beFailsSelectvalue ofarg.
- Let
- Else if
argis a numerical value or a string matching thenumber-literalproduction, then- Let
Inputbe the numerical value ofarg.
- Let
- Else,
- Emit "bad-input" Resolution Error.
- Use a fallback value as the resolved value of the expression. Further steps of this algorithm are not followed.
- If the
decimalPlacesoption is set, then- If its value resolves to a numerical integer value 0 or 1
or their corresponding string representations
'0'or'1', then- Set
DecimalPlacesto be the numerical value of the option.
- Set
- Else if its value is not an unresolved value set by option resolution,
- Emit "bad-option" Resolution Error.
- Use a fallback value as the resolved value of the expression.
- If its value resolves to a numerical integer value 0 or 1
or their corresponding string representations
- If the
failsoption is set, then- If its value resolves to the string
'always', then- Set
FailsFormatto betrue. - Set
FailsSelectto betrue.
- Set
- Else if its value resolves to the string
'format', then- Set
FailsFormatto betrue.
- Set
- Else if its value resolves to the string
'select', then- Set
FailsSelectto betrue.
- Set
- Else if its value does not resolve to the string
'never', then- Emit "bad-option" Resolution Error.
- If its value resolves to the string
When :test:function is used as a selector,
the behaviour of calling it as the rv value of Match(rv, key)
(see Pattern Selection for more information)
depends on its Input, DecimalPlaces and FailsSelect values.
- If
FailsSelectistrue, calling the method will emit a Bad Option error and not return any value. - If the
Inputis 1 andDecimalPlacesis 1, the method will return true for either'1.0'or'1', and false for any other key. - If the
Inputis 1 andDecimalPlacesis 0, the method will return true for'1'and false for any other key. - If the
Inputis any other value, the method will return false.
When :test:function is used as a selector,
the behaviour of calling it as the rv value of BetterThan(rv, key1, key2)
(see Pattern Selection for more information)
- The method will return true if
key1is'1.0', and false otherwise.
When an expression with a :test:function annotation is assigned to a variable by a declaration
and that variable is used as an option value,
its resolved value is the Input value.
When :test:function is used as a formatter,
a placeholder resolving to a value with a :test:function expression
is formatted as a concatenation of the following parts:
- If
Inputis less than 0, the character-U+002D Hyphen-Minus. - The truncated absolute integer value of
Input, i.e. floor(abs(Input)), formatted as a sequence of decimal digit characters (U+0030...U+0039). - If
DecimalPlacesis 1, then- The character
.U+002E Full Stop. - The single decimal digit character representing the value floor((abs(
Input) - floor(abs(Input))) * 10)
- The character
If the formatting target is a sequence of parts, each of the above parts will be emitted separately rather than being concatenated into a single string.
If FailsFormat is true,
attempting to format the placeholder to any formatting target will
emit a Bad Option error.
Note that emitting Bad Option here does not indicate an incorrect option. Actual functions in your implementation might emit an implementation-defined or platform-specific runtime error or exception when the function handler is called. Your implementation might thus produce a Message Function Error not provided with a label in the JSON Schema of this test suite.
This function accepts the same operands and options,
and behaves exactly the same as :test:function,
except that it cannot be used for formatting.
When :test:select is used as a formatter,
a "not-formattable" error is emitted and the placeholder is formatted with
a fallback value.
This function accepts the same operands and options,
and behaves exactly the same as :test:function,
except that it cannot be used for selection.
When :test:format is used as a selector,
the steps under 2.iii. of Resolve Selectors are followed.
The tests in the ./tests/ directory were originally copied from the messageformat project
and are here relicensed by their original author (Eemeli Aro) under the Unicode License.