fix imports, new container tests, update randomization logic
This commit is contained in:
parent
aea8237631
commit
88dbd18394
|
@ -5,6 +5,7 @@ import ssz_bitlist
|
|||
import ssz_bitvector
|
||||
import ssz_boolean
|
||||
import ssz_uints
|
||||
import ssz_container
|
||||
|
||||
|
||||
def create_provider(handler_name: str, suite_name: str, case_maker) -> gen_typing.TestProvider:
|
||||
|
@ -38,4 +39,6 @@ if __name__ == "__main__":
|
|||
create_provider("boolean", "invalid", ssz_boolean.invalid_cases),
|
||||
create_provider("uints", "valid", ssz_uints.valid_cases),
|
||||
create_provider("uints", "invalid", ssz_uints.invalid_cases),
|
||||
create_provider("containers", "valid", ssz_container.valid_cases),
|
||||
create_provider("containers", "invalid", ssz_container.invalid_cases),
|
||||
])
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from .ssz_test_case import invalid_test_case, valid_test_case
|
||||
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
|
||||
|
@ -27,23 +27,34 @@ BASIC_TYPES: Dict[str, BasicType] = {
|
|||
def valid_cases():
|
||||
rng = Random(1234)
|
||||
for (name, typ) in BASIC_TYPES.items():
|
||||
random_modes = [RandomizationMode.mode_zero, RandomizationMode.mode_max]
|
||||
if name != 'bool':
|
||||
random_modes.append(RandomizationMode.mode_random)
|
||||
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()}',\
|
||||
for mode in random_modes:
|
||||
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''
|
||||
for (name, typ) in BASIC_TYPES.items():
|
||||
yield f'vec_{name}_0', invalid_test_case(lambda: b'')
|
||||
|
||||
rng = Random(1234)
|
||||
for (name, typ) in BASIC_TYPES.items():
|
||||
random_modes = [RandomizationMode.mode_zero, RandomizationMode.mode_max]
|
||||
if name != 'bool':
|
||||
random_modes.append(RandomizationMode.mode_random)
|
||||
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]:
|
||||
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)))
|
||||
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', \
|
||||
invalid_test_case(lambda: serialize(basic_vector_case_fn(rng, mode, typ, length))[:-1])
|
||||
yield f'vec_{name}_{length}_{mode.to_name()}_one_byte_more', \
|
||||
invalid_test_case(lambda: serialize(basic_vector_case_fn(rng, mode, typ, length))
|
||||
+ serialize(basic_vector_case_fn(rng, mode, uint8, 1)))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from .ssz_test_case import invalid_test_case, valid_test_case
|
||||
from ssz_test_case import invalid_test_case, valid_test_case
|
||||
from eth2spec.utils.ssz.ssz_typing import Bitlist
|
||||
from eth2spec.utils.ssz.ssz_impl import serialize
|
||||
from random import Random
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from .ssz_test_case import invalid_test_case, valid_test_case
|
||||
from ssz_test_case import invalid_test_case, valid_test_case
|
||||
from eth2spec.utils.ssz.ssz_typing import Bitvector
|
||||
from eth2spec.utils.ssz.ssz_impl import serialize
|
||||
from random import Random
|
||||
|
@ -21,7 +21,7 @@ def valid_cases():
|
|||
|
||||
def invalid_cases():
|
||||
# zero length bitvecors are illegal
|
||||
yield 'bitvec_0', lambda: b''
|
||||
yield 'bitvec_0', invalid_test_case(lambda: b'')
|
||||
rng = Random(1234)
|
||||
for (typ_size, test_size) in [(1, 2), (2, 3), (3, 4), (4, 5),
|
||||
(5, 6), (8, 9), (9, 8), (16, 8), (32, 33), (512, 513)]:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from .ssz_test_case import valid_test_case, invalid_test_case
|
||||
from ssz_test_case import valid_test_case, invalid_test_case
|
||||
from eth2spec.utils.ssz.ssz_typing import boolean
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
from ssz_test_case import invalid_test_case, valid_test_case
|
||||
from eth2spec.utils.ssz.ssz_typing import SSZType, Container, byte, uint8, uint16, \
|
||||
uint32, uint64, List, Bytes, Vector, Bitvector, Bitlist
|
||||
from eth2spec.utils.ssz.ssz_impl import serialize
|
||||
from random import Random
|
||||
from typing import Dict, Tuple, Sequence, Callable
|
||||
from eth2spec.debug.random_value import RandomizationMode, get_random_ssz_object
|
||||
|
||||
|
||||
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]
|
||||
|
||||
|
||||
def container_case_fn(rng: Random, mode: RandomizationMode, typ: SSZType):
|
||||
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]]] = {
|
||||
'SingleFieldTestStruct': (SingleFieldTestStruct, []),
|
||||
'SmallTestStruct': (SmallTestStruct, []),
|
||||
'FixedTestStruct': (FixedTestStruct, []),
|
||||
'VarTestStruct': (VarTestStruct, [2]),
|
||||
'ComplexTestStruct': (ComplexTestStruct, [2, 2 + 4 + 1, 2 + 4 + 1 + 4]),
|
||||
'BitsStruct': (BitsStruct, [0, 4 + 1 + 1, 4 + 1 + 1 + 4]),
|
||||
}
|
||||
|
||||
|
||||
def valid_cases():
|
||||
rng = Random(1234)
|
||||
for (name, (typ, offsets)) in PRESET_CONTAINERS.items():
|
||||
for mode in [RandomizationMode.mode_zero, RandomizationMode.mode_max]:
|
||||
yield f'{name}_{mode.to_name()}', valid_test_case(lambda: container_case_fn(rng, mode, typ))
|
||||
random_modes = [RandomizationMode.mode_random, RandomizationMode.mode_zero, RandomizationMode.mode_max]
|
||||
if len(offsets) != 0:
|
||||
random_modes.extend([RandomizationMode.mode_nil_count,
|
||||
RandomizationMode.mode_one_count,
|
||||
RandomizationMode.mode_max_count])
|
||||
for mode in random_modes:
|
||||
for variation in range(10):
|
||||
yield f'{name}_{mode.to_name()}_{variation}', \
|
||||
valid_test_case(lambda: container_case_fn(rng, mode, typ))
|
||||
for variation in range(3):
|
||||
yield f'{name}_{mode.to_name()}_chaos_{variation}', \
|
||||
valid_test_case(lambda: container_case_fn(rng, mode, typ))
|
||||
|
||||
|
||||
def mod_offset(b: bytes, offset_index: int, change: Callable[[int], int]):
|
||||
return b[:offset_index] + \
|
||||
(change(int.from_bytes(b[offset_index:offset_index + 4], byteorder='little')) & 0xffffffff) \
|
||||
.to_bytes(length=4, byteorder='little') + \
|
||||
b[offset_index + 4:]
|
||||
|
||||
|
||||
def invalid_cases():
|
||||
rng = Random(1234)
|
||||
for (name, (typ, offsets)) in PRESET_CONTAINERS.items():
|
||||
# using mode_max_count, so that the extra byte cannot be picked up as normal list content
|
||||
yield f'{name}_extra_byte', \
|
||||
invalid_test_case(lambda: serialize(
|
||||
container_case_fn(rng, RandomizationMode.mode_max_count, typ)) + b'\xff')
|
||||
|
||||
if len(offsets) != 0:
|
||||
# Note: there are many more ways to have invalid offsets,
|
||||
# these are just example to get clients started looking into hardening ssz.
|
||||
for mode in [RandomizationMode.mode_random,
|
||||
RandomizationMode.mode_nil_count,
|
||||
RandomizationMode.mode_one_count,
|
||||
RandomizationMode.mode_max_count]:
|
||||
if len(offsets) != 0:
|
||||
for offset_index in offsets:
|
||||
yield f'{name}_offset_{offset_index}_plus_one', \
|
||||
invalid_test_case(lambda: mod_offset(
|
||||
b=serialize(container_case_fn(rng, mode, typ)),
|
||||
offset_index=offset_index,
|
||||
change=lambda x: x + 1
|
||||
))
|
||||
yield f'{name}_offset_{offset_index}_zeroed', \
|
||||
invalid_test_case(lambda: mod_offset(
|
||||
b=serialize(container_case_fn(rng, mode, typ)),
|
||||
offset_index=offset_index,
|
||||
change=lambda x: 0
|
||||
))
|
|
@ -1,4 +1,4 @@
|
|||
from .ssz_test_case import invalid_test_case, valid_test_case
|
||||
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 random import Random
|
||||
from eth2spec.debug.random_value import RandomizationMode, get_random_ssz_object
|
||||
|
|
Loading…
Reference in New Issue