A new more complete test format for ETH 2.0 testing
This commit is contained in:
parent
f5c5c166af
commit
80067721e2
|
@ -1,71 +0,0 @@
|
||||||
# General test format [WIP]
|
|
||||||
|
|
||||||
This document defines the general YAML format to which all tests should conform. Testing specifications in Eth2.0 are still a work in progress. _Expect breaking changes_
|
|
||||||
|
|
||||||
## ToC
|
|
||||||
|
|
||||||
* [About](#about)
|
|
||||||
* [YAML Fields](#yaml-fields)
|
|
||||||
* [Example test suite](#example-test-suite)
|
|
||||||
|
|
||||||
## About
|
|
||||||
Ethereum 2.0 uses YAML as the format for all cross client tests. This document describes at a high level the general format to which all test files should conform.
|
|
||||||
|
|
||||||
The particular formats of specific types of tests (test suites) are defined in separate documents.
|
|
||||||
|
|
||||||
## YAML fields
|
|
||||||
`title` _(required)_
|
|
||||||
|
|
||||||
`summary` _(optional)_
|
|
||||||
|
|
||||||
`test_suite` _(required)_ string defining the test suite to which the test cases conform
|
|
||||||
|
|
||||||
`fork` _(required)_ production release versioning
|
|
||||||
|
|
||||||
`version` _(required)_ version for particular test document
|
|
||||||
|
|
||||||
`test_cases` _(required)_ list of test cases each of which is formatted to conform to the `test_case` standard defined by `test_suite`. All test cases have optional `name` and `description` string fields.
|
|
||||||
|
|
||||||
## Example test suite
|
|
||||||
`shuffle` is a test suite that defines test cases for the `shuffle()` helper function defined in the `beacon-chain` spec.
|
|
||||||
|
|
||||||
Test cases that conform to the `shuffle` test suite have the following fields:
|
|
||||||
|
|
||||||
* `input` _(required)_ the list of items passed into `shuffle()`
|
|
||||||
* `output` _(required)_ the expected list returned by `shuffle()`
|
|
||||||
* `seed` _(required)_ the seed of entropy passed into `shuffle()`
|
|
||||||
|
|
||||||
As for all test cases, `name` and `description` are optional string fields.
|
|
||||||
|
|
||||||
The following is a sample YAML document for the `shuffle` test suite:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
title: Shuffling Algorithm Tests
|
|
||||||
summary: Test vectors for shuffling a list based upon a seed using `shuffle`
|
|
||||||
test_suite: shuffle
|
|
||||||
fork: tchaikovsky
|
|
||||||
version: 1.0
|
|
||||||
|
|
||||||
test_cases:
|
|
||||||
- input: []
|
|
||||||
output: []
|
|
||||||
seed: !!binary ""
|
|
||||||
- name: boring_list
|
|
||||||
description: List with a single element, 0
|
|
||||||
input: [0]
|
|
||||||
output: [0]
|
|
||||||
seed: !!binary ""
|
|
||||||
- input: [255]
|
|
||||||
output: [255]
|
|
||||||
seed: !!binary ""
|
|
||||||
- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5]
|
|
||||||
output: [1, 6, 4, 1, 6, 6, 2, 2, 4, 5]
|
|
||||||
seed: !!binary ""
|
|
||||||
- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
|
|
||||||
output: [4, 7, 10, 13, 3, 1, 2, 9, 12, 6, 11, 8, 5]
|
|
||||||
seed: !!binary ""
|
|
||||||
- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5]
|
|
||||||
output: [6, 65, 2, 5, 4, 2, 6, 6, 1, 1]
|
|
||||||
seed: !!binary |
|
|
||||||
JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0=
|
|
||||||
```
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
# General test format
|
||||||
|
|
||||||
|
This document defines the YAML format and structure used for ETH 2.0 testing.
|
||||||
|
|
||||||
|
## ToC
|
||||||
|
|
||||||
|
* [About](#about)
|
||||||
|
* [Glossary](#glossary)
|
||||||
|
* [Test format philosophy](#test-format-philosophy)
|
||||||
|
* [Test Suite](#yaml-suite)
|
||||||
|
* [Config](#config)
|
||||||
|
* [Fork-timeline](#fork-timeline)
|
||||||
|
* [Config sourcing](#config-sourcing)
|
||||||
|
* [Test structure](#test-structure)
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
Ethereum 2.0 uses YAML as the format for all cross client tests. This document describes at a high level the general format to which all test files should conform.
|
||||||
|
|
||||||
|
The particular formats of specific types of tests (test suites) are defined in separate documents.
|
||||||
|
|
||||||
|
## Glossary
|
||||||
|
|
||||||
|
- `generator`: a program that outputs one or more `suite` files.
|
||||||
|
- `type`: the specialization of one single `generator`.
|
||||||
|
- `suite`: a YAML file with:
|
||||||
|
- a header: describes the `suite`, and defines what the `suite` is for
|
||||||
|
- a list of test cases
|
||||||
|
- `runner`: where a generator is a "producer", this is the 1-to-1 "consumer". A `runner` focuses on one `type`.
|
||||||
|
- `handler`: a `runner` may be too limited sometimes, you may have a `suite` with a specific focus that requires a different format.
|
||||||
|
To facilitate this, you specify a `handler`: the runner can deal with the format by using the specified handler.
|
||||||
|
Using a `handler` in a `runner` is optional.
|
||||||
|
- `case`: a test case, an entry in the `test_cases` list of a `suite`. A case can be anything in general,
|
||||||
|
but its format should be well-defined in the documentation corresponding to the `type` (and `handler`).\
|
||||||
|
A test has the same exact configuration and fork context as the other entries in the `case` list of its `suite`.
|
||||||
|
- `forks_timeline`: a fork timeline definition, a YAML file containing a key for each fork-name, and a slot number as value.
|
||||||
|
|
||||||
|
## Test format philosophy
|
||||||
|
|
||||||
|
### Config design
|
||||||
|
|
||||||
|
After long discussion, the following types of configured constants were identified:
|
||||||
|
- Never changing: genesis data
|
||||||
|
- Changing, but reliant on old value: e.g. a slot time may change, but if you want to do the conversion
|
||||||
|
`(genesis data, timestamp) -> slot number` you end up needing both constants.
|
||||||
|
- Changing, but kept around during fork transition: finalization may take a while,
|
||||||
|
e.g. an executable has to deal with new deposits and old deposits at the same time. Another example may be economic constants.
|
||||||
|
- Additional, back-wards compatible: new constants are introduced for later phases
|
||||||
|
- Changing: there is a very small chance some constant may really be *replaced*.
|
||||||
|
In this off-chance, it is likely better to include it as an additional variable,
|
||||||
|
and some clients may simply stop supporting the old one, if they do not want to sync from genesis.
|
||||||
|
|
||||||
|
Based on these types of changes, we model the config as a list of key value pairs,
|
||||||
|
that only grows with every fork (they may change in development versions of forks however, git manages this).
|
||||||
|
With this approach, configurations are backwards compatible (older clients ignore unknown variables), and easy to maintain.
|
||||||
|
|
||||||
|
### Fork config design
|
||||||
|
|
||||||
|
There are two types of fork-data:
|
||||||
|
1) timeline: when does a fork take place?
|
||||||
|
2) coverage: what forks are covered by a test?
|
||||||
|
|
||||||
|
The first is neat to have as a separate form: we prevent duplication, and can run with different presets
|
||||||
|
(e.g. fork timeline for a minimal local test, for a public testnet, or for main-net)
|
||||||
|
|
||||||
|
The second is still somewhat ambiguous: some tests may want cover multiple forks, and can do so in different ways:
|
||||||
|
- run one test, transitioning from one to the other
|
||||||
|
- run the same test for both
|
||||||
|
- run a test for every transition from one fork to the other
|
||||||
|
- more
|
||||||
|
|
||||||
|
There is a common factor here however: the options are exclusive, and give a clear idea on what test suites need to be ran to cover testing for a specific fork.
|
||||||
|
The way this list of forks is interpreted, is up to the test-runner:
|
||||||
|
State-transition test suites may want to just declare forks that are being covered in the test suite,
|
||||||
|
whereas shuffling test suites may want to declare a list of forks to test the shuffling algorithm for individually.
|
||||||
|
|
||||||
|
### Test completeness
|
||||||
|
|
||||||
|
We want tests to be independent from any sync-data. If one wants to run a test, the input data should be available from the YAML.
|
||||||
|
The aim is to provide clients with a well-defined scope of work to run a particular set of test-suites.
|
||||||
|
|
||||||
|
- Clients that are complete are expected to contribute to testing, seeking for better resources to get conformance with the spec, and other clients.
|
||||||
|
- Clients that are not complete in functionality can choose to ignore suites that use certain test-runners, or specific handlers of these test-runners.
|
||||||
|
- Clients that are on older versions can test there work based on older releases of the generated tests, and catch up with newer releases when possible.
|
||||||
|
|
||||||
|
## Test Suite
|
||||||
|
|
||||||
|
```
|
||||||
|
title: <required, string, short, one line> -- Display name for the test suite
|
||||||
|
summary: <required, string, average, 1-3 lines> -- Summarizes the test suite
|
||||||
|
forks_timeline: <required, string, reference to a fork definition file, without extension> -- Used to determine the forking timeline
|
||||||
|
forks: <required, list of strings> -- Runner decides what to do: run for each fork, or run for all at once, each fork transition, etc.
|
||||||
|
- ... <required, string, first the phase name, then the spec version>
|
||||||
|
config: <required, string, reference to a config file, without extension> -- Used to determine which set of constants to run (possibly compile time) with
|
||||||
|
runner: <required, string, no spaces, python-like naming format> *MUST be consistent with folder structure*
|
||||||
|
handler: <optional, string, no spaces, python-like naming format> *MUST be consistent with folder structure*
|
||||||
|
|
||||||
|
test_cases: <list, values being maps defining a test case each>
|
||||||
|
...
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Config
|
||||||
|
|
||||||
|
A configuration is a separate YAML file.
|
||||||
|
Separation of configuration and tests aims to:
|
||||||
|
- prevent duplication of a minimal set of tests
|
||||||
|
- make all tests easy to upgrade when a new config constant is introduced.
|
||||||
|
- clearly define which constants to use
|
||||||
|
- share-able between clients, for cross-client short or long lived test-nets
|
||||||
|
- minimize the amounts of different constants permutations to compile as a client. \**
|
||||||
|
|
||||||
|
\**: Some clients prefer compile-time constants and optimizations.
|
||||||
|
They should compile for each configuration once, and run the corresponding tests per build target.
|
||||||
|
|
||||||
|
|
||||||
|
## Fork-timeline
|
||||||
|
|
||||||
|
A fork timeline is (preferably) loaded in as a configuration object into a client, as opposed to the constants configuration:
|
||||||
|
- we do not allocate or optimize any code based on slot numbers
|
||||||
|
- when we transition from one fork to the other, it is preferred to stay online.
|
||||||
|
- we may decide on a slot number for a fork based on external events (e.g. Eth1 log event),
|
||||||
|
a client should be able to activate a fork dynamically.
|
||||||
|
|
||||||
|
Note that phases are considered to be "super forks",
|
||||||
|
i.e. they will just have a fork name, and be more heavy on changes.
|
||||||
|
|
||||||
|
## Config sourcing
|
||||||
|
|
||||||
|
The constants configurations are located in:
|
||||||
|
|
||||||
|
```
|
||||||
|
<specs repo root>/configs/contants/<config name>.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
And copied by CI for testing purposes to:
|
||||||
|
|
||||||
|
```
|
||||||
|
<tests repo root>/configs/contants/<config name>.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
The fork timelines are located in:
|
||||||
|
|
||||||
|
```
|
||||||
|
<specs repo root>/configs/fork_timelines/<timeline name>.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
And copied by CI for testing purposes to:
|
||||||
|
|
||||||
|
```
|
||||||
|
<tests repo root>/configs/fork_timelines/<timeline name>.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test structure
|
||||||
|
|
||||||
|
To prevent parsing of hundreds of different YAML files to test a specific test type,
|
||||||
|
or even more specific, just a handler, tests should be structured in the following nested form:
|
||||||
|
|
||||||
|
```
|
||||||
|
. <--- root of eth2.0 tests repository
|
||||||
|
├── bls <--- collection of handler for a specific test-runner, example runner: "bls"
|
||||||
|
│ ├── signing <--- collection of test suites for a specific handler, example handler: "signing". If no handler, use a dummy folder "main"
|
||||||
|
│ │ ├── sign_msg.yml <--- an entry list of test suites
|
||||||
|
│ │ ... <--- more suite files (optional)
|
||||||
|
│ ... <--- more handlers
|
||||||
|
... <--- more test types
|
||||||
|
```
|
Loading…
Reference in New Issue