import random from eth_utils import ( to_tuple, ) import ssz from ssz.sedes import ( UInt, ) from renderers import ( render_test, render_test_case, ) random.seed(0) BIT_SIZES = [i for i in range(8, 512 + 1, 8)] RANDOM_TEST_CASES_PER_BIT_SIZE = 10 RANDOM_TEST_CASES_PER_LENGTH = 3 def get_random_bytes(length): return bytes(random.randint(0, 255) for _ in range(length)) def generate_uint_bounds_test(): test_cases = generate_uint_bounds_test_cases() + generate_uint_out_of_bounds_test_cases() return render_test( title="UInt Bounds", summary="Integers right at or beyond the bounds of the allowed value range", fork="phase0-0.2.0", test_cases=test_cases, ) def generate_uint_random_test(): test_cases = generate_random_uint_test_cases() return render_test( title="UInt Random", summary="Random integers chosen uniformly over the allowed value range", fork="phase0-0.2.0", test_cases=test_cases, ) def generate_uint_wrong_length_test(): test_cases = generate_uint_wrong_length_test_cases() return render_test( title="UInt Wrong Length", summary="Serialized integers that are too short or too long", fork="phase0-0.2.0", test_cases=test_cases, ) @to_tuple def generate_random_uint_test_cases(): for bit_size in BIT_SIZES: sedes = UInt(bit_size) for _ in range(RANDOM_TEST_CASES_PER_BIT_SIZE): value = random.randrange(0, 2 ** bit_size) serial = ssz.encode(value, sedes) # note that we need to create the tags in each loop cycle, otherwise ruamel will use # YAML references which makes the resulting file harder to read tags = tuple(["atomic", "uint", "random"]) yield render_test_case( sedes=sedes, valid=True, value=value, serial=serial, tags=tags, ) @to_tuple def generate_uint_wrong_length_test_cases(): for bit_size in BIT_SIZES: sedes = UInt(bit_size) lengths = sorted({ 0, sedes.length // 2, sedes.length - 1, sedes.length + 1, sedes.length * 2, }) for length in lengths: for _ in range(RANDOM_TEST_CASES_PER_LENGTH): tags = tuple(["atomic", "uint", "wrong_length"]) yield render_test_case( sedes=sedes, valid=False, serial=get_random_bytes(length), tags=tags, ) @to_tuple def generate_uint_bounds_test_cases(): common_tags = ("atomic", "uint") for bit_size in BIT_SIZES: sedes = UInt(bit_size) for value, tag in ((0, "uint_lower_bound"), (2 ** bit_size - 1, "uint_upper_bound")): serial = ssz.encode(value, sedes) yield render_test_case( sedes=sedes, valid=True, value=value, serial=serial, tags=common_tags + (tag,), ) @to_tuple def generate_uint_out_of_bounds_test_cases(): common_tags = ("atomic", "uint") for bit_size in BIT_SIZES: sedes = UInt(bit_size) for value, tag in ((-1, "uint_underflow"), (2 ** bit_size, "uint_overflow")): yield render_test_case( sedes=sedes, valid=False, value=value, tags=common_tags + (tag,), )