Skip to content
This repository has been archived by the owner on May 23, 2023. It is now read-only.

Piper/add property based testing for abi encoding #355

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ pyethereum/todo.txt
pyethereum/monkeypatch.py
.eggs
.cache
.hypothesis
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ env:
- TOX_ENV=py27
global:
secure: cKbIgpTJ1yjKLBxpCEiT6IH7NShDWZUE+BvnrAfc+ujCsR6LyLJcKxFQmKnWryJCqg7fp82Ep2bF2oDKzanAROar2xDY1SFGbai42seYMaFCw53YPGJ6u3VNCcfT0rN9BWgE7el/m4fjcD6CRsZYKArNNJbMX8csRt3uXXCFLso=
cache:
directories:
- $HOME/.cache/pip
- .hypothesis
install:
- pip install -Ur requirements.txt
- pip install -Ur dev_requirements.txt
Expand Down
1 change: 1 addition & 0 deletions dev_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ coveralls
pytest>=2.9.0
pytest-catchlog==1.2.2
pytest-timeout==1.0.0
hypothesis>=3.4.0
https://github.com/ethereum/serpent/tarball/develop
88 changes: 88 additions & 0 deletions ethereum/tests/abi_type_strategies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import itertools

import hypothesis.strategies as st


strat_int256 = st.integers(min_value=-1 * 2**255, max_value=2**255 - 1)
strat_uint256 = st.integers(min_value=0, max_value=2**256 - 1)

MAX_LIST_SIZE = 8
MIN_LIST_SIZE = 0


uint_raw_strats = [
('uint' + str(sub), st.integers(min_value=0, max_value=2**sub - 1))
for sub in range(8, 257, 8)
]
uint_strats = [
st.tuples(st.just(key), strat) for key, strat in uint_raw_strats
]


int_raw_strats = [
('int' + str(sub), st.integers(min_value=-1 * 2**(sub - 1), max_value=2**(sub - 1) - 1))
for sub in range(8, 257, 8)
]
int_strats = [
st.tuples(st.just(key), strat) for key, strat in int_raw_strats
]


bytes_raw_strats = [
('bytes' + str(sub), st.binary(min_size=sub, max_size=sub))
for sub in range(1, 33)
]
bytes_strats = [
st.tuples(st.just(key), strat) for key, strat in bytes_raw_strats
]


address_raw_strat = st.binary(min_size=20, max_size=20).map(lambda v: v.encode('hex'))
address_strat = st.tuples(
st.just('address'),
address_raw_strat,
)


all_basic_raw_strats = list(itertools.chain(
int_raw_strats, uint_raw_strats, bytes_raw_strats, [('address', address_raw_strat)],
))
all_basic_strats = list(itertools.chain(
int_strats, uint_strats, bytes_strats, [address_strat],
))


unsized_list_raw_strats = [
(type_str + "[]", st.lists(type_strat, min_size=0, max_size=MAX_LIST_SIZE))
for type_str, type_strat in all_basic_raw_strats
]
unsized_list_strats = [
st.tuples(st.just(type_str), type_strat)
for type_str, type_strat in unsized_list_raw_strats
]


sized_list_strats = [
st.tuples(
st.shared(
st.integers(min_value=MIN_LIST_SIZE, max_value=MAX_LIST_SIZE),
key="n",
).map(lambda n: type_str + "[{0}]".format(n)),
st.shared(
st.integers(min_value=MIN_LIST_SIZE, max_value=MAX_LIST_SIZE),
key="n",
).flatmap(lambda n: st.lists(type_strat, min_size=n, max_size=n))
) for type_str, type_strat in all_basic_raw_strats
]


def zip_types_and_values(types_and_values):
types, values = zip(*types_and_values)
return list(types), list(values)


all_abi_strats = st.lists(
st.one_of(itertools.chain(unsized_list_strats, sized_list_strats, all_basic_strats)),
min_size=1,
max_size=10,
).map(zip_types_and_values)
17 changes: 16 additions & 1 deletion ethereum/tests/test_abi.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
import os
import pytest
from hypothesis import given
import ethereum.testutils as testutils
from ethereum.slogging import get_logger
import ethereum.abi as abi
from ethereum.utils import zpad

from .abi_type_strategies import all_abi_strats


logger = get_logger()


@given(all_abi_strats)
def test_reversability(types_and_values):
"""
Tests round trip encoding and decoding for basic types and lists of basic
types.
"""
types, value = types_and_values
encoded_value = abi.encode_abi(types, value)
decoded_value = abi.decode_abi(types, encoded_value)
assert value == decoded_value


def test_abi_encode_var_sized_array():
abi.encode_abi(['address[]'], [[b'\x00' * 20] * 3])

Expand Down