Skip to content

Commit

Permalink
Test identical functionality across versions (#605)
Browse files Browse the repository at this point in the history
  • Loading branch information
tzaffi committed Jan 11, 2023
1 parent 319e0bb commit dc6466a
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 123 deletions.
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
black==22.3.0
flake8==5.0.4
flake8-tidy-imports==4.6.0
graviton@git+https://github.com/algorand/graviton@v0.5.0
graviton@git+https://github.com/algorand/graviton@v0.7.0
mypy==0.991
pytest==7.2.0
pytest-cov==3.0.0
Expand Down
62 changes: 49 additions & 13 deletions tests/blackbox.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Callable, Generic, Sequence, TypeVar, cast
from typing import Any, Callable, Generic, Optional, Sequence, TypeVar, cast
from dataclasses import dataclass

import algosdk.abi
Expand Down Expand Up @@ -144,8 +144,14 @@ def decorator_blackbox(func: SubroutineFnWrapper | ABIReturnSubroutine):

@dataclass(frozen=True)
class _MatchMode(Generic[Output]):
runner: Optional["PyTealDryRunExecutor"]
app_case: Lazy
signature_case: Lazy
trace: Any = None

def __post_init__(self):
if self.runner and self.trace:
self.runner.add_trace(self.trace)

def __call__(self, mode: Mode, *args, **kwargs) -> Output:
match mode:
Expand All @@ -159,6 +165,7 @@ def __call__(self, mode: Mode, *args, **kwargs) -> Output:

def mode_to_execution_mode(mode: Mode) -> blackbox.ExecutionMode:
return _MatchMode(
runner=None,
app_case=lambda: blackbox.ExecutionMode.Application,
signature_case=lambda: blackbox.ExecutionMode.Signature,
)(mode)
Expand Down Expand Up @@ -192,9 +199,31 @@ def __init__(self, subr: BlackboxWrapper, mode: Mode):

self._pyteal_lambda: Callable[..., Expr] = approval

self.traces: list = []

def add_trace(self, trace: Any) -> None:
self.traces.append(trace)

def is_abi(self) -> bool:
return isinstance(self.subr.subroutine, ABIReturnSubroutine)

def abi_method_signature(self) -> None | str:
if self.is_abi():
abi_subr = cast(ABIReturnSubroutine, self.subr.subroutine)
return abi_subr.method_signature()

# create an artificial method signature
# based on the `abi_argument_types()` and `abi_return_type()`
if arg_types := self.abi_argument_types():
if all(t is None for t in arg_types):
return None

ret_type = self.abi_return_type()
ret = str(ret_type) if ret_type else "void"
return f"ptdre_foo({','.join(map(str, arg_types))}){ret}"

return None

def abi_argument_types(self) -> None | list[algosdk.abi.ABIType]:
if not (self.input_types or self.is_abi()):
return None
Expand Down Expand Up @@ -389,6 +418,7 @@ def approval():

def compile(self, version: int, assemble_constants: bool = False) -> str:
return _MatchMode(
runner=self,
app_case=lambda: compileTeal(
self.program(),
self.mode,
Expand All @@ -408,41 +438,47 @@ def dryrun_on_sequence(
inputs: list[Sequence[PyTypes]],
compiler_version=6,
) -> list[DryRunInspector]:
teal = self.compile(compiler_version)
return _MatchMode(
self,
app_case=lambda: DryRunExecutor.dryrun_app_on_sequence(
algod=algod_with_assertion(),
teal=self.compile(compiler_version),
teal=teal,
inputs=inputs,
abi_argument_types=self.abi_argument_types(),
abi_return_type=self.abi_return_type(),
abi_method_signature=self.abi_method_signature(),
omit_method_selector=True,
),
signature_case=lambda: DryRunExecutor.dryrun_logicsig_on_sequence(
algod=algod_with_assertion(),
teal=self.compile(compiler_version),
teal=teal,
inputs=inputs,
abi_argument_types=self.abi_argument_types(),
abi_return_type=self.abi_return_type(),
abi_method_signature=self.abi_method_signature(),
omit_method_selector=True,
),
trace=teal,
)(self.mode)

def dryrun(
self,
args: Sequence[bytes | str | int],
compiler_version=6,
) -> DryRunInspector:
teal = self.compile(compiler_version)
return _MatchMode(
self,
app_case=lambda: DryRunExecutor.dryrun_app(
algod_with_assertion(),
self.compile(compiler_version),
teal,
args,
self.abi_argument_types(),
self.abi_return_type(),
abi_method_signature=self.abi_method_signature(),
omit_method_selector=True,
),
signature_case=lambda: DryRunExecutor.dryrun_logicsig(
algod_with_assertion(),
self.compile(compiler_version),
teal,
args,
self.abi_argument_types(),
self.abi_return_type(),
abi_method_signature=self.abi_method_signature(),
omit_method_selector=True,
),
trace=teal,
)(self.mode)
6 changes: 3 additions & 3 deletions tests/integration/graviton_abi_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ def test_integer65(version: int):

bbpt_add = PyTealDryRunExecutor(int65_add, pt.Mode.Application)

def pynum_to_tuple(n):
def pynum_to_int65tuple(n):
return (n >= 0, abs(n))

def pytuple_to_num(t):
Expand All @@ -323,10 +323,10 @@ def pytuple_to_num(t):
random.seed(42)

choices = range(-9_999, 10_000)
unary_inputs = [(pynum_to_tuple(x),) for x in random.sample(choices, N)]
unary_inputs = [(pynum_to_int65tuple(x),) for x in random.sample(choices, N)]

binary_inputs = [
(pynum_to_tuple(x), pynum_to_tuple(y))
(pynum_to_int65tuple(x), pynum_to_int65tuple(y))
for x, y in zip(random.sample(choices, N), random.sample(choices, N))
]

Expand Down

0 comments on commit dc6466a

Please sign in to comment.