Module hebi.tests.test_misc
Expand source code
import unittest
import frozendict
from hypothesis import given
from hypothesis import strategies as st
from parameterized import parameterized
from uplc import ast as uplc, eval as uplc_eval
from ..util import CompilerError
from .. import compiler, prelude
def fib(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
class MiscTest(unittest.TestCase):
def test_assert_sum_contract_succeed(self):
input_file = "examples/smart_contracts/assert_sum.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [uplc.PlutusInteger(20), uplc.PlutusInteger(22), uplc.BuiltinUnit()]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
self.assertEqual(ret, uplc.PlutusConstr(0, []))
def test_assert_sum_contract_fail(self):
input_file = "examples/smart_contracts/assert_sum.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
try:
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [
uplc.PlutusInteger(0),
uplc.PlutusInteger(23),
uplc.BuiltinUnit(),
]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
failed = False
except Exception as e:
failed = True
self.assertTrue(failed, "Machine did validate the content")
@given(
a=st.integers(),
b=st.integers(),
)
def test_sum(self, a: int, b: int):
input_file = "examples/sum.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [uplc.PlutusInteger(a), uplc.PlutusInteger(b)]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
self.assertEqual(ret, uplc.PlutusInteger(a + b))
def test_complex_datum_correct_vals(self):
input_file = "examples/complex_datum.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [
uplc.data_from_cbor(
bytes.fromhex(
"d8799fd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd87a80d8799f1a38220b0bff1a001e84801a001e8480582051176daeee7f2ce62963c50a16f641951e21b8522da262980d4dd361a9bf331b4e4d7565736c69537761705f414d4dff"
)
)
]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
self.assertEqual(
uplc.PlutusByteString(
bytes.fromhex(
"81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acf"
)
),
ret,
)
def test_hello_world(self):
input_file = "examples/hello_world.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [uplc.PlutusConstr(0, [])]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
def test_list_datum_correct_vals(self):
input_file = "examples/list_datum.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [uplc.data_from_cbor(bytes.fromhex("d8799f9f41014102ffff"))]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
self.assertEqual(
uplc.PlutusInteger(1),
ret,
)
def test_showcase(self):
input_file = "examples/showcase.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [uplc.PlutusInteger(1)]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
self.assertEqual(
uplc.PlutusInteger(40),
ret,
)
@given(n=st.integers(min_value=0, max_value=5))
def test_fib_rec(self, n):
input_file = "examples/fib_rec.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [uplc.PlutusInteger(n)]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
self.assertEqual(
uplc.PlutusInteger(fib(n)),
ret,
)
def test_gift_contract_succeed(self):
input_file = "examples/smart_contracts/gift.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [
uplc.PlutusConstr(
0,
[
uplc.PlutusByteString(
bytes.fromhex(
"dc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2"
)
)
],
),
uplc.PlutusConstr(0, []),
uplc.data_from_cbor(
bytes.fromhex(
(
"d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff"
)
)
),
]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
self.assertEqual(ret, uplc.PlutusConstr(0, []))
def test_gift_contract_fail(self):
input_file = "examples/smart_contracts/gift.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
try:
# required sig missing int this script context
for d in [
uplc.PlutusConstr(
0,
[
uplc.PlutusByteString(
bytes.fromhex(
"dc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2"
)
)
],
),
uplc.PlutusConstr(0, []),
uplc.data_from_cbor(
bytes.fromhex(
(
"d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff"
)
)
),
]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
failed = False
except Exception as e:
failed = True
self.assertTrue(failed, "Machine did validate the content")
def test_recursion(self):
source_code = """
def validator(_: None) -> int:
def a(n: int) -> int:
if n == 0:
res = 0
else:
res = a(n-1)
return res
b = a
def a(x: int) -> int:
return 100
return b(1)
"""
ast = compiler.parse(source_code)
try:
code = compiler.compile(ast)
self.fail("Example compiled")
except CompilerError:
pass
def test_datum_cast(self):
input_file = "examples/datum_cast.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# Note that this passes even though we pass in a "wrong" datum - the cast only changes the type, it does not do any checks for correctness
for d in [
uplc.data_from_cbor(
bytes.fromhex(
"d8799fd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd87a80d8799f1a38220b0bff1a001e84801a001e8480582051176daeee7f2ce62963c50a16f641951e21b8522da262980d4dd361a9bf331b4e4d7565736c69537761705f414d4dff"
)
),
uplc.PlutusByteString(b"test"),
]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
self.assertEqual(
uplc.PlutusByteString(
bytes.fromhex(
"81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acf"
)
+ b"test"
),
ret,
)
def test_wrapping_contract_compile(self):
# TODO devise tests for this
input_file = "examples/smart_contracts/wrapped_token.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast, force_three_params=True)
code = code.compile()
f = code.term
def test_dual_use_compile(self):
# TODO devise tests for this
input_file = "examples/smart_contracts/dual_use.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast, force_three_params=True)
code = code.compile()
f = code.term
def test_marketplace_compile(self):
# TODO devise tests for this
input_file = "examples/smart_contracts/marketplace.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
def test_marketplace_compile_fail(self):
# TODO devise tests for this
input_file = "examples/smart_contracts/marketplace.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
try:
code = compiler.compile(ast, force_three_params=True)
self.fail(
"Allowed to compile an incompatible contract with three parameters"
)
except Exception:
pass
def test_parameterized_compile(self):
# TODO devise tests for this
input_file = "examples/smart_contracts/parameterized.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
def test_dict_datum(self):
input_file = "examples/dict_datum.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
try:
# required sig missing int this script context
for d in [
uplc.PlutusConstr(
0,
[
uplc.PlutusMap(
frozendict.frozendict(
{
uplc.PlutusConstr(
0, [uplc.PlutusByteString(b"\x01")]
): 2
}
)
)
],
),
]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
failed = False
except Exception as e:
failed = True
self.assertTrue(failed, "Machine did validate the content")
def test_overopt_removedeadvar(self):
# this tests that errors that are caused by assignments are actually triggered at the time of assigning
source_code = """
from hebi.prelude import *
def validator(x: Token) -> bool:
a = x.policy_id
return True
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
try:
for d in [
uplc.PlutusConstr(0, []),
]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
failed = False
except Exception as e:
failed = True
self.assertTrue(failed, "Machine did validate the content")
def test_list_expr(self):
# this tests that the list expression is evaluated correctly
source_code = """
def validator(x: None) -> List[int]:
return [1, 2, 3, 4, 5]
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [
uplc.PlutusConstr(0, []),
]:
f = uplc.Apply(f, d)
ret = [x.value for x in uplc_eval(f).value]
self.assertEqual(ret, [1, 2, 3, 4, 5], "Machine did validate the content")
def test_redefine_constr(self):
# this tests that classes defined by assignment inherit constructors
source_code = """
def validator(x: None) -> bytes:
a = bytes
return a([2, 3])
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [
uplc.PlutusConstr(0, []),
]:
f = uplc.Apply(f, d)
ret = uplc_eval(f).value
self.assertEqual(ret, bytes([2, 3]), "Machine did validate the content")
def test_wrap_into_generic_data(self):
# this tests that errors that are caused by assignments are actually triggered at the time of assigning
source_code = """
from hebi.prelude import *
def validator(_: None) -> SomeOutputDatum:
return SomeOutputDatum(b"a")
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [
uplc.PlutusConstr(0, []),
]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
self.assertEqual(
ret,
uplc.data_from_cbor(
prelude.SomeOutputDatum(b"a").to_cbor(encoding="bytes")
),
"Machine did validate the content",
)
def test_list_comprehension_even(self):
input_file = "examples/list_comprehensions.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [
uplc.PlutusInteger(8),
uplc.PlutusInteger(1),
]:
f = uplc.Apply(f, d)
ret = [x.value for x in uplc_eval(f).value]
self.assertEqual(
ret,
[x * x for x in range(8) if x % 2 == 0],
"List comprehension with filter incorrectly evaluated",
)
def test_list_comprehension_all(self):
input_file = "examples/list_comprehensions.py"
with open(input_file) as fp:
source_code = fp.read()
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
for d in [
uplc.PlutusInteger(8),
uplc.PlutusInteger(0),
]:
f = uplc.Apply(f, d)
ret = [x.value for x in uplc_eval(f).value]
self.assertEqual(
ret,
[x * x for x in range(8)],
"List comprehension incorrectly evaluated",
)
def test_union_type_attr_access_all_records(self):
source_code = """
from hebi.prelude import *
@dataclass()
class A(PlutusData):
CONSTR_ID = 0
foo: SomeOutputDatumHash
@dataclass()
class B(PlutusData):
CONSTR_ID = 1
foo: SomeOutputDatum
def validator(x: Union[A, B]) -> Union[SomeOutputDatumHash, SomeOutputDatum]:
return x.foo
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast)
@unittest.expectedFailure
def test_union_type_all_records_same_constr(self):
source_code = """
from hebi.prelude import *
@dataclass()
class A(PlutusData):
CONSTR_ID = 0
foo: SomeOutputDatumHash
@dataclass()
class B(PlutusData):
CONSTR_ID = 0
foo: SomeOutputDatum
def validator(x: Union[A, B]) -> Union[SomeOutputDatumHash, SomeOutputDatum]:
return x.foo
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast)
@unittest.expectedFailure
def test_union_type_attr_access_all_records_same_constr(self):
source_code = """
from hebi.prelude import *
@dataclass()
class A(PlutusData):
CONSTR_ID = 0
foo: Token
@dataclass()
class B(PlutusData):
CONSTR_ID = 1
foo: Address
def validator(x: Union[A, B]) -> int:
m = x.foo
if isinstance(m, Address):
k = 0
else:
k = 1
return k
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast)
def test_union_type_attr_access_maximum_type(self):
source_code = """
from hebi.prelude import *
@dataclass()
class A(PlutusData):
CONSTR_ID = 0
foo: int
@dataclass()
class B(PlutusData):
CONSTR_ID = 1
foo: int
def validator(x: Union[A, B]) -> int:
return x.foo
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast)
def test_union_type_attr_anytype(self):
source_code = """
from hebi.prelude import *
@dataclass()
class A(PlutusData):
CONSTR_ID = 0
foo: str
@dataclass()
class B(PlutusData):
CONSTR_ID = 1
foo: int
def validator(x: Union[A, B]) -> Anything:
return x.foo
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast)
def test_no_reassign(self):
# this tests that variables can not be re-assigned
source_code = """
def validator(x: int) -> int:
x = 1
return x
"""
ast = compiler.parse(source_code)
try:
code = compiler.compile(ast)
self.fail("Compilation passed")
except CompilerError:
pass
def test_typecast_anything_int(self):
source_code = """
def validator(x: Anything) -> int:
b: int = x
return b
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value
self.assertEqual(res, 0)
def test_typecast_int_anything(self):
# this should compile, it happens implicitly anyways when calling a function with Any parameters
source_code = """
def validator(x: int) -> Anything:
b: Anything = x
return b
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value
self.assertEqual(res, 0)
def test_typecast_int_anything_int(self):
source_code = """
def validator(x: int) -> Anything:
b: Anything = x
c: int = b
return c + 1
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value
self.assertEqual(res, 1)
def test_typecast_anything_int_anything(self):
source_code = """
def validator(x: Anything) -> Anything:
b: int = x
c: Anything = b + 1
return c
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value
self.assertEqual(res, 1)
@unittest.expectedFailure
def test_typecast_int_str(self):
# this should compile, the two types are unrelated and there is no meaningful way to cast them either direction
source_code = """
def validator(x: int) -> str:
b: str = x
return b
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast)
def test_typecast_int_int(self):
source_code = """
def validator(x: int) -> int:
b: int = x
return b
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value
self.assertEqual(res, 0)
def test_zero_ary(self):
source_code = """
def a() -> None:
assert False, "Executed a"
def validator(x: None) -> None:
b = a
if False:
b()
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0)))
@unittest.expectedFailure
def test_zero_ary_exec(self):
source_code = """
def a() -> None:
assert False, "Executed a"
def validator(x: None) -> None:
b = a
if True:
b()
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0)))
def test_zero_ary_method(self):
source_code = """
def validator(x: None) -> None:
b = b"\\xFF".decode
if False:
b()
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0)))
@unittest.expectedFailure
def test_zero_ary_method_exec(self):
source_code = """
def validator(x: None) -> None:
b = b"\\xFF".decode
if True:
b()
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0)))
def test_return_anything(self):
source_code = """
from hebi.prelude import *
def validator() -> Anything:
return b""
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, [])))
self.assertEqual(res, uplc.PlutusByteString(b""))
def test_no_return_annotation(self):
source_code = """
from hebi.prelude import *
def validator():
return b""
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, [])))
self.assertEqual(res, uplc.PlutusByteString(b""))
def test_no_parameter_annotation(self):
source_code = """
from hebi.prelude import *
def validator(a) -> bytes:
b: bytes = a
return b
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusByteString(b"")))
self.assertEqual(res, uplc.PlutusByteString(b""))
def test_nested_deconstruction(self):
source_code = """
def validator(xs) -> int:
a, ((b, c), d) = (1, ((2, 3), 4))
return a + b + c + d
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
f = uplc.Apply(f, uplc.PlutusConstr(0, []))
ret = uplc_eval(f).value
self.assertEqual(
ret,
1 + 2 + 3 + 4,
"for loop deconstruction did not behave as expected",
)
def test_different_return_types_anything(self):
source_code = """
from hebi.prelude import *
def validator(a: int) -> Anything:
if a > 0:
return b""
else:
return 0
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(1)))
self.assertEqual(res, uplc.PlutusByteString(b""))
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(-1)))
self.assertEqual(res, uplc.PlutusInteger(0))
def test_no_return_annotation_no_return(self):
source_code = """
from hebi.prelude import *
def validator(a):
pass
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, [])))
self.assertEqual(res, uplc.PlutusConstr(0, []))
def test_opt_unsafe_cast(self):
# test that unsafe casts are not optimized away
source_code = """
from hebi.prelude import *
def validator(x: Token) -> bool:
b: Anything = x
a: int = b
return True
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast)
code = code.compile()
f = code.term
# UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
try:
for d in [
uplc.PlutusConstr(0, []),
]:
f = uplc.Apply(f, d)
ret = uplc_eval(f)
failed = False
except Exception as e:
failed = True
self.assertTrue(failed, "Machine did validate the content")
Functions
def fib(n)
-
Expand source code
def fib(n): a, b = 0, 1 for _ in range(n): a, b = b, a + b return a
Classes
class MiscTest (methodName='runTest')
-
A class whose instances are single test cases.
By default, the test code itself should be placed in a method named 'runTest'.
If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute.
Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively.
If it is necessary to override the init method, the base class init method must always be called. It is important that subclasses should not change the signature of their init method, since instances of the classes are instantiated automatically by parts of the framework in order to be run.
When subclassing TestCase, you can set these attributes: * failureException: determines which exception will be raised when the instance's assertion methods fail; test methods raising this exception will be deemed to have 'failed' rather than 'errored'. * longMessage: determines whether long messages (including repr of objects used in assert methods) will be printed on failure in addition to any explicit message passed. * maxDiff: sets the maximum length of a diff in failure messages by assert methods using difflib. It is looked up as an instance attribute so can be configured by individual tests if required.
Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name.
Expand source code
class MiscTest(unittest.TestCase): def test_assert_sum_contract_succeed(self): input_file = "examples/smart_contracts/assert_sum.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [uplc.PlutusInteger(20), uplc.PlutusInteger(22), uplc.BuiltinUnit()]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual(ret, uplc.PlutusConstr(0, [])) def test_assert_sum_contract_fail(self): input_file = "examples/smart_contracts/assert_sum.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() try: f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusInteger(0), uplc.PlutusInteger(23), uplc.BuiltinUnit(), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) failed = False except Exception as e: failed = True self.assertTrue(failed, "Machine did validate the content") @given( a=st.integers(), b=st.integers(), ) def test_sum(self, a: int, b: int): input_file = "examples/sum.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [uplc.PlutusInteger(a), uplc.PlutusInteger(b)]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual(ret, uplc.PlutusInteger(a + b)) def test_complex_datum_correct_vals(self): input_file = "examples/complex_datum.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.data_from_cbor( bytes.fromhex( "d8799fd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd87a80d8799f1a38220b0bff1a001e84801a001e8480582051176daeee7f2ce62963c50a16f641951e21b8522da262980d4dd361a9bf331b4e4d7565736c69537761705f414d4dff" ) ) ]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual( uplc.PlutusByteString( bytes.fromhex( "81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acf" ) ), ret, ) def test_hello_world(self): input_file = "examples/hello_world.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [uplc.PlutusConstr(0, [])]: f = uplc.Apply(f, d) ret = uplc_eval(f) def test_list_datum_correct_vals(self): input_file = "examples/list_datum.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [uplc.data_from_cbor(bytes.fromhex("d8799f9f41014102ffff"))]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual( uplc.PlutusInteger(1), ret, ) def test_showcase(self): input_file = "examples/showcase.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [uplc.PlutusInteger(1)]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual( uplc.PlutusInteger(40), ret, ) @given(n=st.integers(min_value=0, max_value=5)) def test_fib_rec(self, n): input_file = "examples/fib_rec.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [uplc.PlutusInteger(n)]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual( uplc.PlutusInteger(fib(n)), ret, ) def test_gift_contract_succeed(self): input_file = "examples/smart_contracts/gift.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusConstr( 0, [ uplc.PlutusByteString( bytes.fromhex( "dc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2" ) ) ], ), uplc.PlutusConstr(0, []), uplc.data_from_cbor( bytes.fromhex( ( "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" ) ) ), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual(ret, uplc.PlutusConstr(0, [])) def test_gift_contract_fail(self): input_file = "examples/smart_contracts/gift.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying try: # required sig missing int this script context for d in [ uplc.PlutusConstr( 0, [ uplc.PlutusByteString( bytes.fromhex( "dc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2" ) ) ], ), uplc.PlutusConstr(0, []), uplc.data_from_cbor( bytes.fromhex( ( "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" ) ) ), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) failed = False except Exception as e: failed = True self.assertTrue(failed, "Machine did validate the content") def test_recursion(self): source_code = """ def validator(_: None) -> int: def a(n: int) -> int: if n == 0: res = 0 else: res = a(n-1) return res b = a def a(x: int) -> int: return 100 return b(1) """ ast = compiler.parse(source_code) try: code = compiler.compile(ast) self.fail("Example compiled") except CompilerError: pass def test_datum_cast(self): input_file = "examples/datum_cast.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # Note that this passes even though we pass in a "wrong" datum - the cast only changes the type, it does not do any checks for correctness for d in [ uplc.data_from_cbor( bytes.fromhex( "d8799fd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd87a80d8799f1a38220b0bff1a001e84801a001e8480582051176daeee7f2ce62963c50a16f641951e21b8522da262980d4dd361a9bf331b4e4d7565736c69537761705f414d4dff" ) ), uplc.PlutusByteString(b"test"), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual( uplc.PlutusByteString( bytes.fromhex( "81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acf" ) + b"test" ), ret, ) def test_wrapping_contract_compile(self): # TODO devise tests for this input_file = "examples/smart_contracts/wrapped_token.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast, force_three_params=True) code = code.compile() f = code.term def test_dual_use_compile(self): # TODO devise tests for this input_file = "examples/smart_contracts/dual_use.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast, force_three_params=True) code = code.compile() f = code.term def test_marketplace_compile(self): # TODO devise tests for this input_file = "examples/smart_contracts/marketplace.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term def test_marketplace_compile_fail(self): # TODO devise tests for this input_file = "examples/smart_contracts/marketplace.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) try: code = compiler.compile(ast, force_three_params=True) self.fail( "Allowed to compile an incompatible contract with three parameters" ) except Exception: pass def test_parameterized_compile(self): # TODO devise tests for this input_file = "examples/smart_contracts/parameterized.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term def test_dict_datum(self): input_file = "examples/dict_datum.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying try: # required sig missing int this script context for d in [ uplc.PlutusConstr( 0, [ uplc.PlutusMap( frozendict.frozendict( { uplc.PlutusConstr( 0, [uplc.PlutusByteString(b"\x01")] ): 2 } ) ) ], ), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) failed = False except Exception as e: failed = True self.assertTrue(failed, "Machine did validate the content") def test_overopt_removedeadvar(self): # this tests that errors that are caused by assignments are actually triggered at the time of assigning source_code = """ from hebi.prelude import * def validator(x: Token) -> bool: a = x.policy_id return True """ ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying try: for d in [ uplc.PlutusConstr(0, []), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) failed = False except Exception as e: failed = True self.assertTrue(failed, "Machine did validate the content") def test_list_expr(self): # this tests that the list expression is evaluated correctly source_code = """ def validator(x: None) -> List[int]: return [1, 2, 3, 4, 5] """ ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusConstr(0, []), ]: f = uplc.Apply(f, d) ret = [x.value for x in uplc_eval(f).value] self.assertEqual(ret, [1, 2, 3, 4, 5], "Machine did validate the content") def test_redefine_constr(self): # this tests that classes defined by assignment inherit constructors source_code = """ def validator(x: None) -> bytes: a = bytes return a([2, 3]) """ ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusConstr(0, []), ]: f = uplc.Apply(f, d) ret = uplc_eval(f).value self.assertEqual(ret, bytes([2, 3]), "Machine did validate the content") def test_wrap_into_generic_data(self): # this tests that errors that are caused by assignments are actually triggered at the time of assigning source_code = """ from hebi.prelude import * def validator(_: None) -> SomeOutputDatum: return SomeOutputDatum(b"a") """ ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusConstr(0, []), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual( ret, uplc.data_from_cbor( prelude.SomeOutputDatum(b"a").to_cbor(encoding="bytes") ), "Machine did validate the content", ) def test_list_comprehension_even(self): input_file = "examples/list_comprehensions.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusInteger(8), uplc.PlutusInteger(1), ]: f = uplc.Apply(f, d) ret = [x.value for x in uplc_eval(f).value] self.assertEqual( ret, [x * x for x in range(8) if x % 2 == 0], "List comprehension with filter incorrectly evaluated", ) def test_list_comprehension_all(self): input_file = "examples/list_comprehensions.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusInteger(8), uplc.PlutusInteger(0), ]: f = uplc.Apply(f, d) ret = [x.value for x in uplc_eval(f).value] self.assertEqual( ret, [x * x for x in range(8)], "List comprehension incorrectly evaluated", ) def test_union_type_attr_access_all_records(self): source_code = """ from hebi.prelude import * @dataclass() class A(PlutusData): CONSTR_ID = 0 foo: SomeOutputDatumHash @dataclass() class B(PlutusData): CONSTR_ID = 1 foo: SomeOutputDatum def validator(x: Union[A, B]) -> Union[SomeOutputDatumHash, SomeOutputDatum]: return x.foo """ ast = compiler.parse(source_code) code = compiler.compile(ast) @unittest.expectedFailure def test_union_type_all_records_same_constr(self): source_code = """ from hebi.prelude import * @dataclass() class A(PlutusData): CONSTR_ID = 0 foo: SomeOutputDatumHash @dataclass() class B(PlutusData): CONSTR_ID = 0 foo: SomeOutputDatum def validator(x: Union[A, B]) -> Union[SomeOutputDatumHash, SomeOutputDatum]: return x.foo """ ast = compiler.parse(source_code) code = compiler.compile(ast) @unittest.expectedFailure def test_union_type_attr_access_all_records_same_constr(self): source_code = """ from hebi.prelude import * @dataclass() class A(PlutusData): CONSTR_ID = 0 foo: Token @dataclass() class B(PlutusData): CONSTR_ID = 1 foo: Address def validator(x: Union[A, B]) -> int: m = x.foo if isinstance(m, Address): k = 0 else: k = 1 return k """ ast = compiler.parse(source_code) code = compiler.compile(ast) def test_union_type_attr_access_maximum_type(self): source_code = """ from hebi.prelude import * @dataclass() class A(PlutusData): CONSTR_ID = 0 foo: int @dataclass() class B(PlutusData): CONSTR_ID = 1 foo: int def validator(x: Union[A, B]) -> int: return x.foo """ ast = compiler.parse(source_code) code = compiler.compile(ast) def test_union_type_attr_anytype(self): source_code = """ from hebi.prelude import * @dataclass() class A(PlutusData): CONSTR_ID = 0 foo: str @dataclass() class B(PlutusData): CONSTR_ID = 1 foo: int def validator(x: Union[A, B]) -> Anything: return x.foo """ ast = compiler.parse(source_code) code = compiler.compile(ast) def test_no_reassign(self): # this tests that variables can not be re-assigned source_code = """ def validator(x: int) -> int: x = 1 return x """ ast = compiler.parse(source_code) try: code = compiler.compile(ast) self.fail("Compilation passed") except CompilerError: pass def test_typecast_anything_int(self): source_code = """ def validator(x: Anything) -> int: b: int = x return b """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value self.assertEqual(res, 0) def test_typecast_int_anything(self): # this should compile, it happens implicitly anyways when calling a function with Any parameters source_code = """ def validator(x: int) -> Anything: b: Anything = x return b """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value self.assertEqual(res, 0) def test_typecast_int_anything_int(self): source_code = """ def validator(x: int) -> Anything: b: Anything = x c: int = b return c + 1 """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value self.assertEqual(res, 1) def test_typecast_anything_int_anything(self): source_code = """ def validator(x: Anything) -> Anything: b: int = x c: Anything = b + 1 return c """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value self.assertEqual(res, 1) @unittest.expectedFailure def test_typecast_int_str(self): # this should compile, the two types are unrelated and there is no meaningful way to cast them either direction source_code = """ def validator(x: int) -> str: b: str = x return b """ ast = compiler.parse(source_code) code = compiler.compile(ast) def test_typecast_int_int(self): source_code = """ def validator(x: int) -> int: b: int = x return b """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value self.assertEqual(res, 0) def test_zero_ary(self): source_code = """ def a() -> None: assert False, "Executed a" def validator(x: None) -> None: b = a if False: b() """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))) @unittest.expectedFailure def test_zero_ary_exec(self): source_code = """ def a() -> None: assert False, "Executed a" def validator(x: None) -> None: b = a if True: b() """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))) def test_zero_ary_method(self): source_code = """ def validator(x: None) -> None: b = b"\\xFF".decode if False: b() """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))) @unittest.expectedFailure def test_zero_ary_method_exec(self): source_code = """ def validator(x: None) -> None: b = b"\\xFF".decode if True: b() """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))) def test_return_anything(self): source_code = """ from hebi.prelude import * def validator() -> Anything: return b"" """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, []))) self.assertEqual(res, uplc.PlutusByteString(b"")) def test_no_return_annotation(self): source_code = """ from hebi.prelude import * def validator(): return b"" """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, []))) self.assertEqual(res, uplc.PlutusByteString(b"")) def test_no_parameter_annotation(self): source_code = """ from hebi.prelude import * def validator(a) -> bytes: b: bytes = a return b """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusByteString(b""))) self.assertEqual(res, uplc.PlutusByteString(b"")) def test_nested_deconstruction(self): source_code = """ def validator(xs) -> int: a, ((b, c), d) = (1, ((2, 3), 4)) return a + b + c + d """ ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying f = uplc.Apply(f, uplc.PlutusConstr(0, [])) ret = uplc_eval(f).value self.assertEqual( ret, 1 + 2 + 3 + 4, "for loop deconstruction did not behave as expected", ) def test_different_return_types_anything(self): source_code = """ from hebi.prelude import * def validator(a: int) -> Anything: if a > 0: return b"" else: return 0 """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(1))) self.assertEqual(res, uplc.PlutusByteString(b"")) res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(-1))) self.assertEqual(res, uplc.PlutusInteger(0)) def test_no_return_annotation_no_return(self): source_code = """ from hebi.prelude import * def validator(a): pass """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, []))) self.assertEqual(res, uplc.PlutusConstr(0, [])) def test_opt_unsafe_cast(self): # test that unsafe casts are not optimized away source_code = """ from hebi.prelude import * def validator(x: Token) -> bool: b: Anything = x a: int = b return True """ ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying try: for d in [ uplc.PlutusConstr(0, []), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) failed = False except Exception as e: failed = True self.assertTrue(failed, "Machine did validate the content")
Ancestors
- unittest.case.TestCase
Methods
def test_assert_sum_contract_fail(self)
-
Expand source code
def test_assert_sum_contract_fail(self): input_file = "examples/smart_contracts/assert_sum.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() try: f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusInteger(0), uplc.PlutusInteger(23), uplc.BuiltinUnit(), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) failed = False except Exception as e: failed = True self.assertTrue(failed, "Machine did validate the content")
def test_assert_sum_contract_succeed(self)
-
Expand source code
def test_assert_sum_contract_succeed(self): input_file = "examples/smart_contracts/assert_sum.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [uplc.PlutusInteger(20), uplc.PlutusInteger(22), uplc.BuiltinUnit()]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual(ret, uplc.PlutusConstr(0, []))
def test_complex_datum_correct_vals(self)
-
Expand source code
def test_complex_datum_correct_vals(self): input_file = "examples/complex_datum.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.data_from_cbor( bytes.fromhex( "d8799fd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd87a80d8799f1a38220b0bff1a001e84801a001e8480582051176daeee7f2ce62963c50a16f641951e21b8522da262980d4dd361a9bf331b4e4d7565736c69537761705f414d4dff" ) ) ]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual( uplc.PlutusByteString( bytes.fromhex( "81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acf" ) ), ret, )
def test_datum_cast(self)
-
Expand source code
def test_datum_cast(self): input_file = "examples/datum_cast.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # Note that this passes even though we pass in a "wrong" datum - the cast only changes the type, it does not do any checks for correctness for d in [ uplc.data_from_cbor( bytes.fromhex( "d8799fd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd87a80d8799f1a38220b0bff1a001e84801a001e8480582051176daeee7f2ce62963c50a16f641951e21b8522da262980d4dd361a9bf331b4e4d7565736c69537761705f414d4dff" ) ), uplc.PlutusByteString(b"test"), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual( uplc.PlutusByteString( bytes.fromhex( "81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acf" ) + b"test" ), ret, )
def test_dict_datum(self)
-
Expand source code
def test_dict_datum(self): input_file = "examples/dict_datum.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying try: # required sig missing int this script context for d in [ uplc.PlutusConstr( 0, [ uplc.PlutusMap( frozendict.frozendict( { uplc.PlutusConstr( 0, [uplc.PlutusByteString(b"\x01")] ): 2 } ) ) ], ), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) failed = False except Exception as e: failed = True self.assertTrue(failed, "Machine did validate the content")
def test_different_return_types_anything(self)
-
Expand source code
def test_different_return_types_anything(self): source_code = """ from hebi.prelude import * def validator(a: int) -> Anything: if a > 0: return b"" else: return 0 """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(1))) self.assertEqual(res, uplc.PlutusByteString(b"")) res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(-1))) self.assertEqual(res, uplc.PlutusInteger(0))
def test_dual_use_compile(self)
-
Expand source code
def test_dual_use_compile(self): # TODO devise tests for this input_file = "examples/smart_contracts/dual_use.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast, force_three_params=True) code = code.compile() f = code.term
def test_fib_rec(self) ‑> None
-
Expand source code
@given(n=st.integers(min_value=0, max_value=5)) def test_fib_rec(self, n): input_file = "examples/fib_rec.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [uplc.PlutusInteger(n)]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual( uplc.PlutusInteger(fib(n)), ret, )
def test_gift_contract_fail(self)
-
Expand source code
def test_gift_contract_fail(self): input_file = "examples/smart_contracts/gift.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying try: # required sig missing int this script context for d in [ uplc.PlutusConstr( 0, [ uplc.PlutusByteString( bytes.fromhex( "dc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2" ) ) ], ), uplc.PlutusConstr(0, []), uplc.data_from_cbor( bytes.fromhex( ( "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" ) ) ), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) failed = False except Exception as e: failed = True self.assertTrue(failed, "Machine did validate the content")
def test_gift_contract_succeed(self)
-
Expand source code
def test_gift_contract_succeed(self): input_file = "examples/smart_contracts/gift.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusConstr( 0, [ uplc.PlutusByteString( bytes.fromhex( "dc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2" ) ) ], ), uplc.PlutusConstr(0, []), uplc.data_from_cbor( bytes.fromhex( ( "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" ) ) ), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual(ret, uplc.PlutusConstr(0, []))
def test_hello_world(self)
-
Expand source code
def test_hello_world(self): input_file = "examples/hello_world.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [uplc.PlutusConstr(0, [])]: f = uplc.Apply(f, d) ret = uplc_eval(f)
def test_list_comprehension_all(self)
-
Expand source code
def test_list_comprehension_all(self): input_file = "examples/list_comprehensions.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusInteger(8), uplc.PlutusInteger(0), ]: f = uplc.Apply(f, d) ret = [x.value for x in uplc_eval(f).value] self.assertEqual( ret, [x * x for x in range(8)], "List comprehension incorrectly evaluated", )
def test_list_comprehension_even(self)
-
Expand source code
def test_list_comprehension_even(self): input_file = "examples/list_comprehensions.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusInteger(8), uplc.PlutusInteger(1), ]: f = uplc.Apply(f, d) ret = [x.value for x in uplc_eval(f).value] self.assertEqual( ret, [x * x for x in range(8) if x % 2 == 0], "List comprehension with filter incorrectly evaluated", )
def test_list_datum_correct_vals(self)
-
Expand source code
def test_list_datum_correct_vals(self): input_file = "examples/list_datum.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [uplc.data_from_cbor(bytes.fromhex("d8799f9f41014102ffff"))]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual( uplc.PlutusInteger(1), ret, )
def test_list_expr(self)
-
Expand source code
def test_list_expr(self): # this tests that the list expression is evaluated correctly source_code = """ def validator(x: None) -> List[int]: return [1, 2, 3, 4, 5] """ ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusConstr(0, []), ]: f = uplc.Apply(f, d) ret = [x.value for x in uplc_eval(f).value] self.assertEqual(ret, [1, 2, 3, 4, 5], "Machine did validate the content")
def test_marketplace_compile(self)
-
Expand source code
def test_marketplace_compile(self): # TODO devise tests for this input_file = "examples/smart_contracts/marketplace.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term
def test_marketplace_compile_fail(self)
-
Expand source code
def test_marketplace_compile_fail(self): # TODO devise tests for this input_file = "examples/smart_contracts/marketplace.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) try: code = compiler.compile(ast, force_three_params=True) self.fail( "Allowed to compile an incompatible contract with three parameters" ) except Exception: pass
def test_nested_deconstruction(self)
-
Expand source code
def test_nested_deconstruction(self): source_code = """ def validator(xs) -> int: a, ((b, c), d) = (1, ((2, 3), 4)) return a + b + c + d """ ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying f = uplc.Apply(f, uplc.PlutusConstr(0, [])) ret = uplc_eval(f).value self.assertEqual( ret, 1 + 2 + 3 + 4, "for loop deconstruction did not behave as expected", )
def test_no_parameter_annotation(self)
-
Expand source code
def test_no_parameter_annotation(self): source_code = """ from hebi.prelude import * def validator(a) -> bytes: b: bytes = a return b """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusByteString(b""))) self.assertEqual(res, uplc.PlutusByteString(b""))
def test_no_reassign(self)
-
Expand source code
def test_no_reassign(self): # this tests that variables can not be re-assigned source_code = """ def validator(x: int) -> int: x = 1 return x """ ast = compiler.parse(source_code) try: code = compiler.compile(ast) self.fail("Compilation passed") except CompilerError: pass
def test_no_return_annotation(self)
-
Expand source code
def test_no_return_annotation(self): source_code = """ from hebi.prelude import * def validator(): return b"" """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, []))) self.assertEqual(res, uplc.PlutusByteString(b""))
def test_no_return_annotation_no_return(self)
-
Expand source code
def test_no_return_annotation_no_return(self): source_code = """ from hebi.prelude import * def validator(a): pass """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, []))) self.assertEqual(res, uplc.PlutusConstr(0, []))
def test_opt_unsafe_cast(self)
-
Expand source code
def test_opt_unsafe_cast(self): # test that unsafe casts are not optimized away source_code = """ from hebi.prelude import * def validator(x: Token) -> bool: b: Anything = x a: int = b return True """ ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying try: for d in [ uplc.PlutusConstr(0, []), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) failed = False except Exception as e: failed = True self.assertTrue(failed, "Machine did validate the content")
def test_overopt_removedeadvar(self)
-
Expand source code
def test_overopt_removedeadvar(self): # this tests that errors that are caused by assignments are actually triggered at the time of assigning source_code = """ from hebi.prelude import * def validator(x: Token) -> bool: a = x.policy_id return True """ ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying try: for d in [ uplc.PlutusConstr(0, []), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) failed = False except Exception as e: failed = True self.assertTrue(failed, "Machine did validate the content")
def test_parameterized_compile(self)
-
Expand source code
def test_parameterized_compile(self): # TODO devise tests for this input_file = "examples/smart_contracts/parameterized.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term
def test_recursion(self)
-
Expand source code
def test_recursion(self): source_code = """ def validator(_: None) -> int: def a(n: int) -> int: if n == 0: res = 0 else: res = a(n-1) return res b = a def a(x: int) -> int: return 100 return b(1) """ ast = compiler.parse(source_code) try: code = compiler.compile(ast) self.fail("Example compiled") except CompilerError: pass
def test_redefine_constr(self)
-
Expand source code
def test_redefine_constr(self): # this tests that classes defined by assignment inherit constructors source_code = """ def validator(x: None) -> bytes: a = bytes return a([2, 3]) """ ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusConstr(0, []), ]: f = uplc.Apply(f, d) ret = uplc_eval(f).value self.assertEqual(ret, bytes([2, 3]), "Machine did validate the content")
def test_return_anything(self)
-
Expand source code
def test_return_anything(self): source_code = """ from hebi.prelude import * def validator() -> Anything: return b"" """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, []))) self.assertEqual(res, uplc.PlutusByteString(b""))
def test_showcase(self)
-
Expand source code
def test_showcase(self): input_file = "examples/showcase.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [uplc.PlutusInteger(1)]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual( uplc.PlutusInteger(40), ret, )
def test_sum(self) ‑> None
-
Expand source code
@given( a=st.integers(), b=st.integers(), ) def test_sum(self, a: int, b: int): input_file = "examples/sum.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [uplc.PlutusInteger(a), uplc.PlutusInteger(b)]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual(ret, uplc.PlutusInteger(a + b))
def test_typecast_anything_int(self)
-
Expand source code
def test_typecast_anything_int(self): source_code = """ def validator(x: Anything) -> int: b: int = x return b """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value self.assertEqual(res, 0)
def test_typecast_anything_int_anything(self)
-
Expand source code
def test_typecast_anything_int_anything(self): source_code = """ def validator(x: Anything) -> Anything: b: int = x c: Anything = b + 1 return c """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value self.assertEqual(res, 1)
def test_typecast_int_anything(self)
-
Expand source code
def test_typecast_int_anything(self): # this should compile, it happens implicitly anyways when calling a function with Any parameters source_code = """ def validator(x: int) -> Anything: b: Anything = x return b """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value self.assertEqual(res, 0)
def test_typecast_int_anything_int(self)
-
Expand source code
def test_typecast_int_anything_int(self): source_code = """ def validator(x: int) -> Anything: b: Anything = x c: int = b return c + 1 """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value self.assertEqual(res, 1)
def test_typecast_int_int(self)
-
Expand source code
def test_typecast_int_int(self): source_code = """ def validator(x: int) -> int: b: int = x return b """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value self.assertEqual(res, 0)
def test_typecast_int_str(self)
-
Expand source code
@unittest.expectedFailure def test_typecast_int_str(self): # this should compile, the two types are unrelated and there is no meaningful way to cast them either direction source_code = """ def validator(x: int) -> str: b: str = x return b """ ast = compiler.parse(source_code) code = compiler.compile(ast)
def test_union_type_all_records_same_constr(self)
-
Expand source code
@unittest.expectedFailure def test_union_type_all_records_same_constr(self): source_code = """ from hebi.prelude import * @dataclass() class A(PlutusData): CONSTR_ID = 0 foo: SomeOutputDatumHash @dataclass() class B(PlutusData): CONSTR_ID = 0 foo: SomeOutputDatum def validator(x: Union[A, B]) -> Union[SomeOutputDatumHash, SomeOutputDatum]: return x.foo """ ast = compiler.parse(source_code) code = compiler.compile(ast)
def test_union_type_attr_access_all_records(self)
-
Expand source code
def test_union_type_attr_access_all_records(self): source_code = """ from hebi.prelude import * @dataclass() class A(PlutusData): CONSTR_ID = 0 foo: SomeOutputDatumHash @dataclass() class B(PlutusData): CONSTR_ID = 1 foo: SomeOutputDatum def validator(x: Union[A, B]) -> Union[SomeOutputDatumHash, SomeOutputDatum]: return x.foo """ ast = compiler.parse(source_code) code = compiler.compile(ast)
def test_union_type_attr_access_all_records_same_constr(self)
-
Expand source code
@unittest.expectedFailure def test_union_type_attr_access_all_records_same_constr(self): source_code = """ from hebi.prelude import * @dataclass() class A(PlutusData): CONSTR_ID = 0 foo: Token @dataclass() class B(PlutusData): CONSTR_ID = 1 foo: Address def validator(x: Union[A, B]) -> int: m = x.foo if isinstance(m, Address): k = 0 else: k = 1 return k """ ast = compiler.parse(source_code) code = compiler.compile(ast)
def test_union_type_attr_access_maximum_type(self)
-
Expand source code
def test_union_type_attr_access_maximum_type(self): source_code = """ from hebi.prelude import * @dataclass() class A(PlutusData): CONSTR_ID = 0 foo: int @dataclass() class B(PlutusData): CONSTR_ID = 1 foo: int def validator(x: Union[A, B]) -> int: return x.foo """ ast = compiler.parse(source_code) code = compiler.compile(ast)
def test_union_type_attr_anytype(self)
-
Expand source code
def test_union_type_attr_anytype(self): source_code = """ from hebi.prelude import * @dataclass() class A(PlutusData): CONSTR_ID = 0 foo: str @dataclass() class B(PlutusData): CONSTR_ID = 1 foo: int def validator(x: Union[A, B]) -> Anything: return x.foo """ ast = compiler.parse(source_code) code = compiler.compile(ast)
def test_wrap_into_generic_data(self)
-
Expand source code
def test_wrap_into_generic_data(self): # this tests that errors that are caused by assignments are actually triggered at the time of assigning source_code = """ from hebi.prelude import * def validator(_: None) -> SomeOutputDatum: return SomeOutputDatum(b"a") """ ast = compiler.parse(source_code) code = compiler.compile(ast) code = code.compile() f = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in [ uplc.PlutusConstr(0, []), ]: f = uplc.Apply(f, d) ret = uplc_eval(f) self.assertEqual( ret, uplc.data_from_cbor( prelude.SomeOutputDatum(b"a").to_cbor(encoding="bytes") ), "Machine did validate the content", )
def test_wrapping_contract_compile(self)
-
Expand source code
def test_wrapping_contract_compile(self): # TODO devise tests for this input_file = "examples/smart_contracts/wrapped_token.py" with open(input_file) as fp: source_code = fp.read() ast = compiler.parse(source_code) code = compiler.compile(ast, force_three_params=True) code = code.compile() f = code.term
def test_zero_ary(self)
-
Expand source code
def test_zero_ary(self): source_code = """ def a() -> None: assert False, "Executed a" def validator(x: None) -> None: b = a if False: b() """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0)))
def test_zero_ary_exec(self)
-
Expand source code
@unittest.expectedFailure def test_zero_ary_exec(self): source_code = """ def a() -> None: assert False, "Executed a" def validator(x: None) -> None: b = a if True: b() """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0)))
def test_zero_ary_method(self)
-
Expand source code
def test_zero_ary_method(self): source_code = """ def validator(x: None) -> None: b = b"\\xFF".decode if False: b() """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0)))
def test_zero_ary_method_exec(self)
-
Expand source code
@unittest.expectedFailure def test_zero_ary_method_exec(self): source_code = """ def validator(x: None) -> None: b = b"\\xFF".decode if True: b() """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0)))