diff --git a/test_generators/ssz_generic/main.py b/test_generators/ssz_generic/main.py index 2e34aacf4..5f223eb29 100644 --- a/test_generators/ssz_generic/main.py +++ b/test_generators/ssz_generic/main.py @@ -1,6 +1,41 @@ - +from typing import Iterable from gen_base import gen_runner, gen_typing +import ssz_basic_vector +import ssz_bitlist +import ssz_bitvector +import ssz_boolean +import ssz_uints + + +def create_provider(handler_name: str, suite_name: str, case_maker) -> gen_typing.TestProvider: + + def prepare_fn(configs_path: str) -> str: + return "general" + + def cases_fn() -> Iterable[gen_typing.TestCase]: + for (case_name, case_fn) in case_maker(): + yield gen_typing.TestCase( + fork_name='phase0', + runner_name='ssz_generic', + handler_name=handler_name, + suite_name=suite_name, + case_name=case_name, + case_fn=case_fn + ) + + return gen_typing.TestProvider(prepare=prepare_fn, make_cases=cases_fn) if __name__ == "__main__": - gen_runner.run_generator("ssz_generic", [ssz_random_uint_suite, ssz_wrong_uint_suite, ssz_uint_bounds_suite]) + gen_runner.run_generator("ssz_generic", [ + create_provider("basic_vector", "valid", ssz_basic_vector.valid_cases), + create_provider("basic_vector", "invalid", ssz_basic_vector.invalid_cases), + create_provider("bitlist", "valid", ssz_bitlist.valid_cases), + create_provider("bitlist", "invalid", ssz_bitlist.invalid_cases), + create_provider("bitvector", "valid", ssz_bitvector.valid_cases), + create_provider("bitvector", "invalid", ssz_bitvector.invalid_cases), + create_provider("boolean", "valid", ssz_boolean.valid_cases), + create_provider("boolean", "invalid", ssz_boolean.invalid_cases), + create_provider("uints", "valid", ssz_uints.valid_cases), + create_provider("uints", "invalid", ssz_uints.invalid_cases), + ]) diff --git a/test_generators/ssz_generic/ssz_basic_vector.py b/test_generators/ssz_generic/ssz_basic_vector.py new file mode 100644 index 000000000..fa51113d9 --- /dev/null +++ b/test_generators/ssz_generic/ssz_basic_vector.py @@ -0,0 +1,49 @@ +from .ssz_test_case import invalid_test_case, valid_test_case +from eth2spec.utils.ssz.ssz_typing import boolean, uint8, uint16, uint32, uint64, uint128, uint256, Vector, BasicType +from eth2spec.utils.ssz.ssz_impl import serialize +from random import Random +from typing import Dict +from eth2spec.debug.random_value import RandomizationMode, get_random_ssz_object + + +def basic_vector_case_fn(rng: Random, mode: RandomizationMode, elem_type: BasicType, length: int): + return get_random_ssz_object(rng, Vector[elem_type, length], + max_bytes_length=length * 8, + max_list_length=length, + mode=mode, chaos=False) + + +BASIC_TYPES: Dict[str, BasicType] = { + 'bool': boolean, + 'uint8': uint8, + 'uint16': uint16, + 'uint32': uint32, + 'uint64': uint64, + 'uint128': uint128, + 'uint256': uint256 +} + + +def valid_cases(): + rng = Random(1234) + for (name, typ) in BASIC_TYPES.items(): + for length in [1, 2, 3, 4, 5, 8, 16, 31, 512, 513]: + for mode in [RandomizationMode.mode_random, RandomizationMode.mode_zero, RandomizationMode.mode_max]: + yield f'vec_{name}_{length}_{mode.to_name()}',\ + valid_test_case(lambda: basic_vector_case_fn(rng, mode, typ, length)) + + +def invalid_cases(): + # zero length vectors are illegal + for (name, typ) in BASIC_TYPES: + yield f'vec_{name}_0', lambda: b'' + + rng = Random(1234) + for (name, typ) in BASIC_TYPES.items(): + for length in [1, 2, 3, 4, 5, 8, 16, 31, 512, 513]: + yield f'vec_{name}_{length}_nil', invalid_test_case(lambda: b'') + for mode in [RandomizationMode.mode_random, RandomizationMode.mode_zero, RandomizationMode.mode_max]: + yield f'vec_{name}_{length}_{mode.to_name()}_one_less', \ + invalid_test_case(lambda: serialize(basic_vector_case_fn(rng, mode, typ, length - 1))) + yield f'vec_{name}_{length}_{mode.to_name()}_one_more', \ + invalid_test_case(lambda: serialize(basic_vector_case_fn(rng, mode, typ, length + 1))) diff --git a/test_generators/ssz_generic/ssz_bitlist.py b/test_generators/ssz_generic/ssz_bitlist.py index 45303123d..e0c756aeb 100644 --- a/test_generators/ssz_generic/ssz_bitlist.py +++ b/test_generators/ssz_generic/ssz_bitlist.py @@ -16,7 +16,11 @@ def valid_cases(): rng = Random(1234) for size in [1, 2, 3, 4, 5, 8, 16, 31, 512, 513]: for variation in range(5): - for mode in [RandomizationMode.mode_random, RandomizationMode.mode_zero, RandomizationMode.mode_max]: + for mode in [RandomizationMode.mode_nil_count, + RandomizationMode.mode_max_count, + RandomizationMode.mode_random, + RandomizationMode.mode_zero, + RandomizationMode.mode_max]: yield f'bitlist_{size}_{mode.to_name()}_{variation}', \ valid_test_case(lambda: bitlist_case_fn(rng, mode, size)) diff --git a/test_generators/ssz_generic/ssz_uints.py b/test_generators/ssz_generic/ssz_uints.py index 6fb55279d..93af6b91e 100644 --- a/test_generators/ssz_generic/ssz_uints.py +++ b/test_generators/ssz_generic/ssz_uints.py @@ -11,9 +11,12 @@ def uint_case_fn(rng: Random, mode: RandomizationMode, typ: BasicType): mode=mode, chaos=False) +UINT_TYPES = [uint8, uint16, uint32, uint64, uint128, uint256] + + def valid_cases(): rng = Random(1234) - for uint_type in [uint8, uint16, uint32, uint64, uint128, uint256]: + for uint_type in UINT_TYPES: yield f'uint_{uint_type.byte_len * 8}_last_byte_empty', \ valid_test_case(lambda: uint_type((2 ** ((uint_type.byte_len - 1) * 8)) - 1)) for variation in range(5): @@ -23,7 +26,7 @@ def valid_cases(): def invalid_cases(): - for uint_type in [uint8, uint16, uint32, uint64, uint128, uint256]: + for uint_type in UINT_TYPES: yield f'uint_{uint_type.byte_len * 8}_one_too_high', \ invalid_test_case(lambda: (2 ** (uint_type.byte_len * 8)).to_bytes(uint_type.byte_len + 1, 'little')) for uint_type in [uint8, uint16, uint32, uint64, uint128, uint256]: