From 22620bfe5dec9b75acc686d025c375ad72dfeafc Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 11 Mar 2020 23:18:06 +0100 Subject: [PATCH] Fix generic SSZ tests, update remerkleable with small bugfix --- setup.py | 2 +- .../ssz_generic/ssz_basic_vector.py | 17 +++++++---- tests/generators/ssz_generic/ssz_container.py | 8 ++--- tests/generators/ssz_generic/ssz_test_case.py | 4 +-- tests/generators/ssz_generic/ssz_uints.py | 29 +++++++++++-------- 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/setup.py b/setup.py index 6dd4de861..e0f2880d9 100644 --- a/setup.py +++ b/setup.py @@ -470,7 +470,7 @@ setup( "pycryptodome==3.9.4", "py_ecc==2.0.0", "dataclasses==0.6", - "remerkleable==0.1.11", + "remerkleable==0.1.12", "ruamel.yaml==0.16.5" ] ) diff --git a/tests/generators/ssz_generic/ssz_basic_vector.py b/tests/generators/ssz_generic/ssz_basic_vector.py index 6e7e08daa..51dfd4ba1 100644 --- a/tests/generators/ssz_generic/ssz_basic_vector.py +++ b/tests/generators/ssz_generic/ssz_basic_vector.py @@ -1,19 +1,19 @@ 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_typing import boolean, uint8, uint16, uint32, uint64, uint128, uint256, Vector, BasicView from eth2spec.utils.ssz.ssz_impl import serialize from random import Random -from typing import Dict +from typing import Dict, Type 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): +def basic_vector_case_fn(rng: Random, mode: RandomizationMode, elem_type: Type[BasicView], 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] = { +BASIC_TYPES: Dict[str, Type[BasicView]] = { 'bool': boolean, 'uint8': uint8, 'uint16': uint16, @@ -49,8 +49,13 @@ def invalid_cases(): 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 random_modes: - yield f'vec_{name}_{length}_{mode.to_name()}_one_less', \ - invalid_test_case(lambda: serialize(basic_vector_case_fn(rng, mode, typ, length - 1))) + if length == 1: + # empty bytes, no elements. It may seem valid, but empty fixed-size elements are not valid SSZ. + yield f'vec_{name}_{length}_{mode.to_name()}_one_less', \ + invalid_test_case(lambda: b"") + else: + 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))) yield f'vec_{name}_{length}_{mode.to_name()}_one_byte_less', \ diff --git a/tests/generators/ssz_generic/ssz_container.py b/tests/generators/ssz_generic/ssz_container.py index ecb2d8c34..cf7c33839 100644 --- a/tests/generators/ssz_generic/ssz_container.py +++ b/tests/generators/ssz_generic/ssz_container.py @@ -1,9 +1,9 @@ from ssz_test_case import invalid_test_case, valid_test_case -from eth2spec.utils.ssz.ssz_typing import SSZType, Container, byte, uint8, uint16, \ +from eth2spec.utils.ssz.ssz_typing import View, Container, byte, uint8, uint16, \ uint32, uint64, List, ByteList, Vector, Bitvector, Bitlist from eth2spec.utils.ssz.ssz_impl import serialize from random import Random -from typing import Dict, Tuple, Sequence, Callable +from typing import Dict, Tuple, Sequence, Callable, Type from eth2spec.debug.random_value import RandomizationMode, get_random_ssz_object @@ -46,14 +46,14 @@ class BitsStruct(Container): E: Bitvector[8] -def container_case_fn(rng: Random, mode: RandomizationMode, typ: SSZType): +def container_case_fn(rng: Random, mode: RandomizationMode, typ: Type[View]): return get_random_ssz_object(rng, typ, max_bytes_length=2000, max_list_length=2000, mode=mode, chaos=False) -PRESET_CONTAINERS: Dict[str, Tuple[SSZType, Sequence[int]]] = { +PRESET_CONTAINERS: Dict[str, Tuple[Type[View], Sequence[int]]] = { 'SingleFieldTestStruct': (SingleFieldTestStruct, []), 'SmallTestStruct': (SmallTestStruct, []), 'FixedTestStruct': (FixedTestStruct, []), diff --git a/tests/generators/ssz_generic/ssz_test_case.py b/tests/generators/ssz_generic/ssz_test_case.py index 42955bd3e..6cef4960b 100644 --- a/tests/generators/ssz_generic/ssz_test_case.py +++ b/tests/generators/ssz_generic/ssz_test_case.py @@ -1,10 +1,10 @@ from eth2spec.utils.ssz.ssz_impl import serialize, hash_tree_root from eth2spec.debug.encode import encode -from eth2spec.utils.ssz.ssz_typing import SSZValue, Container +from eth2spec.utils.ssz.ssz_typing import View from typing import Callable -def valid_test_case(value_fn: Callable[[], SSZValue]): +def valid_test_case(value_fn: Callable[[], View]): def case_fn(): value = value_fn() yield "value", "data", encode(value) diff --git a/tests/generators/ssz_generic/ssz_uints.py b/tests/generators/ssz_generic/ssz_uints.py index b21fb251c..896443f4c 100644 --- a/tests/generators/ssz_generic/ssz_uints.py +++ b/tests/generators/ssz_generic/ssz_uints.py @@ -1,12 +1,13 @@ from ssz_test_case import invalid_test_case, valid_test_case -from eth2spec.utils.ssz.ssz_typing import BasicType, uint8, uint16, uint32, uint64, uint128, uint256 +from eth2spec.utils.ssz.ssz_typing import BasicView, uint8, uint16, uint32, uint64, uint128, uint256 from random import Random +from typing import Type from eth2spec.debug.random_value import RandomizationMode, get_random_ssz_object -def uint_case_fn(rng: Random, mode: RandomizationMode, typ: BasicType): +def uint_case_fn(rng: Random, mode: RandomizationMode, typ: Type[BasicView]): return get_random_ssz_object(rng, typ, - max_bytes_length=typ.byte_len, + max_bytes_length=typ.type_byte_length(), max_list_length=1, mode=mode, chaos=False) @@ -17,21 +18,25 @@ UINT_TYPES = [uint8, uint16, uint32, uint64, uint128, uint256] def valid_cases(): rng = Random(1234) 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)) + byte_len = uint_type.type_byte_length() + yield f'uint_{byte_len * 8}_last_byte_empty', \ + valid_test_case(lambda: uint_type((2 ** ((byte_len - 1) * 8)) - 1)) for variation in range(5): for mode in [RandomizationMode.mode_random, RandomizationMode.mode_zero, RandomizationMode.mode_max]: - yield f'uint_{uint_type.byte_len * 8}_{mode.to_name()}_{variation}', \ + yield f'uint_{byte_len * 8}_{mode.to_name()}_{variation}', \ valid_test_case(lambda: uint_case_fn(rng, mode, uint_type)) def invalid_cases(): 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')) + byte_len = uint_type.type_byte_length() + yield f'uint_{byte_len * 8}_one_too_high', \ + invalid_test_case(lambda: (2 ** (byte_len * 8)).to_bytes(byte_len + 1, 'little')) for uint_type in [uint8, uint16, uint32, uint64, uint128, uint256]: - yield f'uint_{uint_type.byte_len * 8}_one_byte_longer', \ - invalid_test_case(lambda: (2 ** (uint_type.byte_len * 8) - 1).to_bytes(uint_type.byte_len + 1, 'little')) + byte_len = uint_type.type_byte_length() + yield f'uint_{byte_len * 8}_one_byte_longer', \ + invalid_test_case(lambda: (2 ** (byte_len * 8) - 1).to_bytes(byte_len + 1, 'little')) for uint_type in [uint8, uint16, uint32, uint64, uint128, uint256]: - yield f'uint_{uint_type.byte_len * 8}_one_byte_shorter', \ - invalid_test_case(lambda: (2 ** ((uint_type.byte_len - 1) * 8) - 1).to_bytes(uint_type.byte_len - 1, 'little')) + byte_len = uint_type.type_byte_length() + yield f'uint_{byte_len * 8}_one_byte_shorter', \ + invalid_test_case(lambda: (2 ** ((byte_len - 1) * 8) - 1).to_bytes(byte_len - 1, 'little'))