Skip to content

Commit

Permalink
fix some more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
charles-cooper committed Dec 7, 2023
1 parent 6c81142 commit e7e37b8
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 65 deletions.
2 changes: 1 addition & 1 deletion tests/unit/cli/outputs/test_storage_layout_overrides.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def test_overflow():
storage_layout_override = {"x": {"slot": 2**256 - 1, "type": "uint256[2]"}}

with pytest.raises(
StorageLayoutException, match=f"Invalid storage slot for var x, out of bounds: {2**256}\n"
StorageLayoutException, match=f"Invalid storage slot for var x, out of bounds: {2**256}"
):
compile_code(
code, output_formats=["layout"], storage_layout_override=storage_layout_override
Expand Down
136 changes: 73 additions & 63 deletions tests/unit/cli/vyper_compile/test_compile_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def test_invalid_root_path():
compile_files([], [], root_folder="path/that/does/not/exist")


FOO_CODE = """
CONTRACT_CODE = """
{}
struct FooStruct:
Expand All @@ -45,78 +45,83 @@ def bar(a: address) -> FooStruct:
return {}(a).bar()
"""

BAR_CODE = """
INTERFACE_CODE = """
struct FooStruct:
foo_: uint256
@external
def foo() -> FooStruct:
...
@external
def bar() -> FooStruct:
return FooStruct({foo_: 13})
...
"""


SAME_FOLDER_IMPORT_STMT = [
("import Bar as Bar", "Bar"),
("import contracts.Bar as Bar", "Bar"),
("from . import Bar", "Bar"),
("from contracts import Bar", "Bar"),
("from ..contracts import Bar", "Bar"),
("from . import Bar as FooBar", "FooBar"),
("from contracts import Bar as FooBar", "FooBar"),
("from ..contracts import Bar as FooBar", "FooBar"),
("import IFoo as IFoo", "IFoo"),
("import contracts.IFoo as IFoo", "IFoo"),
("from . import IFoo", "IFoo"),
("from contracts import IFoo", "IFoo"),
("from ..contracts import IFoo", "IFoo"),
("from . import IFoo as FooBar", "FooBar"),
("from contracts import IFoo as FooBar", "FooBar"),
("from ..contracts import IFoo as FooBar", "FooBar"),
]


@pytest.mark.parametrize("import_stmt,alias", SAME_FOLDER_IMPORT_STMT)
def test_import_same_folder(import_stmt, alias, tmp_path, make_file):
foo = "contracts/foo.vy"
make_file("contracts/foo.vy", FOO_CODE.format(import_stmt, alias))
make_file("contracts/Bar.vy", BAR_CODE)
make_file("contracts/foo.vy", CONTRACT_CODE.format(import_stmt, alias))
make_file("contracts/IFoo.vyi", INTERFACE_CODE)

assert compile_files([foo], ["combined_json"], root_folder=tmp_path)


SUBFOLDER_IMPORT_STMT = [
("import other.Bar as Bar", "Bar"),
("import contracts.other.Bar as Bar", "Bar"),
("from other import Bar", "Bar"),
("from contracts.other import Bar", "Bar"),
("from .other import Bar", "Bar"),
("from ..contracts.other import Bar", "Bar"),
("from other import Bar as FooBar", "FooBar"),
("from contracts.other import Bar as FooBar", "FooBar"),
("from .other import Bar as FooBar", "FooBar"),
("from ..contracts.other import Bar as FooBar", "FooBar"),
("import other.IFoo as IFoo", "IFoo"),
("import contracts.other.IFoo as IFoo", "IFoo"),
("from other import IFoo", "IFoo"),
("from contracts.other import IFoo", "IFoo"),
("from .other import IFoo", "IFoo"),
("from ..contracts.other import IFoo", "IFoo"),
("from other import IFoo as FooBar", "FooBar"),
("from contracts.other import IFoo as FooBar", "FooBar"),
("from .other import IFoo as FooBar", "FooBar"),
("from ..contracts.other import IFoo as FooBar", "FooBar"),
]


@pytest.mark.parametrize("import_stmt, alias", SUBFOLDER_IMPORT_STMT)
def test_import_subfolder(import_stmt, alias, tmp_path, make_file):
foo = make_file("contracts/foo.vy", (FOO_CODE.format(import_stmt, alias)))
make_file("contracts/other/Bar.vy", BAR_CODE)
foo = make_file("contracts/foo.vy", (CONTRACT_CODE.format(import_stmt, alias)))
make_file("contracts/other/IFoo.vyi", INTERFACE_CODE)

assert compile_files([foo], ["combined_json"], root_folder=tmp_path)


OTHER_FOLDER_IMPORT_STMT = [
("import interfaces.Bar as Bar", "Bar"),
("from interfaces import Bar", "Bar"),
("from ..interfaces import Bar", "Bar"),
("from interfaces import Bar as FooBar", "FooBar"),
("from ..interfaces import Bar as FooBar", "FooBar"),
("import interfaces.IFoo as IFoo", "IFoo"),
("from interfaces import IFoo", "IFoo"),
("from ..interfaces import IFoo", "IFoo"),
("from interfaces import IFoo as FooBar", "FooBar"),
("from ..interfaces import IFoo as FooBar", "FooBar"),
]


@pytest.mark.parametrize("import_stmt, alias", OTHER_FOLDER_IMPORT_STMT)
def test_import_other_folder(import_stmt, alias, tmp_path, make_file):
foo = make_file("contracts/foo.vy", FOO_CODE.format(import_stmt, alias))
make_file("interfaces/Bar.vy", BAR_CODE)
foo = make_file("contracts/foo.vy", CONTRACT_CODE.format(import_stmt, alias))
make_file("interfaces/IFoo.vyi", INTERFACE_CODE)

assert compile_files([foo], ["combined_json"], root_folder=tmp_path)


def test_import_parent_folder(tmp_path, make_file):
foo = make_file("contracts/baz/foo.vy", FOO_CODE.format("from ... import Bar", "Bar"))
make_file("Bar.vy", BAR_CODE)
foo = make_file("contracts/baz/foo.vy", CONTRACT_CODE.format("from ... import IFoo", "IFoo"))
make_file("IFoo.vyi", INTERFACE_CODE)

assert compile_files([foo], ["combined_json"], root_folder=tmp_path)

Expand All @@ -125,62 +130,67 @@ def test_import_parent_folder(tmp_path, make_file):


META_IMPORT_STMT = [
"import Meta as Meta",
"import contracts.Meta as Meta",
"from . import Meta",
"from contracts import Meta",
"import ISelf as ISelf",
"import contracts.ISelf as ISelf",
"from . import ISelf",
"from contracts import ISelf",
]


@pytest.mark.parametrize("import_stmt", META_IMPORT_STMT)
def test_import_self_interface(import_stmt, tmp_path, make_file):
# a contract can access its derived interface by importing itself
interface_code = f"""
struct FooStruct:
foo_: uint256
@external
def know_thyself(a: address) -> FooStruct:
...
@external
def be_known() -> FooStruct:
...
"""
code = f"""
{import_stmt}
# TODO: use ISelf.FooStruct
struct FooStruct:
foo_: uint256
@external
def know_thyself(a: address) -> FooStruct:
return Meta(a).be_known()
return ISelf(a).be_known()
@external
def be_known() -> FooStruct:
return FooStruct({{foo_: 42}})
"""
meta = make_file("contracts/Meta.vy", code)
make_file("contracts/ISelf.vyi", interface_code)
meta = make_file("contracts/Self.vy", code)

assert compile_files([meta], ["combined_json"], root_folder=tmp_path)


DERIVED_IMPORT_STMT_BAZ = ["import Foo as Foo", "from . import Foo"]

DERIVED_IMPORT_STMT_FOO = ["import Bar as Bar", "from . import Bar"]


@pytest.mark.parametrize("import_stmt_baz", DERIVED_IMPORT_STMT_BAZ)
@pytest.mark.parametrize("import_stmt_foo", DERIVED_IMPORT_STMT_FOO)
def test_derived_interface_imports(import_stmt_baz, import_stmt_foo, tmp_path, make_file):
# contracts-as-interfaces should be able to contain import statements
# implement IFoo in another contract for fun
@pytest.mark.parametrize("import_stmt_foo,alias", SAME_FOLDER_IMPORT_STMT)
def test_another_interface_implementation(import_stmt_foo, alias, tmp_path, make_file):
baz_code = f"""
{import_stmt_baz}
{import_stmt_foo}
struct FooStruct:
foo_: uint256
@external
def foo(a: address) -> FooStruct:
return Foo(a).foo()
return {alias}(a).foo()
@external
def bar(_foo: address, _bar: address) -> FooStruct:
return Foo(_foo).bar(_bar)
def bar(_foo: address) -> FooStruct:
return {alias}(_foo).bar()
"""

make_file("Foo.vy", FOO_CODE.format(import_stmt_foo, "Bar"))
make_file("Bar.vy", BAR_CODE)
baz = make_file("Baz.vy", baz_code)
make_file("contracts/IFoo.vyi", INTERFACE_CODE)
baz = make_file("contracts/Baz.vy", baz_code)

assert compile_files([baz], ["combined_json"], root_folder=tmp_path)

Expand All @@ -207,15 +217,15 @@ def test_local_namespace(make_file, tmp_path):
make_file(filename, code)
paths.append(filename)

for file_name in ("foo.vy", "bar.vy"):
make_file(file_name, BAR_CODE)
for file_name in ("foo.vyi", "bar.vyi"):
make_file(file_name, INTERFACE_CODE)

assert compile_files(paths, ["combined_json"], root_folder=tmp_path)


def test_compile_outside_root_path(tmp_path, make_file):
# absolute paths relative to "."
foo = make_file("foo.vy", FOO_CODE.format("import bar as Bar", "Bar"))
bar = make_file("bar.vy", BAR_CODE)
foo = make_file("foo.vy", CONTRACT_CODE.format("import ifoo as IFoo", "IFoo"))
ifoo = make_file("ifoo.vyi", INTERFACE_CODE)

Check notice

Code scanning / CodeQL

Unused local variable Note test

Variable ifoo is not used.

assert compile_files([foo, bar], ["combined_json"], root_folder=".")
assert compile_files([foo], ["combined_json"], root_folder=".")
2 changes: 1 addition & 1 deletion vyper/semantics/analysis/data_positions.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def set_storage_slots_with_overrides(

# Search through function definitions to find non-reentrant functions
for node in vyper_module.get_children(vy_ast.FunctionDef):
type_ = node._metadata["type"]
type_ = node._metadata["func_type"]

# Ignore functions without non-reentrant
if type_.nonreentrant is None:
Expand Down
4 changes: 4 additions & 0 deletions vyper/semantics/analysis/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,10 @@ def visit_Continue(self, node):
raise StructureException("`continue` must be enclosed in a `for` loop", node)

def visit_Expr(self, node):
if isinstance(node.value, vy_ast.Ellipsis):
raise StructureException("`...` is not allowed in `.vy` files! "
"Did you mean to import me as a `.vyi` file?", node)

if not isinstance(node.value, vy_ast.Call):
raise StructureException("Expressions without assignment are disallowed", node)

Expand Down

0 comments on commit e7e37b8

Please sign in to comment.