Skip to content

Commit

Permalink
Update to latest SSZ with SOS and add Boolean test generators
Browse files Browse the repository at this point in the history
  • Loading branch information
pipermerriam committed Apr 11, 2019
1 parent bbcfb29 commit aa87efb
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 10 deletions.
25 changes: 25 additions & 0 deletions ssz/_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import contextlib
import functools
import random


@contextlib.contextmanager
def random_seed(seed=0):
original_state = random.getstate()
try:
random.seed(seed)
yield
finally:
random.setstate(original_state)


def seed(fn):
@functools.wraps(fn)
def inner(*args, **kwargs):
with random_seed():
return fn(*args, **kwargs)
return inner


def get_random_bytes(length):
return bytes(random.randint(0, 255) for _ in range(length))
122 changes: 122 additions & 0 deletions ssz/bool_test_generators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
from eth_utils import (
to_tuple,
)

import ssz
from ssz.sedes import (
Boolean,
)
from renderers import (
render_test,
render_test_case,
)
from _utils import (
seed,
)



@seed
def generate_bool_true_and_false_test():
test_cases = mk_bool_true_and_false_test_cases()

return render_test(
title="Bool Values",
summary="The two valid values for a boolean",
fork="phase0-0.2.0",
test_cases=test_cases,
)


@seed
def generate_bool_wrong_length_test():
test_cases = mk_bool_wrong_length_test_cases()

return render_test(
title="Bool Wrong Length",
summary="Byte strings of incorrect length",
fork="phase0-0.2.0",
test_cases=test_cases,
)


@seed
def generate_bool_invalid_byte_test():
test_cases = mk_bool_invalid_byte_test_cases()

return render_test(
title="Bool Invalid Byte",
summary="Single byte values that are not 0x00 or 0x01",
fork="phase0-0.2.0",
test_cases=test_cases,
)


@to_tuple
def mk_bool_true_and_false_test_cases():
sedes = Boolean()

true_serial = ssz.encode(True, sedes)
yield render_test_case(
sedes=sedes,
valid=True,
value=True,
serial=true_serial,
tags=("atomic", "bool", "true")
)

false_serial = ssz.encode(False, sedes)
yield render_test_case(
sedes=sedes,
valid=True,
value=False,
serial=false_serial,
tags=("atomic", "bool", "false")
)


WRONG_LENGTH_SERIALS = (
b'',
b'\x00' * 2,
b'\x01' * 2,
b'\xFF' * 2,
b'\x00' * 3,
b'\x01' * 3,
b'\xFF' * 3,
b'\x00' * 5,
b'\x01' * 5,
b'\xFF' * 5,
b'\x00\x01',
b'\x01\x00',
b'\x00\xFF',
b'\x01\xFF',
)


@to_tuple
def mk_bool_wrong_length_test_cases():
tags = ("atomic", "bool", "wrong_length")
sedes = Boolean()

for serial in WRONG_LENGTH_SERIALS:
yield render_test_case(
sedes=sedes,
valid=False,
serial=serial,
tags=tags,
)


@to_tuple
def mk_bool_invalid_byte_test_cases():
tags = ("atomic", "bool", "invalid")
sedes = Boolean()

for i in range(2, 255):
serial = bytes((i,))
yield render_test_case(
sedes=sedes,
valid=False,
serial=serial,
tags=tags,
)
5 changes: 5 additions & 0 deletions ssz/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Mapping,
Sequence,
)
import copy

from eth_utils import (
encode_hex,
Expand Down Expand Up @@ -82,6 +83,10 @@ def render_test_case(*, sedes, valid, value=None, serial=None, description=None,
if tags is None:
tags = []

# Ensure that ruemel doesn't use references, allowing callers of this
# function to re-use the same `tags` object across multiple calls.
tags = tuple(tag for tag in tags)

yield "type", render_type_definition(sedes)
yield "valid", valid
if value is not None:
Expand Down
10 changes: 10 additions & 0 deletions ssz/test_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,21 @@
generate_uint_random_test,
generate_uint_wrong_length_test,
)
from bool_test_generators import (
generate_bool_true_and_false_test,
generate_bool_wrong_length_test,
generate_bool_invalid_byte_test,
)

test_generators = [
# uint
generate_uint_random_test,
generate_uint_wrong_length_test,
generate_uint_bounds_test,
# bool
generate_bool_true_and_false_test,
generate_bool_wrong_length_test,
generate_bool_invalid_byte_test,
]


Expand Down
22 changes: 12 additions & 10 deletions ssz/uint_test_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@
from ssz.sedes import (
UInt,
)

from _utils import (
seed,
get_random_bytes,
)
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))


@seed
def generate_uint_bounds_test():
test_cases = generate_uint_bounds_test_cases() + generate_uint_out_of_bounds_test_cases()

Expand All @@ -36,6 +36,7 @@ def generate_uint_bounds_test():
)


@seed
def generate_uint_random_test():
test_cases = generate_random_uint_test_cases()

Expand All @@ -47,6 +48,7 @@ def generate_uint_random_test():
)


@seed
def generate_uint_wrong_length_test():
test_cases = generate_uint_wrong_length_test_cases()

Expand All @@ -60,15 +62,14 @@ def generate_uint_wrong_length_test():

@to_tuple
def generate_random_uint_test_cases():
tags = ("atomic", "uint", "random")

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,
Expand All @@ -80,6 +81,8 @@ def generate_random_uint_test_cases():

@to_tuple
def generate_uint_wrong_length_test_cases():
tags = ("atomic", "uint", "wrong_length")

for bit_size in BIT_SIZES:
sedes = UInt(bit_size)
lengths = sorted({
Expand All @@ -91,7 +94,6 @@ def generate_uint_wrong_length_test_cases():
})
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,
Expand Down

0 comments on commit aa87efb

Please sign in to comment.