eth2.0-specs/specs/test_formats/ssz_generic/README.md

198 lines
4.4 KiB
Markdown

# SSZ, generic tests
This set of test-suites provides general testing for SSZ:
to decode any container/list/vector/other type from binary data, encode it back, and compute the hash-tree-root.
This test collection for general-purpose SSZ is experimental.
The `ssz_static` suite is the required minimal support for SSZ, and should be prioritized.
The `ssz_generic` tests are split up into different handler, each specialized into a SSZ type:
- Vectors
- `basic_vector`
- `complex_vector` *not supported yet*
- List
- `basic_list` *not supported yet*
- `complex_list` *not supported yet*
- Bitfields
- `bitvector`
- `bitlist`
- Basic types
- `boolean`
- `uints`
- Containers
- `containers`
## Format
For each type, a `valid` and a `invalid` suite is implemented.
The cases have the same format, but those in the `invalid` suite only declare a subset of the data a test in the `valid` declares.
Each of the handlers encodes the SSZ type declaration in the file-name. See [Type Declarations](#type-declarations).
### `valid`
Valid has 3 parts: `meta.yaml`, `serialized.ssz`, `value.yaml`
### `meta.yaml`
Valid ssz objects can have a hash-tree-root, and for some types also a signing-root.
The expected roots are encoded into the metadata yaml:
```yaml
root: Bytes32 -- Hash-tree-root of the object
signing_root: Bytes32 -- Signing-root of the object
```
The `Bytes32` is encoded as a string, hexadecimal encoding, prefixed with `0x`.
### `serialized.ssz`
The serialized form of the object, as raw SSZ bytes.
### `value.yaml`
The object, encoded as a YAML structure. Using the same familiar encoding as YAML data in the other test suites.
### Conditions
The conditions are the same for each type:
- Encoding: After encoding the given `value` object, the output should match `serialized`.
- Decoding: After decoding the given `serialized` bytes, it should match the `value` object.
- Hash-tree-root: the root should match the root declared in the metadata.
- Signing-root: if present in metadata, the signing root of the object should match the container.
## `invalid`
Test cases in the `invalid` suite only include the `serialized.ssz`
#### Condition
Unlike the `valid` suite, invalid encodings do not have any `value` or hash tree root.
The `serialized` data should simply not be decoded without raising an error.
Note that for some type declarations in the invalid suite, the type itself may technically be invalid.
This is a valid way of detecting `invalid` data too. E.g. a 0-length basic vector.
## Type declarations
Most types are not as static, and reasonably be constructed during test runtime from the test case name.
Formats are listed below.
For each test case, an additional `_{extra...}` may be appended to the name,
where `{extra...}` contains a human readable indication of the test case contents for debugging purposes.
### `basic_vector`
```
Template:
vec_{element type}_{length}
Data:
{element type}: bool, uint8, uint16, uint32, uint64, uint128, uint256
{length}: an unsigned integer
```
### `bitlist`
```
Template:
bitlist_{limit}
Data:
{limit}: the list limit, in bits, of the bitlist. Does not include the length-delimiting bit in the serialized form.
```
### `bitvector`
```
Template:
bitvec_{length}
Data:
{length}: the length, in bits, of the bitvector.
```
### `boolean`
A boolean has no type variations. Instead, file names just plainly describe the contents for debugging.
### `uints`
```
Template:
uint_{size}
Data:
{size}: the uint size: 8, 16, 32, 64, 128 or 256.
```
### `containers`
Containers are more complicated than the other types. Instead, a set of pre-defined container structures is referenced:
```
Template:
{container name}
Data:
{container name}: Any of the container names listed below (exluding the `(Container)` python super type)
```
```python
class SingleFieldTestStruct(Container):
A: byte
class SmallTestStruct(Container):
A: uint16
B: uint16
class FixedTestStruct(Container):
A: uint8
B: uint64
C: uint32
class VarTestStruct(Container):
A: uint16
B: List[uint16, 1024]
C: uint8
class ComplexTestStruct(Container):
A: uint16
B: List[uint16, 128]
C: uint8
D: Bytes[256]
E: VarTestStruct
F: Vector[FixedTestStruct, 4]
G: Vector[VarTestStruct, 2]
class BitsStruct(Container):
A: Bitlist[5]
B: Bitvector[2]
C: Bitvector[1]
D: Bitlist[6]
E: Bitvector[8]
```