| > [!IMPORTANT] | 
 | > This page was copied from https://github.com/dart-lang/sdk/wiki and needs review. | 
 | > Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date - | 
 | > removing this header - or send a CL to delete the file. | 
 |  | 
 | --- | 
 |  | 
 | Stability is important for a programming language used to implement applications | 
 | that [manage billions of dollars](http://news.dartlang.org/2016/03/the-new-adwords-ui-uses-dart-we-asked.html). To that end, the Dart repository contains a | 
 | comprehensive test suite to cover the various configurations, compilers, tools, | 
 | and runtimes we maintain and support. | 
 |  | 
 | We have tens of thousands of tests and a single test may be run across a | 
 | combinatorial explosion of configurations. Does the static analyzer report any | 
 | errors on it? In strong mode? Does it run on the standalone VM? Can dart2js | 
 | compile it? Does the resulting code run in Chrome? Firefox? IE? In checked mode? | 
 | With minification on? You get the idea. | 
 |  | 
 | Many tests are only meaningful for certain combinations of configurations. A | 
 | test that uses "dart:io" is, by design, not going to run in a browser which | 
 | doesn't have access to the local file system. Some bleeding edge web features | 
 | aren't fully supported across all browsers. As we ramp up new tools, parts of | 
 | our own stack may not be passing all tests. | 
 |  | 
 | So, for all of these tests, we need to track not just the test itself, but it's | 
 | *status* -- what the expected outcome of the test is on various configurations. | 
 | This status information lives (mostly) outside of the tests in separate "status | 
 | files" with a ".status" extension. | 
 |  | 
 | This document explains the format of those files and how the test runner | 
 | interprets them. | 
 |  | 
 | ## Outcomes and expectations | 
 |  | 
 | The test runner's main job, as you'd imagine, is to run tests. This sometimes | 
 | involves invoking a compiler, and then spawning another process to execute the | 
 | test itself. That process then may or may not complete successfully. | 
 |  | 
 | The test runner monitors this and tracks the various ways it can go wrong. | 
 | Each of these outcomes has a canonical name. Things like: | 
 |  | 
 | - **Pass** – The runtime exited with exit code zero. | 
 | - **CompileTimeError** – The compiler exited with a non-zero exit code. | 
 | - **RuntimeError** – The runtime exited with a non-zero exit code. | 
 |  | 
 | There are other, more exotic outcomes. For the full list of them, see the code: | 
 |  | 
 | [`pkg/status_file/lib/expectation.dart`](https://github.com/dart-lang/sdk/blob/main/pkg/status_file/lib/expectation.dart) | 
 |  | 
 | In a perfect world, every test would pass in every configuration and the test | 
 | runner could simplify verify that every test's outcome was "Pass". Alas, life is | 
 | complicated. The status files keep track of what the *expected* outcome of each | 
 | test is, which is why these outcomes are usually referred to as "expectations". | 
 |  | 
 | A test that ends with a runtime error is a successful test if the status file | 
 | says we *expect* to get a runtime error. The test fails if no runtime error | 
 | occurred. | 
 |  | 
 | ## Status files | 
 |  | 
 | Status files define the expectations for the tests by combining three facets: | 
 |  | 
 | * What are the expected outcomes... | 
 | * ...for which tests... | 
 | * ...under which configurations. | 
 |  | 
 | It's a bit like [Clue][]'s "Miss Scarlett, in the library, with the revolver." | 
 | The status file says something like "'math/low_test', when compiled using | 
 | dart2js, should produce a CompileError". | 
 |  | 
 | [clue]: https://en.wikipedia.org/wiki/Cluedo | 
 |  | 
 | With miles of tests and piles of configurations, we need a compact notation for | 
 | defining expectations. That's what status files aim to be. | 
 |  | 
 | A status file is a line-oriented (newlines are significant) plain text file. | 
 | Comments start with `#` and continue to the end of the line. Blank lines are | 
 | ignored. | 
 |  | 
 | ### Sections | 
 |  | 
 | Each status file consists of a list of **sections**. Each section starts with a | 
 | **header**, followed by one or more **entries**. (Entries at the top of the file | 
 | above any header go into an implicit header-less section.) | 
 |  | 
 | Sections have no relation to each other and the order does not matter. | 
 |  | 
 | ### Headers | 
 |  | 
 | The header defines which configurations its entries apply to. It lets you | 
 | specify the conditions under which a set of expectations come into play. The | 
 | header contains an expression made up of accesses to various configuration | 
 | variables. It's evaluated against the current configuration's values for those | 
 | variables. If the expression evaluates to true, the section is applied and its | 
 | entries are used. Otherwise, its entries are ignored. | 
 |  | 
 | If there are entries in the implicit first headerless section, the condition is | 
 | always considered to be true and the entries are always applied. | 
 |  | 
 | Arbitrarily large expressions are supported, but the larger they are, the harder | 
 | it is for your fellow teammates to understand what outcomes are expected for a | 
 | given configuration. | 
 |  | 
 | Here's a complex example: | 
 |  | 
 | ```text | 
 | [ $compiler == dart2js && ( $browser || $runtime == d8 ) ] | 
 | ``` | 
 |  | 
 | The expression is contained in square brackets. Since we all love EBNF, the | 
 | grammar for the expression inside is: | 
 |  | 
 | ```text | 
 | expression := or | 
 | or         := and ( "||" and )* | 
 | and        := primary ( "&&" primary )* | 
 | primary    := "$" identifier ( "==" | "!=" ) identifier | | 
 |               "!"? "$" identifier | | 
 |               "(" expression ")" | 
 | identifier := regex "\w+" | 
 | ``` | 
 |  | 
 | There are a few different expression forms: | 
 |  | 
 | *   **Variable** – This looks up the value of some configuration option like | 
 |     `$runtime` for which execution environment the test will be run in or | 
 |     `$strong` for whether the test is run in strong mode. Variables are always | 
 |     prefixed by `$`. | 
 |  | 
 |     If the variable is a Boolean, you use it as a bare identifier like `$strong` | 
 |     or `$checked`. It may be prefixed with `!` to negate its value, so `! | 
 |     $checked` evaluates to true if the test is run in unchecked mode. | 
 |  | 
 |     Non-Boolean variables accept one of an enumerated set of values. The set of | 
 |     values depends on the variable. For example, `$mode` can be `debug`, | 
 |     `release`, or `product`. To use one of these, it must be followed by `==` or | 
 |     `!=` and the value being tested. Examples: | 
 |  | 
 |     ```text | 
 |     $runtime == vm | 
 |     $mode != debug | 
 |     ``` | 
 |  | 
 |     Note that unlike variables, values are not prefixed with `$`. Note also | 
 |     that the equality operator and value is part of the variable expression | 
 |     itself. You can't do something like: `$mode == $runtime`. You always have | 
 |     to test against a literal value. | 
 |  | 
 |     The set of variables that are available in status file expressions is baked | 
 |     into `test.dart`. You can see the full list of them here: | 
 |  | 
 |     [`tools/testing/dart/environment.dart`](https://github.com/dart-lang/sdk/blob/main/pkg/test_runner/lib/src/environment.dart#L12) | 
 |  | 
 |     For each variable, `test.dart` also knows all of the values that are allowed | 
 |     for it. It uses this to validate these expressions at parse time. If you | 
 |     misspell a variable, like `$compile` or test it against a value it can't | 
 |     have like `$runtime == dart2js` (dart2js is a compiler, not a runtime), it | 
 |     reports an error. | 
 |  | 
 | *   **Logical operators** - You can join two subexpressions using `||` or `&&`, | 
 |     with their usual meaning. `&&` has higher precedence than `||`. | 
 |  | 
 | *   **Parentheses** – If you want a `||` expression to be an operand to a `&&` | 
 |     expression, you can explicitly parenthesize. | 
 |  | 
 | Here are some examples: | 
 |  | 
 | ```text | 
 | [ ! $checked ] | 
 | ``` | 
 |  | 
 | This section applies only when not running the test in checked mode. | 
 |  | 
 | ```text | 
 | [ $arch == simarm || $arch == simarmv6 || $arch == simarmv5te ] | 
 | ``` | 
 |  | 
 | This section applies only on various ARM simulator architectures. | 
 |  | 
 | ```text | 
 | [ $checked && ($compiler == dartk || $compiler == dartkp) ] | 
 | ``` | 
 |  | 
 | This section applies if the test is running in checked mode and using either of | 
 | two Kernel compilers. | 
 |  | 
 | ```text | 
 | [ $compiler != dart2js ] | 
 | ``` | 
 |  | 
 | This section applies for any compiler except dart2js. | 
 |  | 
 | ### Entries | 
 |  | 
 | After the header, a section contains a list of entries. Each entry defines a | 
 | glob-like path that matches a set of test files. Then it specifies the set of | 
 | allowed outcomes for those tests. | 
 |  | 
 | For example: | 
 |  | 
 | ``` | 
 | typed_data/int64_list_load_store_test: RuntimeError # Issue 10275 | 
 | ``` | 
 |  | 
 | The syntax is a path, followed by `:`, followed by a comma-separated list of | 
 | expectation names. It's a good idea to have a comment explaining why the test(s) | 
 | have this expectation. If the expectation is because the test should be passing | 
 | but isn't, the comment usually mentions the relevant issue number. | 
 |  | 
 | Here, it says the "int64_list_load_store_test" is failing at runtime because of | 
 | some bug we should fix. | 
 |  | 
 | The path string is relative to the directory containing the status file. Note | 
 | that paths do not have ".dart" extensions, even when they only match a single | 
 | file (which is the normal case). You can also use `*` like a glob to match part | 
 | of a path component as in: | 
 |  | 
 | ```text | 
 | async/*deferred*: Pass,RuntimeError # Issue 17458 | 
 | ``` | 
 |  | 
 | This matches any test inside the "async" directory whose name contains | 
 | "deferred". If you want an entry that matches every single test in the directory | 
 | containing the status file, use: | 
 |  | 
 | ```text | 
 | *: Skip # Issue 28649 | 
 | ``` | 
 |  | 
 | ## Applying status files | 
 |  | 
 | The trickiest part of status files is that the same test may be matched by | 
 | multiple entries in different sections, potentially spread across different | 
 | status files. These entries may apply and overlap in some configurations but not | 
 | in others. For example, the status file for the corelib tests has five sections | 
 | with entries that all match "async/multiple_timer_test" (I removed other | 
 | unrelated entries here): | 
 |  | 
 | ```text | 
 | [ $compiler == dart2js && $runtime == jsshell ] | 
 | async/multiple_timer_test: RuntimeError,OK # Needs Timer to run. | 
 |  | 
 | [ $runtime == vm && $system == fuchsia ] | 
 | async/multiple_timer_test: RuntimeError | 
 |  | 
 | [ $compiler == none && ($runtime == drt || $runtime == dartium) ] | 
 | async/multiple_timer_test: Fail, Pass # Issue 15487 | 
 |  | 
 | [ $compiler == none && $runtime == drt && $system == windows ] | 
 | async/multiple_timer_test: Fail, Pass # See Issue 10982 | 
 |  | 
 | [ $hot_reload || $hot_reload_rollback ] | 
 | async/multiple_timer_test: Pass, Fail # Timing related | 
 | ``` | 
 |  | 
 | Many of these sections are disjoint so that if one applies, another won't, but | 
 | not all of them are. For example, if you're running on Fuchsia on the VM with | 
 | hot reload enabled, the second and last sections both apply. They have different | 
 | expectations. So what does `test.dart` expect this test to do? | 
 |  | 
 | When there are multiple sets of expectations for the same file, `test.dart` | 
 | unions all of the sets together. So, in this case, the resulting expectation is | 
 | "RuntimeError, Pass, Fail". | 
 |  | 
 | A test succeeds if the outcome is *any* of the expectations. Here, that | 
 | basically means the test is going to succeed no matter what as long as it | 
 | doesn't crash or timeout or something. | 
 |  | 
 | If no entries match a given file, the default expectation is "Pass". That means | 
 | you only need to mention a file in a status file if it doesn't pass in at least | 
 | one configuration. | 
 |  | 
 | ## Special expectations | 
 |  | 
 | Some "expectations" don't line up with actual possible test outcomes. Instead, | 
 | they affect how the test runner works or have another purpose. A couple of | 
 | important ones are: | 
 |  | 
 | *   **Skip** and **SkipByDesign** – These tell `test.dart` to not run the test | 
 |     at all. The latter is OK, it means "this behavior isn't relevant for this | 
 |     configuration". For example, Dartium doesn't support "dart:io", so the | 
 |     status file says: | 
 |  | 
 |     ```text | 
 |     [ $compiler == none && ($runtime == drt || $runtime == dartium) ] | 
 |     io/*: SkipByDesign # Don't run tests using dart:io in the browser | 
 |     ``` | 
 |  | 
 |     The "Skip" expectation is older and should be avoided, since it doesn't | 
 |     convey *why* the test is being skipped. | 
 |  | 
 | *   **OK** isn't a real expectation. It's more like a comment for a reader of | 
 |     the status file to know the behavior is intentional and desired. For | 
 |     example: | 
 |  | 
 |     ```text | 
 |     [ $compiler == dart2js && $runtime == jsshell ] | 
 |     async/timer_cancel_test: RuntimeError,OK # Needs Timer to run. | 
 |     ``` | 
 |  | 
 |     jsshell doesn't support Times, so we never expect this test to pass. | 
 |  | 
 | There are some other special expectations, documented in the source here: | 
 |  | 
 | [`/pkg/status_file/lib/expectation.dart`](https://github.com/dart-lang/sdk/blob/main/pkg/status_file/lib/expectation.dart) |